import Parser from "rss-parser"; import { ListenerRSSInfos as ListenerInfo, ListenerRSSInfos, } from "./Models/ListenerRSSInfos"; import EventEmitter from "events"; const DEFAULT_TIMELOOP: number = 5 * 60; // default timeloop is 5 min /** * Emit 'update' when he's making a fetch during the start fun * Emit 'error' when the fetch has an issue * Emit 'newEntries' when the fetch has new entris */ export class ListenerRss extends EventEmitter { address: string = ""; timeloop: number = DEFAULT_TIMELOOP; // time in seconds customfields?: { [key: string]: string[] | string }; // private fields parser: Parser; loopRunning: boolean = false; lastEntriesLinks: string[] = []; /** * @brief constructor * @param config ListenerRSSInfos interface who contains the ListenerInfos */ constructor(config: ListenerInfo) { super(); this.address = config.address; this.timeloop = config.timeloop === undefined ? DEFAULT_TIMELOOP : config.timeloop; this.customfields = config.customfields; this.lastEntriesLinks = config.lastEntriesLinks === undefined ? [] : config.lastEntriesLinks; this.parser = this.generateParser(); } /** * @brief Private function. Is used to initilize the parser object with the customfields var */ generateParser() { const parserConfig = this.customfields && { customFields: { feed: [], item: Object.entries(this.customfields).map(([, value]) => { return Array.isArray(value) ? value[0] : value; }), }, }; return new Parser(parserConfig); } /** * @brief use the parseURL function from rss-parser with the objects data * @return return a promise with the received data */ fetchRSS(): Promise> { return this.parser.parseURL(this.address); } /** * @brief call the callback function each looptime */ start(): void { this.loopRunning = true; const fun: () => void = async () => { await Promise.resolve( this.fetchRSS() .then((obj: { [key: string]: any }) => { this.emit("update", obj); const updatedEntriesLinks = obj.items.map( (item: { link: string }) => item.link ); const newEntries = obj.items.filter( (item: { link: string }) => !this.lastEntriesLinks.includes(item.link) ); if (newEntries.length !== 0) { this.emit("newEntries", newEntries); } this.lastEntriesLinks = updatedEntriesLinks; }) .catch((err) => this.emit("error", err)) ); }; (async () => { while (this.loopRunning) { await fun(); await new Promise((res) => setTimeout(res, this.timeloop * 1000)); } })(); } /** * @brief stop the async function */ stop(): void { this.loopRunning = false; } /** * @brief parse the datas inti a ListenerRSSInfos object * @return return a ListenerRSSInfos object */ getProperty(): ListenerRSSInfos { return { address: this.address, customfields: this.customfields, lastEntriesLinks: this.lastEntriesLinks, timeloop: this.timeloop, }; } }