Compare commits

..

13 commits
1.3.2 ... main

Author SHA1 Message Date
Pas
775a1dbea4
Update README with safety information
Added safety section to clarify extension usage and privacy.
2025-12-07 22:07:06 -07:00
Pas
555a260e10
Revise README for P-Stream Extension details
Updated README to provide detailed information about the P-Stream Extension, its functionality, and safety measures.
2025-12-07 22:04:00 -07:00
Pas
0f85396bda Update package.json 2025-12-07 14:06:30 -07:00
Pas
920396521a Update package.json 2025-11-14 12:12:25 -07:00
Pas
1473ad357c Update package.json 2025-11-13 10:04:45 -07:00
Pas
21d46078b6 bump version 2025-11-07 19:29:16 -07:00
Pas
543bd8b0c2 add github link to popup 2025-11-07 19:29:10 -07:00
Pas
27615ac512 bump version 2025-11-07 19:16:53 -07:00
Pas
8f2b94f50d update packages 2025-11-07 19:08:54 -07:00
Pas
58af0ea837
Update README.md 2025-11-07 13:54:13 -07:00
Pas
3e3d108293 Update manifest.json 2025-10-29 22:59:24 -06:00
Pas
9f5d127111
Update LICENSE 2025-10-06 12:58:58 -06:00
Pas
07fdf769ce update uuid again 2025-09-07 12:43:52 -06:00
12 changed files with 2753 additions and 2527 deletions

View file

