Telegraf Webhook Slow Join Event

mail@pastecode.io avatar
unknown
javascript
a year ago
8.3 kB
3
Indexable
Never
import express from "express";
import axios from "axios";
import { Telegraf, Input } from "telegraf";
import getPayload from "./getPayload.js";
import "dotenv/config";
import alreadyJoinChat from "./alreadyJoinChat.js";
import fiveMinutes from "./fiveMinutes.js";
import mention from "./mention.js";
import getInviteLink from "./getInviteLink.js";

interface ICDNSyndicationResponse {
  mediaDetails: {
    type?: "video";
    video_info: {
      variants: {
        bitrate: number;
        content_type: "video/mp4" | "application/x-mpegURL";
        url: string;
      }[];
    };
  }[];
}
interface ITaskManager {
  [userId: number]:
    | {
        joinVidGroup?: {
          messageId: number;
          deleteMessageTimeout: NodeJS.Timeout;
          kickMemberTimeout: NodeJS.Timeout;
          clearTaskTimeout: NodeJS.Timeout;
        };
        leftBaseGroup?: {
          messageId: number;
          deleteMessageTimeout: NodeJS.Timeout;
          kickMemberTimeout: NodeJS.Timeout;
          clearTaskTimeout: NodeJS.Timeout;
        };
      }
    | undefined;
}
const env = process.env;
const token = env.BOT_TOKEN;
const vidGroupId = Number(env.VID_GROUP_ID);
const baseGroupId = Number(env.BASE_GROUP_ID);
const executeTime = 5 * 60000;

if (!token) {
  throw Error("Please provide BOT_TOKEN");
}
if (!vidGroupId) {
  throw Error("Please provide VID_GROUP_ID");
}
if (!baseGroupId) {
  throw Error("Please provide BASE_GROUP_ID");
}
const app = new Telegraf(token);
const server = express();
const taskManager: ITaskManager = {};
const port = env.PORT || 8080;

server.use(await app.createWebhook({ domain: "https://fair-puce-snail-ring.cyclic.app/" }));

