Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

mx-puppet-bridge

Package Overview
Dependencies
Maintainers
1
Versions
112
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mx-puppet-bridge - npm Package Compare versions

Comparing version 0.0.40 to 0.0.41

12

lib/src/interfaces.d.ts
/// <reference types="node" />
import { IStringFormatterVars } from "./structures/stringformatter";
import { MessageEvent, TextualMessageEventContent, FileMessageEventContent } from "@sorunome/matrix-bot-sdk";
declare type PuppetDataSingleType = string | number | boolean | IPuppetData | null | undefined;

@@ -73,2 +74,11 @@ export interface IPuppetData {

}
export interface IEventInfo {
message?: IMessageEvent;
file?: IFileEvent;
event: MessageEvent<TextualMessageEventContent> | MessageEvent<FileMessageEventContent>;
user: ISendingUser;
}
export interface IReplyEvent extends IMessageEvent {
reply: IEventInfo;
}
export interface IFileEvent {

@@ -84,2 +94,3 @@ filename: string;

url: string;
type: string;
eventId?: string;

@@ -118,2 +129,3 @@ }

mxid: string;
user: IRemoteUser | null;
}

@@ -120,0 +132,0 @@ export declare type CreateUserHook = (user: IRemoteUser) => Promise<IRemoteUser | null>;

