mirror of
https://github.com/Viren070/AIOStreams.git
synced 2025-12-01 23:14:04 +01:00
feat: Add regex-based stream sorting with API key protection (#156)
* feat: add regex-based stream sorting with API key protection * refactor: optimize regex matching for stream sorting * fix: add set regex sort pattern in loadFromConfig
This commit is contained in:
@@ -740,6 +740,29 @@ export class AIOStreams {
|
||||
(resolution) => resolution[b.resolution]
|
||||
)
|
||||
);
|
||||
} else if (field === 'regexSort') {
|
||||
if (!this.config.regexSortPattern) return 0;
|
||||
|
||||
try {
|
||||
const regex = new RegExp(this.config.regexSortPattern);
|
||||
const aMatch = a.filename ? regex.test(a.filename) : false;
|
||||
const bMatch = b.filename ? regex.test(b.filename) : false;
|
||||
|
||||
// If both match or both don't match, they are equal
|
||||
if ((aMatch && bMatch) || (!aMatch && !bMatch)) return 0;
|
||||
|
||||
// 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;
|
||||
if (direction === 'asc') {
|
||||
// In ascending order, matching files come last
|
||||
return aMatch ? 1 : -1;
|
||||
} else {
|
||||
// In descending order, matching files come first
|
||||
return aMatch ? -1 : 1;
|
||||
}
|
||||
} catch (e) {
|
||||
return 0;
|
||||
}
|
||||
} else if (field === 'cached') {
|
||||
let aCanbeCached = a.provider;
|
||||
let bCanbeCached = b.provider;
|
||||
|
||||
@@ -465,5 +465,25 @@ export function validateConfig(
|
||||
}
|
||||
}
|
||||
|
||||
if (config.regexSortPattern) {
|
||||
if (!config.apiKey) {
|
||||
return createResponse(
|
||||
false,
|
||||
'missingApiKey',
|
||||
'Regex sorting requires an API key to be set'
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
new RegExp(config.regexSortPattern);
|
||||
} catch (e) {
|
||||
return createResponse(
|
||||
false,
|
||||
'invalidRegexSortPattern',
|
||||
'Invalid regex sort pattern'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return createResponse(true, null, null);
|
||||
}
|
||||
|
||||
@@ -118,6 +118,7 @@ const defaultSortCriteria: SortBy[] = [
|
||||
{ quality: false },
|
||||
{ seeders: false, direction: 'desc' },
|
||||
{ addon: false },
|
||||
{ regexSort: false, direction: 'desc' },
|
||||
];
|
||||
|
||||
const defaultResolutions: Resolution[] = [
|
||||
@@ -219,6 +220,7 @@ export default function Configure() {
|
||||
excludePattern?: string;
|
||||
includePattern?: string;
|
||||
}>({});
|
||||
const [regexSortPattern, setRegexSortPattern] = useState<string>('');
|
||||
|
||||
useEffect(() => {
|
||||
// get config from the server
|
||||
@@ -284,6 +286,7 @@ export default function Configure() {
|
||||
excludePattern: regexFilters.excludePattern || undefined,
|
||||
includePattern: regexFilters.includePattern || undefined
|
||||
} : undefined,
|
||||
regexSortPattern: regexSortPattern,
|
||||
};
|
||||
return config;
|
||||
};
|
||||
@@ -553,6 +556,7 @@ export default function Configure() {
|
||||
})) || []
|
||||
);
|
||||
setRegexFilters(decodedConfig.regexFilters || {});
|
||||
setRegexSortPattern(decodedConfig.regexSortPattern || '');
|
||||
|
||||
setServices(loadValidServices(decodedConfig.services));
|
||||
setMaxMovieSize(
|
||||
@@ -1064,6 +1068,27 @@ export default function Configure() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{showApiKeyInput && (
|
||||
<div className={styles.section}>
|
||||
<h2 style={{ padding: '5px' }}>Regex Sort Pattern</h2>
|
||||
<p style={{ padding: '5px' }}>
|
||||
Enter a regex pattern to sort streams. This will sort streams based on whether their filename matches the pattern. Matching files will come first in descending order, and last in ascending order.
|
||||
</p>
|
||||
{/* <div className={styles.settingInput}> */}
|
||||
<input
|
||||
type="text"
|
||||
value={regexSortPattern}
|
||||
onChange={(e) => setRegexSortPattern(e.target.value)}
|
||||
placeholder="Example: \b(3L|BiZKiT|BLURANiUM)"
|
||||
style={{
|
||||
width: '97.5%',
|
||||
padding: '5px',
|
||||
marginLeft: '5px',
|
||||
}}
|
||||
className={styles.input}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className={styles.section}>
|
||||
<div className={styles.slidersSetting}>
|
||||
<div>
|
||||
|
||||
@@ -181,6 +181,7 @@ export interface Config {
|
||||
enabled: boolean;
|
||||
credentials: { [key: string]: string };
|
||||
}[];
|
||||
regexSortPattern?: string;
|
||||
}
|
||||
|
||||
interface BaseOptionDetail {
|
||||
|
||||
Reference in New Issue
Block a user