From 7c45cacd36dcdc26e27104abf33bebdcc9b42dd9 Mon Sep 17 00:00:00 2001 From: sdaqo Date: Tue, 8 Aug 2023 13:50:18 +0200 Subject: [PATCH] add ff2mpv setting + new hosters (#14) * add Kwik, use unpacker to improve reliabilty * use packer for filemoon * use packer for upstream * add ff2mpv setting + functionality * Update README.md * get rid of @types/webextension-polyfill * Revert "Update README.md" This reverts commit affb6000968beb798423a5403508215b7f6e4670. * Update README.md * Update info link for ff2mpv * add kwik to hosters in readme * removes console.logs * Delete package-lock.json * add package-lock.json to .gitignore * unpack without using eval * Merge main branch into here * Add Dropload Hoster * Add Supervideo Hoster * Add GoodStream Hoster * Add hosters to readme and delete console.logs * Delete package-lock.json * Fix ff2mpv info url * Update readme --------- Co-authored-by: bytedream --- README.md | 39 ++++++++++++++++++++++++++-- src/background.ts | 6 +++++ src/index.ts | 6 ++++- src/manifest.json | 1 + src/match/matches.ts | 57 +++++++++++++++++++++++++++++++++++++---- src/store/settings.ts | 27 +++++++++++++++++++ src/store/store.ts | 2 ++ src/ui/popup/popup.html | 8 ++++++ src/ui/popup/popup.scss | 12 ++++++++- src/ui/popup/popup.ts | 46 +++++++++++++++++++++++++++++++++ 10 files changed, 195 insertions(+), 9 deletions(-) create mode 100644 src/store/settings.ts diff --git a/README.md b/README.md index 9ce7eaa..53f0812 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,9 @@ A multi-browser addon / extension for multiple streaming providers which redirec • Supported Sites 📜 • - Building ⚙️ + Building 🛠️ + • + Settings ⚙️License ⚖

@@ -84,6 +86,9 @@ Install the addon directly from the [firefox addon store](https://addons.mozilla | [voe.sx](https://voe.sx) | ✔ | | | [vupload.com](https://vupload.com) | ✔ | | | [kwik.cx](https://kwik.cx) | ✔ | | +| [dropload.io](https://dropload.io) | ✔ | | +| [supervideo.tv](https://supervideo.tv) | ✔ | | +| [goodstream.uno](https://goodstream.uno) | ✔ | | - ✔️: Everything ok. - ⚠: Included in the addon but will probably not work. See `Note` in this case, an explanation why will stand there in the most cases. @@ -100,7 +105,7 @@ Some sites put much effort in obfuscating their code / how they receive the vide -## ⚙️ Building +## 🛠️ Building If you want to build the addon from source and not using the [installation](#installation) way, follow the instructions. @@ -129,6 +134,36 @@ When using firefox, use the following: 3. Under `Temporary Extensions`, click `Load Temporary Add-on`. 4. Choose any file in the directory where the compiled sources are. + +## ⚙️ Settings + +### ff2mpv: use mpv to directly play streams +ff2mpv is located at this repository: https://github.com/woodruffw/ff2mpv + +Steps to get it set up: + - In the [Usage](https://github.com/woodruffw/ff2mpv#usage) section of the ff2mpv repository pick the installation instruction for your operating system (Linux/Windows/macOS; you do not need the browser addon). + - Scroll down to `Install manually` + - Follow instructions for Firefox/Chrome + - Edit the `ff2mpv.json` you created: + - Firefox: Add `{55dd42e8-3dd9-455a-b4fe-86664881b10c}` to `allowed_extensions` -> + ``` + "allowed_extensions": [ + "ff2mpv@yossarian.net", + "{55dd42e8-3dd9-455a-b4fe-86664881b10c}" + ] + ``` + - Chrome/Chromium: + - Go To: Settings -> Extensions + - Click on `Details` of the Stream Bypass extension and copy the ID + - Add `chrome-extension://your-id-here/` to `allowed_origins` -> + ``` + "allowed_origins": [ + "chrome-extension://ephjcajbkgplkjmelpglennepbpmdpjg/", + "chrome-extension://your-id-her/" + ] + ``` + + ## ⚖ License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for more details. diff --git a/src/background.ts b/src/background.ts index 78e5145..f93a36e 100644 --- a/src/background.ts +++ b/src/background.ts @@ -2,6 +2,12 @@ import {getMatch} from "./match/match"; import {storageDelete, storageGet, storageSet} from "./store/store"; import {Match} from "./match/matches"; +chrome.runtime.onMessage.addListener((message, sender) => { + if (message.action == "ff2mpv") { + chrome.runtime.sendNativeMessage("ff2mpv", {url: message.url}) + .catch((error) => {console.error(error)}) + } +}) chrome.webRequest.onBeforeRedirect.addListener(async details => { // check if redirects origins from a previous redirect diff --git a/src/index.ts b/src/index.ts index ab2e63f..13f81e4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ import {getMatch} from "./match/match"; -import {storageDelete, storageGet} from "./store/store"; +import {storageDelete, storageGet, getSetting} from "./store/store"; import {Match, matches} from "./match/matches"; async function main() { @@ -21,6 +21,10 @@ async function main() { const url = await match.match(re) + if (await getSetting("ff2mpv")) { + chrome.runtime.sendMessage({action: "ff2mpv", url: url}) + } + if (match.replace && !url.includes('.m3u8')) { const player = document.createElement('video') player.style.width = '100%' diff --git a/src/manifest.json b/src/manifest.json index 0b4b949..8d97e5b 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -30,6 +30,7 @@ "permissions": [ "storage", "webRequest", + "nativeMessaging", "" ], "web_accessible_resources": [ diff --git a/src/match/matches.ts b/src/match/matches.ts index f809627..d7185fa 100644 --- a/src/match/matches.ts +++ b/src/match/matches.ts @@ -55,14 +55,14 @@ class Filemoon implements Match { id = 'filemoon' reliability = Reliability.HIGH domains = [ - 'filemoon.sx' + 'filemoon.sx', + 'filemoon.in' ] regex = new RegExp(/eval\(function\(p,a,c,k,e,d\).*?(?=\<\/script\>)/gms) async match(match: RegExpMatchArray): Promise { let unpacked = await unPack(match[0]) let url = unpacked.match(/(?<=file:").*(?=")/)[0] - console.log(url) return url } } @@ -99,7 +99,6 @@ class Mp4Upload implements Match { async match(match: RegExpMatchArray): Promise { let unpacked = await unPack(match[0]) - console.log(unpacked) let url = unpacked.match(/(?<=player.src\(").*(?=")/)[0] return url } @@ -226,11 +225,56 @@ class Kwik implements Match { console.log(match[0]); let unpacked = await unPack(match[0]) let url = unpacked.match(/(?<=source=').*(?=')/)[0] - console.log(url) return url } } +class DropLoad implements Match { + name = 'Dropload' + id = 'dropload' + reliability = Reliability.HIGH + domains = [ + 'dropload.io' + ] + regex = new RegExp(/eval\(function\(p,a,c,k,e,d\).*?(?=\<\/script\>)/gms) + + async match(match: RegExpMatchArray): Promise { + let unpacked = await unPack(match[0]) + let url = unpacked.match(/(?<=file:").*(?=")/)[0] + return url + } +} + +class SuperVideo implements Match { + name = 'Supervideo' + id = 'supervideo' + reliability = Reliability.HIGH + domains = [ + 'supervideo.tv' + ] + regex = new RegExp(/eval\(function\(p,a,c,k,e,d\).*?(?=\<\/script\>)/gms) + + async match(match: RegExpMatchArray): Promise { + let unpacked = await unPack(match[0]) + let url = unpacked.match(/(?<=file:").*(?=")/)[0] + return url + } +} + +class GoodStream implements Match { + name = 'Goodstream' + id = 'goodstream' + reliability = Reliability.NORMAL + domains = [ + 'goodstream.uno' + ] + regex = new RegExp(/(?<=file:\s+").*(?=")/g) + + async match(match: RegExpMatchArray): Promise { + return match[0] + } +} + export const matches = [ new Doodstream(), new Filemoon(), @@ -243,5 +287,8 @@ export const matches = [ new Vidoza(), new Voe(), new Vupload(), - new Kwik() + new Kwik(), + new DropLoad(), + new SuperVideo(), + new GoodStream() ] diff --git a/src/store/settings.ts b/src/store/settings.ts new file mode 100644 index 0000000..62dea20 --- /dev/null +++ b/src/store/settings.ts @@ -0,0 +1,27 @@ +import { storageSet, storageGet } from "./store" + +export class Setting { + name: string + info_url?: string + + constructor(name: string, info_url?: string) { + this.name = name + this.info_url = info_url + } + + async enable() { + await storageSet(this.name, true) + } + + async disable() { + await storageSet(this.name, false) + } + + async get_status() { + return await storageGet(this.name) + } +} + +export const Settings = [ + new Setting("ff2mpv", "https://github.com/ByteDream/stream-bypass/tree/master#ff2mpv-use-mpv-to-directly-play-streams") +] diff --git a/src/store/store.ts b/src/store/store.ts index 0dae7e2..497854d 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -66,3 +66,5 @@ export async function disable(match: Match) { await storageSet('disabled', disabled) } } + +export const getSetting = storageGet \ No newline at end of file diff --git a/src/ui/popup/popup.html b/src/ui/popup/popup.html index b612913..63bfcd6 100644 --- a/src/ui/popup/popup.html +++ b/src/ui/popup/popup.html @@ -13,8 +13,16 @@ On Off +

Hosters

+ +
+
+

Settings

+ +

+
Something does not work diff --git a/src/ui/popup/popup.scss b/src/ui/popup/popup.scss index f578333..719083e 100644 --- a/src/ui/popup/popup.scss +++ b/src/ui/popup/popup.scss @@ -40,16 +40,26 @@ a { } + hr { margin: 3px 0; + + &.upper-hr { + width: 100%; + } } #all { display: flex; - justify-content: center; + align-items: center; + flex-direction: column; margin: 10px 0 } +.buttons { + margin-bottom: 10px; +} + .low-reliability { text-decoration: underline; text-decoration-color: rgb(255, 0, 0); diff --git a/src/ui/popup/popup.ts b/src/ui/popup/popup.ts index b4fc106..222172f 100644 --- a/src/ui/popup/popup.ts +++ b/src/ui/popup/popup.ts @@ -1,5 +1,6 @@ import {getDisabled, disable, enable, getAllDisabled, enableAll, disableAll} from "../../store/store"; import {matches, Reliability} from "../../match/matches"; +import { Settings, Setting } from "../../store/settings"; async function main() { const disabled = await getDisabled() @@ -52,6 +53,51 @@ async function main() { subContainer.append(row) } + const settingsContainer = document.getElementById("settings-container") + for (const s of Settings) { + const row = document.createElement('tr') + + const name = document.createElement('td') + const nameValue = document.createElement('p') + nameValue.innerText = s.name + + const buttons = document.createElement('td') + buttons.classList.add('buttons') + const on = document.createElement('a') + on.innerText = 'On' + const off = document.createElement('a') + off.innerText = 'Off' + const info = document.createElement('a') + info.target = "_blank" + info.href = s.info_url + info.innerText = "🛈" + + await s.get_status() ? on.classList.add('active') : off.classList.add('active') + + on.onclick = async function () { + if (!on.classList.contains('disabled')) { + await s.enable() + on.classList.add('active') + off.classList.remove('active') + } + } + off.onclick = async function () { + if (!off.classList.contains('disabled')) { + await s.disable() + on.classList.remove('active') + off.classList.add('active') + } + } + + name.append(nameValue) + buttons.append(on, off) + if (s.info_url) { + buttons.append(info) + } + row.append(name, buttons) + settingsContainer.append(row) + } + const allOnButton = document.getElementById('all').getElementsByTagName('a')[0] const allOffButton = document.getElementById('all').getElementsByTagName('a')[1]