mirror of
https://github.com/zoriya/flood.git
synced 2025-12-05 23:06:20 +00:00
Add custom scripts for rss download
This commit is contained in:
@@ -220,6 +220,7 @@ describe('PUT /api/feed-monitor/rules', () => {
|
||||
feedIDs: [''],
|
||||
match: '',
|
||||
exclude: '.*',
|
||||
script: '',
|
||||
destination: tempDirectory,
|
||||
tags: ['FeedItem'],
|
||||
startOnLoad: false,
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
@@ -259,22 +260,22 @@ class FeedService extends BaseService<Record<string, never>> {
|
||||
}
|
||||
|
||||
handleNewItems = (feedReaderOptions: FeedReaderOptions, feedItems: Array<FeedItem>): void => {
|
||||
this.getPreviouslyMatchedUrls()
|
||||
.then((previouslyMatchedUrls) => {
|
||||
const {feedID, feedLabel} = feedReaderOptions;
|
||||
const applicableRules = this.rules[feedID];
|
||||
if (!applicableRules) return;
|
||||
this.getPreviouslyMatchedUrls().then(async (previouslyMatchedUrls) => {
|
||||
const {feedID, feedLabel} = feedReaderOptions;
|
||||
const applicableRules = this.rules[feedID];
|
||||
if (!applicableRules) return;
|
||||
|
||||
const itemsMatchingRules = getFeedItemsMatchingRules(feedItems, applicableRules);
|
||||
const itemsToDownload = itemsMatchingRules.filter((item) =>
|
||||
item.urls.some((url) => !previouslyMatchedUrls.includes(url)),
|
||||
);
|
||||
const itemsMatchingRules = await getFeedItemsMatchingRules(feedItems, applicableRules);
|
||||
const itemsToDownload = itemsMatchingRules.filter((item) =>
|
||||
item.urls.some((url) => !previouslyMatchedUrls.includes(url)),
|
||||
);
|
||||
|
||||
if (itemsToDownload.length === 0) {
|
||||
return;
|
||||
}
|
||||
if (itemsToDownload.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Promise.all(
|
||||
try {
|
||||
const ArrayOfURLArrays = await Promise.all(
|
||||
itemsToDownload.map(async (item): Promise<Array<string>> => {
|
||||
const {urls, destination, start, tags, ruleID} = item;
|
||||
|
||||
@@ -298,28 +299,29 @@ class FeedService extends BaseService<Record<string, never>> {
|
||||
|
||||
return urls;
|
||||
}),
|
||||
).then((ArrayOfURLArrays) => {
|
||||
const addedURLs = ArrayOfURLArrays.reduce(
|
||||
(URLArray: Array<string>, urls: Array<string>) => URLArray.concat(urls),
|
||||
[],
|
||||
);
|
||||
);
|
||||
const addedURLs = ArrayOfURLArrays.reduce(
|
||||
(URLArray: Array<string>, urls: Array<string>) => URLArray.concat(urls),
|
||||
[],
|
||||
);
|
||||
|
||||
this.db.update({type: 'matchedTorrents'}, {$push: {urls: {$each: addedURLs}}}, {upsert: true});
|
||||
this.db.update({type: 'matchedTorrents'}, {$push: {urls: {$each: addedURLs}}}, {upsert: true});
|
||||
|
||||
this.services?.notificationService.addNotification(
|
||||
itemsToDownload.map((item) => ({
|
||||
id: 'notification.feed.torrent.added',
|
||||
data: {
|
||||
title: item.matchTitle,
|
||||
feedLabel,
|
||||
ruleLabel: item.ruleLabel,
|
||||
},
|
||||
})),
|
||||
);
|
||||
this.services?.torrentService.fetchTorrentList();
|
||||
});
|
||||
})
|
||||
.catch(console.error);
|
||||
this.services?.notificationService.addNotification(
|
||||
itemsToDownload.map((item) => ({
|
||||
id: 'notification.feed.torrent.added',
|
||||
data: {
|
||||
title: item.matchTitle,
|
||||
feedLabel,
|
||||
ruleLabel: item.ruleLabel,
|
||||
},
|
||||
})),
|
||||
);
|
||||
this.services?.torrentService.fetchTorrentList();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
async removeItem(id: string): Promise<void> {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import {spawn} from 'node:child_process';
|
||||
|
||||
import type {FeedItem} from 'feedsub';
|
||||
|
||||
import type {AddTorrentByURLOptions} from '../../shared/schema/api/torrents';
|
||||
@@ -53,36 +55,58 @@ export const getTorrentUrlsFromFeedItem = (feedItem: FeedItem): Array<string> =>
|
||||
return [];
|
||||
};
|
||||
|
||||
export const getFeedItemsMatchingRules = (
|
||||
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 = async (
|
||||
feedItems: Array<FeedItem>,
|
||||
rules: Array<Rule>,
|
||||
): Array<PendingDownloadItems> => {
|
||||
return feedItems.reduce((matchedItems: Array<PendingDownloadItems>, feedItem) => {
|
||||
rules.forEach((rule) => {
|
||||
const matchField = rule.field ? (feedItem[rule.field] as string) : (feedItem.title as string);
|
||||
const isMatched = new RegExp(rule.match, 'gi').test(matchField);
|
||||
const isExcluded = rule.exclude !== '' && new RegExp(rule.exclude, 'gi').test(matchField);
|
||||
): Promise<Array<PendingDownloadItems>> => {
|
||||
const matchedItems: Array<PendingDownloadItems> = [];
|
||||
|
||||
if (isMatched && !isExcluded) {
|
||||
const torrentUrls = getTorrentUrlsFromFeedItem(feedItem);
|
||||
const isAlreadyDownloaded = matchedItems.some((matchedItem) =>
|
||||
torrentUrls.every((url) => matchedItem.urls.includes(url)),
|
||||
);
|
||||
await Promise.all(
|
||||
feedItems.map(async (feedItem) => {
|
||||
await Promise.all(
|
||||
rules.map(async (rule) => {
|
||||
const matchField = rule.field ? (feedItem[rule.field] as string) : (feedItem.title as string);
|
||||
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, matchField)) === 80;
|
||||
|
||||
if (!isAlreadyDownloaded && torrentUrls[0] != null) {
|
||||
matchedItems.push({
|
||||
urls: torrentUrls as [string, ...string[]],
|
||||
tags: rule.tags,
|
||||
matchTitle: feedItem.title as string,
|
||||
ruleID: rule._id,
|
||||
ruleLabel: rule.label,
|
||||
destination: rule.destination,
|
||||
start: rule.startOnLoad,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
if (isMatched && !isExcluded && scriptMatch) {
|
||||
const torrentUrls = getTorrentUrlsFromFeedItem(feedItem);
|
||||
const isAlreadyDownloaded = matchedItems.some((matchedItem) =>
|
||||
torrentUrls.every((url) => matchedItem.urls.includes(url)),
|
||||
);
|
||||
|
||||
return matchedItems;
|
||||
}, []);
|
||||
if (!isAlreadyDownloaded && torrentUrls[0] != null) {
|
||||
matchedItems.push({
|
||||
urls: torrentUrls as [string, ...string[]],
|
||||
tags: rule.tags,
|
||||
matchTitle: feedItem.title as string,
|
||||
ruleID: rule._id,
|
||||
ruleLabel: rule.label,
|
||||
destination: rule.destination,
|
||||
start: rule.startOnLoad,
|
||||
});
|
||||
}
|
||||
}
|
||||
}),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
return matchedItems;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user