Fix all the scrobbling
This commit is contained in:
148
background.js
148
background.js
@ -1,8 +1,10 @@
|
|||||||
const SCROBBLE_ENDPOINT = "https://life.lab.unbl.ink/?scrobble_url=";
|
// ======== Life Scrobbler Extension ========
|
||||||
const STOP_ENDPOINT = "https://life.lab.unbl.ink/?action=stop&scrobble_url=";
|
// Fully self-contained version with base64 icons
|
||||||
|
// Stop scrobble code is commented out for now
|
||||||
|
|
||||||
|
// ====== Default Settings ======
|
||||||
const DEFAULT_SETTINGS = {
|
const DEFAULT_SETTINGS = {
|
||||||
delay: 7,
|
delay: 8,
|
||||||
blacklist: [
|
blacklist: [
|
||||||
"*.unbl.ink",
|
"*.unbl.ink",
|
||||||
"moz-extension://",
|
"moz-extension://",
|
||||||
@ -21,9 +23,23 @@ const DEFAULT_SETTINGS = {
|
|||||||
"*.todoist.com",
|
"*.todoist.com",
|
||||||
],
|
],
|
||||||
paused: false,
|
paused: false,
|
||||||
siteDelays: { "readscomisconline.ru": 1 },
|
siteDelays: { "readcomicsonline.ru": 1 },
|
||||||
|
scrobbleBaseUrl: "https://life.lab.unbl.ink",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ====== Base64 icons ======
|
||||||
|
const ICONS = {
|
||||||
|
wait: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA...",
|
||||||
|
scrobbled: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA...",
|
||||||
|
stopped: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA...",
|
||||||
|
pause: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA...",
|
||||||
|
};
|
||||||
|
|
||||||
|
// ====== State ======
|
||||||
|
let activeTabs = new Map(); // tabId -> timeout
|
||||||
|
let pausedTabs = new Set(); // tabIds that are paused
|
||||||
|
|
||||||
|
// ====== Utility Functions ======
|
||||||
function matchPattern(url, pattern) {
|
function matchPattern(url, pattern) {
|
||||||
if (pattern.startsWith("*.")) {
|
if (pattern.startsWith("*.")) {
|
||||||
const domain = pattern.slice(2);
|
const domain = pattern.slice(2);
|
||||||
@ -36,11 +52,56 @@ function isBlacklisted(url, blacklist) {
|
|||||||
return blacklist.some((p) => matchPattern(url, p));
|
return blacklist.some((p) => matchPattern(url, p));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getSettings() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
browser.storage.local.get(DEFAULT_SETTINGS, resolve);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function setPaused(tabId, paused) {
|
||||||
|
if (paused) pausedTabs.add(tabId);
|
||||||
|
else pausedTabs.delete(tabId);
|
||||||
|
|
||||||
|
updateIcon(tabId, paused ? "pause" : "wait");
|
||||||
|
// persist globally
|
||||||
|
await browser.storage.local.set({ paused });
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateIcon(tabId, state) {
|
||||||
|
browser.browserAction.setIcon({ path: ICONS[state], tabId });
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====== Scrobble Start ======
|
||||||
|
async function scrobbleStart(url, baseUrl) {
|
||||||
|
const endpoint = `${baseUrl}/?scrobble_url=${encodeURIComponent(url)}`;
|
||||||
|
try {
|
||||||
|
await fetch(endpoint, { method: "GET" });
|
||||||
|
console.log("LifeScrobbler: scrobbled", url);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("LifeScrobbler: failed scrobble", url, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====== Scrobble Stop ======
|
||||||
|
async function scrobbleStop(url, baseUrl) {
|
||||||
|
const endpoint = `${baseUrl}/?action=stop&scrobble_url=${encodeURIComponent(url)}`;
|
||||||
|
try {
|
||||||
|
await fetch(endpoint, { method: "GET" });
|
||||||
|
console.log("LifeScrobbler: stopped", url);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("LifeScrobbler: stop failed", url, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====== Delay for given URL ======
|
||||||
function getDelayForUrl(url, settings) {
|
function getDelayForUrl(url, settings) {
|
||||||
try {
|
try {
|
||||||
const u = new URL(url);
|
const u = new URL(url);
|
||||||
|
console.log(u);
|
||||||
for (const [domain, customDelay] of Object.entries(settings.siteDelays)) {
|
for (const [domain, customDelay] of Object.entries(settings.siteDelays)) {
|
||||||
|
console.log(domain, customDelay, u.hostname, domain == u.hostname);
|
||||||
if (u.hostname.includes(domain)) {
|
if (u.hostname.includes(domain)) {
|
||||||
|
console.log("Found custom delay of ", customDelay);
|
||||||
return customDelay;
|
return customDelay;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,44 +109,28 @@ function getDelayForUrl(url, settings) {
|
|||||||
return settings.delay;
|
return settings.delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
let activeTabs = new Map();
|
// ====== Tab Updates ======
|
||||||
|
|
||||||
// Load settings
|
|
||||||
async function getSettings() {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
browser.storage.local.get(DEFAULT_SETTINGS, (items) => resolve(items));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save pause state
|
|
||||||
async function setPaused(paused) {
|
|
||||||
await browser.storage.local.set({ paused });
|
|
||||||
updateIcon(paused ? "pause" : "wait");
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateIcon(state) {
|
|
||||||
const icons = {
|
|
||||||
wait: "icons/wait.png",
|
|
||||||
scrobbled: "icons/check.png",
|
|
||||||
stopped: "icons/stop.png",
|
|
||||||
pause: "icons/pause.png",
|
|
||||||
};
|
|
||||||
browser.browserAction.setIcon({ path: icons[state] });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle tab updates
|
|
||||||
browser.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
|
browser.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
|
||||||
if (changeInfo.status !== "complete" || !tab.url) return;
|
if (changeInfo.status !== "complete" || !tab.url) return;
|
||||||
const settings = await getSettings();
|
|
||||||
const { delay, blacklist, paused } = await getSettings();
|
|
||||||
|
|
||||||
if (paused || isBlacklisted(tab.url, blacklist)) return;
|
const { delay, blacklist, scrobbleBaseUrl, paused } = await getSettings();
|
||||||
if (tab.url.startsWith("moz-extension://")) return;
|
const url = tab.url;
|
||||||
|
|
||||||
const url = encodeURIComponent(tab.url);
|
// Skip if globally paused or blacklisted
|
||||||
updateIcon("wait");
|
console.log(
|
||||||
|
"Globally paused? ",
|
||||||
|
paused,
|
||||||
|
" - Is this tab paused? ",
|
||||||
|
pausedTabs.has(tabId),
|
||||||
|
" - Is site blacklisted? ",
|
||||||
|
isBlacklisted(url, blacklist),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (paused || pausedTabs.has(tabId) || isBlacklisted(url, blacklist)) return;
|
||||||
|
updateIcon(tabId, "wait");
|
||||||
|
|
||||||
const siteDelay = getDelayForUrl(url, await getSettings());
|
const siteDelay = getDelayForUrl(url, await getSettings());
|
||||||
|
console.log("Waiting " + siteDelay + " seconds before scrobbling ...");
|
||||||
|
|
||||||
if (activeTabs.has(tabId)) clearTimeout(activeTabs.get(tabId));
|
if (activeTabs.has(tabId)) clearTimeout(activeTabs.get(tabId));
|
||||||
const timeout = setTimeout(() => {
|
const timeout = setTimeout(() => {
|
||||||
@ -97,27 +142,22 @@ browser.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
|
|||||||
activeTabs.set(tabId, timeout);
|
activeTabs.set(tabId, timeout);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Stop scrobble when navigating away or closing
|
// ====== Pause Toggle via Toolbar Icon ======
|
||||||
function stopScrobble(tabId, url) {
|
browser.browserAction.onClicked.addListener(async (tab) => {
|
||||||
getSettings().then(({ blacklist }) => {
|
const { paused } = await getSettings();
|
||||||
if (!url || isBlacklisted(url, blacklist)) return;
|
const tabPaused = pausedTabs.has(tab.id) || paused;
|
||||||
if (url.startsWith("moz-extension://")) return;
|
setPaused(tab.id, !tabPaused);
|
||||||
fetch(`${STOP_ENDPOINT}${encodeURIComponent(url)}`).then(() =>
|
});
|
||||||
updateIcon("stopped"),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// ====== Clean up on Tab Close ======
|
||||||
browser.tabs.onRemoved.addListener((tabId) => {
|
browser.tabs.onRemoved.addListener((tabId) => {
|
||||||
if (activeTabs.has(tabId)) clearTimeout(activeTabs.get(tabId));
|
if (activeTabs.has(tabId)) clearTimeout(activeTabs.get(tabId));
|
||||||
|
pausedTabs.delete(tabId);
|
||||||
});
|
});
|
||||||
|
|
||||||
//browser.webNavigation.onBeforeNavigate.addListener((details) => {
|
// ====== Web Navigation stop code is commented ======
|
||||||
// stopScrobble(details.tabId, details.url);
|
browser.webNavigation.onBeforeNavigate.addListener((details) => {
|
||||||
//});
|
const { scrobbleBaseUrl } = DEFAULT_SETTINGS;
|
||||||
|
// scrobbleStop(details.url, scrobbleBaseUrl);
|
||||||
// Toggle pause on icon click
|
// TODO need to fix this in Scrobbler to check if a running scrobble exists and stop if it does
|
||||||
browser.browserAction.onClicked.addListener(async () => {
|
|
||||||
const { paused } = await getSettings();
|
|
||||||
setPaused(!paused);
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user