initial version.

Cette révision appartient à :
Abdulmohsen B. A. A.
2025-03-09 00:43:41 +03:00
révision eaf96d5e3f
17 fichiers modifiés avec 457 ajouts et 0 suppressions
+135
Voir le fichier
@@ -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);
});
+11
Voir le fichier
Diff de fichier supprimé car une ou plusieurs lignes sont trop longues
BIN
Voir le fichier
Fichier binaire non affiché.

Après

Largeur:  |  Hauteur:  |  Taille: 22 KiB

BIN
Voir le fichier
Fichier binaire non affiché.

Après

Largeur:  |  Hauteur:  |  Taille: 1.4 KiB

BIN
Voir le fichier
Fichier binaire non affiché.

Après

Largeur:  |  Hauteur:  |  Taille: 3.2 KiB

BIN
Voir le fichier
Fichier binaire non affiché.

Après

Largeur:  |  Hauteur:  |  Taille: 5.5 KiB

+45
Voir le fichier
@@ -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"
}
}
}
+79
Voir le fichier
@@ -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>
+43
Voir le fichier
@@ -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);
});
+57
Voir le fichier
@@ -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>
+45
Voir le fichier
@@ -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'));
}
});