@ -7,7 +7,7 @@ module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: './tsconfig.json',
tsconfigRootDir: './',
tsconfigRootDir: __dirname,
},
settings: {
'import/resolver': {

View file

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2023 P-Stream
Copyright (c) 2023 movie-web
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View file

@ -1,6 +1,42 @@
# extension
# P-Stream Extension
Enhance your experience with just one click
Enhance your experience with just one click!
## About
The extension is an optional "plugin" for P-Stream (and all movie-web forks) that adds a more sources that usually yield a better-quality stream!
In simple terms: it acts as a local proxy. Imagine it opens an invisible tab to extract (scrape) the stream from the desired website. The only difference is that the extension can send specific headers, cookies, and is locally based. Some sources have restrictions that block scrapers; the extension helps us bypass that, such as IP restrictions, where the stream needs to be loaded on the same IP that it was originally scraped from.
In more complex terms: It uses the declarativeNetRequest API to connect to third party sites and fetch their html content. Because browsers have Cross Origin Resource Security (CORS) that protects sites from fetching content from other sites, a proxy is needed. This extension acts as a local proxy to bypass CORS and fetch the content.
During the onboarding process (/onboarding) the user can select between 3 options:
- Extension - This gives the user the most sources —sometimes with the best quality. (This extension)
- Custom Proxy - The user can host their own remote proxy on a service like Netlify to bypass restrictions, however, it can't do everything the extension can.
- Default Setup - This is the default and requires no user action, just pick it and watch. The site comes with default proxies already configured. The downsides are you are sharing bandwidth with other users and there are fewer sources.
### Why does the extension ask to "Access Data on All Sites"?
- This project (movie-web) is designed to be 100% self-hostable and is completely open-source. Hard coding a set list of sites that it asks for permission would prevent the extension from working on self-hosted sites. The user would need to edit the code to manually add their site to the permission list.
- Because we scrape from many sites, it would be tedious to allow every site.
## Safety
- It's **not required** to use P-Stream, it's entirely optional.
- It doesn't track the user in any way or send data to any site besides the site you intend to use it with.
- **All of the code is open-source and anyone can inspect it.**
- The extension **must** be enabled on a per site basis, otherwise the connecting site cannot talk to the extension (using runtime.sendMessage).
> Previously offical sites were hardcoded to automatically be enabled on, but due to concerns about how this could be abused, that has been removed. **We do not believe this was ever exploited.**
### Will this ever work with Safari?
TL:DR: No, Apple's restrictions make it impossible currently.
1. Problem's with WebKits declarativeNetRequest API:
The extension is a local CORS proxy used to change request headers so we can scrape content. However, WebKits implementation is “incomplete”… Half of the headers that we need to change, simply dont work because Apple has blacklisted many, and some are simply half-baked. https://bugs.webkit.org/show_bug.cgi?id=290922
2. Orion (A Webkit browser with extension support) had 2 issues:
Firstly, Orion is using WebKits DNR API, which is the main problem. Technically its possible for them to use Firefoxs for example, but it hasnt been done yet. Secondly, the runtime.sendMessage API is currently broken in Orion. So the extension literally cannot talk to the website and vice verca.
https://orionfeedback.org/d/8053-extensions-support-for-declarativenetrequest-redirects/11
These can both be fixed, and Im surprised WebKits APIs are so under-baked but it is what it is.
## Running for development
@ -10,3 +46,13 @@ We use pnpm with the latest version of NodeJS.
pnpm i
pnpm dev
```
## Building for production
```sh
pnpm i
pnpm build
or
pnpm build:firefox
```

View file

@ -4,7 +4,7 @@
"optional_host_permissions": ["\u003Call_urls>"],
"permissions": ["storage", "declarativeNetRequest", "activeTab", "cookies"],
"update_url": "https://clients2.google.com/service/update2/crx",
"version": "1.2.0",
"version": "${version}",
"web_accessible_resources": [
{
"matches": ["\u003Call_urls>"],

View file

@ -1,7 +1,7 @@
{
"name": "@movie-web/extension",
"name": "@p-stream/extension",
"displayName": "P-Stream extension",
"version": "1.3.2",
"version": "1.3.7",
"description": "Enhance your streaming experience with just one click",
"author": "P-Stream",
"scripts": {
@ -9,37 +9,38 @@
"build": "plasmo build",
"build:firefox": "plasmo build --target=firefox-mv3",
"package": "plasmo package",
"package:firefox": "plasmo package --target=firefox-mv3",
"package:firefox": "npm run build:firefox && plasmo package --target=firefox-mv3 && mv build/firefox-mv3-prod.zip build/firefox-mv3-prod.xpi",
"lint": "eslint --ext .tsx,.ts src",
"lint:fix": "eslint --fix --ext .tsx,.ts src",
"lint:report": "eslint --ext .tsx,.ts --output-file eslint_report.json --format json src",
"preinstall": "npx -y only-allow pnpm"
},
"dependencies": {
"@plasmohq/messaging": "^0.6.2",
"@plasmohq/storage": "^1.11.0",
"plasmo": "0.89.4",
"react": "18.2.0",
"react-dom": "18.2.0"
"@plasmohq/messaging": "^0.7.2",
"@plasmohq/storage": "^1.15.0",
"react": "19.2.0",
"react-dom": "19.2.0",
"sharp": "^0.34.5"
},
"devDependencies": {
"@types/chrome": "0.0.251",
"@types/firefox-webext-browser": "^120.0.4",
"@types/node": "20.9.0",
"@types/react": "18.2.37",
"@types/react-dom": "18.2.15",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"eslint": "^8.57.0",
"@types/chrome": "0.1.27",
"@types/firefox-webext-browser": "^120.0.5",
"@types/node": "24.10.0",
"@types/react": "19.2.2",
"@types/react-dom": "19.2.2",
"@typescript-eslint/eslint-plugin": "^8.46.3",
"@typescript-eslint/parser": "^8.46.3",
"eslint": "^8.57.1",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.35.0",
"eslint-plugin-react-hooks": "^4.6.2",
"prettier": "3.0.3",
"typescript": "5.2.2"
"eslint-config-prettier": "^10.1.8",
"eslint-import-resolver-typescript": "^3.10.1",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-prettier": "^5.5.4",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.0.1",
"plasmo": "0.90.5",
"prettier": "3.6.2",
"typescript": "5.9.3"
},
"manifest": {
"permissions": [
@ -52,10 +53,24 @@
],
"browser_specific_settings": {
"gecko": {
"id": "{0c3fcdbd-5e0f-40d5-8f6c-d5eef8ff2b7c}"
"id": "{e613be14-63c3-4bd9-8a4a-502c12bcf201}",
"data_collection_permissions": {
"required": [
"browsingActivity",
"authenticationInfo",
"websiteContent"
]
}
},
"gecko_android": {
"id": "{0c3fcdbd-5e0f-40d5-8f6c-d5eef8ff2b7c}"
"id": "{e613be14-63c3-4bd9-8a4a-502c12bcf201}",
"data_collection_permissions": {
"required": [
"browsingActivity",
"authenticationInfo",
"websiteContent"
]
}
}
},
"web_accessible_resources": [

File diff suppressed because it is too large Load diff

8
pnpm-workspace.yaml Normal file
View file

@ -0,0 +1,8 @@
onlyBuiltDependencies:
- '@parcel/watcher'
- '@swc/core'
- esbuild
- lmdb
- msgpackr-extract
- sharp
- unrs-resolver

View file

@ -18,6 +18,16 @@
font-size: 14px;
}
.github-link {
color: #4A4863;
text-decoration: none;
transition: opacity 0.2s ease;
}
.github-link:hover {
text-decoration: underline;
}
.dot {
width: 3px;
height: 3px;

View file

@ -9,6 +9,10 @@ export function BottomLabel() {
{version}
<div className="dot" />
P-Stream
<div className="dot" />
<a href="https://github.com/p-stream/extension" target="_blank" rel="noopener noreferrer" className="github-link">
Github
</a>
</h3>
);
}

View file

@ -27,9 +27,7 @@ export function useToggleWhitelistDomain(domain: string | null) {
const { domainWhitelist, addDomain, removeDomain } = useDomainWhitelist();
const isWhitelisted = domainWhitelist.includes(domain ?? '');
const { grantPermission } = usePermission();
const iconPath = (chrome || browser).runtime.getURL(
isWhitelisted ? 'assets/active.png' : 'assets/inactive.png',
);
const iconPath = (chrome || browser).runtime.getURL(isWhitelisted ? 'assets/active.png' : 'assets/inactive.png');
(chrome || browser).action.setIcon({
path: iconPath,

View file

@ -1 +1,2 @@
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface BaseRequest {}

View file

@ -1,5 +1,4 @@
import { isChrome } from './extension';
import { modifiableResponseHeaders } from './storage';
interface DynamicRule {
ruleId: number;