From 64d29b5a4f1052f4352350671ce6b86f4f2779be Mon Sep 17 00:00:00 2001 From: Kevin Gibbons Date: Fri, 2 Dec 2022 18:51:15 -0800 Subject: [PATCH] format --- extension/background.js | 302 ++++++++++++-------------- extension/popup.js | 266 +++++++++++------------ extension/script.js | 468 +++++++++++++++++++--------------------- 3 files changed, 491 insertions(+), 545 deletions(-) diff --git a/extension/background.js b/extension/background.js index 7bcdb5f..980cbe9 100644 --- a/extension/background.js +++ b/extension/background.js @@ -2,226 +2,202 @@ extension background script listening for events */ -console.log("running background.js"); +console.log('running background.js'); let browserType = getBrowser(); - // boilerplate to dedect browser type api function getBrowser() { - if (typeof chrome !== "undefined") { - if (typeof browser !== "undefined") { - return browser; - } else { - return chrome; - } + if (typeof chrome !== 'undefined') { + if (typeof browser !== 'undefined') { + return browser; } else { - console.log("failed to detect browser"); - throw "browser detection error" - }; + return chrome; + } + } else { + console.log('failed to detect browser'); + throw 'browser detection error'; + } } - // send get request to API backend async function sendGet(path) { + let access = await getAccess(); + const url = `${access.url}:${access.port}/${path}`; + console.log('GET: ' + url); - let access = await getAccess(); - const url = `${access.url}:${access.port}/${path}`; - console.log("GET: " + url); + const rawResponse = await fetch(url, { + method: 'GET', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + Authorization: 'Token ' + access.apiKey, + mode: 'no-cors', + }, + }); - const rawResponse = await fetch(url, { - method: "GET", - headers: { - "Accept": "application/json", - "Content-Type": "application/json", - "Authorization": "Token " + access.apiKey, - "mode": "no-cors" - } - }); - - const content = await rawResponse.json(); - return content; + const content = await rawResponse.json(); + return content; } - // send post/put request to API backend async function sendData(path, payload, method) { + let access = await getAccess(); + const url = `${access.url}:${access.port}/${path}`; + console.log(`${method}: ${url}`); + console.log(`${method}: ${JSON.stringify(payload)}`); - let access = await getAccess(); - const url = `${access.url}:${access.port}/${path}`; - console.log(`${method}: ${url}`); - console.log(`${method}: ${JSON.stringify(payload)}`); - - try { - const rawResponse = await fetch(url, { - method: method, - headers: { - "Accept": "application/json", - "Content-Type": "application/json", - "Authorization": "Token " + access.apiKey, - "mode": "no-cors" - }, - body: JSON.stringify(payload) - }); - const content = await rawResponse.json(); - return content; - } catch (e) { - console.error(e); - return null - } - + try { + const rawResponse = await fetch(url, { + method: method, + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + Authorization: 'Token ' + access.apiKey, + mode: 'no-cors', + }, + body: JSON.stringify(payload), + }); + const content = await rawResponse.json(); + return content; + } catch (e) { + console.error(e); + return null; + } } - // read access details from storage.local async function getAccess() { + var storage = await browserType.storage.local.get('access'); - var storage = await browserType.storage.local.get("access"); - - return storage.access - + return storage.access; } - // check if cookie is valid async function getCookieState() { + const path = 'api/cookie/'; + let response = await sendGet(path); + console.log('cookie state: ' + JSON.stringify(response)); - const path = "api/cookie/"; - let response = await sendGet(path) - console.log("cookie state: " + JSON.stringify(response)); - - return response - + return response; } - // send ping to server, return response async function verifyConnection() { + const path = 'api/ping/'; + let response = await sendGet(path); + console.log('verify connection: ' + JSON.stringify(response)); - const path = "api/ping/"; - let response = await sendGet(path) - console.log("verify connection: " + JSON.stringify(response)); - - return response + return response; } - // send youtube link from injected buttons async function youtubeLink(youtubeMessage) { - - let path; - let payload; - - if (youtubeMessage.action === "download") { - path = "api/download/"; - payload = { - "data": [ - { - "youtube_id": youtubeMessage.url, - "status": "pending", - } - ] - } - } else if (youtubeMessage.action === "subscribe") { - path = "api/channel/"; - payload = { - "data": [ - { - "channel_id": youtubeMessage.url, - "channel_subscribed": true, - } - ] - } - } + let path; + let payload; - let response = await sendData(path, payload, "POST"); - return response + if (youtubeMessage.action === 'download') { + path = 'api/download/'; + payload = { + data: [ + { + youtube_id: youtubeMessage.url, + status: 'pending', + }, + ], + }; + } else if (youtubeMessage.action === 'subscribe') { + path = 'api/channel/'; + payload = { + data: [ + { + channel_id: youtubeMessage.url, + channel_subscribed: true, + }, + ], + }; + } + + let response = await sendData(path, payload, 'POST'); + return response; } - async function cookieStr(cookieLines) { + const path = 'api/cookie/'; + let payload = { + cookie: cookieLines.join('\n'), + }; + let response = await sendData(path, payload, 'PUT'); - const path = "api/cookie/"; - let payload = { - "cookie": cookieLines.join("\n") - } - let response = await sendData(path, payload, "PUT"); - - return response - + return response; } - function buildCookieLine(cookie) { - return [ - cookie.domain, - "TRUE", - cookie.path, - cookie.httpOnly.toString().toUpperCase(), - Math.trunc(cookie.expirationDate) || 0, - cookie.name, - cookie.value, - ].join("\t"); + return [ + cookie.domain, + 'TRUE', + cookie.path, + cookie.httpOnly.toString().toUpperCase(), + Math.trunc(cookie.expirationDate) || 0, + cookie.name, + cookie.value, + ].join('\t'); } - async function sendCookies() { - console.log("function sendCookies"); + console.log('function sendCookies'); - let cookieStores = await browserType.cookies.getAllCookieStores(); - var cookieLines = [ - "# Netscape HTTP Cookie File", - "# https://curl.haxx.se/rfc/cookie_spec.html", - "# This is a generated file! Do not edit.\n" - ]; - for (let i = 0; i < cookieStores.length; i++) { - const cookieStore = cookieStores[i]; - var allCookiesStore = await browserType.cookies.getAll({ - domain: ".youtube.com", - storeId: cookieStore["id"] - }); - for (let j = 0; j < allCookiesStore.length; j++) { - const cookie = allCookiesStore[j]; - cookieLines.push(buildCookieLine(cookie)); - } + let cookieStores = await browserType.cookies.getAllCookieStores(); + var cookieLines = [ + '# Netscape HTTP Cookie File', + '# https://curl.haxx.se/rfc/cookie_spec.html', + '# This is a generated file! Do not edit.\n', + ]; + for (let i = 0; i < cookieStores.length; i++) { + const cookieStore = cookieStores[i]; + var allCookiesStore = await browserType.cookies.getAll({ + domain: '.youtube.com', + storeId: cookieStore['id'], + }); + for (let j = 0; j < allCookiesStore.length; j++) { + const cookie = allCookiesStore[j]; + cookieLines.push(buildCookieLine(cookie)); } + } - let response = cookieStr(cookieLines); - - return response + let response = cookieStr(cookieLines); + return response; } - - // process and return message if needed function handleMessage(request, sender, sendResponse) { - console.log("message background.js listener: " + JSON.stringify(request)); + console.log('message background.js listener: ' + JSON.stringify(request)); - if (request.verify === true) { - let response = verifyConnection(); - response.then(message => { - sendResponse(message); - }) - } else if (request.youtube) { - let response = youtubeLink(request.youtube); - response.then(message => { - sendResponse(message) - }) - } else if (request.cookieState) { - let response = getCookieState(); - response.then(message => { - sendResponse(message) - }) - } else if (request.sendCookie) { - console.log("backgound: " + JSON.stringify(request)); - let response = sendCookies(); - response.then(message => { - sendResponse(message) - }) - } + if (request.verify === true) { + let response = verifyConnection(); + response.then(message => { + sendResponse(message); + }); + } else if (request.youtube) { + let response = youtubeLink(request.youtube); + response.then(message => { + sendResponse(message); + }); + } else if (request.cookieState) { + let response = getCookieState(); + response.then(message => { + sendResponse(message); + }); + } else if (request.sendCookie) { + console.log('backgound: ' + JSON.stringify(request)); + let response = sendCookies(); + response.then(message => { + sendResponse(message); + }); + } - return true; + return true; } browserType.runtime.onMessage.addListener(handleMessage); diff --git a/extension/popup.js b/extension/popup.js index 2bd53f1..1e59401 100644 --- a/extension/popup.js +++ b/extension/popup.js @@ -6,186 +6,170 @@ let browserType = getBrowser(); // boilerplate to dedect browser type api function getBrowser() { - if (typeof chrome !== "undefined") { - if (typeof browser !== "undefined") { - return browser; - } else { - return chrome; - } + if (typeof chrome !== 'undefined') { + if (typeof browser !== 'undefined') { + return browser; } else { - console.log("failed to dedect browser"); - throw "browser detection error" - }; + return chrome; + } + } else { + console.log('failed to dedect browser'); + throw 'browser detection error'; + } } - // store access details -document.getElementById("save-login").addEventListener("click", function () { - let url = document.getElementById("full-url").value; - if (!url.includes('://')) { - url = 'http://' + url; - } - let parsed = new URL(url); - let toStore = { - "access": { - "url": `${parsed.protocol}//${parsed.hostname}`, - "port": parsed.port || (parsed.protocol === 'https:' ? '443' : '80'), - "apiKey": document.getElementById("api-key").value - } - }; - browserType.storage.local.set(toStore, function() { - console.log("Stored connection details: " + JSON.stringify(toStore)); - pingBackend(); - }); -}) - +document.getElementById('save-login').addEventListener('click', function () { + let url = document.getElementById('full-url').value; + if (!url.includes('://')) { + url = 'http://' + url; + } + let parsed = new URL(url); + let toStore = { + access: { + url: `${parsed.protocol}//${parsed.hostname}`, + port: parsed.port || (parsed.protocol === 'https:' ? '443' : '80'), + apiKey: document.getElementById('api-key').value, + }, + }; + browserType.storage.local.set(toStore, function () { + console.log('Stored connection details: ' + JSON.stringify(toStore)); + pingBackend(); + }); +}); // verify connection status -document.getElementById("status-icon").addEventListener("click", function() { - pingBackend(); -}) - +document.getElementById('status-icon').addEventListener('click', function () { + pingBackend(); +}); // send cookie -document.getElementById("sendCookies").addEventListener("click", function() { - sendCookie(); -}) - +document.getElementById('sendCookies').addEventListener('click', function () { + sendCookie(); +}); function sendCookie() { - console.log("popup send cookie"); + console.log('popup send cookie'); - function handleResponse(message) { - console.log("handle cookie response: " + JSON.stringify(message)); - let cookie_validated = message.cookie_validated; - document.getElementById("sendCookiesStatus").innerText = "validated: " + cookie_validated - } + function handleResponse(message) { + console.log('handle cookie response: ' + JSON.stringify(message)); + let cookie_validated = message.cookie_validated; + document.getElementById('sendCookiesStatus').innerText = 'validated: ' + cookie_validated; + } - function handleError(error) { - console.log(`Error: ${error}`); - } + function handleError(error) { + console.log(`Error: ${error}`); + } - let checked = document.getElementById("sendCookies").checked; - let toStore = { - "sendCookies": { - "checked": checked - } - }; - browserType.storage.local.set(toStore, function() { - console.log("stored option: " + JSON.stringify(toStore)); - }) - if (checked === false) { - return - } - let sending = browserType.runtime.sendMessage({"sendCookie": true}); - sending.then(handleResponse, handleError); + let checked = document.getElementById('sendCookies').checked; + let toStore = { + sendCookies: { + checked: checked, + }, + }; + browserType.storage.local.set(toStore, function () { + console.log('stored option: ' + JSON.stringify(toStore)); + }); + if (checked === false) { + return; + } + let sending = browserType.runtime.sendMessage({ sendCookie: true }); + sending.then(handleResponse, handleError); } - // send ping message to TA backend function pingBackend() { - - function handleResponse(message) { - if (message.response === "pong") { - setStatusIcon(true); - console.log("connection validated") - } + function handleResponse(message) { + if (message.response === 'pong') { + setStatusIcon(true); + console.log('connection validated'); } + } - function handleError(error) { - console.log(`Error: ${error}`); - setStatusIcon(false); - } - - console.log("ping TA server") - let sending = browserType.runtime.sendMessage({"verify": true}); - sending.then(handleResponse, handleError); + function handleError(error) { + console.log(`Error: ${error}`); + setStatusIcon(false); + } + console.log('ping TA server'); + let sending = browserType.runtime.sendMessage({ verify: true }); + sending.then(handleResponse, handleError); } // add url to image function addUrl(access) { - const url = `${access.url}:${access.port}`; - document.getElementById("ta-url").setAttribute("href", url); + const url = `${access.url}:${access.port}`; + document.getElementById('ta-url').setAttribute('href', url); } - function setCookieState() { - - function handleResponse(message) { - console.log(message); - document.getElementById("sendCookies").checked = message.cookie_enabled; - if (message.validated_str) { - document.getElementById("sendCookiesStatus").innerText = message.validated_str; - } + function handleResponse(message) { + console.log(message); + document.getElementById('sendCookies').checked = message.cookie_enabled; + if (message.validated_str) { + document.getElementById('sendCookiesStatus').innerText = message.validated_str; } + } - function handleError(error) { - console.log(`Error: ${error}`); - } + function handleError(error) { + console.log(`Error: ${error}`); + } - console.log("set cookie state"); - let sending = browserType.runtime.sendMessage({"cookieState": true}); - sending.then(handleResponse, handleError) - document.getElementById("sendCookies").checked = true; + console.log('set cookie state'); + let sending = browserType.runtime.sendMessage({ cookieState: true }); + sending.then(handleResponse, handleError); + document.getElementById('sendCookies').checked = true; } - // change status icon based on connection status function setStatusIcon(connected) { - - let statusIcon = document.getElementById("status-icon") - if (connected == true) { - statusIcon.innerHTML = "☑"; - statusIcon.style.color = "green"; - } else { - statusIcon.innerHTML = "☒"; - statusIcon.style.color = "red"; - } - + let statusIcon = document.getElementById('status-icon'); + if (connected == true) { + statusIcon.innerHTML = '☑'; + statusIcon.style.color = 'green'; + } else { + statusIcon.innerHTML = '☒'; + statusIcon.style.color = 'red'; + } } - // fill in form -document.addEventListener("DOMContentLoaded", async () => { - - function onGot(item) { - if (!item.access) { - console.log("no access details found"); - setStatusIcon(false); - return - } - let { url, port } = item.access; - let fullUrl = url; - if (!(url.startsWith('http://') && port === '80')) { - fullUrl += `:${port}`; - } - document.getElementById("full-url").value = fullUrl; - document.getElementById("api-key").value = item.access.apiKey; - pingBackend(); - addUrl(item.access); - }; - - function setCookiesOptions(result) { - if (!result.sendCookies || result.sendCookies.checked === false) { - console.log("sync cookies not set"); - return - } - console.log("set options: " + JSON.stringify(result)); - setCookieState(); - +document.addEventListener('DOMContentLoaded', async () => { + function onGot(item) { + if (!item.access) { + console.log('no access details found'); + setStatusIcon(false); + return; } + let { url, port } = item.access; + let fullUrl = url; + if (!(url.startsWith('http://') && port === '80')) { + fullUrl += `:${port}`; + } + document.getElementById('full-url').value = fullUrl; + document.getElementById('api-key').value = item.access.apiKey; + pingBackend(); + addUrl(item.access); + } - function onError(error) { - console.log(`Error: ${error}`); - }; + function setCookiesOptions(result) { + if (!result.sendCookies || result.sendCookies.checked === false) { + console.log('sync cookies not set'); + return; + } + console.log('set options: ' + JSON.stringify(result)); + setCookieState(); + } - browserType.storage.local.get("access", function(result) { - onGot(result) - }); + function onError(error) { + console.log(`Error: ${error}`); + } - browserType.storage.local.get("sendCookies", function(result) { - setCookiesOptions(result) - }) + browserType.storage.local.get('access', function (result) { + onGot(result); + }); -}) + browserType.storage.local.get('sendCookies', function (result) { + setCookiesOptions(result); + }); +}); diff --git a/extension/script.js b/extension/script.js index a7f00db..929f8e6 100644 --- a/extension/script.js +++ b/extension/script.js @@ -4,21 +4,20 @@ content script running on youtube.com let browserType = getBrowser(); - // boilerplate to dedect browser type api function getBrowser() { - if (typeof chrome !== "undefined") { - if (typeof browser !== "undefined") { - console.log("detected firefox"); - return browser; - } else { - console.log("detected chrome"); - return chrome; - } + if (typeof chrome !== 'undefined') { + if (typeof browser !== 'undefined') { + console.log('detected firefox'); + return browser; } else { - console.log("failed to dedect browser"); - throw "browser detection error" - }; + console.log('detected chrome'); + return chrome; + } + } else { + console.log('failed to dedect browser'); + throw 'browser detection error'; + } } const downloadIcon = ` { - e.preventDefault(); - var currentLocation = window.location.href; - console.log("subscribe to: " + currentLocation); - sendUrl(currentLocation, "subscribe", subLink); - }); - subLink.addEventListener("mouseover", e => { - let subText - if (window.location.pathname == "/watch") { - var currentLocation = window.location.href; - subText = currentLocation; - } else { - subText = channelContainer.querySelector("#text").textContent; - }; + var subLink = document.createElement('span'); + subLink.innerText = 'Subscribe'; + subLink.addEventListener('click', e => { + e.preventDefault(); + var currentLocation = window.location.href; + console.log('subscribe to: ' + currentLocation); + sendUrl(currentLocation, 'subscribe', subLink); + }); + subLink.addEventListener('mouseover', e => { + let subText; + if (window.location.pathname == '/watch') { + var currentLocation = window.location.href; + subText = currentLocation; + } else { + subText = channelContainer.querySelector('#text').textContent; + } - e.target.title = "TA Subscribe: " + subText; - }); - Object.assign(subLink.style, { - padding: "5px", - cursor: "pointer", - }); - - return subLink + e.target.title = 'TA Subscribe: ' + subText; + }); + Object.assign(subLink.style, { + padding: '5px', + cursor: 'pointer', + }); + + return subLink; } function buildSpacer() { - var spacer = document.createElement("span"); - spacer.innerText = "|"; + var spacer = document.createElement('span'); + spacer.innerText = '|'; - return spacer + return spacer; } function buildDlLink(channelContainer) { - var dlLink = document.createElement("span"); - dlLink.innerHTML = downloadIcon; + var dlLink = document.createElement('span'); + dlLink.innerHTML = downloadIcon; - dlLink.addEventListener('click', e => { - e.preventDefault(); - var currentLocation = window.location.href; - console.log("download: " + currentLocation) - sendUrl(currentLocation, "download", dlLink); - }); - dlLink.addEventListener("mouseover", e => { - let subText - if (window.location.pathname == "/watch") { - var currentLocation = window.location.href; - subText = currentLocation; - } else { - subText = channelContainer.querySelector("#text").textContent; - }; + dlLink.addEventListener('click', e => { + e.preventDefault(); + var currentLocation = window.location.href; + console.log('download: ' + currentLocation); + sendUrl(currentLocation, 'download', dlLink); + }); + dlLink.addEventListener('mouseover', e => { + let subText; + if (window.location.pathname == '/watch') { + var currentLocation = window.location.href; + subText = currentLocation; + } else { + subText = channelContainer.querySelector('#text').textContent; + } - e.target.title = "TA Download: " + subText; - }); - Object.assign(dlLink.style, { - filter: "invert()", - width: "20px", - padding: "0 5px", - cursor: "pointer", - }); + e.target.title = 'TA Download: ' + subText; + }); + Object.assign(dlLink.style, { + filter: 'invert()', + width: '20px', + padding: '0 5px', + cursor: 'pointer', + }); - return dlLink + return dlLink; } - function buildChannelButton(channelContainer) { + var buttonDiv = buildButtonDiv(); - var buttonDiv = buildButtonDiv() - - var subLink = buildSubLink(channelContainer); - buttonDiv.appendChild(subLink) + var subLink = buildSubLink(channelContainer); + buttonDiv.appendChild(subLink); - var spacer = buildSpacer() - buttonDiv.appendChild(spacer); + var spacer = buildSpacer(); + buttonDiv.appendChild(spacer); - var dlLink = buildDlLink(channelContainer) - buttonDiv.appendChild(dlLink); - - return buttonDiv + var dlLink = buildDlLink(channelContainer); + buttonDiv.appendChild(dlLink); + return buttonDiv; } function getChannelContainers() { - var nodes = document.querySelectorAll("#inner-header-container, #owner"); - return nodes + var nodes = document.querySelectorAll('#inner-header-container, #owner'); + return nodes; } function getThubnailContainers() { - var nodes = document.querySelectorAll('#thumbnail'); - return nodes + var nodes = document.querySelectorAll('#thumbnail'); + return nodes; } function buildVideoButton(thumbContainer) { - var thumbLink = thumbContainer?.href; - if (!thumbLink) return; - if (thumbLink.includes('list=') || thumbLink.includes('/shorts/')) return; + var thumbLink = thumbContainer?.href; + if (!thumbLink) return; + if (thumbLink.includes('list=') || thumbLink.includes('/shorts/')) return; - var dlButton = document.createElement("a"); - dlButton.setAttribute("id", "ta-video-button"); - dlButton.href = '#' - - dlButton.addEventListener('click', e => { - e.preventDefault(); - let videoLink = thumbContainer.href; - console.log("download: " + videoLink); - sendUrl(videoLink, "download", dlButton) - }); - dlButton.addEventListener('mouseover', e => { - Object.assign(dlButton.style, { - opacity: 1, - }); - let videoTitle = thumbContainer.href; - e.target.title = "TA download: " + videoTitle; - }) - dlButton.addEventListener('mouseout', e => { - Object.assign(dlButton.style, { - opacity: 0, - }); - }) + var dlButton = document.createElement('a'); + dlButton.setAttribute('id', 'ta-video-button'); + dlButton.href = '#'; + dlButton.addEventListener('click', e => { + e.preventDefault(); + let videoLink = thumbContainer.href; + console.log('download: ' + videoLink); + sendUrl(videoLink, 'download', dlButton); + }); + dlButton.addEventListener('mouseover', e => { Object.assign(dlButton.style, { - display: "flex", - position: "absolute", - top: "5px", - left: "5px", - alignItems: "center", - backgroundColor: "#00202f", - color: "#fff", - fontSize: "1.4rem", - textDecoration: "none", - borderRadius: "8px", - cursor: "pointer", - opacity: 0, - transition: "all 0.3s ease 0.3s", + opacity: 1, }); - - var dlIcon = document.createElement("span"); - dlIcon.innerHTML = downloadIcon; - Object.assign(dlIcon.style, { - filter: "invert()", - width: "20px", - padding: "10px 13px", + let videoTitle = thumbContainer.href; + e.target.title = 'TA download: ' + videoTitle; + }); + dlButton.addEventListener('mouseout', e => { + Object.assign(dlButton.style, { + opacity: 0, }); - - dlButton.appendChild(dlIcon); + }); - return dlButton + Object.assign(dlButton.style, { + display: 'flex', + position: 'absolute', + top: '5px', + left: '5px', + alignItems: 'center', + backgroundColor: '#00202f', + color: '#fff', + fontSize: '1.4rem', + textDecoration: 'none', + borderRadius: '8px', + cursor: 'pointer', + opacity: 0, + transition: 'all 0.3s ease 0.3s', + }); + var dlIcon = document.createElement('span'); + dlIcon.innerHTML = downloadIcon; + Object.assign(dlIcon.style, { + filter: 'invert()', + width: '20px', + padding: '10px 13px', + }); + + dlButton.appendChild(dlIcon); + + return dlButton; } - // fix positioning of #owner div to fit new button function adjustOwner(channelContainer) { - let sponsorButton = channelContainer.querySelector('#sponsor-button'); - if (sponsorButton === null) { - return channelContainer - } + let sponsorButton = channelContainer.querySelector('#sponsor-button'); + if (sponsorButton === null) { + return channelContainer; + } - let variableMinWidth - if (sponsorButton.hasChildNodes()) { - variableMinWidth = '140px'; - } else { - variableMinWidth = '45px'; - } + let variableMinWidth; + if (sponsorButton.hasChildNodes()) { + variableMinWidth = '140px'; + } else { + variableMinWidth = '45px'; + } - Object.assign(channelContainer.firstElementChild.style, { - minWidth: variableMinWidth - }) - Object.assign(channelContainer.style, { - minWidth: 'calc(40% + 50px)' - }) - return channelContainer + Object.assign(channelContainer.firstElementChild.style, { + minWidth: variableMinWidth, + }); + Object.assign(channelContainer.style, { + minWidth: 'calc(40% + 50px)', + }); + return channelContainer; } - function ensureTALinks() { + var channelContainerNodes = getChannelContainers(); - var channelContainerNodes = getChannelContainers() + for (var channelContainer of channelContainerNodes) { + channelContainer = adjustOwner(channelContainer); + if (channelContainer.hasTA) continue; + var channelButton = buildChannelButton(channelContainer); + channelContainer.appendChild(channelButton); + channelContainer.hasTA = true; + } - for (var channelContainer of channelContainerNodes) { - channelContainer = adjustOwner(channelContainer); - if (channelContainer.hasTA) continue; - var channelButton = buildChannelButton(channelContainer); - channelContainer.appendChild(channelButton); - channelContainer.hasTA = true; - } - - var thumbContainerNodes = getThubnailContainers(); - - for (var thumbContainer of thumbContainerNodes) { - if (thumbContainer.hasTA) continue; - var videoButton = buildVideoButton(thumbContainer); - if (videoButton == null) continue; - thumbContainer.parentElement.appendChild(videoButton); - thumbContainer.hasTA = true; - } + var thumbContainerNodes = getThubnailContainers(); + for (var thumbContainer of thumbContainerNodes) { + if (thumbContainer.hasTA) continue; + var videoButton = buildVideoButton(thumbContainer); + if (videoButton == null) continue; + thumbContainer.parentElement.appendChild(videoButton); + thumbContainer.hasTA = true; + } } - function buttonError(button) { - let buttonSpan = button.querySelector("span"); - if (buttonSpan === null) { - buttonSpan = button - } - buttonSpan.style.filter = "invert(19%) sepia(93%) saturate(7472%) hue-rotate(359deg) brightness(105%) contrast(113%)"; - buttonSpan.style.color = "red"; + let buttonSpan = button.querySelector('span'); + if (buttonSpan === null) { + buttonSpan = button; + } + buttonSpan.style.filter = + 'invert(19%) sepia(93%) saturate(7472%) hue-rotate(359deg) brightness(105%) contrast(113%)'; + buttonSpan.style.color = 'red'; - button.style.opacity = 1; - button.addEventListener('mouseout', e => { - Object.assign(button.style, { - opacity: 1, - }); - }) + button.style.opacity = 1; + button.addEventListener('mouseout', e => { + Object.assign(button.style, { + opacity: 1, + }); + }); } function buttonSuccess(button) { - let buttonSpan = button.querySelector("span"); - if (buttonSpan === null) { - buttonSpan = button; - } - if (buttonSpan.innerHTML === "Subscribe") { - buttonSpan.innerHTML = "Success"; - setTimeout(() => { - buttonSpan.innerHTML = "Subscribe"; - }, 2000); - } else { - buttonSpan.innerHTML = checkmarkIcon; - setTimeout(() => { - buttonSpan.innerHTML = downloadIcon; - }, 2000); - } + let buttonSpan = button.querySelector('span'); + if (buttonSpan === null) { + buttonSpan = button; + } + if (buttonSpan.innerHTML === 'Subscribe') { + buttonSpan.innerHTML = 'Success'; + setTimeout(() => { + buttonSpan.innerHTML = 'Subscribe'; + }, 2000); + } else { + buttonSpan.innerHTML = checkmarkIcon; + setTimeout(() => { + buttonSpan.innerHTML = downloadIcon; + }, 2000); + } } - function sendUrl(url, action, button) { - - function handleResponse(message) { - console.log("sendUrl response: " + JSON.stringify(message)); - if (message === null || message.detail === "Invalid token.") { - buttonError(button); - } else { - buttonSuccess(button); - } + function handleResponse(message) { + console.log('sendUrl response: ' + JSON.stringify(message)); + if (message === null || message.detail === 'Invalid token.') { + buttonError(button); + } else { + buttonSuccess(button); } + } - function handleError(error) { - console.log("error"); - console.log(JSON.stringify(error)); - } + function handleError(error) { + console.log('error'); + console.log(JSON.stringify(error)); + } - let payload = { - "youtube": { - "url": url, - "action": action, - } - } + let payload = { + youtube: { + url: url, + action: action, + }, + }; - console.log("youtube link: " + JSON.stringify(payload)); - - let sending = browserType.runtime.sendMessage(payload); - sending.then(handleResponse, handleError); - -}; + console.log('youtube link: ' + JSON.stringify(payload)); + let sending = browserType.runtime.sendMessage(payload); + sending.then(handleResponse, handleError); +} let throttleBlock; const throttle = (callback, time) => { - if (throttleBlock) return; - throttleBlock = true; - setTimeout(() => { - callback(); - throttleBlock = false; - }, time); + if (throttleBlock) return; + throttleBlock = true; + setTimeout(() => { + callback(); + throttleBlock = false; + }, time); }; let observer = new MutationObserver(list => { - if (list.some(i => i.type === 'childList' && i.addedNodes.length > 0)) { - throttle(ensureTALinks, 700); - } + if (list.some(i => i.type === 'childList' && i.addedNodes.length > 0)) { + throttle(ensureTALinks, 700); + } }); observer.observe(document.body, { attributes: false, childList: true, subtree: true });