From 4864a787bedded49cccfdf15ef9cf9a75d930754 Mon Sep 17 00:00:00 2001 From: YOLOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO Date: Sat, 1 Feb 2025 08:29:27 +0800 Subject: [PATCH] Add files via upload --- panel/panel.css | 145 ++++++++++++++++++++++++++ panel/panel.html | 98 ++++++++++++++++++ panel/panel.js | 259 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 502 insertions(+) create mode 100644 panel/panel.css create mode 100644 panel/panel.html create mode 100644 panel/panel.js diff --git a/panel/panel.css b/panel/panel.css new file mode 100644 index 0000000..25a6707 --- /dev/null +++ b/panel/panel.css @@ -0,0 +1,145 @@ +body { + font-family: Arial, sans-serif; + background-color: #ffffff; + color: black; + width: 400px; +} +.toggleButton { + width: 24px; +} +select { + max-width: 330px; +} +.text-box { + outline: none; + width: 80%; +} +#downloader-name { + width: 160px; +} +#export { + margin-top: 5px; +} + +/* Dark mode */ +.dark-mode { + background-color: #1b1b1b; + color: #d5d5d5; +} +.dark-mode fieldset { + border-color: #535353; +} +.dark-mode button, +.dark-mode select { + background-color: #222; + color: #d5d5d5; +} +.dark-mode button:hover, +.dark-mode select:hover { + background-color: #323232; +} +.dark-mode .expandableDiv { + background-color: #1b2027; +} +.dark-mode .text-box { + background-color: #323232; + color: #d5d5d5; +} + +/* Switch */ +.switch { + position: relative; + display: inline-block; + width: 40px; + height: 20px; + margin-left: 10px; +} +.switch input { + opacity: 0; + width: 0; + height: 0; +} + +/* Slider */ +.slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #ccc; + transition: 0.4s; + border-radius: 20px; +} +.slider:before { + position: absolute; + content: ""; + height: 14px; + width: 14px; + left: 3px; + bottom: 3px; + background-color: white; + border-radius: 50%; +} +input:checked + .slider { + background-color: #2196f3; +} +input:checked + .slider:before { + transform: translateX(20px); +} + +#clear { + width: 100%; + margin-bottom: 3px; +} + +#type-select { + margin-left: auto; +} + +#settings { + display: flex; +} + +.header { + display: flex; + justify-content: center; + align-items: center; +} +.header > * { + margin: 5px; +} + +#remote { + margin: 5px; +} + +.log-container { + display: flex; + justify-content: center; +} +.right-bound { + text-align: right; +} +.expandableDiv { + width: 100%; + overflow: hidden; + background-color: lightblue; + padding: 0; +} +.expandableDiv.expanded { + padding: 5px; +} +.expandableDiv.collapsed { + padding: 0; +} +.always-visible { + display: block; +} +.expanded-only { + display: none; +} +.expandableDiv.expanded .expanded-only { + display: block; +} diff --git a/panel/panel.html b/panel/panel.html new file mode 100644 index 0000000..d2f90ca --- /dev/null +++ b/panel/panel.html @@ -0,0 +1,98 @@ + + + + + + Playready Proxy Settings + + + + +
+ PlayreadyProxy Icon + ProxyText +
+ +
+ Settings +
+ +
+ + +
+ +
+ +
+ Remote CDM + + +
+ +
+ +
+ Local CDM + + +
+ +
+ +
+ Proxy Settings +
+ + +
+ +
+ +
+ Command Options +
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ Keys + +
+
+ + \ No newline at end of file diff --git a/panel/panel.js b/panel/panel.js new file mode 100644 index 0000000..bab9a32 --- /dev/null +++ b/panel/panel.js @@ -0,0 +1,259 @@ +import { + AsyncLocalStorage, + base64toUint8Array, + stringToUint8Array, + RemoteCDMManager, + SettingsManager, +} from "../util.js"; + +const key_container = document.getElementById("key-container"); + +// ================ Main ================ +const enabled = document.getElementById("enabled"); +enabled.addEventListener("change", async function () { + await SettingsManager.setEnabled(enabled.checked); +}); + +const export_button = document.getElementById("export"); +export_button.addEventListener("click", async function () { + const logs = await AsyncLocalStorage.getStorage(null); + SettingsManager.downloadFile( + stringToUint8Array(JSON.stringify(logs)), + "logs.json" + ); +}); + + +// ================ Remote CDM ================ +document.getElementById("remoteInput").addEventListener("click", () => { + chrome.runtime.sendMessage({ type: "OPEN_PICKER" }); + window.close(); +}); + +const remote_remove = document.getElementById("remoteRemove"); +remote_remove.addEventListener("click", async function () { + await RemoteCDMManager.removeSelectedRemoteCDM(); + remote_combobox.innerHTML = ""; + await RemoteCDMManager.loadSetAllRemoteCDMs(); + const selected_option = + remote_combobox.options[remote_combobox.selectedIndex]; + if (selected_option) { + await RemoteCDMManager.saveSelectedRemoteCDM(selected_option.text); + } else { + await RemoteCDMManager.removeSelectedRemoteCDMKey(); + } +}); + +const remote_download = document.getElementById("remoteDownload"); +remote_download.addEventListener("click", async function () { + const remote_cdm = await RemoteCDMManager.getSelectedRemoteCDM(); + SettingsManager.downloadFile( + await RemoteCDMManager.loadRemoteCDM(remote_cdm), + remote_cdm + ".json" + ); +}); + +const remote_combobox = document.getElementById("remote-combobox"); +remote_combobox.addEventListener("change", async function () { + await RemoteCDMManager.saveSelectedRemoteCDM( + remote_combobox.options[remote_combobox.selectedIndex].text + ); +}); + +const local_combobox = document.getElementById("local-combobox"); +local_combobox.addEventListener("change", async function () { + await LocalCDMManager.saveSelectedLocalCDM( + local_combobox.options[local_combobox.selectedIndex].text + ); +}); +// ============================================ + +// ====================== Proxy Settings ====================== + +// Get elements +const enableProxy = document.getElementById("enable-proxy"); +const proxyConfig = document.getElementById("proxy-config"); +const proxyUrlInput = document.getElementById("proxy-url"); + +// Enable or disable proxy settings +enableProxy.addEventListener("change", async function () { + const isProxyEnabled = enableProxy.checked; + if (isProxyEnabled) { + proxyConfig.style.display = "block"; + } else { + proxyConfig.style.display = "none"; + await SettingsManager.saveProxyConfig(""); // Clear proxy setting if disabled + } + await SettingsManager.setProxyEnabled(isProxyEnabled); +}); + +// Save proxy URL +proxyUrlInput.addEventListener("input", async function () { + const proxyUrl = proxyUrlInput.value; + await SettingsManager.saveProxyConfig(proxyUrl); // Save the proxy config +}); + + +// ================ Command Options ================ +const use_shaka = document.getElementById("use-shaka"); +use_shaka.addEventListener("change", async function () { + await SettingsManager.saveUseShakaPackager(use_shaka.checked); +}); + +const use_ddownloader = document.getElementById("use-ddownloader"); +use_shaka.addEventListener("change", async function () { + await SettingsManager.saveUseShakaPackager(use_ddownloader.checked); +}); + +const downloader_name = document.getElementById("downloader-name"); +downloader_name.addEventListener("input", async function (event) { + console.log("input change", event); + await SettingsManager.saveExecutableName(downloader_name.value); +}); +// ================================================= + +// ================ Keys ================ +const clear = document.getElementById("clear"); +clear.addEventListener("click", async function () { + chrome.runtime.sendMessage({ type: "CLEAR" }); + key_container.innerHTML = ""; +}); + +async function createCommand(json, key_string) { + const metadata = JSON.parse(json); + const header_string = Object.entries(metadata.headers) + .map(([key, value]) => `-H "${key}: ${value.replace(/"/g, "'")}"`) + .join(" "); + + // Assuming `metadata.url` is the URL to use, and output is derived from `metadata.id` or some other field + const output = metadata.id || "output"; // Change this according to how you want to generate the output name. + + return `DDownloader -u "${metadata.url}" ${header_string} ${key_string} -o "${output}"`; +} + +async function appendLog(result) { + const key_string = result.keys + .map((key) => `--key ${key.kid}:${key.k}`) + .join(" "); + + const logContainer = document.createElement("div"); + logContainer.classList.add("log-container"); + logContainer.innerHTML = ` + + `; + + const keysInput = logContainer.querySelector(".key-copy"); + keysInput.addEventListener("click", () => { + navigator.clipboard.writeText(key_string); + }); + + if (result.manifests.length > 0) { + const command = logContainer.querySelector("#command"); + + const select = logContainer.querySelector("#manifest"); + select.addEventListener("change", async () => { + command.value = await createCommand(select.value, key_string); + }); + result.manifests.forEach((manifest) => { + const option = new Option( + `[${manifest.type}] ${manifest.url}`, + JSON.stringify(manifest) + ); + select.add(option); + }); + command.value = await createCommand(select.value, key_string); + + const manifest_copy = logContainer.querySelector(".manifest-copy"); + manifest_copy.addEventListener("click", () => { + navigator.clipboard.writeText(JSON.parse(select.value).url); + }); + + const command_copy = logContainer.querySelector(".command-copy"); + command_copy.addEventListener("click", () => { + navigator.clipboard.writeText(command.value); + }); + } + + const toggleButtons = logContainer.querySelector(".toggleButton"); + toggleButtons.addEventListener("click", function () { + const expandableDiv = this.nextElementSibling; + if (expandableDiv.classList.contains("collapsed")) { + toggleButtons.innerHTML = "-"; + expandableDiv.classList.remove("collapsed"); + expandableDiv.classList.add("expanded"); + } else { + toggleButtons.innerHTML = "+"; + expandableDiv.classList.remove("expanded"); + expandableDiv.classList.add("collapsed"); + } + }); + + key_container.appendChild(logContainer); +} + +chrome.storage.onChanged.addListener(async (changes, areaName) => { + if (areaName === "local") { + for (const [key, values] of Object.entries(changes)) { + await appendLog(values.newValue); + } + } +}); + +function checkLogs() { + chrome.runtime.sendMessage({ type: "GET_LOGS" }, (response) => { + if (response) { + response.forEach(async (result) => { + await appendLog(result); + }); + } + }); +} + +document.addEventListener("DOMContentLoaded", async function () { + enabled.checked = await SettingsManager.getEnabled(); + use_shaka.checked = await SettingsManager.getUseShakaPackager(); + downloader_name.value = await SettingsManager.getExecutableName(); + await RemoteCDMManager.loadSetAllRemoteCDMs(); + await RemoteCDMManager.selectRemoteCDM( + await RemoteCDMManager.getSelectedRemoteCDM() + ); + checkLogs(); +}); + +document.addEventListener("DOMContentLoaded", async function () { + const isProxyEnabled = await SettingsManager.getProxyEnabled(); + enableProxy.checked = isProxyEnabled; + if (isProxyEnabled) { + proxyConfig.style.display = "block"; + } + + const savedProxyUrl = await SettingsManager.getProxy(); + const savedProxyPort = await SettingsManager.getProxyPort(); + + // Combine the proxy URL and port (if available) + if (savedProxyUrl && savedProxyPort) { + proxyUrlInput.value = `${savedProxyUrl}:${savedProxyPort}`; + } else { + proxyUrlInput.value = savedProxyUrl || ''; + } +}); + +// ======================================