16 Commits

14 changed files with 168 additions and 154 deletions

View File

@ -68,9 +68,11 @@ Install the addon directly from the [firefox addon store](https://addons.mozilla
## 📜 Supported sites
| Site | Supported | Note |
|-----------------------------------------------------------------------|-----------|--------------------------------------------------|
|-----------------------------------------------------------------------|-----------|-------------------------------------------------------|
| [doodstream.com](doodstream.com) / [dood.pm](https://dood.pm) | ✔️ | |
| [evoload.io](https://evoload.io) | ✔️ | |
| [evoload.io](https://evoload.io) | ⚠️️ | Website down / Timeout |
| [filemoon.sx](https://filemoon.sx) | ✔ | |
| [mcloud.to](https://mcloud.to/) | ❌ | Reverse engineering the site costs too much time (#5) |
| [mixdrop.co](https://mixdrop.co) | ✔ | |
| [mp4upload.com](https://mp4upload.com) | ✔ | |
| [newgrounds.com](https://newgrounds.com) | ✔ | |
@ -80,8 +82,9 @@ Install the addon directly from the [firefox addon store](https://addons.mozilla
| [videovard.sx](https://videovard.sx) | ❌ | Reverse engineering the site costs too much time |
| [vidlox.me](https://vidlox.me) | ⚠ | Website down / Timeout |
| [vidoza.net](https://vidoza.net) | ✔ | |
| [vistream.pro](https://vidstream.pro) | ❌ | Reverse engineering the site costs too much time (#5) |
| [vivo.sx](https://vivo.sx) | ⚠️ | Website down / Timeout |
| [voe.sx](https://voe.sx) / [voeunblk.com](https://voeunblk.com) | ✔ | |
| [voe.sx](https://voe.sx) | ✔ | |
| [vupload.com](https://vupload.com) | ✔ | |
- ✔️: Everything ok.

View File

@ -1,6 +1,6 @@
{
"name": "stream-bypass",
"version": "2.1.3",
"version": "2.1.6",
"description": "Multi-browser addon for multiple streaming providers which redirects directly to the source video",
"main": "src/index.ts",
"scripts": {
@ -21,12 +21,12 @@
"homepage": "https://github.com/ByteDream/stream-bypass#readme",
"devDependencies": {
"@rollup/plugin-commonjs": "^22.0.0",
"@rollup/plugin-node-resolve": "^13.3.0",
"@rollup/plugin-node-resolve": "^14.0.1",
"@rollup/plugin-replace": "^4.0.0",
"@rollup/plugin-typescript": "^8.3.3",
"@typescript-eslint/eslint-plugin": "^5.27.1",
"@typescript-eslint/parser": "^5.27.1",
"@types/chrome": "^0.0.190",
"@types/chrome": "^0.0.196",
"@types/node-sass": "^4.11.2",
"@types/yazl": "^2.4.2",
"eslint": "^8.17.0",

View File

@ -1,5 +1,5 @@
import {getMatch} from "./match/match";
import {storageGet, storageSet} from "./store/store";
import {storageDelete, storageGet, storageSet} from "./store/store";
import {Match} from "./match/matches";
chrome.webRequest.onBeforeRedirect.addListener(async details => {
@ -9,6 +9,8 @@ chrome.webRequest.onBeforeRedirect.addListener(async details => {
if ((match = await getMatch(new URL(details.url).host)) !== undefined) {
await storageSet('redirect', match.id)
}
} else {
await storageDelete('redirect')
}
}, {
urls: ['<all_urls>'],

View File

@ -4,20 +4,20 @@ import {Match, matches} from "./match/matches";
async function main() {
let match: Match;
let redirect = false;
if ((match = await getMatch(window.location.host)) === undefined) {
let id: string
if ((id = await storageGet('redirect')) !== undefined) {
redirect = true
match = matches.find(m => m.id === id)
await storageDelete('redirect')
} else {
return
}
}
const re = document.body.innerHTML.match(match.regex)
if (re === null) {
return
}
if (re === null) return
if (redirect) await storageDelete('redirect')
const url = await match.match(re)

View File

@ -3,7 +3,7 @@
"name": "Stream Bypass",
"author": "ByteDream",
"description": "A multi-browser addon / extension for multiple streaming providers which redirects directly to the source video.",
"version": "2.1.3",
"version": "2.1.6",
"homepage_url": "https://github.com/ByteDream/stream-bypass",
"browser_specific_settings": {
"gecko": {

View File

@ -1,5 +1,5 @@
export enum Reliability {
HIGH = 1,
HIGH,
NORMAL,
LOW,
}
@ -19,11 +19,12 @@ export abstract class Match {
class Doodstream implements Match {
name = 'Doodstream'
id = 'doodstream'
reliability = Reliability.HIGH
reliability = Reliability.NORMAL
domains = [
'doodstream.com',
'dood.pm',
'dood.ws'
'dood.ws',
'dood.wf'
]
replace = true
regex = new RegExp(/(\/pass_md5\/.*?)'.*(\?token=.*?expiry=)/s)
@ -64,6 +65,26 @@ class Evoload implements Match {
}
}
class Filemoon implements Match {
name = 'Filemoon'
id = 'filemoon'
reliability = Reliability.HIGH
domains = [
'filemoon.sx'
]
regex = new RegExp(/(?<=\|)\w{2,}/gm)
async match(match: RegExpMatchArray): Promise<string> {
const start_idx = match.indexOf('moon')
const prefix = `${match[start_idx]}-${match[start_idx-1]}-${match[start_idx-2]}-${match[start_idx-3]}`
const time = match.find(m => m.length === 10 && !isNaN(parseInt(m)))
const offset = !isNaN(parseInt(match[start_idx-12])) && parseInt(match[start_idx-12]).toString().length == match[start_idx-12].length ? 0 : -1
return `https://${prefix}.filemoon.${match[start_idx-4]}/${match[start_idx-5]}/${match[start_idx-6]}/${match[start_idx-7]}/${match[start_idx-8]}/master.m3u8?t=${match[start_idx-11]}${offset != 0 ? `-${match[start_idx-12]}` : ''}&s=${time}&e=${match[start_idx + offset - 12]}&sp=${match[start_idx + offset - 18]}`
}
}
class Mixdrop implements Match {
name = 'Mixdrop'
id = 'mixdrop'
@ -97,7 +118,8 @@ class Mp4Upload implements Match {
regex = new RegExp(/(?<=\|)\w{2,}/gm)
async match(match: RegExpMatchArray): Promise<string> {
return `https://${match[34]}.mp4upload.com:${match[89]}/d/${match[88]}/video.mp4`
let id = match.slice().reduce((a, b) => a.length >= b.length ? a : b)
return `https://www4.mp4upload.com:282/d/${id}/video.mp4`
}
}
@ -139,7 +161,7 @@ class Streamtape implements Match {
class Streamzz implements Match {
name = 'Streamzz'
id = 'streamzz'
reliability = Reliability.NORMAL
reliability = Reliability.LOW
domains = [
'streamzz.to',
'streamz.ws'
@ -252,6 +274,7 @@ class Vupload implements Match {
export const matches = [
new Doodstream(),
new Evoload(),
new Filemoon(),
new Mixdrop(),
new Mp4Upload(),
new Newgrounds(),

View File

@ -11,7 +11,7 @@
<div id="message-container">
<p id="message"></p>
<br>
<p>Open a new issue <a href="https://github.com/ByteDream/stream-bypass/issues/new">here</a></p>
<p>Open a new issue <a href="https://github.com/ByteDream/stream-bypass/issues">here</a></p>
</div>
</body>
</html>

View File

@ -1,28 +0,0 @@
body
background-color: #131313
html, body, video
width: 100%
height: 100%
margin: 0
video
position: absolute
top: 0
left: 0
#message-container
visibility: hidden
display: flex
justify-content: center
align-items: center
flex-direction: column
color: white
text-align: center
height: 100%
& *
visibility: inherit
& a, & a:visited
color: red

34
src/ui/player/player.scss Normal file
View File

@ -0,0 +1,34 @@
body {
background-color: #131313;
}
html, body, video {
width: 100%;
height: 100%;
margin: 0;
}
video {
position: absolute;
top: 0;
left: 0;
}
#message-container {
visibility: hidden;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
color: white;
text-align: center;
height: 100%;
& * {
visibility: inherit;
}
& a, & a:visited {
color: red
}
}

View File

@ -1,4 +1,4 @@
import {Match, matches, Reliability} from "../../match/matches";
import {matches} from "../../match/matches";
// @ts-ignore
import Hls from "hls.js";
@ -8,13 +8,13 @@ function show_message(message: string) {
document.getElementById('video').hidden = true
}
async function play_native(url: string, match: Match) {
async function play_native(url: string) {
const video = document.getElementById('video') as HTMLVideoElement
video.controls = true
video.src = url
}
async function play_hls(url: string, match: Match) {
async function play_hls(url: string) {
const video = document.getElementById('video') as HTMLVideoElement
video.controls = true
@ -26,36 +26,6 @@ async function play_hls(url: string, match: Match) {
})
hls.loadSource(url)
hls.attachMedia(video)
const loaded = await new Promise((resolve, reject) => {
setTimeout(() => {
resolve(false)
}, match.reliability * 3000)
hls.on(Hls.Events.MANIFEST_PARSED, () => {
resolve(true)
})
})
if (!loaded) {
let message: string
switch (match.reliability) {
case Reliability.LOW:
message = `The reliability for this domain is low, errors like this are common.
Try to choose another streaming provider (if existent) or deactivate the addon for this provider (${match.name}) and try again`
break
case Reliability.NORMAL:
message = `The reliability for this domain is normal, errors like this can occur but are not very common. Try to refresh the page`
break
case Reliability.HIGH:
message = `The reliability for this domains is high, errors like this are very unlikely to happen.
Try to refresh the page and if the error still exists you might want to open a new issue.
When you're using Tor, such errors have a slight chance to occur more often,
so if this is the case just try to reload the page and see if it's working then`
break
}
show_message(`Could not load video. ${message}`)
}
} else {
show_message('Failed to play m3u8 video (hls is not supported). Try again or create a new issue <a href="https://github.com/ByteDream/stream-bypass/issues/new">here</a>')
}
@ -64,17 +34,17 @@ async function play_hls(url: string, match: Match) {
async function main() {
const urlQuery = new URLSearchParams(window.location.search)
const id = urlQuery.get('id')
const url = urlQuery.get('url')
const url = decodeURIComponent(urlQuery.get('url'))
const domain = urlQuery.get('domain')
const match = matches.find((m) => m.id === id)
if (match === undefined) {
show_message(`Invalid id: ${id}. Please report this <a href="https://github.com/ByteDream/stream-bypass/issues/new">here</a>`)
show_message(`Invalid id: ${id}. Please report this <a href="https://github.com/ByteDream/stream-bypass/issues">here</a>`)
return
}
document.title = `Stream Bypass (${domain})`
url.endsWith('.m3u8') ? await play_hls(url, match) : await play_native(url, match)
new URL(url).pathname.endsWith('.m3u8') ? await play_hls(url) : await play_native(url)
}
main()

View File

@ -17,7 +17,7 @@
<hr>
<table id="sub-container">
</table>
<a id="error" href="https://github.com/ByteDream/stream-bypass/issues/new">Something does not work</a>
<a id="error" href="https://github.com/ByteDream/stream-bypass/issues">Something does not work</a>
</div>
</body>
</html>

View File

@ -1,56 +0,0 @@
body
background-color: #2b2a33
font-weight: bold
max-height: 500px
overflow-x: hidden
overflow-y: auto
a, p
color: white
font-size: 16px
margin: 5px 0
cursor: default
a
border: 1px solid #281515
cursor: pointer
font-weight: normal
padding: 5px 8px
&.active
background-color: rgba(255, 65, 65, 0.74)
cursor: default
&.disabled
background-color: grey
cursor: not-allowed
&#error
border: none
display: block
font-weight: lighter
font-size: 0.8rem
text-align: center
padding: 10px 0 5px 0
hr
margin: 3px 0
#all
display: flex
justify-content: center
margin: 10px 0
.low-reliability
text-decoration: underline
text-decoration-color: rgb(255, 0, 0)
.normal-reliability
text-decoration: underline
text-decoration-color: yellow
.high-reliability
text-decoration: underline
text-decoration-color: #00ff00

66
src/ui/popup/popup.scss Normal file
View File

@ -0,0 +1,66 @@
body {
background-color: #2b2a33;
font-weight: bold;
max-height: 500px;
overflow-x: hidden;
overflow-y: auto;
}
a, p {
color: white;
font-size: 16px;
margin: 5px 0;
cursor: default;
}
a {
border: 1px solid #281515;
cursor: pointer;
font-weight: normal;
padding: 5px 8px;
&.active {
background-color: rgba(255, 65, 65, 0.74);
cursor: default;
}
&.disabled {
background-color: grey;
cursor: not-allowed;
}
&#error {
border: none;
display: block;
font-weight: lighter;
font-size: 0.8rem;
text-align: center;
padding: 10px 0 5px 0;
}
}
hr {
margin: 3px 0;
}
#all {
display: flex;
justify-content: center;
margin: 10px 0
}
.low-reliability {
text-decoration: underline;
text-decoration-color: rgb(255, 0, 0);
}
.normal-reliability {
text-decoration: underline;
text-decoration-color: yellow;
}
.high-reliability {
text-decoration: underline;
text-decoration-color: #00ff00;
}

View File

@ -47,8 +47,8 @@ async function buildHtml() {
async function buildCss() {
const files = {
'src/ui/popup/popup.sass': 'build/ui/popup/popup.css',
'src/ui/player/player.sass': 'build/ui/player/player.css'
'src/ui/popup/popup.scss': 'build/ui/popup/popup.css',
'src/ui/player/player.scss': 'build/ui/player/player.css'
}
for (const [src, dst] of Object.entries(files)) {