diff --git a/PROXY_SETUP.md b/PROXY_SETUP.md new file mode 100644 index 00000000..3a3a1b2c --- /dev/null +++ b/PROXY_SETUP.md @@ -0,0 +1,129 @@ +# SlowGuardian Dual Proxy System + +SlowGuardian now supports two proxy systems for different user tiers: + +## Proxy Systems + +### 1. Ultraviolet (All Users) +- **URL Prefix**: `/a/` +- **Access**: Available to all users +- **Repository**: https://github.com/titaniumnetwork-dev/Ultraviolet +- **Status**: ✅ Always enabled + +### 2. Scramjet (Premium Users Only) +- **URL Prefix**: `/scram/` +- **Access**: Premium users only (requires `sg_premium=1` cookie) +- **Repository**: https://github.com/MercuryWorkshop/scramjet +- **Status**: ✅ Enabled for premium users + +## Setup + +### Automatic Setup (Recommended) +When you run `npm install`, the Scramjet files are automatically set up via the `postinstall` script. + +### Manual Setup +If you need to manually set up Scramjet: + +```bash +npm run setup:scramjet +``` + +This copies the necessary Scramjet files from `node_modules/@mercuryworkshop/scramjet` to `static/scram/`. + +## Premium User Detection + +The service worker checks for the `sg_premium` cookie to determine if a user has premium access: + +- **Premium users** (`sg_premium=1`): Can access both `/scram/` and `/a/` proxies +- **Non-premium users**: Can only access `/a/` proxy +- If a non-premium user tries to access `/scram/`, they are automatically redirected to `/a/` + +## Service Worker Architecture + +The service worker (`static/sw.js`) handles routing for all proxy systems: + +1. **Dynamic** (`/dy/`) - Base proxy system +2. **Scramjet** (`/scram/`) - Premium only, loaded conditionally +3. **Ultraviolet** (`/a/`) - Available to all users + +```javascript +// Premium detection +function isPremiumUser(request) { + const cookies = request.headers.get('cookie') || ''; + return cookies.includes('sg_premium=1'); +} +``` + +## File Structure + +``` +static/ +├── scram/ # Scramjet files (gitignored, built on install) +│ ├── config.js +│ ├── scramjet.worker.js +│ ├── scramjet.client.js +│ └── scramjet.codecs.js +├── m/ # Ultraviolet files +│ ├── config.js +│ ├── bundle.js +│ ├── handler.js +│ └── sw.js +└── sw.js # Main service worker with dual proxy support +``` + +## External Scripts + +The service worker is configured to NOT intercept external scripts (AdSense, Analytics, Cookie Consent): + +```javascript +// Don't intercept external requests - let browser handle them +if (url.origin !== location.origin) { + return; // Browser handles it naturally +} +``` + +## Testing + +To verify both proxies are working: + +1. **Test Ultraviolet** (all users): + - Navigate to: `http://localhost:8080/a/hvtrs8%2F-gmoelg.aoo%2F` + +2. **Test Scramjet** (premium only): + - Set cookie: `sg_premium=1` + - Navigate to: `http://localhost:8080/scram/[encoded-url]` + +## Troubleshooting + +### Scramjet files not found +Run the setup script manually: +```bash +npm run setup:scramjet +``` + +### Service worker not loading Scramjet +Check browser console for errors. Scramjet will log: +- `✓ Scramjet loaded for premium users` - Success +- `⚠ Scramjet not available` - Failed to load (will fallback to UV only) + +### Non-premium user trying to access Scramjet +Users without `sg_premium=1` cookie will be automatically redirected to Ultraviolet. + +## Development + +When developing, ensure: +1. Run `npm install` to set up all dependencies +2. The `static/scram/` directory is automatically created +3. Check that all proxy files are accessible (should return 200): + - `/sw.js` + - `/m/config.js` + - `/scram/config.js` + - `/scram/scramjet.worker.js` + +## Production Deployment + +For production: +1. Ensure `npm install` runs during deployment +2. The postinstall script will automatically set up Scramjet +3. Verify both proxies are accessible +4. Configure premium user authentication as needed diff --git a/package-lock.json b/package-lock.json index 9bcf2a4c..35be5a73 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "slowguardian", "version": "9.0.0", + "hasInstallScript": true, "license": "GPL-3.0-or-later", "dependencies": { "@mercuryworkshop/epoxy-transport": "^2.1.28", @@ -406,6 +407,8 @@ }, "node_modules/@mercuryworkshop/scramjet": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@mercuryworkshop/scramjet/-/scramjet-1.0.2.tgz", + "integrity": "sha512-65k+TXYlMAnqTrcTyVlXyG+CVymOSHMW4a8ofJtX6yHDKmWGHL4LVzls+ukoTqth6JyqOk7OoT3iQdufZMoE7g==", "license": "ISC", "dependencies": { "@mercuryworkshop/bare-mux": "^1.1.2", diff --git a/package.json b/package.json index f91c79a4..520b7c43 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,8 @@ "test-sw-headless": "node scripts/test-sw-puppeteer.js", "test-sw-simple": "node scripts/test-sw-simple.js", "build": "npm run build:version && npm run format", + "postinstall": "node scripts/setup-scramjet.cjs", + "setup:scramjet": "node scripts/setup-scramjet.cjs", "build:production": "NODE_ENV=production npm run build:version && npm run format && npm run audit-fix", "build:version": "node scripts/build-version.js", "audit-fix": "npm audit fix", diff --git a/scripts/setup-scramjet.cjs b/scripts/setup-scramjet.cjs new file mode 100755 index 00000000..2f842ed9 --- /dev/null +++ b/scripts/setup-scramjet.cjs @@ -0,0 +1,74 @@ +#!/usr/bin/env node + +/** + * Script to set up Scramjet proxy for premium users + * Copies necessary files from node_modules to static directory + */ + +const fs = require('fs'); +const path = require('path'); + +const scramjetSrc = path.join(__dirname, '../node_modules/@mercuryworkshop/scramjet'); +const scramjetDest = path.join(__dirname, '../static/scram'); + +console.log('Setting up Scramjet for premium users...'); + +// Create destination directory +if (!fs.existsSync(scramjetDest)) { + fs.mkdirSync(scramjetDest, { recursive: true }); + console.log('✓ Created /static/scram directory'); +} + +// Check if Scramjet package exists +if (!fs.existsSync(scramjetSrc)) { + console.error('✗ Scramjet package not found in node_modules'); + console.log(' Run: npm install @mercuryworkshop/scramjet'); + process.exit(1); +} + +// List of files to copy (based on Scramjet documentation) +const filesToCopy = [ + 'scramjet.bundle.js', + 'scramjet.worker.js', + 'scramjet.client.js', + 'scramjet.codecs.js' +]; + +let copiedCount = 0; + +// Try to copy files from various possible locations +const possiblePaths = ['dist', 'lib', '', 'dist/']; + +for (const file of filesToCopy) { + let found = false; + + for (const subPath of possiblePaths) { + const srcPath = path.join(scramjetSrc, subPath, file); + const destPath = path.join(scramjetDest, file); + + if (fs.existsSync(srcPath)) { + try { + fs.copyFileSync(srcPath, destPath); + console.log(`✓ Copied ${file}`); + copiedCount++; + found = true; + break; + } catch (err) { + console.error(`✗ Error copying ${file}:`, err.message); + } + } + } + + if (!found) { + console.log(`⚠ ${file} not found (may not be needed)`); + } +} + +if (copiedCount > 0) { + console.log(`\n✓ Successfully set up Scramjet with ${copiedCount} files`); + console.log(' Scramjet will be available for premium users at /scram/ prefix'); +} else { + console.log('\n⚠ No Scramjet files were copied'); + console.log(' Please check the Scramjet package installation'); + console.log(' or refer to: https://github.com/MercuryWorkshop/scramjet'); +} diff --git a/static/404.html b/static/404.html index 89ab9b50..26f74931 100644 --- a/static/404.html +++ b/static/404.html @@ -214,6 +214,9 @@ } } + + +
diff --git a/static/apps.html b/static/apps.html index 83e87e96..7ed6c217 100644 --- a/static/apps.html +++ b/static/apps.html @@ -44,6 +44,22 @@ + + + + + + + + + + @@ -98,10 +114,48 @@Failed to load
+Internal Server Error
+ +Try:
+If you"re the administrator of , try:
+Scramjet v
+ @@ -875,12 +878,10 @@