mirror of
https://github.com/muerwre/vk-tg-bot.git
synced 2025-04-25 06:56:40 +07:00
added vk events handler stub
This commit is contained in:
parent
dfae42c197
commit
3f908da91e
11 changed files with 125 additions and 67 deletions
|
@ -1,13 +1,17 @@
|
|||
http:
|
||||
port: 3002
|
||||
telegram:
|
||||
# Get it from bot father
|
||||
key: ''
|
||||
webhook:
|
||||
url: https://something.org:65534/webhook
|
||||
enabled: false
|
||||
webhook:
|
||||
url: https://something.org:3002/webhook
|
||||
enabled: false
|
||||
logger:
|
||||
level: info
|
||||
#vk:
|
||||
vk:
|
||||
# Default path for POST requests from VK api
|
||||
endpoint: /
|
||||
groups: []
|
||||
# groups:
|
||||
# - id: 0
|
||||
# name: 'Group name'
|
||||
|
|
|
@ -6,19 +6,21 @@ import loggerHttpMiddleware from "../../service/logger/http";
|
|||
import logger from "../../service/logger";
|
||||
import { TelegramService } from "../../service/telegram";
|
||||
import http from "http";
|
||||
import { WebhookConfig } from "../../config/types";
|
||||
import { URL } from "url";
|
||||
import { corsMiddleware, errorMiddleware } from "./middleware";
|
||||
import { WebhookConfig } from "../../service/telegram/types";
|
||||
|
||||
export class HttpApi {
|
||||
app: Express;
|
||||
webhook: WebhookConfig;
|
||||
|
||||
constructor(
|
||||
private props: HttpConfig,
|
||||
private telegram: TelegramService,
|
||||
private vk: VkService,
|
||||
private webhook?: WebhookConfig
|
||||
private vk: VkService
|
||||
) {
|
||||
this.webhook = this.telegram.webhook;
|
||||
|
||||
this.app = express();
|
||||
this.app.use(corsMiddleware);
|
||||
this.app.use(express.json());
|
||||
|
@ -28,11 +30,7 @@ export class HttpApi {
|
|||
this.app.use(bodyParser.json());
|
||||
this.app.use(express.json());
|
||||
|
||||
if (this?.webhook?.enabled && this?.webhook?.url) {
|
||||
const url = new URL(this.webhook.url);
|
||||
logger.info(`using webhook at ${url.pathname}`);
|
||||
this.app.post(url.pathname, this.handleWebhook);
|
||||
}
|
||||
this.setupHandlers();
|
||||
|
||||
this.app.use(errorMiddleware);
|
||||
}
|
||||
|
@ -46,6 +44,21 @@ export class HttpApi {
|
|||
logger.info(`http api listening at ${this.props.port}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds webhandlers
|
||||
*/
|
||||
private setupHandlers() {
|
||||
// Webhooks (if available)
|
||||
if (this?.webhook?.enabled && this?.webhook?.url) {
|
||||
const url = new URL(this.webhook.url);
|
||||
logger.info(`using webhook at ${url.pathname}`);
|
||||
this.app.post(url.pathname, this.handleWebhook);
|
||||
this.app.get(url.pathname, this.testWebhook);
|
||||
}
|
||||
|
||||
this.app.post(this.vk.endpoint, this.handleVkEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles telegram webhooks
|
||||
*/
|
||||
|
@ -53,4 +66,19 @@ export class HttpApi {
|
|||
logger.debug("got message via webhook", req.body);
|
||||
await this.telegram.handleUpdate(req.body, res);
|
||||
};
|
||||
|
||||
/**
|
||||
* Just returns 200
|
||||
*/
|
||||
private testWebhook = async (req: Request, res: Response) => {
|
||||
res.sendStatus(200);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles VK events
|
||||
*/
|
||||
private handleVkEvent = async (req: Request, res: Response) => {
|
||||
await this.vk.handle(req.body);
|
||||
res.sendStatus(200);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -3,14 +3,9 @@ import { VkConfig } from "../service/vk/types";
|
|||
import { HttpConfig } from "../api/http/types";
|
||||
import { LoggerConfig } from "../service/logger/types";
|
||||
|
||||
export interface WebhookConfig {
|
||||
url?: string;
|
||||
enabled?: boolean;
|
||||
}
|
||||
export interface Config extends Record<string, any> {
|
||||
http: HttpConfig;
|
||||
telegram: TelegramConfig;
|
||||
vk: VkConfig;
|
||||
logger?: LoggerConfig;
|
||||
webhook?: WebhookConfig;
|
||||
}
|
||||
|
|
|
@ -5,17 +5,11 @@ import { vkConfigSchema } from "../service/vk/validation";
|
|||
import { telegramConfigSchema } from "../service/telegram/validation";
|
||||
import { loggerConfigSchema } from "../service/logger/config";
|
||||
|
||||
const webhookValidationSchema = object().optional().shape({
|
||||
url: string(),
|
||||
enabled: boolean(),
|
||||
});
|
||||
|
||||
const configSchema = object<Config>().required().shape({
|
||||
http: httpConfigSchema,
|
||||
vk: vkConfigSchema,
|
||||
telegram: telegramConfigSchema,
|
||||
logger: loggerConfigSchema,
|
||||
webhook: webhookValidationSchema,
|
||||
});
|
||||
|
||||
export const validateConfig = (config: Config) =>
|
||||
|
|
|
@ -8,18 +8,13 @@ import { HttpApi } from "./api/http";
|
|||
async function main() {
|
||||
try {
|
||||
const config = prepareConfig();
|
||||
const telegram = new TelegramService(config.telegram, config.webhook);
|
||||
const telegram = new TelegramService(config.telegram);
|
||||
const vkService = new VkService(config.vk);
|
||||
|
||||
const telegramApi = new TelegramApi(telegram).listen();
|
||||
await telegram.start();
|
||||
|
||||
const httpApi = new HttpApi(
|
||||
config.http,
|
||||
telegram,
|
||||
vkService,
|
||||
config.webhook
|
||||
).listen();
|
||||
const httpApi = new HttpApi(config.http, telegram, vkService).listen();
|
||||
} catch (e) {
|
||||
logger.error(e.message);
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import { TelegramConfig } from "./types";
|
||||
import { TelegramConfig, WebhookConfig } from "./types";
|
||||
import { Telegraf } from "telegraf";
|
||||
import logger from "../logger";
|
||||
import { Response } from "express";
|
||||
import { Update } from "typegram";
|
||||
import loggerTgMiddleware from "../logger/tg";
|
||||
import { WebhookConfig } from "../../config/types";
|
||||
|
||||
// import SocksProxyAgent from 'socks-proxy-agent';
|
||||
|
||||
export class TelegramService {
|
||||
public readonly bot: Telegraf;
|
||||
public readonly webhook: WebhookConfig = {};
|
||||
|
||||
constructor(private props: TelegramConfig, private webhook: WebhookConfig) {
|
||||
constructor(private props: TelegramConfig) {
|
||||
// const agent = (CONFIG.PROXY && new SocksProxyAgent(CONFIG.PROXY)) || null;
|
||||
const options: Partial<Telegraf.Options<any>> = {
|
||||
telegram: {
|
||||
|
@ -21,6 +21,8 @@ export class TelegramService {
|
|||
},
|
||||
};
|
||||
|
||||
this.webhook = props.webhook;
|
||||
|
||||
this.bot = new Telegraf(props.key, options);
|
||||
this.bot.use(loggerTgMiddleware);
|
||||
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
export interface WebhookConfig {
|
||||
url?: string;
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
export interface TelegramConfig {
|
||||
key: string;
|
||||
webhook: WebhookConfig;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
import * as yup from "yup";
|
||||
import { boolean, object, string } from "yup";
|
||||
|
||||
const webhookValidationSchema = object().optional().shape({
|
||||
url: string(),
|
||||
enabled: boolean(),
|
||||
});
|
||||
|
||||
export const telegramConfigSchema = yup.object().required().shape({
|
||||
key: yup.string().required(),
|
||||
webhook: webhookValidationSchema,
|
||||
});
|
||||
|
|
|
@ -1,9 +1,20 @@
|
|||
import { VkConfig } from './types';
|
||||
import { VkConfig } from "./types";
|
||||
|
||||
export class VkService {
|
||||
public endpoint: string = "/";
|
||||
|
||||
constructor(private config: VkConfig) {
|
||||
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");
|
||||
}
|
||||
|
||||
this.endpoint = config.endpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles incoming VK events
|
||||
*/
|
||||
public handle = async (event: any) => {
|
||||
// TODO: handle events
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,26 +1,27 @@
|
|||
export interface VkConfig extends Record<string, any> {
|
||||
groups: ConfigGroup[]
|
||||
groups: ConfigGroup[];
|
||||
endpoint?: string;
|
||||
}
|
||||
|
||||
interface ConfigGroup {
|
||||
id: number
|
||||
name: string
|
||||
testResponse: string
|
||||
secretKey: string
|
||||
apiKey: string
|
||||
channels: GroupChannel[]
|
||||
id: number;
|
||||
name: string;
|
||||
testResponse: string;
|
||||
secretKey: string;
|
||||
apiKey: string;
|
||||
channels: GroupChannel[];
|
||||
}
|
||||
|
||||
interface GroupChannel {
|
||||
id: string,
|
||||
events: VkEvent[]
|
||||
id: string;
|
||||
events: VkEvent[];
|
||||
}
|
||||
|
||||
export enum VkEvent {
|
||||
Confirmation = 'confirmation',
|
||||
WallPostNew = 'wall_post_new',
|
||||
PostSuggestion = 'post_suggestion',
|
||||
GroupJoin = 'group_join',
|
||||
GroupLeave = 'group_leave',
|
||||
MessageNew = 'message_new',
|
||||
Confirmation = "confirmation",
|
||||
WallPostNew = "wall_post_new",
|
||||
PostSuggestion = "post_suggestion",
|
||||
GroupJoin = "group_join",
|
||||
GroupLeave = "group_leave",
|
||||
MessageNew = "message_new",
|
||||
}
|
||||
|
|
|
@ -1,20 +1,35 @@
|
|||
import * as yup from 'yup'
|
||||
import { VkConfig, VkEvent } from './types';
|
||||
import * as yup from "yup";
|
||||
import { VkConfig, VkEvent } from "./types";
|
||||
|
||||
const vkChannelEventSchema = yup.string().oneOf(Object.values(VkEvent))
|
||||
const vkChannelEventSchema = yup.string().oneOf(Object.values(VkEvent));
|
||||
|
||||
const vkChannelSchema = yup.object().required().shape({
|
||||
id: yup.string().required().matches(/^@/, ({ path }) => `${path} should start with "@"`),
|
||||
events: yup.array().of(vkChannelEventSchema)
|
||||
})
|
||||
const vkChannelSchema = yup
|
||||
.object()
|
||||
.required()
|
||||
.shape({
|
||||
id: yup
|
||||
.string()
|
||||
.required()
|
||||
.matches(/^@/, ({ path }) => `${path} should start with "@"`),
|
||||
events: yup.array().of(vkChannelEventSchema),
|
||||
});
|
||||
|
||||
export const vkConfigSchema = yup.object<VkConfig>().required().shape({
|
||||
groups: yup.array().required().of(yup.object().shape({
|
||||
id: yup.number().positive(),
|
||||
name: yup.string().required(),
|
||||
testResponse: yup.string().required(),
|
||||
secretKey: yup.string().required(),
|
||||
apiKey: yup.string().required(),
|
||||
channels: yup.array().of(vkChannelSchema),
|
||||
}))
|
||||
})
|
||||
export const vkConfigSchema = yup
|
||||
.object<VkConfig>()
|
||||
.required()
|
||||
.shape({
|
||||
endpoint: yup.string().optional(),
|
||||
groups: yup
|
||||
.array()
|
||||
.required()
|
||||
.of(
|
||||
yup.object().shape({
|
||||
id: yup.number().positive(),
|
||||
name: yup.string().required(),
|
||||
testResponse: yup.string().required(),
|
||||
secretKey: yup.string().required(),
|
||||
apiKey: yup.string().required(),
|
||||
channels: yup.array().of(vkChannelSchema),
|
||||
})
|
||||
),
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue