Support for edits and better replies

This commit is contained in:
Inex Code 2020-11-13 01:40:53 +00:00
parent f3635581d5
commit f384ba6584
3 changed files with 119 additions and 27 deletions

View File

@ -22,19 +22,20 @@ Register that one with synapse and start the bridge with `npm run start`.
- [ ] Typing notifs - not possible yet - [ ] Typing notifs - not possible yet
- [ ] Presence - not possible yet - [ ] Presence - not possible yet
- [ ] Read notifications - not possible yet - [ ] Read notifications - not possible yet
- [ ] Message edits - [x] Message edits
- [ ] Message redacts - [ ] Message redacts
- VK -> Matrix - VK -> Matrix
- [x] Text content - [x] Text content
- [x] Image content - [x] Image content
- [ ] Audio/Video content - [x] Audio content
- [ ] Stickers - [ ] Video content
- [x] Stickers
- [ ] Other files - [ ] Other files
- [ ] Presence - not effective to track - [ ] Presence - not effective to track
- [x] Typing notifs - [x] Typing notifs
- [x] User profiles - [x] User profiles
- [ ] Read notifications - [ ] Read notifications - not effective to track
- [ ] Message edits - [x] Message edits
- [ ] Message redacts - [ ] Message redacts
## Usage ## Usage

View File

