import { Injectable, NotFoundException } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { Action, Command, Ctx, Start, Update, } from 'nestjs-telegraf'; import { Context, Telegraf } from 'telegraf'; import { PrismaService } from '@/src/core/prisma/prisma.service'; import { BUTTONS } from '@/src/module/libs/telegram/telegram.button'; import { MESSAGES } from '@/src/module/libs/telegram/telegram.message'; import { SessionInfo } from '@/src/shared/types/session-metadata.types'; import { SponsorshipPlan, TokenType, User } from '@prisma/generated'; import { ProcessEnv } from '../../../shared/types/env'; @Update() @Injectable() export class TelegramService extends Telegraf { private readonly _token: string; constructor( private readonly prismaService: PrismaService, private readonly configService: ConfigService, ) { super(configService.getOrThrow('TELEGRAM_BOT_TOKEN')); this._token = configService.getOrThrow('TELEGRAM_BOT_TOKEN'); } @Start() public async onStart(@Ctx() ctx: Context) { const chatId = ctx.chat?.id.toString(); // @ts-ignore const token = ctx.message.text.split(' ')[1] as string; if (token) { const authToken = await this.prismaService.token.findUnique({ where: { token, type: TokenType.TELEGRAM_AUTH, }, }); if (!authToken?.userId) { await ctx.reply('Токен не найден'); return; } const hasExpired = new Date(authToken.expiresIn) < new Date(); if (hasExpired) { await ctx.reply(MESSAGES.invalidToken); return; } await this.connectTelegram(authToken.userId, chatId!); await this.prismaService.token.delete({ where: { id: authToken.id }, }); await ctx.replyWithHTML(MESSAGES.authSuccess, BUTTONS.authSuccess); return; } const user = await this.findUserByChatId(chatId!); if (user) { await this.onMe(ctx); return; } await ctx.replyWithHTML(MESSAGES.welcome, BUTTONS.profile); } @Command('me') @Action('me') public async onMe(@Ctx() ctx: Context) { const chatId = ctx.chat?.id.toString(); if (typeof chatId === 'undefined') { throw new NotFoundException('Пользователь не найден'); } const user = await this.findUserByChatId(chatId); if (!user) { throw new NotFoundException('Пользователь не найден'); } const followersCount = await this.prismaService.follow.count({ where: { followingId: user.id }, }); await ctx.replyWithHTML(MESSAGES.profile(user, followersCount), BUTTONS.profile); } @Command('follows') @Action('follows') public async onFollow(@Ctx() ctx: Context) { const chatId = ctx.chat?.id; if (typeof chatId === 'undefined') { throw new NotFoundException('Пользователь не найден'); } const user = await this.findUserByChatId(chatId.toString()); if (!user) { throw new NotFoundException('Пользователь не найден'); } const follows = await this.prismaService.follow.findMany({ where: { followerId: user.id }, include: { following: true }, }); if (follows.length > 0) { const followList = follows.map((follow) => MESSAGES.follows(follow.following)).join('\n'); const message = `Каналы, на которые Вы подписаны\n\n${followList}`; await ctx.replyWithHTML(message); return; } await ctx.replyWithHTML('❌ У Вас нет подписок'); } public async sendPasswordResetToken(chatId: string, token: string, metadata: SessionInfo) { await this.telegram.sendMessage(chatId, MESSAGES.resetPassword(token, metadata), { parse_mode: 'HTML' }); } public async sendDeactivateToken(chatId: string, token: string, metadata: SessionInfo) { await this.telegram.sendMessage(chatId, MESSAGES.deactivate(token, metadata), { parse_mode: 'HTML' }); } public async sendAccountDeletionToken(chatId: string) { await this.telegram.sendMessage(chatId, MESSAGES.accountDeleted, { parse_mode: 'HTML' }); } public async sendStreamStart(chatId: string, channel: User) { await this.telegram.sendMessage(chatId, MESSAGES.streamStart(channel), { parse_mode: 'HTML' }); } public async sendNewSponsorship(chatId: string, plan: SponsorshipPlan, sponsor: User) { await this.telegram.sendMessage(chatId, MESSAGES.newSponsorship(plan, sponsor), { parse_mode: 'HTML' }); } public async sendNewFollowing(chatId: string, follower: User) { const user = await this.findUserByChatId(chatId); if (!user) { throw new NotFoundException('Пользователь не найден'); } await this.telegram.sendMessage(chatId, MESSAGES.newFollowing(follower, user.followings.length), { parse_mode: 'HTML' }); } public async sendEnableTwoFactor(chatId: string) { return this.telegram.sendMessage(chatId, MESSAGES.enableTwoFactor, { parse_mode: 'HTML' }); } public async sendVerifyChannel(chatId: string) { return this.telegram.sendMessage(chatId, MESSAGES.verifyChannel, { parse_mode: 'HTML' }); } private async connectTelegram(userId: string, chatId: string) { return this.prismaService.user.update({ where: { id: userId }, data: { telegramId: chatId }, }); } private async findUserByChatId(chatId: string) { return this.prismaService.user.findUnique({ where: { telegramId: chatId }, include: { followings: true, followers: true, }, }); } }