From 1754092f7ce94aa16a83da8f0b0dbb87c6e3e23e Mon Sep 17 00:00:00 2001
From: Fedor Katurov <gotham48@gmail.com>
Date: Wed, 28 Apr 2021 13:03:10 +0700
Subject: [PATCH] added working message handler

---
 src/index.ts                                 |  2 +-
 src/service/vk/handlers/MessageNewHandler.ts | 30 +++++++++++++----
 src/service/vk/handlers/VkEventHandler.ts    | 21 ++++++++++++
 src/service/vk/handlers/index.ts             | 15 +++++----
 src/service/vk/handlers/types.ts             | 13 --------
 src/service/vk/index.ts                      | 35 +++++++++++++-------
 6 files changed, 77 insertions(+), 39 deletions(-)
 create mode 100644 src/service/vk/handlers/VkEventHandler.ts
 delete mode 100644 src/service/vk/handlers/types.ts

diff --git a/src/index.ts b/src/index.ts
index 4baefb8..db54ff5 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -9,7 +9,7 @@ async function main() {
   try {
     const config = prepareConfig();
     const telegram = new TelegramService(config.telegram);
-    const vkService = new VkService(config.vk);
+    const vkService = new VkService(config.vk, telegram);
 
     const telegramApi = new TelegramApi(telegram).listen();
     await telegram.start();
diff --git a/src/service/vk/handlers/MessageNewHandler.ts b/src/service/vk/handlers/MessageNewHandler.ts
index c8a1f55..8a1b8fc 100644
--- a/src/service/vk/handlers/MessageNewHandler.ts
+++ b/src/service/vk/handlers/MessageNewHandler.ts
@@ -1,12 +1,28 @@
-import { VkEventHandler } from "./types";
-import { ContextDefaultState, MessageContext } from "vk-io";
+import { VkEventHandler } from "./VkEventHandler";
+import { MessageContext } from "vk-io";
 import { NextMiddleware } from "middleware-io";
+import logger from "../../logger";
+import { ContextDefaultState } from "vk-io/lib/structures/contexts/context";
+
+export class MessageNewHandler extends VkEventHandler {
+  public execute = async (
+    context: MessageContext<ContextDefaultState>,
+    next: NextMiddleware
+  ) => {
+    if (context.isOutbox) {
+      await next();
+      return;
+    }
+
+    const users = await this.instance.api.users.get({
+      user_ids: [String(context.senderId)],
+    });
+    const from = users[0];
+
+    logger.debug(
+      `received message from ${from.first_name} ${from.last_name}: ${context.text}`
+    );
 
-export class MessageNewHandler extends VkEventHandler<
-  MessageContext<ContextDefaultState>
-> {
-  public execute = async (context, next: NextMiddleware) => {
-    console.log("received message!");
     await next();
   };
 }
diff --git a/src/service/vk/handlers/VkEventHandler.ts b/src/service/vk/handlers/VkEventHandler.ts
new file mode 100644
index 0000000..a767757
--- /dev/null
+++ b/src/service/vk/handlers/VkEventHandler.ts
@@ -0,0 +1,21 @@
+import { NextMiddleware } from "middleware-io";
+import { ConfigGroup, GroupInstance } from "../types";
+import { VkService } from "../index";
+import { TelegramService } from "../../telegram";
+
+export abstract class VkEventHandler {
+  public constructor(
+    protected group: ConfigGroup,
+    protected instance: GroupInstance,
+    protected vk: VkService,
+    protected telegram: TelegramService
+  ) {}
+
+  public execute: (
+    context: any,
+    next: NextMiddleware
+  ) => Promise<void> = async (ctx, next) => {
+    console.log(`vk received unknown event`, ctx);
+    await next();
+  };
+}
diff --git a/src/service/vk/handlers/index.ts b/src/service/vk/handlers/index.ts
index ac7b8af..ac03f9a 100644
--- a/src/service/vk/handlers/index.ts
+++ b/src/service/vk/handlers/index.ts
@@ -1,11 +1,14 @@
 import { VkEvent } from "../types";
-import { VkEventHandler } from "./types";
+import { VkEventHandler } from "./VkEventHandler";
 import { MessageNewHandler } from "./MessageNewHandler";
 
-export const vkEventToHandler: Record<VkEvent, typeof VkEventHandler> = {
-  [VkEvent.GroupJoin]: VkEventHandler,
-  [VkEvent.GroupLeave]: VkEventHandler,
+type DerivedHandler = typeof VkEventHandler;
+interface Handler extends DerivedHandler {}
+
+export const vkEventToHandler: Record<VkEvent, Handler> = {
+  [VkEvent.GroupJoin]: MessageNewHandler,
+  [VkEvent.GroupLeave]: MessageNewHandler,
   [VkEvent.MessageNew]: MessageNewHandler,
-  [VkEvent.PostSuggestion]: VkEventHandler,
-  [VkEvent.WallPostNew]: VkEventHandler,
+  [VkEvent.PostSuggestion]: MessageNewHandler,
+  [VkEvent.WallPostNew]: MessageNewHandler,
 };
diff --git a/src/service/vk/handlers/types.ts b/src/service/vk/handlers/types.ts
deleted file mode 100644
index 96ce7e1..0000000
--- a/src/service/vk/handlers/types.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-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();
-  };
-}
diff --git a/src/service/vk/index.ts b/src/service/vk/index.ts
index 60f8283..ac62d14 100644
--- a/src/service/vk/index.ts
+++ b/src/service/vk/index.ts
@@ -4,15 +4,16 @@ 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 { VkEventHandler } from "./handlers/VkEventHandler";
 import { vkEventToHandler } from "./handlers";
+import { TelegramService } from "../telegram";
 
 export class VkService {
   public endpoint: string = "/";
   private readonly instances: Record<string, GroupInstance>;
   private readonly groups: Record<number, ConfigGroup>;
 
-  constructor(private config: VkConfig) {
+  constructor(private config: VkConfig, private telegram: TelegramService) {
     if (!config.groups.length) {
       throw new Error("No vk groups to handle. Specify them in config");
     }
@@ -63,7 +64,6 @@ export class VkService {
   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({
@@ -73,7 +73,14 @@ export class VkService {
       webhookSecret: group.secretKey,
     });
 
-    const handlers = this.setupHandlers(group);
+    const instance = {
+      api,
+      upload,
+      updates,
+    };
+
+    const handlers = this.setupHandlers(group, instance);
+
     handlers.forEach((channel) => {
       keys(channel).forEach((event) => {
         console.log(`updates in ${String(event)}`);
@@ -81,22 +88,26 @@ export class VkService {
       });
     });
 
-    return {
-      api,
-      upload,
-      updates,
-    };
+    return instance;
   };
 
   /**
    * Setups handlers
    */
-  private setupHandlers(group: ConfigGroup): Record<VkEvent, VkEventHandler>[] {
+  private setupHandlers(
+    group: ConfigGroup,
+    instance: GroupInstance
+  ): Record<VkEvent, VkEventHandler>[] {
     return flatten(
       group.channels.map((chan) =>
         chan.events.reduce((acc, event) => {
-          const handler = vkEventToHandler[event];
-          return { ...acc, [event]: new handler(group) };
+          const handler = new (vkEventToHandler as any)[event](
+            group,
+            instance,
+            this,
+            this.telegram
+          );
+          return { ...acc, [event]: handler };
         }, {} as Record<VkEvent, VkEventHandler>[])
       )
     );