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]