mirror of
https://github.com/bytedream/stream-bypass.git
synced 2025-06-28 02:50:32 +02:00
Rewrite
This commit is contained in:
24
src/entries/background/main.ts
Normal file
24
src/entries/background/main.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import type { Match } from '~/lib/match';
|
||||
import { storageDelete, storageGet, storageSet } from '~/lib/settings';
|
||||
import { getMatch } from '~/lib/match';
|
||||
|
||||
chrome.runtime.onMessage.addListener(async (message) => {
|
||||
if (message.action == 'ff2mpv') {
|
||||
await chrome.runtime.sendNativeMessage('ff2mpv', { url: message.url });
|
||||
}
|
||||
});
|
||||
|
||||
chrome.webRequest.onBeforeRedirect.addListener(
|
||||
async (details) => {
|
||||
// check if redirects origins from a previous redirect
|
||||
if ((await storageGet('redirect')) === undefined) {
|
||||
let match: Match;
|
||||
if ((match = await getMatch(new URL(details.url).hostname)) !== undefined) {
|
||||
await storageSet('redirect', match.id);
|
||||
}
|
||||
} else {
|
||||
await storageDelete('redirect');
|
||||
}
|
||||
},
|
||||
{ urls: ['<all_urls>'], types: ['main_frame', 'sub_frame'] }
|
||||
);
|
51
src/entries/contentScript/main.ts
Normal file
51
src/entries/contentScript/main.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import type { Match } from '~/lib/match';
|
||||
import { getMatch } from '~/lib/match';
|
||||
import { Other, Redirect } from '~/lib/settings';
|
||||
import browser from 'webextension-polyfill';
|
||||
|
||||
async function main() {
|
||||
let match: Match;
|
||||
let redirect = false;
|
||||
if ((match = await getMatch(window.location.host)) === null) {
|
||||
if ((match = await Redirect.get()) === null) {
|
||||
return;
|
||||
}
|
||||
redirect = true;
|
||||
}
|
||||
|
||||
const re = document.body.innerHTML.match(match.regex);
|
||||
if (re === null) {
|
||||
return;
|
||||
}
|
||||
if (redirect) {
|
||||
await Redirect.delete();
|
||||
}
|
||||
|
||||
const url = await match.match(re);
|
||||
|
||||
// send the url to the ff2mpv (https://github.com/woodruffw/ff2mpv) application
|
||||
if (await Other.getFf2mpv()) {
|
||||
await browser.runtime.sendMessage({ action: 'ff2mpv', url: url });
|
||||
}
|
||||
|
||||
if (match.replace && !url.includes('.m3u8')) {
|
||||
const player = document.createElement('video');
|
||||
player.style.width = '100%';
|
||||
player.style.height = '100%';
|
||||
player.controls = true;
|
||||
player.src = url;
|
||||
|
||||
document.body.innerHTML = '';
|
||||
document.body.append(player);
|
||||
} else {
|
||||
window.location.assign(
|
||||
browser.runtime.getURL(
|
||||
`src/entries/player/player.html?id=${match.id}&url=${encodeURIComponent(url)}&domain=${
|
||||
window.location.hostname
|
||||
}`
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
62
src/entries/player/Player.svelte
Normal file
62
src/entries/player/Player.svelte
Normal file
@ -0,0 +1,62 @@
|
||||
<script lang="ts">
|
||||
import { play } from '~/entries/player/player';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
let errorMessage: string | null = null;
|
||||
let videoElem: HTMLVideoElement;
|
||||
|
||||
onMount(async () => {
|
||||
try {
|
||||
await play(videoElem);
|
||||
videoElem.controls = true;
|
||||
} catch (e) {
|
||||
errorMessage = e;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-media-has-caption -->
|
||||
<video id="video" bind:this={videoElem} />
|
||||
{#if errorMessage}
|
||||
<div id="message-container">
|
||||
<p>
|
||||
{@html errorMessage}
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style lang="scss" global>
|
||||
body {
|
||||
background-color: #131313;
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
video {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#message-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
color: white;
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
|
||||
& a,
|
||||
& a:visited {
|
||||
color: inherit;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
</style>
|
16
src/entries/player/player.html
Normal file
16
src/entries/player/player.html
Normal file
@ -0,0 +1,16 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Stream Bypass</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="module">
|
||||
import Player from '~/entries/player/Player.svelte';
|
||||
|
||||
new Player({
|
||||
target: document.body
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
39
src/entries/player/player.ts
Normal file
39
src/entries/player/player.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { matches } from '~/lib/match';
|
||||
import Hls from 'hls.js';
|
||||
|
||||
async function playNative(url: string, videoElem: HTMLVideoElement) {
|
||||
videoElem.src = url;
|
||||
}
|
||||
|
||||
async function playHls(url: string, videoElem: HTMLVideoElement) {
|
||||
if (videoElem.canPlayType('application/vnd.apple.mpegurl')) {
|
||||
videoElem.src = url;
|
||||
} else if (Hls.isSupported()) {
|
||||
const hls = new Hls({
|
||||
enableWorker: false
|
||||
});
|
||||
hls.loadSource(url);
|
||||
hls.attachMedia(videoElem);
|
||||
} else {
|
||||
throw '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>';
|
||||
}
|
||||
}
|
||||
|
||||
export async function play(videoElem: HTMLVideoElement) {
|
||||
const urlQuery = new URLSearchParams(window.location.search);
|
||||
const id = urlQuery.get('id');
|
||||
const url = decodeURIComponent(urlQuery.get('url'));
|
||||
const domain = urlQuery.get('domain');
|
||||
|
||||
const match = matches[id];
|
||||
if (match === undefined) {
|
||||
throw `Invalid id: ${id}. Please report this <a href="https://github.com/ByteDream/stream-bypass/issues">here</a>`;
|
||||
}
|
||||
document.title = `Stream Bypass (${domain})`;
|
||||
|
||||
if (new URL(url).pathname.endsWith('.m3u8')) {
|
||||
await playHls(url, videoElem);
|
||||
} else {
|
||||
await playNative(url, videoElem);
|
||||
}
|
||||
}
|
217
src/entries/popup/Popup.svelte
Normal file
217
src/entries/popup/Popup.svelte
Normal file
@ -0,0 +1,217 @@
|
||||
<script lang="ts">
|
||||
import { matches, Reliability } from '~/lib/match';
|
||||
import { Hosters, Other } from '~/lib/settings';
|
||||
|
||||
let hostersEnabled: boolean;
|
||||
let hosters = [];
|
||||
(async () => {
|
||||
hostersEnabled = !(await Hosters.getAllDisabled());
|
||||
|
||||
const disabled = await Hosters.getDisabled();
|
||||
hosters = Object.values(matches).map((m) => {
|
||||
m['active'] = disabled.findIndex((p) => p.id == m.id) == -1;
|
||||
m['disabled'] = !hostersEnabled;
|
||||
return m;
|
||||
});
|
||||
})();
|
||||
|
||||
let ff2mpvEnabled: boolean;
|
||||
(async () => {
|
||||
ff2mpvEnabled = await Other.getFf2mpv();
|
||||
})();
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<div>
|
||||
<h3 class="header">Hosters</h3>
|
||||
<div class="buttons super-buttons">
|
||||
<button
|
||||
class:active={hostersEnabled}
|
||||
on:click={async () => {
|
||||
await Hosters.enableAll();
|
||||
hostersEnabled = true;
|
||||
hosters = hosters.map((m) => {
|
||||
m['disabled'] = false;
|
||||
return m;
|
||||
});
|
||||
}}>On</button
|
||||
>
|
||||
<button
|
||||
class:active={!hostersEnabled}
|
||||
on:click={async () => {
|
||||
await Hosters.disableAll();
|
||||
hostersEnabled = false;
|
||||
hosters = hosters.map((m) => {
|
||||
m['disabled'] = true;
|
||||
return m;
|
||||
});
|
||||
}}>Off</button
|
||||
>
|
||||
</div>
|
||||
<table class="setting-table">
|
||||
{#each hosters as hoster}
|
||||
<tr>
|
||||
<td class="setting-name">
|
||||
<p
|
||||
class:reliability-low={hoster.reliability === Reliability.LOW}
|
||||
class:reliability-normal={hoster.reliability === Reliability.NORMAL}
|
||||
class:reliability-high={hoster.reliability === Reliability.HIGH}
|
||||
>
|
||||
{hoster.name}
|
||||
</p>
|
||||
</td>
|
||||
<td class="buttons">
|
||||
<button
|
||||
class:disabled={hoster.disabled}
|
||||
class:active={hoster.active}
|
||||
on:click={async () => {
|
||||
if (hoster.disabled) return;
|
||||
await Hosters.enable(hoster);
|
||||
hoster.active = true;
|
||||
}}>On</button
|
||||
>
|
||||
<button
|
||||
class:disabled={hoster.disabled}
|
||||
class:active={!hoster.active}
|
||||
on:click={async () => {
|
||||
if (hoster.disabled) return;
|
||||
await Hosters.disable(hoster);
|
||||
hoster.active = false;
|
||||
}}>Off</button
|
||||
>
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</table>
|
||||
</div>
|
||||
<hr />
|
||||
<div>
|
||||
<h3 class="header">Other</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<td class="setting-name">
|
||||
<p>ff2mpv</p>
|
||||
</td>
|
||||
<td class="buttons">
|
||||
<button
|
||||
class:active={ff2mpvEnabled}
|
||||
on:click={async () => {
|
||||
await Other.setFf2mpv(true);
|
||||
ff2mpvEnabled = true;
|
||||
}}>On</button
|
||||
>
|
||||
<button
|
||||
class:active={!ff2mpvEnabled}
|
||||
on:click={async () => {
|
||||
await Other.setFf2mpv(false);
|
||||
ff2mpvEnabled = false;
|
||||
}}>Off</button
|
||||
>
|
||||
<a
|
||||
href="https://github.com/ByteDream/stream-bypass/tree/master#ff2mpv-use-mpv-to-directly-play-streams"
|
||||
>🛈</a
|
||||
>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<hr />
|
||||
<a id="bug-notice" href="https://github.com/ByteDream/stream-bypass/issues"
|
||||
>Something does not work</a
|
||||
>
|
||||
</main>
|
||||
|
||||
<style lang="scss" global>
|
||||
body {
|
||||
background-color: #2b2a33;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#bug-notice {
|
||||
border: none;
|
||||
color: white;
|
||||
display: block;
|
||||
font-weight: lighter;
|
||||
font-size: 0.8rem;
|
||||
text-align: center;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.settings {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.header {
|
||||
font-size: 16px;
|
||||
margin: 5px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.setting-table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
.setting-name {
|
||||
height: 34px;
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 34px;
|
||||
|
||||
button,
|
||||
a {
|
||||
border: 1px solid #281515;
|
||||
background-color: transparent;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
padding: 5px 8px;
|
||||
margin: 0;
|
||||
text-decoration: none;
|
||||
|
||||
&.active {
|
||||
background-color: rgba(255, 65, 65, 0.74);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
background-color: gray;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
&.super-buttons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.reliability-low {
|
||||
text-decoration: underline;
|
||||
text-decoration-color: red;
|
||||
}
|
||||
.reliability-normal {
|
||||
text-decoration: underline;
|
||||
text-decoration-color: yellow;
|
||||
}
|
||||
.reliability-high {
|
||||
text-decoration: underline;
|
||||
text-decoration-color: #00ff00;
|
||||
}
|
||||
</style>
|
16
src/entries/popup/index.html
Normal file
16
src/entries/popup/index.html
Normal file
@ -0,0 +1,16 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Stream Bypass</title>
|
||||
</head>
|
||||
<body style="width: fit-content; height: 500px">
|
||||
<script type="module">
|
||||
import Popup from '~/entries/popup/Popup.svelte';
|
||||
|
||||
new Popup({
|
||||
target: document.body
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
5
src/entries/popup/main.ts
Normal file
5
src/entries/popup/main.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import App from './Popup.svelte';
|
||||
|
||||
new App({
|
||||
target: document.getElementById('app')
|
||||
});
|
Reference in New Issue
Block a user