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:
parent
c1fb45742e
commit
c709bbf94c
9 changed files with 90 additions and 8 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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();
|
||||||
|
|
19
src/service/db/postgres/entities/Request.ts
Normal file
19
src/service/db/postgres/entities/Request.ts
Normal 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;
|
||||||
|
}
|
|
@ -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");
|
||||||
|
|
|
@ -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)
|
||||||
|
);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,5 +5,6 @@ export interface WebhookConfig {
|
||||||
|
|
||||||
export interface TelegramConfig {
|
export interface TelegramConfig {
|
||||||
key: string;
|
key: string;
|
||||||
|
owners?: string[];
|
||||||
webhook: WebhookConfig;
|
webhook: WebhookConfig;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
});
|
});
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue