mirror of
https://github.com/sussy-code/browser-ext.git
synced 2026-07-27 05:32:07 +00:00
Compare commits
11 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20c7342dc0 | ||
|
|
cd2ecdb6b6 | ||
|
|
e6756d25f8 | ||
|
|
fa1e42eab1 | ||
|
|
af263c1f70 | ||
|
|
0a55847ce0 | ||
|
|
4c724ff9c9 | ||
|
|
1f214dddb3 | ||
|
|
9f146d2032 | ||
|
|
8a9b689a92 | ||
|
|
e1b943bdc1 |
16 changed files with 5555 additions and 4421 deletions
2
.github/CODE_OF_CONDUCT.md
vendored
2
.github/CODE_OF_CONDUCT.md
vendored
|
|
@ -1 +1 @@
|
||||||
Please visit the [main document at primary repository](https://github.com/movie-web/movie-web/blob/dev/.github/CODE_OF_CONDUCT.md).
|
Please visit the [main document at primary repository](https://github.com/sussy-code/smov/blob/dev/.github/CODE_OF_CONDUCT.md).
|
||||||
|
|
|
||||||
2
.github/CONTRIBUTING.md
vendored
2
.github/CONTRIBUTING.md
vendored
|
|
@ -1 +1 @@
|
||||||
Please visit the [main document at primary repository](https://github.com/movie-web/movie-web/blob/dev/.github/CONTRIBUTING.md).
|
Please visit the [main document at primary repository](https://github.com/sussy-code/smov/blob/dev/.github/CONTRIBUTING.md).
|
||||||
|
|
|
||||||
6
.github/SECURITY.md
vendored
6
.github/SECURITY.md
vendored
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
## Supported Versions
|
## Supported Versions
|
||||||
|
|
||||||
The latest version of movie-web is the only version that is supported, as it is the only version that is being actively developed.
|
The latest version of sudo-flix is the only version that is supported, as it is the only version that is being actively developed.
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
You can contact the movie-web maintainers to report a vulnerability:
|
You can contact the sudo-flix maintainers to report a vulnerability:
|
||||||
- Report the vulnerability in the [movie-web Discord server](https://movie-web.github.io/links/discord)
|
- Report the vulnerability in the [Discord server](https://discord.gg/g742e7Mu2W)
|
||||||
|
|
|
||||||
6
.github/pull_request_template.md
vendored
6
.github/pull_request_template.md
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
This pull request resolves #XXX
|
This pull request resolves #XXX
|
||||||
|
|
||||||
- [ ] I have read and agreed to the [code of conduct](https://github.com/movie-web/movie-web/blob/dev/.github/CODE_OF_CONDUCT.md).
|
- [ ] I have read and agreed to the [code of conduct](https://github.com/sussy-code/smov/blob/dev/.github/CODE_OF_CONDUCT.md).
|
||||||
- [ ] I have read and complied with the [contributing guidelines](https://github.com/movie-web/movie-web/blob/dev/.github/CONTRIBUTING.md).
|
- [ ] I have read and complied with the [contributing guidelines](https://github.com/sussy-code/smov/blob/dev/.github/CONTRIBUTING.md).
|
||||||
- [ ] What I'm implementing was assigned to me and is an [approved issue](https://github.com/movie-web/movie-web/issues?q=is%3Aopen+is%3Aissue+label%3Aapproved). For reference, please take a look at our [GitHub projects](https://github.com/movie-web/movie-web/projects).
|
- [ ] What I'm implementing was assigned to me and is an [approved issue](https://github.com/sussy-code/smov/issues?q=is%3Aopen+is%3Aissue+label%3Aapproved). For reference, please take a look at our [GitHub projects](https://github.com/sussy-code/smov/projects).
|
||||||
- [ ] I have tested all of my changes.
|
- [ ] I have tested all of my changes.
|
||||||
|
|
|
||||||
2
LICENSE
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2023 movie-web
|
Copyright (c) 2023 sudo-flix
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# extension
|
# extension
|
||||||
|
|
||||||
Enhance your movie-web experience with just one click
|
Enhance your experience with just one click
|
||||||
|
|
||||||
## Running for development
|
## Running for development
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
"optional_host_permissions": [ "\u003Call_urls>" ],
|
"optional_host_permissions": [ "\u003Call_urls>" ],
|
||||||
"permissions": [ "storage", "declarativeNetRequest", "activeTab", "cookies" ],
|
"permissions": [ "storage", "declarativeNetRequest", "activeTab", "cookies" ],
|
||||||
"update_url": "https://clients2.google.com/service/update2/crx",
|
"update_url": "https://clients2.google.com/service/update2/crx",
|
||||||
"version": "1.1.4",
|
"version": "1.2.0",
|
||||||
"web_accessible_resources": [ {
|
"web_accessible_resources": [ {
|
||||||
"matches": [ "\u003Call_urls>" ],
|
"matches": [ "\u003Call_urls>" ],
|
||||||
"resources": [ "assets/active.png", "assets/inactive.png" ]
|
"resources": [ "assets/active.png", "assets/inactive.png" ]
|
||||||
|
|
|
||||||
26
package.json
26
package.json
|
|
@ -1,9 +1,9 @@
|
||||||
{
|
{
|
||||||
"name": "@movie-web/extension",
|
"name": "@movie-web/extension",
|
||||||
"displayName": "movie-web extension",
|
"displayName": "sudo-flix extension",
|
||||||
"version": "1.1.4",
|
"version": "1.2.0",
|
||||||
"description": "Enhance your movie-web experience with just one click",
|
"description": "Enhance your streaming experience with just one click",
|
||||||
"author": "movie-web",
|
"author": "sudo-flix",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "plasmo dev",
|
"dev": "plasmo dev",
|
||||||
"build": "plasmo build",
|
"build": "plasmo build",
|
||||||
|
|
@ -16,28 +16,28 @@
|
||||||
"preinstall": "npx -y only-allow pnpm"
|
"preinstall": "npx -y only-allow pnpm"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@plasmohq/messaging": "^0.6.1",
|
"@plasmohq/messaging": "^0.6.2",
|
||||||
"@plasmohq/storage": "^1.9.0",
|
"@plasmohq/storage": "^1.11.0",
|
||||||
"plasmo": "0.84.0",
|
"plasmo": "0.84.0",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0"
|
"react-dom": "18.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/chrome": "0.0.251",
|
"@types/chrome": "0.0.251",
|
||||||
"@types/firefox-webext-browser": "^120.0.0",
|
"@types/firefox-webext-browser": "^120.0.4",
|
||||||
"@types/node": "20.9.0",
|
"@types/node": "20.9.0",
|
||||||
"@types/react": "18.2.37",
|
"@types/react": "18.2.37",
|
||||||
"@types/react-dom": "18.2.15",
|
"@types/react-dom": "18.2.15",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.15.0",
|
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
||||||
"@typescript-eslint/parser": "^6.15.0",
|
"@typescript-eslint/parser": "^6.21.0",
|
||||||
"eslint": "^8.56.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-config-airbnb": "^19.0.4",
|
"eslint-config-airbnb": "^19.0.4",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-import-resolver-typescript": "^3.6.1",
|
"eslint-import-resolver-typescript": "^3.6.1",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.29.1",
|
||||||
"eslint-plugin-prettier": "^5.1.1",
|
"eslint-plugin-prettier": "^5.2.1",
|
||||||
"eslint-plugin-react": "^7.33.2",
|
"eslint-plugin-react": "^7.35.0",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.2",
|
||||||
"prettier": "3.0.3",
|
"prettier": "3.0.3",
|
||||||
"typescript": "5.2.2"
|
"typescript": "5.2.2"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
9846
pnpm-lock.yaml
9846
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
|
|
@ -5,7 +5,7 @@ import type { BaseResponse } from '~types/response';
|
||||||
import { removeDynamicRules, setDynamicRules } from '~utils/declarativeNetRequest';
|
import { removeDynamicRules, setDynamicRules } from '~utils/declarativeNetRequest';
|
||||||
import { isFirefox } from '~utils/extension';
|
import { isFirefox } from '~utils/extension';
|
||||||
import { makeFullUrl } from '~utils/fetcher';
|
import { makeFullUrl } from '~utils/fetcher';
|
||||||
import { assertDomainWhitelist } from '~utils/storage';
|
import { assertDomainWhitelist, canAccessCookies } from '~utils/storage';
|
||||||
|
|
||||||
const MAKE_REQUEST_DYNAMIC_RULE = 23498;
|
const MAKE_REQUEST_DYNAMIC_RULE = 23498;
|
||||||
|
|
||||||
|
|
@ -60,6 +60,12 @@ const handler: PlasmoMessaging.MessageHandler<Request, Response<any>> = async (r
|
||||||
ruleId: MAKE_REQUEST_DYNAMIC_RULE,
|
ruleId: MAKE_REQUEST_DYNAMIC_RULE,
|
||||||
targetDomains: [new URL(url).hostname],
|
targetDomains: [new URL(url).hostname],
|
||||||
requestHeaders: req.body.headers,
|
requestHeaders: req.body.headers,
|
||||||
|
// set Access-Control-Allow-Credentials if the reqested host has access to cookies
|
||||||
|
responseHeaders: {
|
||||||
|
...(canAccessCookies(new URL(url).hostname) && {
|
||||||
|
'Access-Control-Allow-Credentials': 'true',
|
||||||
|
}),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
|
|
@ -84,7 +90,10 @@ const handler: PlasmoMessaging.MessageHandler<Request, Response<any>> = async (r
|
||||||
statusCode: response.status,
|
statusCode: response.status,
|
||||||
headers: {
|
headers: {
|
||||||
...Object.fromEntries(response.headers.entries()),
|
...Object.fromEntries(response.headers.entries()),
|
||||||
'Set-Cookie': cookies.map((cookie) => `${cookie.name}=${cookie.value}`).join(', '),
|
// include cookies if allowed for the reqested host
|
||||||
|
...(canAccessCookies(new URL(url).hostname) && {
|
||||||
|
'Set-Cookie': cookies.map((cookie) => `${cookie.name}=${cookie.value}`).join(', '),
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
body,
|
body,
|
||||||
finalUrl: response.url,
|
finalUrl: response.url,
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import type { PlasmoMessaging } from '@plasmohq/messaging';
|
||||||
import type { BaseRequest } from '~types/request';
|
import type { BaseRequest } from '~types/request';
|
||||||
import type { BaseResponse } from '~types/response';
|
import type { BaseResponse } from '~types/response';
|
||||||
import { setDynamicRules } from '~utils/declarativeNetRequest';
|
import { setDynamicRules } from '~utils/declarativeNetRequest';
|
||||||
import { assertDomainWhitelist } from '~utils/storage';
|
import { assertDomainWhitelist, modifiableResponseHeaders } from '~utils/storage';
|
||||||
|
|
||||||
interface Request extends BaseRequest {
|
interface Request extends BaseRequest {
|
||||||
ruleId: number;
|
ruleId: number;
|
||||||
|
|
@ -18,6 +18,17 @@ const handler: PlasmoMessaging.MessageHandler<Request, BaseResponse> = async (re
|
||||||
if (!req.sender?.tab?.url) throw new Error('No tab URL found in the request.');
|
if (!req.sender?.tab?.url) throw new Error('No tab URL found in the request.');
|
||||||
if (!req.body) throw new Error('No request body found in the request.');
|
if (!req.body) throw new Error('No request body found in the request.');
|
||||||
|
|
||||||
|
// restrict what response headers can be modified
|
||||||
|
req.body.responseHeaders = Object.keys(req.body.responseHeaders ?? {})
|
||||||
|
.filter((key) => modifiableResponseHeaders.includes(key.toLowerCase()))
|
||||||
|
.reduce(
|
||||||
|
(obj, key) => {
|
||||||
|
obj[key] = (req.body?.responseHeaders ?? {})[key];
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
|
{} as Record<string, string>,
|
||||||
|
);
|
||||||
|
|
||||||
await assertDomainWhitelist(req.sender.tab.url);
|
await assertDomainWhitelist(req.sender.tab.url);
|
||||||
await setDynamicRules(req.body);
|
await setDynamicRules(req.body);
|
||||||
res.send({
|
res.send({
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ export function BottomLabel() {
|
||||||
<h3 className="bottom-label">
|
<h3 className="bottom-label">
|
||||||
{version}
|
{version}
|
||||||
<div className="dot" />
|
<div className="dot" />
|
||||||
movie-web
|
sudo-flix
|
||||||
</h3>
|
</h3>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ export function DisabledScreen() {
|
||||||
<Icon name="warningCircle" />
|
<Icon name="warningCircle" />
|
||||||
</div>
|
</div>
|
||||||
<p>
|
<p>
|
||||||
The <strong>movie-web extension</strong> can not be used on this page
|
The <strong>sudo-flix extension</strong> can not be used on this page
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ export default function PermissionRequest() {
|
||||||
We need some <br /> browser permissions
|
We need some <br /> browser permissions
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-color paragraph">
|
<p className="text-color paragraph">
|
||||||
We don't like it either, but the movie-web extension needs quite a few permissions to function. Listed
|
We don't like it either, but the sudo-flix extension needs quite a few permissions to function. Listed
|
||||||
below is an explanation for all permissions we need.
|
below is an explanation for all permissions we need.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
@ -41,7 +41,7 @@ export default function PermissionRequest() {
|
||||||
purple
|
purple
|
||||||
icon={<Icon name="github" />}
|
icon={<Icon name="github" />}
|
||||||
right={
|
right={
|
||||||
<Button type="secondary" href="https://github.com/movie-web/extension">
|
<Button type="secondary" href="https://github.com/sussy-code/browser-ext">
|
||||||
Read source code
|
Read source code
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +66,7 @@ export default function PermissionRequest() {
|
||||||
<h3>Network Requests</h3>
|
<h3>Network Requests</h3>
|
||||||
<p className="text-color paragraph">
|
<p className="text-color paragraph">
|
||||||
This permission allows the extension to instruct the browser how to request data from sites. In more
|
This permission allows the extension to instruct the browser how to request data from sites. In more
|
||||||
technical terms, this allows movie-web to modify HTTP headers that it wouldn't normally be allowed
|
technical terms, this allows sudo-flix to modify HTTP headers that it wouldn't normally be allowed
|
||||||
to.
|
to.
|
||||||
</p>
|
</p>
|
||||||
<p className="text-color paragraph">
|
<p className="text-color paragraph">
|
||||||
|
|
@ -76,7 +76,8 @@ export default function PermissionRequest() {
|
||||||
<Card icon={<Icon name="cookie" />}>
|
<Card icon={<Icon name="cookie" />}>
|
||||||
<h3>Read and write cookies</h3>
|
<h3>Read and write cookies</h3>
|
||||||
<p className="text-color paragraph">
|
<p className="text-color paragraph">
|
||||||
Some sources use cookies for authentication. We need to be able to read and set those cookies.
|
Some sources use cookies for authentication. We need to be able to read and set those cookies. The
|
||||||
|
extension will only be able to accees the cookies for a few sites we scrape.
|
||||||
</p>
|
</p>
|
||||||
<p className="text-color paragraph">
|
<p className="text-color paragraph">
|
||||||
You won't be prompted for this permission, it's included in “Read & change data from all sites”.
|
You won't be prompted for this permission, it's included in “Read & change data from all sites”.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { isChrome } from './extension';
|
import { isChrome } from './extension';
|
||||||
|
import { modifiableResponseHeaders } from './storage';
|
||||||
|
|
||||||
interface DynamicRule {
|
interface DynamicRule {
|
||||||
ruleId: number;
|
ruleId: number;
|
||||||
|
|
@ -56,11 +57,6 @@ export const setDynamicRules = async (body: DynamicRule) => {
|
||||||
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
|
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
|
||||||
value: '*',
|
value: '*',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
header: 'Access-Control-Allow-Credentials',
|
|
||||||
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
|
|
||||||
value: 'true',
|
|
||||||
},
|
|
||||||
...mapHeadersToDeclarativeNetRequestHeaders(
|
...mapHeadersToDeclarativeNetRequestHeaders(
|
||||||
body.responseHeaders ?? {},
|
body.responseHeaders ?? {},
|
||||||
chrome.declarativeNetRequest.HeaderOperation.SET,
|
chrome.declarativeNetRequest.HeaderOperation.SET,
|
||||||
|
|
@ -104,11 +100,6 @@ export const setDynamicRules = async (body: DynamicRule) => {
|
||||||
operation: 'set',
|
operation: 'set',
|
||||||
value: '*',
|
value: '*',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
header: 'Access-Control-Allow-Credentials',
|
|
||||||
operation: 'set',
|
|
||||||
value: 'true',
|
|
||||||
},
|
|
||||||
...mapHeadersToDeclarativeNetRequestHeaders(body.responseHeaders ?? {}, 'set'),
|
...mapHeadersToDeclarativeNetRequestHeaders(body.responseHeaders ?? {}, 'set'),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,32 @@ import { useStorage } from '@plasmohq/storage/hook';
|
||||||
|
|
||||||
import { makeUrlIntoDomain } from '~utils/domains';
|
import { makeUrlIntoDomain } from '~utils/domains';
|
||||||
|
|
||||||
export const DEFAULT_DOMAIN_WHITELIST = [
|
export const DEFAULT_DOMAIN_WHITELIST = [];
|
||||||
'mw.lonelil.ru',
|
|
||||||
'watch.qtchaos.de',
|
export const modifiableResponseHeaders = [
|
||||||
'bmov.app',
|
'access-control-allow-origin',
|
||||||
'bmov.vercel.app',
|
'access-control-allow-methods',
|
||||||
'stream.thehairy.me',
|
'access-control-allow-headers',
|
||||||
'scootydooter.vercel.app',
|
'content-security-policy',
|
||||||
'movie-web-me.vercel.app',
|
'content-security-policy-report-only',
|
||||||
|
'content-disposition',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const hostsWithCookiesAccess: RegExp[] = [
|
||||||
|
/^(?:.*\.)?ee3\.me$/,
|
||||||
|
/^(?:.*\.)?rips\.cc$/,
|
||||||
|
/^(?:.*\.)?m4ufree\.(?:tv|to|pw)$/,
|
||||||
|
/^(?:.*\.)?goojara\.to$/,
|
||||||
|
/^(?:.*\.)?levidia\.ch$/,
|
||||||
|
/^(?:.*\.)?wootly\.ch$/,
|
||||||
|
/^(?:.*\.)?multimovies\.(?:sbs|online|cloud)$/,
|
||||||
|
];
|
||||||
|
|
||||||
|
export function canAccessCookies(host: string): boolean {
|
||||||
|
if (hostsWithCookiesAccess.some((regex) => regex.test(host))) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
export const storage = new Storage();
|
export const storage = new Storage();
|
||||||
|
|
||||||
const getDomainWhiteList = async () => {
|
const getDomainWhiteList = async () => {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue