Version 0.7.0
* Add read markers support from matrix side * Allow sending audio messages from matrix side * Attempt to fix post forwarding, not fixed entirely yet * Fixed message formatting in wall forwards
This commit is contained in:
parent
40a1682d01
commit
8ab14c574e
12
README.md
12
README.md
|
@ -29,7 +29,7 @@ Register that one with synapse and start the bridge with `npm run start`.
|
||||||
- [x] Replies
|
- [x] Replies
|
||||||
- [x] Typing notifs - [see note](#Note-on-presence-from-matrix-side)
|
- [x] Typing notifs - [see note](#Note-on-presence-from-matrix-side)
|
||||||
- [ ] Presence - ~~not possible yet~~
|
- [ ] Presence - ~~not possible yet~~
|
||||||
- [ ] Read notifications - ~~not possible yet~~
|
- [x] Read notifications
|
||||||
- [x] Message edits
|
- [x] Message edits
|
||||||
- [x] Message redacts - works as edit, real redact unavailable without being admin in chat
|
- [x] Message redacts - works as edit, real redact unavailable without being admin in chat
|
||||||
- [ ] Initiate rooms from the matrix side
|
- [ ] Initiate rooms from the matrix side
|
||||||
|
@ -108,12 +108,12 @@ where the access token is `df89482ba9a19e5a2dee85031612b021a08cd521115e1c7d2cd70
|
||||||
- Matrix -> VK (AS A USER)
|
- Matrix -> VK (AS A USER)
|
||||||
- [x] Text content
|
- [x] Text content
|
||||||
- [x] Image content
|
- [x] Image content
|
||||||
- [x] Audio/Video content
|
- [x] Audio messages
|
||||||
- [x] Other files
|
- [x] Other files
|
||||||
- [x] Replies
|
- [x] Replies
|
||||||
- [x] Typing notifs
|
- [x] Typing notifs
|
||||||
- [ ] Presence
|
- [ ] Presence
|
||||||
- [ ] Read notifications
|
- [x] Read notifications
|
||||||
- [x] Message edits
|
- [x] Message edits
|
||||||
- [x] Message redacts - in 24 hours
|
- [x] Message redacts - in 24 hours
|
||||||
- [ ] Initiate rooms from the matrix side
|
- [ ] Initiate rooms from the matrix side
|
||||||
|
@ -163,7 +163,7 @@ npm run build
|
||||||
- [x] Ответы
|
- [x] Ответы
|
||||||
- [x] Индикатор печати - [смотрите примечание](#примечание-о-эфемерных-событиях)
|
- [x] Индикатор печати - [смотрите примечание](#примечание-о-эфемерных-событиях)
|
||||||
- [ ] Индикатор "в сети"
|
- [ ] Индикатор "в сети"
|
||||||
- [ ] Индикаторы прочтения
|
- [x] Индикаторы прочтения
|
||||||
- [x] Редактирование сообщений
|
- [x] Редактирование сообщений
|
||||||
- [x] Удаление сообщений - работает как редактирование
|
- [x] Удаление сообщений - работает как редактирование
|
||||||
- [ ] Инициация чатов со стороны Matrix
|
- [ ] Инициация чатов со стороны Matrix
|
||||||
|
@ -239,12 +239,12 @@ https://oauth.vk.com/blank.html#access_token=df89482ba9a19e5a2dee85031612b021a08
|
||||||
- Matrix -> Вконтакте (как пользователь)
|
- Matrix -> Вконтакте (как пользователь)
|
||||||
- [x] Текстовые сообщения
|
- [x] Текстовые сообщения
|
||||||
- [x] Изображения
|
- [x] Изображения
|
||||||
- [x] Аудио и видео
|
- [x] Аудио сообщения
|
||||||
- [x] Прочие файлы
|
- [x] Прочие файлы
|
||||||
- [x] Ответы
|
- [x] Ответы
|
||||||
- [x] Индикатор печати
|
- [x] Индикатор печати
|
||||||
- [ ] Индикатор "в сети"
|
- [ ] Индикатор "в сети"
|
||||||
- [ ] Индикаторы прочтения
|
- [x] Индикаторы прочтения
|
||||||
- [x] Редактирование сообщений
|
- [x] Редактирование сообщений
|
||||||
- [x] Удаление сообщений - в течении 24 часов
|
- [x] Удаление сообщений - в течении 24 часов
|
||||||
- [ ] Инициация чатов со стороны Matrix
|
- [ ] Инициация чатов со стороны Matrix
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "mx-puppet-vk",
|
"name": "mx-puppet-vk",
|
||||||
"version": "0.6.0",
|
"version": "0.7.0",
|
||||||
"description": "Matrix <-> VK bridge based on mx-puppet-bridge and VK-IO.",
|
"description": "Matrix <-> VK bridge based on mx-puppet-bridge and VK-IO.",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|
|
@ -239,6 +239,12 @@ export class AttachmentsHandler {
|
||||||
case AttachmentType.LINK:
|
case AttachmentType.LINK:
|
||||||
formatted += `> 🔗 [ ${attachment["title"] ? attachment["title"] : attachment["url"]} ](${attachment["url"]})\n`;
|
formatted += `> 🔗 [ ${attachment["title"] ? attachment["title"] : attachment["url"]} ](${attachment["url"]})\n`;
|
||||||
break;
|
break;
|
||||||
|
case AttachmentType.WALL:
|
||||||
|
const wallpost = await vkPuppet.renderWallPost(puppetId, attachment);
|
||||||
|
formatted += wallpost.split("\n").forEach((element) => {
|
||||||
|
formatted += `> ${element}\n`;
|
||||||
|
});
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
formatted += `> ❓️ Unhandled attachment of type ${attachment.type}\n`;
|
formatted += `> ❓️ Unhandled attachment of type ${attachment.type}\n`;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -48,6 +48,7 @@ if (options.help) {
|
||||||
const protocol: IProtocolInformation = {
|
const protocol: IProtocolInformation = {
|
||||||
features: {
|
features: {
|
||||||
image: true,
|
image: true,
|
||||||
|
audio: true,
|
||||||
file: true,
|
file: true,
|
||||||
presence: true,
|
presence: true,
|
||||||
reply: true,
|
reply: true,
|
||||||
|
@ -93,9 +94,11 @@ async function run() {
|
||||||
puppet.on("redact", vk.handleMatrixRedact.bind(vk));
|
puppet.on("redact", vk.handleMatrixRedact.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("audio", vk.handleMatrixAudio.bind(vk));
|
||||||
puppet.on("file", vk.handleMatrixFile.bind(vk));
|
puppet.on("file", vk.handleMatrixFile.bind(vk));
|
||||||
|
|
||||||
puppet.on("typing", vk.handleMatrixTyping.bind(vk));
|
puppet.on("typing", vk.handleMatrixTyping.bind(vk));
|
||||||
|
puppet.on("read", vk.handleMatrixRead.bind(vk));
|
||||||
|
|
||||||
puppet.setCreateRoomHook(vk.createRoom.bind(vk));
|
puppet.setCreateRoomHook(vk.createRoom.bind(vk));
|
||||||
puppet.setGetUserIdsInRoomHook(vk.getUserIdsInRoom.bind(vk));
|
puppet.setGetUserIdsInRoomHook(vk.getUserIdsInRoom.bind(vk));
|
||||||
|
|
97
src/vk.ts
97
src/vk.ts
|
@ -418,6 +418,65 @@ export class VkPuppet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async handleMatrixAudio(
|
||||||
|
room: IRemoteRoom,
|
||||||
|
data: IFileEvent,
|
||||||
|
asUser: ISendingUser | null,
|
||||||
|
// tslint:disable-next-line: no-any
|
||||||
|
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 {
|
||||||
|
const attachment = await p.client.upload.audioMessage({
|
||||||
|
peer_id: Number(room.roomId),
|
||||||
|
source: {
|
||||||
|
value: data.url,
|
||||||
|
filename: data.filename,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const response = await p.client.api.messages.send({
|
||||||
|
peer_id: Number(room.roomId),
|
||||||
|
random_id: new Date().getTime(),
|
||||||
|
message: asUser ? `${asUser.displayname} sent an audio message:` : undefined,
|
||||||
|
attachment: [`doc${attachment.ownerId}_${attachment.id}`],
|
||||||
|
});
|
||||||
|
await this.puppet.eventSync.insert(room, data.eventId!, response.toString());
|
||||||
|
} catch (err) {
|
||||||
|
try {
|
||||||
|
const response = await p.client.api.messages.send({
|
||||||
|
peer_ids: Number(room.roomId),
|
||||||
|
message: `Audio message ${data.filename} was sent, but VK refused to recieve it. You may download it there:\n${data.url}`,
|
||||||
|
random_id: new Date().getTime(),
|
||||||
|
});
|
||||||
|
await this.puppet.eventSync.insert(room, data.eventId!,
|
||||||
|
p.data.isUserToken ? response[0]["message_id"].toString() : response[0]["conversation_message_id"].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_ids: 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!,
|
||||||
|
p.data.isUserToken ? response[0]["message_id"].toString() : response[0]["conversation_message_id"].toString());
|
||||||
|
} catch (err) {
|
||||||
|
log.error("Error sending to vk", err.error || err.body || err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public async handleMatrixFile(
|
public async handleMatrixFile(
|
||||||
room: IRemoteRoom,
|
room: IRemoteRoom,
|
||||||
data: IFileEvent,
|
data: IFileEvent,
|
||||||
|
@ -476,8 +535,6 @@ export class VkPuppet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Never called on my server for some reason, but
|
|
||||||
// if being called, should work
|
|
||||||
public async handleMatrixTyping(
|
public async handleMatrixTyping(
|
||||||
room: IRemoteRoom,
|
room: IRemoteRoom,
|
||||||
typing: boolean,
|
typing: boolean,
|
||||||
|
@ -500,6 +557,24 @@ export class VkPuppet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async handleMatrixRead(
|
||||||
|
room: IRemoteRoom,
|
||||||
|
eventId: string
|
||||||
|
) {
|
||||||
|
const p = this.puppets[room.puppetId];
|
||||||
|
if (!p) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const response = await p.client.api.messages.markAsRead({
|
||||||
|
peer_id: Number(room.roomId),
|
||||||
|
start_message_id: Number(eventId),
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
log.error("Error sending read event to vk", err.error || err.body || err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
@ -599,6 +674,7 @@ export class VkPuppet {
|
||||||
: context.attachments;
|
: context.attachments;
|
||||||
|
|
||||||
for (const f of attachments) {
|
for (const f of attachments) {
|
||||||
|
let rendered: string;
|
||||||
switch (f.type) {
|
switch (f.type) {
|
||||||
case AttachmentType.PHOTO:
|
case AttachmentType.PHOTO:
|
||||||
await attachmentHandler.handlePhotoAttachment(params, f);
|
await attachmentHandler.handlePhotoAttachment(params, f);
|
||||||
|
@ -627,14 +703,18 @@ export class VkPuppet {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AttachmentType.WALL:
|
case AttachmentType.WALL:
|
||||||
|
rendered = await this.renderWallPost(puppetId, f)
|
||||||
await this.puppet.sendMessage(params, {
|
await this.puppet.sendMessage(params, {
|
||||||
body: await this.renderWallPost(puppetId, f),
|
body: rendered,
|
||||||
|
formattedBody: this.converter.makeHtml(rendered),
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AttachmentType.WALL_REPLY:
|
case AttachmentType.WALL_REPLY:
|
||||||
|
rendered = await this.renderWallPost(puppetId, f)
|
||||||
await this.puppet.sendMessage(params, {
|
await this.puppet.sendMessage(params, {
|
||||||
body: await this.renderWallPost(puppetId, f),
|
body: rendered,
|
||||||
|
formattedBody: this.converter.makeHtml(rendered),
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -741,7 +821,7 @@ export class VkPuppet {
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderWallPostAsUser = async () => {
|
const renderWallPostAsUser = async () => {
|
||||||
const user = await this.getRemoteUser(puppetId, Number(post.fromId));
|
const user = await this.getRemoteUser(puppetId, Number(post.wall.ownerId));
|
||||||
let formatted = `Forwarded post from [${user.name}](${user.externalUrl})\n`;
|
let formatted = `Forwarded post from [${user.name}](${user.externalUrl})\n`;
|
||||||
post = post.wall;
|
post = post.wall;
|
||||||
post.text?.split("\n").forEach((element) => {
|
post.text?.split("\n").forEach((element) => {
|
||||||
|
@ -770,6 +850,13 @@ export class VkPuppet {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (post.copy_history !== undefined && post.copy_history !== 0) {
|
||||||
|
const subpost = await this.renderWallPost(puppetId, { wall: post.copy_history[0] })
|
||||||
|
subpost.split("\n").forEach((element) => {
|
||||||
|
formatted += `> ${element}\n`;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return formatted;
|
return formatted;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue