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

added working vk event handlers

This commit is contained in:
Fedor Katurov 2021-04-28 12:17:47 +07:00
parent 3f908da91e
commit 12c8e30a1e
8 changed files with 184 additions and 15 deletions

View file

@ -21,6 +21,7 @@
"telegraf": "^4.3.0", "telegraf": "^4.3.0",
"typescript": "^4.2.3", "typescript": "^4.2.3",
"url": "^0.11.0", "url": "^0.11.0",
"vk-io": "^4.2.0",
"winston": "^3.3.3", "winston": "^3.3.3",
"yargs": "^17.0.0-candidate.10", "yargs": "^17.0.0-candidate.10",
"yup": "^0.32.9" "yup": "^0.32.9"

View file

@ -56,7 +56,8 @@ export class HttpApi {
this.app.get(url.pathname, this.testWebhook); this.app.get(url.pathname, this.testWebhook);
} }
this.app.post(this.vk.endpoint, this.handleVkEvent); // VK event handler
this.app.post(this.vk.endpoint, this.vk.handle);
} }
/** /**
@ -73,12 +74,4 @@ export class HttpApi {
private testWebhook = async (req: Request, res: Response) => { private testWebhook = async (req: Request, res: Response) => {
res.sendStatus(200); res.sendStatus(200);
}; };
/**
* Handles VK events
*/
private handleVkEvent = async (req: Request, res: Response) => {
await this.vk.handle(req.body);
res.sendStatus(200);
};
} }

View file

@ -0,0 +1,12 @@
import { VkEventHandler } from "./types";
import { ContextDefaultState, MessageContext } from "vk-io";
import { NextMiddleware } from "middleware-io";
export class MessageNewHandler extends VkEventHandler<
MessageContext<ContextDefaultState>
> {
public execute = async (context, next: NextMiddleware) => {
console.log("received message!");
await next();
};
}

View file

@ -0,0 +1,11 @@
import { VkEvent } from "../types";
import { VkEventHandler } from "./types";
import { MessageNewHandler } from "./MessageNewHandler";
export const vkEventToHandler: Record<VkEvent, typeof VkEventHandler> = {
[VkEvent.GroupJoin]: VkEventHandler,
[VkEvent.GroupLeave]: VkEventHandler,
[VkEvent.MessageNew]: MessageNewHandler,
[VkEvent.PostSuggestion]: VkEventHandler,
[VkEvent.WallPostNew]: VkEventHandler,
};

View file

@ -0,0 +1,13 @@
import { NextMiddleware } from "middleware-io";
import { ConfigGroup } from "../types";
export class VkEventHandler<T = any> {
public constructor(protected config: ConfigGroup) {}
public execute: (context: T, next: NextMiddleware) => Promise<void> = async (
ctx,
next
) => {
console.log(`vk received unknown event`, ctx);
await next();
};
}

View file

@ -1,7 +1,16 @@
import { VkConfig } from "./types"; import { ConfigGroup, GroupInstance, VkConfig, VkEvent } from "./types";
import { API, Upload, Updates } from "vk-io";
import logger from "../logger";
import { Request, Response } from "express";
import { flatten, has, keys } from "ramda";
import { NextFunction } from "connect";
import { VkEventHandler } from "./handlers/types";
import { vkEventToHandler } from "./handlers";
export class VkService { export class VkService {
public endpoint: string = "/"; public endpoint: string = "/";
private readonly instances: Record<string, GroupInstance>;
private readonly groups: Record<number, ConfigGroup>;
constructor(private config: VkConfig) { constructor(private config: VkConfig) {
if (!config.groups.length) { if (!config.groups.length) {
@ -9,12 +18,87 @@ export class VkService {
} }
this.endpoint = config.endpoint; this.endpoint = config.endpoint;
this.groups = config.groups.reduce(
(acc, group) => ({
...acc,
[group.id]: group,
}),
{}
);
this.instances = config.groups.reduce(
(acc, group) => ({
...acc,
[group.id]: this.createGroupInstance(group),
}),
{}
);
} }
/** /**
* Handles incoming VK events * Handles incoming VK events
*/ */
public handle = async (event: any) => { public handle = async (req: Request, res: Response, next: NextFunction) => {
// TODO: handle events try {
const { body } = req;
const { groups } = this;
const groupId = body?.group_id;
if (!groupId || !has(groupId, groups) || !has(groupId, this.instances)) {
logger.warn(`vk received unknown call`, { body });
res.sendStatus(200);
return;
}
logger.debug(`received vk event`, { body });
const inst = this.instances[groupId] as GroupInstance;
inst.updates.getWebhookCallback(this.config.endpoint)(req, res, next);
} catch (e) {
next(e);
}
}; };
private createGroupInstance = (group: ConfigGroup): GroupInstance => {
const api = new API({
token: group.apiKey,
apiBaseUrl: this.config.endpoint,
});
const upload = new Upload({ api });
const updates = new Updates({
api,
upload,
webhookConfirmation: group.testResponse,
webhookSecret: group.secretKey,
});
const handlers = this.setupHandlers(group);
handlers.forEach((channel) => {
keys(channel).forEach((event) => {
console.log(`updates in ${String(event)}`);
updates.on(event as any, channel[event].execute);
});
});
return {
api,
upload,
updates,
};
};
/**
* Setups handlers
*/
private setupHandlers(group: ConfigGroup): Record<VkEvent, VkEventHandler>[] {
return flatten(
group.channels.map((chan) =>
chan.events.reduce((acc, event) => {
const handler = vkEventToHandler[event];
return { ...acc, [event]: new handler(group) };
}, {} as Record<VkEvent, VkEventHandler>[])
)
);
}
} }

View file

@ -1,9 +1,11 @@
import { API, Upload, Updates } from "vk-io";
export interface VkConfig extends Record<string, any> { export interface VkConfig extends Record<string, any> {
groups: ConfigGroup[]; groups: ConfigGroup[];
endpoint?: string; endpoint?: string;
} }
interface ConfigGroup { export interface ConfigGroup {
id: number; id: number;
name: string; name: string;
testResponse: string; testResponse: string;
@ -18,10 +20,15 @@ interface GroupChannel {
} }
export enum VkEvent { export enum VkEvent {
Confirmation = "confirmation",
WallPostNew = "wall_post_new", WallPostNew = "wall_post_new",
PostSuggestion = "post_suggestion", PostSuggestion = "post_suggestion",
GroupJoin = "group_join", GroupJoin = "group_join",
GroupLeave = "group_leave", GroupLeave = "group_leave",
MessageNew = "message_new", MessageNew = "message_new",
} }
export interface GroupInstance {
api: API;
upload: Upload;
updates: Updates;
}

View file

@ -177,6 +177,11 @@ async@^3.1.0:
resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720" resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720"
integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw== integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
balanced-match@^1.0.0: balanced-match@^1.0.0:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
@ -298,6 +303,13 @@ colorspace@1.1.x:
color "3.0.x" color "3.0.x"
text-hex "1.0.x" text-hex "1.0.x"
combined-stream@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
dependencies:
delayed-stream "~1.0.0"
concat-map@0.0.1: concat-map@0.0.1:
version "0.0.1" version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@ -357,6 +369,11 @@ debug@4, debug@^4.3.1:
dependencies: dependencies:
ms "2.1.2" ms "2.1.2"
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
depd@~1.1.2: depd@~1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
@ -481,6 +498,15 @@ fn.name@1.x.x:
resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc"
integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==
form-data@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"
forwarded@~0.1.2: forwarded@~0.1.2:
version "0.1.2" version "0.1.2"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
@ -577,6 +603,11 @@ inherits@2.0.3:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
inspectable@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/inspectable/-/inspectable-1.1.1.tgz#7a9ecc277e483b00ca9a4eadd08bf22659b23585"
integrity sha512-dMT0Qj7iXzWt4pjAVRkWBdq8u1Yro5BEHDwv5EdNrIcbDp1wfhrYrWu4P48eAK5VA5MmVWPtKUB/xvBQA92rXw==
ip@^1.1.5: ip@^1.1.5:
version "1.1.5" version "1.1.5"
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
@ -673,12 +704,17 @@ methods@~1.1.2:
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
middleware-io@^2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/middleware-io/-/middleware-io-2.6.0.tgz#bce019eabf14ad0adb8c7ec328cb57ec37b8eb84"
integrity sha512-o/Aa6ZtufvXGFCKurGSu7QBCud4b2OAzj7LMR6eKMFX9IuC7UqDMDszKjo1pNIelhDX4TbAQVFobRRzLD1IgDQ==
mime-db@1.47.0: mime-db@1.47.0:
version "1.47.0" version "1.47.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.47.0.tgz#8cb313e59965d3c05cfbf898915a267af46a335c" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.47.0.tgz#8cb313e59965d3c05cfbf898915a267af46a335c"
integrity sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw== integrity sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==
mime-types@~2.1.24: mime-types@^2.1.12, mime-types@~2.1.24:
version "2.1.30" version "2.1.30"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.30.tgz#6e7be8b4c479825f85ed6326695db73f9305d62d" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.30.tgz#6e7be8b4c479825f85ed6326695db73f9305d62d"
integrity sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg== integrity sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==
@ -1187,6 +1223,18 @@ vary@~1.1.2:
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
vk-io@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/vk-io/-/vk-io-4.2.0.tgz#ff16cd94ef8f96eacf3deac95eb448137bd8bbea"
integrity sha512-jBoS3NhJU5qHULcd2uYKvS3sT6aYxj66F0CD7ryeHci4jMpHVzmuT8NCueJrygoJDccm3pX+DzbGY6JeVaB8FQ==
dependencies:
abort-controller "^3.0.0"
debug "^4.3.1"
form-data "^4.0.0"
inspectable "^1.1.1"
middleware-io "^2.6.0"
node-fetch "^2.6.1"
winston-transport@^4.4.0: winston-transport@^4.4.0:
version "4.4.0" version "4.4.0"
resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.4.0.tgz#17af518daa690d5b2ecccaa7acf7b20ca7925e59" resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.4.0.tgz#17af518daa690d5b2ecccaa7acf7b20ca7925e59"