178 lines
5.5 KiB
TypeScript
178 lines
5.5 KiB
TypeScript
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<ProcessEnv>,
|
||
) {
|
||
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 = `<b>Каналы, на которые Вы подписаны</b>\n\n${followList}`;
|
||
await ctx.replyWithHTML(message);
|
||
|
||
return;
|
||
}
|
||
|
||
await ctx.replyWithHTML('❌ <b>У Вас нет подписок</b>');
|
||
}
|
||
|
||
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,
|
||
},
|
||
});
|
||
}
|
||
}
|