From 5510dc059bbfe2090815ecc2126e8c0a3b4c4a4d Mon Sep 17 00:00:00 2001 From: Inex Code Date: Tue, 3 Nov 2020 16:38:06 +0000 Subject: [PATCH] Initial reply implementation --- README.md | 10 +++---- src/index.ts | 6 ++--- src/vk.ts | 75 ++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 66 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index cc71037..8ed2a47 100755 --- a/README.md +++ b/README.md @@ -18,10 +18,10 @@ Register that one with synapse and start the bridge with `npm run start`. - [ ] Image content - [ ] Audio/Video content - [ ] Other files - - [ ] Replies - - [ ] Typing notifs - - [ ] Presence - - [ ] Read notifications + - [x] Replies + - [ ] Typing notifs - not possible yet + - [ ] Presence - not possible yet + - [ ] Read notifications - not possible yet - [ ] Message edits - [ ] Message redacts - VK -> Matrix @@ -30,7 +30,7 @@ Register that one with synapse and start the bridge with `npm run start`. - [ ] Audio/Video content - [ ] Stickers - [ ] Other files - - [ ] Presence + - [ ] Presence - not effective to track - [x] Typing notifs - [x] User profiles - [ ] Read notifications diff --git a/src/index.ts b/src/index.ts index f786648..b53a8ff 100755 --- a/src/index.ts +++ b/src/index.ts @@ -82,12 +82,12 @@ async function run() { // create our own protocol class const vk = new VkPuppet(puppet); - // required: listen to when a new puppet is created puppet.on("puppetNew", vk.newPuppet.bind(vk)); - // required: listen to when a puppet is deleted puppet.on("puppetDelete", vk.deletePuppet.bind(vk)); - // required: listen to when a message is received from matrix puppet.on("message", vk.handleMatrixMessage.bind(vk)); + puppet.on("reply", vk.handleMatrixReply.bind(vk)); + + puppet.setCreateRoomHook(vk.createRoom.bind(vk)); // required: get description hook puppet.setGetDescHook(async (puppetId: number, data: any): Promise => { diff --git a/src/vk.ts b/src/vk.ts index dd8da98..303ac9e 100755 --- a/src/vk.ts +++ b/src/vk.ts @@ -37,7 +37,7 @@ export class VkPuppet { ) { } public async getSendParams(puppetId: number, peerId: number, senderId: number, eventId?: string | undefined): - Promise { + 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}...`); @@ -159,6 +159,10 @@ export class VkPuppet { delete this.puppets[puppetId]; // and finally delete our local copy } + ////////////////////////// + // Matrix -> VK section // + ////////////////////////// + public async handleMatrixMessage(room: IRemoteRoom, data: IMessageEvent, event: any) { // this is called every time we receive a message from matrix and need to // forward it to the remote protocol. @@ -169,7 +173,6 @@ export class VkPuppet { return; } // usually you'd send it here to the remote protocol via the client object - const dedupeKey = `${room.puppetId};${room.roomId}`; try { const response = await p.client.api.messages.send({ peer_id: Number(room.roomId), @@ -180,7 +183,29 @@ export class VkPuppet { } catch (err) { log.error("Error sending to vk", err.error || err.body || err); } + } + public async handleMatrixReply( + room: IRemoteRoom, + eventId: string, + data: IMessageEvent, + event: any, + ) { + const p = this.puppets[room.puppetId]; + if (!p) { + return; + } + try { + const response = await p.client.api.messages.send({ + peer_id: Number(room.roomId), + message: data.body, + random_id: new Date().getTime(), + reply_to: Number(eventId), + }); + 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 { @@ -193,19 +218,9 @@ export class VkPuppet { return await this.getRemoteRoom(room.puppetId, Number(room.roomId)); } - public async getDmRoomId(user: IRemoteUser): Promise { - // this is called whenever someone invites a ghost on the matrix side - // from the user ID we need to return the room ID of the DM room, or null if none is present - - // first we check if the puppet exists - const p = this.puppets[user.puppetId]; - if (!p) { - return null; - } - - // now we just return the userId of the ghost - return user.userId; - } + ////////////////////////// + // VK -> Matrix section // + ////////////////////////// public async handleVkMessage(puppetId: number, context: MessageContext) { const p = this.puppets[puppetId]; @@ -213,14 +228,40 @@ export class VkPuppet { return; } log.info("Received new message!", context); + if (context.isOutbox) { + return; // Deduping + } const params = await this.getSendParams(puppetId, context.peerId, context.senderId, context.id.toString()); - if (context.hasText && !context.isOutbox) { - const opts = { + if (context.hasText) { + const opts: IMessageEvent = { body: context.text || "Attachment", }; + if (context.hasReplyMessage) { + if (this.puppet.eventSync.getMatrix(params.room, context.replyMessage!.id.toString())) { + // We got referenced message in room, using matrix reply + await this.puppet.sendReply(params, context.replyMessage!.id.toString(), opts); + } else { + // Using a fallback + } + } await this.puppet.sendMessage(params, opts); } } + + //////////////// + // Formatters // + //////////////// + + public async prependReply(puppetId: number, body: string, reply: string, userid: string) { + const user = await this.getRemoteUser(puppetId, Number(userid)); + const replySplitted = reply.split("\n"); + let formatted: string = `> <${user.name}>\n`; + replySplitted.forEach((element) => { + formatted += `> ${element}`; + }); + formatted += `\n\n${body}`; + return formatted; + } }