portal.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import { type Handler } from "aws-lambda";
  2. import { createRestAPIClient } from "masto";
  3. import ScraperArticles from "../utils/scraper-articles";
  4. import RedisClient from "../libs/redis-client";
  5. import LogLevels from "../enums/log-levels";
  6. import Emojis from "../enums/emojis";
  7. import config from "../config";
  8. import { type IScraperArticlesOptions } from "../interfaces/scaper-articles-options";
  9. export default class Portal {
  10. private readonly _name: string;
  11. private readonly _scraperArticlesOptions: IScraperArticlesOptions
  12. private readonly _redisClient: RedisClient;
  13. private readonly _mastodonClient: any
  14. private readonly _scraperArticles: ScraperArticles;
  15. constructor (name: string, accessToken: string, scraperArticlesOptions: IScraperArticlesOptions) {
  16. this._name = name;
  17. this._scraperArticlesOptions = scraperArticlesOptions;
  18. this._scraperArticles = new ScraperArticles(this._name, this._scraperArticlesOptions);
  19. this._redisClient = new RedisClient();
  20. this._mastodonClient = createRestAPIClient({ url: config.MASTODON_URL, accessToken });
  21. }
  22. public async run (event?: any, context?: any): Promise<void> {
  23. try {
  24. const articles = await this._scraperArticles.getArticles();
  25. if (config.LOG_LEVEL === LogLevels.DEBUG) {
  26. console.log(`${this._name} | Articles`, articles);
  27. }
  28. let totalPublished = 0;
  29. const length = articles.length;
  30. // Order has to be reversed to appear in the correct order when posting
  31. for (let i = length - 1; i >= 0; i--) {
  32. const article = articles[i];
  33. const exists = await this._redisClient.retrieve(article.link);
  34. if (exists !== null) {
  35. continue;
  36. }
  37. const date = new Date(Date.now()).toLocaleDateString();
  38. let message = `${Emojis.NEWS} ${article.title}`;
  39. if (article.content !== "") {
  40. message += `\n\n${article.content}`;
  41. }
  42. message += `\n${Emojis.LINK} ${article.link}`;
  43. if (message.trim().length === 0) {
  44. continue;
  45. }
  46. // Adding hashtags if there is
  47. if (this._scraperArticlesOptions.hashtags) {
  48. message += `\n${Emojis.TAGS} ` ;
  49. this._scraperArticlesOptions.hashtags.forEach(hashtag => {
  50. message += "#" + hashtag + " "
  51. });
  52. }
  53. message.trimEnd();
  54. // To avoid publiposts (I'm lookint at you La Tercera >:-|)
  55. if (article.link.includes("publirreportajes")) {
  56. continue;
  57. }
  58. if (article.title.includes("Exclusivo suscriptor")) {
  59. article.title = article.title.replace("Exclusivo suscriptor", "");
  60. }
  61. // If the message is more than 400 characters long, its very likely due to the article.content
  62. if (message.length > 400) {
  63. message = `${Emojis.NEWS} ${article.title}.\n\n${article.content}`.substring(0, 397) + "...";
  64. message += `\n${Emojis.LINK} ${article.link}`;
  65. }
  66. const mediaIds: any[] = [];
  67. if (article.image !== null && article.image !== undefined) {
  68. const media = await this._mastodonClient.v2.media.create({ file: article.image, description: article.title });
  69. mediaIds.push(media.id);
  70. }
  71. console.log(`\n${this._name} | Sending`, message);
  72. await this._mastodonClient.v1.statuses.create({ status: message, mediaIds });
  73. await this._redisClient.store(
  74. article.link,
  75. date,
  76. { EX: this._scraperArticlesOptions.cacheExpiration ? this._scraperArticlesOptions.cacheExpiration : 60 * 60 * 24 } // EX: 24 hrs expiration
  77. );
  78. totalPublished++
  79. }
  80. console.log(`${this._name} | Published ${totalPublished} new articles`);
  81. } catch (err: any) {
  82. console.log(`${this._name} | An error has occurred\n`)
  83. console.error(err.message);
  84. if (config.LOG_LEVEL === LogLevels.DEBUG) {
  85. if (event !== undefined) {
  86. console.debug("\nEvent\n");
  87. console.debug(event);
  88. }
  89. if (context !== undefined) {
  90. console.debug("\nContext\n");
  91. console.debug(context);
  92. }
  93. }
  94. }
  95. console.log(`${this._name} | Finished`);
  96. }
  97. public getHandler (): Handler {
  98. return async (event, context) => {
  99. await this.run(event, context);
  100. }
  101. }
  102. }