style: format code

This commit is contained in:
Viren070
2025-05-04 19:54:18 +01:00
parent ace955b6e4
commit 4ab1c7dee1
6 changed files with 102 additions and 48 deletions
+36 -13
View File
@@ -54,8 +54,12 @@ export class AIOStreams {
this.config = config;
// Pre-compile regex patterns if they exist
if (this.config.regexSortPatterns) {
const regexSortPatterns = this.config.regexSortPatterns.split(/\s+/).filter(Boolean);
this.preCompiledRegexPatterns = regexSortPatterns.map(pattern => new RegExp(pattern));
const regexSortPatterns = this.config.regexSortPatterns
.split(/\s+/)
.filter(Boolean);
this.preCompiledRegexPatterns = regexSortPatterns.map(
(pattern) => new RegExp(pattern)
);
}
}
@@ -377,22 +381,35 @@ export class AIOStreams {
// apply regex filters if API key is set
if (this.config.apiKey && this.config.regexFilters) {
const { excludePattern, includePattern } = this.config.regexFilters;
if (excludePattern) {
const regexExclude = new RegExp(excludePattern, 'i');
if (parsedStream.filename && safeRegexTest(regexExclude, parsedStream.filename)) {
if (
parsedStream.filename &&
safeRegexTest(regexExclude, parsedStream.filename)
) {
skipReasons.excludeRegex++;
return false;
}
if (parsedStream.indexers && safeRegexTest(regexExclude, parsedStream.indexers)) {
if (
parsedStream.indexers &&
safeRegexTest(regexExclude, parsedStream.indexers)
) {
skipReasons.excludeRegex++;
return false;
}
}
if (includePattern) {
const regexInclude = new RegExp(includePattern, 'i');
if (!((parsedStream.filename && safeRegexTest(regexInclude, parsedStream.filename)) || (parsedStream.indexers && safeRegexTest(regexInclude, parsedStream.indexers)))) {
if (
!(
(parsedStream.filename &&
safeRegexTest(regexInclude, parsedStream.filename)) ||
(parsedStream.indexers &&
safeRegexTest(regexInclude, parsedStream.indexers))
)
) {
skipReasons.requiredRegex++;
return false;
}
@@ -677,7 +694,11 @@ export class AIOStreams {
// Identify streams that require proxying
const streamsToProxy = parsedStreams
.map((stream, index) => ({ stream, index }))
.filter(({ stream }) => stream.url && this.shouldProxyStream(stream, mediaFlowConfig, stremThruConfig));
.filter(
({ stream }) =>
stream.url &&
this.shouldProxyStream(stream, mediaFlowConfig, stremThruConfig)
);
const proxiedUrls = streamsToProxy.length
? mediaFlowConfig.mediaFlowEnabled
@@ -795,18 +816,20 @@ export class AIOStreams {
);
} else if (field === 'regexSort') {
if (!this.config.regexSortPatterns) return 0;
try {
for (let i = 0; i < this.preCompiledRegexPatterns.length; i++) {
const regex = this.preCompiledRegexPatterns[i];
const aMatch = a.filename ? safeRegexTest(regex, a.filename) : false;
const bMatch = b.filename ? safeRegexTest(regex, b.filename) : false;
// If both match or both don't match, continue to next pattern
if ((aMatch && bMatch) || (!aMatch && !bMatch)) continue;
// If one matches and the other doesn't, use direction to determine order
const direction = this.config.sortBy.find((sort) => Object.keys(sort)[0] === 'regexSort')?.direction;
const direction = this.config.sortBy.find(
(sort) => Object.keys(sort)[0] === 'regexSort'
)?.direction;
if (direction === 'asc') {
// In ascending order, matching files come last
return aMatch ? 1 : -1;
@@ -815,7 +838,7 @@ export class AIOStreams {
return aMatch ? -1 : 1;
}
}
// If we get here, no patterns matched or all patterns matched the same way
return 0;
} catch (e) {
+6 -3
View File
@@ -383,7 +383,10 @@ export function validateConfig(
);
}
if (config.mediaFlowConfig?.mediaFlowEnabled && config.stremThruConfig?.stremThruEnabled) {
if (
config.mediaFlowConfig?.mediaFlowEnabled &&
config.stremThruConfig?.stremThruEnabled
) {
return createResponse(
false,
'multipleProxyServices',
@@ -464,7 +467,7 @@ export function validateConfig(
'Regex filtering requires an API key to be set'
);
}
if (config.regexFilters.excludePattern) {
try {
new RegExp(config.regexFilters.excludePattern);
@@ -476,7 +479,7 @@ export function validateConfig(
);
}
}
if (config.regexFilters.includePattern) {
try {
new RegExp(config.regexFilters.includePattern);
+17 -5
View File
@@ -9,7 +9,11 @@ const DEFAULT_TIMEOUT = 1000; // 1 second timeout
* @param timeoutMs Optional timeout in milliseconds (default: 1000ms)
* @returns boolean indicating if the pattern matches the string
*/
export function safeRegexTest(pattern: RegExp, str: string, timeoutMs: number = DEFAULT_TIMEOUT): boolean {
export function safeRegexTest(
pattern: RegExp,
str: string,
timeoutMs: number = DEFAULT_TIMEOUT
): boolean {
try {
return isMatch(pattern, str, { timeout: timeoutMs });
} catch (error) {
@@ -25,7 +29,11 @@ export function safeRegexTest(pattern: RegExp, str: string, timeoutMs: number =
* @param timeoutMs Optional timeout in milliseconds (default: 1000ms)
* @returns The first match or undefined if no match or timeout
*/
export function safeRegexMatch(pattern: RegExp, str: string, timeoutMs: number = DEFAULT_TIMEOUT): string | undefined {
export function safeRegexMatch(
pattern: RegExp,
str: string,
timeoutMs: number = DEFAULT_TIMEOUT
): string | undefined {
try {
const match = firstMatch(pattern, str, { timeout: timeoutMs });
return match?.match;
@@ -42,12 +50,16 @@ export function safeRegexMatch(pattern: RegExp, str: string, timeoutMs: number =
* @param timeoutMs Optional timeout in milliseconds (default: 1000ms)
* @returns Array of matches or empty array if no matches or timeout
*/
export function safeRegexMatches(pattern: RegExp, str: string, timeoutMs: number = DEFAULT_TIMEOUT): string[] {
export function safeRegexMatches(
pattern: RegExp,
str: string,
timeoutMs: number = DEFAULT_TIMEOUT
): string[] {
try {
const matches = Array.from(pattern[Symbol.matchAll](str));
return matches.map(m => m[0]);
return matches.map((m) => m[0]);
} catch (error) {
console.error(`Regex matches timed out after ${timeoutMs}ms:`, error);
return [];
}
}
}
+39 -25
View File
@@ -302,10 +302,13 @@ export default function Configure() {
},
addons,
services,
regexFilters: (regexFilters.excludePattern || regexFilters.includePattern) ? {
excludePattern: regexFilters.excludePattern || undefined,
includePattern: regexFilters.includePattern || undefined
} : undefined,
regexFilters:
regexFilters.excludePattern || regexFilters.includePattern
? {
excludePattern: regexFilters.excludePattern || undefined,
includePattern: regexFilters.includePattern || undefined,
}
: undefined,
regexSortPatterns: regexSortPatterns,
};
return config;
@@ -1034,54 +1037,63 @@ export default function Configure() {
{showApiKeyInput && (
<div className={styles.section}>
<div>
<h2 style={{ padding: '5px', margin: '0px ' }}>Regex Filtering</h2>
<h2 style={{ padding: '5px', margin: '0px ' }}>
Regex Filtering
</h2>
<p style={{ margin: '5px 0 12px 5px' }}>
Configure regex patterns to filter streams. These filters will be applied in addition to keyword filters.
Configure regex patterns to filter streams. These filters will
be applied in addition to keyword filters.
</p>
</div>
<div style={{ marginBottom: '0px' }}>
<div className={styles.section}>
<h3 style={{ margin: '2px 0 2px 0' }}>Exclude Pattern</h3>
<p style={{ margin: '10px 0 10px 0' }}>
Enter a regex pattern to exclude streams. Streams will be excluded if their filename OR indexers match this pattern.
Enter a regex pattern to exclude streams. Streams will be
excluded if their filename OR indexers match this pattern.
</p>
<input
type="text"
value={regexFilters.excludePattern || ''}
onChange={(e) => setRegexFilters({
...regexFilters,
excludePattern: e.target.value
})}
onChange={(e) =>
setRegexFilters({
...regexFilters,
excludePattern: e.target.value,
})
}
placeholder="Example: \b(0neshot|1XBET)\b"
className={styles.input}
/>
<p className={styles.helpText}>
Example patterns:
<br />
- \b(0neshot|1XBET|24xHD)\b (exclude 0neshot, 1XBET, and 24xHD releases)
<br />
- ^.*Hi10.*$ (exclude Hi10 profile releases)
- \b(0neshot|1XBET|24xHD)\b (exclude 0neshot, 1XBET, and 24xHD
releases)
<br />- ^.*Hi10.*$ (exclude Hi10 profile releases)
</p>
</div>
<div className={styles.section} style={{ marginBottom: '0px' }}>
<h3 style={{ margin: '2px 0 2px 0' }}>Include Pattern</h3>
<p style={{ margin: '10px 0 10px 0' }}>
Enter a regex pattern to include streams. Only streams whose filename or indexers match this pattern will be included.
Enter a regex pattern to include streams. Only streams whose
filename or indexers match this pattern will be included.
</p>
<input
type="text"
value={regexFilters.includePattern || ''}
onChange={(e) => setRegexFilters({
...regexFilters,
includePattern: e.target.value
})}
onChange={(e) =>
setRegexFilters({
...regexFilters,
includePattern: e.target.value,
})
}
placeholder="Example: \b(3L|BiZKiT)\b"
className={styles.input}
/>
<p className={styles.helpText}>
Example patterns:
<br />
- \b(3L|BiZKiT|BLURANiUM)\b (only include 3L, BiZKiT, and BLURANiUM releases)
<br />- \b(3L|BiZKiT|BLURANiUM)\b (only include 3L, BiZKiT,
and BLURANiUM releases)
</p>
</div>
</div>
@@ -1092,8 +1104,10 @@ export default function Configure() {
<div className={styles.section}>
<h2 style={{ padding: '5px' }}>Regex Sort Patterns</h2>
<p style={{ padding: '5px' }}>
Enter space-separated regex patterns to sort streams. Streams will be sorted based on the order of matching patterns.
Matching files will come first in descending order, and last in ascending order for each pattern.
Enter space-separated regex patterns to sort streams. Streams will
be sorted based on the order of matching patterns. Matching files
will come first in descending order, and last in ascending order
for each pattern.
</p>
<input
type="text"
@@ -1109,8 +1123,8 @@ export default function Configure() {
/>
<p className={styles.helpText}>
Example patterns:
<br />
- \b(3L|BiZKiT|BLURANiUM)\b \b(FraMeSToR)\b (sort 3L/BiZKiT/BLURANiUM releases first, then FraMeSToR releases)
<br />- \b(3L|BiZKiT|BLURANiUM)\b \b(FraMeSToR)\b (sort
3L/BiZKiT/BLURANiUM releases first, then FraMeSToR releases)
</p>
</div>
)}
+2 -1
View File
@@ -88,7 +88,8 @@ export class Settings {
public static readonly MAX_KEYWORD_FILTERS = process.env.MAX_KEYWORD_FILTERS
? parseInt(process.env.MAX_KEYWORD_FILTERS)
: 30;
public static readonly MAX_REGEX_SORT_PATTERNS = process.env.MAX_REGEX_SORT_PATTERNS
public static readonly MAX_REGEX_SORT_PATTERNS = process.env
.MAX_REGEX_SORT_PATTERNS
? parseInt(process.env.MAX_REGEX_SORT_PATTERNS)
: 20;
public static readonly MAX_MOVIE_SIZE = process.env.MAX_MOVIE_SIZE
+2 -1
View File
@@ -47,7 +47,8 @@ export async function generateStremThruStreams(
});
if (Settings.ENCRYPT_STREMTHRU_URLS) {
headers['X-StremThru-Authorization'] = `Basic ${stremThruConfig.credential}`;
headers['X-StremThru-Authorization'] =
`Basic ${stremThruConfig.credential}`;
} else {
proxyUrl.searchParams.set('token', stremThruConfig.credential);
}