app.command("/d", async (ctx) => {
  try {
    await app.telegram.deleteMessage(ctx.chat.id, ctx.message.message_id);

    const tweetUrl = getPayload(ctx.message.text);
    const tweetId = new URL(tweetUrl).pathname.split("/")[3];
    const cdnSyndicationUrl = "https://cdn.syndication.twimg.com/tweet-result?id=" + tweetId;
    const response = await axios.get<ICDNSyndicationResponse>(cdnSyndicationUrl);
    const vids = response.data.mediaDetails.filter((media) => media.type === "video");
    const mp4Vids = vids.map((vid) =>
      vid.video_info.variants.filter((variant) => variant.content_type === "video/mp4")
    );
    mp4Vids.forEach(async (vid) => {
      const highestBitrate = Math.max(...vid.map((variant) => variant.bitrate));
      const bestVideo = vid.find((variant) => variant.bitrate === highestBitrate);
      await app.telegram.sendVideo(ctx.chat.id, Input.fromURL(bestVideo!.url));
    });
  } catch (err) {
    return ctx.reply((err as any).message);
  }
});
app.on("new_chat_members", async (ctx) => {
  try {
    const newMembers = ctx.message.new_chat_members;

    if (ctx.chat.id === vidGroupId) {
      newMembers.forEach(async (user) => {
        if (!(await alreadyJoinChat(app, baseGroupId, user.id))) {
          const message = await ctx.replyWithHTML(
            `welcome ${mention(user.first_name, user.id)}\n\nplease join this group ${await getInviteLink(
              app,
              baseGroupId
            )} or you will be kicked on 5 minutes`
          );
          const kickMemberTimeout = setTimeout(async () => {
            await app.telegram.banChatMember(vidGroupId, user.id, fiveMinutes());
          }, executeTime);
          const deleteMessageTimeout = setTimeout(async () => {
            await app.telegram.deleteMessage(vidGroupId, message.message_id);
          }, executeTime);
          const clearTaskTimeout = setTimeout(() => {
            // this is needed for the sake of typescript
            // see https://t.me/thedevs_js/516215
            const userTask = taskManager[user.id];

            if (userTask) {
              delete userTask.joinVidGroup;
            }
          }, executeTime);

          taskManager[user.id] = {
            joinVidGroup: {
              messageId: message.message_id,
              kickMemberTimeout,
              deleteMessageTimeout,
              clearTaskTimeout,
            },
          };
        }
      });
    }
    if (ctx.chat.id === baseGroupId) {
      newMembers.forEach(async (user) => {
        if (await alreadyJoinChat(app, vidGroupId, user.id)) {
          const currentUser = taskManager[user.id];
          if (!currentUser) return;

          if (currentUser.joinVidGroup) {
            clearTimeout(currentUser.joinVidGroup.kickMemberTimeout);
            clearTimeout(currentUser.joinVidGroup.deleteMessageTimeout);
            clearTimeout(currentUser.joinVidGroup.clearTaskTimeout);

            await app.telegram.deleteMessage(vidGroupId, currentUser.joinVidGroup.messageId);
            delete currentUser.joinVidGroup;
          }
          if (currentUser.leftBaseGroup) {
            clearTimeout(currentUser.leftBaseGroup.kickMemberTimeout);
            clearTimeout(currentUser.leftBaseGroup.deleteMessageTimeout);
            clearTimeout(currentUser.leftBaseGroup.clearTaskTimeout);

            await app.telegram.deleteMessage(vidGroupId, currentUser.leftBaseGroup.messageId);
            delete currentUser.leftBaseGroup;
          }
          if (!currentUser.joinVidGroup && !currentUser.leftBaseGroup) {
            delete taskManager[user.id];
          }
        }
      });
    }
  } catch (err) {
    return ctx.reply((err as any).message);
  }
});
app.on("left_chat_member", async (ctx) => {
  try {
    const user = ctx.message.left_chat_member;

    if (ctx.chat.id === vidGroupId) {
      const currentUser = taskManager[user.id];
      if (!currentUser) return;

      if (currentUser.joinVidGroup) {
        clearTimeout(currentUser.joinVidGroup.kickMemberTimeout);
        clearTimeout(currentUser.joinVidGroup.deleteMessageTimeout);
        clearTimeout(currentUser.joinVidGroup.clearTaskTimeout);

        await app.telegram.deleteMessage(vidGroupId, currentUser.joinVidGroup.messageId);
        delete currentUser.joinVidGroup;
      }
      if (currentUser.leftBaseGroup) {
        clearTimeout(currentUser.leftBaseGroup.kickMemberTimeout);
        clearTimeout(currentUser.leftBaseGroup.deleteMessageTimeout);
        clearTimeout(currentUser.leftBaseGroup.clearTaskTimeout);

        await app.telegram.deleteMessage(vidGroupId, currentUser.leftBaseGroup.messageId);
        delete currentUser.leftBaseGroup;
      }
      if (!currentUser.joinVidGroup && !currentUser.leftBaseGroup) {
        delete taskManager[user.id];
      }
    }
    if (ctx.chat.id === baseGroupId) {
      if (await alreadyJoinChat(app, vidGroupId, user.id)) {
        const message = await app.telegram.sendMessage(
          vidGroupId,
          `brody ${mention(
            user.first_name,
            user.id
          )}\nkarena lu telah keluar maka lu akan otomatis gw kick dalam 5 menit yahaha\n\nuntuk membatalkan silahkan gabung kembali ${await getInviteLink(
            app,
            baseGroupId
          )}`,
          { parse_mode: "HTML" }
        );
        const kickMemberTimeout = setTimeout(async () => {
          await app.telegram.banChatMember(vidGroupId, user.id, fiveMinutes());
        }, executeTime);
        const deleteMessageTimeout = setTimeout(async () => {
          await app.telegram.deleteMessage(vidGroupId, message.message_id);
        }, executeTime);
        const clearTaskTimeout = setTimeout(() => {
          // this is needed for the sake of typescript
          // see https://t.me/thedevs_js/516215
          const userTask = taskManager[user.id];

          if (userTask) {
            delete userTask.joinVidGroup;
          }
        }, executeTime);
        taskManager[user.id] = {
          joinVidGroup: {
            messageId: message.message_id,
            kickMemberTimeout,
            deleteMessageTimeout,
            clearTaskTimeout,
          },
        };
      }
    }
  } catch (err) {
    return ctx.reply((err as any).message);
  }
});
server.listen(port, () => console.log(`Server listening on ${port}`));

process.once("SIGINT", () => app.stop("SIGINT"));
process.once("SIGTERM", () => app.stop("SIGTERM"));