mirror of
https://github.com/movie-web/extension.git
synced 2025-09-13 16:53:24 +00:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
6a3d32dcc3 | ||
|
3b88b136e8 | ||
|
67ef3a1e88 | ||
|
302b6ef71c | ||
|
c740bc6685 | ||
|
f49cd01b7a | ||
|
65ff4ab91a | ||
|
a2647a58d6 | ||
|
658f59eb24 |
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@movie-web/extension",
|
"name": "@movie-web/extension",
|
||||||
"displayName": "movie-web extension",
|
"displayName": "movie-web extension",
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"description": "Enhance your movie-web experience with just one click",
|
"description": "Enhance your movie-web experience with just one click",
|
||||||
"author": "movie-web",
|
"author": "movie-web",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@@ -1,6 +1,13 @@
|
|||||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@500;800&display=swap');
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@500;800&display=swap');
|
||||||
|
|
||||||
|
html {
|
||||||
|
min-height: 300px;
|
||||||
|
min-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
min-height: 300px;
|
||||||
|
min-width: 300px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: 'Inter', sans-serif;
|
font-family: 'Inter', sans-serif;
|
||||||
}
|
}
|
||||||
|
@@ -2,9 +2,12 @@ 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 { removeDynamicRules, setDynamicRules } from '~utils/declarativeNetRequest';
|
||||||
import { makeFullUrl } from '~utils/fetcher';
|
import { makeFullUrl } from '~utils/fetcher';
|
||||||
import { assertDomainWhitelist } from '~utils/storage';
|
import { assertDomainWhitelist } from '~utils/storage';
|
||||||
|
|
||||||
|
const MAKE_REQUEST_DYNAMIC_RULE = 23498;
|
||||||
|
|
||||||
export interface Request extends BaseRequest {
|
export interface Request extends BaseRequest {
|
||||||
baseUrl?: string;
|
baseUrl?: string;
|
||||||
headers?: Record<string, string>;
|
headers?: Record<string, string>;
|
||||||
@@ -12,7 +15,8 @@ export interface Request extends BaseRequest {
|
|||||||
query?: Record<string, string>;
|
query?: Record<string, string>;
|
||||||
readHeaders?: Record<string, string>;
|
readHeaders?: Record<string, string>;
|
||||||
url: string;
|
url: string;
|
||||||
body?: string | FormData | URLSearchParams;
|
body?: any;
|
||||||
|
bodyType?: 'string' | 'FormData' | 'URLSearchParams' | 'object';
|
||||||
}
|
}
|
||||||
|
|
||||||
type Response<T> = BaseResponse<{
|
type Response<T> = BaseResponse<{
|
||||||
@@ -24,15 +28,45 @@ type Response<T> = BaseResponse<{
|
|||||||
};
|
};
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
const mapBodyToFetchBody = (body: Request['body'], bodyType: Request['bodyType']): BodyInit => {
|
||||||
|
if (bodyType === 'FormData') {
|
||||||
|
const formData = new FormData();
|
||||||
|
body.forEach(([key, value]) => {
|
||||||
|
formData.append(key, value.toString());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (bodyType === 'URLSearchParams') {
|
||||||
|
return new URLSearchParams(body);
|
||||||
|
}
|
||||||
|
if (bodyType === 'object') {
|
||||||
|
return JSON.stringify(body);
|
||||||
|
}
|
||||||
|
if (bodyType === 'string') {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
return body;
|
||||||
|
};
|
||||||
|
|
||||||
const handler: PlasmoMessaging.MessageHandler<Request, Response<any>> = async (req, res) => {
|
const handler: PlasmoMessaging.MessageHandler<Request, Response<any>> = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
await assertDomainWhitelist(req.sender.tab.url);
|
await assertDomainWhitelist(req.sender.tab.url);
|
||||||
|
|
||||||
|
if (req.body.headers['User-Agent']) {
|
||||||
|
await setDynamicRules({
|
||||||
|
ruleId: MAKE_REQUEST_DYNAMIC_RULE,
|
||||||
|
targetDomains: [new URL(req.body.url).hostname],
|
||||||
|
requestHeaders: {
|
||||||
|
'User-Agent': req.body.headers['User-Agent'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const response = await fetch(makeFullUrl(req.body.url, req.body), {
|
const response = await fetch(makeFullUrl(req.body.url, req.body), {
|
||||||
method: req.body.method,
|
method: req.body.method,
|
||||||
headers: req.body.headers,
|
headers: req.body.headers,
|
||||||
body: req.body.body,
|
body: mapBodyToFetchBody(req.body.body, req.body.bodyType),
|
||||||
});
|
});
|
||||||
|
await removeDynamicRules([MAKE_REQUEST_DYNAMIC_RULE]);
|
||||||
const contentType = response.headers.get('content-type');
|
const contentType = response.headers.get('content-type');
|
||||||
const body = contentType?.includes('application/json') ? await response.json() : await response.text();
|
const body = contentType?.includes('application/json') ? await response.json() : await response.text();
|
||||||
|
|
||||||
|
@@ -2,7 +2,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 { isChrome } from '~utils/extension';
|
import { setDynamicRules } from '~utils/declarativeNetRequest';
|
||||||
import { assertDomainWhitelist } from '~utils/storage';
|
import { assertDomainWhitelist } from '~utils/storage';
|
||||||
|
|
||||||
interface Request extends BaseRequest {
|
interface Request extends BaseRequest {
|
||||||
@@ -13,108 +13,10 @@ interface Request extends BaseRequest {
|
|||||||
responseHeaders?: Record<string, string>;
|
responseHeaders?: Record<string, string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapHeadersToDeclarativeNetRequestHeaders = (
|
|
||||||
headers: Record<string, string>,
|
|
||||||
op: string,
|
|
||||||
): { header: string; operation: any; value: string }[] => {
|
|
||||||
return Object.entries(headers).map(([name, value]) => ({
|
|
||||||
header: name,
|
|
||||||
operation: op,
|
|
||||||
value,
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
const handler: PlasmoMessaging.MessageHandler<Request, BaseResponse> = async (req, res) => {
|
const handler: PlasmoMessaging.MessageHandler<Request, BaseResponse> = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
await assertDomainWhitelist(req.sender.tab.url);
|
await assertDomainWhitelist(req.sender.tab.url);
|
||||||
if (isChrome()) {
|
await setDynamicRules(req.body);
|
||||||
await chrome.declarativeNetRequest.updateDynamicRules({
|
|
||||||
removeRuleIds: [req.body.ruleId],
|
|
||||||
addRules: [
|
|
||||||
{
|
|
||||||
id: req.body.ruleId,
|
|
||||||
condition: {
|
|
||||||
...(req.body.targetDomains && { requestDomains: req.body.targetDomains }),
|
|
||||||
...(req.body.targetRegex && { regexFilter: req.body.targetRegex }),
|
|
||||||
},
|
|
||||||
action: {
|
|
||||||
type: chrome.declarativeNetRequest.RuleActionType.MODIFY_HEADERS,
|
|
||||||
...(req.body.requestHeaders && Object.keys(req.body.requestHeaders).length > 0
|
|
||||||
? {
|
|
||||||
requestHeaders: mapHeadersToDeclarativeNetRequestHeaders(
|
|
||||||
req.body.requestHeaders,
|
|
||||||
chrome.declarativeNetRequest.HeaderOperation.SET,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
: {}),
|
|
||||||
responseHeaders: [
|
|
||||||
{
|
|
||||||
header: 'Access-Control-Allow-Origin',
|
|
||||||
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
|
|
||||||
value: '*',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Access-Control-Allow-Methods',
|
|
||||||
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
|
|
||||||
value: 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Access-Control-Allow-Headers',
|
|
||||||
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
|
|
||||||
value: '*',
|
|
||||||
},
|
|
||||||
...mapHeadersToDeclarativeNetRequestHeaders(
|
|
||||||
req.body.responseHeaders ?? {},
|
|
||||||
chrome.declarativeNetRequest.HeaderOperation.SET,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
if (chrome.runtime.lastError?.message) throw new Error(chrome.runtime.lastError.message);
|
|
||||||
} else {
|
|
||||||
await browser.declarativeNetRequest.updateDynamicRules({
|
|
||||||
removeRuleIds: [req.body.ruleId],
|
|
||||||
addRules: [
|
|
||||||
{
|
|
||||||
id: req.body.ruleId,
|
|
||||||
condition: {
|
|
||||||
...(req.body.targetDomains && { requestDomains: req.body.targetDomains }),
|
|
||||||
...(req.body.targetRegex && { regexFilter: req.body.targetRegex }),
|
|
||||||
},
|
|
||||||
action: {
|
|
||||||
type: 'modifyHeaders',
|
|
||||||
...(req.body.requestHeaders && Object.keys(req.body.requestHeaders).length > 0
|
|
||||||
? {
|
|
||||||
requestHeaders: mapHeadersToDeclarativeNetRequestHeaders(req.body.requestHeaders, 'set'),
|
|
||||||
}
|
|
||||||
: {}),
|
|
||||||
responseHeaders: [
|
|
||||||
{
|
|
||||||
header: 'Access-Control-Allow-Origin',
|
|
||||||
operation: 'set',
|
|
||||||
value: '*',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Access-Control-Allow-Methods',
|
|
||||||
operation: 'set',
|
|
||||||
value: 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Access-Control-Allow-Headers',
|
|
||||||
operation: 'set',
|
|
||||||
value: '*',
|
|
||||||
},
|
|
||||||
...mapHeadersToDeclarativeNetRequestHeaders(req.body.responseHeaders ?? {}, 'set'),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
if (browser.runtime.lastError?.message) throw new Error(browser.runtime.lastError.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
res.send({
|
res.send({
|
||||||
success: true,
|
success: true,
|
||||||
});
|
});
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
.frame {
|
.frame {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
background-color: #0a080e;
|
background-color: #0a080e;
|
||||||
background-image: radial-gradient(271.48% 132.05% at 136.13% 65.62%, #271945b3 0%, #1c1c2c00 100%), radial-gradient(671.15% 123.02% at 76.68% -34.38%, #272753 0%, #17172000 100%);
|
background-image: radial-gradient(271.48% 132.05% at 136.13% 65.62%, #271945b3 0%, #1c1c2c00 100%), radial-gradient(671.15% 123.02% at 76.68% -34.38%, #272753 0%, #17172000 100%);
|
||||||
}
|
}
|
@@ -7,9 +7,5 @@ export interface FrameProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function Frame(props: FrameProps) {
|
export function Frame(props: FrameProps) {
|
||||||
return (
|
return <div className="frame">{props.children}</div>;
|
||||||
<div className="frame" style={{ width: 300, height: 300 }}>
|
|
||||||
{props.children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
117
src/utils/declarativeNetRequest.ts
Normal file
117
src/utils/declarativeNetRequest.ts
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
import { isChrome } from './extension';
|
||||||
|
|
||||||
|
interface DynamicRule {
|
||||||
|
ruleId: number;
|
||||||
|
targetDomains?: [string, ...string[]];
|
||||||
|
targetRegex?: string;
|
||||||
|
requestHeaders?: Record<string, string>;
|
||||||
|
responseHeaders?: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapHeadersToDeclarativeNetRequestHeaders = (
|
||||||
|
headers: Record<string, string>,
|
||||||
|
op: string,
|
||||||
|
): { header: string; operation: any; value: string }[] => {
|
||||||
|
return Object.entries(headers).map(([name, value]) => ({
|
||||||
|
header: name,
|
||||||
|
operation: op,
|
||||||
|
value,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const setDynamicRules = async (body: DynamicRule) => {
|
||||||
|
if (isChrome()) {
|
||||||
|
await chrome.declarativeNetRequest.updateDynamicRules({
|
||||||
|
removeRuleIds: [body.ruleId],
|
||||||
|
addRules: [
|
||||||
|
{
|
||||||
|
id: body.ruleId,
|
||||||
|
condition: {
|
||||||
|
...(body.targetDomains && { requestDomains: body.targetDomains }),
|
||||||
|
...(body.targetRegex && { regexFilter: body.targetRegex }),
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: chrome.declarativeNetRequest.RuleActionType.MODIFY_HEADERS,
|
||||||
|
...(body.requestHeaders && Object.keys(body.requestHeaders).length > 0
|
||||||
|
? {
|
||||||
|
requestHeaders: mapHeadersToDeclarativeNetRequestHeaders(
|
||||||
|
body.requestHeaders,
|
||||||
|
chrome.declarativeNetRequest.HeaderOperation.SET,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
responseHeaders: [
|
||||||
|
{
|
||||||
|
header: 'Access-Control-Allow-Origin',
|
||||||
|
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
|
||||||
|
value: '*',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: 'Access-Control-Allow-Methods',
|
||||||
|
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
|
||||||
|
value: 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: 'Access-Control-Allow-Headers',
|
||||||
|
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
|
||||||
|
value: '*',
|
||||||
|
},
|
||||||
|
...mapHeadersToDeclarativeNetRequestHeaders(
|
||||||
|
body.responseHeaders ?? {},
|
||||||
|
chrome.declarativeNetRequest.HeaderOperation.SET,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
if (chrome.runtime.lastError?.message) throw new Error(chrome.runtime.lastError.message);
|
||||||
|
} else {
|
||||||
|
await browser.declarativeNetRequest.updateDynamicRules({
|
||||||
|
removeRuleIds: [body.ruleId],
|
||||||
|
addRules: [
|
||||||
|
{
|
||||||
|
id: body.ruleId,
|
||||||
|
condition: {
|
||||||
|
...(body.targetDomains && { requestDomains: body.targetDomains }),
|
||||||
|
...(body.targetRegex && { regexFilter: body.targetRegex }),
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: 'modifyHeaders',
|
||||||
|
...(body.requestHeaders && Object.keys(body.requestHeaders).length > 0
|
||||||
|
? {
|
||||||
|
requestHeaders: mapHeadersToDeclarativeNetRequestHeaders(body.requestHeaders, 'set'),
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
responseHeaders: [
|
||||||
|
{
|
||||||
|
header: 'Access-Control-Allow-Origin',
|
||||||
|
operation: 'set',
|
||||||
|
value: '*',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: 'Access-Control-Allow-Methods',
|
||||||
|
operation: 'set',
|
||||||
|
value: 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: 'Access-Control-Allow-Headers',
|
||||||
|
operation: 'set',
|
||||||
|
value: '*',
|
||||||
|
},
|
||||||
|
...mapHeadersToDeclarativeNetRequestHeaders(body.responseHeaders ?? {}, 'set'),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
if (browser.runtime.lastError?.message) throw new Error(browser.runtime.lastError.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const removeDynamicRules = async (ruleIds: number[]) => {
|
||||||
|
await (chrome || browser).declarativeNetRequest.updateDynamicRules({
|
||||||
|
removeRuleIds: ruleIds,
|
||||||
|
});
|
||||||
|
if ((chrome || browser).runtime.lastError?.message) throw new Error((chrome || browser).runtime.lastError.message);
|
||||||
|
};
|
Reference in New Issue
Block a user