ydl_api_ng/params/userscript.js

324 lines
11 KiB
JavaScript

// ==UserScript==
// @name ydl_api_ng
// @match http*://*/*
// @grant GM_registerMenuCommand
// @grant GM_xmlhttpRequest
// @grant GM_notification
// ==/UserScript==
(function () {
'use strict';
const key_mapping = "0123456789abcdefghijklmnopqrstuvwxyz";
// CUSTOMIZE HERE
const default_host = 'http://localhost:5011';
const notificationTimeout = 5000;
const userToken = null;
// STOP CUSTOMIZE HERE
const format_date = function (date) {
const year = date.getFullYear();
const month = `${date.getMonth() + 1}`.padStart(2, "0");
const day = `${date.getDate()}`.padStart(2, "0");
const hours = `${date.getHours()}`.padStart(2, "0");
const minutes = `${date.getMinutes()}`.padStart(2, "0");
return `${year}-${month}-${day} ${hours}:${minutes}`;
}
const find_url_in_mapping = function (site_mapping) {
const current_url = window.location.href;
for (let site of site_mapping) {
for (let url of site.url) {
if (current_url.includes(url)) {
return site.presets;
}
}
}
return null;
}
const build_url = function (preset) {
const url = new URL(preset.route.route);
url.searchParams.append('url', window.location.href);
if (userToken !== null) {
url.searchParams.append('token', userToken);
}
if (preset.query_params !== undefined) {
Object.entries(preset.query_params).forEach(([key, value]) => {
url.searchParams.append(key, value);
});
}
return url.href;
};
const launch_request = function (preset) {
const notificationOptions = {};
const effective_method = preset.method !== undefined ? preset.method : preset.route.method;
let data = null;
let headers = {};
if (preset.body !== undefined) {
data = JSON.stringify(preset.body());
headers = {
"Content-Type": "application/json",
};
}
GM_xmlhttpRequest({
method: effective_method,
headers: headers,
data: data,
url: build_url(preset),
onerror: function () {
notificationOptions.title = `Download failed`;
notificationOptions.text = `Host seams unreachable, is the server up ?`;
GM_notification(notificationOptions);
},
onload: function (response) {
notificationOptions.title = `Unknown error`;
notificationOptions.text = `An unknown response code has been found`;
notificationOptions.timeout = null;
const status_code = preset.route.return_code[response.status]
if (status_code !== undefined) {
notificationOptions.title = status_code.title;
notificationOptions.text = status_code.text;
notificationOptions.timeout = status_code.timeout;
}
GM_notification(notificationOptions);
}
});
};
// CUSTOMIZE HERE
const routes = {
download: {
route: default_host + '/download',
method: 'GET',
return_code: {
200: {
title: 'Download launched',
text: 'Downloading',
timeout: notificationTimeout
},
202: {
title: 'Download launched',
text: 'Download not checked. Some files may not be downloaded',
timeout: notificationTimeout
},
206: {
title: 'Download launched',
text: 'Some presets failed download check',
timeout: notificationTimeout
},
400: {
title: 'Bad request',
text: 'An error append during parameters validation',
timeout: null
},
401: {
title: 'Authentication failed',
text: 'The server requires an user token or the provided token is wrong',
timeout: null
},
403: {
title: 'Unauthorized',
text: 'You are not allowed to use this api',
timeout: null
}
}
},
programmation: {
route: default_host + '/programmation',
method: 'POST',
return_code: {
200: {
title: 'Programmation added',
text: '',
timeout: notificationTimeout
},
400: {
title: 'Invalid programmation',
text: 'Some parameters are wrong',
timeout: null
},
401: {
title: 'Authentication failed',
text: 'The server requires an user token or the provided token is wrong',
timeout: null
},
403: {
title: 'Unauthorized',
text: 'You are not allowed to use this api',
timeout: null
},
409: {
title: 'Non supported',
text: 'This feature require redis enabled on the server',
timeout: null
}
}
}
}
const programmation_id = new URL(document.URL).pathname.replaceAll('/', '')
const presets_mapping = {
'default': {name: 'Default', route: routes.download},
'best': {name: 'Best', route: routes.download, query_params: {presets: 'BEST'}},
'720p': {name: '720p', route: routes.download, query_params: {presets: 'HD'}},
'audio': {name: 'Audio', route: routes.download, query_params: {presets: 'AUDIO'}},
'best+audio': {name: 'Best + Audio', route: routes.download, query_params: {presets: 'BEST,AUDIO'}},
'samples': (days = 15, presets = null) => {
let preset_name = 'Samples'
let recurrence_end_date = null
if (days !== null) {
const end_date = new Date();
end_date.setDate(end_date.getDate() + days)
recurrence_end_date = format_date(end_date)
preset_name = `Samples (${days} days)`
}
return {
name: preset_name, route: routes.programmation, body: () => {
const end_date = new Date();
end_date.setDate(end_date.getDate() + days)
return {
id: new URL(document.URL).pathname.replaceAll('/', ''),
planning: {
recurrence_cron: `${Math.floor(Math.random() * 15)}/15 * * * *`,
recording_duration: 2,
recording_stops_at_end: true,
recording_restarts_during_duration: false,
recurrence_end_date: recurrence_end_date
},
presets: presets
}
}
}
},
'spy': (days = null, presets = null) => {
let planning = {}
let preset_name = 'Spy'
if (days !== null) {
const end_date = new Date();
end_date.setDate(end_date.getDate() + days)
planning = {
recurrence_end_date: format_date(end_date)
}
preset_name = `Spy (${days} days)`
}
return {
name: preset_name, route: routes.programmation, body: () => {
return {
id: programmation_id,
presets: presets,
planning: planning
}
}
}
},
'prog_id': (name = 'DEFAULT', preset = null) => {
return {
name: name, route: routes.download, method: 'POST', body: () => {
return {
programmation: {
id: programmation_id
},
presets: [{
"_preset": preset
}]
}
}
}
},
'time_limit': (minutes = 60, preset = 'DEFAULT') => {
return {
name: `${minutes} minutes`, route: routes.download, method: 'POST', body: () => {
return {
programmation: {
id: programmation_id,
planning: {
recording_duration: minutes,
},
},
presets: [{
"_preset": preset
}]
}
}
}
},
'delete_prog': (id) => {
return {
name: 'Delete programmation', route: routes.programmation, method: 'DELETE', route_path: `/${id}`
}
},
};
const site_mapping = [
{
url: ['youtube.com', 'youtu.be'],
presets: ['best', '720p', 'audio', 'best+audio'],
},
{
url: ['twitch.tv'],
presets: [
presets_mapping['prog_id']('Best', 'BEST'),
presets_mapping['prog_id']('720p', 'HD'),
presets_mapping['time_limit'](60),
presets_mapping['time_limit'](30),
presets_mapping['time_limit'](15),
'spy', 'samples'],
},
];
// STOP CUSTOMIZE HERE
let effective_presets = find_url_in_mapping(site_mapping);
if (effective_presets == null) {
effective_presets = Object.keys(presets_mapping);
}
effective_presets.forEach((preset, index) => {
let preset_object = null;
if (typeof preset == 'object') {
preset_object = preset;
} else if (typeof preset == 'string') {
if (typeof presets_mapping[preset] == 'function') {
preset_object = presets_mapping[preset]();
} else {
preset_object = presets_mapping[preset];
}
} else if (typeof preset == 'function') {
preset_object = preset();
}
if (preset_object !== undefined && preset_object !== null) {
let key = null;
if (index < key_mapping.length) {
key = key_mapping[index];
}
GM_registerMenuCommand(preset_object.name, () => {
launch_request(preset_object);
}, key);
}
});
})();