| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- // Background script for the extension
- browser.storage.local.get("playlists").then(function (data) {
- if (!data.playlists) {
- console.log("pre-populating playlists");
- browser.storage.local.set({
- playlists: {
- "listening-1": [],
- "listening-2": [],
- "listening-3": [],
- "watching-1": [],
- "watching-2": [],
- },
- });
- } else {
- console.log("no need to pre-populate playlists");
- }
- });
- browser.storage.local.get("history").then(function (data) {
- if (!data.history) {
- console.log("pre-populating history");
- browser.storage.local.set({
- history: {},
- });
- } else {
- console.log("no need to pre-populate history");
- }
- });
- // Create context menu items when the extension is installed
- browser.runtime.onInstalled.addListener(() => {
- // Parent menu item
- browser.contextMenus.create({
- id: "my-playlist-menu",
- title: "Add to Playlist",
- contexts: ["link"],
- targetUrlPatterns: ["https://*.youtube.com/watch*"],
- });
- // Sub-menu items
- browser.contextMenus.create({
- id: "listening-1",
- parentId: "my-playlist-menu",
- title: "Listening - 1",
- contexts: ["link"],
- });
- browser.contextMenus.create({
- id: "listening-2",
- parentId: "my-playlist-menu",
- title: "Listening - 2",
- contexts: ["link"],
- });
- browser.contextMenus.create({
- id: "listening-3",
- parentId: "my-playlist-menu",
- title: "Listening - 3",
- contexts: ["link"],
- });
- // Separator
- browser.contextMenus.create({
- id: "separator-1",
- parentId: "my-playlist-menu",
- type: "separator",
- contexts: ["link"],
- });
- browser.contextMenus.create({
- id: "watching-1",
- parentId: "my-playlist-menu",
- title: "Watching - 1",
- contexts: ["link"],
- });
- browser.contextMenus.create({
- id: "watching-2",
- parentId: "my-playlist-menu",
- title: "Watching - 2",
- contexts: ["link"],
- });
- // test message
- //browser.tabs.sendMessage(tab.id, payload);
- });
- function findMatchingUrlKey(current, inputUrl) {
- // Extract the "v" query parameter from input URL
- let inputVParam;
- try {
- const urlObj = new URL(inputUrl);
- inputVParam = urlObj.searchParams.get("v");
- } catch (e) {
- return false;
- }
- // If no "v" parameter found, return false
- if (!inputVParam) {
- return false;
- }
- // Check each key in the current object
- for (const key in current) {
- const items = current[key];
- // Check each item in the array
- for (const item of items) {
- try {
- const itemUrl = new URL(item.url);
- const itemVParam = itemUrl.searchParams.get("v");
- // If the "v" parameters match, return this key
- if (itemVParam === inputVParam) {
- return key;
- }
- } catch (e) {
- // Skip malformed URLs
- continue;
- }
- }
- }
- // No match found
- return false;
- }
- async function addLinkToPlaylist(plName, item) {
- const { playlists: currentPlaylists } =
- await browser.storage.local.get("playlists");
- const alreadyHave = findMatchingUrlKey(currentPlaylists, item.linkUrl);
- if (alreadyHave) {
- console.log("already have that link in", alreadyHave);
- } else {
- const { [plName]: playlist, ...others } = currentPlaylists;
- await browser.storage.local.set({
- playlists: {
- [plName]: [...playlist, { url: item.linkUrl, title: item.linkText }],
- ...others,
- },
- });
- }
- }
- // Context menu click handler
- browser.contextMenus.onClicked.addListener(async (item, _tab) => {
- addLinkToPlaylist(item.menuItemId, item);
- });
- // Function to navigate a tab to a new URL
- function navigateTab(tabId, url) {
- return browser.tabs.update(tabId, { url: url });
- }
- async function updateHistory(message) {
- const { history: currentHistory } =
- await browser.storage.local.get("history");
- console.log("currentHistory", currentHistory);
- const q = new URL(message.url);
- const v = q.searchParams.get("v");
- console.log("v??", message.url, q, q.searchParams.get("v"));
- console.log("history?", currentHistory[v]);
- if (currentHistory[v]) {
- const { [v]: existing, ...rest } = currentHistory;
- await browser.storage.local.set({
- history: {
- [v]: {
- ...existing,
- duration:
- !isNaN(existing.duration) && isFinite(existing.duration)
- ? Math.max(message.duration, existing.duration)
- : message.duration,
- history: [
- ...existing.history,
- {
- action: message.type,
- position: message.timestamp,
- timestamp: Date.now(),
- },
- ],
- },
- ...rest,
- },
- });
- } else {
- await browser.storage.local.set({
- history: {
- [v]: {
- url: message.url,
- title: message.title,
- duration: message.duration,
- history: [
- {
- action: message.type,
- position: message.timestamp,
- timestamp: Date.now(),
- },
- ],
- },
- ...currentHistory,
- },
- });
- }
- console.log("proposed:", {
- url: message.url,
- title: message.title,
- duration: message.duration,
- history: [
- {
- action: message.type,
- position: message.timestamp,
- timestamp: Date.now(),
- },
- ],
- });
- }
- // Listen for messages from popup or content scripts
- browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
- console.log("MESSAGE", message);
- switch (message.type) {
- case "ended":
- console.log("ENDED");
- case "play":
- case "playing":
- case "pause":
- updateHistory(message);
- break;
- }
- if (message.command === "navigate") {
- if (message.tabId && message.url) {
- navigateTab(message.tabId, message.url)
- .then(() => sendResponse({ status: "success" }))
- .catch((error) =>
- sendResponse({ status: "error", message: error.message }),
- );
- return true; // Required for async sendResponse
- }
- }
- });
|