@ -51,6 +51,7 @@ const protocol: IProtocolInformation = {
file: true, file: true,
presence: false, presence: false,
reply: true, reply: true,
edit: true,
}, },
id: "vk", // an internal ID for the protocol, all lowercase id: "vk", // an internal ID for the protocol, all lowercase
displayname: "VK", // a human-readable name of the protocol 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("puppetNew", vk.newPuppet.bind(vk));
puppet.on("puppetDelete", vk.deletePuppet.bind(vk)); puppet.on("puppetDelete", vk.deletePuppet.bind(vk));
puppet.on("message", vk.handleMatrixMessage.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("reply", vk.handleMatrixReply.bind(vk));
puppet.on("image", vk.handleMatrixImage.bind(vk)); puppet.on("image", vk.handleMatrixImage.bind(vk));
puppet.on("file", vk.handleMatrixFile.bind(vk)); puppet.on("file", vk.handleMatrixFile.bind(vk));

133
src/vk.ts
View File

@ -42,7 +42,7 @@ export class VkPuppet {
Promise<IReceiveParams> { Promise<IReceiveParams> {
// we will use this function internally to create the send parameters // we will use this function internally to create the send parameters
// needed to send a message, a file, reactions, ... to matrix // 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 { return {
room: await this.getRemoteRoom(puppetId, peerId), room: await this.getRemoteRoom(puppetId, peerId),
@ -53,7 +53,7 @@ export class VkPuppet {
public async getRemoteUser(puppetId: number, userId: number): Promise<IRemoteUser> { public async getRemoteUser(puppetId: number, userId: number): Promise<IRemoteUser> {
const p = this.puppets[puppetId]; const p = this.puppets[puppetId];
log.info("User id:", userId, userId.toString()); //log.info("User id:", userId, userId.toString());
if (userId < 0) { if (userId < 0) {
const info = await p.client.api.groups.getById({ group_id: Math.abs(userId).toString() }); const info = await p.client.api.groups.getById({ group_id: Math.abs(userId).toString() });
const response: IRemoteUser = { const response: IRemoteUser = {
@ -78,7 +78,7 @@ export class VkPuppet {
public async getRemoteRoom(puppetId: number, peerId: number): Promise<IRemoteRoom> { public async getRemoteRoom(puppetId: number, peerId: number): Promise<IRemoteRoom> {
const p = this.puppets[puppetId]; const p = this.puppets[puppetId];
const info = await p.client.api.messages.getConversationsById({ peer_ids: peerId, fields: ["photo_max"] }); 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; let response: IRemoteRoom;
switch (info.items[0].peer.type) { switch (info.items[0].peer.type) {
case "user": case "user":
@ -125,7 +125,7 @@ export class VkPuppet {
const client = new VK({ token: data.token, apiLimit: 20 }); const client = new VK({ token: data.token, apiLimit: 20 });
log.info("Trying to init listener with", data.token); log.info("Trying to init listener with", data.token);
client.updates.on("message", async (context) => { client.updates.on("message_new", async (context) => {
try { try {
log.info("Recieved something!"); log.info("Recieved something!");
await this.handleVkMessage(puppetId, context); await this.handleVkMessage(puppetId, context);
@ -133,6 +133,14 @@ export class VkPuppet {
log.error("Error handling vk message event", err.error || err.body || err); 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) => { client.updates.on("message_typing_state", async (context) => {
if (context.isUser) { if (context.isUser) {
const params = await this.getSendParams(puppetId, context.fromId, context.fromId); 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( public async handleMatrixReply(
room: IRemoteRoom, room: IRemoteRoom,
eventId: string, eventId: string,
@ -198,10 +226,10 @@ export class VkPuppet {
return; return;
} }
try { try {
log.info("Sending reply", Number(eventId)); //log.info("Sending reply", Number(eventId));
const response = await p.client.api.messages.send({ const response = await p.client.api.messages.send({
peer_id: Number(room.roomId), peer_id: Number(room.roomId),
message: data.body, message: await this.stripReply(data.body),
random_id: new Date().getTime(), random_id: new Date().getTime(),
reply_to: Number(eventId), reply_to: Number(eventId),
}); });
@ -226,14 +254,14 @@ export class VkPuppet {
if (size < MAXFILESIZE) { if (size < MAXFILESIZE) {
try { try {
log.info("Sending image..."); //log.info("Sending image...");
const attachment = await p.client.upload.messagePhoto({ const attachment = await p.client.upload.messagePhoto({
peer_id: Number(room.roomId), peer_id: Number(room.roomId),
source: { source: {
value: data.url, value: data.url,
}, },
}); });
log.info("Image sent", attachment); //log.info("Image sent", attachment);
const response = await p.client.api.messages.send({ const response = await p.client.api.messages.send({
peer_id: Number(room.roomId), peer_id: Number(room.roomId),
random_id: new Date().getTime(), random_id: new Date().getTime(),
@ -272,7 +300,7 @@ export class VkPuppet {
if (size < MAXFILESIZE) { if (size < MAXFILESIZE) {
try { try {
log.info("Sending file..."); //log.info("Sending file...");
const attachment = await p.client.upload.messageDocument({ const attachment = await p.client.upload.messageDocument({
peer_id: Number(room.roomId), peer_id: Number(room.roomId),
source: { source: {
@ -280,7 +308,7 @@ export class VkPuppet {
filename: data.filename, filename: data.filename,
}, },
}); });
log.info("File sent", attachment); //log.info("File sent", attachment);
const response = await p.client.api.messages.send({ const response = await p.client.api.messages.send({
peer_id: Number(room.roomId), peer_id: Number(room.roomId),
random_id: new Date().getTime(), random_id: new Date().getTime(),
@ -313,6 +341,7 @@ export class VkPuppet {
} }
} }
public async createRoom(room: IRemoteRoom): Promise<IRemoteRoom | null> { public async createRoom(room: IRemoteRoom): Promise<IRemoteRoom | null> {
const p = this.puppets[room.puppetId]; const p = this.puppets[room.puppetId];
if (!p) { if (!p) {
@ -332,7 +361,7 @@ export class VkPuppet {
if (!p) { if (!p) {
return; return;
} }
log.info("Received new message!", context); //log.info("Received new message!", context);
if (context.isOutbox) { if (context.isOutbox) {
return; // Deduping return; // Deduping
} }
@ -367,22 +396,69 @@ export class VkPuppet {
} }
if (context.hasAttachments()) { if (context.hasAttachments()) {
for (const f of context.attachments) { for (const f of context.attachments) {
if (f.type === AttachmentType.PHOTO) { switch (f.type) {
log.info(f); case AttachmentType.PHOTO:
try { try {
// tslint:disable-next-line: no-string-literal // tslint:disable-next-line: no-string-literal
await this.puppet.sendFileDetect(params, f["largeSizeUrl"]); await this.puppet.sendFileDetect(params, f["largeSizeUrl"]);
} catch (err) { } catch (err) {
const opts: IMessageEvent = { const opts: IMessageEvent = {
body: `Image was sent: ${f["largeSizeUrl"]}`, body: `Image was sent: ${f["largeSizeUrl"]}`,
}; };
await this.puppet.sendMessage(params, opts); 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 // // Formatters //
//////////////// ////////////////
@ -397,4 +473,17 @@ export class VkPuppet {
formatted += `\n\n${body}`; formatted += `\n\n${body}`;
return formatted; 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());
}
} }