import { PuppetBridge } from "./puppetbridge";
import { MatrixClient } from "@sorunome/matrix-bot-sdk";
import { IEventInfo } from "./interfaces";
export declare class MatrixEventHandler {

@@ -7,2 +9,3 @@ private bridge;

registerAppserviceEvents(): void;
getEventInfo(roomId: string, eventId: string, client?: MatrixClient | null, sender?: string): Promise<IEventInfo | null>;
private handleRoomEvent;

@@ -15,3 +18,5 @@ private handleJoinEvent;

private handleMessageEvent;
private getFileEventData;
private handleFileEvent;
private getMessageEventData;
private handleTextEvent;

@@ -18,0 +23,0 @@ private handleInviteEvent;

135

lib/src/matrixeventhandler.js

@@ -66,2 +66,41 @@ "use strict";

}
getEventInfo(roomId, eventId, client, sender) {
return __awaiter(this, void 0, void 0, function* () {
try {
if (!client) {
client = yield this.bridge.roomSync.getRoomOp(roomId);
}
if (!client) {
log.error(`Failed fetching event in room ${roomId}: no client`);
return null;
}
const rawEvent = yield client.getEvent(roomId, eventId);
if (!rawEvent) {
return null;
}
const evt = new matrix_bot_sdk_1.MessageEvent(rawEvent);
const info = {
user: (yield this.getSendingUser(true, roomId, evt.sender, sender)),
event: evt,
};
if (["m.file", "m.image", "m.audio", "m.sticker", "m.video"].includes(this.getMessageType(evt))) {
// file event
const replyEvent = new matrix_bot_sdk_1.MessageEvent(evt.raw);
info.event = replyEvent;
info.file = this.getFileEventData(replyEvent);
}
else {
// message event
const replyEvent = new matrix_bot_sdk_1.MessageEvent(evt.raw);
info.event = replyEvent;
info.message = this.getMessageEventData(replyEvent);
}
return info;
}
catch (err) {
log.error(`Event ${eventId} in room ${roomId} not found`, err.error || err.body || err);
return null;
}
});
}
handleRoomEvent(roomId, event) {

@@ -304,2 +343,27 @@ return __awaiter(this, void 0, void 0, function* () {

}
getFileEventData(event) {
const msgtype = this.getMessageType(event);
const content = event.content;
const url = this.bridge.getUrlFromMxc(content.url);
const data = {
filename: content.body || "",
mxc: content.url,
url,
eventId: event.eventId,
type: "file",
};
if (content.info) {
data.info = content.info;
}
data.type = {
"m.image": "image",
"m.audio": "audio",
"m.video": "video",
"m.sticker": "sticker",
}[msgtype];
if (!data.type) {
data.type = "file";
}
return data;
}
handleFileEvent(roomId, room, puppetData, event) {

@@ -309,22 +373,4 @@ return __awaiter(this, void 0, void 0, function* () {

log.info(`Handling file event with msgtype ${msgtype}...`);
const content = event.content;
const url = this.bridge.getUrlFromMxc(content.url);
const data = {
filename: content.body,
mxc: content.url,
url,
eventId: event.eventId,
};
if (content.info) {
data.info = content.info;
}
let emitEvent = {
"m.image": "image",
"m.audio": "audio",
"m.video": "video",
"m.sticker": "sticker",
}[msgtype];
if (!emitEvent) {
emitEvent = "file";
}
const data = this.getFileEventData(event);
const emitEvent = data.type;
const asUser = yield this.getSendingUser(puppetData, roomId, event.sender);

@@ -359,2 +405,16 @@ // alright, now determine fallbacks etc.

}
getMessageEventData(event) {
const msgtype = this.getMessageType(event);
const content = event.content;
const msgData = {
body: content.body || "",
emote: msgtype === "m.emote",
notice: msgtype === "m.notice",
eventId: event.eventId,
};
if (content.format) {
msgData.formattedBody = content.formatted_body;
}
return msgData;
}
handleTextEvent(roomId, room, puppetData, event) {

@@ -364,12 +424,3 @@ return __awaiter(this, void 0, void 0, function* () {

log.info(`Handling text event with msgtype ${msgtype}...`);
const content = event.content;
const msgData = {
body: content.body || "",
emote: msgtype === "m.emote",
notice: msgtype === "m.notice",
eventId: event.eventId,
};
if (content.format) {
msgData.formattedBody = content.formatted_body;
}
const msgData = this.getMessageEventData(event);
const relate = event.content["m.relates_to"]; // there is no relates_to interface yet :[

@@ -398,5 +449,12 @@ const asUser = yield this.getSendingUser(puppetData, roomId, event.sender);

if (this.bridge.protocol.features.reply && (relate.rel_type === "m.in_reply_to" || relate["m.in_reply_to"])) {
log.debug("Emitting reply event...");
this.bridge.emit("reply", room, relEvent, msgData, asUser, event);
return;
// okay, let's try to fetch the original event
const info = yield this.getEventInfo(roomId, eventId, null, event.sender);
if (info) {
const replyData = Object.assign(msgData, {
reply: info,
});
log.debug("Emitting reply event...");
this.bridge.emit("reply", room, relEvent, replyData, asUser, event);
return;
}
}

@@ -598,8 +656,13 @@ if (relate.rel_type === "m.annotation") {

}
getSendingUser(puppetData, roomId, userId) {
getSendingUser(puppetData, roomId, userId, sender) {
return __awaiter(this, void 0, void 0, function* () {
if (puppetData.type !== "relay") {
if (!puppetData || (typeof puppetData !== "boolean" && puppetData.type !== "relay")) {
return null;
}
const membership = yield this.getRoomMemberInfo(roomId, userId);
let user = null;
try {
user = yield this.getUserParts(userId, sender || userId);
}
catch (_a) { } // ignore error
if (!membership) {

@@ -611,2 +674,3 @@ return {

avatarUrl: null,
user,
};

@@ -625,2 +689,3 @@ }

avatarUrl,
user,
};

@@ -627,0 +692,0 @@ });

@@ -24,3 +24,3 @@ /// <reference types="node" />

import { DelayedFunction } from "./structures/delayedfunction";
import { IPuppetBridgeRegOpts, IPuppetBridgeFeatures, IReceiveParams, IMessageEvent, IProtocolInformation, CreateRoomHook, CreateUserHook, CreateGroupHook, GetDescHook, BotHeaderMsgHook, GetDataFromStrHook, GetDmRoomIdHook, ListUsersHook, ListRoomsHook, IRemoteUser, IRemoteRoom, IRemoteGroup, IPuppetData, GetUserIdsInRoomHook, UserExistsHook, RoomExistsHook, GroupExistsHook, ResolveRoomIdHook } from "./interfaces";
import { IPuppetBridgeRegOpts, IPuppetBridgeFeatures, IReceiveParams, IMessageEvent, IProtocolInformation, CreateRoomHook, CreateUserHook, CreateGroupHook, GetDescHook, BotHeaderMsgHook, GetDataFromStrHook, GetDmRoomIdHook, ListUsersHook, ListRoomsHook, IRemoteUser, IRemoteRoom, IRemoteGroup, IPuppetData, GetUserIdsInRoomHook, UserExistsHook, RoomExistsHook, GroupExistsHook, ResolveRoomIdHook, IEventInfo } from "./interfaces";
export interface IPuppetBridgeHooks {

@@ -255,3 +255,4 @@ createUser?: CreateUserHook;

redactEvent(client: MatrixClient, roomId: string, eventId: string): Promise<void>;
getEventInfo(roomId: string | IRemoteRoom, eventId: string, client?: MatrixClient): Promise<IEventInfo | null>;
}
export {};

@@ -772,3 +772,23 @@ "use strict";

}
getEventInfo(roomId, eventId, client) {
return __awaiter(this, void 0, void 0, function* () {
let sender;
if (typeof roomId !== "string") {
const maybeRoomId = yield this.roomSync.maybeGetMxid(roomId);
if (!maybeRoomId) {
return null;
}
if (roomId.puppetId !== -1) {
try {
sender = yield this.provisioner.getMxid(roomId.puppetId);
}
catch (_a) { }
}
eventId = (yield this.eventSync.getMatrix(roomId, eventId))[0];
roomId = maybeRoomId;
}
return this.matrixEventHandler.getEventInfo(roomId, eventId, client, sender);
});
}
}
exports.PuppetBridge = PuppetBridge;

@@ -27,2 +27,3 @@ "use strict";

const timedcache_1 = require("./structures/timedcache");
const escapeHtml = require("escape-html");
const log = new log_1.Log("RemoteEventHandler");

@@ -88,5 +89,5 @@ // tslint:disable no-magic-numbers

}
const origEvents = yield this.bridge.eventSync.getMatrix(params.room, params.eventId);
for (const origEvent of origEvents) {
yield ret.client.sendReadReceipt(ret.mxid, origEvent.split(";")[0]);
const origEventIdIds = yield this.bridge.eventSync.getMatrix(params.room, params.eventId);
for (const origEventId of origEventIdIds) {
yield ret.client.sendReadReceipt(ret.mxid, origEventId);
}

@@ -175,12 +176,12 @@ });

}
const origEvents = yield this.bridge.eventSync.getMatrix(params.room, eventId);
const origEventIdIds = yield this.bridge.eventSync.getMatrix(params.room, eventId);
if (ix < 0) {
// negative indexes are from the back
ix = origEvents.length + ix;
ix = origEventIdIds.length + ix;
}
if (ix >= origEvents.length) {
if (ix >= origEventIdIds.length) {
// sanity check on the index
ix = 0;
}
const origEvent = origEvents[ix];
const origEventId = origEventIdIds[ix];
// this object is set to any-type as the interfaces don't do edits yet

@@ -196,5 +197,5 @@ const send = {

}; // tslint:disable-line no-any
if (origEvent) {
if (origEventId) {
send["m.relates_to"] = {
event_id: origEvent.split(";")[0],
event_id: origEventId,
rel_type: "m.replace",

@@ -231,5 +232,5 @@ };

const { client, mxid } = yield this.prepareSend(params);
const origEvents = yield this.bridge.eventSync.getMatrix(params.room, eventId);
for (const origEvent of origEvents) {
yield this.bridge.redactEvent(client, mxid, origEvent.split(";")[0]);
const origEventIdIds = yield this.bridge.eventSync.getMatrix(params.room, eventId);
for (const origEventId of origEventIdIds) {
yield this.bridge.redactEvent(client, mxid, origEventId);
}

@@ -252,4 +253,4 @@ });

}
const origEvents = yield this.bridge.eventSync.getMatrix(params.room, eventId);
const origEvent = origEvents[0];
const origEventIds = yield this.bridge.eventSync.getMatrix(params.room, eventId);
const origEventId = origEventIds[0];
// this send object needs to be any-type, as the interfaces don't do replies yet

@@ -259,10 +260,57 @@ const send = {

body: opts.body,
format: "org.matrix.custom.html",
formatted_body: opts.formattedBody ? opts.formattedBody : escapeHtml(opts.body).replace(/\n/g, "<br>"),
source: this.bridge.protocol.id,
}; // tslint:disable-line no-any
if (origEvent) {
if (opts.formattedBody) {
send.format = "org.matrix.custom.html";
send.formatted_body = opts.formattedBody;
}
if (origEventId) {
send["m.relates_to"] = {
"m.in_reply_to": {
event_id: origEvent.split(";")[0],
event_id: origEventId,
},
};
try {
const info = yield this.bridge.getEventInfo(mxid, origEventId, client);
if (info) {
if (info.message) {
if (!info.message.formattedBody) {
info.message.formattedBody = escapeHtml(info.message.body).replace(/\n/g, "<br>");
}
const bodyParts = info.message.body.split("\n");
bodyParts[0] = `${info.message.emote ? "* " : ""}<${info.user.mxid}> ${bodyParts[0]}`;
send.body = `${bodyParts.map((l) => `> ${l}`).join("\n")}\n\n${send.body}`;
const richHeader = `<mx-reply><blockquote>
<a href="https://matrix.to/#/${mxid}/${origEventId}">In reply to</a>
${info.message.emote ? "* " : ""}<a href="https://matrix.to/#/${info.user.mxid}">${info.user.mxid}</a>
<br>${info.message.formattedBody}
</blockquote></mx-reply>`;
send.formatted_body = richHeader + send.formatted_body;
}
else if (info.file) {
let msg = {
image: "an image",
audio: "an audio file",
video: "a video",
sticker: "a sticker",
}[info.file.type];
if (!msg) {
msg = "a file";
}
const plainHeader = `> <${info.user.mxid}> sent ${msg}.\n\n`;
send.body = plainHeader + send.body;
const richHeader = `<mx-reply><blockquote>
<a href="https://matrix.to/#/${mxid}/${origEventId}">In reply to</a>
<a href="https://matrix.to/#/${info.user.mxid}">${info.user.mxid}</a>
<br>sent ${msg}.
</blockquote></mx-reply>`;
send.formatted_body = richHeader + send.formatted_body;
}
}
}
catch (err) {
log.warn("Failed to add reply fallback", err.error || err.body || err);
}
}

@@ -272,6 +320,2 @@ else {

}
if (opts.formattedBody) {
send.format = "org.matrix.custom.html";
send.formatted_body = opts.formattedBody;
}
if (params.externalUrl) {

@@ -278,0 +322,0 @@ send.external_url = params.externalUrl;

{
"name": "mx-puppet-bridge",
"version": "0.0.40",
"version": "0.0.41",
"description": "Matrix Puppeting Bridge library",

@@ -24,7 +24,8 @@ "repository": {

"@sorunome/matrix-bot-sdk": "^0.5.3-2",
"got": "^10.7.0",
"better-sqlite3": "^6.0.1",
"escape-html": "^1.0.3",
"events": "^3.1.0",
"expire-set": "^1.0.0",
"file-type": "^12.4.2",
"got": "^10.7.0",
"hasha": "^5.2.0",

@@ -31,0 +32,0 @@ "js-yaml": "^3.13.1",

@@ -56,3 +56,4 @@ /*

const result: string[] = [];
const rows = await this.db.All("SELECT * FROM event_store WHERE puppet_id = $p AND room_id = $room AND matrix_id = $m", {
const rows = await this.db.All(
"SELECT * FROM event_store WHERE puppet_id = $p AND room_id = $room AND matrix_id = $m", {
p: puppetId,

@@ -59,0 +60,0 @@ room: roomId,

@@ -15,2 +15,5 @@ /*

import { IStringFormatterVars } from "./structures/stringformatter";
import {
MessageEvent, TextualMessageEventContent, FileMessageEventContent,
} from "@sorunome/matrix-bot-sdk";

@@ -112,2 +115,13 @@ type PuppetDataSingleType = string | number | boolean | IPuppetData | null | undefined;

export interface IEventInfo {
message?: IMessageEvent;
file?: IFileEvent;
event: MessageEvent<TextualMessageEventContent> | MessageEvent<FileMessageEventContent>;
user: ISendingUser;
}
export interface IReplyEvent extends IMessageEvent {
reply: IEventInfo;
}
export interface IFileEvent {

@@ -123,2 +137,3 @@ filename: string;

url: string;
type: string;
eventId?: string;

@@ -163,2 +178,3 @@ }

mxid: string;
user: IRemoteUser | null;
}

@@ -165,0 +181,0 @@

@@ -18,5 +18,7 @@ /*

MembershipEvent, RedactionEvent, RoomEvent, MessageEvent, FileMessageEventContent, TextualMessageEventContent,
MembershipEventContent, RoomEventContent, MessageEventContent,
MembershipEventContent, RoomEventContent, MessageEventContent, MatrixClient,
} from "@sorunome/matrix-bot-sdk";
import { IFileEvent, IMessageEvent, IRemoteRoom, ISendingUser, IRemoteUser } from "./interfaces";
import {
IFileEvent, IMessageEvent, IRemoteRoom, ISendingUser, IRemoteUser, IReplyEvent, IEventInfo,
} from "./interfaces";
import * as escapeHtml from "escape-html";

@@ -68,2 +70,44 @@ import { IPuppet } from "./db/puppetstore";

public async getEventInfo(
roomId: string,
eventId: string,
client?: MatrixClient | null,
sender?: string,
): Promise<IEventInfo | null> {
try {
if (!client) {
client = await this.bridge.roomSync.getRoomOp(roomId);
}
if (!client) {
log.error(`Failed fetching event in room ${roomId}: no client`);
return null;
}
const rawEvent = await client.getEvent(roomId, eventId);
if (!rawEvent) {
return null;
}
const evt = new MessageEvent<MessageEventContent>(rawEvent);
const info: IEventInfo = {
user: (await this.getSendingUser(true, roomId, evt.sender, sender))!,
event: evt,
};
if (["m.file", "m.image", "m.audio", "m.sticker", "m.video"].includes(this.getMessageType(evt))) {
// file event
const replyEvent = new MessageEvent<FileMessageEventContent>(evt.raw);
info.event = replyEvent;
info.file = this.getFileEventData(replyEvent);
} else {
// message event
const replyEvent = new MessageEvent<TextualMessageEventContent>(evt.raw);
info.event = replyEvent;
info.message = this.getMessageEventData(replyEvent);
}
return info;
} catch (err) {
log.error(`Event ${eventId} in room ${roomId} not found`, err.error || err.body || err);
return null;
}
}
private async handleRoomEvent(roomId: string, event: RoomEvent<RoomEventContent>) {

@@ -304,17 +348,12 @@ if (event.type === "m.room.member") {

private async handleFileEvent(
roomId: string,
room: IRemoteRoom,
puppetData: IPuppet,
event: MessageEvent<FileMessageEventContent>,
) {
private getFileEventData(event: MessageEvent<FileMessageEventContent>): IFileEvent {
const msgtype = this.getMessageType(event);
log.info(`Handling file event with msgtype ${msgtype}...`);
const content = event.content;
const url = this.bridge.getUrlFromMxc(content.url);
const data: IFileEvent = {
filename: content.body,
filename: content.body || "",
mxc: content.url,
url,
eventId: event.eventId,
type: "file",
};

@@ -324,3 +363,3 @@ if (content.info) {

}
let emitEvent = {
data.type = {
"m.image": "image",

@@ -331,5 +370,18 @@ "m.audio": "audio",

}[msgtype];
if (!emitEvent) {
emitEvent = "file";
if (!data.type) {
data.type = "file";
}
return data;
}
private async handleFileEvent(
roomId: string,
room: IRemoteRoom,
puppetData: IPuppet,
event: MessageEvent<FileMessageEventContent>,
) {
const msgtype = this.getMessageType(event);
log.info(`Handling file event with msgtype ${msgtype}...`);
const data = this.getFileEventData(event);
const emitEvent = data.type;
const asUser = await this.getSendingUser(puppetData, roomId, event.sender);

@@ -364,10 +416,4 @@ // alright, now determine fallbacks etc.

private async handleTextEvent(
roomId: string,
room: IRemoteRoom,
puppetData: IPuppet,
event: MessageEvent<TextualMessageEventContent>,
) {
private getMessageEventData(event: MessageEvent<TextualMessageEventContent>): IMessageEvent {
const msgtype = this.getMessageType(event);
log.info(`Handling text event with msgtype ${msgtype}...`);
const content = event.content;

@@ -383,2 +429,14 @@ const msgData: IMessageEvent = {

}
return msgData;
}
private async handleTextEvent(
roomId: string,
room: IRemoteRoom,
puppetData: IPuppet,
event: MessageEvent<TextualMessageEventContent>,
) {
const msgtype = this.getMessageType(event);
log.info(`Handling text event with msgtype ${msgtype}...`);
const msgData = this.getMessageEventData(event);
const relate = event.content["m.relates_to"]; // there is no relates_to interface yet :[

@@ -408,5 +466,12 @@ const asUser = await this.getSendingUser(puppetData, roomId, event.sender);

if (this.bridge.protocol.features.reply && (relate.rel_type === "m.in_reply_to" || relate["m.in_reply_to"])) {
log.debug("Emitting reply event...");
this.bridge.emit("reply", room, relEvent, msgData, asUser, event);
return;
// okay, let's try to fetch the original event
const info = await this.getEventInfo(roomId, eventId, null, event.sender);
if (info) {
const replyData: IReplyEvent = Object.assign(msgData, {
reply: info,
});
log.debug("Emitting reply event...");
this.bridge.emit("reply", room, relEvent, replyData, asUser, event);
return;
}
}

@@ -606,7 +671,16 @@ if (relate.rel_type === "m.annotation") {

private async getSendingUser(puppetData: IPuppet, roomId: string, userId: string): Promise<ISendingUser | null> {
if (puppetData.type !== "relay") {
private async getSendingUser(
puppetData: IPuppet | boolean,
roomId: string,
userId: string,
sender?: string,
): Promise<ISendingUser | null> {
if (!puppetData || (typeof puppetData !== "boolean" && puppetData.type !== "relay")) {
return null;
}
const membership = await this.getRoomMemberInfo(roomId, userId);
let user: IRemoteUser | null = null;
try {
user = await this.getUserParts(userId, sender || userId);
} catch {} // ignore error
if (!membership) {

@@ -618,2 +692,3 @@ return {

avatarUrl: null,
user,
};

@@ -632,2 +707,3 @@ }

avatarUrl,
user,
};

@@ -634,0 +710,0 @@ }

@@ -57,2 +57,3 @@ /*

IRemoteGroup, IPuppetData, GetUserIdsInRoomHook, UserExistsHook, RoomExistsHook, GroupExistsHook, ResolveRoomIdHook,
IEventInfo,
} from "./interfaces";

@@ -834,2 +835,24 @@

}
public async getEventInfo(
roomId: string | IRemoteRoom,
eventId: string,
client?: MatrixClient,
): Promise<IEventInfo | null> {
let sender: string | undefined;
if (typeof roomId !== "string") {
const maybeRoomId = await this.roomSync.maybeGetMxid(roomId);
if (!maybeRoomId) {
return null;
}
if (roomId.puppetId !== -1) {
try {
sender = await this.provisioner.getMxid(roomId.puppetId);
} catch {}
}
eventId = (await this.eventSync.getMatrix(roomId, eventId))[0];
roomId = maybeRoomId;
}
return this.matrixEventHandler.getEventInfo(roomId, eventId, client, sender);
}
}

@@ -22,4 +22,5 @@ /*

TextualMessageEventContent, FileMessageEventContent, FileWithThumbnailInfo, MatrixClient, DimensionalFileInfo,
VideoFileInfo, TimedFileInfo,
VideoFileInfo, TimedFileInfo, MessageEvent, MessageEventContent,
} from "@sorunome/matrix-bot-sdk";
import * as escapeHtml from "escape-html";

@@ -94,5 +95,5 @@ const log = new Log("RemoteEventHandler");

}
const origEvents = await this.bridge.eventSync.getMatrix(params.room, params.eventId);
for (const origEvent of origEvents) {
await ret.client.sendReadReceipt(ret.mxid, origEvent.split(";")[0]);
const origEventIdIds = await this.bridge.eventSync.getMatrix(params.room, params.eventId);
for (const origEventId of origEventIdIds) {
await ret.client.sendReadReceipt(ret.mxid, origEventId);
}

@@ -175,12 +176,12 @@ }

}
const origEvents = await this.bridge.eventSync.getMatrix(params.room, eventId);
const origEventIdIds = await this.bridge.eventSync.getMatrix(params.room, eventId);
if (ix < 0) {
// negative indexes are from the back
ix = origEvents.length + ix;
ix = origEventIdIds.length + ix;
}
if (ix >= origEvents.length) {
if (ix >= origEventIdIds.length) {
// sanity check on the index
ix = 0;
}
const origEvent = origEvents[ix];
const origEventId = origEventIdIds[ix];
// this object is set to any-type as the interfaces don't do edits yet

@@ -196,5 +197,5 @@ const send = {

} as any; // tslint:disable-line no-any
if (origEvent) {
if (origEventId) {
send["m.relates_to"] = {
event_id: origEvent.split(";")[0],
event_id: origEventId,
rel_type: "m.replace",

@@ -229,5 +230,5 @@ };

const { client, mxid } = await this.prepareSend(params);
const origEvents = await this.bridge.eventSync.getMatrix(params.room, eventId);
for (const origEvent of origEvents) {
await this.bridge.redactEvent(client, mxid, origEvent.split(";")[0]);
const origEventIdIds = await this.bridge.eventSync.getMatrix(params.room, eventId);
for (const origEventId of origEventIdIds) {
await this.bridge.redactEvent(client, mxid, origEventId);
}

@@ -248,4 +249,4 @@ }

}
const origEvents = await this.bridge.eventSync.getMatrix(params.room, eventId);
const origEvent = origEvents[0];
const origEventIds = await this.bridge.eventSync.getMatrix(params.room, eventId);
const origEventId = origEventIds[0];
// this send object needs to be any-type, as the interfaces don't do replies yet

@@ -255,17 +256,58 @@ const send = {

body: opts.body,
format: "org.matrix.custom.html",
formatted_body: opts.formattedBody ? opts.formattedBody : escapeHtml(opts.body).replace(/\n/g, "<br>"),
source: this.bridge.protocol.id,
} as any; // tslint:disable-line no-any
if (origEvent) {
if (opts.formattedBody) {
send.format = "org.matrix.custom.html";
send.formatted_body = opts.formattedBody;
}
if (origEventId) {
send["m.relates_to"] = {
"m.in_reply_to": {
event_id: origEvent.split(";")[0],
event_id: origEventId,
},
};
try {
const info = await this.bridge.getEventInfo(mxid, origEventId, client);
if (info) {
if (info.message) {
if (!info.message.formattedBody) {
info.message.formattedBody = escapeHtml(info.message.body).replace(/\n/g, "<br>");
}
const bodyParts = info.message.body.split("\n");
bodyParts[0] = `${info.message.emote ? "* " : ""}<${info.user.mxid}> ${bodyParts[0]}`;
send.body = `${bodyParts.map((l) => `> ${l}`).join("\n")}\n\n${send.body}`;
const richHeader = `<mx-reply><blockquote>
<a href="https://matrix.to/#/${mxid}/${origEventId}">In reply to</a>
${info.message.emote ? "* " : ""}<a href="https://matrix.to/#/${info.user.mxid}">${info.user.mxid}</a>
<br>${info.message.formattedBody}
</blockquote></mx-reply>`;
send.formatted_body = richHeader + send.formatted_body;
} else if (info.file) {
let msg = {
image: "an image",
audio: "an audio file",
video: "a video",
sticker: "a sticker",
}[info.file.type];
if (!msg) {
msg = "a file";
}
const plainHeader = `> <${info.user.mxid}> sent ${msg}.\n\n`;
send.body = plainHeader + send.body;
const richHeader = `<mx-reply><blockquote>
<a href="https://matrix.to/#/${mxid}/${origEventId}">In reply to</a>
<a href="https://matrix.to/#/${info.user.mxid}">${info.user.mxid}</a>
<br>sent ${msg}.
</blockquote></mx-reply>`;
send.formatted_body = richHeader + send.formatted_body;
}
}
} catch (err) {
log.warn("Failed to add reply fallback", err.error || err.body || err);
}
} else {
log.warn("Couldn't find event, sending as normal message...");
}
if (opts.formattedBody) {
send.format = "org.matrix.custom.html";
send.formatted_body = opts.formattedBody;
}
if (params.externalUrl) {

@@ -272,0 +314,0 @@ send.external_url = params.externalUrl;

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc