Add files via upload

This commit is contained in:
YOLOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
2025-02-01 08:29:27 +08:00
committed by GitHub
parent c88b4d9068
commit 4864a787be
3 changed files with 502 additions and 0 deletions

145
panel/panel.css Normal file
View File

@@ -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;
}

98
panel/panel.html Normal file
View File

@@ -0,0 +1,98 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Playready Proxy Settings</title>
<script type="module" src="panel.js" defer></script>
<link rel="stylesheet" href="panel.css" />
</head>
<body class="dark-mode" style="min-width: 200px">
<div class="header">
<img
src="../images/icon-128.png"
alt="PlayreadyProxy Icon"
width="64"
/>
<img
src="../images/proxy_text.png"
alt="ProxyText"
width="200"
/>
</div>
<fieldset>
<legend>Settings</legend>
<div id="settings">
<!-- Enabled -->
<div>
<input type="checkbox" id="enabled" />
<label for="enabled"> Enabled</label>
</div>
<!-- Dark mode -->
</div>
<fieldset id="remote">
<legend>Remote CDM</legend>
<button type="button" id="remoteInput">
Choose Config
</button>
<button type="button" id="remoteRemove">Remove</button>
<button type="button" id="remoteDownload">Download</button><br />
<label for="remote-combobox">
Select Config:
<select id="remote-combobox"></select>
</label>
</fieldset>
<fieldset id="local">
<legend>Local CDM</legend>
<button type="button" id="localInput">
Choose Device
</button>
<button type="button" id="localRemove">Remove</button>
<button type="button" id="localDownload">Download</button><br />
<label for="local-combobox">
Select Device:
<select id="local-combobox"></select>
</label>
</fieldset>
<fieldset id="proxy-settings">
<legend>Proxy Settings</legend>
<div>
<input type="checkbox" id="enable-proxy" />
<label for="enable-proxy">Enable Proxy</label>
</div>
<div id="proxy-config" style="display: none;">
<label for="proxy-url">Proxy URL: </label>
<input type="text" class="text-box" id="proxy-url" placeholder="http://your.proxy.url:port" />
</div>
</fieldset>
<fieldset id="command-options">
<legend>Command Options</legend>
<div>
<input type="checkbox" id="use-shaka" /> <!-- Unchecked by default -->
<label for="use-shaka"> Use Shaka Packager</label>
</div>
<div>
<input type="checkbox" id="use-ddownloader" checked /> <!-- Default checked -->
<label for="use-ddownloader"> Use DDownloader</label>
</div>
<div>
<label for="downloader-name">Executable name: </label>
<input type="text" class="text-box" id="downloader-name" />
</div>
</fieldset>
<button type="button" id="export">Export Logs</button>
</fieldset>
<fieldset>
<legend>Keys</legend>
<button type="button" id="clear">Clear</button>
<div id="key-container"></div>
</fieldset>
</body>
</html>

259
panel/panel.js Normal file
View File

@@ -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 = `
<button class="toggleButton">+</button>
<div class="expandableDiv collapsed">
<label class="always-visible right-bound">
URL:<input type="text" class="text-box" value="${result.url}">
</label>
<label class="expanded-only right-bound">
<label class="expanded-only right-bound key-copy">
<a href="#" title="Click to copy">Keys:</a><input type="text" class="text-box" value="${key_string}">
</label>
${
result.manifests.length > 0
? `<label class="expanded-only right-bound manifest-copy">
<a href="#" title="Click to copy">Manifest:</a><select id="manifest" class="text-box"></select>
</label>
<label class="expanded-only right-bound command-copy">
<a href="#" title="Click to copy">Cmd:</a><input type="text" id="command" class="text-box">
</label>`
: ""
}
</div>`;
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 || '';
}
});
// ======================================