add torrentio format, improve config page

This commit is contained in:
Viren070
2024-12-23 21:12:04 +00:00
parent 77418e43fe
commit 0901b0143b
8 changed files with 167 additions and 10 deletions
+8 -1
View File
@@ -1,6 +1,6 @@
import { BaseWrapper, Torbox, Torrentio } from '@aiostreams/wrappers';
import { Stream, ParsedStream, StreamRequest, Config } from '@aiostreams/types';
import { gdriveFormat } from '@aiostreams/formatters';
import { gdriveFormat, torrentioFormat } from '@aiostreams/formatters';
export class AIOStreams {
private config: Config;
@@ -84,6 +84,13 @@ export class AIOStreams {
description = _description;
break;
}
case 'torrentio': {
const { name: _name, description: _description } =
torrentioFormat(parsedStream);
name = _name;
description = _description;
break;
}
default: {
throw new Error('Unsupported formatter');
}
+1
View File
@@ -1,2 +1,3 @@
export * from './gdrive';
export * from './utils';
export * from './torrentio';
+46
View File
@@ -0,0 +1,46 @@
import { ParsedStream } from '@aiostreams/types';
import { formatSize } from './utils';
export function torrentioFormat(stream: ParsedStream): {
name: string;
description: string;
} {
let name: string = '';
if (stream.provider) {
name += stream.provider.cached
? `[${stream.provider.name}+]\n`
: `[${stream.provider.name} download]\n`;
}
name += `${stream.addonName} ${stream.resolution} `;
if (stream.visualTags.length > 0) {
name += stream.visualTags.join(' | ');
}
let description = stream.filename;
if (
stream.size ||
stream.torrent?.seeders ||
stream.usenet?.age ||
stream.indexers
) {
description += '\n';
description += stream.torrent?.seeders
? `👤 ${stream.torrent.seeders} `
: '';
description += stream.usenet?.age ? `📅 ${stream.usenet.age}d ` : '';
description += `💾 ${formatSize(stream.size || 0)} `;
description += stream.indexers ? `⚙️ ${stream.indexers} ` : '';
}
if (stream.languages.length !== 0) {
description += `\n${stream.languages.join(' / ')}`;
}
return { name, description };
}
+5 -5
View File
@@ -9,18 +9,18 @@
"lint": "next lint"
},
"dependencies": {
"react": "^19.0.0",
"react-dom": "^19.0.0",
"@aiostreams/types": "^1.0.0",
"next": "15.1.2",
"@aiostreams/types": "^1.0.0"
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"devDependencies": {
"typescript": "^5",
"@eslint/eslintrc": "^3",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
"eslint-config-next": "15.1.2",
"@eslint/eslintrc": "^3"
"typescript": "^5"
}
}
+20
View File
@@ -176,6 +176,26 @@ a.secondary {
gap: 8px;
}
.buttonGroup {
display: flex;
gap: 16px;
margin-top: 16px;
}
.configButton {
padding: 10px 20px;
font-size: 16px;
background-color: var(--foreground);
color: var(--background);
border: none;
border-radius: 4px;
cursor: pointer;
}
.configButton:hover {
background-color: var(--button-primary-hover);
}
/* Enable hover only on non-touch devices */
@media (hover: hover) and (pointer: fine) {
a.primary:hover {
+82 -3
View File
@@ -1,6 +1,6 @@
'use client';
import { useState } from 'react';
import { useState, useEffect } from 'react';
import styles from './page.module.css';
const predefinedResolutions = ['2160p', '1080p', '720p', '480p', 'Unknown'];
@@ -66,6 +66,18 @@ export default function Configure() {
const [selectedDebridService, setSelectedDebridService] = useState('');
useEffect(() => {
const path = window.location.pathname;
const configMatch = path.match(/\/([^/]+)\/configure/);
if (configMatch) {
const decodedConfig = JSON.parse(atob(configMatch[1]));
setConfig((prevConfig) => ({
...prevConfig,
...decodedConfig,
}));
}
}, []);
const handleSubmit = (e: any) => {
e.preventDefault();
const filteredConfig = {
@@ -75,7 +87,11 @@ export default function Configure() {
),
};
const encodedConfig = btoa(JSON.stringify(filteredConfig));
window.location.href = `/${encodedConfig}/manifest.json`;
const protocol = window.location.protocol;
const host = window.location.host;
const link = `${protocol}//${host}/${encodedConfig}/manifest.json`;
navigator.clipboard.writeText(link);
alert('Link copied to clipboard!');
};
const handleChange = (e: any) => {
@@ -105,6 +121,47 @@ export default function Configure() {
}));
};
const handleCopyLink = () => {
const filteredConfig = {
...config,
apiKeys: Object.fromEntries(
Object.entries(config.apiKeys).filter(([_, value]) => value)
),
};
const encodedConfig = btoa(JSON.stringify(filteredConfig));
const protocol = window.location.protocol;
const host = window.location.host;
const link = `${protocol}//${host}/${encodedConfig}/manifest.json`;
navigator.clipboard.writeText(link);
alert('Link copied to clipboard!');
};
const handleInstallToWeb = () => {
const filteredConfig = {
...config,
apiKeys: Object.fromEntries(
Object.entries(config.apiKeys).filter(([_, value]) => value)
),
};
const encodedConfig = btoa(JSON.stringify(filteredConfig));
const protocol = window.location.protocol;
const host = window.location.host;
const link = `https://web.stremio.com/#/addons?addon=${protocol}//${host}/${encodedConfig}/manifest.json`;
window.location.href = link;
};
const handleInstall = () => {
const filteredConfig = {
...config,
apiKeys: Object.fromEntries(
Object.entries(config.apiKeys).filter(([_, value]) => value)
),
};
const encodedConfig = btoa(JSON.stringify(filteredConfig));
const link = `stremio://${encodedConfig}/manifest.json`;
window.location.href = link;
};
return (
<div className={styles.page}>
<main className={styles.main}>
@@ -226,7 +283,29 @@ export default function Configure() {
</label>
</>
)}
<button type="submit">Submit</button>
<div className={styles.buttonGroup}>
<button
type="button"
onClick={handleInstall}
className={styles.configButton}
>
➕ Install
</button>
<button
type="button"
onClick={handleInstallToWeb}
className={styles.configButton}
>
🌐 Install to Web
</button>
<button
type="button"
onClick={handleCopyLink}
className={styles.configButton}
>
📋 Copy Link
</button>
</div>
</form>
</main>
</div>
+1 -1
View File
@@ -28,7 +28,7 @@ export interface ParsedStream extends ParsedNameData {
};
url?: string;
externalUrl?: string;
indexers?: string;
stream?: {
subtitles?: Subtitle[];
behaviorHints?: {
+4
View File
@@ -39,6 +39,9 @@ export class Torrentio extends BaseWrapper {
const seedersMatch = RegExp(/👤 (\d+)/).exec(stream.title!);
const seeders = seedersMatch ? parseInt(seedersMatch[1]) : undefined;
const indexerMatch = RegExp(/⚙️ ([a-zA-Z0-9]+)/).exec(stream.title!);
const indexer = indexerMatch ? indexerMatch[1] : undefined;
return {
...parsedFilename,
filename,
@@ -52,6 +55,7 @@ export class Torrentio extends BaseWrapper {
seeders: seeders,
sources: stream.sources,
},
indexers: indexer,
provider: debrid
? {
name: debrid.provider,