refactor: update to support new API design.
Cette révision appartient à :
@@ -1,5 +1,10 @@
|
|||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
|
## 1.1.0 - 2026-01-25
|
||||||
|
|
||||||
|
- **Added**: Support for YTPTube API changes where presets are returned in an "items" array.
|
||||||
|
- **Removed**: Output template and folder setting. You can set them via preset server-side.
|
||||||
|
|
||||||
## 1.0.4 - 2025-11-01
|
## 1.0.4 - 2025-11-01
|
||||||
|
|
||||||
- **Fixed**: Issue with saving options for firefox.
|
- **Fixed**: Issue with saving options for firefox.
|
||||||
|
|||||||
+9
-22
@@ -1,6 +1,4 @@
|
|||||||
// noinspection JSUnresolvedReference
|
const str_keys = ["instance_url", "preset", "username", "password"]
|
||||||
|
|
||||||
const str_keys = ["instance_url", "preset", "template", "folder", "username", "password"]
|
|
||||||
const bool_keys = ["showContextMenu"]
|
const bool_keys = ["showContextMenu"]
|
||||||
|
|
||||||
if (typeof chrome === 'undefined') {
|
if (typeof chrome === 'undefined') {
|
||||||
@@ -28,7 +26,7 @@ const shouldShowContextMenu = async () => {
|
|||||||
|
|
||||||
const syncContextMenu = async () => {
|
const syncContextMenu = async () => {
|
||||||
let showContextMenu = await shouldShowContextMenu();
|
let showContextMenu = await shouldShowContextMenu();
|
||||||
chrome.contextMenus.update("send-to-ytptube", {visible: showContextMenu});
|
chrome.contextMenus.update("send-to-ytptube", { visible: showContextMenu });
|
||||||
}
|
}
|
||||||
|
|
||||||
chrome.contextMenus.create({
|
chrome.contextMenus.create({
|
||||||
@@ -37,7 +35,7 @@ chrome.contextMenus.create({
|
|||||||
contexts: ["link"]
|
contexts: ["link"]
|
||||||
}, onMenuCreated);
|
}, onMenuCreated);
|
||||||
|
|
||||||
const getCurrentUrl = async () => (await chrome.tabs.query({currentWindow: true, active: true}))[0].url
|
const getCurrentUrl = async () => (await chrome.tabs.query({ currentWindow: true, active: true }))[0].url
|
||||||
|
|
||||||
const getOption = async key => {
|
const getOption = async key => {
|
||||||
let item = await chrome.storage.sync.get(key);
|
let item = await chrome.storage.sync.get(key);
|
||||||
@@ -70,7 +68,7 @@ const sendRequest = async (path, data) => {
|
|||||||
const url = new URL(instanceUrl);
|
const url = new URL(instanceUrl);
|
||||||
url.pathname = path;
|
url.pathname = path;
|
||||||
|
|
||||||
let opts = {method: Object.keys(data).length > 0 ? 'POST' : 'GET', headers: headers};
|
let opts = { method: Object.keys(data).length > 0 ? 'POST' : 'GET', headers: headers };
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
opts.headers['Content-Type'] = 'application/json';
|
opts.headers['Content-Type'] = 'application/json';
|
||||||
@@ -80,38 +78,27 @@ const sendRequest = async (path, data) => {
|
|||||||
console.debug(`Sending to '${instanceUrl}'.`, opts, headers.length > 0 ? 'with auth header' : 'without auth header');
|
console.debug(`Sending to '${instanceUrl}'.`, opts, headers.length > 0 ? 'with auth header' : 'without auth header');
|
||||||
|
|
||||||
const req = await fetch(url, opts);
|
const req = await fetch(url, opts);
|
||||||
return {status: req.status, statusText: req.statusText, data: req};
|
return { status: req.status, statusText: req.statusText, data: req };
|
||||||
};
|
};
|
||||||
|
|
||||||
const sendUrl = async (user_url, preset = null) => {
|
const sendUrl = async (user_url, preset = null) => {
|
||||||
try {
|
try {
|
||||||
const requestData = {url: user_url};
|
const requestData = { url: user_url };
|
||||||
if (preset) {
|
if (preset) {
|
||||||
requestData.preset = preset;
|
requestData.preset = preset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add template and folder if configured
|
|
||||||
const template = await getOption("template");
|
|
||||||
if (template) {
|
|
||||||
requestData.template = template;
|
|
||||||
}
|
|
||||||
|
|
||||||
const folder = await getOption("folder");
|
|
||||||
if (folder) {
|
|
||||||
requestData.folder = folder;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.debug('Sending request data:', requestData);
|
console.debug('Sending request data:', requestData);
|
||||||
|
|
||||||
const data = await sendRequest('/api/history', requestData);
|
const data = await sendRequest('/api/history', requestData);
|
||||||
if (200 === data.status) {
|
if ([200, 201, 202].includes(data.status)) {
|
||||||
notify('Request sent successfully.');
|
notify('Request sent successfully.');
|
||||||
return { success: true, message: 'Request sent successfully.' };
|
return { success: true, message: 'Request sent successfully.' };
|
||||||
}
|
}
|
||||||
const errorMessage = `Failed to send request. '${data.status}: ${data.statusText}'.`;
|
const errorMessage = `Failed to send request. '${data.status}: ${data.statusText}'.`;
|
||||||
notify(errorMessage);
|
notify(errorMessage);
|
||||||
return { success: false, message: errorMessage };
|
return { success: false, message: errorMessage };
|
||||||
}catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
const errorMessage = `Failed to send request. '${e.message}'.`;
|
const errorMessage = `Failed to send request. '${e.message}'.`;
|
||||||
notify(errorMessage);
|
notify(errorMessage);
|
||||||
@@ -156,7 +143,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
return true; // Keep the messaging channel open for async response
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"name": "YTPTube Extension",
|
"name": "YTPTube Extension",
|
||||||
"version": "1.0.4",
|
"version": "1.1.0",
|
||||||
"description": "Add URLs to YTPTube instance",
|
"description": "Add URLs to YTPTube instance",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"activeTab",
|
"activeTab",
|
||||||
|
|||||||
@@ -27,24 +27,6 @@
|
|||||||
<span class="help">Preset to use for the URL</span>
|
<span class="help">Preset to use for the URL</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
|
||||||
<label class="label" for="template">Output Template</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="text" class="input" id="template"
|
|
||||||
placeholder="Leave empty to use default output template.">
|
|
||||||
</div>
|
|
||||||
<span class="help">Filename template to use for the output file.</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field">
|
|
||||||
<label class="label" for="folder">Download Folder</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="text" class="input" id="folder"
|
|
||||||
placeholder="Leave empty to use default download path.">
|
|
||||||
</div>
|
|
||||||
<span class="help">Where to save downloaded files.</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label" for="username">Auth Username</label>
|
<label class="label" for="username">Auth Username</label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// noinspection JSUnresolvedReference
|
// noinspection JSUnresolvedReference
|
||||||
|
|
||||||
const str_keys = ["instance_url", "preset", "template", "folder", "username", "password"]
|
const str_keys = ["instance_url", "preset", "username", "password"]
|
||||||
let storedOriginPattern = null;
|
let storedOriginPattern = null;
|
||||||
|
|
||||||
if (typeof chrome === 'undefined') {
|
if (typeof chrome === 'undefined') {
|
||||||
@@ -38,7 +38,7 @@ const ensureOriginPermission = async (originPattern) => {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await chrome.permissions.request({origins: [originPattern]});
|
return await chrome.permissions.request({ origins: [originPattern] });
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeOriginPermission = async (originPattern) => {
|
const removeOriginPermission = async (originPattern) => {
|
||||||
@@ -46,16 +46,15 @@ const removeOriginPermission = async (originPattern) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasPermission = await chrome.permissions.contains({origins: [originPattern]});
|
const hasPermission = await chrome.permissions.contains({ origins: [originPattern] });
|
||||||
if (!hasPermission) {
|
if (!hasPermission) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await chrome.permissions.remove({origins: [originPattern]});
|
await chrome.permissions.remove({ origins: [originPattern] });
|
||||||
};
|
};
|
||||||
|
|
||||||
const testConfig = async () => {
|
const testConfig = async () => {
|
||||||
|
|
||||||
document.querySelector('#error_msg').innerText = "";
|
document.querySelector('#error_msg').innerText = "";
|
||||||
|
|
||||||
let instance_url = document.querySelector("#instance_url").value.trim();
|
let instance_url = document.querySelector("#instance_url").value.trim();
|
||||||
@@ -133,7 +132,7 @@ document.getElementById("ytptube_options").addEventListener("submit", async e =>
|
|||||||
|
|
||||||
let showContextMenu = document.querySelector("#showContextMenu").checked;
|
let showContextMenu = document.querySelector("#showContextMenu").checked;
|
||||||
|
|
||||||
let data = {presets: {presets: ['default'], last_updated: 0}}
|
let data = { presets: { presets: ['default'], last_updated: 0 } }
|
||||||
|
|
||||||
str_keys.forEach(key => data[key] = document.querySelector(`#${key}`).value)
|
str_keys.forEach(key => data[key] = document.querySelector(`#${key}`).value)
|
||||||
data["showContextMenu"] = showContextMenu;
|
data["showContextMenu"] = showContextMenu;
|
||||||
@@ -147,7 +146,7 @@ document.getElementById("ytptube_options").addEventListener("submit", async e =>
|
|||||||
storedOriginPattern = newOriginPattern;
|
storedOriginPattern = newOriginPattern;
|
||||||
|
|
||||||
chrome.storage.sync.set(data);
|
chrome.storage.sync.set(data);
|
||||||
chrome.contextMenus.update("send-to-ytptube", {visible: showContextMenu});
|
chrome.contextMenus.update("send-to-ytptube", { visible: showContextMenu });
|
||||||
|
|
||||||
notify("Options saved.", true);
|
notify("Options saved.", true);
|
||||||
|
|
||||||
|
|||||||
+11
-6
@@ -54,7 +54,7 @@ $("#ytptube_popup").addEventListener("submit", async (e) => {
|
|||||||
showLoading(true)
|
showLoading(true)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await chrome.runtime.sendMessage({command: 'send-to-ytptube', url: url, preset: preset})
|
const response = await chrome.runtime.sendMessage({ command: 'send-to-ytptube', url: url, preset: preset })
|
||||||
|
|
||||||
if (response && response.success) {
|
if (response && response.success) {
|
||||||
showStatusMessage('Request sent successfully!', true)
|
showStatusMessage('Request sent successfully!', true)
|
||||||
@@ -69,7 +69,7 @@ $("#ytptube_popup").addEventListener("submit", async (e) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const getCurrentUrl = async () => (await chrome.tabs.query({currentWindow: true, active: true}))[0].url
|
const getCurrentUrl = async () => (await chrome.tabs.query({ currentWindow: true, active: true }))[0].url
|
||||||
|
|
||||||
addEventListener('DOMContentLoaded', async _ => {
|
addEventListener('DOMContentLoaded', async _ => {
|
||||||
let url = await getCurrentUrl()
|
let url = await getCurrentUrl()
|
||||||
@@ -90,7 +90,7 @@ addEventListener('DOMContentLoaded', async _ => {
|
|||||||
if (Date.now() - cache.last_updated > 1000 * 60 * 60) {
|
if (Date.now() - cache.last_updated > 1000 * 60 * 60) {
|
||||||
cache.presets = await getPresets()
|
cache.presets = await getPresets()
|
||||||
cache.last_updated = Date.now()
|
cache.last_updated = Date.now()
|
||||||
await chrome.storage.sync.set({presets: cache})
|
await chrome.storage.sync.set({ presets: cache })
|
||||||
}
|
}
|
||||||
|
|
||||||
const s = $('#preset')
|
const s = $('#preset')
|
||||||
@@ -120,7 +120,7 @@ $('#go-to-options').addEventListener('click', function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#preset').addEventListener('change', async e => await chrome.storage.sync.set({preset: e.target.value}))
|
$('#preset').addEventListener('change', async e => await chrome.storage.sync.set({ preset: e.target.value }))
|
||||||
|
|
||||||
const getPresets = async () => {
|
const getPresets = async () => {
|
||||||
let presets = []
|
let presets = []
|
||||||
@@ -143,13 +143,18 @@ const getPresets = async () => {
|
|||||||
url.pathname = '/api/presets';
|
url.pathname = '/api/presets';
|
||||||
url.search = 'filter=name';
|
url.search = 'filter=name';
|
||||||
|
|
||||||
const req = await fetch(url, {method: 'GET', headers: {...headers, 'Accept': 'application/json'}});
|
const req = await fetch(url, { method: 'GET', headers: { ...headers, 'Accept': 'application/json' } });
|
||||||
if (200 !== req.status) {
|
if (200 !== req.status) {
|
||||||
presets.push('Error fetching presets from YTPTube.');
|
presets.push('Error fetching presets from YTPTube.');
|
||||||
return presets
|
return presets
|
||||||
}
|
}
|
||||||
|
|
||||||
(await req.json()).forEach(preset => presets.push(preset.name))
|
const data = await req.json()
|
||||||
|
if (data.items && Array.isArray(data.items)) {
|
||||||
|
data.items.forEach(preset => presets.push(preset.name))
|
||||||
|
} else {
|
||||||
|
data.forEach(preset => presets.push(preset.name))
|
||||||
|
}
|
||||||
|
|
||||||
return presets
|
return presets
|
||||||
};
|
};
|
||||||
Référencer dans un nouveau ticket
Bloquer un utilisateur