Support for edits and better replies
This commit is contained in:
parent
f3635581d5
commit
f384ba6584
11
README.md
11
README.md
|
@ -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
|
||||||
|
|
|
@ -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
133
src/vk.ts
|
@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue