mirror of
https://github.com/muerwre/vk-tg-bot.git
synced 2025-04-24 22:46:41 +07:00
#4 made strict type checking
This commit is contained in:
parent
01211eae0f
commit
43aa09a88b
18 changed files with 138 additions and 82 deletions
|
@ -23,6 +23,7 @@ templates:
|
||||||
# testResponse: 'testResponseCode'
|
# testResponse: 'testResponseCode'
|
||||||
# secretKey: 'groupSecretKey'
|
# secretKey: 'groupSecretKey'
|
||||||
# apiKey: 'callbackApiKey'
|
# apiKey: 'callbackApiKey'
|
||||||
|
# post_types: ['post','copy','reply','postpone','suggest']
|
||||||
# channels:
|
# channels:
|
||||||
# - id: '@pogonia_test_chan'
|
# - id: '@pogonia_test_chan'
|
||||||
# events:
|
# events:
|
||||||
|
|
|
@ -10,7 +10,7 @@ export interface Config extends Record<string, any> {
|
||||||
http: HttpConfig;
|
http: HttpConfig;
|
||||||
telegram: TelegramConfig;
|
telegram: TelegramConfig;
|
||||||
vk: VkConfig;
|
vk: VkConfig;
|
||||||
logger?: LoggerConfig;
|
logger: LoggerConfig;
|
||||||
templates?: TemplateConfig;
|
templates: TemplateConfig;
|
||||||
postgres?: PostgresConfig;
|
postgres: PostgresConfig;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,13 +9,13 @@ export interface Storage {
|
||||||
tgMessageId: number,
|
tgMessageId: number,
|
||||||
groupId: number,
|
groupId: number,
|
||||||
channel: string
|
channel: string
|
||||||
): Promise<Event>;
|
): Promise<Event | undefined>;
|
||||||
getEventById(
|
getEventById(
|
||||||
type: VkEvent,
|
type: VkEvent,
|
||||||
eventId: number,
|
eventId: number,
|
||||||
groupId: number,
|
groupId: number,
|
||||||
channel: string
|
channel: string
|
||||||
): Promise<Event>;
|
): Promise<Event | undefined>;
|
||||||
createEvent(
|
createEvent(
|
||||||
type: VkEvent,
|
type: VkEvent,
|
||||||
eventId: number,
|
eventId: number,
|
||||||
|
@ -23,7 +23,7 @@ export interface Storage {
|
||||||
channel: string,
|
channel: string,
|
||||||
tgMessageId: number,
|
tgMessageId: number,
|
||||||
text: Record<any, any>
|
text: Record<any, any>
|
||||||
): Promise<Event>;
|
): Promise<Event | undefined>;
|
||||||
createOrUpdateLike(
|
createOrUpdateLike(
|
||||||
messageId: number,
|
messageId: number,
|
||||||
channel: string,
|
channel: string,
|
||||||
|
@ -31,7 +31,11 @@ export interface Storage {
|
||||||
text: string
|
text: string
|
||||||
): Promise<Like>;
|
): Promise<Like>;
|
||||||
getLikesFor(channel: string, messageId: number): Promise<Like[]>;
|
getLikesFor(channel: string, messageId: number): Promise<Like[]>;
|
||||||
getLikeBy(channel: string, messageId: number, author: number): Promise<Like>;
|
getLikeBy(
|
||||||
createPost(eventId: number, text: string): Promise<Post>;
|
channel: string,
|
||||||
findPostByEvent(eventId: number): Promise<Post>;
|
messageId: number,
|
||||||
|
author: number
|
||||||
|
): Promise<Like | undefined>;
|
||||||
|
createPost(eventId: number, text: string): Promise<Post | undefined>;
|
||||||
|
findPostByEvent(eventId: number): Promise<Post | undefined>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,21 +10,21 @@ import { VkEvent } from "../../../vk/types";
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Event {
|
export class Event {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn()
|
||||||
id: number;
|
id!: number;
|
||||||
@Column()
|
@Column()
|
||||||
type: VkEvent;
|
type!: VkEvent;
|
||||||
@Column()
|
@Column()
|
||||||
vkEventId: number;
|
vkEventId!: number;
|
||||||
@Column()
|
@Column()
|
||||||
vkGroupId: number;
|
vkGroupId!: number;
|
||||||
@Column()
|
@Column()
|
||||||
channel: string;
|
channel!: string;
|
||||||
@Column()
|
@Column()
|
||||||
tgMessageId: number;
|
tgMessageId!: number;
|
||||||
@CreateDateColumn()
|
@CreateDateColumn()
|
||||||
createdAt: Date;
|
createdAt!: Date;
|
||||||
@UpdateDateColumn()
|
@UpdateDateColumn()
|
||||||
updatedAt: Date;
|
updatedAt!: Date;
|
||||||
@Column("simple-json", { default: {}, nullable: false })
|
@Column("simple-json", { default: {}, nullable: false })
|
||||||
text: Record<any, any>;
|
text!: Record<any, any>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,17 +9,17 @@ import {
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Like {
|
export class Like {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn()
|
||||||
id: number;
|
id!: number;
|
||||||
@Column()
|
@Column()
|
||||||
messageId: number;
|
messageId!: number;
|
||||||
@Column()
|
@Column()
|
||||||
channel: string;
|
channel!: string;
|
||||||
@Column({ type: "text" })
|
@Column({ type: "text" })
|
||||||
text: string;
|
text!: string;
|
||||||
@Column()
|
@Column()
|
||||||
author: number;
|
author!: number;
|
||||||
@CreateDateColumn()
|
@CreateDateColumn()
|
||||||
createdAt: Date;
|
createdAt!: Date;
|
||||||
@UpdateDateColumn()
|
@UpdateDateColumn()
|
||||||
updatedAt: Date;
|
updatedAt!: Date;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,13 +9,13 @@ import {
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Post {
|
export class Post {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn()
|
||||||
id: number;
|
id!: number;
|
||||||
@Column()
|
@Column()
|
||||||
eventId: number;
|
eventId!: number;
|
||||||
@Column({ type: "text" })
|
@Column({ type: "text" })
|
||||||
text: string;
|
text!: string;
|
||||||
@CreateDateColumn()
|
@CreateDateColumn()
|
||||||
createdAt: Date;
|
createdAt!: Date;
|
||||||
@UpdateDateColumn()
|
@UpdateDateColumn()
|
||||||
updatedAt: Date;
|
updatedAt!: Date;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,10 +11,10 @@ import { Post } from "./entities/Post";
|
||||||
const entities = [path.join(__dirname, "./entities/*")];
|
const entities = [path.join(__dirname, "./entities/*")];
|
||||||
|
|
||||||
export class PostgresDB implements Storage {
|
export class PostgresDB implements Storage {
|
||||||
private connection: Connection;
|
private connection!: Connection;
|
||||||
private events: Repository<Event>;
|
private events!: Repository<Event>;
|
||||||
private likes: Repository<Like>;
|
private likes!: Repository<Like>;
|
||||||
private posts: Repository<Post>;
|
private posts!: Repository<Post>;
|
||||||
|
|
||||||
constructor(private config: PostgresConfig) {}
|
constructor(private config: PostgresConfig) {}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ const config = prepareConfig();
|
||||||
const logger = createLogger({
|
const logger = createLogger({
|
||||||
transports: new transports.Console({
|
transports: new transports.Console({
|
||||||
format: format.simple(),
|
format: format.simple(),
|
||||||
level: config.logger.level || "info",
|
level: config.logger?.level || "info",
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ export class TelegramService {
|
||||||
if (isWebhookEnabled) {
|
if (isWebhookEnabled) {
|
||||||
await this.bot.telegram
|
await this.bot.telegram
|
||||||
.deleteWebhook()
|
.deleteWebhook()
|
||||||
.then(() => this.bot.telegram.setWebhook(this.webhook.url))
|
.then(() => this.bot.telegram.setWebhook(this.webhook.url!))
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
const info = await this.bot.telegram.getWebhookInfo();
|
const info = await this.bot.telegram.getWebhookInfo();
|
||||||
if (!info.url) {
|
if (!info.url) {
|
||||||
|
@ -71,7 +71,7 @@ export class TelegramService {
|
||||||
* Checks webhook availability
|
* Checks webhook availability
|
||||||
*/
|
*/
|
||||||
private getWebhookAvailable = async (): Promise<boolean> => {
|
private getWebhookAvailable = async (): Promise<boolean> => {
|
||||||
const isWebhookEnabled = this.webhook.enabled && this.webhook.url;
|
const isWebhookEnabled = !!this.webhook.enabled && !!this.webhook.url;
|
||||||
// TODO: test this.webhook.url with axios instead of 'true'
|
// TODO: test this.webhook.url with axios instead of 'true'
|
||||||
return isWebhookEnabled && true;
|
return isWebhookEnabled && true;
|
||||||
};
|
};
|
||||||
|
|
|
@ -54,6 +54,7 @@ export class Template<
|
||||||
*/
|
*/
|
||||||
public static registerHelpers() {
|
public static registerHelpers() {
|
||||||
hb.registerHelper("ifEq", function (arg1, arg2, options) {
|
hb.registerHelper("ifEq", function (arg1, arg2, options) {
|
||||||
|
// @ts-ignore
|
||||||
return arg1 == arg2 ? options.fn(this) : options.inverse(this);
|
return arg1 == arg2 ? options.fn(this) : options.inverse(this);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ export class MessageNewHandler extends VkEventHandler<Fields, Values> {
|
||||||
const parsed = this.template.theme({
|
const parsed = this.template.theme({
|
||||||
user,
|
user,
|
||||||
group: this.group,
|
group: this.group,
|
||||||
text: context.text,
|
text: context?.text || "",
|
||||||
});
|
});
|
||||||
|
|
||||||
const extras: ExtraReplyMessage = {
|
const extras: ExtraReplyMessage = {
|
||||||
|
@ -46,7 +46,7 @@ export class MessageNewHandler extends VkEventHandler<Fields, Values> {
|
||||||
|
|
||||||
this.appendButtons(extras, user.id);
|
this.appendButtons(extras, user.id);
|
||||||
|
|
||||||
await this.telegram.sendMessageToChan(this.channel, parsed, extras);
|
await this.telegram.sendMessageToChan(this.channel.id, parsed, extras);
|
||||||
|
|
||||||
await next();
|
await next();
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,7 +21,7 @@ type UrlPrefix = string;
|
||||||
type ExtraGenerator = (
|
type ExtraGenerator = (
|
||||||
text: string,
|
text: string,
|
||||||
eventId?: number
|
eventId?: number
|
||||||
) => Promise<InlineKeyboardButton[]>;
|
) => Promise<InlineKeyboardButton[] | undefined>;
|
||||||
|
|
||||||
interface Fields {
|
interface Fields {
|
||||||
image?: boolean;
|
image?: boolean;
|
||||||
|
@ -35,6 +35,7 @@ interface Values {
|
||||||
user?: UsersUserFull;
|
user?: UsersUserFull;
|
||||||
group: ConfigGroup;
|
group: ConfigGroup;
|
||||||
text: string;
|
text: string;
|
||||||
|
type?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
type LikeCtx = Composer.Context<CallbackQueryUpdate> & { match: string[] };
|
type LikeCtx = Composer.Context<CallbackQueryUpdate> & { match: string[] };
|
||||||
|
@ -52,12 +53,9 @@ export class PostNewHandler extends VkEventHandler<Fields, Values> {
|
||||||
|
|
||||||
public execute = async (context: WallPostContext, next: NextMiddleware) => {
|
public execute = async (context: WallPostContext, next: NextMiddleware) => {
|
||||||
const id = context?.wall?.id;
|
const id = context?.wall?.id;
|
||||||
|
const postType = context?.wall?.postType;
|
||||||
|
|
||||||
if (
|
if (context.isRepost || !this.isValidPostType(postType) || !id) {
|
||||||
context.isRepost ||
|
|
||||||
!PostNewHandler.isValidPostType(context?.wall?.postType) ||
|
|
||||||
!id
|
|
||||||
) {
|
|
||||||
await next();
|
await next();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -75,9 +73,9 @@ export class PostNewHandler extends VkEventHandler<Fields, Values> {
|
||||||
? await this.getUserByID(String(context.wall.signerId))
|
? await this.getUserByID(String(context.wall.signerId))
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const text = context.wall.text.trim();
|
const text = context.wall?.text?.trim() || "";
|
||||||
|
|
||||||
const parsed = this.themeText(text, user);
|
const parsed = this.themeText(text, postType, user);
|
||||||
|
|
||||||
const extras: ExtraReplyMessage = {
|
const extras: ExtraReplyMessage = {
|
||||||
disable_web_page_preview: true,
|
disable_web_page_preview: true,
|
||||||
|
@ -95,13 +93,17 @@ export class PostNewHandler extends VkEventHandler<Fields, Values> {
|
||||||
if (hasThumb) {
|
if (hasThumb) {
|
||||||
const thumb = await images.find((img) => img.mediumSizeUrl);
|
const thumb = await images.find((img) => img.mediumSizeUrl);
|
||||||
msg = await this.telegram.sendPhotoToChan(
|
msg = await this.telegram.sendPhotoToChan(
|
||||||
this.channel,
|
this.channel.id,
|
||||||
this.trimTextForPhoto(text, user),
|
this.trimTextForPhoto(text, postType, user),
|
||||||
thumb.mediumSizeUrl,
|
thumb?.mediumSizeUrl!,
|
||||||
extras
|
extras
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
msg = await this.telegram.sendMessageToChan(this.channel, parsed, extras);
|
msg = await this.telegram.sendMessageToChan(
|
||||||
|
this.channel.id,
|
||||||
|
parsed,
|
||||||
|
extras
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const event = await this.createEvent(
|
const event = await this.createEvent(
|
||||||
|
@ -109,7 +111,8 @@ export class PostNewHandler extends VkEventHandler<Fields, Values> {
|
||||||
msg.message_id,
|
msg.message_id,
|
||||||
context.wall.toJSON()
|
context.wall.toJSON()
|
||||||
);
|
);
|
||||||
await this.db.createPost(event.id, context.wall.text);
|
|
||||||
|
await this.db.createPost(event!.id, context?.wall?.text || "");
|
||||||
|
|
||||||
await next();
|
await next();
|
||||||
};
|
};
|
||||||
|
@ -117,8 +120,16 @@ export class PostNewHandler extends VkEventHandler<Fields, Values> {
|
||||||
/**
|
/**
|
||||||
* Checks if event of type we can handle
|
* Checks if event of type we can handle
|
||||||
*/
|
*/
|
||||||
public static isValidPostType(type: string): boolean {
|
private isValidPostType(type?: string): boolean {
|
||||||
return type === "post";
|
if (!type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.channel.post_types) {
|
||||||
|
return type === "post";
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.channel.post_types.includes(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -127,7 +138,7 @@ export class PostNewHandler extends VkEventHandler<Fields, Values> {
|
||||||
private createKeyboard = async (
|
private createKeyboard = async (
|
||||||
text: string,
|
text: string,
|
||||||
eventId?: number
|
eventId?: number
|
||||||
): Promise<InlineKeyboardMarkup> => {
|
): Promise<InlineKeyboardMarkup | undefined> => {
|
||||||
const { buttons } = this.template.fields;
|
const { buttons } = this.template.fields;
|
||||||
|
|
||||||
if (!buttons?.length) {
|
if (!buttons?.length) {
|
||||||
|
@ -137,7 +148,10 @@ export class PostNewHandler extends VkEventHandler<Fields, Values> {
|
||||||
const rows = await Promise.all(
|
const rows = await Promise.all(
|
||||||
buttons.map((button) => this.extrasGenerators[button](text, eventId))
|
buttons.map((button) => this.extrasGenerators[button](text, eventId))
|
||||||
);
|
);
|
||||||
const inline_keyboard = rows.filter((el) => el && el.length);
|
|
||||||
|
const inline_keyboard = rows.filter(
|
||||||
|
(el) => el && el.length
|
||||||
|
) as InlineKeyboardButton[][];
|
||||||
|
|
||||||
if (!inline_keyboard.length) {
|
if (!inline_keyboard.length) {
|
||||||
return;
|
return;
|
||||||
|
@ -153,13 +167,13 @@ export class PostNewHandler extends VkEventHandler<Fields, Values> {
|
||||||
const links = this.template.fields.links;
|
const links = this.template.fields.links;
|
||||||
|
|
||||||
if (!links) {
|
if (!links) {
|
||||||
return [];
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const urls = extractURLs(text);
|
const urls = extractURLs(text);
|
||||||
|
|
||||||
if (!urls) {
|
if (!urls) {
|
||||||
return [];
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return urls
|
return urls
|
||||||
|
@ -170,7 +184,7 @@ export class PostNewHandler extends VkEventHandler<Fields, Values> {
|
||||||
|
|
||||||
return label ? { text: links[label], url: url.toString() } : undefined;
|
return label ? { text: links[label], url: url.toString() } : undefined;
|
||||||
})
|
})
|
||||||
.filter((el) => el);
|
.filter((el) => el) as InlineKeyboardButton[];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -179,7 +193,15 @@ export class PostNewHandler extends VkEventHandler<Fields, Values> {
|
||||||
private generateLikes: ExtraGenerator = async (text, eventId) => {
|
private generateLikes: ExtraGenerator = async (text, eventId) => {
|
||||||
if (eventId) {
|
if (eventId) {
|
||||||
const event = await this.getEventById(eventId);
|
const event = await this.getEventById(eventId);
|
||||||
const likes = await this.db.getLikesFor(this.channel, event.tgMessageId);
|
if (!event) {
|
||||||
|
throw new Error(`Can't find event`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const likes = await this.db.getLikesFor(
|
||||||
|
this.channel.id,
|
||||||
|
event.tgMessageId
|
||||||
|
);
|
||||||
|
|
||||||
const withCount = likes.reduce(
|
const withCount = likes.reduce(
|
||||||
(acc, like) => ({
|
(acc, like) => ({
|
||||||
...acc,
|
...acc,
|
||||||
|
@ -209,7 +231,7 @@ export class PostNewHandler extends VkEventHandler<Fields, Values> {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds needed listeners
|
* Adds needed listeners for telegram
|
||||||
*/
|
*/
|
||||||
protected onInit = () => {
|
protected onInit = () => {
|
||||||
if (this.template.fields.likes) {
|
if (this.template.fields.likes) {
|
||||||
|
@ -227,7 +249,7 @@ export class PostNewHandler extends VkEventHandler<Fields, Values> {
|
||||||
* Reacts to like button press
|
* Reacts to like button press
|
||||||
*/
|
*/
|
||||||
private onLikeAction = async (ctx: LikeCtx, next) => {
|
private onLikeAction = async (ctx: LikeCtx, next) => {
|
||||||
const id = ctx.update.callback_query.message.message_id;
|
const id = ctx.update.callback_query?.message?.message_id;
|
||||||
const author = ctx.update.callback_query.from.id;
|
const author = ctx.update.callback_query.from.id;
|
||||||
const [, channel, emo] = ctx.match;
|
const [, channel, emo] = ctx.match;
|
||||||
const event = await this.getEventByTgMessageId(id);
|
const event = await this.getEventByTgMessageId(id);
|
||||||
|
@ -237,7 +259,7 @@ export class PostNewHandler extends VkEventHandler<Fields, Values> {
|
||||||
!emo ||
|
!emo ||
|
||||||
!id ||
|
!id ||
|
||||||
!event ||
|
!event ||
|
||||||
channel != this.channel ||
|
channel != this.channel.id ||
|
||||||
!this.likes.includes(emo)
|
!this.likes.includes(emo)
|
||||||
) {
|
) {
|
||||||
await next();
|
await next();
|
||||||
|
@ -261,7 +283,7 @@ export class PostNewHandler extends VkEventHandler<Fields, Values> {
|
||||||
const markup = await this.createKeyboard(post.text, event.id);
|
const markup = await this.createKeyboard(post.text, event.id);
|
||||||
|
|
||||||
await ctx.telegram.editMessageReplyMarkup(
|
await ctx.telegram.editMessageReplyMarkup(
|
||||||
ctx.chat.id,
|
ctx.chat?.id,
|
||||||
id,
|
id,
|
||||||
ctx.inlineMessageId,
|
ctx.inlineMessageId,
|
||||||
markup
|
markup
|
||||||
|
@ -274,6 +296,9 @@ export class PostNewHandler extends VkEventHandler<Fields, Values> {
|
||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates or updates like for {author} on {messageId} with {emo}
|
||||||
|
*/
|
||||||
private createOrUpdateLike = async (
|
private createOrUpdateLike = async (
|
||||||
author: number,
|
author: number,
|
||||||
messageId: number,
|
messageId: number,
|
||||||
|
@ -281,23 +306,31 @@ export class PostNewHandler extends VkEventHandler<Fields, Values> {
|
||||||
) => {
|
) => {
|
||||||
return await this.db.createOrUpdateLike(
|
return await this.db.createOrUpdateLike(
|
||||||
messageId,
|
messageId,
|
||||||
this.channel,
|
this.channel.id,
|
||||||
author,
|
author,
|
||||||
emo
|
emo
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets like by {author} on {messageId}
|
||||||
|
*/
|
||||||
private getLike = async (author: number, messageId: number) => {
|
private getLike = async (author: number, messageId: number) => {
|
||||||
return await this.db.getLikeBy(this.channel, messageId, author);
|
return await this.db.getLikeBy(this.channel.id, messageId, author);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies template theming to photos
|
* Applies template theming to photos
|
||||||
*/
|
*/
|
||||||
private themeText = (text: string, user?: UsersUserFull): string => {
|
private themeText = (
|
||||||
|
text: string,
|
||||||
|
type?: string,
|
||||||
|
user?: UsersUserFull
|
||||||
|
): string => {
|
||||||
return this.template.theme({
|
return this.template.theme({
|
||||||
user,
|
user,
|
||||||
group: this.group,
|
group: this.group,
|
||||||
|
type,
|
||||||
text,
|
text,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -305,10 +338,24 @@ export class PostNewHandler extends VkEventHandler<Fields, Values> {
|
||||||
/**
|
/**
|
||||||
* Calculates, how much should we cut off the text to match photo caption limitations
|
* Calculates, how much should we cut off the text to match photo caption limitations
|
||||||
*/
|
*/
|
||||||
private trimTextForPhoto = (text: string, user: UsersUserFull): string => {
|
private trimTextForPhoto = (
|
||||||
const withText = this.themeText(text, user);
|
text: string,
|
||||||
const withoutText = this.themeText("", user);
|
type?: string,
|
||||||
|
user?: UsersUserFull
|
||||||
|
): string => {
|
||||||
|
const withText = this.themeText(text, type, user);
|
||||||
|
|
||||||
return withText.slice(0, PHOTO_CAPTION_LIMIT - withoutText.length);
|
if (withText.length < PHOTO_CAPTION_LIMIT) {
|
||||||
|
return withText;
|
||||||
|
}
|
||||||
|
|
||||||
|
const withoutText = this.themeText("", type, user);
|
||||||
|
const suffix = "...";
|
||||||
|
const trimmed = text.slice(
|
||||||
|
0,
|
||||||
|
PHOTO_CAPTION_LIMIT - withoutText.length - suffix.length
|
||||||
|
);
|
||||||
|
|
||||||
|
return this.themeText(`${trimmed}${suffix}`, type, user);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { NextMiddleware } from "middleware-io";
|
import { NextMiddleware } from "middleware-io";
|
||||||
import { ConfigGroup, GroupInstance, VkEvent } from "../types";
|
import { ConfigGroup, GroupChannel, GroupInstance, VkEvent } from "../types";
|
||||||
import { VkService } from "../index";
|
import { VkService } from "../index";
|
||||||
import { TelegramService } from "../../telegram";
|
import { TelegramService } from "../../telegram";
|
||||||
import { Template } from "../../template";
|
import { Template } from "../../template";
|
||||||
|
@ -13,7 +13,7 @@ export class VkEventHandler<
|
||||||
public constructor(
|
public constructor(
|
||||||
protected type: VkEvent,
|
protected type: VkEvent,
|
||||||
protected group: ConfigGroup,
|
protected group: ConfigGroup,
|
||||||
protected channel: string,
|
protected channel: GroupChannel,
|
||||||
protected instance: GroupInstance,
|
protected instance: GroupInstance,
|
||||||
protected vk: VkService,
|
protected vk: VkService,
|
||||||
protected telegram: TelegramService,
|
protected telegram: TelegramService,
|
||||||
|
@ -60,7 +60,7 @@ export class VkEventHandler<
|
||||||
this.type,
|
this.type,
|
||||||
id,
|
id,
|
||||||
this.group.id,
|
this.group.id,
|
||||||
this.channel
|
this.channel.id
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ export class VkEventHandler<
|
||||||
this.type,
|
this.type,
|
||||||
tgMessageId,
|
tgMessageId,
|
||||||
this.group.id,
|
this.group.id,
|
||||||
this.channel
|
this.channel.id
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ export class VkEventHandler<
|
||||||
this.type,
|
this.type,
|
||||||
id,
|
id,
|
||||||
this.group.id,
|
this.group.id,
|
||||||
this.channel,
|
this.channel.id,
|
||||||
tgMessageId,
|
tgMessageId,
|
||||||
text
|
text
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ConfigGroup, GroupInstance, VkEvent } from "../types";
|
import { ConfigGroup, GroupChannel, GroupInstance, VkEvent } from "../types";
|
||||||
import { VkEventHandler } from "./VkEventHandler";
|
import { VkEventHandler } from "./VkEventHandler";
|
||||||
import { MessageNewHandler } from "./MessageNewHandler";
|
import { MessageNewHandler } from "./MessageNewHandler";
|
||||||
import { StubHandler } from "./StubHandler";
|
import { StubHandler } from "./StubHandler";
|
||||||
|
@ -12,7 +12,7 @@ interface Handler {
|
||||||
new (
|
new (
|
||||||
type: VkEvent,
|
type: VkEvent,
|
||||||
group: ConfigGroup,
|
group: ConfigGroup,
|
||||||
channel: string,
|
channel: GroupChannel,
|
||||||
instance: GroupInstance,
|
instance: GroupInstance,
|
||||||
vk: VkService,
|
vk: VkService,
|
||||||
telegram: TelegramService,
|
telegram: TelegramService,
|
||||||
|
|
|
@ -29,7 +29,7 @@ export class VkService {
|
||||||
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;
|
this.endpoint = config.endpoint || "/";
|
||||||
|
|
||||||
this.groups = config.groups.reduce(
|
this.groups = config.groups.reduce(
|
||||||
(acc, group) => ({
|
(acc, group) => ({
|
||||||
|
@ -121,7 +121,7 @@ export class VkService {
|
||||||
const handler = new vkEventToHandler[event](
|
const handler = new vkEventToHandler[event](
|
||||||
event,
|
event,
|
||||||
group,
|
group,
|
||||||
chan.id,
|
chan,
|
||||||
instance,
|
instance,
|
||||||
this,
|
this,
|
||||||
this.telegram,
|
this.telegram,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { API, Upload, Updates } from "vk-io";
|
import { API, Upload, Updates } from "vk-io";
|
||||||
|
import { WallPostType } from "vk-io/lib/api/schemas/objects";
|
||||||
|
|
||||||
export interface VkConfig extends Record<string, any> {
|
export interface VkConfig extends Record<string, any> {
|
||||||
groups: ConfigGroup[];
|
groups: ConfigGroup[];
|
||||||
|
@ -17,6 +18,7 @@ export interface ConfigGroup {
|
||||||
export interface GroupChannel {
|
export interface GroupChannel {
|
||||||
id: string;
|
id: string;
|
||||||
events: VkEvent[];
|
events: VkEvent[];
|
||||||
|
post_types: WallPostType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum VkEvent {
|
export enum VkEvent {
|
||||||
|
|
|
@ -13,5 +13,5 @@ export const extractURLs = (text: string): URL[] => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter((el) => el);
|
.filter((el) => el) as URL[];
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,7 +12,8 @@
|
||||||
"target": "es2017",
|
"target": "es2017",
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {},
|
"paths": {},
|
||||||
"lib": ["esnext"]
|
"lib": ["esnext"],
|
||||||
|
"strict": true
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"./**/*",
|
"./**/*",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue