mirror of
https://github.com/Viren070/AIOStreams.git
synced 2025-12-01 23:14:04 +01:00
style: format
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
export * from './addon';
|
||||
export * from './config';
|
||||
export * from './manifest';
|
||||
export * from './responses';
|
||||
export * from './responses';
|
||||
|
||||
@@ -14,7 +14,6 @@ export const manifest = {
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
export const getManifest = (configured: boolean): typeof manifest => {
|
||||
return {
|
||||
...manifest,
|
||||
@@ -23,4 +22,4 @@ export const getManifest = (configured: boolean): typeof manifest => {
|
||||
configurationRequired: configured,
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,25 +1,23 @@
|
||||
|
||||
export const missingConfig = (origin: string) => {
|
||||
return {
|
||||
streams: [
|
||||
{
|
||||
externalUrl: origin + '/configure',
|
||||
name: '[⚠️] AIOStreams',
|
||||
description: 'You must configure this addon to use it',
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
return {
|
||||
streams: [
|
||||
{
|
||||
externalUrl: origin + '/configure',
|
||||
name: '[⚠️] AIOStreams',
|
||||
description: 'You must configure this addon to use it',
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
export const invalidConfig = (origin: string, errorMessage: string) => {
|
||||
return {
|
||||
streams: [
|
||||
{
|
||||
externalUrl: origin + '/configure',
|
||||
name: '[⚠️] AIOStreams',
|
||||
description: errorMessage,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
streams: [
|
||||
{
|
||||
externalUrl: origin + '/configure',
|
||||
name: '[⚠️] AIOStreams',
|
||||
description: errorMessage,
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
@@ -6,11 +6,11 @@ import { validateConfig } from './config';
|
||||
import { getManifest } from './manifest';
|
||||
import { invalidConfig, missingConfig } from './responses';
|
||||
|
||||
|
||||
const app = express();
|
||||
const port = process.env.PORT || 3000;
|
||||
|
||||
const rootUrl = (req: Request) => `${req.protocol}://${req.hostname}${req.hostname === 'localhost' ? `:${port}` : ''}`;
|
||||
const rootUrl = (req: Request) =>
|
||||
`${req.protocol}://${req.hostname}${req.hostname === 'localhost' ? `:${port}` : ''}`;
|
||||
|
||||
// Built-in middleware for parsing JSON
|
||||
app.use(express.json());
|
||||
@@ -44,7 +44,6 @@ app.get('/:config/manifest.json', (req, res) => {
|
||||
|
||||
// Route for /stream
|
||||
app.get('/stream/:type/:id', (req: Request, res: Response) => {
|
||||
|
||||
res.status(200).json(missingConfig(rootUrl(req)));
|
||||
});
|
||||
|
||||
@@ -118,7 +117,9 @@ app.get('/:config/stream/:type/:id', (req: Request, res: Response) => {
|
||||
const { valid, errorCode, errorMessage } = validateConfig(configJson);
|
||||
if (!valid) {
|
||||
console.error(`Invalid config: ${errorCode} - ${errorMessage}`);
|
||||
res.status(200).json(invalidConfig(rootUrl(req), errorMessage ?? 'Unknown'));
|
||||
res
|
||||
.status(200)
|
||||
.json(invalidConfig(rootUrl(req), errorMessage ?? 'Unknown'));
|
||||
}
|
||||
|
||||
const aioStreams = new AIOStreams(configJson);
|
||||
|
||||
@@ -1,140 +1,147 @@
|
||||
import { AIOStreams, getManifest, invalidConfig, missingConfig, validateConfig } from '@aiostreams/addon';
|
||||
import {
|
||||
AIOStreams,
|
||||
getManifest,
|
||||
invalidConfig,
|
||||
missingConfig,
|
||||
validateConfig,
|
||||
} from '@aiostreams/addon';
|
||||
import { Config, StreamRequest } from '@aiostreams/types';
|
||||
|
||||
|
||||
const HEADERS = {
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Access-Control-Allow-Methods": "GET,HEAD,POST,OPTIONS",
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Methods': 'GET,HEAD,POST,OPTIONS',
|
||||
};
|
||||
|
||||
function createJsonResponse(data: any): Response {
|
||||
return new Response(JSON.stringify(data, null, 4), {
|
||||
headers: HEADERS
|
||||
});
|
||||
return new Response(JSON.stringify(data, null, 4), {
|
||||
headers: HEADERS,
|
||||
});
|
||||
}
|
||||
|
||||
function createResponse(message: string, status: number): Response {
|
||||
return new Response(message, {
|
||||
status,
|
||||
headers: HEADERS
|
||||
});
|
||||
return new Response(message, {
|
||||
status,
|
||||
headers: HEADERS,
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
async fetch(request, env, ctx): Promise<Response> {
|
||||
try {
|
||||
|
||||
const url = new URL(
|
||||
decodeURIComponent(request.url)
|
||||
);
|
||||
const components = url.pathname.split('/').splice(1);
|
||||
console.log(components);
|
||||
async fetch(request, env, ctx): Promise<Response> {
|
||||
try {
|
||||
const url = new URL(decodeURIComponent(request.url));
|
||||
const components = url.pathname.split('/').splice(1);
|
||||
console.log(components);
|
||||
|
||||
// handle static asset requests
|
||||
if (components.includes('_next')) {
|
||||
return env.ASSETS.fetch(request);
|
||||
}
|
||||
|
||||
// redirect to /configure if root path is requested
|
||||
if (url.pathname === '/') {
|
||||
return Response.redirect(url.origin + "/configure", 301);
|
||||
}
|
||||
// handle static asset requests
|
||||
if (components.includes('_next')) {
|
||||
return env.ASSETS.fetch(request);
|
||||
}
|
||||
|
||||
// handle /configure and /:config/configure requests
|
||||
if (components.includes('configure')) {
|
||||
if (components.length === 1) {
|
||||
return env.ASSETS.fetch(request);
|
||||
} else {
|
||||
// display configure page with config still in url
|
||||
return env.ASSETS.fetch(new Request(url.origin + '/configure', request));
|
||||
}
|
||||
}
|
||||
// redirect to /configure if root path is requested
|
||||
if (url.pathname === '/') {
|
||||
return Response.redirect(url.origin + '/configure', 301);
|
||||
}
|
||||
|
||||
|
||||
// handle /manifest.json and /:config/manifest.json requests
|
||||
if (components.includes('manifest.json')) {
|
||||
if (components.length === 1) {
|
||||
return createJsonResponse(getManifest(true));
|
||||
} else {
|
||||
return createJsonResponse(getManifest(false));
|
||||
}
|
||||
}
|
||||
|
||||
if (components.includes('stream')) {
|
||||
// when /stream is requested without config
|
||||
if (components.length !== 4) {
|
||||
return createJsonResponse(missingConfig(url.origin));
|
||||
}
|
||||
|
||||
const config = components[0];
|
||||
const decodedPath = decodeURIComponent(url.pathname);
|
||||
|
||||
const streamMatch = new RegExp(
|
||||
`/${config}/stream/(movie|series)/tt([0-9]{7,})(?::([0-9]+):([0-9]+))?.json`
|
||||
).exec(decodedPath);
|
||||
|
||||
if (!streamMatch) {
|
||||
let path = decodedPath.replace(`/${config}`, '')
|
||||
console.error(`Invalid request: ${path}`);
|
||||
return createResponse('Invalid request', 400);
|
||||
}
|
||||
|
||||
const [type, id, season, episode] = streamMatch.slice(1);
|
||||
console.log(`Received /stream request with Type: ${type}, ID: ${id}, Season: ${season}, Episode: ${episode}`);
|
||||
|
||||
let decodedConfig: Config;
|
||||
try {
|
||||
decodedConfig = JSON.parse(atob(config));
|
||||
} catch (error: any) {
|
||||
return createJsonResponse(invalidConfig(url.origin, 'Outdated Configuration'));
|
||||
}
|
||||
const {valid, errorMessage, errorCode} = validateConfig(decodedConfig);
|
||||
if (!valid) {
|
||||
console.error(`Invalid config: ${errorMessage}`);
|
||||
return createJsonResponse(invalidConfig(url.origin, errorMessage ?? 'Unknown'));
|
||||
}
|
||||
|
||||
let streamRequest: StreamRequest;
|
||||
|
||||
switch (type) {
|
||||
case 'series':
|
||||
if (!season || !episode) {
|
||||
return createResponse('Invalid Request', 400);
|
||||
}
|
||||
streamRequest = {
|
||||
id,
|
||||
type: 'series',
|
||||
season: season,
|
||||
episode: episode,
|
||||
};
|
||||
break;
|
||||
case 'movie':
|
||||
streamRequest = {
|
||||
id,
|
||||
type: 'movie',
|
||||
};
|
||||
break;
|
||||
default:
|
||||
return createResponse('Invalid Request', 400);
|
||||
}
|
||||
|
||||
const aioStreams = new AIOStreams(decodedConfig);
|
||||
const streams = await aioStreams.getStreams(streamRequest);
|
||||
return createJsonResponse({ streams });
|
||||
|
||||
}
|
||||
|
||||
return env.ASSETS.fetch(new Request(url.origin + "/404", request));
|
||||
|
||||
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return new Response('Internal Server Error', {
|
||||
status: 500,
|
||||
headers: {
|
||||
'Content-Type': 'text/plain',
|
||||
},
|
||||
});
|
||||
// handle /configure and /:config/configure requests
|
||||
if (components.includes('configure')) {
|
||||
if (components.length === 1) {
|
||||
return env.ASSETS.fetch(request);
|
||||
} else {
|
||||
// display configure page with config still in url
|
||||
return env.ASSETS.fetch(
|
||||
new Request(url.origin + '/configure', request)
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// handle /manifest.json and /:config/manifest.json requests
|
||||
if (components.includes('manifest.json')) {
|
||||
if (components.length === 1) {
|
||||
return createJsonResponse(getManifest(true));
|
||||
} else {
|
||||
return createJsonResponse(getManifest(false));
|
||||
}
|
||||
}
|
||||
|
||||
if (components.includes('stream')) {
|
||||
// when /stream is requested without config
|
||||
if (components.length !== 4) {
|
||||
return createJsonResponse(missingConfig(url.origin));
|
||||
}
|
||||
|
||||
const config = components[0];
|
||||
const decodedPath = decodeURIComponent(url.pathname);
|
||||
|
||||
const streamMatch = new RegExp(
|
||||
`/${config}/stream/(movie|series)/tt([0-9]{7,})(?::([0-9]+):([0-9]+))?.json`
|
||||
).exec(decodedPath);
|
||||
|
||||
if (!streamMatch) {
|
||||
let path = decodedPath.replace(`/${config}`, '');
|
||||
console.error(`Invalid request: ${path}`);
|
||||
return createResponse('Invalid request', 400);
|
||||
}
|
||||
|
||||
const [type, id, season, episode] = streamMatch.slice(1);
|
||||
console.log(
|
||||
`Received /stream request with Type: ${type}, ID: ${id}, Season: ${season}, Episode: ${episode}`
|
||||
);
|
||||
|
||||
let decodedConfig: Config;
|
||||
try {
|
||||
decodedConfig = JSON.parse(atob(config));
|
||||
} catch (error: any) {
|
||||
return createJsonResponse(
|
||||
invalidConfig(url.origin, 'Outdated Configuration')
|
||||
);
|
||||
}
|
||||
const { valid, errorMessage, errorCode } =
|
||||
validateConfig(decodedConfig);
|
||||
if (!valid) {
|
||||
console.error(`Invalid config: ${errorMessage}`);
|
||||
return createJsonResponse(
|
||||
invalidConfig(url.origin, errorMessage ?? 'Unknown')
|
||||
);
|
||||
}
|
||||
|
||||
let streamRequest: StreamRequest;
|
||||
|
||||
switch (type) {
|
||||
case 'series':
|
||||
if (!season || !episode) {
|
||||
return createResponse('Invalid Request', 400);
|
||||
}
|
||||
streamRequest = {
|
||||
id,
|
||||
type: 'series',
|
||||
season: season,
|
||||
episode: episode,
|
||||
};
|
||||
break;
|
||||
case 'movie':
|
||||
streamRequest = {
|
||||
id,
|
||||
type: 'movie',
|
||||
};
|
||||
break;
|
||||
default:
|
||||
return createResponse('Invalid Request', 400);
|
||||
}
|
||||
|
||||
const aioStreams = new AIOStreams(decodedConfig);
|
||||
const streams = await aioStreams.getStreams(streamRequest);
|
||||
return createJsonResponse({ streams });
|
||||
}
|
||||
|
||||
return env.ASSETS.fetch(new Request(url.origin + '/404', request));
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return new Response('Internal Server Error', {
|
||||
status: 500,
|
||||
headers: {
|
||||
'Content-Type': 'text/plain',
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
} satisfies ExportedHandler<Env>;
|
||||
|
||||
@@ -1,50 +1,48 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"compilerOptions": {
|
||||
"target": "es2021",
|
||||
"lib": ["es2021"],
|
||||
/* Specify what JSX code is generated. */
|
||||
"jsx": "react-jsx",
|
||||
|
||||
/* Specify what module code is generated. */
|
||||
"module": "es2022",
|
||||
/* Specify how TypeScript looks up a file from a given module specifier. */
|
||||
"moduleResolution": "Bundler",
|
||||
/* Specify type package names to be included without being referenced in a source file. */
|
||||
"types": ["@cloudflare/workers-types"],
|
||||
/* Enable importing .json files */
|
||||
"resolveJsonModule": true,
|
||||
|
||||
"target": "es2021",
|
||||
"lib": ["es2021"],
|
||||
/* Specify what JSX code is generated. */
|
||||
"jsx": "react-jsx",
|
||||
/* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
|
||||
"allowJs": true,
|
||||
/* Enable error reporting in type-checked JavaScript files. */
|
||||
"checkJs": false,
|
||||
|
||||
/* Specify what module code is generated. */
|
||||
"module": "es2022",
|
||||
/* Specify how TypeScript looks up a file from a given module specifier. */
|
||||
"moduleResolution": "Bundler",
|
||||
/* Specify type package names to be included without being referenced in a source file. */
|
||||
"types": ["@cloudflare/workers-types"],
|
||||
/* Enable importing .json files */
|
||||
"resolveJsonModule": true,
|
||||
/* Disable emitting files from a compilation. */
|
||||
"noEmit": true,
|
||||
|
||||
/* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
|
||||
"allowJs": true,
|
||||
/* Enable error reporting in type-checked JavaScript files. */
|
||||
"checkJs": false,
|
||||
/* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||
"isolatedModules": true,
|
||||
/* Allow 'import x from y' when a module doesn't have a default export. */
|
||||
"allowSyntheticDefaultImports": true,
|
||||
/* Ensure that casing is correct in imports. */
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
|
||||
/* Disable emitting files from a compilation. */
|
||||
"noEmit": true,
|
||||
/* Enable all strict type-checking options. */
|
||||
"strict": true,
|
||||
|
||||
/* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||
"isolatedModules": true,
|
||||
/* Allow 'import x from y' when a module doesn't have a default export. */
|
||||
"allowSyntheticDefaultImports": true,
|
||||
/* Ensure that casing is correct in imports. */
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
|
||||
/* Enable all strict type-checking options. */
|
||||
"strict": true,
|
||||
|
||||
/* Skip type checking all .d.ts files. */
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "../addon"
|
||||
},
|
||||
{
|
||||
"path": "../types"
|
||||
}
|
||||
],
|
||||
"exclude": ["test"],
|
||||
"include": ["worker-configuration.d.ts", "src/**/*.ts"]
|
||||
/* Skip type checking all .d.ts files. */
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "../addon"
|
||||
},
|
||||
{
|
||||
"path": "../types"
|
||||
}
|
||||
],
|
||||
"exclude": ["test"],
|
||||
"include": ["worker-configuration.d.ts", "src/**/*.ts"]
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// Generated by Wrangler by running `wrangler types`
|
||||
|
||||
interface Env {
|
||||
ASSETS: Fetcher;
|
||||
ASSETS: Fetcher;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,6 @@
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
|
||||
.slider {
|
||||
width: 100%;
|
||||
margin: 10px 0;
|
||||
@@ -80,7 +79,6 @@
|
||||
height: 15px;
|
||||
transition: opacity 0.2s;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
|
||||
}
|
||||
|
||||
.slider:hover {
|
||||
@@ -88,14 +86,25 @@
|
||||
}
|
||||
|
||||
.sliderMax {
|
||||
background: linear-gradient(to right, #1b1b1b 0%, #d3d3d3 var(--maxValue), #1a1a1a var(--maxValue), #1a1a1a 100%);
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
#1b1b1b 0%,
|
||||
#d3d3d3 var(--maxValue),
|
||||
#1a1a1a var(--maxValue),
|
||||
#1a1a1a 100%
|
||||
);
|
||||
}
|
||||
|
||||
.sliderMin {
|
||||
background: linear-gradient(to right, #414141 0%, #ffffff var(--minValue), #1a1a1a var(--minValue), #1a1a1a 100%);
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
#414141 0%,
|
||||
#ffffff var(--minValue),
|
||||
#1a1a1a var(--minValue),
|
||||
#1a1a1a 100%
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
.slider::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
|
||||
@@ -310,18 +310,27 @@ export default function Configure() {
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const slider = document.querySelector(`.${styles.sliderMin}`) as HTMLElement;
|
||||
const slider = document.querySelector(
|
||||
`.${styles.sliderMin}`
|
||||
) as HTMLElement;
|
||||
if (slider) {
|
||||
slider.style.setProperty('--minValue', `${(minSize || 0) / 150000000000 * 100}%`);
|
||||
slider.style.setProperty(
|
||||
'--minValue',
|
||||
`${((minSize || 0) / 150000000000) * 100}%`
|
||||
);
|
||||
}
|
||||
}, [minSize]);
|
||||
|
||||
useEffect(() => {
|
||||
const slider = document.querySelector(`.${styles.sliderMax}`) as HTMLElement;
|
||||
const slider = document.querySelector(
|
||||
`.${styles.sliderMax}`
|
||||
) as HTMLElement;
|
||||
if (slider) {
|
||||
slider.style.setProperty('--maxValue', `${(maxSize || 0) / 150000000000 * 100}%`);
|
||||
slider.style.setProperty(
|
||||
'--maxValue',
|
||||
`${((maxSize || 0) / 150000000000) * 100}%`
|
||||
);
|
||||
}
|
||||
}, [maxSize]);
|
||||
|
||||
@@ -434,7 +443,8 @@ export default function Configure() {
|
||||
<div>
|
||||
<h2 style={{ padding: '5px' }}>Size Filter</h2>
|
||||
<p style={{ padding: '5px' }}>
|
||||
Filter streams by size. Leave both sliders at 0 to disable the filter.
|
||||
Filter streams by size. Leave both sliders at 0 to disable the
|
||||
filter.
|
||||
</p>
|
||||
</div>
|
||||
<div className={styles.slidersContainer}>
|
||||
@@ -444,7 +454,11 @@ export default function Configure() {
|
||||
max="150000000000"
|
||||
step="50000000"
|
||||
value={minSize || 0}
|
||||
onChange={(e) => setMinSize(e.target.value === '0' ? null : parseInt(e.target.value))}
|
||||
onChange={(e) =>
|
||||
setMinSize(
|
||||
e.target.value === '0' ? null : parseInt(e.target.value)
|
||||
)
|
||||
}
|
||||
className={styles.slider + ' ' + styles.sliderMin}
|
||||
/>
|
||||
<div className={styles.sliderValue}>
|
||||
@@ -456,7 +470,11 @@ export default function Configure() {
|
||||
max="150000000000"
|
||||
step="50000000"
|
||||
value={maxSize || 0}
|
||||
onChange={(e) => setMaxSize(e.target.value === '0' ? null : parseInt(e.target.value))}
|
||||
onChange={(e) =>
|
||||
setMaxSize(
|
||||
e.target.value === '0' ? null : parseInt(e.target.value)
|
||||
)
|
||||
}
|
||||
className={styles.slider + ' ' + styles.sliderMax}
|
||||
/>
|
||||
<div className={styles.sliderValue}>
|
||||
|
||||
@@ -14,7 +14,8 @@ const geistMono = Geist_Mono({
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'AIOStreams',
|
||||
description: 'Combine all your streams into one addon and display them with consistent formatting, sorting, and filtering.',
|
||||
description:
|
||||
'Combine all your streams into one addon and display them with consistent formatting, sorting, and filtering.',
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #1a1a1a;
|
||||
background-color: #1a1a1a;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 8px rgb(0, 0, 0);
|
||||
padding: 10px;
|
||||
|
||||
Reference in New Issue
Block a user