mirror of
https://github.com/bytedream/stream-bypass.git
synced 2025-05-09 20:25:14 +02:00
2 new websites + indicator for redirect reliability
This commit is contained in:
parent
99d4577d1d
commit
0916f1c637
@ -4,7 +4,9 @@ mixdrop.co
|
||||
streamtape.com
|
||||
streamzz.to
|
||||
thevideome.com
|
||||
upstream.to
|
||||
vidlox.me
|
||||
vidstream.pro
|
||||
vidoza.net
|
||||
vivo.st
|
||||
vivo.sx
|
||||
|
2
build.py
2
build.py
@ -40,7 +40,7 @@ def write_manifest():
|
||||
toplevel = match.split('.')[-1]
|
||||
if toplevel not in domains:
|
||||
domains.append(toplevel)
|
||||
manifest['content_security_policy'] = f"script-src 'self' blob: https://cdn.jsdelivr.net {' '.join(f'*.{toplevel}' for toplevel in domains)}; object-src 'self'"
|
||||
manifest['content_security_policy'] = f"script-src 'self' blob: https://cdn.jsdelivr.net https://unpkg.com {' '.join(f'*.{toplevel}' for toplevel in domains)}; object-src 'self'"
|
||||
|
||||
json.dump(manifest, open('src/manifest.json', 'w'), indent=2)
|
||||
|
||||
|
10
src/index.ts
10
src/index.ts
@ -10,10 +10,12 @@ chrome.storage.local.get(['all', 'disabled'], function (result) {
|
||||
}
|
||||
// @ts-ignore
|
||||
for (let match of matches) {
|
||||
if (window.location.href.indexOf(match[0]) !== -1) {
|
||||
if (keys.indexOf('disabled') === -1 || result['disabled'].indexOf(match[0]) === -1) {
|
||||
let domain = match[0] as string
|
||||
if (window.location.href.indexOf(domain) !== -1) {
|
||||
if (keys.indexOf('disabled') === -1 || result['disabled'].indexOf(domain) === -1) {
|
||||
let regex = match[1] as RegExp
|
||||
let matchClass = match[2] as Match
|
||||
let reliability = match[3] as Reliability
|
||||
|
||||
let re
|
||||
if (regex !== null) {
|
||||
@ -29,12 +31,12 @@ chrome.storage.local.get(['all', 'disabled'], function (result) {
|
||||
location.assign(document.body.innerHTML)
|
||||
} else {
|
||||
// @ts-ignore
|
||||
location.assign(hasSuffix(re[0], 'm3u8') ? chrome.runtime.getURL(`res/hls.html#${re[0]}`) : re[0])
|
||||
location.assign(hasSuffix(re[0], 'm3u8') ? chrome.runtime.getURL(`res/hls.html?domain=${domain}&reliability=${reliability}#${re[0]}`) : re[0])
|
||||
}
|
||||
} else {
|
||||
matchClass.match(re).then(function (path) {
|
||||
// @ts-ignore
|
||||
location.assign(hasSuffix(path, 'm3u8') ? chrome.runtime.getURL(`res/hls.html#${path}`) : path)
|
||||
location.assign(hasSuffix(path, 'm3u8') ? chrome.runtime.getURL(`res/hls.html?domain=${domain}&reliability=${reliability}#${path}`) : path)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
"name": "Stream Bypass",
|
||||
"author": "ByteDream",
|
||||
"description": "",
|
||||
"version": "1.1.4",
|
||||
"version": "1.2.0",
|
||||
"homepage_url": "https://github.com/ByteDream/stream-bypass",
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
@ -20,7 +20,9 @@
|
||||
"*://streamtape.com/*",
|
||||
"*://streamzz.to/*",
|
||||
"*://thevideome.com/*",
|
||||
"*://upstream.to/*",
|
||||
"*://vidlox.me/*",
|
||||
"*://vidstream.pro/*",
|
||||
"*://vidoza.net/*",
|
||||
"*://vivo.st/*",
|
||||
"*://vivo.sx/*",
|
||||
@ -30,13 +32,14 @@
|
||||
"js": [
|
||||
"match.js",
|
||||
"index.js"
|
||||
]
|
||||
],
|
||||
"run_at": "document_end"
|
||||
}
|
||||
],
|
||||
"permissions": [
|
||||
"storage"
|
||||
],
|
||||
"content_security_policy": "script-src 'self' blob: https://cdn.jsdelivr.net *.io *.to *.co *.com *.me *.net *.st *.sx; object-src 'self'",
|
||||
"content_security_policy": "script-src 'self' blob: https://cdn.jsdelivr.net https://unpkg.com *.io *.to *.co *.com *.me *.pro *.net *.st *.sx; object-src 'self'",
|
||||
"browser_action": {
|
||||
"default_icon": "icons/stream-bypass.png",
|
||||
"default_title": "Stream Bypass",
|
||||
|
64
src/match.ts
64
src/match.ts
@ -1,3 +1,9 @@
|
||||
enum Reliability {
|
||||
LOW = 1,
|
||||
NORMAL,
|
||||
HIGH
|
||||
}
|
||||
|
||||
interface Match {
|
||||
match(match: RegExpMatchArray): Promise<string>
|
||||
}
|
||||
@ -50,6 +56,26 @@ class TheVideoMe implements Match {
|
||||
}
|
||||
}
|
||||
|
||||
class Upstream implements Match {
|
||||
async match(match: RegExpMatchArray): Promise<string> {
|
||||
return `https://${match[48]}.upstreamcdn.co/hls/,${match.sort((a, b) => {return b.length - a.length})[0]},.urlset/master.m3u8`
|
||||
}
|
||||
}
|
||||
|
||||
class Vidstream implements Match {
|
||||
async match(match: RegExpMatchArray): Promise<string> {
|
||||
const code = window.location.pathname.split('/').slice(-1)[0]
|
||||
const response = await fetch(`https://vidstream.pro/info/${code}?skey=${match[0]}`, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
referrer: `https://vidstream.pro/embed/${code}`
|
||||
})
|
||||
const json = await response.json()
|
||||
return json['media']['sources'][0]['file']
|
||||
}
|
||||
}
|
||||
|
||||
class Vivo implements Match {
|
||||
async match(match: RegExpMatchArray): Promise<string> {
|
||||
return this.rot47(decodeURIComponent(match[0]))
|
||||
@ -76,18 +102,30 @@ class Vupload implements Match {
|
||||
}
|
||||
}
|
||||
|
||||
// every match HAS to be on an separate line
|
||||
// all domains to match. the matches must be structured like this:
|
||||
// [domain, regex match (can be null), class to call after match (can be null), reliability]
|
||||
// => the domain which should be redirected
|
||||
// => the regex gets called if the user visits a site with the given domain and matches the websites document body.
|
||||
// if the regex is null, the complete document body gets handled as one big regex match
|
||||
// => the class to call when the regex was parsed successfully. the class has to implement the `Match` interface.
|
||||
// if the class is null, the user gets redirected to the first regex match element
|
||||
// => the reliability shows how reliable a stream redirect is. for example, vivo.sx works nearly every time whereas
|
||||
// upstream.to works only sometimes because of a security mechanism they're using (CORS) which currently can't be bypassed
|
||||
//
|
||||
// every match HAS to be on an separate line (for automatically manifest generation)
|
||||
const matches = [
|
||||
['evoload.io', null, new Evoload()],
|
||||
['mcloud.to', new RegExp(/(?<=')\w+(?=';)/gm), new MCloud()],
|
||||
['mixdrop.co', new RegExp(/(?<=\|)\w{2,}/gm), new Mixdrop()],
|
||||
['streamtape.com', new RegExp(/id=\S*(?=')/gm), new Streamtape()],
|
||||
['streamzz.to', new RegExp(/https?:\/\/get.streamz.tw\/getlink-\w+\.dll/gm), null],
|
||||
['thevideome.com', new RegExp(/(?<=\|)\w{2,}/gm), new TheVideoMe()],
|
||||
['vidlox.me', new RegExp(/(?<=\[")\S+?(?=")/gm), null],
|
||||
['vidoza.net', new RegExp(/(?<=src:(\s*)?")\S*(?=")/gm), null],
|
||||
['vivo.st', new RegExp(/(?<=source:\s')(\S+)(?=')/gm), new Vivo()],
|
||||
['vivo.sx', new RegExp(/(?<=source:\s')(\S+)(?=')/gm), new Vivo()],
|
||||
['voe.sx', new RegExp(/https?:\/\/\S*m3u8(?=")/gm), null],
|
||||
['vupload.com', new RegExp(/(?<=class\|)\w*/gm), new Vupload()]
|
||||
['evoload.io', null, new Evoload(), Reliability.NORMAL],
|
||||
['mcloud.to', new RegExp(/(?<=')\w+(?=';)/gm), new MCloud(), Reliability.NORMAL],
|
||||
['mixdrop.co', new RegExp(/(?<=\|)\w{2,}/gm), new Mixdrop(), Reliability.HIGH],
|
||||
['streamtape.com', new RegExp(/id=\S*(?=')/gm), new Streamtape(), Reliability.NORMAL],
|
||||
['streamzz.to', new RegExp(/https?:\/\/get.streamz.tw\/getlink-\w+\.dll/gm), null, Reliability.NORMAL],
|
||||
['thevideome.com', new RegExp(/(?<=\|)\w{2,}/gm), new TheVideoMe(), Reliability.NORMAL],
|
||||
['upstream.to', new RegExp(/(?<=\|)\w{2,}/gm), new Upstream(), Reliability.LOW],
|
||||
['vidlox.me', new RegExp(/(?<=\[")\S+?(?=")/gm), null, Reliability.NORMAL],
|
||||
['vidstream.pro', new RegExp(/(?<=')\w+(?=';)/gm), new Vidstream(), Reliability.LOW],
|
||||
['vidoza.net', new RegExp(/(?<=src:(\s*)?")\S*(?=")/gm), null, Reliability.NORMAL],
|
||||
['vivo.st', new RegExp(/(?<=source:\s')(\S+)(?=')/gm), new Vivo(), Reliability.HIGH],
|
||||
['vivo.sx', new RegExp(/(?<=source:\s')(\S+)(?=')/gm), new Vivo(), Reliability.HIGH],
|
||||
['voe.sx', new RegExp(/https?:\/\/\S*m3u8(?=")/gm), null, Reliability.HIGH],
|
||||
['vupload.com', new RegExp(/(?<=class\|)\w*/gm), new Vupload(), Reliability.NORMAL]
|
||||
]
|
||||
|
@ -4,6 +4,8 @@
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
<link rel="stylesheet" href="popup.css">
|
||||
<script src="https://unpkg.com/@popperjs/core@2"></script>
|
||||
<script src="https://unpkg.com/tippy.js@6"></script>
|
||||
<script src="../match.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -5,13 +5,11 @@ body
|
||||
overflow-x: hidden
|
||||
overflow-y: auto
|
||||
|
||||
|
||||
a, p
|
||||
color: white
|
||||
font-size: 16px
|
||||
margin: 5px 0
|
||||
|
||||
|
||||
a
|
||||
border: 1px solid #281515
|
||||
cursor: pointer
|
||||
@ -26,7 +24,6 @@ a
|
||||
background-color: grey
|
||||
cursor: not-allowed
|
||||
|
||||
|
||||
hr
|
||||
margin: 3px 0
|
||||
|
||||
@ -35,3 +32,16 @@ hr
|
||||
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
|
||||
|
@ -51,12 +51,53 @@ chrome.storage.local.get(['all', 'disabled'], function (result) {
|
||||
let name = document.createElement('td')
|
||||
let nameValue = document.createElement('p')
|
||||
nameValue.innerText = match[0]
|
||||
switch (match[3]) {
|
||||
case 1: // low
|
||||
nameValue.classList.add('low-reliability')
|
||||
// @ts-ignore
|
||||
tippy(nameValue, {
|
||||
content: 'Low reliability: Errors may occur often'
|
||||
})
|
||||
break
|
||||
case 2: // normal
|
||||
nameValue.classList.add('normal-reliability')
|
||||
// @ts-ignore
|
||||
tippy(nameValue, {
|
||||
content: 'Normal reliability: Save to use but errors may occur'
|
||||
})
|
||||
break
|
||||
case 3: //high
|
||||
nameValue.classList.add('high-reliability')
|
||||
// @ts-ignore
|
||||
tippy(nameValue, {
|
||||
content: 'High reliability: Errors are very unlikely to happen'
|
||||
})
|
||||
break
|
||||
}
|
||||
let buttons = document.createElement('td')
|
||||
buttons.classList.add('buttons')
|
||||
let on = document.createElement('a')
|
||||
on.innerText = 'On'
|
||||
// @ts-ignore
|
||||
let onTippy = tippy(on, {
|
||||
content: `Enable ${match[0]}`,
|
||||
onMount: () => {
|
||||
if (on.classList.contains('active') || off.classList.contains('disabled')) {
|
||||
onTippy.hide()
|
||||
}
|
||||
}
|
||||
})
|
||||
let off = document.createElement('a')
|
||||
off.innerText = 'Off'
|
||||
// @ts-ignore
|
||||
let offTippy = tippy(off, {
|
||||
content: `Disable ${match[0]}`,
|
||||
onMount: () => {
|
||||
if (off.classList.contains('active') || off.classList.contains('disabled')) {
|
||||
offTippy.hide()
|
||||
}
|
||||
}
|
||||
})
|
||||
disabled.has(match[0]) ? off.classList.add('active') : on.classList.add('active')
|
||||
if (allDisabled) {
|
||||
on.classList.add('disabled')
|
||||
@ -85,6 +126,7 @@ chrome.storage.local.get(['all', 'disabled'], function (result) {
|
||||
}
|
||||
|
||||
let allButtons = document.getElementById('all').getElementsByTagName('a')
|
||||
let allOn = allButtons[0]
|
||||
allButtons[0].onclick = function () {
|
||||
if (!allButtons[0].classList.contains('disabled')) {
|
||||
enableAll(true)
|
||||
@ -92,6 +134,15 @@ chrome.storage.local.get(['all', 'disabled'], function (result) {
|
||||
allButtons[1].classList.remove('active')
|
||||
}
|
||||
}
|
||||
// @ts-ignore
|
||||
let allOnTippy = tippy(allOn, {
|
||||
content: 'Enable all websites',
|
||||
onMount: () => {
|
||||
if (allButtons[0].classList.contains('active')) {
|
||||
allOnTippy.hide()
|
||||
}
|
||||
}
|
||||
})
|
||||
allButtons[1].onclick = function () {
|
||||
if (!allButtons[1].classList.contains('disabled')) {
|
||||
enableAll(false)
|
||||
@ -99,5 +150,14 @@ chrome.storage.local.get(['all', 'disabled'], function (result) {
|
||||
allButtons[1].classList.add('active')
|
||||
}
|
||||
}
|
||||
// @ts-ignore
|
||||
let allOffTippy = tippy(allButtons[1], {
|
||||
content: 'Disable all websites',
|
||||
onMount: () => {
|
||||
if (allButtons[1].classList.contains('active')) {
|
||||
allOffTippy.hide()
|
||||
}
|
||||
}
|
||||
})
|
||||
allDisabled ? allButtons[1].classList.add('active') : allButtons[0].classList.add('active')
|
||||
})
|
||||
|
@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
|
||||
<link rel="stylesheet" href="/res/hls.css">
|
||||
<title>m3u8</title>
|
||||
<link rel="stylesheet" href="/res/hls.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
|
||||
</head>
|
||||
<body style="margin: 0">
|
||||
<video id="video" style="width: 100%; height: 100%"></video>
|
||||
<p id="not-supported" hidden>Filed to play m3u8 video. Try again or create a new issue <a href="https://github.com/ByteDream/stream-bypass/issues">here</a></p>
|
||||
<body>
|
||||
<video id="video"></video>
|
||||
<p id="message" hidden></p>
|
||||
<script src="/res/hls.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -1,6 +1,9 @@
|
||||
html, body, video
|
||||
height: 100%
|
||||
width: 100%
|
||||
height: 100%
|
||||
margin: 0
|
||||
|
||||
video
|
||||
margin: auto
|
||||
position: absolute
|
||||
top: 0
|
||||
left: 0
|
@ -1,3 +1,10 @@
|
||||
function showMessage(message: string) {
|
||||
let messageElement = document.getElementById('message') as HTMLParagraphElement
|
||||
messageElement.innerHTML = message
|
||||
messageElement.hidden = false
|
||||
document.getElementById('video').hidden = true
|
||||
}
|
||||
|
||||
function loadHls() {
|
||||
let url = window.location.hash.substring(1)
|
||||
let video = document.getElementById('video') as HTMLVideoElement;
|
||||
@ -11,9 +18,42 @@ function loadHls() {
|
||||
let hls = new Hls()
|
||||
hls.loadSource(url)
|
||||
hls.attachMedia(video)
|
||||
|
||||
let searchParams = new URLSearchParams(window.location.search)
|
||||
let rawReliability = parseInt(searchParams.get('reliability'))
|
||||
|
||||
let thirdPartyFallback = setTimeout(() => {
|
||||
let message: string
|
||||
|
||||
switch (rawReliability) {
|
||||
case 1: // low
|
||||
message = `The reliability for this domain is low, so errors like this are common.
|
||||
Try to choose another streaming provider (if existent) or deactivate the addon for this domain (${searchParams.get('domain')}) and try again`
|
||||
break
|
||||
case 2: // 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 3: // 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 <a href="https://github.com/ByteDream/stream-bypass/issues">here</a>.
|
||||
When your using <a href="https://www.torproject.org/">Tor</a> 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 you it's working then`
|
||||
break
|
||||
}
|
||||
|
||||
// shows a message if hls could not be loaded
|
||||
showMessage(`Could not load hls video. ${message}`)
|
||||
}, rawReliability * 3000)
|
||||
|
||||
// @ts-ignore
|
||||
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
||||
clearTimeout(thirdPartyFallback)
|
||||
document.getElementById('video').hidden = false
|
||||
document.getElementById('message').hidden = true
|
||||
})
|
||||
} else {
|
||||
// shows a message if hls is not supported
|
||||
document.getElementById('not-supported').hidden = false
|
||||
showMessage(`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">here</a>`)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,11 +2,13 @@
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es2015",
|
||||
"removeComments": true,
|
||||
"lib": [
|
||||
"dom",
|
||||
"es5",
|
||||
"scripthost",
|
||||
"es2015.collection"
|
||||
"es2015.collection",
|
||||
"es2015.promise"
|
||||
]
|
||||
},
|
||||
"exclude": [
|
||||
|
Loading…
x
Reference in New Issue
Block a user