'use client'; import { useState } from 'react'; import styles from './page.module.css'; import { Slide, ToastContainer, toast, ToastOptions } from 'react-toastify'; import { isValueEncrypted } from '@aiostreams/utils'; interface CustomConfig { key: string; value: string; } const toastOptions: ToastOptions = { autoClose: 5000, hideProgressBar: true, closeOnClick: false, pauseOnHover: true, draggable: 'touch', style: { borderRadius: '8px', backgroundColor: '#ededed', color: 'black', }, }; const showToast = ( message: string, type: 'success' | 'error' | 'info' | 'warning', id?: string ) => { toast[type](message, { ...toastOptions, toastId: id, }); }; const isValidBase64 = (value: string): boolean => { try { JSON.parse(atob(value)); return true; } catch { return false; } }; const isValidBase64Compressed = (value: string): boolean => { if (value.startsWith('B-')) return true; return false; }; const isValidConfigFormat = (value: string): boolean => { return value ? isValueEncrypted(value) || isValidBase64(value) || isValidBase64Compressed(value) : false; }; const handleCopyEvent = (text: string) => { navigator.clipboard .writeText(text) .then(() => { showToast('Copied to clipboard!', 'success'); }) .catch((error: Error) => { console.error(error); showToast('Failed to copy to clipboard.', 'error'); }); }; const CopyButton = ({ text }: { text: string }) => ( ); export default function CustomConfigGenerator() { const [configs, setConfigs] = useState([]); const [newConfig, setNewConfig] = useState({ key: '', value: '', }); const [output, setOutput] = useState(null); const extractConfigValue = (value: string): string => { try { const url = new URL(value); const pathParts = url.pathname.split('/'); const longUniqueId = pathParts[pathParts.length - 2]; return longUniqueId; } catch { return value; } }; const validateKeyValuePair = (key: string, value: string) => { if (!key || !value) { showToast('Both key and value are required.', 'error', 'requiredFields'); return false; } if (!isValidConfigFormat(value)) { showToast( 'Invalid configuration format.', 'error', 'invalidConfigFormat' ); return false; } return true; }; const handleAddRow = () => { if ( !validateKeyValuePair(newConfig.key, extractConfigValue(newConfig.value)) ) return; if (configs.some((config) => config.key === newConfig.key)) { showToast('Key already exists.', 'error', 'uniqueKeyConstraintViolation'); return false; } newConfig.value = extractConfigValue(newConfig.value); setConfigs([...configs, newConfig]); setNewConfig({ key: '', value: '' }); }; const handleDeleteRow = (index: number) => { const newConfigs = configs.filter((_, i) => i !== index); setConfigs(newConfigs); }; const handleChange = ( index: number, field: 'key' | 'value', value: string ) => { const newConfigs = configs.map((config, i) => i === index ? { ...config, [field]: value } : config ); setConfigs(newConfigs); }; const generateJson = () => { if (configs.length === 0) { showToast('No configurations to generate.', 'error', 'noConfigs'); setOutput(null); return; } configs.forEach(({ key, value }) => { if (!validateKeyValuePair(key, value)) { setOutput(null); return; } }); const json = configs.reduce( (acc, { key, value }) => { if (key) acc[key] = value; return acc; }, {} as { [key: string]: string } ); // double stringify to escape the quotes setOutput(JSON.stringify(json)); }; return (

AIOStreams

This tool allows you to generate the value needed for the{' '} CUSTOM_CONFIGS environment variable.

Your Configurations

Add your configurations below. Put the name of the configuration in the key field and the manifest URL in the value field.

How to get the config value?

Once you have configured AIOStreams, upon clicking the{' '} Generate Manifest URL button, make sure to click the{' '} Copy URL button at the configuration page. You then paste that URL in the value field below.

{configs.map((config, index) => (
handleChange(index, 'key', e.target.value)} className={styles.keyInput} /> handleChange(index, 'value', e.target.value)} className={styles.valueInput} />
))}
setNewConfig({ ...newConfig, key: e.target.value }) } className={styles.keyInput} /> setNewConfig({ ...newConfig, value: e.target.value }) } className={styles.valueInput} />

Generate JSON Output

Click the Generate button to generate the JSON output. This is the value you need to set for the{' '} CUSTOM_CONFIGS environment variable.

{output && (

Output

)} {output && (
)}
{output && (

Setting the environment variable

Set the CUSTOM_CONFIGS environment variable to the value generated above. You can either manually use the value above or use the following commands to set it in a .env{' '} file. Ensure you are running these commands in the root directory of AIOStreams.

Windows:

Linux/Mac:

> .env`} className={styles.envInput} /> > .env`} />
)}
); }