Skip to content

Commit

Permalink
Add custom scripts for rss download
Browse files Browse the repository at this point in the history
  • Loading branch information
zoriya committed Aug 10, 2024
1 parent 404d8c7 commit e2286ed
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ const DownloadRuleForm: FC<DownloadRuleFormProps> = ({
)}
</Textbox>
</FormRow>
<FormRow>
<Textbox
id="script"
label={i18n._('feeds.script')}
defaultValue={rule.script}
/>
</FormRow>
<FormRow>
<FormRowItem>
<FilesystemBrowserTextbox
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const initialRule: AddRuleOptions = {
feedIDs: [],
match: '',
exclude: '',
script: '',
tags: [],
destination: '',
startOnLoad: false,
Expand Down Expand Up @@ -64,6 +65,7 @@ interface RuleFormData {
feedID: string;
label: string;
match: string;
script: string;
tags: string;
isBasePath: boolean;
startOnLoad: boolean;
Expand Down Expand Up @@ -140,6 +142,7 @@ const DownloadRulesTab: FC = () => {
field: formData.field,
match: formData.match ?? initialRule.match,
exclude: formData.exclude ?? initialRule.exclude,
script: formData.script ?? initialRule.script,
destination: formData.destination ?? initialRule.destination,
tags: formData.tags?.split(',') ?? initialRule.tags,
startOnLoad: formData.startOnLoad ?? initialRule.startOnLoad,
Expand Down
1 change: 1 addition & 0 deletions client/src/javascript/i18n/strings/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
"feeds.no.items.matching": "No items matching search term.",
"feeds.no.rules.defined": "No rules defined.",
"feeds.regEx": "RegEx",
"feeds.script": "Script",
"feeds.search": "Search term",
"feeds.search.term": "Search term",
"feeds.select.feed": "Select Feed",
Expand Down
1 change: 1 addition & 0 deletions server/routes/api/feed-monitor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ describe('PUT /api/feed-monitor/rules', () => {
feedIDs: [''],
match: '',
exclude: '.*',
script: '',
destination: tempDirectory,
tags: ['FeedItem'],
startOnLoad: false,
Expand Down
1 change: 1 addition & 0 deletions server/services/feedService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class FeedService extends BaseService<Record<string, never>> {
field: rule.field,
match: rule.match,
exclude: rule.exclude,
script: rule.script,
startOnLoad: rule.startOnLoad,
isBasePath: rule.isBasePath,
});
Expand Down
23 changes: 20 additions & 3 deletions server/util/feedUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {cdata as matchCDATA} from '../../shared/util/regEx';

import type {AddTorrentByURLOptions} from '../../shared/schema/api/torrents';
import type {Rule} from '../../shared/types/Feed';
import { spawn } from 'child_process';

interface PendingDownloadItems
extends Required<Pick<AddTorrentByURLOptions, 'urls' | 'destination' | 'tags' | 'start'>> {
Expand Down Expand Up @@ -54,17 +55,33 @@ export const getTorrentUrlsFromFeedItem = (feedItem: FeedItem): Array<string> =>
return [];
};

const execAsync = (...command: string[]) => {
const p = spawn(command[0], command.slice(1));
return new Promise((resolveFunc) => {
p.stdout.on("data", (x) => {
process.stdout.write(x.toString());
});
p.stderr.on("data", (x) => {
process.stderr.write(x.toString());
});
p.on("exit", (code) => {
resolveFunc(code);
});
});
}

export const getFeedItemsMatchingRules = (
feedItems: Array<FeedItem>,
rules: Array<Rule>,
): Array<PendingDownloadItems> => {
return feedItems.reduce((matchedItems: Array<PendingDownloadItems>, feedItem) => {
rules.forEach((rule) => {
rules.forEach(async (rule) => {
const matchField = rule.field ? (feedItem[rule.field] as string) : (feedItem.title as string);
const isMatched = new RegExp(rule.match, 'gi').test(matchField);
const isMatched = rule.match === '' || new RegExp(rule.match, 'gi').test(matchField);
const isExcluded = rule.exclude !== '' && new RegExp(rule.exclude, 'gi').test(matchField);
const scriptMatch = rule.script === '' || await execAsync(rule.script) === 80;

if (isMatched && !isExcluded) {
if (isMatched && !isExcluded && scriptMatch) {
const torrentUrls = getTorrentUrlsFromFeedItem(feedItem);
const isAlreadyDownloaded = matchedItems.some((matchedItem) =>
torrentUrls.every((url) => matchedItem.urls.includes(url)),
Expand Down
2 changes: 2 additions & 0 deletions shared/types/Feed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export interface Rule {
match: string;
// Regular expression to exclude items.
exclude: string;
// Custom script to select if the item should be downloaded (exit with status 80 to download).
script: string;
// Destination path where matched items are downloaded to.
destination: string;
// Tags to be added when items are queued for download.
Expand Down

0 comments on commit e2286ed

Please sign in to comment.