bot-ru.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import TelegramBot, { SendMessageOptions } from "node-telegram-bot-api";
  2. import * as dotenv from "dotenv";
  3. import axios from "axios";
  4. import moment from "moment";
  5. dotenv.config();
  6. const tgApiKey = process.env.TG_API_KEY_RU || "";
  7. const bot = new TelegramBot(tgApiKey, { polling: true });
  8. moment.locale("ru");
  9. const loadScoringPeriodData = async () => {
  10. const url =
  11. "https://raw.githubusercontent.com/Joystream/founding-members/main/data/fm-info.json";
  12. const { data } = await axios.get(url);
  13. return data.scoringPeriodsFull;
  14. };
  15. interface ScoringPeriodData {
  16. currentScoringPeriod: {
  17. scoringPeriodId: number;
  18. started: string;
  19. ends: string;
  20. referralCode: number;
  21. };
  22. lastPeriod: {
  23. scoringPeriodId: number;
  24. started: string;
  25. ends: string;
  26. referralCode: number;
  27. totalDirectScore: number;
  28. totalReferralScore: number;
  29. highlights: string[];
  30. };
  31. }
  32. let nextSyncDate = moment();
  33. let scoringData = {} as ScoringPeriodData;
  34. let lastGradedPeriod = null as number | null;
  35. const messageDeletionTimeout = 60000; // 1 minute
  36. bot.on("message", async (msg: TelegramBot.Message) => {
  37. if (nextSyncDate.isBefore(moment())) {
  38. scoringData = await loadScoringPeriodData();
  39. lastGradedPeriod = scoringData.lastPeriod.scoringPeriodId;
  40. nextSyncDate = moment.parseZone(scoringData.currentScoringPeriod.ends);
  41. }
  42. if (msg && msg.from) {
  43. console.log(msg.chat);
  44. const chatId = msg.chat.id;
  45. const username = `${msg.from.first_name} ${
  46. msg.from.last_name || ""
  47. }`.trim();
  48. const userParsed = `[${username}](tg://user?id=${msg.from.id})`;
  49. const leaderboardLink = `[Проверить баллы](https://t.me/JoystreamLeaderboardBot)`;
  50. const options: SendMessageOptions = { parse_mode: "Markdown", disable_web_page_preview: true };
  51. if (msg.text?.startsWith("/scoring")) {
  52. const startDate = moment.parseZone(
  53. scoringData.currentScoringPeriod.started
  54. );
  55. const endDate = moment.parseZone(scoringData.currentScoringPeriod.ends);
  56. const duration = moment.duration(endDate.diff(moment()));
  57. const daysDuration = duration.asDays().toFixed();
  58. let dayText = "дней";
  59. if (daysDuration === "1") {
  60. dayText = "день";
  61. } else if (
  62. daysDuration === "2" ||
  63. daysDuration === "3" ||
  64. daysDuration === "4"
  65. ) {
  66. dayText = "дня";
  67. }
  68. const daysLeft = `***${duration
  69. .asDays()
  70. .toFixed()} ${dayText} в ${endDate.format(
  71. "dddd DD MMM"
  72. )} в ${endDate.format("HH:mm")}***`;
  73. const deadline = endDate.add(5, "d").format("dddd DD MMM HH:mm");
  74. const prevDeadline = startDate.add(5, "d").format("dddd DD MMM HH:mm");
  75. const hello = `Приветствую ${userParsed}!\n`;
  76. const currentPeriodId = scoringData.currentScoringPeriod.scoringPeriodId;
  77. const prevPeriodId = scoringData.currentScoringPeriod.scoringPeriodId - 1;
  78. const currentScoring = `Текущий отчетный период ***#${currentPeriodId}*** заканчивается через ${daysLeft}\n`;
  79. const currentDeadline = `Успей [подать отчет](https://www.joystream.org/founding-members/form) за период ***#${currentPeriodId}*** до окончания срока подачи ***${deadline}***\n`;
  80. const isLastScoringClosed = endDate
  81. .add(5, "d")
  82. .subtract(2, "w")
  83. .isAfter(moment());
  84. const previousPeriodDeadline = isLastScoringClosed
  85. ? `Подача отчетов за прошлый период ***#${prevPeriodId}*** окончена\n`
  86. : `Подача отчетов за прошлый период ***#${prevPeriodId}*** открыта до ***${prevDeadline}***\n`;
  87. const latestGradedPeriod = `Последний период с начисленными баллами - ***#${lastGradedPeriod}*** - ${leaderboardLink}`;
  88. const messageContent = `${hello}${currentScoring}${currentDeadline}${previousPeriodDeadline}${latestGradedPeriod}`;
  89. bot.sendMessage(chatId, messageContent, options).then((message) => {
  90. try {
  91. bot.deleteMessage(chatId, msg.message_id.toString());
  92. } catch (e) {}
  93. setTimeout(() => {
  94. try {
  95. bot.deleteMessage(chatId, message.message_id.toString());
  96. } catch (e) {}
  97. }, messageDeletionTimeout);
  98. });
  99. }
  100. }
  101. });