From 877804cf42a06f147f2cdea26fa2b351cc33be50 Mon Sep 17 00:00:00 2001 From: Inex Code Date: Tue, 3 Nov 2020 19:02:44 +0000 Subject: [PATCH] Add file handling --- README.md | 8 +-- src/index.ts | 6 ++- src/vk.ts | 135 +++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 139 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 8ed2a47..636b830 100755 --- a/README.md +++ b/README.md @@ -15,9 +15,9 @@ Register that one with synapse and start the bridge with `npm run start`. ## Features and roadmap - Matrix -> VK - [x] Text content - - [ ] Image content - - [ ] Audio/Video content - - [ ] Other files + - [x] Image content + - [x] Audio/Video content + - [x] Other files - [x] Replies - [ ] Typing notifs - not possible yet - [ ] Presence - not possible yet @@ -26,7 +26,7 @@ Register that one with synapse and start the bridge with `npm run start`. - [ ] Message redacts - VK -> Matrix - [x] Text content - - [ ] Image content + - [x] Image content - [ ] Audio/Video content - [ ] Stickers - [ ] Other files diff --git a/src/index.ts b/src/index.ts index b53a8ff..470f367 100755 --- a/src/index.ts +++ b/src/index.ts @@ -47,8 +47,10 @@ if (options.help) { // here we define some information about our protocol, what features it supports etc. const protocol: IProtocolInformation = { features: { - file: false, + image: true, + file: true, presence: false, + reply: true, }, id: "vk", // an internal ID for the protocol, all lowercase displayname: "VK", // a human-readable name of the protocol @@ -86,6 +88,8 @@ async function run() { puppet.on("puppetDelete", vk.deletePuppet.bind(vk)); puppet.on("message", vk.handleMatrixMessage.bind(vk)); puppet.on("reply", vk.handleMatrixReply.bind(vk)); + puppet.on("image", vk.handleMatrixImage.bind(vk)); + puppet.on("file", vk.handleMatrixFile.bind(vk)); puppet.setCreateRoomHook(vk.createRoom.bind(vk)); diff --git a/src/vk.ts b/src/vk.ts index 303ac9e..411673c 100755 --- a/src/vk.ts +++ b/src/vk.ts @@ -8,11 +8,13 @@ import { IFileEvent, MessageDeduplicator, Log, + ISendingUser, } from "mx-puppet-bridge"; -import { VK, MessageContext, Context } from "vk-io"; +import { VK, MessageContext, Context, AttachmentType } from "vk-io"; import { userInfo } from "os"; import { runInThisContext } from "vm"; +import { lookup } from "dns"; // here we create our log instance const log = new Log("VKPuppet:vk"); @@ -196,6 +198,7 @@ export class VkPuppet { return; } try { + log.info("Sending reply", Number(eventId)); const response = await p.client.api.messages.send({ peer_id: Number(room.roomId), message: data.body, @@ -208,6 +211,100 @@ export class VkPuppet { } } + public async handleMatrixImage( + room: IRemoteRoom, + data: IFileEvent, + asUser: ISendingUser | null, + event: any, + ) { + const p = this.puppets[room.puppetId]; + if (!p) { + return; + } + const MAXFILESIZE = 50000000; + const size = data.info ? data.info.size || 0 : 0; + + if (size < MAXFILESIZE) { + try { + log.info("Sending image..."); + const attachment = await p.client.upload.messagePhoto({ + peer_id: Number(room.roomId), + source: { + value: data.url, + }, + }); + log.info("Image sent", attachment); + const response = await p.client.api.messages.send({ + peer_id: Number(room.roomId), + random_id: new Date().getTime(), + attachment: [`photo${attachment.ownerId}_${attachment.id}`], + }); + await this.puppet.eventSync.insert(room, data.eventId!, response.toString()); + } catch (err) { + log.error("Error sending to vk", err.error || err.body || err); + } + } else { + try { + const response = await p.client.api.messages.send({ + peer_id: Number(room.roomId), + message: `File ${data.filename} was sent, but it is too big for VK. You may download it there:\n${data.url}`, + random_id: new Date().getTime(), + }); + await this.puppet.eventSync.insert(room, data.eventId!, response.toString()); + } catch (err) { + log.error("Error sending to vk", err.error || err.body || err); + } + } + } + + public async handleMatrixFile( + room: IRemoteRoom, + data: IFileEvent, + asUser: ISendingUser | null, + event: any, + ) { + const p = this.puppets[room.puppetId]; + if (!p) { + return; + } + const MAXFILESIZE = 50000000; + const size = data.info ? data.info.size || 0 : 0; + + if (size < MAXFILESIZE) { + try { + log.info("Sending file..."); + const attachment = await p.client.upload.messageDocument({ + peer_id: Number(room.roomId), + source: { + value: data.url, + filename: data.filename, + contentType: + }, + }); + log.info("File sent", attachment); + const response = await p.client.api.messages.send({ + peer_id: Number(room.roomId), + random_id: new Date().getTime(), + attachment: [`doc${attachment.ownerId}_${attachment.id}`], + }); + await this.puppet.eventSync.insert(room, data.eventId!, response.toString()); + } catch (err) { + log.error("Error sending to vk", err.error || err.body || err); + } + } else { + try { + const response = await p.client.api.messages.send({ + peer_id: Number(room.roomId), + message: `File ${data.filename} was sent, but it is too big for VK. You may download it there:\n${data.url}`, + random_id: new Date().getTime(), + }); + await this.puppet.eventSync.insert(room, data.eventId!, response.toString()); + } catch (err) { + log.error("Error sending to vk", err.error || err.body || err); + } + } + } + public async createRoom(room: IRemoteRoom): Promise { const p = this.puppets[room.puppetId]; if (!p) { @@ -235,18 +332,46 @@ export class VkPuppet { const params = await this.getSendParams(puppetId, context.peerId, context.senderId, context.id.toString()); if (context.hasText) { - const opts: IMessageEvent = { - body: context.text || "Attachment", - }; if (context.hasReplyMessage) { if (this.puppet.eventSync.getMatrix(params.room, context.replyMessage!.id.toString())) { + const opts: IMessageEvent = { + body: context.text || "Attachment", + }; // We got referenced message in room, using matrix reply await this.puppet.sendReply(params, context.replyMessage!.id.toString(), opts); } else { // Using a fallback + const opts: IMessageEvent = { + body: await this.prependReply( + puppetId, context.text || "", + context.replyMessage?.text || "", + context.senderId.toString(), + ), + }; + await this.puppet.sendMessage(params, opts); + } + } else { + const opts: IMessageEvent = { + body: context.text || "Attachment", + }; + await this.puppet.sendMessage(params, opts); + } + } + if (context.hasAttachments()) { + for (const f of context.attachments) { + if (f.type === AttachmentType.PHOTO) { + log.info(f); + try { + // tslint:disable-next-line: no-string-literal + await this.puppet.sendFileDetect(params, f["largeSizeUrl"]); + } catch (err) { + const opts: IMessageEvent = { + body: `Image was sent: ${f["largeSizeUrl"]}`, + }; + await this.puppet.sendMessage(params, opts); + } } } - await this.puppet.sendMessage(params, opts); } }