mirror of
https://github.com/Viren070/AIOStreams.git
synced 2025-12-01 23:14:04 +01:00
99 lines
2.8 KiB
TypeScript
99 lines
2.8 KiB
TypeScript
import { BaseProxy, ProxyStream } from './base';
|
|
import { createLogger, maskSensitiveInfo, Env } from '../utils';
|
|
|
|
const logger = createLogger('stremthru');
|
|
|
|
export class StremThruProxy extends BaseProxy {
|
|
protected generateProxyUrl(endpoint: string): URL {
|
|
const proxyUrl = new URL(this.config.url.replace(/\/$/, ''));
|
|
proxyUrl.pathname = `${proxyUrl.pathname === '/' ? '' : proxyUrl.pathname}${endpoint}`;
|
|
return proxyUrl;
|
|
}
|
|
|
|
protected getPublicIpEndpoint(): string {
|
|
return '/v0/health/__debug__';
|
|
}
|
|
|
|
protected getPublicIpFromResponse(data: any): string | null {
|
|
return typeof data.data?.ip?.exposed === 'object'
|
|
? data.data.ip.exposed['*'] || data.data.ip.machine
|
|
: data.data?.ip?.machine || null;
|
|
}
|
|
|
|
protected getHeaders(): Record<string, string> {
|
|
const headers: Record<string, string> = {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
};
|
|
|
|
if (Env.ENCRYPT_STREMTHRU_URLS) {
|
|
headers['X-StremThru-Authorization'] = `Basic ${this.config.credentials}`;
|
|
}
|
|
|
|
return headers;
|
|
}
|
|
|
|
protected async generateStreamUrls(
|
|
streams: ProxyStream[]
|
|
): Promise<string[] | null> {
|
|
const proxyUrl = this.generateProxyUrl('/v0/proxy');
|
|
|
|
if (!Env.ENCRYPT_STREMTHRU_URLS) {
|
|
proxyUrl.searchParams.set('token', this.config.credentials);
|
|
}
|
|
|
|
const data = new URLSearchParams();
|
|
|
|
streams.forEach((stream, i) => {
|
|
data.append('url', stream.url);
|
|
let req_headers = '';
|
|
if (stream.headers?.request) {
|
|
for (const [key, value] of Object.entries(stream.headers.request)) {
|
|
req_headers += `${key}: ${value}\n`;
|
|
}
|
|
}
|
|
data.append(`req_headers[${i}]`, req_headers);
|
|
if (stream.filename) {
|
|
data.append(`filename[${i}]`, stream.filename);
|
|
}
|
|
});
|
|
|
|
if (Env.LOG_SENSITIVE_INFO) {
|
|
logger.debug(`POST ${proxyUrl.toString()}`);
|
|
} else {
|
|
logger.debug(
|
|
`POST ${proxyUrl.protocol}://${maskSensitiveInfo(proxyUrl.hostname)}${proxyUrl.port ? `:${proxyUrl.port}` : ''}/v0/proxy`
|
|
);
|
|
}
|
|
|
|
const response = await fetch(proxyUrl.toString(), {
|
|
method: 'POST',
|
|
headers: this.getHeaders(),
|
|
body: data,
|
|
signal: AbortSignal.timeout(30000),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`${response.status}: ${response.statusText}`);
|
|
}
|
|
|
|
let responseData: any;
|
|
try {
|
|
responseData = await response.json();
|
|
} catch (error) {
|
|
const text = await response.text();
|
|
logger.debug(`Response body: ${text}`);
|
|
throw new Error('Failed to parse JSON response from StremThru');
|
|
}
|
|
|
|
if (responseData.error) {
|
|
throw new Error(responseData.error);
|
|
}
|
|
|
|
if (responseData.data?.items) {
|
|
return responseData.data.items;
|
|
} else {
|
|
throw new Error('No URLs were returned from StremThru');
|
|
}
|
|
}
|
|
}
|