import { type Handler } from "aws-lambda"; import { createRestAPIClient } from "masto"; import ScraperArticles from "../utils/scraper-articles"; import RedisClient from "../libs/redis-client"; import LogLevels from "../enums/log-levels"; import Emojis from "../enums/emojis"; import config from "../config"; import { type IScraperArticlesOptions } from "../interfaces/scaper-articles-options"; export default class Portal { private readonly _name: string; private readonly _scraperArticlesOptions: IScraperArticlesOptions private readonly _redisClient: RedisClient; private readonly _mastodonClient: any private readonly _scraperArticles: ScraperArticles; constructor (name: string, accessToken: string, scraperArticlesOptions: IScraperArticlesOptions) { this._name = name; this._scraperArticlesOptions = scraperArticlesOptions; this._scraperArticles = new ScraperArticles(this._name, this._scraperArticlesOptions); this._redisClient = new RedisClient(); this._mastodonClient = createRestAPIClient({ url: config.MASTODON_URL, accessToken }); } public async run (event?: any, context?: any): Promise { try { const articles = await this._scraperArticles.getArticles(); if (config.LOG_LEVEL === LogLevels.DEBUG) { console.log(`${this._name} | Articles`, articles); } let totalPublished = 0; const length = articles.length; // Order has to be reversed to appear in the correct order when posting for (let i = length - 1; i >= 0; i--) { const article = articles[i]; const exists = await this._redisClient.retrieve(article.link); if (exists !== null) { continue; } const date = new Date(Date.now()).toLocaleDateString(); let message = `${Emojis.NEWS} ${article.title}`; if (article.content !== "") { message += `\n\n${article.content}`; } message += `\n${Emojis.LINK} ${article.link}`; if (message.trim().length === 0) { continue; } // Adding hashtags if there is if (this._scraperArticlesOptions.hashtags) { message += `\n${Emojis.TAGS} ` ; this._scraperArticlesOptions.hashtags.forEach(hashtag => { message += "#" + hashtag + " " }); } message.trimEnd(); // To avoid publiposts (I'm lookint at you La Tercera >:-|) if (article.link.includes("publirreportajes")) { continue; } if (article.title.includes("Exclusivo suscriptor")) { article.title = article.title.replace("Exclusivo suscriptor", ""); } // If the message is more than 400 characters long, its very likely due to the article.content if (message.length > 400) { message = `${Emojis.NEWS} ${article.title}.\n\n${article.content}`.substring(0, 397) + "..."; message += `\n${Emojis.LINK} ${article.link}`; } if (this._name.toUpperCase() == "Chile Cultura".toUpperCase()) { // Icons Chilecultura let regex = new RegExp(/\n(\d{1,2} \w{3})\s*\n?\s*-\s*(\d{1,2} \w{3})/); message = message.replace("date_range", `${Emojis.CALENDAR} `); message = message.replace(regex, (match, p1, p2) => { return `${p1} - ${p2}`; }); message = message.replace("location_on", Emojis.PIN).replace(`${Emojis.PIN}\n`, `${Emojis.PIN} `); // Expresión regular para capturar el texto antes del 📆 seguido de una fecha regex = new RegExp(/(.*?)📆 (\d{1,2} \w{3} - \d{1,2} \w{3})/); message = message.replace(regex, (match, p1, p2) => { return `🎭 ${p1}\n📆 ${p2}`; }); } const mediaIds: any[] = []; if (article.image !== null && article.image !== undefined) { const media = await this._mastodonClient.v2.media.create({ file: article.image, description: article.title }); mediaIds.push(media.id); } console.log(`\n${this._name} | Sending`, message); await this._mastodonClient.v1.statuses.create({ status: message, mediaIds }); await this._redisClient.store( article.link, date, { EX: this._scraperArticlesOptions.cacheExpiration ? this._scraperArticlesOptions.cacheExpiration : 60 * 60 * 24 } // EX: 24 hrs expiration ); totalPublished++ } console.log(`${this._name} | Published ${totalPublished} new articles`); } catch (err: any) { console.log(`${this._name} | An error has occurred\n`) console.error(err.message); if (config.LOG_LEVEL === LogLevels.DEBUG) { if (event !== undefined) { console.debug("\nEvent\n"); console.debug(event); } if (context !== undefined) { console.debug("\nContext\n"); console.debug(context); } } } console.log(`${this._name} | Finished`); } public getHandler (): Handler { return async (event, context) => { await this.run(event, context); } } }