commit edbe7b4b06c80ce9e6c36e0748737de7ab6b2d1d Author: XMYSTERlOUSX <73080587+XMYSTERlOUSX@users.noreply.github.com> Date: Mon Oct 3 18:09:49 2022 +0530 Chrome Extensions! diff --git a/Aha Capture/background.js b/Aha Capture/background.js new file mode 100644 index 0000000..2748ebb --- /dev/null +++ b/Aha Capture/background.js @@ -0,0 +1,128 @@ +const tabIDs = {}; +const textDecoder = new TextDecoder(); + +function requestToClipboard(tabId) { + chrome.tabs.get(tabId, (details) => { + const lic_headers = tabIDs[details.id].license_request[0]?.license_headers; + const lic_url = tabIDs[details.id].license_url; + const lic_data_json = tabIDs[details.id].license_data; + const mpd_link = tabIDs[details.id].mpd_url; + const video_link = tabIDs[details.id].player_url; + if (!lic_headers) + return; + + // Fetching the user's ip for setting the header X-Forwarded-For. + // This might help to bypass regional restrictions when performing the license request in some cases. + + const ip_retrieve_link = "https://ipinfo.io/ip"; + + var get_ip = new XMLHttpRequest(); + get_ip.open('GET', ip_retrieve_link, true); + get_ip.onload = function () { + var ip_resposnse = this.responseText; + console.log(ip_resposnse); + + var i = 0; + let curl_license_data = "curl "; + curl_license_data += `'${lic_url}' \\`; + for (; i < lic_headers.length; ++i) + curl_license_data += `\n -H '${lic_headers[i].name.toLowerCase()}: ${lic_headers[i].value}' \\`; + curl_license_data += `\n -H 'x-forwarded-for: ${ip_resposnse}' \\`; + curl_license_data += "\n --data-raw "; + + if (lic_data_json.includes("u0008")) { + curl_license_data += `${lic_data_json} \\`; + } else { + curl_license_data += `'${lic_data_json}' \\`; /* It is not the same as above line. Note the additional ' symbol at the start and end! */ + } + + curl_license_data += "\n --compressed"; + + // Generating the curl license text link for https://t.me/drm_downloader_robot + const aha_gen_link = "https://drm-bot.herokuapp.com/aha.php"; + var data = new FormData(); + data.append('playlist', curl_license_data); + data.append('api', 'api'); + + var gen_link = new XMLHttpRequest(); + gen_link.open('POST', aha_gen_link, true); + gen_link.onload = function () { + var gen_link_resposnse = this.responseText; + let json_resp = JSON.parse(gen_link_resposnse); + console.log(json_resp); + let generated_license_link = json_resp.data; + + const final = `${video_link}*${mpd_link}*${generated_license_link}`; + console.log(final); + + const copyText = document.createElement("textarea"); + copyText.style.position = "absolute"; + copyText.style.left = "-5454px"; + copyText.style.top = "-5454px"; + copyText.style.opacity = 0; + document.body.appendChild(copyText); + copyText.value = final; + copyText.select(); + document.execCommand("copy"); + document.body.removeChild(copyText); + + chrome.browserAction.setBadgeBackgroundColor({color: "#FF0000", tabId: details.id}); + chrome.browserAction.setBadgeText({text: "📋", tabId: details.id}); + alert("The aha link and the mpd link and the generated link of widevine license curl data has been copied to your clipboard successfully!\n\nNow go to https://t.me/drm_downloader_robot and paste it and send it to the bot."); + + } + gen_link.send(data); + } + get_ip.send(); + }); +} + +function getLicenseRequestData(details) { + if (details.url.includes(".mpd")) { + console.log(details.url); + tabIDs[details.tabId].mpd_url = details.url; + } else if (details.requestBody && details.requestBody.raw && details.method == "POST") { + for (var j = 0; j < details.requestBody.raw.length; ++j) { + try { + const decodedString = textDecoder.decode(details.requestBody.raw[j].bytes); + const encodedString = btoa(unescape(encodeURIComponent(decodedString))); + + // If the license request does not uses json payloads the data has been sent in raw format. + // But the base64 encoded format of it will have the characters "CAES". + if (encodedString.includes("CAES")) { + tabIDs[details.tabId].license_data = `$'\\u0008\\u0004'` + tabIDs[details.tabId].license_url = details.url + tabIDs[details.tabId].req_id = details.requestId + } else { + return; + } + } catch (e) { + console.error(e); + } + } + } +} +chrome.webRequest.onBeforeRequest.addListener( + getLicenseRequestData, + { urls: ["https://streaming-vod-aha.akamaized.net/*", "https://widevine-proxy.api.aha.firstlight.ai/*"], types: ["xmlhttprequest"] }, + ["requestBody"] +); + +function getLicenseRequestHeaders(details) { + if (details.method == "POST" && tabIDs[details.tabId] && tabIDs[details.tabId].license_url === details.url && tabIDs[details.tabId].req_id === details.requestId) { + console.log(details.url); + tabIDs[details.tabId].license_request.push({license_headers: details.requestHeaders}); + requestToClipboard(details.tabId); + } +} +chrome.webRequest.onBeforeSendHeaders.addListener( + getLicenseRequestHeaders, + { urls: ["https://widevine-proxy.api.aha.firstlight.ai/*"], types: ["xmlhttprequest"] }, + ["requestHeaders"] +); + +chrome?.tabs?.onUpdated?.addListener((tabId, changeInfo, tab) => { + if (tab.url.includes("https://www.aha.video/player/")) { + tabIDs[tabId] = {license_data: "", license_request: [], license_url: "", req_id: "", mpd_url: "", player_url: tab.url}; + } +}); \ No newline at end of file diff --git a/Aha Capture/icon128.png b/Aha Capture/icon128.png new file mode 100644 index 0000000..9c4a677 Binary files /dev/null and b/Aha Capture/icon128.png differ diff --git a/Aha Capture/manifest.json b/Aha Capture/manifest.json new file mode 100644 index 0000000..b34a0c9 --- /dev/null +++ b/Aha Capture/manifest.json @@ -0,0 +1,11 @@ +{ + "background": { + "persistent": true, + "scripts": [ "background.js" ] + }, + "manifest_version": 2, + "name": "Aha Capture", + "browser_action": {"default_icon": "icon128.png"}, + "permissions": [ "activeTab", "webRequest", "https://www.aha.video/*", "https://streaming-vod-aha.akamaized.net/*", "https://widevine-proxy.api.aha.firstlight.ai/*", "https://drm-bot.herokuapp.com/", "tabs", "clipboardWrite", "storage" ], + "version": "2.0" +} \ No newline at end of file diff --git a/Altbalaji Capture/background.js b/Altbalaji Capture/background.js new file mode 100644 index 0000000..d2febc4 --- /dev/null +++ b/Altbalaji Capture/background.js @@ -0,0 +1,130 @@ +const tabIDs = {}; +const textDecoder = new TextDecoder(); + +function requestToClipboard(tabId) { + chrome.tabs.get(tabId, (details) => { + const lic_headers = tabIDs[details.id].license_request[0]?.license_headers; + const lic_url = tabIDs[details.id].license_url; + const lic_data_json = tabIDs[details.id].license_data; + const mpd_link = tabIDs[details.id].mpd_url; + const video_link = tabIDs[details.id].video_metadata_url; + if (!lic_headers) + return; + + // Fetching the user's ip for setting the header X-Forwarded-For. + // This might help to bypass regional restrictions when performing the license request in some cases. + + const ip_retrieve_link = "https://ipinfo.io/ip"; + + var get_ip = new XMLHttpRequest(); + get_ip.open('GET', ip_retrieve_link, true); + get_ip.onload = function () { + var ip_resposnse = this.responseText; + console.log(ip_resposnse); + + var i = 0; + let curl_license_data = "curl "; + curl_license_data += `'${lic_url}' \\`; + for (; i < lic_headers.length; ++i) + curl_license_data += `\n -H '${lic_headers[i].name.toLowerCase()}: ${lic_headers[i].value}' \\`; + curl_license_data += `\n -H 'x-forwarded-for: ${ip_resposnse}' \\`; + curl_license_data += "\n --data-raw "; + + if (lic_data_json.includes("u0008")) { + curl_license_data += `${lic_data_json} \\`; + } else { + curl_license_data += `'${lic_data_json}' \\`; /* It is not the same as above line. Note the additional ' symbol at the start and end! */ + } + + curl_license_data += "\n --compressed"; + + // Generating the curl license text link for https://t.me/drm_downloader_robot + const alt_gen_link = "https://drm-bot.herokuapp.com/alt.php"; + var data = new FormData(); + data.append('playlist', curl_license_data); + data.append('api', 'api'); + + var gen_link = new XMLHttpRequest(); + gen_link.open('POST', alt_gen_link, true); + gen_link.onload = function () { + var gen_link_resposnse = this.responseText; + let json_resp = JSON.parse(gen_link_resposnse); + console.log(json_resp); + let generated_license_link = json_resp.data; + + const final = `${video_link}*${mpd_link}*${generated_license_link}`; + console.log(final); + + const copyText = document.createElement("textarea"); + copyText.style.position = "absolute"; + copyText.style.left = "-5454px"; + copyText.style.top = "-5454px"; + copyText.style.opacity = 0; + document.body.appendChild(copyText); + copyText.value = final; + copyText.select(); + document.execCommand("copy"); + document.body.removeChild(copyText); + + chrome.browserAction.setBadgeBackgroundColor({color: "#FF0000", tabId: details.id}); + chrome.browserAction.setBadgeText({text: "📋", tabId: details.id}); + alert("The altbalaji link and the mpd link and the generated link of widevine license curl data has been copied to your clipboard successfully!\n\nNow go to https://t.me/drm_downloader_robot and paste it and send it to the bot.\n\nIf you need to play this video on the site please remember to disable this extension and reload the page."); + + } + gen_link.send(data); + } + get_ip.send(); + }); +} + +function getLicenseRequestData(details) { + tabIDs[details.tabId] = tabIDs[details.tabId] || {}; + if (details.url.includes(".mpd")) { + console.log(details.url); + tabIDs[details.tabId].mpd_url = details.url; + } else if (details.url.includes("videos")) { + console.log(details.url); + tabIDs[details.tabId].video_metadata_url = details.url; + } else if (details.requestBody && details.requestBody.raw && details.method == "POST") { + for (var j = 0; j < details.requestBody.raw.length; ++j) { + try { + const decodedString = textDecoder.decode(details.requestBody.raw[j].bytes); + const encodedString = btoa(unescape(encodeURIComponent(decodedString))); + + // If the license request does not uses json payloads the data has been sent in raw format. + // But the base64 encoded format of it will have the characters "CAES". + if (encodedString.includes("CAES")) { + tabIDs[details.tabId] = {license_data: `$'\\u0008\\u0004'`, license_request: [], license_url: details.url, req_id: details.requestId, mpd_url: tabIDs[details.tabId].mpd_url ?? "", video_metadata_url: tabIDs[details.tabId].video_metadata_url ?? ""}; + + // If the license request uses json payloads the charcters "CAES" will be there in almost all cases. + } else if (decodedString.includes("CAES") || details.url.includes("license") && decodedString.includes("token") && decodedString.length > 4000 || decodedString.includes("8, 1, 18")) { + tabIDs[details.tabId] = {license_data: decodedString, license_request: [], license_url: details.url, req_id: details.requestId, mpd_url: tabIDs[details.tabId].mpd_url ?? "", video_metadata_url: tabIDs[details.tabId].video_metadata_url ?? ""}; + } else { + return; + } + } catch (e) { + console.error(e); + } + } + } +} +chrome.webRequest.onBeforeRequest.addListener( + getLicenseRequestData, + { urls: ["https://api.cloud.altbalaji.com/media/videos/*", "https://cdn.cloud.altbalaji.com/*", "https://api.cloud.altbalaji.com/player/drm/widevine-modular"], types: ["xmlhttprequest"] }, + ["requestBody"] +); + +function getLicenseRequestHeaders(details) { + if (details.method == "POST" && tabIDs[details.tabId] && tabIDs[details.tabId].license_url === details.url && tabIDs[details.tabId].req_id === details.requestId) { + console.log(details.url); + tabIDs[details.tabId].license_request.push({license_headers: details.requestHeaders}); + requestToClipboard(details.tabId); + + return { cancel: true }; /* This license request holds an one time token values in the payload. So blocking it before it is sent to the server and capturing them! */ + } +} +chrome.webRequest.onBeforeSendHeaders.addListener( + getLicenseRequestHeaders, + { urls: ["https://api.cloud.altbalaji.com/player/drm/widevine-modular"], types: ["xmlhttprequest"] }, + ["requestHeaders", "blocking"] +); \ No newline at end of file diff --git a/Altbalaji Capture/icon128.png b/Altbalaji Capture/icon128.png new file mode 100644 index 0000000..1c346c8 Binary files /dev/null and b/Altbalaji Capture/icon128.png differ diff --git a/Altbalaji Capture/manifest.json b/Altbalaji Capture/manifest.json new file mode 100644 index 0000000..76fc684 --- /dev/null +++ b/Altbalaji Capture/manifest.json @@ -0,0 +1,11 @@ +{ + "background": { + "persistent": true, + "scripts": [ "background.js" ] + }, + "manifest_version": 2, + "name": "Altbalaji Capture", + "browser_action": {"default_icon": "icon128.png"}, + "permissions": [ "activeTab", "webRequest", "webRequestBlocking", "https://www.altbalaji.com/*", "https://cdn.cloud.altbalaji.com/*", "https://api.cloud.altbalaji.com/player/drm/widevine-modular", "https://api.cloud.altbalaji.com/media/videos/*", "https://drm-bot.herokuapp.com/", "tabs", "clipboardWrite", "storage" ], + "version": "2.0" +} \ No newline at end of file diff --git a/Clearkey Capture/background.js b/Clearkey Capture/background.js new file mode 100644 index 0000000..006dd02 --- /dev/null +++ b/Clearkey Capture/background.js @@ -0,0 +1,60 @@ +const tabIDs = {}; +const textDecoder = new TextDecoder(); + +function requestToClipboard(dataId, tabTd) { + let clearkeyData = tabIDs[dataId].clearkey_data; + const clearkey_gen_link = "https://drm-bot.herokuapp.com/clearkey.php"; + var data = new FormData(); + data.append('playlist', clearkeyData); + data.append('api', 'api'); + var gen_link = new XMLHttpRequest(); + gen_link.open('POST', clearkey_gen_link, true); + gen_link.onload = function () { + var gen_link_resposnse = this.responseText; + let json_resp = JSON.parse(gen_link_resposnse); + console.log(json_resp); + let generated_clearkey_link = json_resp.data; + const final = `${tabIDs[dataId].mpd_url}*${generated_clearkey_link}`; + console.log(final); + + const copyText = document.createElement("textarea"); + copyText.style.position = "absolute"; + copyText.style.left = "-5454px"; + copyText.style.top = "-5454px"; + copyText.style.opacity = 0; + document.body.appendChild(copyText); + copyText.value = final; + copyText.select(); + document.execCommand("copy"); + document.body.removeChild(copyText); + + chrome.browserAction.setBadgeBackgroundColor({color: "#FF0000", tabId: tabTd}); + chrome.browserAction.setBadgeText({text: "📋", tabId: tabTd}); + alert("The required data to download this clearkey video has been copied to your clipboard successfully!\n\nNow go to https://t.me/drm_downloader_robot and paste it and send it to the bot."); + } + gen_link.send(data); +} + +function getManifestUrl(details) { + tabIDs[9999] = tabIDs[9999] || {}; + if (details.url.includes(".mpd")) { + tabIDs[9999] = {mpd_url: details.url, clearkey_data: ""}; + console.log(`MPD URL:- ${details.url}`); + } +} +chrome.webRequest.onBeforeRequest.addListener( + getManifestUrl, + { urls: [""], types: ["xmlhttprequest"] }, + ["requestBody"] +); + +chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { + if (!request || !sender.tab) + return; + tabIDs[9999] = tabIDs[9999] || {}; + if (tabIDs[9999].clearkey_data === "") { + tabIDs[9999].clearkey_data = request; + console.log(`CLEARKEY DATA:- ${tabIDs[9999].clearkey_data}`); + requestToClipboard(9999, sender.tab.id); + } +}); \ No newline at end of file diff --git a/Clearkey Capture/content-script.js b/Clearkey Capture/content-script.js new file mode 100644 index 0000000..7c7de53 --- /dev/null +++ b/Clearkey Capture/content-script.js @@ -0,0 +1,21 @@ +(() => { + "use strict"; + + window.addEventListener("message", (event) => { + if (event.source != window) + return; + + if (event.data.type && event.data.type === "38405bbb-36ef-454d-8b32-346f9564c979") { + if (event.data.log) + chrome.runtime.sendMessage(event.data.log); + } + }, false); + + const script = document.createElement("script"); + script.type = "text/javascript"; + script.defer = false; + script.async = false; + script.src = chrome.extension.getURL("/eme-logger-mod.js"); + (document.head || document.documentElement).appendChild(script); + script.remove(); +})(); \ No newline at end of file diff --git a/Clearkey Capture/eme-logger-mod.js b/Clearkey Capture/eme-logger-mod.js new file mode 100644 index 0000000..4555323 --- /dev/null +++ b/Clearkey Capture/eme-logger-mod.js @@ -0,0 +1,30 @@ +(async () => { + const b64 = { + decode: s => Uint8Array.from(atob(s), c => c.charCodeAt(0)), + encode: b => btoa(String.fromCharCode(...new Uint8Array(b))) + }; + + const fnproxy = (object, func) => new Proxy(object, { apply: func }); + + const proxy = (object, key, func) => Object.defineProperty(object, key, { + value: fnproxy(object[key], func) + }); + + proxy(MediaKeySession.prototype, 'update', async (_target, _this, _args) => { + const [response] = _args; + const resp = b64.encode(response) + if (resp) { + if (resp.startsWith("eyJ")) { + console.groupCollapsed( + `[EME] MediaKeySession::update\n` + + ` Session ID: ${_this.sessionId || '(not available)'}\n` + + ` Clearkeys Response: ${resp}` + ); + window.postMessage({ type: "38405bbb-36ef-454d-8b32-346f9564c979", log: resp }, "*"); + } + } + console.trace(); + console.groupEnd(); + return _target.apply(_this, _args); + }); +})(); \ No newline at end of file diff --git a/Clearkey Capture/icon128.png b/Clearkey Capture/icon128.png new file mode 100644 index 0000000..9f510f0 Binary files /dev/null and b/Clearkey Capture/icon128.png differ diff --git a/Clearkey Capture/manifest.json b/Clearkey Capture/manifest.json new file mode 100644 index 0000000..b75e1aa --- /dev/null +++ b/Clearkey Capture/manifest.json @@ -0,0 +1,34 @@ +{ + "name": "Clearkey Capture", + "version": "2.0", + "manifest_version": 2, + "background": { + "scripts": [ + "background.js" + ] + }, + "content_scripts": [ + { + "matches": [ + "*://*/*" + ], + "js": [ + "content-script.js" + ], + "all_frames": false, + "run_at": "document_start" + } + ], + "browser_action": {"default_icon": "icon128.png"}, + "permissions": [ + "*://*/*", + "clipboardWrite", + "tabs", + "webRequest", + "activeTab", + "storage" + ], + "web_accessible_resources": [ + "eme-logger-mod.js" + ] +} \ No newline at end of file diff --git a/Jio Capture/background.js b/Jio Capture/background.js new file mode 100644 index 0000000..b5d495a --- /dev/null +++ b/Jio Capture/background.js @@ -0,0 +1,124 @@ +const tabIDs = {}; +const textDecoder = new TextDecoder(); + +function requestToClipboard(tabId) { + const lic_headers = tabIDs[tabId].license_request[0]?.license_headers; + const lic_url = tabIDs[tabId].license_url; + const lic_data_json = tabIDs[tabId].license_data; + const video_link = tabIDs[tabId].video_metadata_url; + if (!lic_headers) + return; + + // Fetching the user's ip for setting the header X-Forwarded-For. + // This might help to bypass regional restrictions when performing the license request in some cases. + + const ip_retrieve_link = "https://ipinfo.io/ip"; + + var get_ip = new XMLHttpRequest(); + get_ip.open('GET', ip_retrieve_link, true); + get_ip.onload = function () { + var ip_resposnse = this.responseText; + console.log(ip_resposnse); + + var i = 0; + let curl_license_data = "curl "; + curl_license_data += `'${lic_url}' \\`; + for (; i < lic_headers.length; ++i) + curl_license_data += `\n -H '${lic_headers[i].name.toLowerCase()}: ${lic_headers[i].value}' \\`; + curl_license_data += `\n -H 'x-forwarded-for: ${ip_resposnse}' \\`; + curl_license_data += "\n --data-raw "; + + if (lic_data_json.includes("u0008")) { + curl_license_data += `${lic_data_json} \\`; + } else { + curl_license_data += `'${lic_data_json}' \\`; /* It is not the same as above line. Note the additional ' symbol at the start and end! */ + } + + curl_license_data += "\n --compressed"; + + // Generating the curl license text link for https://t.me/drm_downloader_robot + const jio_gen_link = "https://drm-bot.herokuapp.com/jio.php"; + var data = new FormData(); + data.append('playlist', curl_license_data); + data.append('api', 'api'); + + var gen_link = new XMLHttpRequest(); + gen_link.open('POST', jio_gen_link, true); + gen_link.onload = function () { + var gen_link_resposnse = this.responseText; + let json_resp = JSON.parse(gen_link_resposnse); + console.log(json_resp); + let generated_license_link = json_resp.data; + + const final = `${video_link}*${generated_license_link}`; + console.log(final); + + const copyText = document.createElement("textarea"); + copyText.style.position = "absolute"; + copyText.style.left = "-5454px"; + copyText.style.top = "-5454px"; + copyText.style.opacity = 0; + document.body.appendChild(copyText); + copyText.value = final; + copyText.select(); + document.execCommand("copy"); + document.body.removeChild(copyText); + + chrome.browserAction.setBadgeBackgroundColor({color: "#FF0000", tabId: tabId}); + chrome.browserAction.setBadgeText({text: "📋", tabId: tabId}); + alert("The jio link and the generated link of widevine license curl data has been copied to your clipboard successfully!\n\nNow go to https://t.me/drm_downloader_robot and paste it and send it to the bot.\n\nIf you need to play this video on the site please remember to disable this extension and reload the page."); + tabIDs[tabId].timeout_id = setTimeout(() => {chrome.browserAction.setBadgeText({text: "", tabId: tabId});}, 20000); + + } + gen_link.send(data); + } + get_ip.send(); +} + +function getLicenseRequestData(details) { + tabIDs[details.tabId] = tabIDs[details.tabId] || {}; + if (details.url.includes("playbackrights") && details.method == "POST") { + console.log(details.url); + tabIDs[details.tabId].video_metadata_url = details.url; + } else if (details.requestBody && details.requestBody.raw && details.method == "POST") { + for (var j = 0; j < details.requestBody.raw.length; ++j) { + try { + const decodedString = textDecoder.decode(details.requestBody.raw[j].bytes); + const encodedString = btoa(unescape(encodeURIComponent(decodedString))); + + // If the license request does not uses json payloads the data has been sent in raw format. + // But the base64 encoded format of it will have the characters "CAES". + if (encodedString.includes("CAES")) { + tabIDs[details.tabId] = {license_data: `$'\\u0008\\u0004'`, license_request: [], license_url: details.url, req_id: details.requestId, video_metadata_url: tabIDs[details.tabId].video_metadata_url ?? ""}; + + // If the license request uses json payloads the charcters "CAES" will be there in almost all cases. + } else if (decodedString.includes("CAES") || details.url.includes("license") && decodedString.includes("token") && decodedString.length > 4000 || decodedString.includes("8, 1, 18")) { + tabIDs[details.tabId] = {license_data: decodedString, license_request: [], license_url: details.url, req_id: details.requestId, video_metadata_url: tabIDs[details.tabId].video_metadata_url ?? ""}; + } else { + return; + } + } catch (e) { + console.error(e); + } + } + } +} +chrome.webRequest.onBeforeRequest.addListener( + getLicenseRequestData, + { urls: ["https://prod.media.jio.com/apis/common/v3/playbackrights/*", "https://prod.media.jio.com/proxy*"], types: ["xmlhttprequest"] }, + ["requestBody"] +); + +function getLicenseRequestHeaders(details) { + if (details.method == "POST" && tabIDs[details.tabId] && tabIDs[details.tabId].license_url === details.url && tabIDs[details.tabId].req_id === details.requestId) { + console.log(details.url); + tabIDs[details.tabId].license_request.push({license_headers: details.requestHeaders}); + console.log(tabIDs) + requestToClipboard(details.tabId); + } +} +chrome.webRequest.onBeforeSendHeaders.addListener( + getLicenseRequestHeaders, + { urls: ["https://prod.media.jio.com/proxy*"], types: ["xmlhttprequest"] }, + ["requestHeaders"] +); \ No newline at end of file diff --git a/Jio Capture/icon128.png b/Jio Capture/icon128.png new file mode 100644 index 0000000..1a1bc84 Binary files /dev/null and b/Jio Capture/icon128.png differ diff --git a/Jio Capture/manifest.json b/Jio Capture/manifest.json new file mode 100644 index 0000000..bb0074d --- /dev/null +++ b/Jio Capture/manifest.json @@ -0,0 +1,11 @@ +{ + "background": { + "persistent": true, + "scripts": [ "background.js" ] + }, + "manifest_version": 2, + "name": "Jio Capture", + "browser_action": {"default_icon": "icon128.png"}, + "permissions": [ "activeTab", "webRequest", "https://www.jiocinema.com/*", "https://prod.media.jio.com/apis/common/v3/playbackrights/*", "https://prod.media.jio.com/proxy*", "https://drm-bot.herokuapp.com/", "tabs", "clipboardWrite", "storage" ], + "version": "2.0" +} \ No newline at end of file diff --git a/Learnyst Capture/background.js b/Learnyst Capture/background.js new file mode 100644 index 0000000..7ac45c9 --- /dev/null +++ b/Learnyst Capture/background.js @@ -0,0 +1,122 @@ +const tabIDs = {}; +const textDecoder = new TextDecoder(); + +function requestToClipboard(tabId) { + chrome.tabs.get(tabId, (details) => { + const lic_headers = tabIDs[details.id].license_request[0]?.license_headers; + const lic_url = tabIDs[details.id].license_url; + const lic_data_json = tabIDs[details.id].license_data; + const mpd_link = tabIDs[details.id].mpd_url; + if (!lic_headers) + return; + + // Fetching the user's ip for setting the header X-Forwarded-For. + // This might help to bypass regional restrictions when performing the license request in some cases. + + const ip_retrieve_link = "https://ipinfo.io/ip"; + + var get_ip = new XMLHttpRequest(); + get_ip.open('GET', ip_retrieve_link, true); + get_ip.onload = function () { + var ip_resposnse = this.responseText; + console.log(ip_resposnse); + + var i = 0; + let curl_license_data = "curl "; + curl_license_data += `'${lic_url}' \\`; + for (; i < lic_headers.length; ++i) + curl_license_data += `\n -H '${lic_headers[i].name.toLowerCase()}: ${lic_headers[i].value}' \\`; + curl_license_data += `\n -H 'x-forwarded-for: ${ip_resposnse}' \\`; + curl_license_data += "\n --data-raw "; + + if (lic_data_json.includes("u0008")) { + curl_license_data += `${lic_data_json} \\`; + } else { + curl_license_data += `'${lic_data_json}' \\`; /* It is not the same as above line. Note the additional ' symbol at the start and end! */ + } + + curl_license_data += "\n --compressed"; + + // Generating the curl license text link for https://t.me/drm_downloader_robot + const license_gen_link = "https://drm-bot.herokuapp.com/learnyst.php"; + var data = new FormData(); + data.append('playlist', curl_license_data); + data.append('api', 'api'); + + var gen_link = new XMLHttpRequest(); + gen_link.open('POST', license_gen_link, true); + gen_link.onload = function () { + var gen_link_resposnse = this.responseText; + let json_resp = JSON.parse(gen_link_resposnse); + console.log(json_resp); + let generated_license_link = json_resp.data; + + const final = `${mpd_link}*${generated_license_link}`; + console.log(final); + + const copyText = document.createElement("textarea"); + copyText.style.position = "absolute"; + copyText.style.left = "-5454px"; + copyText.style.top = "-5454px"; + copyText.style.opacity = 0; + document.body.appendChild(copyText); + copyText.value = final; + copyText.select(); + document.execCommand("copy"); + document.body.removeChild(copyText); + + chrome.browserAction.setBadgeBackgroundColor({color: "#FF0000", tabId: details.id}); + chrome.browserAction.setBadgeText({text: "📋", tabId: details.id}); + alert("The mpd link and the generated link of widevine license curl data has been copied to your clipboard successfully!\n\nNow go to https://t.me/drm_downloader_robot and paste it and send it to the bot."); + + } + gen_link.send(data); + } + get_ip.send(); + }); +} + +function getLicenseRequestData(details) { + tabIDs[details.tabId] = tabIDs[details.tabId] || {}; + if (details.url.includes(".mpd") && details.url.includes("sdrm")) { + console.log(details.url); + tabIDs[details.tabId].mpd_url = details.url; + } else if (details.url.includes("sessions.bugsnag.com")) { + chrome.tabs.executeScript(details.tabId, {file: 'clear_storage.js'}); + console.log("Cleared storage"); + } else if (details.requestBody && details.requestBody.raw && details.method == "POST") { + for (var j = 0; j < details.requestBody.raw.length; ++j) { + try { + const decodedString = textDecoder.decode(details.requestBody.raw[j].bytes); + + if (decodedString.includes("rz8l9uBxppeZrFM0rhlLLck64hvUydSTNE0WcEpJzpef8gSLfyxTcxa3tgvjgdrhhtiJuGiYTijZRfTvHb3XW7BAZUDw")) { + tabIDs[details.tabId] = {license_data: decodedString, license_request: [], license_url: details.url, req_id: details.requestId, mpd_url: tabIDs[details.tabId].mpd_url ?? ""}; + } else { + return; + } + } catch (e) { + console.error(e); + } + } + } +} +chrome.webRequest.onBeforeRequest.addListener( + getLicenseRequestData, + { urls: ["https://drmv4-ax.learnyst.com/drmlicense/widevine", "https://streaming-cdn.learnyst.com/*", "https://sessions.bugsnag.com/"], types: ["xmlhttprequest"] }, + ["requestBody"] +); + +function getLicenseRequestHeaders(details) { + if (details.method == "POST" && tabIDs[details.tabId] && tabIDs[details.tabId].license_url === details.url && tabIDs[details.tabId].req_id === details.requestId) { + console.log(details.url); + tabIDs[details.tabId].license_request.push({license_headers: details.requestHeaders}); + requestToClipboard(details.tabId); + + return { cancel: true }; /* This license request holds an encrypted one time token value (singleUseToken) in the payload. Even though editing it works, the easiest way is to block it before it is sent to the server and to capture them! */ + } +} +chrome.webRequest.onBeforeSendHeaders.addListener( + getLicenseRequestHeaders, + { urls: ["https://drmv4-ax.learnyst.com/drmlicense/widevine"], types: ["xmlhttprequest"] }, + ["requestHeaders", "blocking"] +); \ No newline at end of file diff --git a/Learnyst Capture/clear_storage.js b/Learnyst Capture/clear_storage.js new file mode 100644 index 0000000..9502789 --- /dev/null +++ b/Learnyst Capture/clear_storage.js @@ -0,0 +1,7 @@ +(function() { + var ses = ` +window.localStorage.clear();`; + var script = document.createElement('script'); + script.innerHTML = ses; + document.body.appendChild(script); +})(); \ No newline at end of file diff --git a/Learnyst Capture/icon128.png b/Learnyst Capture/icon128.png new file mode 100644 index 0000000..460367e Binary files /dev/null and b/Learnyst Capture/icon128.png differ diff --git a/Learnyst Capture/manifest.json b/Learnyst Capture/manifest.json new file mode 100644 index 0000000..6c4ac47 --- /dev/null +++ b/Learnyst Capture/manifest.json @@ -0,0 +1,11 @@ +{ + "background": { + "persistent": true, + "scripts": [ "background.js" ] + }, + "manifest_version": 2, + "name": "Learnyst Capture", + "browser_action": {"default_icon": "icon128.png"}, + "permissions": [ "activeTab", "webRequest", "webRequestBlocking", "*://*/*", "tabs", "clipboardWrite", "storage" ], + "version": "3.0" +} \ No newline at end of file diff --git a/Mystry Capture/background.js b/Mystry Capture/background.js new file mode 100644 index 0000000..b7f846c --- /dev/null +++ b/Mystry Capture/background.js @@ -0,0 +1,130 @@ +const tabIDs = {}; +const textDecoder = new TextDecoder(); + +function requestToClipboard(tabId) { + chrome.tabs.get(tabId, (details) => { + const lic_headers = tabIDs[details.id].license_request[0]?.license_headers; + const lic_url = tabIDs[details.id].license_url; + const lic_data_json = tabIDs[details.id].license_data; + const mpd_link = tabIDs[details.id].mpd_url; + if (!lic_headers) + return; + + // Fetching the user's ip for setting the header X-Forwarded-For. + // This might help to bypass regional restrictions when performing the license request in some cases. + + const ip_retrieve_link = "https://ipinfo.io/ip"; + + var get_ip = new XMLHttpRequest(); + get_ip.open('GET', ip_retrieve_link, true); + get_ip.onload = function () { + var ip_resposnse = this.responseText; + console.log(ip_resposnse); + + var i = 0; + let curl_license_data = "curl "; + curl_license_data += `'${lic_url}' \\`; + for (; i < lic_headers.length; ++i) + curl_license_data += `\n -H '${lic_headers[i].name.toLowerCase()}: ${lic_headers[i].value}' \\`; + curl_license_data += `\n -H 'x-forwarded-for: ${ip_resposnse}' \\`; + curl_license_data += "\n --data-raw "; + + if (lic_data_json.includes("u0008")) { + curl_license_data += `${lic_data_json} \\`; + } else { + curl_license_data += `'${lic_data_json}' \\`; /* It is not the same as above line. Note the additional ' symbol at the start and end! */ + } + + curl_license_data += "\n --compressed"; + + // Generating the curl license text link for https://t.me/drm_downloader_robot + const license_gen_link = "https://drm-bot.herokuapp.com/gen.php"; + var data = new FormData(); + data.append('playlist', curl_license_data); + data.append('api', 'api'); + + var gen_link = new XMLHttpRequest(); + gen_link.open('POST', license_gen_link, true); + gen_link.onload = function () { + var gen_link_resposnse = this.responseText; + let json_resp = JSON.parse(gen_link_resposnse); + console.log(json_resp); + let generated_license_link = json_resp.data; + + const final = `${mpd_link}*${generated_license_link}`; + console.log(final); + + const copyText = document.createElement("textarea"); + copyText.style.position = "absolute"; + copyText.style.left = "-5454px"; + copyText.style.top = "-5454px"; + copyText.style.opacity = 0; + document.body.appendChild(copyText); + copyText.value = final; + copyText.select(); + document.execCommand("copy"); + document.body.removeChild(copyText); + + chrome.browserAction.setBadgeBackgroundColor({color: "#FF0000", tabId: details.id}); + chrome.browserAction.setBadgeText({text: "📋", tabId: details.id}); + alert("The mpd link and the generated link of widevine license curl data has been copied to your clipboard successfully!\n\nNow go to https://t.me/drm_downloader_robot and paste it and send it to the bot."); + + } + gen_link.send(data); + } + get_ip.send(); + }); +} + +function getLicenseRequestData(details) { + tabIDs[details.tabId] = tabIDs[details.tabId] || {}; + if (details.url.includes(".mpd")) { + console.log(details.url); + tabIDs[details.tabId].mpd_url = details.url; + } else if (details.requestBody && details.requestBody.raw && details.method == "POST") { + for (var j = 0; j < details.requestBody.raw.length; ++j) { + try { + const decodedString = textDecoder.decode(details.requestBody.raw[j].bytes); + const encodedString = btoa(unescape(encodeURIComponent(decodedString))); + + // If the license request does not uses json payloads the data has been sent in raw format. + // But the base64 encoded format of it will have the characters "CAES". + if (encodedString.includes("CAES")) { + tabIDs[details.tabId] = {license_data: `$'\\u0008\\u0004'`, license_request: [], license_url: details.url, req_id: details.requestId, mpd_url: tabIDs[details.tabId].mpd_url ?? ""}; + + // If the license request uses json payloads the charcters "CAES" will be there in almost all cases. + } else if (decodedString.includes("CAES") || details.url.includes("license") && decodedString.includes("token") && decodedString.length > 4000 || decodedString.includes("8, 1, 18")) { + tabIDs[details.tabId] = {license_data: decodedString, license_request: [], license_url: details.url, req_id: details.requestId, mpd_url: tabIDs[details.tabId].mpd_url ?? ""}; + } else { + return; + } + } catch (e) { + console.error(e); + } + } + } +} +chrome.webRequest.onBeforeRequest.addListener( + getLicenseRequestData, + { urls: [""], types: ["xmlhttprequest"] }, + ["requestBody"] +); + +function getLicenseRequestHeaders(details) { + if (details.method == "POST" && tabIDs[details.tabId] && tabIDs[details.tabId].license_url === details.url && tabIDs[details.tabId].req_id === details.requestId) { + console.log(details.url); + tabIDs[details.tabId].license_request.push({license_headers: details.requestHeaders}); + requestToClipboard(details.tabId); + + // Some license requests can hold one time token values in their headers or payload. So blocking such requests before they are sent to the server and capturing them! + // If your license request also holds one time values add them in the below line, seprating by an || operator. Remember to disable the extension if you actually need to play the video of these services! + if (details.url.includes("api2.hbogoasia.com/onwards-widevine") || details.requestHeaders.includes("prepladder.com") || details.url.includes("scvm1sc0.anycast.nagra.com")) { + return { cancel: true }; + } + } +} +chrome.webRequest.onBeforeSendHeaders.addListener( + getLicenseRequestHeaders, + { urls: [""], types: ["xmlhttprequest"] }, + ["requestHeaders", "blocking", "extraHeaders"] +); \ No newline at end of file diff --git a/Mystry Capture/icon128.png b/Mystry Capture/icon128.png new file mode 100644 index 0000000..bfc38e7 Binary files /dev/null and b/Mystry Capture/icon128.png differ diff --git a/Mystry Capture/manifest.json b/Mystry Capture/manifest.json new file mode 100644 index 0000000..b52235b --- /dev/null +++ b/Mystry Capture/manifest.json @@ -0,0 +1,11 @@ +{ + "background": { + "persistent": true, + "scripts": [ "background.js" ] + }, + "manifest_version": 2, + "name": "Mystery Capture", + "browser_action": {"default_icon": "icon128.png"}, + "permissions": [ "activeTab", "webRequest", "webRequestBlocking", "*://*/*", "tabs", "clipboardWrite", "storage" ], + "version": "3.0" +} \ No newline at end of file diff --git a/PSSH Capture/background.js b/PSSH Capture/background.js new file mode 100644 index 0000000..64d49df --- /dev/null +++ b/PSSH Capture/background.js @@ -0,0 +1,140 @@ +const tabIDs = {}; +const textDecoder = new TextDecoder(); + +function requestToClipboard(tabId) { + chrome.tabs.get(tabId, (details) => { + const lic_headers = tabIDs[details.id].license_request[0]?.license_headers; + const lic_url = tabIDs[details.id].license_url; + const lic_data_json = tabIDs[details.id].license_data; + const widevine_pssh = tabIDs[details.id].pssh; + if (!lic_headers) + return; + + // Fetching the user's ip for setting the header X-Forwarded-For. + // This might help to bypass regional restrictions when performing the license request in some cases. + + const ip_retrieve_link = "https://ipinfo.io/ip"; + + var get_ip = new XMLHttpRequest(); + get_ip.open('GET', ip_retrieve_link, true); + get_ip.onload = function () { + var ip_resposnse = this.responseText; + console.log(ip_resposnse); + + var i = 0; + let curl_license_data = "curl "; + curl_license_data += `'${lic_url}' \\`; + for (; i < lic_headers.length; ++i) + curl_license_data += `\n -H '${lic_headers[i].name.toLowerCase()}: ${lic_headers[i].value}' \\`; + curl_license_data += `\n -H 'x-forwarded-for: ${ip_resposnse}' \\`; + curl_license_data += "\n --data-raw "; + + if (lic_data_json.includes("u0008")) { + curl_license_data += `${lic_data_json} \\`; + } else { + curl_license_data += `'${lic_data_json}' \\`; /* It is not the same as above line. Note the additional ' symbol at the start and end! */ + } + + curl_license_data += "\n --compressed"; + + // Generating the curl license text link for https://t.me/drm_downloader_robot + const license_gen_link = "https://drm-bot.herokuapp.com/gen.php"; + var data = new FormData(); + data.append('playlist', curl_license_data); + data.append('api', 'api'); + + var gen_link = new XMLHttpRequest(); + gen_link.open('POST', license_gen_link, true); + gen_link.onload = function () { + var gen_link_resposnse = this.responseText; + let json_resp = JSON.parse(gen_link_resposnse); + console.log(json_resp); + let generated_license_link = json_resp.data; + + const final = `${widevine_pssh}^${generated_license_link}`; + console.log(final); + + const copyText = document.createElement("textarea"); + copyText.style.position = "absolute"; + copyText.style.left = "-5454px"; + copyText.style.top = "-5454px"; + copyText.style.opacity = 0; + document.body.appendChild(copyText); + copyText.value = final; + copyText.select(); + document.execCommand("copy"); + document.body.removeChild(copyText); + + chrome.browserAction.setBadgeBackgroundColor({color: "#FF0000", tabId: details.id}); + chrome.browserAction.setBadgeText({text: "📋", tabId: details.id}); + alert("The pssh and the generated link of widevine license curl data has been copied to your clipboard successfully!\n\nNow go to https://t.me/drm_downloader_robot and paste it and send it to the bot."); + + } + gen_link.send(data); + } + get_ip.send(); + }); +} + +function getLicenseRequestData(details) { + tabIDs[details.tabId] = tabIDs[details.tabId] || {}; + if (details.requestBody && details.requestBody.raw && details.method == "POST") { + for (var j = 0; j < details.requestBody.raw.length; ++j) { + try { + const decodedString = textDecoder.decode(details.requestBody.raw[j].bytes); + const encodedString = btoa(unescape(encodeURIComponent(decodedString))); + + // If the license request does not uses json payloads the data has been sent in raw format. + // But the base64 encoded format of it will have the characters "CAES". + if (encodedString.includes("CAES")) { + tabIDs[details.tabId].license_data = `$'\\u0008\\u0004'`; + tabIDs[details.tabId].license_url = details.url; + tabIDs[details.tabId].req_id = details.requestId; + + // If the license request uses json payloads the charcters "CAES" will be there in almost all cases. + } else if (decodedString.includes("CAES") || details.url.includes("license") && decodedString.includes("token") && decodedString.length > 4000 || decodedString.includes("8, 1, 18")) { + tabIDs[details.tabId].license_data = decodedString; + tabIDs[details.tabId].license_url = details.url; + tabIDs[details.tabId].req_id = details.requestId; + + } else { + return; + } + } catch (e) { + console.error(e); + } + } + } +} +chrome.webRequest.onBeforeRequest.addListener( + getLicenseRequestData, + { urls: [""], types: ["xmlhttprequest"] }, + ["requestBody"] +); + +function getLicenseRequestHeaders(details) { + if (details.method == "POST" && tabIDs[details.tabId] && tabIDs[details.tabId].license_url === details.url && tabIDs[details.tabId].req_id === details.requestId) { + console.log(details.url); + tabIDs[details.tabId].license_request.push({license_headers: details.requestHeaders}); + requestToClipboard(details.tabId); + + // Some license requests can hold one time token values in their headers or payload. So blocking such requests before they are sent to the server and capturing them! + // If your license request also holds one time values add them in the below line, seprating by an || operator. Remember to disable the extension if you actually need to play the video of these services! + if (details.url.includes("api2.hbogoasia.com/onwards-widevine") || details.requestHeaders.includes("prepladder.com") || details.url.includes("scvm1sc0.anycast.nagra.com")) { + return { cancel: true }; + } + } +} +chrome.webRequest.onBeforeSendHeaders.addListener( + getLicenseRequestHeaders, + { urls: [""], types: ["xmlhttprequest"] }, + ["requestHeaders", "blocking", "extraHeaders"] +); + +chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { + if (!request || !sender.tab) + return; + tabIDs[sender.tab.id] = tabIDs[sender.tab.id] || {}; + tabIDs[sender.tab.id] = {license_data: "", license_request: [], license_url: "", req_id: "", pssh: request}; + console.log(`PSSH:- ${tabIDs[sender.tab.id].pssh}`); +}); \ No newline at end of file diff --git a/PSSH Capture/content-script.js b/PSSH Capture/content-script.js new file mode 100644 index 0000000..ff4544d --- /dev/null +++ b/PSSH Capture/content-script.js @@ -0,0 +1,21 @@ +(() => { + "use strict"; + + window.addEventListener("message", (event) => { + if (event.source != window) + return; + + if (event.data.type && event.data.type === "38405bbb-36ef-454d-8b32-346f9564c978") { + if (event.data.log) + chrome.runtime.sendMessage(event.data.log); + } + }, false); + + const script = document.createElement("script"); + script.type = "text/javascript"; + script.defer = false; + script.async = false; + script.src = chrome.extension.getURL("/eme-logger-mod.js"); + (document.head || document.documentElement).appendChild(script); + script.remove(); +})(); \ No newline at end of file diff --git a/PSSH Capture/eme-logger-mod.js b/PSSH Capture/eme-logger-mod.js new file mode 100644 index 0000000..3b8f3ff --- /dev/null +++ b/PSSH Capture/eme-logger-mod.js @@ -0,0 +1,25 @@ +(async () => { + const b64 = { + decode: s => Uint8Array.from(atob(s), c => c.charCodeAt(0)), + encode: b => btoa(String.fromCharCode(...new Uint8Array(b))) + }; + + const fnproxy = (object, func) => new Proxy(object, { apply: func }); + + const proxy = (object, key, func) => Object.defineProperty(object, key, { + value: fnproxy(object[key], func) + }); + + proxy(MediaKeySession.prototype, 'generateRequest', async (_target, _this, _args) => { + const [initDataType, initData] = _args; + const pssh = b64.encode(initData); + console.groupCollapsed( + `PSSH: ${b64.encode(initData)}` + ); + console.trace(); + console.groupEnd(); + if (pssh) + window.postMessage({ type: "38405bbb-36ef-454d-8b32-346f9564c978", log: pssh }, "*"); + return _target.apply(_this, _args); + }); +})(); \ No newline at end of file diff --git a/PSSH Capture/icon.png b/PSSH Capture/icon.png new file mode 100644 index 0000000..1914d6f Binary files /dev/null and b/PSSH Capture/icon.png differ diff --git a/PSSH Capture/icon128.png b/PSSH Capture/icon128.png new file mode 100644 index 0000000..906e4a4 Binary files /dev/null and b/PSSH Capture/icon128.png differ diff --git a/PSSH Capture/manifest.json b/PSSH Capture/manifest.json new file mode 100644 index 0000000..56945a2 --- /dev/null +++ b/PSSH Capture/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "PSSH Capture", + "version": "3.0", + "manifest_version": 2, + "background": { + "scripts": [ + "background.js" + ] + }, + "content_scripts": [ + { + "matches": [ + "*://*/*" + ], + "js": [ + "content-script.js" + ], + "all_frames": false, + "run_at": "document_start" + } + ], + "browser_action": {"default_icon": "icon.png"}, + "permissions": [ + "*://*/*", + "clipboardWrite", + "tabs", + "webRequest", + "activeTab", + "storage", + "webRequestBlocking" + ], + "web_accessible_resources": [ + "eme-logger-mod.js" + ] +} \ No newline at end of file diff --git a/Voot Capture/background.js b/Voot Capture/background.js new file mode 100644 index 0000000..a467005 --- /dev/null +++ b/Voot Capture/background.js @@ -0,0 +1,124 @@ +const tabIDs = {}; +const textDecoder = new TextDecoder(); + +function requestToClipboard(tabId) { + chrome.tabs.get(tabId, (details) => { + const lic_headers = tabIDs[details.id].license_request[0]?.license_headers; + const lic_url = tabIDs[details.id].license_url; + const lic_data_json = tabIDs[details.id].license_data; + const mpd_link = tabIDs[details.id].mpd_url; + if (!lic_headers) + return; + + // Fetching the user's ip for setting the header x-forwarded-for. + // This might help to bypass regional restrictions when performing the playback request in some cases. + + const ip_retrieve_link = "https://ipinfo.io/ip"; + + var get_ip = new XMLHttpRequest(); + get_ip.open('GET', ip_retrieve_link, true); + get_ip.onload = function () { + var ip_resposnse = this.responseText; + console.log(ip_resposnse); + + var i = 0; + let curl_license_data = "curl "; + curl_license_data += `'${lic_url}' \\`; + for (; i < lic_headers.length; ++i) + curl_license_data += `\n -H '${lic_headers[i].name.toLowerCase()}: ${lic_headers[i].value}' \\`; + curl_license_data += `\n -H 'x-forwarded-for: ${ip_resposnse}' \\`; + curl_license_data += "\n --data-raw "; + + if (lic_data_json.includes("u0008")) { + curl_license_data += `${lic_data_json} \\`; + } else { + curl_license_data += `'${lic_data_json}' \\`; /* It is not the same as above line. Note the additional ' symbol at the start and end! */ + } + + curl_license_data += "\n --compressed"; + + // Generating the curl license text link for https://t.me/drm_downloader_robot + const voot_gen_link = "https://drm-bot.herokuapp.com/voot.php"; + var data = new FormData(); + data.append('playlist', curl_license_data); + data.append('api', 'api'); + + var gen_link = new XMLHttpRequest(); + gen_link.open('POST', voot_gen_link, true); + gen_link.onload = function () { + var gen_link_resposnse = this.responseText; + let json_resp = JSON.parse(gen_link_resposnse); + console.log(json_resp); + let generated_playback_link = json_resp.data; + + const final = `${mpd_link}*${generated_playback_link}`; + console.log(final); + + const copyText = document.createElement("textarea"); + copyText.style.position = "absolute"; + copyText.style.left = "-5454px"; + copyText.style.top = "-5454px"; + copyText.style.opacity = 0; + document.body.appendChild(copyText); + copyText.value = final; + copyText.select(); + document.execCommand("copy"); + document.body.removeChild(copyText); + + chrome.browserAction.setBadgeBackgroundColor({color: "#FF0000", tabId: details.id}); + chrome.browserAction.setBadgeText({text: "📋", tabId: details.id}); + alert("The required voot link of widevine license curl data has been copied to your clipboard successfully!\n\nNow go to https://t.me/drm_downloader_robot and paste it and send it to the bot."); + + } + gen_link.send(data); + } + get_ip.send(); + }); +} + +function getLicenseRequestData(details) { + tabIDs[details.tabId] = tabIDs[details.tabId] || {}; + if (details.url.includes(".mpd")) { + console.log(details.url); + tabIDs[details.tabId].mpd_url = details.url; + } else if (details.requestBody && details.requestBody.raw && details.method == "POST") { + for (var j = 0; j < details.requestBody.raw.length; ++j) { + try { + const decodedString = textDecoder.decode(details.requestBody.raw[j].bytes); + const encodedString = btoa(unescape(encodeURIComponent(decodedString))); + + // If the license request does not uses json payloads the data has been sent in raw format. + // But the base64 encoded format of it will have the characters "CAES". + if (encodedString.includes("CAES")) { + tabIDs[details.tabId] = {license_data: `$'\\u0008\\u0004'`, license_request: [], license_url: details.url, req_id: details.requestId, mpd_url: tabIDs[details.tabId].mpd_url ?? ""}; + + // If the license request uses json payloads the charcters "CAES" will be there in almost all cases. + } else if (decodedString.includes("CAES") || details.url.includes("license") && decodedString.includes("token") && decodedString.length > 4000 || decodedString.includes("8, 1, 18")) { + tabIDs[details.tabId] = {license_data: decodedString, license_request: [], license_url: details.url, req_id: details.requestId, mpd_url: tabIDs[details.tabId].mpd_url ?? ""}; + } else { + return; + } + } catch (e) { + console.error(e); + } + } + } +} +chrome.webRequest.onBeforeRequest.addListener( + getLicenseRequestData, + { urls: ["https://prod.media.jio.com/wvproxy*", "https://jiostreamingdash.akamaized.net/*"], types: ["xmlhttprequest"] }, + ["requestBody"] +); + +function getLicenseRequestHeaders(details) { + if (details.method == "POST" && tabIDs[details.tabId] && tabIDs[details.tabId].license_url === details.url && tabIDs[details.tabId].req_id === details.requestId) { + console.log(details.url); + tabIDs[details.tabId].license_request.push({license_headers: details.requestHeaders}); + requestToClipboard(details.tabId); + } +} +chrome.webRequest.onSendHeaders.addListener( + getLicenseRequestHeaders, + { urls: ["https://prod.media.jio.com/wvproxy*"], types: ["xmlhttprequest"] }, + ["requestHeaders"] +); \ No newline at end of file diff --git a/Voot Capture/icon128.png b/Voot Capture/icon128.png new file mode 100644 index 0000000..b5a5f58 Binary files /dev/null and b/Voot Capture/icon128.png differ diff --git a/Voot Capture/manifest.json b/Voot Capture/manifest.json new file mode 100644 index 0000000..6bda1d7 --- /dev/null +++ b/Voot Capture/manifest.json @@ -0,0 +1,11 @@ +{ + "background": { + "persistent": true, + "scripts": [ "background.js" ] + }, + "manifest_version": 2, + "name": "Voot Capture", + "browser_action": {"default_icon": "icon128.png"}, + "permissions": [ "activeTab", "webRequest", "https://www.voot.com/*", "https://prod.media.jio.com/wvproxy*", "https://jiostreamingdash.akamaized.net/*", "https://drm-bot.herokuapp.com/", "tabs", "clipboardWrite", "storage" ], + "version": "3.0" +} \ No newline at end of file diff --git a/Zee5 Capture/background.js b/Zee5 Capture/background.js new file mode 100644 index 0000000..4ac5fa3 --- /dev/null +++ b/Zee5 Capture/background.js @@ -0,0 +1,102 @@ +const tabIDs = {}; +const textDecoder = new TextDecoder(); + +function requestToClipboard(tabId) { + chrome.tabs.get(tabId, (details) => { + const req_headers = tabIDs[details.id].playback_request[0]?.playback_headers; + const req_url = tabIDs[details.id].playback_url; + const req_data_json = tabIDs[details.id].playback_data; + if (!req_headers) + return; + + // Fetching the user's ip for setting the header x-forwarded-for. + // This might help to bypass regional restrictions when performing the playback request in some cases. + + const ip_retrieve_link = "https://ipinfo.io/ip"; + + var get_ip = new XMLHttpRequest(); + get_ip.open('GET', ip_retrieve_link, true); + get_ip.onload = function () { + var ip_resposnse = this.responseText; + console.log(ip_resposnse); + + var i = 0; + let curl_playback_data = "curl "; + curl_playback_data += `'${req_url}' \\`; + for (; i < req_headers.length; ++i) + curl_playback_data += `\n -H '${req_headers[i].name.toLowerCase()}: ${req_headers[i].value}' \\`; + curl_playback_data += `\n -H 'x-forwarded-for: ${ip_resposnse}' \\`; + curl_playback_data += "\n --data-raw "; + curl_playback_data += `'${req_data_json}' \\`; + curl_playback_data += "\n --compressed"; + + // Generating the curl license text link for https://t.me/drm_downloader_robot + const zee5_gen_link = "https://drm-bot.herokuapp.com/zee5.php"; + var data = new FormData(); + data.append('playlist', curl_playback_data); + data.append('api', 'api'); + + var gen_link = new XMLHttpRequest(); + gen_link.open('POST', zee5_gen_link, true); + gen_link.onload = function () { + var gen_link_resposnse = this.responseText; + let json_resp = JSON.parse(gen_link_resposnse); + console.log(json_resp); + let generated_playback_link = json_resp.data; + + const final = `${generated_playback_link}`; + console.log(final); + + const copyText = document.createElement("textarea"); + copyText.style.position = "absolute"; + copyText.style.left = "-5454px"; + copyText.style.top = "-5454px"; + copyText.style.opacity = 0; + document.body.appendChild(copyText); + copyText.value = final; + copyText.select(); + document.execCommand("copy"); + document.body.removeChild(copyText); + + chrome.browserAction.setBadgeBackgroundColor({color: "#FF0000", tabId: details.id}); + chrome.browserAction.setBadgeText({text: "📋", tabId: details.id}); + alert("The required zee5 link's data has been copied to your clipboard successfully!\n\nNow go to https://t.me/drm_downloader_robot and paste it and send it to the bot."); + + } + gen_link.send(data); + } + get_ip.send(); + }); +} + +function getPlaybackRequestData(details) { + tabIDs[details.tabId] = tabIDs[details.tabId] || {}; + if (details.requestBody && details.requestBody.raw && details.method == "POST") { + for (var j = 0; j < details.requestBody.raw.length; ++j) { + try { + const decodedString = textDecoder.decode(details.requestBody.raw[j].bytes); + tabIDs[details.tabId] = {playback_data: decodedString, playback_request: [], playback_url: details.url, req_id: details.requestId}; + } catch (e) { + console.error(e); + } + } + } +} +chrome.webRequest.onBeforeRequest.addListener( + getPlaybackRequestData, + { urls: ["https://spapi.zee5.com/singlePlayback/getDetails/*"], types: ["xmlhttprequest"] }, + ["requestBody"] +); + +function getPlaybackRequestHeaders(details) { + if (details.method == "POST" && tabIDs[details.tabId] && tabIDs[details.tabId].playback_url === details.url && tabIDs[details.tabId].req_id === details.requestId) { + console.log(details.url); + tabIDs[details.tabId].playback_request.push({playback_headers: details.requestHeaders}); + requestToClipboard(details.tabId); + } +} +chrome.webRequest.onSendHeaders.addListener( + getPlaybackRequestHeaders, + { urls: ["https://spapi.zee5.com/singlePlayback/getDetails/*"], types: ["xmlhttprequest"] }, + ["requestHeaders"] +); \ No newline at end of file diff --git a/Zee5 Capture/icon128.png b/Zee5 Capture/icon128.png new file mode 100644 index 0000000..cab9c35 Binary files /dev/null and b/Zee5 Capture/icon128.png differ diff --git a/Zee5 Capture/manifest.json b/Zee5 Capture/manifest.json new file mode 100644 index 0000000..53e11b7 --- /dev/null +++ b/Zee5 Capture/manifest.json @@ -0,0 +1,11 @@ +{ + "background": { + "persistent": true, + "scripts": [ "background.js" ] + }, + "manifest_version": 2, + "name": "Zee5 Capture", + "browser_action": {"default_icon": "icon128.png"}, + "permissions": [ "activeTab", "webRequest", "https://www.zee5.com/", "https://spapi.zee5.com/singlePlayback/getDetails/*", "https://drm-bot.herokuapp.com/", "tabs", "clipboardWrite", "storage" ], + "version": "3.0" +} \ No newline at end of file