diff --git a/popup/main.html b/popup/main.html
index cb6afd1..87ead62 100644
--- a/popup/main.html
+++ b/popup/main.html
@@ -142,7 +142,7 @@
CrawlFlix Server
+ placeholder="http://localhost:4200" value="http://localhost:4200">
diff --git a/popup/main.js b/popup/main.js
index a667e8e..d3ad82e 100644
--- a/popup/main.js
+++ b/popup/main.js
@@ -4,109 +4,113 @@ let requests = chrome.extension.getBackgroundPage().requests;
let pageURL = chrome.extension.getBackgroundPage().pageURL;
let targetIds = chrome.extension.getBackgroundPage().targetIds;
let clearkey = chrome.extension.getBackgroundPage().clearkey;
-let userInputs = {};
+let userInputs = {}; // IMPORTANT: Cette variable était manquante!
// === WIDEVINE KEY EXTRACTION ===
class WidevineExtractor {
- static async extractKeys() {
- const guessButton = document.getElementById("guess");
- const resultTextarea = document.getElementById('result');
-
- try {
- // UI feedback
- UIHelpers.setLoadingState(guessButton, true);
- document.body.style.cursor = "wait";
-
- // Initialize Pyodide
- const pyodide = await loadPyodide();
- await pyodide.loadPackage([
- "certifi-2024.2.2-py3-none-any.whl",
- "charset_normalizer-3.3.2-py3-none-any.whl",
- "construct-2.8.8-py2.py3-none-any.whl",
- "idna-3.6-py3-none-any.whl",
- "packaging-23.2-py3-none-any.whl",
- "protobuf-4.24.4-cp312-cp312-emscripten_3_1_52_wasm32.whl",
- "pycryptodome-3.20.0-cp35-abi3-emscripten_3_1_52_wasm32.whl",
- "pymp4-1.4.0-py3-none-any.whl",
- "pyodide_http-0.2.1-py3-none-any.whl",
- "pywidevine-1.8.0-py3-none-any.whl",
- "requests-2.31.0-py3-none-any.whl",
- "urllib3-2.2.1-py3-none-any.whl"
- ].map(e => "/libs/wheels/" + e));
+ static async extractKeys() {
+ const guessButton = document.getElementById("guess");
+ const resultTextarea = document.getElementById('result');
+
+ try {
+ // Vérifier que userInputs.license est défini
+ if (userInputs.license === undefined || !requests[userInputs.license]) {
+ throw new Error('License not selected. Please wait for auto-selection or select manually.');
+ }
+
+ // UI feedback
+ UIHelpers.setLoadingState(guessButton, true);
+ document.body.style.cursor = "wait";
+
+ // Initialize Pyodide
+ const pyodide = await loadPyodide();
+ await pyodide.loadPackage([
+ "certifi-2024.2.2-py3-none-any.whl",
+ "charset_normalizer-3.3.2-py3-none-any.whl",
+ "construct-2.8.8-py2.py3-none-any.whl",
+ "idna-3.6-py3-none-any.whl",
+ "packaging-23.2-py3-none-any.whl",
+ "protobuf-4.24.4-cp312-cp312-emscripten_3_1_52_wasm32.whl",
+ "pycryptodome-3.20.0-cp35-abi3-emscripten_3_1_52_wasm32.whl",
+ "pymp4-1.4.0-py3-none-any.whl",
+ "pyodide_http-0.2.1-py3-none-any.whl",
+ "pywidevine-1.8.0-py3-none-any.whl",
+ "requests-2.31.0-py3-none-any.whl",
+ "urllib3-2.2.1-py3-none-any.whl"
+ ].map(e => "/libs/wheels/" + e));
- // Configure Guesser
- pyodide.globals.set("pssh", document.getElementById('pssh').value);
- pyodide.globals.set("licUrl", requests[userInputs['license']]['url']);
- pyodide.globals.set("licHeaders", requests[userInputs['license']]['headers']);
- pyodide.globals.set("licBody", requests[userInputs['license']]['body']);
+ // Configure Guesser
+ pyodide.globals.set("pssh", document.getElementById('pssh').value);
+ pyodide.globals.set("licUrl", requests[userInputs['license']]['url']);
+ pyodide.globals.set("licHeaders", requests[userInputs['license']]['headers']);
+ pyodide.globals.set("licBody", requests[userInputs['license']]['body']);
- // Load Python scripts
- const [pre, after, scheme] = await Promise.all([
- fetch('/python/pre.py').then(res => res.text()),
- fetch('/python/after.py').then(res => res.text()),
- Promise.resolve(document.getElementById("schemeCode").value)
- ]);
+ // Load Python scripts
+ const [pre, after, scheme] = await Promise.all([
+ fetch('/python/pre.py').then(res => res.text()),
+ fetch('/python/after.py').then(res => res.text()),
+ Promise.resolve(document.getElementById("schemeCode").value)
+ ]);
- // Execute Python script
- const result = await pyodide.runPythonAsync([pre, scheme, after].join("\n"));
- resultTextarea.value = result;
+ // Execute Python script
+ const result = await pyodide.runPythonAsync([pre, scheme, after].join("\n"));
+ resultTextarea.value = result;
- // Save to history
- this.saveToHistory(result);
-
- // Auto-update CrawlFlix integration
- CrawlFlixIntegration.updateAfterKeyExtraction();
-
- StatusManager.show('Keys extracted successfully!', 'success');
-
- } catch (error) {
- console.error('Key extraction failed:', error);
- StatusManager.show(`Key extraction failed: ${error.message}`, 'error');
- } finally {
- // Reset UI
- UIHelpers.setLoadingState(guessButton, false);
- document.body.style.cursor = "auto";
- }
- }
+ // Save to history
+ this.saveToHistory(result);
+
+ // Auto-update CrawlFlix integration
+ CrawlFlixIntegration.updateAfterKeyExtraction();
+
+ StatusManager.show('Keys extracted successfully!', 'success');
+
+ } catch (error) {
+ console.error('Key extraction failed:', error);
+ StatusManager.show(`Key extraction failed: ${error.message}`, 'error');
+ } finally {
+ // Reset UI
+ UIHelpers.setLoadingState(guessButton, false);
+ document.body.style.cursor = "auto";
+ }
+ }
- static saveToHistory(result) {
- const historyData = {
- PSSH: document.getElementById('pssh').value,
- KEYS: result.split("\n").slice(0, -1)
- };
- chrome.storage.local.set({[pageURL]: historyData}, null);
- }
+ static saveToHistory(result) {
+ const historyData = {
+ PSSH: document.getElementById('pssh').value,
+ KEYS: result.split("\n").slice(0, -1)
+ };
+ chrome.storage.local.set({[pageURL]: historyData}, null);
+ }
- static async autoSelect() {
- userInputs["license"] = 0;
- document.getElementById("license").value = requests[0]['url'];
- document.getElementById('pssh').value = psshs[0];
-
- try {
- const selectRules = await fetch("/selectRules.conf").then(r => r.text());
- const rules = selectRules
- .replace(/\n^\s*$|\s*\/\/.*|\s*$/gm, "")
- .split("\n")
- .map(row => row.split("$$"));
+ static async autoSelect() {
+ userInputs["license"] = 0;
+ document.getElementById("license").value = requests[0]['url'];
+ document.getElementById('pssh').value = psshs[0];
+
+ try {
+ const selectRules = await fetch("/selectRules.conf").then(r => r.text());
+ const rules = selectRules
+ .replace(/\n^\s*$|\s*\/\/.*|\s*$/gm, "")
+ .split("\n")
+ .map(row => row.split("$$"));
- for (const item of rules) {
- const search = requests.map(r => r['url']).findIndex(e => e.includes(item[0]));
- if (search >= 0) {
- if (item[1]) document.getElementById("schemeSelect").value = item[1];
- userInputs["license"] = search;
- document.getElementById("license").value = requests[search]['url'];
- break;
- }
- }
+ for (const item of rules) {
+ const search = requests.map(r => r['url']).findIndex(e => e.includes(item[0]));
+ if (search >= 0) {
+ if (item[1]) document.getElementById("schemeSelect").value = item[1];
+ userInputs["license"] = search;
+ document.getElementById("license").value = requests[search]['url'];
+ break;
+ }
+ }
- document.getElementById("schemeSelect").dispatchEvent(new Event("input"));
- } catch (error) {
- console.error('Auto-select failed:', error);
- }
- }
+ document.getElementById("schemeSelect").dispatchEvent(new Event("input"));
+ } catch (error) {
+ console.error('Auto-select failed:', error);
+ }
+ }
}
-// === SMART MPD SELECTOR ===
class SmartMPDSelector {
static scoreAndRankMPDs(mpdUrls) {
const scoredMPDs = mpdUrls.map(url => ({
@@ -359,343 +363,345 @@ class MPDDetector {
// === CRAWLFLIX INTEGRATION ===
class CrawlFlixIntegration {
- static async sendToCrawlFlix(isClearchey = false) {
- const suffix = isClearchey ? 'CK' : '';
- const crawlFlixUrl = document.getElementById(`crawlFlixUrl${suffix}`).value || 'http://localhost:3000';
- const mpdUrl = document.getElementById(`mpdUrl${suffix}`).value;
- const resultTextarea = document.getElementById(isClearchey ? 'ckResult' : 'result');
-
- // Validation
- if (!mpdUrl.trim()) {
- StatusManager.show('Please enter or select an MPD URL', 'error', suffix);
- return;
- }
-
- if (!resultTextarea.value.trim()) {
- StatusManager.show('No keys available to send', 'error', suffix);
- return;
- }
-
- try {
- StatusManager.show('Processing MPD and sending to CrawlFlix...', 'info', suffix);
-
- // Parse and validate keys
- const keys = this.parseKeys(resultTextarea.value);
- if (keys.length === 0) {
- StatusManager.show('No valid keys found in the format key:value', 'error', suffix);
- return;
- }
+ static async sendToCrawlFlix(isClearchey = false) {
+ const suffix = isClearchey ? 'CK' : '';
+ const crawlFlixUrl = document.getElementById(`crawlFlixUrl${suffix}`).value || 'http://localhost:4200';
+ const mpdUrl = document.getElementById(`mpdUrl${suffix}`).value;
+ const resultTextarea = document.getElementById(isClearchey ? 'ckResult' : 'result');
+
+ // Validation
+ if (!mpdUrl.trim()) {
+ StatusManager.show('Please enter or select an MPD URL', 'error', suffix);
+ return;
+ }
+
+ if (!resultTextarea.value.trim()) {
+ StatusManager.show('No keys available to send', 'error', suffix);
+ return;
+ }
+
+ try {
+ StatusManager.show('Opening CrawlFlix with preloaded data...', 'info', suffix);
+
+ // Parse et valide les clés pour information
+ const keys = this.parseKeys(resultTextarea.value);
+ if (keys.length === 0) {
+ StatusManager.show('No valid keys found in the format key:value', 'error', suffix);
+ return;
+ }
- // Test CrawlFlix connection and process MPD
- const mpdData = await this.processMPD(crawlFlixUrl, mpdUrl);
-
- // Create success message
- const message = `✓ Successfully sent to CrawlFlix!
-${keys.length} key(s) • ${mpdData.videoTracks.length} video track(s) • ${mpdData.audioTracks.length} audio track(s) • ${mpdData.subtitles.length} subtitle(s)`;
-
- StatusManager.show(message, 'success', suffix);
-
- // Open CrawlFlix with pre-filled data
- this.openCrawlFlixTab(crawlFlixUrl, mpdUrl, resultTextarea.value);
-
- } catch (error) {
- console.error('CrawlFlix send error:', error);
- StatusManager.show(`Failed to send: ${error.message}`, 'error', suffix);
- }
- }
+ // Ouvrir CrawlFlix directement avec les paramètres
+ this.openCrawlFlixTab(crawlFlixUrl, mpdUrl, resultTextarea.value);
+
+ // Message de succès
+ const contentType = isClearchey ? 'ClearKey' : 'Widevine';
+ StatusManager.show(`${contentType} data sent to CrawlFlix! (${keys.length} keys, MPD URL)`, 'success', suffix);
+
+ } catch (error) {
+ console.error('CrawlFlix send error:', error);
+ StatusManager.show(`Failed to send: ${error.message}`, 'error', suffix);
+ }
+ }
- static parseKeys(keysText) {
- return keysText
- .split('\n')
- .map(line => line.trim())
- .filter(line => line && line.includes(':'))
- .map(line => {
- const [key, value] = line.split(':');
- return {
- key: key?.trim(),
- value: value?.trim()
- };
- })
- .filter(k => k.key && k.value && k.key.length > 0 && k.value.length > 0);
- }
+ static parseKeys(keysText) {
+ return keysText
+ .split('\n')
+ .map(line => line.trim())
+ .filter(line => line && line.includes(':'))
+ .map(line => {
+ const [key, value] = line.split(':');
+ return {
+ key: key?.trim(),
+ value: value?.trim()
+ };
+ })
+ .filter(k => k.key && k.value && k.key.length > 0 && k.value.length > 0);
+ }
- static async processMPD(crawlFlixUrl, mpdUrl) {
- const response = await fetch(`${crawlFlixUrl}/processMPD`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ mpdUrl })
- });
-
- if (!response.ok) {
- const errorText = await response.text().catch(() => 'Unknown error');
- throw new Error(`MPD processing failed (${response.status}): ${errorText}`);
- }
-
- return await response.json();
- }
+ static async processMPD(crawlFlixUrl, mpdUrl) {
+ const response = await fetch(`${crawlFlixUrl}/processMPD`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ mpdUrl })
+ });
+
+ if (!response.ok) {
+ const errorText = await response.text().catch(() => 'Unknown error');
+ throw new Error(`MPD processing failed (${response.status}): ${errorText}`);
+ }
+
+ return await response.json();
+ }
- static openCrawlFlixTab(crawlFlixUrl, mpdUrl, keysText) {
- const params = new URLSearchParams({
- mpdUrl: mpdUrl,
- keys: keysText,
- source: 'widevine-plugin'
- });
-
- const crawlFlixTab = `${crawlFlixUrl}?${params.toString()}`;
- chrome.tabs.create({ url: crawlFlixTab });
- }
+ static openCrawlFlixTab(crawlFlixUrl, mpdUrl, keysText) {
+ // Encoder les données pour l'URL
+ const params = new URLSearchParams({
+ mpdUrl: mpdUrl,
+ keys: keysText,
+ autoLoad: 'true'
+ });
+
+ // Ouvrir CrawlFlix avec les paramètres pré-remplis
+ const crawlFlixTab = `${crawlFlixUrl}?${params.toString()}`;
+ chrome.tabs.create({ url: crawlFlixTab });
+
+ console.log('Opening CrawlFlix with preloaded data:', crawlFlixTab);
+ }
- static copyKeys(resultTextareaId) {
- const textarea = document.getElementById(resultTextareaId);
- if (!textarea || !textarea.value.trim()) {
- StatusManager.show('No keys to copy', 'error');
- return;
- }
+ static copyKeys(resultTextareaId) {
+ const textarea = document.getElementById(resultTextareaId);
+ if (!textarea || !textarea.value.trim()) {
+ StatusManager.show('No keys to copy', 'error');
+ return;
+ }
- navigator.clipboard.writeText(textarea.value).then(() => {
- StatusManager.show('Keys copied to clipboard!', 'success');
- }).catch(err => {
- console.error('Copy failed:', err);
- StatusManager.show('Failed to copy keys', 'error');
- });
- }
+ navigator.clipboard.writeText(textarea.value).then(() => {
+ StatusManager.show('Keys copied to clipboard!', 'success');
+ }).catch(err => {
+ console.error('Copy failed:', err);
+ StatusManager.show('Failed to copy keys', 'error');
+ });
+ }
- static updateAfterKeyExtraction() {
- // Auto-refresh MPD detection after key extraction
- setTimeout(() => {
- MPDDetector.updateDropdowns();
- }, 1000);
- }
+ static updateAfterKeyExtraction() {
+ // Auto-refresh MPD detection after key extraction
+ setTimeout(() => {
+ MPDDetector.updateDropdowns();
+ }, 1000);
+ }
- static loadSavedSettings() {
- chrome.storage.local.get(['crawlFlixUrl'], (result) => {
- if (result.crawlFlixUrl) {
- const inputs = ['crawlFlixUrl', 'crawlFlixUrlCK'];
- inputs.forEach(id => {
- const input = document.getElementById(id);
- if (input && !input.value) {
- input.value = result.crawlFlixUrl;
- }
- });
- }
- });
- }
+ static loadSavedSettings() {
+ chrome.storage.local.get(['crawlFlixUrl'], (result) => {
+ if (result.crawlFlixUrl) {
+ const inputs = ['crawlFlixUrl', 'crawlFlixUrlCK'];
+ inputs.forEach(id => {
+ const input = document.getElementById(id);
+ if (input && !input.value) {
+ input.value = result.crawlFlixUrl;
+ }
+ });
+ }
+ });
+ }
- static saveSettings() {
- const inputs = ['crawlFlixUrl', 'crawlFlixUrlCK'];
- inputs.forEach(id => {
- const input = document.getElementById(id);
- if (input) {
- input.addEventListener('change', (e) => {
- chrome.storage.local.set({ crawlFlixUrl: e.target.value });
- });
- }
- });
- }
+ static saveSettings() {
+ const inputs = ['crawlFlixUrl', 'crawlFlixUrlCK'];
+ inputs.forEach(id => {
+ const input = document.getElementById(id);
+ if (input) {
+ input.addEventListener('change', (e) => {
+ chrome.storage.local.set({ crawlFlixUrl: e.target.value });
+ });
+ }
+ });
+ }
}
// === STATUS MANAGER ===
class StatusManager {
- static show(message, type, suffix = '') {
- const statusDiv = document.getElementById(`crawlFlixStatus${suffix}`);
- if (!statusDiv) return;
+ static show(message, type, suffix = '') {
+ const statusDiv = document.getElementById(`crawlFlixStatus${suffix}`);
+ if (!statusDiv) return;
- // Clear any existing content
- statusDiv.innerHTML = '';
+ // Clear any existing content
+ statusDiv.innerHTML = '';
- // Create alert element
- const alert = document.createElement('div');
- alert.className = `alert alert-${this.getBootstrapClass(type)} alert-dismissible fade show`;
- alert.innerHTML = `
-
- ${message.replace(/\n/g, '
')}
-
- `;
-
- statusDiv.appendChild(alert);
+ // Create alert element
+ const alert = document.createElement('div');
+ alert.className = `alert alert-${this.getBootstrapClass(type)} alert-dismissible fade show`;
+ alert.innerHTML = `
+
+ ${message.replace(/\n/g, '
')}
+
+ `;
+
+ statusDiv.appendChild(alert);
- // Auto-dismiss after delay
- if (type === 'success' || type === 'info') {
- setTimeout(() => {
- if (alert.parentNode) {
- alert.classList.remove('show');
- setTimeout(() => alert.remove(), 300);
- }
- }, 5000);
- }
- }
+ // Auto-dismiss after delay
+ if (type === 'success' || type === 'info') {
+ setTimeout(() => {
+ if (alert.parentNode) {
+ alert.classList.remove('show');
+ setTimeout(() => alert.remove(), 300);
+ }
+ }, 5000);
+ }
+ }
- static getBootstrapClass(type) {
- const mapping = {
- success: 'success',
- error: 'danger',
- info: 'info',
- warning: 'warning'
- };
- return mapping[type] || 'secondary';
- }
+ static getBootstrapClass(type) {
+ const mapping = {
+ success: 'success',
+ error: 'danger',
+ info: 'info',
+ warning: 'warning'
+ };
+ return mapping[type] || 'secondary';
+ }
- static getIcon(type) {
- const mapping = {
- success: 'fa-check-circle',
- error: 'fa-exclamation-triangle',
- info: 'fa-info-circle',
- warning: 'fa-exclamation-triangle'
- };
- return mapping[type] || 'fa-info';
- }
+ static getIcon(type) {
+ const mapping = {
+ success: 'fa-check-circle',
+ error: 'fa-exclamation-triangle',
+ info: 'fa-info-circle',
+ warning: 'fa-exclamation-triangle'
+ };
+ return mapping[type] || 'fa-info';
+ }
}
// === UI HELPERS ===
class UIHelpers {
- static setLoadingState(button, isLoading) {
- if (!button) return;
-
- if (isLoading) {
- button.disabled = true;
- const originalText = button.innerHTML;
- button.dataset.originalText = originalText;
- button.innerHTML = 'Extracting Keys...';
- } else {
- button.disabled = false;
- button.innerHTML = button.dataset.originalText || button.innerHTML;
- }
- }
+ static setLoadingState(button, isLoading) {
+ if (!button) return;
+
+ if (isLoading) {
+ button.disabled = true;
+ const originalText = button.innerHTML;
+ button.dataset.originalText = originalText;
+ button.innerHTML = 'Extracting Keys...';
+ } else {
+ button.disabled = false;
+ button.innerHTML = ' Extract Widevine Keys';
+ }
+ }
- static copyToClipboard(text) {
- const textarea = document.createElement('textarea');
- textarea.value = text;
- document.body.appendChild(textarea);
- textarea.select();
- document.execCommand('copy');
- document.body.removeChild(textarea);
- }
+ static copyToClipboard(text) {
+ const textarea = document.createElement('textarea');
+ textarea.value = text;
+ document.body.appendChild(textarea);
+ textarea.select();
+ document.execCommand('copy');
+ document.body.removeChild(textarea);
+ }
}
// === EVENT LISTENERS ===
class EventManager {
- static init() {
- this.setupWidevineListeners();
- this.setupCrawlFlixListeners();
- this.setupUIListeners();
- }
+ static init() {
+ this.setupWidevineListeners();
+ this.setupCrawlFlixListeners();
+ this.setupUIListeners();
+ }
- static setupWidevineListeners() {
- const guessButton = document.getElementById('guess');
- const resultTextarea = document.getElementById('result');
-
- if (guessButton) {
- guessButton.addEventListener('click', () => WidevineExtractor.extractKeys());
- }
-
- if (resultTextarea) {
- resultTextarea.addEventListener('click', function() {
- this.select();
- navigator.clipboard.writeText(this.value);
- });
- }
- }
+ static setupWidevineListeners() {
+ const guessButton = document.getElementById('guess');
+ const resultTextarea = document.getElementById('result');
+
+ if (guessButton) {
+ guessButton.addEventListener('click', () => WidevineExtractor.extractKeys());
+ }
+
+ if (resultTextarea) {
+ resultTextarea.addEventListener('click', function() {
+ this.select();
+ navigator.clipboard.writeText(this.value);
+ });
+ }
+ }
- static setupCrawlFlixListeners() {
- // Dropdown selections
- ['mpdSelect', 'mpdSelectCK'].forEach(selectId => {
- const select = document.getElementById(selectId);
- const urlInput = document.getElementById(selectId.replace('Select', 'Url'));
- if (select && urlInput) {
- select.addEventListener('change', (e) => {
- if (e.target.value) {
- urlInput.value = e.target.value;
- }
- });
- }
- });
+ static setupCrawlFlixListeners() {
+ // Dropdown selections
+ ['mpdSelect', 'mpdSelectCK'].forEach(selectId => {
+ const select = document.getElementById(selectId);
+ const urlInput = document.getElementById(selectId.replace('Select', 'Url'));
+ if (select && urlInput) {
+ select.addEventListener('change', (e) => {
+ if (e.target.value) {
+ urlInput.value = e.target.value;
+ }
+ });
+ }
+ });
- // Refresh buttons
- ['refreshMPDs', 'refreshMPDsCK'].forEach(buttonId => {
- const button = document.getElementById(buttonId);
- if (button) {
- button.addEventListener('click', () => MPDDetector.updateDropdowns());
- }
- });
+ // Refresh buttons
+ ['refreshMPDs', 'refreshMPDsCK'].forEach(buttonId => {
+ const button = document.getElementById(buttonId);
+ if (button) {
+ button.addEventListener('click', () => MPDDetector.updateDropdowns());
+ }
+ });
- // Send buttons
- const sendButton = document.getElementById('sendToCrawlFlix');
- if (sendButton) {
- sendButton.addEventListener('click', () => CrawlFlixIntegration.sendToCrawlFlix(false));
- }
+ // Send buttons
+ const sendButton = document.getElementById('sendToCrawlFlix');
+ if (sendButton) {
+ sendButton.addEventListener('click', () => CrawlFlixIntegration.sendToCrawlFlix(false));
+ }
- const sendButtonCK = document.getElementById('sendToCrawlFlixCK');
- if (sendButtonCK) {
- sendButtonCK.addEventListener('click', () => CrawlFlixIntegration.sendToCrawlFlix(true));
- }
+ const sendButtonCK = document.getElementById('sendToCrawlFlixCK');
+ if (sendButtonCK) {
+ sendButtonCK.addEventListener('click', () => CrawlFlixIntegration.sendToCrawlFlix(true));
+ }
- // Copy buttons
- const copyButton = document.getElementById('copyKeys');
- if (copyButton) {
- copyButton.addEventListener('click', () => CrawlFlixIntegration.copyKeys('result'));
- }
+ // Copy buttons
+ const copyButton = document.getElementById('copyKeys');
+ if (copyButton) {
+ copyButton.addEventListener('click', () => CrawlFlixIntegration.copyKeys('result'));
+ }
- const copyButtonCK = document.getElementById('copyKeysCK');
- if (copyButtonCK) {
- copyButtonCK.addEventListener('click', () => CrawlFlixIntegration.copyKeys('ckResult'));
- }
- }
+ const copyButtonCK = document.getElementById('copyKeysCK');
+ if (copyButtonCK) {
+ copyButtonCK.addEventListener('click', () => CrawlFlixIntegration.copyKeys('ckResult'));
+ }
+ }
- static setupUIListeners() {
- // ClearKey result click handler
- const ckResult = document.getElementById('ckResult');
- if (ckResult) {
- ckResult.addEventListener('click', function() {
- this.select();
- navigator.clipboard.writeText(this.value);
- });
- }
- }
+ static setupUIListeners() {
+ // ClearKey result click handler
+ const ckResult = document.getElementById('ckResult');
+ if (ckResult) {
+ ckResult.addEventListener('click', function() {
+ this.select();
+ navigator.clipboard.writeText(this.value);
+ });
+ }
+ }
}
// === CORS FETCH HELPER ===
window.corsFetch = (u, m, h, b) => {
- return new Promise((resolve, reject) => {
- chrome.tabs.sendMessage(targetIds[0], {
- type: "FETCH",
- u: u,
- m: m,
- h: h,
- b: b
- }, {frameId: targetIds[1]}, res => {
- resolve(res);
- });
- });
+ return new Promise((resolve, reject) => {
+ chrome.tabs.sendMessage(targetIds[0], {
+ type: "FETCH",
+ u: u,
+ m: m,
+ h: h,
+ b: b
+ }, {frameId: targetIds[1]}, res => {
+ resolve(res);
+ });
+ });
};
// === INITIALIZATION ===
document.addEventListener('DOMContentLoaded', () => {
- EventManager.init();
- CrawlFlixIntegration.loadSavedSettings();
- CrawlFlixIntegration.saveSettings();
+ EventManager.init();
+ CrawlFlixIntegration.loadSavedSettings();
+ CrawlFlixIntegration.saveSettings();
});
// Main initialization logic
if (clearkey) {
- // ClearKey detected
- document.getElementById('noEME').style.display = 'none';
- document.getElementById('ckHome').style.display = 'block';
- document.getElementById('ckResult').value = clearkey;
-
- MPDDetector.updateDropdowns();
- StatusManager.show('ClearKey content detected', 'success');
- MPDDetector.updateBadgeFromPopup();
+ // ClearKey detected
+ document.getElementById('noEME').style.display = 'none';
+ document.getElementById('ckHome').style.display = 'block';
+ document.getElementById('ckResult').value = clearkey;
+
+ MPDDetector.updateDropdowns();
+ StatusManager.show('ClearKey content detected', 'success');
+
} else if (psshs.length) {
- // Widevine detected
- document.getElementById('noEME').style.display = 'none';
- document.getElementById('home').style.display = 'block';
-
- WidevineExtractor.autoSelect();
- MPDDetector.updateDropdowns();
- StatusManager.show('Widevine content detected', 'success');
- MPDDetector.updateBadgeFromPopup();
- // Auto-refresh MPD detection periodically
- setInterval(() => {
- MPDDetector.updateDropdowns();
- }, 3000);
+ // Widevine detected
+ document.getElementById('noEME').style.display = 'none';
+ document.getElementById('home').style.display = 'block';
+
+ // IMPORTANT: Faire autoSelect avant d'initialiser les event listeners
+ WidevineExtractor.autoSelect().then(() => {
+ EventManager.init();
+ MPDDetector.updateDropdowns();
+ StatusManager.show('Widevine content detected and configured', 'success');
+ });
+
+ // Auto-refresh MPD detection periodically
+ setInterval(() => {
+ MPDDetector.updateDropdowns();
+ }, 3000);
}
\ No newline at end of file