From f384ba6584c0e6e8eb7fcfdb4612048ef5973574 Mon Sep 17 00:00:00 2001 From: Inex Code Date: Fri, 13 Nov 2020 01:40:53 +0000 Subject: [PATCH] Support for edits and better replies --- README.md | 11 +++-- src/index.ts | 2 + src/vk.ts | 133 ++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 119 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 636b830..c33764a 100755 --- a/README.md +++ b/README.md @@ -22,19 +22,20 @@ Register that one with synapse and start the bridge with `npm run start`. - [ ] Typing notifs - not possible yet - [ ] Presence - not possible yet - [ ] Read notifications - not possible yet - - [ ] Message edits + - [x] Message edits - [ ] Message redacts - VK -> Matrix - [x] Text content - [x] Image content - - [ ] Audio/Video content - - [ ] Stickers + - [x] Audio content + - [ ] Video content + - [x] Stickers - [ ] Other files - [ ] Presence - not effective to track - [x] Typing notifs - [x] User profiles - - [ ] Read notifications - - [ ] Message edits + - [ ] Read notifications - not effective to track + - [x] Message edits - [ ] Message redacts ## Usage diff --git a/src/index.ts b/src/index.ts index 470f367..3d8efd9 100755 --- a/src/index.ts +++ b/src/index.ts @@ -51,6 +51,7 @@ const protocol: IProtocolInformation = { file: true, presence: false, reply: true, + edit: true, }, id: "vk", // an internal ID for the protocol, all lowercase displayname: "VK", // a human-readable name of the protocol @@ -87,6 +88,7 @@ async function run() { puppet.on("puppetNew", vk.newPuppet.bind(vk)); puppet.on("puppetDelete", vk.deletePuppet.bind(vk)); puppet.on("message", vk.handleMatrixMessage.bind(vk)); + puppet.on("edit", vk.handleMatrixEdit.bind(vk)); puppet.on("reply", vk.handleMatrixReply.bind(vk)); puppet.on("image", vk.handleMatrixImage.bind(vk)); puppet.on("file", vk.handleMatrixFile.bind(vk)); diff --git a/src/vk.ts b/src/vk.ts index 0639d77..30e7cc4 100755 --- a/src/vk.ts +++ b/src/vk.ts @@ -42,7 +42,7 @@ export class VkPuppet { Promise { // we will use this function internally to create the send parameters // needed to send a message, a file, reactions, ... to matrix - log.info(`Creating send params for ${peerId}...`); + //log.info(`Creating send params for ${peerId}...`); return { room: await this.getRemoteRoom(puppetId, peerId), @@ -53,7 +53,7 @@ export class VkPuppet { public async getRemoteUser(puppetId: number, userId: number): Promise { const p = this.puppets[puppetId]; - log.info("User id:", userId, userId.toString()); + //log.info("User id:", userId, userId.toString()); if (userId < 0) { const info = await p.client.api.groups.getById({ group_id: Math.abs(userId).toString() }); const response: IRemoteUser = { @@ -78,7 +78,7 @@ export class VkPuppet { public async getRemoteRoom(puppetId: number, peerId: number): Promise { const p = this.puppets[puppetId]; const info = await p.client.api.messages.getConversationsById({ peer_ids: peerId, fields: ["photo_max"] }); - log.info(info.items[0]); + //log.info(info.items[0]); let response: IRemoteRoom; switch (info.items[0].peer.type) { case "user": @@ -125,7 +125,7 @@ export class VkPuppet { const client = new VK({ token: data.token, apiLimit: 20 }); log.info("Trying to init listener with", data.token); - client.updates.on("message", async (context) => { + client.updates.on("message_new", async (context) => { try { log.info("Recieved something!"); await this.handleVkMessage(puppetId, context); @@ -133,6 +133,14 @@ export class VkPuppet { log.error("Error handling vk message event", err.error || err.body || err); } }); + client.updates.on("message_edit", async (context) => { + try { + log.info("Edit recieved!"); + await this.handleVkEdit(puppetId, context); + } catch (err) { + log.error("Error handling vk message event", err.error || err.body || err); + } + }); client.updates.on("message_typing_state", async (context) => { if (context.isUser) { const params = await this.getSendParams(puppetId, context.fromId, context.fromId); @@ -187,6 +195,26 @@ export class VkPuppet { } } + public async handleMatrixEdit(room: IRemoteRoom, eventId: string, data: IMessageEvent) { + const p = this.puppets[room.puppetId]; + if (!p) { + return; + } + // usually you'd send it here to the remote protocol via the client object + try { + const response = await p.client.api.messages.edit({ + peer_id: Number(room.roomId), + message: data.body, + message_id: Number(eventId), + random_id: new Date().getTime(), + }); + await this.puppet.eventSync.insert(room, data.eventId!, response.toString()); + } catch (err) { + log.error("Error sending edit to vk", err.error || err.body || err); + } + } + + public async handleMatrixReply( room: IRemoteRoom, eventId: string, @@ -198,10 +226,10 @@ export class VkPuppet { return; } try { - log.info("Sending reply", Number(eventId)); + //log.info("Sending reply", Number(eventId)); const response = await p.client.api.messages.send({ peer_id: Number(room.roomId), - message: data.body, + message: await this.stripReply(data.body), random_id: new Date().getTime(), reply_to: Number(eventId), }); @@ -226,14 +254,14 @@ export class VkPuppet { if (size < MAXFILESIZE) { try { - log.info("Sending image..."); + //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); + //log.info("Image sent", attachment); const response = await p.client.api.messages.send({ peer_id: Number(room.roomId), random_id: new Date().getTime(), @@ -272,7 +300,7 @@ export class VkPuppet { if (size < MAXFILESIZE) { try { - log.info("Sending file..."); + //log.info("Sending file..."); const attachment = await p.client.upload.messageDocument({ peer_id: Number(room.roomId), source: { @@ -280,7 +308,7 @@ export class VkPuppet { filename: data.filename, }, }); - log.info("File sent", attachment); + //log.info("File sent", attachment); const response = await p.client.api.messages.send({ peer_id: Number(room.roomId), random_id: new Date().getTime(), @@ -313,6 +341,7 @@ export class VkPuppet { } } + public async createRoom(room: IRemoteRoom): Promise { const p = this.puppets[room.puppetId]; if (!p) { @@ -332,7 +361,7 @@ export class VkPuppet { if (!p) { return; } - log.info("Received new message!", context); + //log.info("Received new message!", context); if (context.isOutbox) { return; // Deduping } @@ -367,22 +396,69 @@ export class VkPuppet { } 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); - } + switch (f.type) { + case AttachmentType.PHOTO: + 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); + } + break; + case AttachmentType.STICKER: + try { + await this.puppet.sendFileDetect(params, f["imagesWithBackground"][4]["url"]); + } catch (err) { + const opts: IMessageEvent = { + body: `Sticker was sent: ${f["imagesWithBackground"][4]["url"]}`, + }; + await this.puppet.sendMessage(params, opts); + } + break; + case AttachmentType.AUDIO_MESSAGE: + try { + await this.puppet.sendAudio(params, f["oggUrl"]); + } catch (err) { + const opts: IMessageEvent = { + body: `Audio message was sent: ${f["url"]}`, + }; + await this.puppet.sendMessage(params, opts); + } + break; + default: + break; } } } } + + public async handleVkEdit(puppetId: number, context: MessageContext) { + log.error("OwO", context); + const p = this.puppets[puppetId]; + if (!p) { + return; + } + // As VK always sends edit as outbox, we won't work with any edits from groups + if (context.senderType == "group") { + log.error("oh no no"); + + return; // Deduping + } + + const params = await this.getSendParams(puppetId, context.peerId, context.senderId, context.id.toString()); + log.error("UWU", context.hasText); + if (context.hasText) { + const opts: IMessageEvent = { + body: context.text || "Attachment", + }; + await this.puppet.sendEdit(params, context.id.toString(), opts); + } + } + //////////////// // Formatters // //////////////// @@ -397,4 +473,17 @@ export class VkPuppet { formatted += `\n\n${body}`; return formatted; } + + public async stripReply(body: string) { + let splitted = body.split("\n"); + let isCitate = true; + while (isCitate) { + if (splitted[0].startsWith(">")) { + splitted.splice(0, 1); + } else { + isCitate = false; + } + } + return(splitted.join('\n').trim()); + } }