diff --git a/package-lock.json b/package-lock.json index 13466365..ec6e7be6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -48,6 +48,10 @@ "resolved": "packages/types", "link": true }, + "node_modules/@aiostreams/utils": { + "resolved": "packages/utils", + "link": true + }, "node_modules/@aiostreams/wrappers": { "resolved": "packages/wrappers", "link": true @@ -2676,6 +2680,12 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -2873,6 +2883,57 @@ "node": ">= 16" } }, + "node_modules/cheerio": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz", + "integrity": "sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==", + "license": "MIT", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.1.0", + "encoding-sniffer": "^0.2.0", + "htmlparser2": "^9.1.0", + "parse5": "^7.1.2", + "parse5-htmlparser2-tree-adapter": "^7.0.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^6.19.5", + "whatwg-mimetype": "^4.0.0" + }, + "engines": { + "node": ">=18.17" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cheerio/node_modules/undici": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.0.tgz", + "integrity": "sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, "node_modules/chokidar": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", @@ -3058,6 +3119,34 @@ "dev": true, "license": "MIT" }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -3264,6 +3353,61 @@ "node": ">=0.10.0" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.1.tgz", + "integrity": "sha512-xWXmuRnN9OMP6ptPd2+H0cCbcYBULa5YDTbMm/2lvkWvNA3O4wcW+GvzooqBuNM8yy6pl3VIAeJTUUWUbfI5Fw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/dotenv": { "version": "16.4.7", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", @@ -3312,6 +3456,31 @@ "node": ">= 0.8" } }, + "node_modules/encoding-sniffer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz", + "integrity": "sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==", + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + } + }, + "node_modules/encoding-sniffer/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/enhanced-resolve": { "version": "5.18.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz", @@ -3326,6 +3495,18 @@ "node": ">=10.13.0" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/es-abstract": { "version": "1.23.7", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.7.tgz", @@ -4598,6 +4779,25 @@ "node": ">= 0.4" } }, + "node_modules/htmlparser2": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", + "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.1.0", + "entities": "^4.5.0" + } + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -5653,6 +5853,18 @@ "node": ">= 10" } }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -5866,6 +6078,43 @@ "node": ">=6" } }, + "node_modules/parse5": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", + "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", + "license": "MIT", + "dependencies": { + "entities": "^4.5.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", + "license": "MIT", + "dependencies": { + "domhandler": "^5.0.3", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", + "license": "MIT", + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -8015,6 +8264,39 @@ } } }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -8707,7 +8989,9 @@ "dependencies": { "@aiostreams/formatters": "^1.0.0", "@aiostreams/types": "^1.0.0", + "@aiostreams/utils": "^1.0.0", "@aiostreams/wrappers": "^1.0.0", + "cheerio": "^1.0.0", "dotenv": "^16.4.7", "express": "^4.21.2" }, @@ -8785,12 +9069,17 @@ "name": "@aiostreams/types", "version": "1.5.4" }, + "packages/utils": { + "name": "@aiostreams/utils", + "version": "1.5.4" + }, "packages/wrappers": { "name": "@aiostreams/wrappers", "version": "1.5.4", "devDependencies": { "@aiostreams/parser": "^1.0.0", - "@aiostreams/types": "^1.0.0" + "@aiostreams/types": "^1.0.0", + "@aiostreams/utils": "^1.0.0" } } } diff --git a/package.json b/package.json index d97cff01..30fb71bc 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "test": "npm run test --workspaces", "format": "prettier --write .", - "build": "npm -w packages/types run build && npm -w packages/parser run build && npm -w packages/wrappers run build && npm -w packages/formatters run build && npm -w packages/addon run build && npm -w packages/frontend run build", + "build": "npm -w packages/types run build && npm -w packages/utils run build && npm -w packages/parser run build && npm -w packages/wrappers run build && npm -w packages/formatters run build && npm -w packages/addon run build && npm -w packages/frontend run build", "build:watch": "tsc --build --watch", "start:addon": "npm -w packages/addon start", "start:addon:dev": "npm -w packages/addon run start:dev", diff --git a/packages/addon/package.json b/packages/addon/package.json index 70e20af8..da2757bd 100644 --- a/packages/addon/package.json +++ b/packages/addon/package.json @@ -14,7 +14,9 @@ "dependencies": { "@aiostreams/formatters": "^1.0.0", "@aiostreams/types": "^1.0.0", + "@aiostreams/utils": "^1.0.0", "@aiostreams/wrappers": "^1.0.0", + "cheerio": "^1.0.0", "dotenv": "^16.4.7", "express": "^4.21.2" }, diff --git a/packages/addon/src/addon.ts b/packages/addon/src/addon.ts index 9910560c..97974d73 100644 --- a/packages/addon/src/addon.ts +++ b/packages/addon/src/addon.ts @@ -17,7 +17,7 @@ import { torrentioFormat, torboxFormat, } from '@aiostreams/formatters'; -import Settings from './settings'; +import { Settings } from '@aiostreams/utils'; export class AIOStreams { private config: Config; @@ -197,7 +197,7 @@ export class AIOStreams { externalUrl: parsedStream.externalUrl, infoHash: parsedStream.torrent?.infoHash, fileIdx: parsedStream.torrent?.fileIdx, - name: "🎲 " + name, + name: Settings.SHOW_DIE ? `🎲 ${name}` : name, description: description, subtitles: parsedStream.stream?.subtitles, sources: parsedStream.torrent?.sources, @@ -384,7 +384,6 @@ export class AIOStreams { addon.options, streamRequest, addonId, - Settings.COMET_URL ); } case 'mediafusion': { @@ -393,7 +392,6 @@ export class AIOStreams { addon.options, streamRequest, addonId, - Settings.MEDIAFUSION_URL ); } case 'gdrive': { diff --git a/packages/addon/src/config.ts b/packages/addon/src/config.ts index 57ceea7a..a5d6f557 100644 --- a/packages/addon/src/config.ts +++ b/packages/addon/src/config.ts @@ -1,12 +1,8 @@ import { AddonDetail, Config } from '@aiostreams/types'; -import { addonDetails, serviceDetails } from '@aiostreams/wrappers'; +import { addonDetails, serviceDetails, Settings } from '@aiostreams/utils'; export const allowedFormatters = ['gdrive', 'torrentio', 'torbox']; -export const MAX_ADDONS = 15; -export const MAX_MOVIE_SIZE = 150000000000; // 150GB -export const MAX_EPISODE_SIZE = 15000000000; // 15GB - export const allowedLanguages = [ 'English', 'Japanese', @@ -249,11 +245,11 @@ export function validateConfig(config: Config): { ); } - if (config.addons.length > MAX_ADDONS) { + if (config.addons.length > Settings.MAX_ADDONS) { return createResponse( false, 'tooManyAddons', - `You can only select a maximum of ${MAX_ADDONS} addons` + `You can only select a maximum of ${Settings.MAX_ADDONS} addons` ); } diff --git a/packages/addon/src/index.ts b/packages/addon/src/index.ts index 9fa492dd..21d564cb 100644 --- a/packages/addon/src/index.ts +++ b/packages/addon/src/index.ts @@ -2,4 +2,3 @@ export * from './addon'; export * from './config'; export * from './manifest'; export * from './responses'; -export * from './crypto'; diff --git a/packages/addon/src/server.ts b/packages/addon/src/server.ts index 9a16f53b..54b1f110 100644 --- a/packages/addon/src/server.ts +++ b/packages/addon/src/server.ts @@ -1,15 +1,34 @@ import express, { Request, Response } from 'express'; import path from 'path'; +import fs from 'fs'; +import {load} from 'cheerio'; import { AIOStreams } from './addon'; import { Config, StreamRequest } from '@aiostreams/types'; import { validateConfig } from './config'; import { getManifest } from './manifest'; import { invalidConfig, missingConfig } from './responses'; -import { compressAndEncrypt, decryptAndDecompress } from './crypto'; -import Settings from './settings'; +import {Settings, compressAndEncrypt, decryptAndDecompress} from '@aiostreams/utils'; const app = express(); +console.log('PORT:', Settings.PORT); +console.log('SECRET_KEY:', Settings.SECRET_KEY ? 'Set' : 'Not Set'); +console.log('COMET_URL:', Settings.COMET_URL); +console.log('MEDIAFUSION_URL:', Settings.MEDIAFUSION_URL); +console.log('MAX_ADDONS:', Settings.MAX_ADDONS); +console.log('MAX_MOVIE_SIZE:', Settings.MAX_MOVIE_SIZE); +console.log('MAX_EPISODE_SIZE:', Settings.MAX_EPISODE_SIZE); +console.log('MAX_TIMEOUT:', Settings.MAX_TIMEOUT); +console.log('MIN_TIMEOUT:', Settings.MIN_TIMEOUT); +console.log('SHOW_DIE:', Settings.SHOW_DIE); +console.log('BRANDING:', Settings.BRANDING ? 'Set' : 'Not Set'); + + +if (!Settings.SECRET_KEY) { + console.warn('You have not set a SECRET_KEY, you will not be able to use encrypted configs'); +} + + const rootUrl = (req: Request) => `${req.protocol}://${req.hostname}${req.hostname === 'localhost' ? `:${Settings.PORT}` : ''}`; @@ -25,18 +44,39 @@ app.use((req, res, next) => { next(); }); -app.use(express.static(path.join(__dirname, '../../frontend/out'))); +//app.use(express.static(path.join(__dirname, '../../frontend/out'))); + +app.get(['/_next/*', '/assets/*'], (req, res) => { + res.sendFile(path.join(__dirname, '../../frontend/out', req.path)); +}); app.get('/', (req, res) => { res.redirect('/configure'); }); +const sendModifiedHtml = (res: Response, filePath: string) => { + fs.readFile(filePath, 'utf8', (err, html) => { + if (err) { + console.error('Failed to read HTML file', err); + res.status(500).send('Internal Server Error'); + return; + } + + const $ = load(html); + + if (Settings.BRANDING) { + $('[id*="BrandingDiv"]').html(Settings.BRANDING); + } + res.send($.html()); + }); +}; + app.get('/configure', (req, res) => { - res.sendFile(path.join(__dirname, '../../frontend/out/configure.html')); + const filePath = path.join(__dirname, '../../frontend/out/configure.html'); + sendModifiedHtml(res, filePath); }); app.get('/:config/configure', (req, res) => { - // if the config starts with E- , decrypt it and redirect to base64 encoded config const config = req.params.config; if (config.startsWith("E-")) { const encryptedConfig = config.replace('E-', ''); @@ -44,7 +84,6 @@ app.get('/:config/configure', (req, res) => { const iv = Buffer.from(ivHex, 'hex'); const encrypted = Buffer.from(encryptedHex, 'hex'); const decryptedData = decryptAndDecompress(encrypted, iv); - // edit out any API keys from the decrypted data const configJson = JSON.parse(decryptedData); if (configJson.services) { configJson.services.forEach((service: any) => { @@ -57,10 +96,10 @@ app.get('/:config/configure', (req, res) => { res.redirect(`/${base64Config}/configure`); return; } - res.sendFile(path.join(__dirname, '../../frontend/out/configure.html')); + const filePath = path.join(__dirname, '../../frontend/out/configure.html'); + sendModifiedHtml(res, filePath); }); - app.get('/manifest.json', (req, res) => { res.status(200).json(getManifest(false)); }); diff --git a/packages/addon/src/settings.ts b/packages/addon/src/settings.ts deleted file mode 100644 index b2244f11..00000000 --- a/packages/addon/src/settings.ts +++ /dev/null @@ -1,19 +0,0 @@ -import dotenv from 'dotenv'; -import path from 'path'; - -try { - dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); -} catch (error) { - console.error('Error loading .env file'); -} - - -class Settings { - public static readonly PORT = process.env.PORT || 3000; - public static readonly SECRET_KEY = process.env.SECRET_KEY; - public static readonly COMET_URL = process.env.COMET_URL || 'https://comet.elfhosted.com/'; - public static readonly MEDIAFUSION_URL = process.env.MEDIAFUSION_URL || 'https://mediafusion.elfhosted.com/'; -} - - -export default Settings; diff --git a/packages/addon/tsconfig.json b/packages/addon/tsconfig.json index ef51a915..ea109a6b 100644 --- a/packages/addon/tsconfig.json +++ b/packages/addon/tsconfig.json @@ -14,6 +14,9 @@ }, { "path": "../types" + }, + { + "path": "../utils" } ] } diff --git a/packages/frontend/src/app/configure/page.tsx b/packages/frontend/src/app/configure/page.tsx index d251a094..38dc8603 100644 --- a/packages/frontend/src/app/configure/page.tsx +++ b/packages/frontend/src/app/configure/page.tsx @@ -22,10 +22,8 @@ import { allowedFormatters, allowedLanguages, validateConfig, - MAX_EPISODE_SIZE, - MAX_MOVIE_SIZE, } from '@aiostreams/config'; -import { addonDetails, serviceDetails } from '@aiostreams/wrappers'; +import { addonDetails, serviceDetails, Settings } from '@aiostreams/utils'; import Slider from '@/components/Slider'; @@ -154,6 +152,7 @@ export default function Configure() { const [minEpisodeSize, setMinEpisodeSize] = useState(null); const [disableButtons, setDisableButtons] = useState(false); + const [branding, setBranding] = useState(null); const getChoosableAddons = () => { // only if torbox service is enabled we can use torbox addon @@ -471,6 +470,12 @@ export default function Configure() { } const path = window.location.pathname; + const brandingDiv = document.getElementById('BrandingDiv'); + console.log('BrandingDiv', brandingDiv); + console.log('BrandingDiv innerHTML', brandingDiv?.innerHTML); + if (brandingDiv) { + setBranding(brandingDiv.innerHTML); + } try { const configMatch = path.match(/\/([^/]+)\/configure/); @@ -495,10 +500,13 @@ export default function Configure() { style={{ alignSelf: 'center', justifyContent: 'center' }} />

AIOStreams v{version}

- {process.env.NEXT_PUBLIC_ELFHOSTED_BRANDING && ( -
-
- )} + {process.env.NEXT_PUBLIC_ELFHOSTED_BRANDING && ( +
+ )} + +
+ +

AIOStreams, the all-in-one streaming addon for Stremio. Combine your streams from all your addons into one and filter them by resolution, @@ -632,7 +640,7 @@ export default function Configure() {

{ const padding = blockSize - (data.length % blockSize); diff --git a/packages/wrappers/src/details.ts b/packages/utils/src/details.ts similarity index 96% rename from packages/wrappers/src/details.ts rename to packages/utils/src/details.ts index d4e1299e..8198f0aa 100644 --- a/packages/wrappers/src/details.ts +++ b/packages/utils/src/details.ts @@ -1,7 +1,6 @@ import { AddonDetail } from '@aiostreams/types'; +import {Settings} from './settings'; -const MAX_TIMEOUT = 40000; -const MIN_TIMEOUT = 1000; export const addonDetails: AddonDetail[] = [ { @@ -50,8 +49,8 @@ export const addonDetails: AddonDetail[] = [ 'The timeout for fetching streams from the Torrentio addon. This is the time in milliseconds that the addon will wait for a response before timing out. Leave it empty to use the recommended timeout.', type: 'number', constraints: { - min: MIN_TIMEOUT, - max: MAX_TIMEOUT, + min: Settings.MIN_TIMEOUT, + max: Settings.MAX_TIMEOUT, }, }, ], @@ -107,8 +106,8 @@ export const addonDetails: AddonDetail[] = [ 'The timeout for fetching streams from the Comet addon. This is the time in milliseconds that the addon will wait for a response before timing out. Leave it empty to use the recommended timeout.', type: 'number', constraints: { - min: MIN_TIMEOUT, - max: MAX_TIMEOUT, + min: Settings.MIN_TIMEOUT, + max: Settings.MAX_TIMEOUT, }, }, ], @@ -168,8 +167,8 @@ export const addonDetails: AddonDetail[] = [ 'The timeout for fetching streams from the Media Fusion addon. This is the time in milliseconds that the addon will wait for a response before timing out. Leave it empty to use the recommended timeout.', type: 'number', constraints: { - min: MIN_TIMEOUT, - max: MAX_TIMEOUT, + min: Settings.MIN_TIMEOUT, + max: Settings.MAX_TIMEOUT, }, }, ], @@ -188,8 +187,8 @@ export const addonDetails: AddonDetail[] = [ 'The timeout for fetching streams from the Torbox addon. This is the time in milliseconds that the addon will wait for a response from Torbox before timing out. Leave it empty to use the recommended timeout.', type: 'number', constraints: { - min: MIN_TIMEOUT, - max: MAX_TIMEOUT, + min: Settings.MIN_TIMEOUT, + max: Settings.MAX_TIMEOUT, }, }, { @@ -232,8 +231,8 @@ export const addonDetails: AddonDetail[] = [ 'The timeout for fetching streams from the Google Drive addon in milliseconds. This is the time in milliseconds that the addon will wait for a response from your Cloudflare Worker before timing out. Leave it empty to use the recommended timeout.', type: 'number', constraints: { - min: MIN_TIMEOUT, - max: MAX_TIMEOUT, + min: Settings.MIN_TIMEOUT, + max: Settings.MAX_TIMEOUT, }, }, ], @@ -268,8 +267,8 @@ export const addonDetails: AddonDetail[] = [ 'The timeout for fetching streams from the custom addon in milliseconds', type: 'number', constraints: { - min: MIN_TIMEOUT, - max: MAX_TIMEOUT, + min: Settings.MIN_TIMEOUT, + max: Settings.MAX_TIMEOUT, }, }, ], diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts new file mode 100644 index 00000000..a41cbaa5 --- /dev/null +++ b/packages/utils/src/index.ts @@ -0,0 +1,3 @@ +export * from './crypto'; +export * from './details'; +export * from './settings'; \ No newline at end of file diff --git a/packages/utils/src/settings.ts b/packages/utils/src/settings.ts new file mode 100644 index 00000000..93d66a3c --- /dev/null +++ b/packages/utils/src/settings.ts @@ -0,0 +1,25 @@ +import dotenv from 'dotenv'; +import path from 'path'; + +try { + dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); +} catch (error) { + console.error('Error loading .env file:', error); +} + + +export class Settings { + public static readonly PORT = process.env.PORT ? process.env.PORT : 3000; + public static readonly BRANDING = process.env.NEXT_PUBLIC_ELFHOSTED_BRANDING; + public static readonly SECRET_KEY = process.env.SECRET_KEY ?? ''; + public static readonly COMET_URL = process.env.COMET_URL ?? 'https://comet.elfhosted.com/'; + public static readonly MEDIAFUSION_URL = process.env.MEDIAFUSION_URL ?? 'https://mediafusion.elfhosted.com/'; + public static readonly MAX_ADDONS = process.env.MAX_ADDONS ? parseInt(process.env.MAX_ADDONS) : 15; + public static readonly MAX_MOVIE_SIZE = process.env.MAX_MOVIE_SIZE ? parseInt(process.env.MAX_MOVIE_SIZE) : 150000000000; // 150GB + public static readonly MAX_EPISODE_SIZE = process.env.MAX_EPISODE_SIZE ? parseInt(process.env.MAX_EPISODE_SIZE) : 15000000000; // 15GB + public static readonly MAX_TIMEOUT = process.env.MAX_TIMEOUT ? parseInt(process.env.MAX_TIMEOUT) : 40000; + public static readonly MIN_TIMEOUT = process.env.MIN_TIMEOUT ? parseInt(process.env.MIN_TIMEOUT) : 1000; + public static readonly SHOW_DIE = process.env.SHOW_DIE ? process.env.SHOW_DIE === 'true' : true; +} + + diff --git a/packages/utils/tsconfig.json b/packages/utils/tsconfig.json new file mode 100644 index 00000000..511d8bf0 --- /dev/null +++ b/packages/utils/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + } + } + \ No newline at end of file diff --git a/packages/wrappers/package.json b/packages/wrappers/package.json index 40118528..303a80d1 100644 --- a/packages/wrappers/package.json +++ b/packages/wrappers/package.json @@ -9,6 +9,7 @@ "description": "Library with wrappers for different addons", "devDependencies": { "@aiostreams/parser": "^1.0.0", - "@aiostreams/types": "^1.0.0" + "@aiostreams/types": "^1.0.0", + "@aiostreams/utils": "^1.0.0" } } diff --git a/packages/wrappers/src/base.ts b/packages/wrappers/src/base.ts index ca1485f7..f4180217 100644 --- a/packages/wrappers/src/base.ts +++ b/packages/wrappers/src/base.ts @@ -5,7 +5,7 @@ import { ParsedNameData, } from '@aiostreams/types'; import { extractSizeInBytes, parseFilename } from '@aiostreams/parser'; -import { serviceDetails } from './details'; +import { serviceDetails } from '@aiostreams/utils'; export class BaseWrapper { private readonly streamPath: string = 'stream/{type}/{id}.json'; diff --git a/packages/wrappers/src/comet.ts b/packages/wrappers/src/comet.ts index 9ad6f860..b267df14 100644 --- a/packages/wrappers/src/comet.ts +++ b/packages/wrappers/src/comet.ts @@ -2,7 +2,8 @@ import { AddonDetail, ParsedNameData, StreamRequest } from '@aiostreams/types'; import { parseFilename, extractSizeInBytes } from '@aiostreams/parser'; import { ParsedStream, Stream, Config } from '@aiostreams/types'; import { BaseWrapper } from './base'; -import { addonDetails } from './details'; +import { addonDetails } from '@aiostreams/utils'; +import { Settings } from '@aiostreams/utils'; interface CometStream extends Stream { torrentTitle?: string; @@ -16,11 +17,10 @@ export class Comet extends BaseWrapper { indexerTimeout: number = 10000, addonName: string = 'Comet', addonId: string, - cometUrl: string ) { let url = overrideUrl ? overrideUrl - : cometUrl + + : Settings.COMET_URL + (configString ? configString + '/' : ''); super(addonName, url, indexerTimeout, addonId); @@ -96,7 +96,6 @@ export async function getCometStreams( }, streamRequest: StreamRequest, addonId: string, - cometUrl: string ): Promise { const supportedServices: string[] = addonDetails.find((addon: AddonDetail) => addon.id === 'comet') @@ -114,7 +113,6 @@ export async function getCometStreams( indexerTimeout, cometOptions.overrideName, addonId, - cometUrl ); return comet.getParsedStreams(streamRequest); } @@ -166,8 +164,7 @@ export async function getCometStreams( null, indexerTimeout, cometOptions.overrideName, - addonId, - cometUrl + addonId ); return comet.getParsedStreams(streamRequest); @@ -188,8 +185,7 @@ export async function getCometStreams( null, indexerTimeout, cometOptions.overrideName, - addonId, - cometUrl + addonId ); const streams = await comet.getParsedStreams(streamRequest); parsedStreams.push(...streams); diff --git a/packages/wrappers/src/index.ts b/packages/wrappers/src/index.ts index 71fb7920..eb05a7b7 100644 --- a/packages/wrappers/src/index.ts +++ b/packages/wrappers/src/index.ts @@ -1,4 +1,3 @@ -export * from './details'; export * from './base'; export * from './torbox'; export * from './torrentio'; diff --git a/packages/wrappers/src/mediafusion.ts b/packages/wrappers/src/mediafusion.ts index 245ce9ed..70924e78 100644 --- a/packages/wrappers/src/mediafusion.ts +++ b/packages/wrappers/src/mediafusion.ts @@ -2,7 +2,7 @@ import { AddonDetail, ParsedNameData, StreamRequest } from '@aiostreams/types'; import { parseFilename, extractSizeInBytes } from '@aiostreams/parser'; import { ParsedStream, Stream, Config } from '@aiostreams/types'; import { BaseWrapper } from './base'; -import { addonDetails, serviceDetails } from './details'; +import { addonDetails, serviceDetails, Settings } from '@aiostreams/utils'; export class MediaFusion extends BaseWrapper { constructor( @@ -11,11 +11,10 @@ export class MediaFusion extends BaseWrapper { indexerTimeout: number = 10000, addonName: string = 'MediaFusion', addonId: string, - mediafusionUrl: string, ) { let url = overrideUrl ? overrideUrl - : mediafusionUrl + + : Settings.MEDIAFUSION_URL + (configString ? configString + '/' : ''); super(addonName, url, indexerTimeout, addonId); @@ -82,7 +81,6 @@ export async function getMediafusionStreams( }, streamRequest: StreamRequest, addonId: string, - mediafusionUrl: string, ): Promise { const supportedServices: string[] = addonDetails.find((addon: AddonDetail) => addon.id === 'mediafusion') @@ -100,7 +98,6 @@ export async function getMediafusionStreams( indexerTimeout, mediafusionOptions.overrideName, addonId, - mediafusionUrl ); return mediafusion.getParsedStreams(streamRequest); } @@ -111,9 +108,8 @@ export async function getMediafusionStreams( ); // if no usable services found, use mediafusion without debrid - if (usableServices.length < 0) { + if (config.services.length < 0) { const configString = await getConfigString( - 'https://mediafusion.elfhosted.com/', getMediaFusionConfig() ); const mediafusion = new MediaFusion( @@ -122,7 +118,6 @@ export async function getMediafusionStreams( indexerTimeout, mediafusionOptions.overrideName, addonId, - mediafusionUrl ); return mediafusion.getParsedStreams(streamRequest); } @@ -158,7 +153,6 @@ export async function getMediafusionStreams( debridService.credentials.apiKey ); const encryptedStr = await getConfigString( - 'https://mediafusion.elfhosted.com/', mediafusionConfig ); const mediafusion = new MediaFusion( @@ -167,7 +161,6 @@ export async function getMediafusionStreams( indexerTimeout, mediafusionOptions.overrideName, addonId, - mediafusionUrl ); return mediafusion.getParsedStreams(streamRequest); @@ -184,7 +177,6 @@ export async function getMediafusionStreams( service.credentials.apiKey ); const encryptedStr = await getConfigString( - mediafusionUrl, mediafusionConfig ); const mediafusion = new MediaFusion( @@ -193,7 +185,6 @@ export async function getMediafusionStreams( indexerTimeout, mediafusionOptions.overrideName, addonId, - mediafusionUrl ); const streams = await mediafusion.getParsedStreams(streamRequest); parsedStreams.push(...streams); @@ -290,10 +281,9 @@ const getMediaFusionConfig = (service?: string, token?: string) => { }; async function getConfigString( - baseUrl: string = 'https://mediafusion.elfhosted.com/', data: any ): Promise { - const encryptUrl = `${baseUrl}encrypt-user-data`; + const encryptUrl = `${Settings.MEDIAFUSION_URL}encrypt-user-data`; const response = await fetch(encryptUrl, { method: 'POST', diff --git a/packages/wrappers/src/torrentio.ts b/packages/wrappers/src/torrentio.ts index 3796956e..f2b3edd8 100644 --- a/packages/wrappers/src/torrentio.ts +++ b/packages/wrappers/src/torrentio.ts @@ -2,7 +2,7 @@ import { AddonDetail, ParsedNameData, StreamRequest } from '@aiostreams/types'; import { parseFilename, extractSizeInBytes } from '@aiostreams/parser'; import { ParsedStream, Stream, Config } from '@aiostreams/types'; import { BaseWrapper } from './base'; -import { addonDetails } from './details'; +import { addonDetails } from '@aiostreams/utils'; export class Torrentio extends BaseWrapper { constructor( diff --git a/packages/wrappers/tsconfig.json b/packages/wrappers/tsconfig.json index ecd8ec57..bfe3d235 100644 --- a/packages/wrappers/tsconfig.json +++ b/packages/wrappers/tsconfig.json @@ -12,6 +12,9 @@ }, { "path": "../types" + }, + { + "path": "../utils" } ] } diff --git a/tsconfig.json b/tsconfig.json index c1b276ad..ef0fda2e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,6 +18,9 @@ }, { "path": "./packages/frontend" + }, + { + "path": "./packages/utils" } ] }