1
0
Fork 0
mirror of https://github.com/muerwre/vk-tg-bot.git synced 2025-04-24 22:46:41 +07:00

added pop action for telegram

This commit is contained in:
Fedor Katurov 2021-05-28 15:04:39 +07:00
parent c1fb45742e
commit c709bbf94c
9 changed files with 90 additions and 8 deletions

View file

@ -2,6 +2,7 @@ http:
port: 80 port: 80
telegram: telegram:
# Get it from bot father # Get it from bot father
owners: []
key: '' key: ''
webhook: webhook:
url: https://something.org/webhook url: https://something.org/webhook

View file

@ -1,12 +1,15 @@
import { TelegramService } from "../../service/telegram"; import { TelegramService } from "../../service/telegram";
import axios from "axios"; import axios from "axios";
import logger from "../../service/logger"; import logger from "../../service/logger";
import { PostgresDB } from "../../service/db/postgres";
import { Readable } from "stream";
export class TelegramApi { export class TelegramApi {
constructor(private telegram: TelegramService) {} constructor(private telegram: TelegramService, private db: PostgresDB) {}
public listen() { public listen() {
this.telegram.bot.command("ping", TelegramApi.ping); this.telegram.bot.command("ping", TelegramApi.ping);
this.telegram.bot.command("pop", this.pop);
return; return;
} }
@ -19,6 +22,30 @@ export class TelegramApi {
); );
} }
/**
* Pops last recorded request from vk
*/
private pop = async (ctx, next) => {
const username = ctx?.update?.message?.from?.username;
if (!username || !this.telegram.isOwner(`@${username}`)) {
return;
}
const { body, createdAt } = await this.db.popRequest();
const source = JSON.stringify(body, null, 2);
await ctx.replyWithDocument(
{
source: Readable.from(source),
filename: `debug-${createdAt.toISOString()}.txt`,
},
{ caption: `recorded at: ${createdAt.toLocaleString()}` }
);
return next();
};
/** /**
* Probes webhook url and falls back to polling mode on error * Probes webhook url and falls back to polling mode on error
*/ */

View file

@ -16,7 +16,7 @@ async function main() {
const telegram = new TelegramService(config.telegram); const telegram = new TelegramService(config.telegram);
const vkService = new VkService(config.vk, telegram, config.templates, db); const vkService = new VkService(config.vk, telegram, config.templates, db);
const telegramApi = new TelegramApi(telegram); const telegramApi = new TelegramApi(telegram, db);
telegramApi.listen(); telegramApi.listen();
await telegram.start(); await telegram.start();

View file

@ -0,0 +1,19 @@
import {
Column,
CreateDateColumn,
Entity,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from "typeorm";
@Entity()
export class Request {
@PrimaryGeneratedColumn()
id!: number;
@Column("simple-json", { default: {}, nullable: false })
body!: Record<any, any>;
@CreateDateColumn()
createdAt!: Date;
@UpdateDateColumn()
updatedAt!: Date;
}

View file

@ -8,6 +8,7 @@ import { Like } from "./entities/Like";
import { Event } from "./entities/Event"; import { Event } from "./entities/Event";
import { Post } from "./entities/Post"; import { Post } from "./entities/Post";
import { LoggerConfig } from "../../logger/types"; import { LoggerConfig } from "../../logger/types";
import { Request } from "./entities/Request";
const entities = [path.join(__dirname, "./entities/*")]; const entities = [path.join(__dirname, "./entities/*")];
@ -16,6 +17,7 @@ export class PostgresDB implements Storage {
private events!: Repository<Event>; private events!: Repository<Event>;
private likes!: Repository<Like>; private likes!: Repository<Like>;
private posts!: Repository<Post>; private posts!: Repository<Post>;
private requests!: Repository<Request>;
constructor( constructor(
private config: PostgresConfig, private config: PostgresConfig,
@ -38,6 +40,7 @@ export class PostgresDB implements Storage {
this.events = this.connection.getRepository(Event); this.events = this.connection.getRepository(Event);
this.likes = this.connection.getRepository(Like); this.likes = this.connection.getRepository(Like);
this.posts = this.connection.getRepository(Post); this.posts = this.connection.getRepository(Post);
this.requests = this.connection.getRepository(Request);
logger.info(`db connected to ${this.config.uri}`); logger.info(`db connected to ${this.config.uri}`);
}; };
@ -132,6 +135,22 @@ export class PostgresDB implements Storage {
return this.posts.save({ eventId, text, vkPostId }); return this.posts.save({ eventId, text, vkPostId });
}; };
insertRequest = async (body: Record<any, any>) => {
return this.requests.save({ body });
};
/**
* Returns last request with shift
*/
popRequest = async (skip: number = 0) => {
const requests = await this.requests.find({
order: { createdAt: "DESC" },
take: 1,
skip,
});
return requests[0];
};
healthcheck = async () => { healthcheck = async () => {
try { try {
await this.connection.query("SELECT 1"); await this.connection.query("SELECT 1");

View file

@ -149,4 +149,13 @@ export class TelegramService {
throw e; throw e;
} }
}; };
/**
* Checks if user is owner
*/
public isOwner = (username: string) => {
return (
!!username && !!this.props.owners && this.props.owners.includes(username)
);
};
} }

View file

@ -5,5 +5,6 @@ export interface WebhookConfig {
export interface TelegramConfig { export interface TelegramConfig {
key: string; key: string;
owners?: string[];
webhook: WebhookConfig; webhook: WebhookConfig;
} }

View file

@ -6,7 +6,11 @@ const webhookValidationSchema = object().optional().shape({
enabled: boolean(), enabled: boolean(),
}); });
export const telegramConfigSchema = yup.object().required().shape({ export const telegramConfigSchema = yup
.object()
.required()
.shape({
key: yup.string().required(), key: yup.string().required(),
owners: yup.array().of(yup.string().required()),
webhook: webhookValidationSchema, webhook: webhookValidationSchema,
}); });

View file

@ -9,7 +9,7 @@ import { vkEventToHandler } from "./handlers";
import { TelegramService } from "../telegram"; import { TelegramService } from "../telegram";
import { Template } from "../template"; import { Template } from "../template";
import { TemplateConfig } from "../../config/types"; import { TemplateConfig } from "../../config/types";
import { Storage } from "../db"; import { PostgresDB } from "../db/postgres";
/** /**
* Service to handle VK to Telegram interactions * Service to handle VK to Telegram interactions
@ -26,7 +26,7 @@ export class VkService {
private config: VkConfig, private config: VkConfig,
private telegram: TelegramService, private telegram: TelegramService,
private templates: TemplateConfig, private templates: TemplateConfig,
private db: Storage private db: PostgresDB
) { ) {
if (!config.groups.length) { if (!config.groups.length) {
throw new Error("No vk groups to handle. Specify them in config"); throw new Error("No vk groups to handle. Specify them in config");
@ -63,6 +63,8 @@ export class VkService {
const eventId = body?.event_id; const eventId = body?.event_id;
const type = body?.type; const type = body?.type;
await this.db.insertRequest(body);
if (!groupId || !has(groupId, groups) || !has(groupId, this.instances)) { if (!groupId || !has(groupId, groups) || !has(groupId, this.instances)) {
logger.warn(`vk received unknown call`, { body }); logger.warn(`vk received unknown call`, { body });
res.sendStatus(200); res.sendStatus(200);