initial version.
Cette révision appartient à :
@@ -0,0 +1,135 @@
|
||||
// noinspection JSUnresolvedReference
|
||||
|
||||
const str_keys = ["instance_url", "preset", "template", "folder", "username", "password"]
|
||||
const bool_keys = ["showContextMenu"]
|
||||
|
||||
if (typeof chrome === 'undefined') {
|
||||
let chrome = browser
|
||||
}
|
||||
|
||||
const notify = message => chrome.notifications.create({
|
||||
"type": "basic",
|
||||
"iconUrl": chrome.runtime.getURL("icons/icon-128.png"),
|
||||
"title": 'YTPTube Extension',
|
||||
"message": message,
|
||||
});
|
||||
|
||||
const onMenuCreated = () => {
|
||||
if (chrome.runtime.lastError) {
|
||||
console.log(`error creating menu item. ${chrome.runtime.lastError}`);
|
||||
}
|
||||
syncContextMenu().then(_ => '').catch(console.error);
|
||||
}
|
||||
|
||||
const shouldShowContextMenu = async () => {
|
||||
let item = await chrome.storage.sync.get("showContextMenu");
|
||||
return 'showContextMenu' in item ? item.showContextMenu : true;
|
||||
};
|
||||
|
||||
const syncContextMenu = async () => {
|
||||
let showContextMenu = await shouldShowContextMenu();
|
||||
chrome.contextMenus.update("send-to-ytptube", {visible: showContextMenu});
|
||||
}
|
||||
|
||||
chrome.contextMenus.create({
|
||||
id: "send-to-ytptube",
|
||||
title: "Send to YTPTube",
|
||||
contexts: ["link"]
|
||||
}, onMenuCreated);
|
||||
|
||||
const getCurrentUrl = async () => (await chrome.tabs.query({currentWindow: true, active: true}))[0].url
|
||||
|
||||
const getOption = async key => {
|
||||
let item = await chrome.storage.sync.get(key);
|
||||
if (str_keys.includes(key)) {
|
||||
return item[key] ?? '';
|
||||
}
|
||||
if (bool_keys.includes(key)) {
|
||||
return item[key] ?? false;
|
||||
}
|
||||
}
|
||||
|
||||
const sendRequest = async user_url => {
|
||||
const instanceUrl = await getOption("instance_url");
|
||||
if (!instanceUrl) {
|
||||
notify('YTPTube instance url not configured.');
|
||||
return;
|
||||
}
|
||||
|
||||
let headers = {};
|
||||
let data = {
|
||||
url: user_url,
|
||||
}
|
||||
|
||||
const auth_username = await getOption("username");
|
||||
const auth_password = await getOption("password");
|
||||
if (auth_username && auth_password) {
|
||||
headers['Authorization'] = 'Basic ' + btoa(`${auth_username}:${auth_password}`);
|
||||
}
|
||||
|
||||
const preset = await getOption("preset");
|
||||
if (preset) {
|
||||
data['preset'] = preset;
|
||||
}
|
||||
|
||||
const template = await getOption("template");
|
||||
if (template) {
|
||||
data['template'] = template;
|
||||
}
|
||||
|
||||
const folder = await getOption("folder");
|
||||
if (folder) {
|
||||
data['folder'] = folder;
|
||||
}
|
||||
|
||||
console.debug(`Sending to '${instanceUrl}'.`, data, headers.length > 0 ? 'with auth header' : 'without auth header');
|
||||
|
||||
const url = new URL(instanceUrl);
|
||||
url.pathname = '/api/history';
|
||||
|
||||
const req = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
...headers,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
if (200 === req.status) {
|
||||
notify('Request sent successfully.');
|
||||
return
|
||||
}
|
||||
|
||||
notify(`Failed to send request. '${req.status}: ${req.statusText}'.`);
|
||||
};
|
||||
|
||||
chrome.contextMenus.onClicked.addListener(async (info, _) => {
|
||||
if (info.menuItemId !== "send-to-ytptube") {
|
||||
return;
|
||||
}
|
||||
if (!info.linkUrl) {
|
||||
notify('No link url found');
|
||||
return;
|
||||
}
|
||||
|
||||
await sendRequest(info.linkUrl);
|
||||
});
|
||||
|
||||
chrome.runtime.onMessage.addListener(async (message) => {
|
||||
if (message.command !== "send-to-ytptube") {
|
||||
return;
|
||||
}
|
||||
|
||||
let url = message.url || await getCurrentUrl();
|
||||
|
||||
if (!url) {
|
||||
await notify('No url found');
|
||||
return;
|
||||
}
|
||||
|
||||
await sendRequest(url);
|
||||
});
|
||||
|
||||
|
||||
|
||||
Diff de fichier supprimé car une ou plusieurs lignes sont trop longues
Fichier binaire non affiché.
|
Après Largeur: | Hauteur: | Taille: 22 KiB |
Fichier binaire non affiché.
|
Après Largeur: | Hauteur: | Taille: 1.4 KiB |
Fichier binaire non affiché.
|
Après Largeur: | Hauteur: | Taille: 3.2 KiB |
Fichier binaire non affiché.
|
Après Largeur: | Hauteur: | Taille: 5.5 KiB |
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"background": {
|
||||
"service_worker": "background.js",
|
||||
"scripts": [
|
||||
"background.js"
|
||||
]
|
||||
},
|
||||
"name": "YTPTube Extension",
|
||||
"version": "0.0.2",
|
||||
"description": "Add URLs to YTPTube instance",
|
||||
"permissions": [
|
||||
"activeTab",
|
||||
"contextMenus",
|
||||
"storage",
|
||||
"notifications"
|
||||
],
|
||||
"homepage_url": "https://github.com/arabcoders/ytptube-extension",
|
||||
"icons": {
|
||||
"16": "icons/icon-16.png",
|
||||
"32": "icons/icon-32.png",
|
||||
"48": "icons/icon-48.png",
|
||||
"128": "icons/icon-128.png"
|
||||
},
|
||||
"options_ui": {
|
||||
"page": "options.html",
|
||||
"open_in_tab": false
|
||||
},
|
||||
"action": {
|
||||
"default_title": "Add URL to YTPTube",
|
||||
"default_popup": "popup.html",
|
||||
"default_icon": {
|
||||
"16": "icons/icon-16.png",
|
||||
"32": "icons/icon-32.png",
|
||||
"48": "icons/icon-48.png",
|
||||
"128": "icons/icon-128.png"
|
||||
}
|
||||
},
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "ytptube@arabcoders.org",
|
||||
"strict_min_version": "113.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Options menu for YTPTube Extension</title>
|
||||
<link rel="stylesheet" href="css/pure.css"/>
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
color: white;
|
||||
background-color: #19191c;
|
||||
}
|
||||
input {
|
||||
background-color: #19191c;
|
||||
color: white;
|
||||
}
|
||||
fieldset > legend {
|
||||
color: white !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<form id="ytptube_options" class="pure-form pure-form-stacked">
|
||||
<fieldset style="padding:1em">
|
||||
<legend>Settings</legend>
|
||||
|
||||
<div class="pure-control-group">
|
||||
<label for="instance_url">YTPTube URL</label>
|
||||
<input type="text" class="pure-input-1" id="instance_url" placeholder="https://ytptube.example.org">
|
||||
<span class="pure-form-message">URL to your YTPTube instance</span><br>
|
||||
</div>
|
||||
|
||||
<div class="pure-control-group">
|
||||
<label for="preset">Preset</label>
|
||||
<input type="text" class="pure-input-1" id="preset" placeholder="Leave empty to use default preset.">
|
||||
<span class="pure-form-message">Preset to use for the URL</span><br>
|
||||
</div>
|
||||
|
||||
<div class="pure-control-group">
|
||||
<label for="template">Output Template</label>
|
||||
<input type="text" class="pure-input-1" id="template"
|
||||
placeholder="Leave empty to use default output template.">
|
||||
<span class="pure-form-message">Filename template to use for the output file.</span><br>
|
||||
</div>
|
||||
|
||||
<div class="pure-control-group">
|
||||
<label for="folder">Download Folder</label>
|
||||
<input type="text" class="pure-input-1" id="folder" placeholder="Leave empty to use default download path.">
|
||||
<span class="pure-form-message">Where to save downloaded files.</span><br>
|
||||
</div>
|
||||
|
||||
<div class="pure-control-group">
|
||||
<label for="username">Auth Username</label>
|
||||
<input type="text" class="pure-input-1" id="username"
|
||||
placeholder="Leave empty if you have not configured a authentication.">
|
||||
<span class="pure-form-message">Username to use for authentication.</span><br>
|
||||
</div>
|
||||
|
||||
<div class="pure-control-group">
|
||||
<label for="password">Auth Password</label>
|
||||
<input type="password" class="pure-input-1" id="password"
|
||||
placeholder="Leave empty if you have not configured a authentication.">
|
||||
<span class="pure-form-message">Password to use for authentication.</span><br>
|
||||
</div>
|
||||
|
||||
<label for="showContextMenu">
|
||||
<input type="checkbox" id="showContextMenu"/> Show context menu in supported sites
|
||||
</label><br>
|
||||
|
||||
<button class="pure-button pure-input-1 pure-button-primary" type="submit">Save</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
<script src="options.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,43 @@
|
||||
// noinspection JSUnresolvedReference
|
||||
|
||||
const str_keys = ["instance_url", "preset", "template", "folder", "username", "password"]
|
||||
|
||||
const $ = s => document.querySelector(s)
|
||||
|
||||
if (typeof chrome === 'undefined') {
|
||||
let chrome = browser
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
function onError(error) {
|
||||
console.log(`Error: ${error}`);
|
||||
}
|
||||
|
||||
str_keys.forEach(k => {
|
||||
chrome.storage.sync.get(k).then(r => document.querySelector(`#${k}`).value = r[k] || "", onError);
|
||||
});
|
||||
|
||||
chrome.storage.sync.get("showContextMenu").then(r => document.querySelector("#showContextMenu").checked = r.showContextMenu || false);
|
||||
});
|
||||
|
||||
document.getElementById("ytptube_options").addEventListener("submit", (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
let showContextMenu = document.querySelector("#showContextMenu").checked;
|
||||
|
||||
let data = {}
|
||||
|
||||
str_keys.forEach(key => data[key] = document.querySelector(`#${key}`).value)
|
||||
data["showContextMenu"] = showContextMenu
|
||||
chrome.storage.sync.set(data);
|
||||
chrome.contextMenus.update("send-to-ytptube", {visible: showContextMenu});
|
||||
|
||||
chrome.notifications.create({
|
||||
"type": "basic",
|
||||
"iconUrl": chrome.runtime.getURL("icons/icon-128.png"),
|
||||
"title": 'YTPTube Extension',
|
||||
"message": "Options saved."
|
||||
});
|
||||
|
||||
setTimeout(() => window.close(), 1000);
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>YTPTube Extension</title>
|
||||
<link rel="stylesheet" href="css/pure.css"/>
|
||||
<style>
|
||||
#ytptube_popup {
|
||||
min-width: 250px;
|
||||
min-height: 120px;
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
color: white;
|
||||
background-color: #19191c;
|
||||
}
|
||||
|
||||
input {
|
||||
background-color: #19191c;
|
||||
color: white;
|
||||
}
|
||||
|
||||
fieldset > legend {
|
||||
color: white !important;
|
||||
}
|
||||
}
|
||||
|
||||
.button-secondary {
|
||||
background: rgb(66, 184, 221);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<form id="ytptube_popup" class="pure-form pure-form-stacked">
|
||||
<div class="pure-control-group">
|
||||
<label for="user_url">URL:</label>
|
||||
<input id="user_url" class="pure-input-1" type="text" placeholder="https://..">
|
||||
<span class="pure-form-message">The URL to send to YTPTube instance</span><br>
|
||||
</div>
|
||||
<div class="pure-control-group">
|
||||
<button class="pure-button pure-input-1 pure-button-primary" type="submit">Send to YTPTube</button>
|
||||
</div>
|
||||
<br>
|
||||
<div class="pure-control-group">
|
||||
<button class="pure-button pure-input-1 button-secondary" type="button" id="go-to-options">
|
||||
Open options page
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script src="popup.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,45 @@
|
||||
// noinspection JSUnresolvedReference
|
||||
|
||||
const $ = s => document.querySelector(s)
|
||||
|
||||
if (typeof chrome === 'undefined') {
|
||||
let chrome = browser
|
||||
}
|
||||
|
||||
const notify = message => chrome.notifications.create({
|
||||
"type": "basic",
|
||||
"iconUrl": chrome.runtime.getURL("icons/icon-128.png"),
|
||||
"title": 'YTPTube Extension',
|
||||
"message": message
|
||||
});
|
||||
|
||||
$("#ytptube_popup").addEventListener("submit", async (e) => {
|
||||
e.preventDefault()
|
||||
const url = $('#user_url').value
|
||||
if (!url) {
|
||||
notify('URL is required.')
|
||||
return
|
||||
}
|
||||
|
||||
await chrome.runtime.sendMessage({command: 'send-to-ytptube', url: url})
|
||||
})
|
||||
|
||||
const getCurrentUrl = async () => (await chrome.tabs.query({currentWindow: true, active: true}))[0].url
|
||||
|
||||
addEventListener('DOMContentLoaded', async _ => {
|
||||
let url = await getCurrentUrl()
|
||||
|
||||
if (url && !url.startsWith('http')) {
|
||||
url = ""
|
||||
}
|
||||
|
||||
$('#user_url').value = url || ''
|
||||
})
|
||||
|
||||
$('#go-to-options').addEventListener('click', function () {
|
||||
if (chrome.runtime.openOptionsPage) {
|
||||
chrome.runtime.openOptionsPage();
|
||||
} else {
|
||||
window.open(chrome.runtime.getURL('options.html'));
|
||||
}
|
||||
});
|
||||
Référencer dans un nouveau ticket
Bloquer un utilisateur