|
@@ -0,0 +1,106 @@
|
|
|
+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/article-scaper-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, 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: config.MASTODON_ACCESS_TOKEN
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ public async run (event?: any, context?: any): Promise<void> {
|
|
|
+ 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${article.link}`;
|
|
|
+
|
|
|
+ if (message.trim().length === 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // To avoid publiposts (I'm lookint at you La Tercera >:-|)
|
|
|
+ if (article.link.includes("publirreportajes")) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 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${article.link}`;
|
|
|
+ }
|
|
|
+
|
|
|
+ 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: 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);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|