Init
This commit is contained in:
56
src/bot.ts
Normal file
56
src/bot.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import { PhotoAttachment, VK } from "vk-io";
|
||||
import { env } from "../env";
|
||||
import { MEDIUM_SIZES, getAttachmentBySizes } from "./utils";
|
||||
import { makeLiquidRescale } from "./queues/liquid.queue";
|
||||
|
||||
export const bot = new VK({ token: env.VK_BOT_TOKEN });
|
||||
|
||||
bot.updates.on('message_new', async (context, next) => {
|
||||
if (context.isChat) return; // ignore chats for now
|
||||
if (!context.hasAllAttachments('photo')) return;
|
||||
|
||||
const processingMessage = await context.reply('Обрабатываю...');
|
||||
|
||||
const results = [];
|
||||
|
||||
for (let attachment of context.attachments) {
|
||||
if (attachment.type === 'photo') {
|
||||
const [size] = getAttachmentBySizes(attachment as PhotoAttachment, MEDIUM_SIZES);
|
||||
const imageUrl = size?.url;
|
||||
|
||||
if (imageUrl) {
|
||||
const liquidRescaleJob = await makeLiquidRescale({ imageUrl: imageUrl });
|
||||
let result;
|
||||
|
||||
try {
|
||||
result = await liquidRescaleJob.finished();
|
||||
} catch (err) {
|
||||
return context.reply('Упс... что-то пошло не так...');
|
||||
}
|
||||
|
||||
results.push(Buffer.from(result.data));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const attachments: PhotoAttachment[] = [];
|
||||
|
||||
for (let image of results) {
|
||||
const attachment = await bot.upload.messagePhoto({
|
||||
peer_id: context.senderId,
|
||||
source: {
|
||||
values: {
|
||||
value: image,
|
||||
contentType: 'image/jpeg'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
attachments.push(attachment);
|
||||
}
|
||||
|
||||
await processingMessage.editMessage({ attachment: attachments });
|
||||
|
||||
return next();
|
||||
});
|
19
src/logger.ts
Normal file
19
src/logger.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import pino, { LoggerOptions } from "pino";
|
||||
import PinoPretty, { PrettyOptions } from "pino-pretty";
|
||||
import { env } from "../env";
|
||||
|
||||
const options: LoggerOptions = {
|
||||
level: env.LOG_LEVEL
|
||||
};
|
||||
|
||||
const prettyOptions: PrettyOptions = {
|
||||
ignore: 'pid,hostname',
|
||||
colorize: env.isDev ? true : false,
|
||||
translateTime: 'SYS:dd.mm.yyyy, HH:MM:ss'
|
||||
};
|
||||
|
||||
export let logger = pino(options);
|
||||
|
||||
if (env.isDev) {
|
||||
logger = pino(options, PinoPretty(prettyOptions));
|
||||
}
|
27
src/processes/liquid.process.ts
Normal file
27
src/processes/liquid.process.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { Job } from "bull";
|
||||
import { logger } from "../logger";
|
||||
import { env } from "../../env";
|
||||
import { fetchImage } from "../utils";
|
||||
|
||||
export const liquidRescaleProcess = async (job: Job) => {
|
||||
logger.info({ id: job.id, data: job.data }, 'Processing liquid rescale job');
|
||||
|
||||
const { imageUrl } = job.data;
|
||||
|
||||
const image = await fetchImage(imageUrl);
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('file', new Blob([image]));
|
||||
|
||||
let result;
|
||||
|
||||
try {
|
||||
result = await fetchImage(env.LIQUID_RESCALE_API_URL, { method: 'POST', body: formData });
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
return Promise.reject(err);
|
||||
}
|
||||
|
||||
// return Promise.resolve({ data: result.toString('base64') });
|
||||
return Promise.resolve(result);
|
||||
};
|
18
src/queues/liquid.queue.ts
Normal file
18
src/queues/liquid.queue.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import Bull from "bull";
|
||||
import { env } from "../../env";
|
||||
import { liquidRescaleProcess } from "../processes/liquid.process";
|
||||
|
||||
export const liquidRescaleQueue = new Bull('liquid-rescale', {
|
||||
redis: {
|
||||
host: env.REDIS_HOST,
|
||||
port: env.REDIS_PORT
|
||||
}
|
||||
});
|
||||
|
||||
liquidRescaleQueue.process(env.BULL_CONCURRENCY, liquidRescaleProcess);
|
||||
|
||||
const makeLiquidRescale = async (data: { imageUrl: string; }) => {
|
||||
return liquidRescaleQueue.add({ ...data }, { attempts: 3 });
|
||||
};
|
||||
|
||||
export { makeLiquidRescale };
|
35
src/utils.ts
Normal file
35
src/utils.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { PhotoAttachment } from "vk-io";
|
||||
|
||||
export const SMALL_SIZES = ['m', 's'];
|
||||
export const MEDIUM_SIZES = ['y', 'r', 'q', 'p', ...SMALL_SIZES];
|
||||
export const LARGE_SIZES = ['w', 'z', ...MEDIUM_SIZES];
|
||||
|
||||
export async function fetchImage(url: string, params?: RequestInit) {
|
||||
const image = await fetch(url, params)
|
||||
.then(r => r.arrayBuffer());
|
||||
const imageBuffer = Buffer.from(image);
|
||||
return imageBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Example:
|
||||
* ```js
|
||||
* const SMALL_SIZES = ['m', 's'];
|
||||
* const MEDIUM_SIZES = ['y', 'r', 'q', 'p', ...SMALL_SIZES];
|
||||
* const LARGE_SIZES = ['w', 'z', ...MEDIUM_SIZES];
|
||||
*
|
||||
* const [size] = getAttachmentBySizes(attachment, LARGE_SIZES);
|
||||
* console.log(size)
|
||||
* ```
|
||||
*/
|
||||
export function getAttachmentBySizes(photoAttachment: PhotoAttachment, sizeTypes: string[] = []) {
|
||||
const { sizes } = photoAttachment;
|
||||
|
||||
if (!sizes) return [];
|
||||
|
||||
return sizeTypes
|
||||
.map((sizeType) => (
|
||||
sizes.find((size) => size.type === sizeType)
|
||||
))
|
||||
.filter(Boolean);
|
||||
}
|
Reference in New Issue
Block a user