├── .env
├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── .npmrc
├── .prettierignore
├── .prettierrc.cjs
├── LICENSE
├── README.md
├── eslint.config.mjs
├── example.gif
├── package-lock.json
├── package.json
├── public
└── icons
│ ├── stream-bypass.svg
│ ├── stream-bypass@128px.png
│ ├── stream-bypass@16px.png
│ ├── stream-bypass@32px.png
│ ├── stream-bypass@48px.png
│ ├── stream-bypass@96px.png
│ ├── stream-bypass_disabled.svg
│ ├── stream-bypass_disabled@128px.png
│ ├── stream-bypass_disabled@16px.png
│ ├── stream-bypass_disabled@32px.png
│ ├── stream-bypass_disabled@48px.png
│ └── stream-bypass_disabled@96px.png
├── src
├── entries
│ ├── background
│ │ ├── mv2.ts
│ │ ├── mv3.ts
│ │ └── shared.ts
│ ├── contentScript
│ │ └── main.ts
│ ├── player
│ │ ├── Player.svelte
│ │ ├── player.html
│ │ └── player.ts
│ └── popup
│ │ ├── Popup.svelte
│ │ ├── index.html
│ │ └── toggle.svelte
├── lib
│ ├── match.ts
│ ├── settings.ts
│ └── util
│ │ ├── extract.ts
│ │ └── userspace.ts
├── manifest.ts
└── vite-env.d.ts
├── svelte.config.js
├── tsconfig.json
└── vite.config.ts
/.env:
--------------------------------------------------------------------------------
1 | MANIFEST_VERSION=2
2 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: ci
2 |
3 | on:
4 | push:
5 | pull_request:
6 |
7 | jobs:
8 | lint:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Checkout
12 | uses: actions/checkout@v4
13 |
14 | - name: Install nodejs
15 | uses: actions/setup-node@v4
16 | with:
17 | node-version: 22
18 | cache: 'npm'
19 |
20 | - name: Install dependencies
21 | run: npm ci
22 |
23 | - name: Lint
24 | run: npm run lint
25 |
26 | build:
27 | runs-on: ubuntu-latest
28 | strategy:
29 | matrix:
30 | include:
31 | - manifest_version: 2
32 | - manifest_version: 3
33 | steps:
34 | - name: Checkout
35 | uses: actions/checkout@v4
36 |
37 | - name: Install nodejs
38 | uses: actions/setup-node@v4
39 | with:
40 | node-version: 22
41 | cache: 'npm'
42 |
43 | - name: Install dependencies
44 | run: npm ci
45 |
46 | - name: Build
47 | env:
48 | MANIFEST_VERSION: ${{ matrix.manifest_version }}
49 | run: npm run build
50 |
51 | - name: Upload
52 | uses: actions/upload-artifact@v4
53 | with:
54 | name: stream-bypass-mv${{ matrix.manifest_version }}
55 | path: ./dist
56 | if-no-files-found: error
57 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | dist/
3 | release/
4 | node_modules/
5 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | auto-install-peers=false
2 | strict-peer-dependencies=false
3 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 | .env
5 | .env.*
6 | !.env.example
7 |
8 | package-lock.json
9 |
--------------------------------------------------------------------------------
/.prettierrc.cjs:
--------------------------------------------------------------------------------
1 | // @ts-check
2 |
3 | /** @type {import("prettier").Config} */
4 | module.exports = {
5 | useTabs: true,
6 | singleQuote: true,
7 | trailingComma: 'none',
8 | printWidth: 100,
9 | plugins: ['prettier-plugin-svelte', '@ianvs/prettier-plugin-sort-imports'],
10 | /* prettier-plugin-svelte */
11 | overrides: [{ files: '*.svelte', options: { parser: 'svelte' } }],
12 | /* @ianvs/prettier-plugin-sort-imports */
13 | importOrder: ['^~/(.*)$', '^./(.*)$', ''],
14 | importOrderParserPlugins: ['typescript'],
15 | importOrderTypeScriptVersion: '5.0.0',
16 | importOrderCaseSensitive: false
17 | };
18 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022-NOW ByteDream
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Stream Bypass
2 |
3 | A multi-browser addon / extension for multiple streaming providers which redirects directly to the source video.
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | Introduction 📝
22 | •
23 | Installation 📥
24 | •
25 | Features ✨
26 | •
27 | Supported Websites 📜
28 | •
29 | Building 🛠️
30 | •
31 | Settings ⚙️
32 | •
33 | License ⚖
34 |
35 |
36 | ## 📝 Introduction
37 |
38 | This addon replaces the video player from this sides with the native player build-in into the browser or redirects directly to the source video.
39 | This has the advantage, that no advertising or popups are shown when trying to interact with the video (playing, skipping, ...) or some sites are showing them even if you do nothing.
40 | Additionally, this enables you to download the video by right-clicking it and just choose the download option.
41 |
42 |
43 | How it's working:
44 |
45 |
46 |
47 | ## 📥 Installation
48 |
49 | ### Official browser stores
50 |
51 | The best way to install the extension are the official browser extension stores:
52 |
53 | - [Firefox Addon Store](https://addons.mozilla.org/de/firefox/addon/stream-bypass/) (Firefox for Android is supported too!)
54 | - [Chrome Web Store](https://chromewebstore.google.com/detail/ddfpfjomnakfckhmilacnbokdaknamdb)
55 |
56 | ### Manual installation
57 |
58 | - Firefox
59 | - Download `stream-bypass--mv2.zip` from the [latest release](https://github.com/ByteDream/stream-bypass/releases/latest) and unzip it (with [7zip](https://www.7-zip.org/) or something like that)
60 | - Go into your browser and type `about:debugging#/runtime/this-firefox` in the address bar
61 | - Click the `Load Temporary Add-on...` button and choose the `manifest.json` file in the unzipped directory
62 | - Chromium / Google Chrome
63 | > As nearly every browser other than Firefox is based on Chromium, this should be the same for most of them
64 | - Download `stream-bypass--mv3.zip` from the [latest release](https://github.com/ByteDream/stream-bypass/releases/latest) and unzip it (with [7zip](https://www.7-zip.org/) or something like that)
65 | - Go into your browser and type `chrome://extensions` in the address bar
66 | - Turn on the developer mode by checking the switch in the top right corner
67 | - Click `Load unpacked` and choose the unzipped directory
68 |
69 | ## ✨ Features
70 |
71 | | Feature | Firefox | Chrome | Firefox for Android |
72 | | --------------------------------------------------------------------------------------------------------------------------------- | ------- | ------ | ------------------- |
73 | | Replace site-speicifc video player with browser native video player | ✔ | ✔ | ✔ |
74 | | Support websites that are accessed via a redirect | ✔ | ❌ | ✔ |
75 | | Open video in mpv (with [ff2mpv](https://github.com/ByteDream/stream-bypass/tree/master#ff2mpv-use-mpv-to-directly-play-streams)) | ✔ | ✔ | ❌ |
76 |
77 | - ✔️: Supported.
78 | - ❌: Not supported.
79 |
80 | ## 📜 Supported websites
81 |
82 | | Site | Firefox & Firefox for Android | Chrome & Chromium based |
83 | | --------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
84 | | [dropload.io](https://dropload.io) | ✔ | ✔ |
85 | | [doodstream.com](doodstream.com) / [dood.pm](https://dood.pm) | ✔ | ⚠ (redirect probably required) |
86 | | [filemoon.to](https://filemoon.to) | ✔ | ✔ |
87 | | [goodstream.uno](https://goodstream.uno) | ✔ | ✔ |
88 | | [kwik.cx](https://kwik.cx) | ✔ | ✔ |
89 | | [loadx.ws](https://loadx.ws) | ✔ | ❌ (background request always required) |
90 | | [luluvdo.com](https://luluvdo.com) | ✔ | ❌ (background request always required) |
91 | | [mixdrop.co](https://mixdrop.co) | ✔ ️ | ✔ |
92 | | [mp4upload.com](https://mp4upload.com) | ✔ | ✔ |
93 | | [newgrounds.com](https://newgrounds.com) | ✔ | ✔ |
94 | | [streama2z.com](https://streama2z.com) | ✔ | ❌ (redirect always required) |
95 | | [streamtape.com](https://streamtape.com) | ⚠ (correct video url can't always be extract, retrying/reloading the page might fix it) | ⚠ (correct video url can't always be extract, retrying/reloading the page might fix it) |
96 | | [streamzz.to](https://streamzz.to) / [streamz.ws](https://streamz.ws) | ✔ | ✔ |
97 | | [supervideo.tv](https://supervideo.tv) | ✔ | ✔ |
98 | | [upstream.to](https://upstream.to) | ✔ | ✔ |
99 | | [vidmoly.to](https://vidmoly.me) | ✔ | ✔ |
100 | | [vidoza.net](https://vidoza.net) | ✔ | ✔ |
101 | | [voe.sx](https://voe.sx) | ✔ | ❌ (redirect always required) |
102 | | [vupload.com](https://vupload.com) | ✔ | ✔ |
103 |
104 | - ✔️: Everything ok.
105 | - ⚠: Works with limitations.
106 | - ❌: Not supported.
107 |
108 | _This table might not be 100% accurate, it isn't actively monitored if the addon works for every website!_
109 |
110 | Some sites put much effort in obfuscating their code / how they receive the video stream so that it simply cost too much time for me to reverse engineer it and find out how to bypass the native video player of the site.
111 |
112 | ## 🛠️ Building
113 |
114 | If you want to build the addon from source and not using the [installation](#installation) way, follow the instructions.
115 |
116 | Requirements:
117 |
118 | - `npm` installed.
119 | - A copy of this repository and a shell / console open in the copied directory.
120 |
121 | If the requirements are satisfied, you can continue with the following commands:
122 |
123 | ```shell
124 | # install all dependencies
125 | $ npm install
126 |
127 | # build the extension source to the dist/ directory
128 | $ npm run build
129 |
130 | # same as build + more optimizations and browser specific settings at release/
131 | $ npm run release:firefox # or "release:chrome" to create a release for chromium based browsers
132 | ```
133 |
134 | ##### Install
135 |
136 | If you want to use the addon in Chromium or any browser which is based on it, follow the steps in [installation](#-installation).
137 | When using firefox, use the following:
138 |
139 | 1. Type `about:debugging` in the browser's address bar.
140 | 2. Select 'This Firefox' tab (maybe named different, depending on your language).
141 | 3. Under `Temporary Extensions`, click `Load Temporary Add-on`.
142 | 4. Choose any file in the directory where the compiled sources are.
143 |
144 | ## ⚙️ Settings
145 |
146 | ### ff2mpv: use mpv to directly play streams
147 |
148 | ff2mpv is located at this repository: https://github.com/woodruffw/ff2mpv
149 |
150 | Steps to get it set up:
151 |
152 | - 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).
153 | - Scroll down to `Install manually`
154 | - Follow instructions for Firefox/Chrome
155 | - Edit the `ff2mpv.json` you created:
156 | - Firefox: Add `{55dd42e8-3dd9-455a-b4fe-86664881b10c}` to `allowed_extensions` ->
157 | ```
158 | "allowed_extensions": [
159 | "ff2mpv@yossarian.net",
160 | "{55dd42e8-3dd9-455a-b4fe-86664881b10c}"
161 | ]
162 | ```
163 | - Chrome/Chromium:
164 | - Go To: Settings -> Extensions
165 | - Click on `Details` of the Stream Bypass extension and copy the ID
166 | - Add `chrome-extension://ddfpfjomnakfckhmilacnbokdaknamdb/` to `allowed_origins` ->
167 | ```
168 | "allowed_origins": [
169 | "chrome-extension://ephjcajbkgplkjmelpglennepbpmdpjg/",
170 | "chrome-extension://ddfpfjomnakfckhmilacnbokdaknamdb/"
171 | ]
172 | ```
173 |
174 | ## ⚖ License
175 |
176 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for more details.
177 |
--------------------------------------------------------------------------------
/eslint.config.mjs:
--------------------------------------------------------------------------------
1 | import js from '@eslint/js';
2 | import prettier from 'eslint-config-prettier';
3 | import svelte from 'eslint-plugin-svelte';
4 | import ts from 'typescript-eslint';
5 |
6 | export default ts.config(
7 | js.configs.recommended,
8 | ...ts.configs.recommended,
9 | ...svelte.configs['flat/recommended'],
10 | prettier,
11 | ...svelte.configs['flat/prettier'],
12 | {
13 | files: ['**/*.svelte'],
14 |
15 | languageOptions: {
16 | parserOptions: {
17 | parser: ts.parser
18 | }
19 | }
20 | },
21 | {
22 | rules: {
23 | '@typescript-eslint/no-explicit-any': 'off',
24 | 'no-undef': 'off'
25 | }
26 | },
27 | {
28 | ignores: [
29 | '.DS_Store',
30 | 'node_modules',
31 | 'dist',
32 | 'release',
33 | '.idea',
34 | '.env',
35 | '.env.*',
36 | '!.env.example',
37 | 'package-lock.json'
38 | ]
39 | }
40 | );
41 |
--------------------------------------------------------------------------------
/example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bytedream/stream-bypass/607326e6d67ab3b7592fc932bf0324c11a026df1/example.gif
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "stream-bypass",
3 | "version": "3.1.6",
4 | "displayName": "Stream Bypass",
5 | "author": "bytedream",
6 | "description": "Multi-browser addon for multiple streaming providers which redirects directly to the source video",
7 | "scripts": {
8 | "build": "vite build",
9 | "watch": "vite build --watch --mode development --minify false",
10 | "dev": "vite",
11 | "serve:firefox": "web-ext run --start-url \"about:debugging#/runtime/this-firefox\" --source-dir ./dist/",
12 | "serve:chrome": "web-ext run -t chromium --start-url \"https://example.com\" --source-dir ./dist/",
13 | "check": "svelte-check --tsconfig ./tsconfig.json",
14 | "lint": "prettier --check . && eslint .",
15 | "format": "prettier --write .",
16 | "release:firefox": "MANIFEST_VERSION=2 vite build --outDir release/firefox",
17 | "release:chrome": "MANIFEST_VERSION=3 vite build --outDir release/chrome"
18 | },
19 | "license": "MIT",
20 | "repository": {
21 | "type": "git",
22 | "url": "git+https://github.com/bytedream/stream-bypass.git"
23 | },
24 | "bugs": {
25 | "url": "https://github.com/bytedream/stream-bypass/issues"
26 | },
27 | "devDependencies": {
28 | "@ianvs/prettier-plugin-sort-imports": "^4.4.1",
29 | "@samrum/vite-plugin-web-extension": "^5.1.1",
30 | "@sveltejs/vite-plugin-svelte": "^5.0.3",
31 | "@tsconfig/svelte": "^5.0.4",
32 | "@types/chrome": "^0.0.320",
33 | "@types/firefox-webext-browser": "^120.0.4",
34 | "eslint": "^9.26.0",
35 | "eslint-config-prettier": "^10.1.3",
36 | "eslint-plugin-svelte": "^3.5.1",
37 | "hls.js": "^1.6.2",
38 | "prettier": "^3.5.3",
39 | "prettier-plugin-svelte": "^3.3.3",
40 | "sass": "^1.87.0",
41 | "svelte": "^5.28.2",
42 | "svelte-check": "^4.1.7",
43 | "svelte-preprocess": "^6.0.3",
44 | "tslib": "^2.8.1",
45 | "typescript": "^5.8.3",
46 | "typescript-eslint": "^8.32.0",
47 | "vite": "^6.3.5",
48 | "web-ext": "^8.6.0"
49 | },
50 | "type": "module"
51 | }
52 |
--------------------------------------------------------------------------------
/public/icons/stream-bypass.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/icons/stream-bypass@128px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bytedream/stream-bypass/607326e6d67ab3b7592fc932bf0324c11a026df1/public/icons/stream-bypass@128px.png
--------------------------------------------------------------------------------
/public/icons/stream-bypass@16px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bytedream/stream-bypass/607326e6d67ab3b7592fc932bf0324c11a026df1/public/icons/stream-bypass@16px.png
--------------------------------------------------------------------------------
/public/icons/stream-bypass@32px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bytedream/stream-bypass/607326e6d67ab3b7592fc932bf0324c11a026df1/public/icons/stream-bypass@32px.png
--------------------------------------------------------------------------------
/public/icons/stream-bypass@48px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bytedream/stream-bypass/607326e6d67ab3b7592fc932bf0324c11a026df1/public/icons/stream-bypass@48px.png
--------------------------------------------------------------------------------
/public/icons/stream-bypass@96px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bytedream/stream-bypass/607326e6d67ab3b7592fc932bf0324c11a026df1/public/icons/stream-bypass@96px.png
--------------------------------------------------------------------------------
/public/icons/stream-bypass_disabled.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/icons/stream-bypass_disabled@128px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bytedream/stream-bypass/607326e6d67ab3b7592fc932bf0324c11a026df1/public/icons/stream-bypass_disabled@128px.png
--------------------------------------------------------------------------------
/public/icons/stream-bypass_disabled@16px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bytedream/stream-bypass/607326e6d67ab3b7592fc932bf0324c11a026df1/public/icons/stream-bypass_disabled@16px.png
--------------------------------------------------------------------------------
/public/icons/stream-bypass_disabled@32px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bytedream/stream-bypass/607326e6d67ab3b7592fc932bf0324c11a026df1/public/icons/stream-bypass_disabled@32px.png
--------------------------------------------------------------------------------
/public/icons/stream-bypass_disabled@48px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bytedream/stream-bypass/607326e6d67ab3b7592fc932bf0324c11a026df1/public/icons/stream-bypass_disabled@48px.png
--------------------------------------------------------------------------------
/public/icons/stream-bypass_disabled@96px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bytedream/stream-bypass/607326e6d67ab3b7592fc932bf0324c11a026df1/public/icons/stream-bypass_disabled@96px.png
--------------------------------------------------------------------------------
/src/entries/background/mv2.ts:
--------------------------------------------------------------------------------
1 | import './shared';
2 |
3 | import { getMatch, type Match } from '~/lib/match';
4 | import { Redirect, UrlReferer } from '~/lib/settings';
5 |
6 | chrome.webRequest.onBeforeSendHeaders.addListener(
7 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment
8 | // @ts-ignore
9 | async (details) => {
10 | const referer = await UrlReferer.get(new URL(details.url).hostname);
11 | if (!referer) return;
12 |
13 | await UrlReferer.delete(new URL(details.url).hostname);
14 |
15 | details.requestHeaders!.push({
16 | name: 'Referer',
17 | value: `https://${referer}/`
18 | });
19 |
20 | return { requestHeaders: details.requestHeaders };
21 | },
22 | { urls: [''], types: ['xmlhttprequest'] },
23 | ['blocking', 'requestHeaders']
24 | );
25 |
26 | chrome.webRequest.onBeforeRedirect.addListener(
27 | async (details) => {
28 | // check if redirects origins from a previous redirect
29 | if ((await Redirect.get()) == null) {
30 | let match: Match | null;
31 | if ((match = await getMatch(new URL(details.url).hostname)) !== null) {
32 | await Redirect.set(match);
33 | }
34 | } else {
35 | await Redirect.delete();
36 | }
37 | },
38 | { urls: [''], types: ['main_frame', 'sub_frame'] }
39 | );
40 |
--------------------------------------------------------------------------------
/src/entries/background/mv3.ts:
--------------------------------------------------------------------------------
1 | import './shared';
2 |
--------------------------------------------------------------------------------
/src/entries/background/shared.ts:
--------------------------------------------------------------------------------
1 | chrome.runtime.onMessage.addListener(async (message) => {
2 | if (message.action == 'ff2mpv') {
3 | await chrome.runtime.sendNativeMessage('ff2mpv', { url: message.url });
4 | }
5 | });
6 |
--------------------------------------------------------------------------------
/src/entries/contentScript/main.ts:
--------------------------------------------------------------------------------
1 | import { getMatch, MatchMediaType, type Match } from '~/lib/match';
2 | import { Other, Redirect } from '~/lib/settings';
3 |
4 | async function main() {
5 | let match: Match | null;
6 | let redirect = false;
7 | if ((match = await getMatch(window.location.host)) === null) {
8 | if ((match = await Redirect.get()) === null) {
9 | return;
10 | }
11 | redirect = true;
12 | }
13 |
14 | // some sites have a javascript based redirect, e.g. example.com redirects to example.org by changing
15 | // window.location.href instead of a 3XX http redirect. an empty body is a sign that such a javascript redirect
16 | // occurred
17 | if (document.body == null) {
18 | await Redirect.set(match);
19 | return;
20 | }
21 |
22 | let re = null;
23 | for (const regex of match.regex) {
24 | if ((re = document.body.innerHTML.match(regex)) !== null) {
25 | break;
26 | }
27 | }
28 | if (re === null) {
29 | return;
30 | }
31 |
32 | if (redirect) {
33 | await Redirect.delete();
34 | }
35 |
36 | let url: string | null;
37 | let urlType: MatchMediaType | null;
38 | try {
39 | const matchResult = await match.match(re);
40 | if (matchResult && typeof matchResult === 'string') {
41 | url = matchResult;
42 | urlType = url.includes('.m3u8') ? MatchMediaType.Hls : MatchMediaType.Native;
43 | } else if (matchResult && typeof matchResult === 'object') {
44 | if (MatchMediaType.Hls in matchResult) {
45 | url = matchResult[MatchMediaType.Hls];
46 | urlType = MatchMediaType.Hls;
47 | } else if (MatchMediaType.Native in matchResult) {
48 | url = matchResult[MatchMediaType.Native];
49 | urlType = MatchMediaType.Native;
50 | }
51 | }
52 | } catch {
53 | return;
54 | }
55 |
56 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment
57 | // @ts-ignore
58 | if (!url || !urlType) {
59 | return;
60 | }
61 |
62 | // send the url to the ff2mpv (https://github.com/woodruffw/ff2mpv) application
63 | if (await Other.getFf2mpv()) {
64 | await chrome.runtime.sendMessage({ action: 'ff2mpv', url: url });
65 | }
66 |
67 | if (match.replace && urlType != MatchMediaType.Hls) {
68 | // this destroys all intervals that may spawn popups or events
69 | let intervalId = window.setInterval(() => {}, 0);
70 | while (intervalId--) {
71 | clearInterval(intervalId);
72 | }
73 | let timeoutId = window.setTimeout(() => {}, 0);
74 | while (timeoutId--) {
75 | clearTimeout(timeoutId);
76 | }
77 |
78 | // clear completed document
79 | document.documentElement.innerHTML = '';
80 |
81 | document.body.style.backgroundColor = '#131313';
82 |
83 | // video player
84 | const player = document.createElement('video');
85 | player.style.width = '100%';
86 | player.style.height = '100%';
87 | player.controls = true;
88 | player.src = url;
89 |
90 | // add video player to document body
91 | document.body.style.margin = '0';
92 | document.body.append(player);
93 | } else {
94 | window.location.assign(
95 | chrome.runtime.getURL(
96 | `src/entries/player/player.html?id=${match.id}&url=${encodeURIComponent(url)}&domain=${
97 | window.location.hostname
98 | }&type=${urlType}`
99 | )
100 | );
101 | }
102 | }
103 |
104 | main();
105 |
--------------------------------------------------------------------------------
/src/entries/player/Player.svelte:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 | {#if errorMessage}
22 |
23 |
24 |
25 | {@html errorMessage}
26 |
27 |
28 | {/if}
29 |
30 |
31 |
66 |
--------------------------------------------------------------------------------
/src/entries/player/player.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Stream Bypass
6 |
7 |
8 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/entries/player/player.ts:
--------------------------------------------------------------------------------
1 | import Hls from 'hls.js';
2 | import { matches, MatchMediaType } from '~/lib/match';
3 | import { UrlReferer } from '~/lib/settings';
4 |
5 | async function playNative(url: string, domain: string, videoElem: HTMLVideoElement) {
6 | await UrlReferer.set(new URL(url).hostname, domain);
7 |
8 | videoElem.src = url;
9 | }
10 |
11 | async function playHls(url: string, domain: string, videoElem: HTMLVideoElement) {
12 | if (videoElem.canPlayType('application/vnd.apple.mpegurl')) {
13 | videoElem.src = url;
14 | } else if (Hls.isSupported()) {
15 | const hls = new Hls({
16 | enableWorker: false,
17 | xhrSetup: async (xhr: XMLHttpRequest, url: string) => {
18 | await UrlReferer.set(new URL(url).hostname, domain);
19 | xhr.open('GET', url);
20 | }
21 | });
22 | hls.loadSource(url);
23 | hls.attachMedia(videoElem);
24 | } else {
25 | throw 'Failed to play m3u8 video (hls is not supported). Try again or create a new issue here';
26 | }
27 | }
28 |
29 | export async function play(videoElem: HTMLVideoElement) {
30 | const urlQuery = new URLSearchParams(window.location.search);
31 | const id = urlQuery.get('id') as string;
32 | const url = decodeURIComponent(urlQuery.get('url') as string);
33 | const domain = urlQuery.get('domain') as string;
34 | const type = urlQuery.get('type') as MatchMediaType;
35 |
36 | const match = matches[id];
37 | if (match === undefined) {
38 | throw `Invalid id: ${id}. Please report this here`;
39 | }
40 | document.title = `Stream Bypass (${domain})`;
41 |
42 | if (type === MatchMediaType.Hls) {
43 | await playHls(url, domain, videoElem);
44 | } else if (type === MatchMediaType.Native) {
45 | await playNative(url, domain, videoElem);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/entries/popup/Popup.svelte:
--------------------------------------------------------------------------------
1 |
28 |
29 |
34 |
67 | {#if !isMobile}
68 |
92 | {/if}
93 | Report issues or requests
96 |
97 |
98 |
99 |
166 |
--------------------------------------------------------------------------------
/src/entries/popup/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Stream Bypass
7 |
8 |
9 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/entries/popup/toggle.svelte:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
20 |
21 |
69 |
--------------------------------------------------------------------------------
/src/lib/match.ts:
--------------------------------------------------------------------------------
1 | import { Hosters, Redirect, TmpHost } from './settings';
2 | import { lastPathSegment } from './util/extract';
3 | import { unpack } from './util/userspace';
4 |
5 | export interface Match {
6 | name: string;
7 | id: string;
8 | domains: string[];
9 | replace?: boolean;
10 | regex: RegExp[];
11 | notice?: string;
12 |
13 | match(
14 | match: RegExpMatchArray
15 | ): Promise<
16 | string | { [MatchMediaType.Hls]: string } | { [MatchMediaType.Native]: string } | null
17 | >;
18 |
19 | // allow other properties that may be implemented by the objects that use this interface declaration
20 | [other: string]: any;
21 | }
22 |
23 | export enum MatchMediaType {
24 | Hls = 'hls',
25 | Native = 'native'
26 | }
27 |
28 | export const Doodstream: Match = {
29 | name: 'Doodstream',
30 | id: 'doodstream',
31 | domains: [
32 | 'doodstream.com',
33 | 'dood.pm',
34 | 'dood.ws',
35 | 'dood.wf',
36 | 'dood.cx',
37 | 'dood.sh',
38 | 'dood.watch',
39 | 'dood.work',
40 | 'dood.to',
41 | 'dood.so',
42 | 'dood.la',
43 | 'dood.li',
44 | 'dood.re',
45 | 'dood.yt',
46 | 'doods.pro',
47 | 'ds2play.com',
48 | 'dooood.com',
49 | 'd000d.com'
50 | ],
51 | replace: true,
52 | regex: [/(\/pass_md5\/.*?)'.*(\?token=.*?expiry=)/s],
53 |
54 | match: async function (match: RegExpMatchArray) {
55 | const response = await fetch(`https://${window.location.host}${match[1]}`, {
56 | headers: {
57 | Range: 'bytes=0-'
58 | },
59 | referrer: `https://${window.location.host}/e/${
60 | window.location.pathname.split('/').slice(-1)[0]
61 | }`
62 | });
63 | return `${await response.text()}1234567890${match[2]}${Date.now()}`;
64 | }
65 | };
66 |
67 | export const DropLoad: Match = {
68 | name: 'Dropload',
69 | id: 'dropload',
70 | domains: ['dropload.io'],
71 | regex: [/eval\(function\(p,a,c,k,e,d\).*?(?=<\/script>)/gms],
72 |
73 | match: async function (match: RegExpMatchArray) {
74 | const unpacked = await unpack(match[0]);
75 | return unpacked.match(/(?<=file:").*(?=")/)![0];
76 | }
77 | };
78 |
79 | export const Filemoon: Match = {
80 | name: 'Filemoon',
81 | id: 'filemoon',
82 | domains: ['filemoon.sx', 'filemoon.to', 'filemoon.in'],
83 | regex: [/(?<=