mirror of
https://github.com/Skylar-Tech/node-red-contrib-matrix-chat.git
synced 2025-04-20 13:03:12 -06:00
Fix module compatibility with Node.js < 22
This commit is contained in:
parent
ad34f018ab
commit
8cb52112c1
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "node-red-contrib-matrix-chat",
|
"name": "node-red-contrib-matrix-chat",
|
||||||
"version": "0.9.0",
|
"version": "0.9.1",
|
||||||
"description": "Matrix chat server client for Node-RED",
|
"description": "Matrix chat server client for Node-RED",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"abort-controller": "^3.0.0",
|
"abort-controller": "^3.0.0",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
const {RelationType, EventType, Direction} = require("matrix-js-sdk");
|
const sdkPromise = import("matrix-js-sdk");
|
||||||
|
|
||||||
module.exports = function(RED) {
|
module.exports = function(RED) {
|
||||||
function MatrixFetchRelations(n) {
|
function MatrixFetchRelations(n) {
|
||||||
@ -49,14 +49,17 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const sdk = await sdkPromise;
|
||||||
|
const Direction = sdk.Direction;
|
||||||
|
|
||||||
function evaluateNodePropertySafe(value, type, node, msg) {
|
function evaluateNodePropertySafe(value, type, node, msg) {
|
||||||
try {
|
try {
|
||||||
return RED.util.evaluateNodeProperty(value, type, node, msg);
|
return RED.util.evaluateNodeProperty(value, type, node, msg);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof TypeError) {
|
if (e instanceof TypeError) {
|
||||||
return undefined; // Handle TypeError and return undefined
|
return undefined;
|
||||||
}
|
}
|
||||||
throw e; // Re-throw other errors to prevent masking issues
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,16 +74,16 @@ module.exports = function(RED) {
|
|||||||
to = evaluateNodePropertySafe(node.toValue, node.toType, node, msg);
|
to = evaluateNodePropertySafe(node.toValue, node.toType, node, msg);
|
||||||
|
|
||||||
let opts = { dir: direction };
|
let opts = { dir: direction };
|
||||||
if(limit) {
|
if (limit) {
|
||||||
opts.limit = limit;
|
opts.limit = limit;
|
||||||
}
|
}
|
||||||
if(recurse === true || recurse === false) {
|
if (recurse === true || recurse === false) {
|
||||||
opts.recurse = recurse;
|
opts.recurse = recurse;
|
||||||
}
|
}
|
||||||
if(from) {
|
if (from) {
|
||||||
opts.from = from;
|
opts.from = from;
|
||||||
}
|
}
|
||||||
if(to) {
|
if (to) {
|
||||||
opts.to = to;
|
opts.to = to;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
const {TimelineWindow, RelationType, Filter} = require("matrix-js-sdk");
|
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
module.exports = function(RED) {
|
|
||||||
function MatrixReceiveMessage(n) {
|
|
||||||
RED.nodes.createNode(this, n);
|
|
||||||
|
|
||||||
|
module.exports = function(RED) {
|
||||||
|
function MatrixMarkRead(n) {
|
||||||
|
RED.nodes.createNode(this, n);
|
||||||
let node = this;
|
let node = this;
|
||||||
this.name = n.name;
|
this.name = n.name;
|
||||||
this.server = RED.nodes.getNode(n.server);
|
this.server = RED.nodes.getNode(n.server);
|
||||||
@ -29,7 +28,7 @@ module.exports = function(RED) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
node.on("input", async function (msg) {
|
node.on("input", async function (msg) {
|
||||||
if (! node.server || ! node.server.matrixClient) {
|
if (!node.server || !node.server.matrixClient) {
|
||||||
node.error("No matrix server selected", msg);
|
node.error("No matrix server selected", msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -38,15 +37,15 @@ module.exports = function(RED) {
|
|||||||
let value = property;
|
let value = property;
|
||||||
if (type === "msg") {
|
if (type === "msg") {
|
||||||
value = RED.util.getMessageProperty(msg, property);
|
value = RED.util.getMessageProperty(msg, property);
|
||||||
} else if ((type === 'flow') || (type === 'global')) {
|
} else if (type === 'flow' || type === 'global') {
|
||||||
try {
|
try {
|
||||||
value = RED.util.evaluateNodeProperty(property, type, node, msg);
|
value = RED.util.evaluateNodeProperty(property, type, node, msg);
|
||||||
} catch(e2) {
|
} catch (e2) {
|
||||||
throw new Error("Invalid value evaluation");
|
throw new Error("Invalid value evaluation");
|
||||||
}
|
}
|
||||||
} else if(type === "bool") {
|
} else if (type === "bool") {
|
||||||
value = (property === 'true');
|
value = (property === 'true');
|
||||||
} else if(type === "num") {
|
} else if (type === "num") {
|
||||||
value = Number(property);
|
value = Number(property);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
@ -66,9 +65,9 @@ module.exports = function(RED) {
|
|||||||
throw new Error(`Event ${eventId} not found in room ${roomId}.`);
|
throw new Error(`Event ${eventId} not found in room ${roomId}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
await node.server.matrixClient.sendReceipt(event, "m.read")
|
await node.server.matrixClient.sendReceipt(event, "m.read");
|
||||||
node.send([msg, null]);
|
node.send([msg, null]);
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
msg.error = `Room pagination error: ${e}`;
|
msg.error = `Room pagination error: ${e}`;
|
||||||
node.error(msg.error, msg);
|
node.error(msg.error, msg);
|
||||||
node.send([null, msg]);
|
node.send([null, msg]);
|
||||||
@ -79,5 +78,5 @@ module.exports = function(RED) {
|
|||||||
node.server.deregister(node);
|
node.server.deregister(node);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
RED.nodes.registerType("matrix-mark-read", MatrixReceiveMessage);
|
RED.nodes.registerType("matrix-mark-read", MatrixMarkRead);
|
||||||
}
|
}
|
@ -1,7 +1,8 @@
|
|||||||
const {TimelineWindow, RelationType, Filter} = require("matrix-js-sdk");
|
const sdkPromise = import("matrix-js-sdk");
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
|
|
||||||
module.exports = function(RED) {
|
module.exports = function(RED) {
|
||||||
function MatrixReceiveMessage(n) {
|
function MatrixPaginateRoom(n) {
|
||||||
RED.nodes.createNode(this, n);
|
RED.nodes.createNode(this, n);
|
||||||
|
|
||||||
let node = this;
|
let node = this;
|
||||||
@ -34,7 +35,7 @@ module.exports = function(RED) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
node.on("input", async function (msg) {
|
node.on("input", async function (msg) {
|
||||||
if (! node.server || ! node.server.matrixClient) {
|
if (!node.server || !node.server.matrixClient) {
|
||||||
node.error("No matrix server selected", msg);
|
node.error("No matrix server selected", msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -43,43 +44,47 @@ module.exports = function(RED) {
|
|||||||
let value = property;
|
let value = property;
|
||||||
if (type === "msg") {
|
if (type === "msg") {
|
||||||
value = RED.util.getMessageProperty(msg, property);
|
value = RED.util.getMessageProperty(msg, property);
|
||||||
} else if ((type === 'flow') || (type === 'global')) {
|
} else if (type === 'flow' || type === 'global') {
|
||||||
try {
|
try {
|
||||||
value = RED.util.evaluateNodeProperty(property, type, node, msg);
|
value = RED.util.evaluateNodeProperty(property, type, node, msg);
|
||||||
} catch(e2) {
|
} catch(e2) {
|
||||||
throw new Error("Invalid value evaluation");
|
throw new Error("Invalid value evaluation");
|
||||||
}
|
}
|
||||||
} else if(type === "bool") {
|
} else if (type === "bool") {
|
||||||
value = (property === 'true');
|
value = (property === 'true');
|
||||||
} else if(type === "num") {
|
} else if (type === "num") {
|
||||||
value = Number(property);
|
value = Number(property);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setToValue(value, type, property) {
|
function setToValue(value, type, property) {
|
||||||
if(type === 'global' || type === 'flow') {
|
if (type === 'global' || type === 'flow') {
|
||||||
var contextKey = RED.util.parseContextStore(property);
|
var contextKey = RED.util.parseContextStore(property);
|
||||||
if (/\[msg/.test(contextKey.key)) {
|
if (/\[msg/.test(contextKey.key)) {
|
||||||
// The key has a nest msg. reference to evaluate first
|
// The key has a nested msg. reference that must be evaluated first
|
||||||
contextKey.key = RED.util.normalisePropertyExpression(contextKey.key, msg, true)
|
contextKey.key = RED.util.normalisePropertyExpression(contextKey.key, msg, true);
|
||||||
}
|
}
|
||||||
var target = node.context()[type];
|
var target = node.context()[type];
|
||||||
var callback = err => {
|
target.set(contextKey.key, value, contextKey.store, err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
node.error(err, msg);
|
node.error(err, msg);
|
||||||
getterErrors[rule.p] = err.message;
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
target.set(contextKey.key, value, contextKey.store, callback);
|
} else if (type === 'msg') {
|
||||||
} else if(type === 'msg') {
|
|
||||||
if (!RED.util.setMessageProperty(msg, property, value)) {
|
if (!RED.util.setMessageProperty(msg, property, value)) {
|
||||||
node.warn(RED._("change.errors.no-override",{property:property}));
|
node.warn(RED._("change.errors.no-override", { property: property }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Dynamically load the SDK
|
||||||
|
const sdk = await sdkPromise;
|
||||||
|
const TimelineWindow = sdk.TimelineWindow;
|
||||||
|
const RelationType = sdk.RelationType;
|
||||||
|
// (Filter was imported originally but is not used, so we omit it.)
|
||||||
|
|
||||||
let roomId = getToValue(msg, node.roomType, node.roomValue),
|
let roomId = getToValue(msg, node.roomType, node.roomValue),
|
||||||
paginateBackwards = getToValue(msg, node.paginateBackwardsType, node.paginateBackwardsValue),
|
paginateBackwards = getToValue(msg, node.paginateBackwardsType, node.paginateBackwardsValue),
|
||||||
pageSize = getToValue(msg, node.pageSizeType, node.pageSizeValue),
|
pageSize = getToValue(msg, node.pageSizeType, node.pageSizeValue),
|
||||||
@ -87,42 +92,37 @@ module.exports = function(RED) {
|
|||||||
|
|
||||||
let room = node.server.matrixClient.getRoom(roomId);
|
let room = node.server.matrixClient.getRoom(roomId);
|
||||||
|
|
||||||
if(!room) {
|
if (!room) {
|
||||||
throw new Error(`Room ${roomId} does not exist`);
|
throw new Error(`Room ${roomId} does not exist`);
|
||||||
}
|
}
|
||||||
if(pageSize > node.server.initialSyncLimit) {
|
if (pageSize > node.server.initialSyncLimit) {
|
||||||
throw new Error(`Page size=${pageSize} cannot exceed initialSyncLimit=${node.server.initialSyncLimit}`);
|
throw new Error(`Page size=${pageSize} cannot exceed initialSyncLimit=${node.server.initialSyncLimit}`);
|
||||||
}
|
}
|
||||||
if(!pageKey) {
|
if (!pageKey) {
|
||||||
pageKey = crypto.randomUUID();
|
pageKey = crypto.randomUUID();
|
||||||
setToValue(pageKey, node.paginateKeyType, node.paginateKeyValue);
|
setToValue(pageKey, node.paginateKeyType, node.paginateKeyValue);
|
||||||
}
|
}
|
||||||
let timelineWindow = node.timelineWindows.get(pageKey),
|
let timelineWindow = node.timelineWindows.get(pageKey),
|
||||||
moreMessages = true;
|
moreMessages = true;
|
||||||
if(!timelineWindow) {
|
if (!timelineWindow) {
|
||||||
let timelineSet = room.getUnfilteredTimelineSet();
|
let timelineSet = room.getUnfilteredTimelineSet();
|
||||||
// node.debug(JSON.stringify(timelineSet.getFilter()));
|
// MatrixClient's option initialSyncLimit gets set to the filter we are using,
|
||||||
|
// so override that value with our pageSize.
|
||||||
// MatrixClient's option initialSyncLimit gets set to the filter we are using
|
|
||||||
// so override that value with our pageSize
|
|
||||||
timelineWindow = new TimelineWindow(node.server.matrixClient, timelineSet);
|
timelineWindow = new TimelineWindow(node.server.matrixClient, timelineSet);
|
||||||
await timelineWindow.load(msg.eventId || null, pageSize);
|
await timelineWindow.load(msg.eventId || null, pageSize);
|
||||||
node.timelineWindows.set(pageKey, timelineWindow);
|
node.timelineWindows.set(pageKey, timelineWindow);
|
||||||
} else {
|
} else {
|
||||||
moreMessages = await timelineWindow.paginate(paginateBackwards ? 'b' : 'f', pageSize); // b for backwards f for forwards
|
moreMessages = await timelineWindow.paginate(paginateBackwards ? 'b' : 'f', pageSize); // 'b' for backwards, 'f' for forwards
|
||||||
if(moreMessages) {
|
if (moreMessages) {
|
||||||
await timelineWindow.unpaginate(pageSize, !paginateBackwards);
|
await timelineWindow.unpaginate(pageSize, !paginateBackwards);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MatrixEvent objects are massive so this throws an encode error for the string being too long
|
// To avoid errors converting massive MatrixEvent objects to JSON, we omit them.
|
||||||
// since msg objects convert to JSON
|
|
||||||
// msg.payload = moreMessages ? timelineWindow.getEvents() : false;
|
|
||||||
|
|
||||||
msg.payload = false;
|
msg.payload = false;
|
||||||
msg.start = timelineWindow.getTimelineIndex('b')?.index;
|
msg.start = timelineWindow.getTimelineIndex('b')?.index;
|
||||||
msg.end = timelineWindow.getTimelineIndex('f')?.index;
|
msg.end = timelineWindow.getTimelineIndex('f')?.index;
|
||||||
if(moreMessages) {
|
if (moreMessages) {
|
||||||
msg.payload = timelineWindow.getEvents().map(function(event) {
|
msg.payload = timelineWindow.getEvents().map(function(event) {
|
||||||
return {
|
return {
|
||||||
encrypted : event.isEncrypted(),
|
encrypted : event.isEncrypted(),
|
||||||
@ -152,5 +152,5 @@ module.exports = function(RED) {
|
|||||||
node.server.deregister(node);
|
node.server.deregister(node);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
RED.nodes.registerType("matrix-paginate-room", MatrixReceiveMessage);
|
RED.nodes.registerType("matrix-paginate-room", MatrixPaginateRoom);
|
||||||
}
|
}
|
@ -1,4 +1,3 @@
|
|||||||
const {RelationType} = require("matrix-js-sdk");
|
|
||||||
module.exports = function(RED) {
|
module.exports = function(RED) {
|
||||||
function MatrixReceiveMessage(n) {
|
function MatrixReceiveMessage(n) {
|
||||||
RED.nodes.createNode(this, n);
|
RED.nodes.createNode(this, n);
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
const {RelationType} = require("matrix-js-sdk");
|
const sdkPromise = import("matrix-js-sdk");
|
||||||
|
|
||||||
module.exports = function(RED) {
|
module.exports = function(RED) {
|
||||||
function MatrixSendImage(n) {
|
function MatrixSendImage(n) {
|
||||||
RED.nodes.createNode(this, n);
|
RED.nodes.createNode(this, n);
|
||||||
|
|
||||||
var node = this;
|
var node = this;
|
||||||
|
|
||||||
this.name = n.name;
|
this.name = n.name;
|
||||||
@ -68,12 +67,17 @@ module.exports = function(RED) {
|
|||||||
node.status({ fill: "green", shape: "ring", text: "connected" });
|
node.status({ fill: "green", shape: "ring", text: "connected" });
|
||||||
});
|
});
|
||||||
|
|
||||||
node.on("input", function (msg) {
|
// Make the input handler async so we can await the dynamic import.
|
||||||
|
node.on("input", async function (msg) {
|
||||||
|
// Await the SDK import and get the RelationType constant.
|
||||||
|
const sdk = await sdkPromise;
|
||||||
|
const RelationType = sdk.RelationType;
|
||||||
|
|
||||||
function getToValue(msg, type, property) {
|
function getToValue(msg, type, property) {
|
||||||
let value = property;
|
let value = property;
|
||||||
if (type === "msg") {
|
if (type === "msg") {
|
||||||
value = RED.util.getMessageProperty(msg, property);
|
value = RED.util.getMessageProperty(msg, property);
|
||||||
} else if ((type === 'flow') || (type === 'global')) {
|
} else if (type === 'flow' || type === 'global') {
|
||||||
try {
|
try {
|
||||||
value = RED.util.evaluateNodeProperty(property, type, node, msg);
|
value = RED.util.evaluateNodeProperty(property, type, node, msg);
|
||||||
} catch(e2) {
|
} catch(e2) {
|
||||||
@ -115,19 +119,19 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let content = null;
|
let content = null;
|
||||||
if(typeof payload === 'object') {
|
if (typeof payload === 'object') {
|
||||||
content = payload;
|
content = payload;
|
||||||
} else {
|
} else {
|
||||||
if(msgType === 'msg.type') {
|
if (msgType === 'msg.type') {
|
||||||
if(!msg.type) {
|
if (!msg.type) {
|
||||||
node.error("msg.type type is set to be passed in via msg.type but was not defined", msg);
|
node.error("msg.type is set to be passed in via msg.type but was not defined", msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
msgType = msg.type;
|
msgType = msg.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(msgFormat === 'msg.format') {
|
if (msgFormat === 'msg.format') {
|
||||||
if(!Object.hasOwn(msg, 'format')) {
|
if (!Object.hasOwn(msg, 'format')) {
|
||||||
node.error("Message format is set to be passed in via msg.format but was not defined", msg);
|
node.error("Message format is set to be passed in via msg.format but was not defined", msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -139,7 +143,7 @@ module.exports = function(RED) {
|
|||||||
body: payload.toString()
|
body: payload.toString()
|
||||||
};
|
};
|
||||||
|
|
||||||
if(msgFormat === 'html') {
|
if (msgFormat === 'html') {
|
||||||
content.format = "org.matrix.custom.html";
|
content.format = "org.matrix.custom.html";
|
||||||
content.formatted_body =
|
content.formatted_body =
|
||||||
(typeof msg.formatted_payload !== 'undefined' && msg.formatted_payload)
|
(typeof msg.formatted_payload !== 'undefined' && msg.formatted_payload)
|
||||||
@ -147,15 +151,15 @@ module.exports = function(RED) {
|
|||||||
: payload.toString();
|
: payload.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if((node.replaceMessage || msg.replace) && msg.eventId) {
|
if ((node.replaceMessage || msg.replace) && msg.eventId) {
|
||||||
content['m.new_content'] = {
|
content['m.new_content'] = {
|
||||||
msgtype: content.msgtype,
|
msgtype: content.msgtype,
|
||||||
body: content.body
|
body: content.body
|
||||||
};
|
};
|
||||||
if('format' in content) {
|
if ('format' in content) {
|
||||||
content['m.new_content']['format'] = content['format'];
|
content['m.new_content']['format'] = content['format'];
|
||||||
}
|
}
|
||||||
if('formatted_body' in content) {
|
if ('formatted_body' in content) {
|
||||||
content['m.new_content']['formatted_body'] = content['formatted_body'];
|
content['m.new_content']['formatted_body'] = content['formatted_body'];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,17 +168,19 @@ module.exports = function(RED) {
|
|||||||
event_id: msg.eventId
|
event_id: msg.eventId
|
||||||
};
|
};
|
||||||
content['body'] = ' * ' + content['body'];
|
content['body'] = ' * ' + content['body'];
|
||||||
} else if(threadReply) {
|
} else if (threadReply) {
|
||||||
// if incoming message is a reply to a thread we fetch the thread parent from the m.relates_to property
|
// If incoming message is a reply to a thread we fetch the thread parent from m.relates_to,
|
||||||
// otherwise fallback to msg.eventId
|
// otherwise fallback to msg.eventId.
|
||||||
let threadParent = (msg?.content?.['m.relates_to']?.rel_type === RelationType.Thread ? msg?.content?.['m.relates_to']?.event_id : null) || msg.eventId;
|
let threadParent = (msg?.content?.['m.relates_to']?.rel_type === RelationType.Thread
|
||||||
if(threadParent) {
|
? msg?.content?.['m.relates_to']?.event_id
|
||||||
|
: null) || msg.eventId;
|
||||||
|
if (threadParent) {
|
||||||
content["m.relates_to"] = {
|
content["m.relates_to"] = {
|
||||||
"rel_type": RelationType.Thread,
|
"rel_type": RelationType.Thread,
|
||||||
"event_id": threadParent,
|
"event_id": threadParent,
|
||||||
"is_falling_back": true,
|
"is_falling_back": true,
|
||||||
};
|
};
|
||||||
if(msg.eventId !== threadParent) {
|
if (msg.eventId !== threadParent) {
|
||||||
content["m.relates_to"]["m.in_reply_to"] = {
|
content["m.relates_to"]["m.in_reply_to"] = {
|
||||||
"event_id": msg.eventId
|
"event_id": msg.eventId
|
||||||
};
|
};
|
||||||
@ -202,4 +208,4 @@ module.exports = function(RED) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
RED.nodes.registerType("matrix-send-message", MatrixSendImage);
|
RED.nodes.registerType("matrix-send-message", MatrixSendImage);
|
||||||
}
|
};
|
||||||
|
@ -1,32 +1,52 @@
|
|||||||
const {RelationType, TimelineWindow} = require("matrix-js-sdk");
|
|
||||||
|
|
||||||
global.Olm = require('olm');
|
global.Olm = require('olm');
|
||||||
const fs = require("fs-extra");
|
const fs = require("fs-extra");
|
||||||
const sdk = require("matrix-js-sdk");
|
let RelationType, TimelineWindow, sdk, LocalStorageCryptoStore, RoomEvent, RoomMemberEvent, HttpApiEvent, ClientEvent, MemoryStore;
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const mod = await import("matrix-js-sdk");
|
||||||
|
RelationType = mod.RelationType;
|
||||||
|
TimelineWindow = mod.TimelineWindow;
|
||||||
|
// matrix-js-sdk doesn't export a default – the top-level export is the same object:
|
||||||
|
sdk = mod;
|
||||||
|
|
||||||
|
RoomEvent = mod.RoomEvent;
|
||||||
|
RoomMemberEvent = mod.RoomMemberEvent;
|
||||||
|
HttpApiEvent = mod.HttpApiEvent;
|
||||||
|
ClientEvent = mod.ClientEvent;
|
||||||
|
MemoryStore = mod.MemoryStore;
|
||||||
|
|
||||||
|
// For LocalStorageCryptoStore, specify the file extension for Node 20+:
|
||||||
|
const cmod = await import("matrix-js-sdk/lib/crypto/store/localStorage-crypto-store.js");
|
||||||
|
LocalStorageCryptoStore = cmod.LocalStorageCryptoStore;
|
||||||
|
})();
|
||||||
|
|
||||||
const { resolve } = require('path');
|
const { resolve } = require('path');
|
||||||
const { LocalStorage } = require('node-localstorage');
|
const { LocalStorage } = require('node-localstorage');
|
||||||
const { LocalStorageCryptoStore } = require('matrix-js-sdk/lib/crypto/store/localStorage-crypto-store');
|
|
||||||
const {RoomEvent, RoomMemberEvent, HttpApiEvent, ClientEvent, MemoryStore} = require("matrix-js-sdk");
|
|
||||||
require("abort-controller/polyfill"); // polyfill abort-controller if we don't have it
|
require("abort-controller/polyfill"); // polyfill abort-controller if we don't have it
|
||||||
if (!globalThis.fetch) {
|
if (!globalThis.fetch) {
|
||||||
// polyfill fetch if we don't have it
|
// polyfill fetch if we don't have it
|
||||||
if (!globalThis.fetch) {
|
if (!globalThis.fetch) {
|
||||||
import('node-fetch').then(({ default: fetch, Headers, Request, Response }) => {
|
import('node-fetch').then(({ default: fetch, Headers, Request, Response }) => {
|
||||||
Object.assign(globalThis, { fetch, Headers, Request, Response })
|
Object.assign(globalThis, { fetch, Headers, Request, Response });
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = function(RED) {
|
module.exports = function(RED) {
|
||||||
// disable logging if set to "off"
|
// disable logging if set to "off"
|
||||||
let loggingSettings = RED.settings.get('logging');
|
let loggingSettings = RED.settings.get('logging');
|
||||||
if(
|
if (
|
||||||
typeof loggingSettings.console !== 'undefined' &&
|
typeof loggingSettings.console !== 'undefined' &&
|
||||||
typeof loggingSettings.console.level !== 'undefined' &&
|
typeof loggingSettings.console.level !== 'undefined' &&
|
||||||
['info','debug','trace'].indexOf(loggingSettings.console.level.toLowerCase()) >= 0
|
['info','debug','trace'].indexOf(loggingSettings.console.level.toLowerCase()) >= 0
|
||||||
) {
|
) {
|
||||||
const { logger } = require('matrix-js-sdk/lib/logger');
|
import('matrix-js-sdk/lib/logger.js')
|
||||||
|
.then(({ logger }) => {
|
||||||
logger.disableAll();
|
logger.disableAll();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error("Error loading logger module:", err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function MatrixFolderNameFromUserId(name) {
|
function MatrixFolderNameFromUserId(name) {
|
||||||
@ -59,7 +79,7 @@ module.exports = function(RED) {
|
|||||||
this.initializedAt = new Date();
|
this.initializedAt = new Date();
|
||||||
node.initialSyncLimit = 25;
|
node.initialSyncLimit = 25;
|
||||||
|
|
||||||
// Keep track of all consumers of this node to be able to catch errors
|
// Keep track of all consumers of this node to catch errors
|
||||||
node.register = function(consumerNode) {
|
node.register = function(consumerNode) {
|
||||||
node.users[consumerNode.id] = consumerNode;
|
node.users[consumerNode.id] = consumerNode;
|
||||||
};
|
};
|
||||||
@ -99,7 +119,7 @@ module.exports = function(RED) {
|
|||||||
device_id = this.matrixClient.getDeviceId();
|
device_id = this.matrixClient.getDeviceId();
|
||||||
|
|
||||||
if(!device_id && node.enableE2ee) {
|
if(!device_id && node.enableE2ee) {
|
||||||
node.error("Failed to auto detect deviceId for this auth token. You will need to manually specify one. You may need to login to create a new deviceId.", {})
|
node.error("Failed to auto detect deviceId for this auth token. You will need to manually specify one. You may need to login to create a new deviceId.", {});
|
||||||
} else {
|
} else {
|
||||||
if(!stored_device_id || stored_device_id !== device_id) {
|
if(!stored_device_id || stored_device_id !== device_id) {
|
||||||
node.log(`Saving Device ID (old:${stored_device_id} new:${device_id})`);
|
node.log(`Saving Device ID (old:${stored_device_id} new:${device_id})`);
|
||||||
@ -116,7 +136,7 @@ module.exports = function(RED) {
|
|||||||
node.matrixClient.setDeviceDetails(device_id, {
|
node.matrixClient.setDeviceDetails(device_id, {
|
||||||
display_name: node.deviceLabel
|
display_name: node.deviceLabel
|
||||||
}).then(
|
}).then(
|
||||||
function(response) {},
|
function() {},
|
||||||
function(error) {
|
function(error) {
|
||||||
node.error("Failed to set device label: " + error, {});
|
node.error("Failed to set device label: " + error, {});
|
||||||
}
|
}
|
||||||
@ -154,7 +174,6 @@ module.exports = function(RED) {
|
|||||||
}),
|
}),
|
||||||
userId: this.userId,
|
userId: this.userId,
|
||||||
deviceId: (this.deviceId || getStoredDeviceId(localStorage)) || undefined
|
deviceId: (this.deviceId || getStoredDeviceId(localStorage)) || undefined
|
||||||
// verificationMethods: ["m.sas.v1"]
|
|
||||||
});
|
});
|
||||||
|
|
||||||
node.debug(`hasLazyLoadMembersEnabled=${node.matrixClient.hasLazyLoadMembersEnabled()}`);
|
node.debug(`hasLazyLoadMembersEnabled=${node.matrixClient.hasLazyLoadMembersEnabled()}`);
|
||||||
@ -180,7 +199,7 @@ module.exports = function(RED) {
|
|||||||
if(node.globalAccess) {
|
if(node.globalAccess) {
|
||||||
try {
|
try {
|
||||||
node.context().global.set('matrixClient["'+node.userId+'"]', undefined);
|
node.context().global.set('matrixClient["'+node.userId+'"]', undefined);
|
||||||
} catch(e){
|
} catch(e) {
|
||||||
node.error(e.message, {});
|
node.error(e.message, {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,15 +213,15 @@ module.exports = function(RED) {
|
|||||||
node.matrixClient.on(RoomEvent.Timeline, async function(event, room, toStartOfTimeline, removed, data) {
|
node.matrixClient.on(RoomEvent.Timeline, async function(event, room, toStartOfTimeline, removed, data) {
|
||||||
if (toStartOfTimeline) {
|
if (toStartOfTimeline) {
|
||||||
node.log("Ignoring" + (event.isEncrypted() ? ' encrypted' : '') +" timeline event [" + (event.getContent()['msgtype'] || event.getType()) + "]: (" + room.name + ") " + event.getId() + " for reason: paginated result");
|
node.log("Ignoring" + (event.isEncrypted() ? ' encrypted' : '') +" timeline event [" + (event.getContent()['msgtype'] || event.getType()) + "]: (" + room.name + ") " + event.getId() + " for reason: paginated result");
|
||||||
return; // ignore paginated results
|
return;
|
||||||
}
|
}
|
||||||
if (!data || !data.liveEvent) {
|
if (!data || !data.liveEvent) {
|
||||||
node.log("Ignoring" + (event.isEncrypted() ? ' encrypted' : '') +" timeline event [" + (event.getContent()['msgtype'] || event.getType()) + "]: (" + room.name + ") " + event.getId() + " for reason: old message");
|
node.log("Ignoring" + (event.isEncrypted() ? ' encrypted' : '') +" timeline event [" + (event.getContent()['msgtype'] || event.getType()) + "]: (" + room.name + ") " + event.getId() + " for reason: old message");
|
||||||
return; // ignore old message (we only want live events)
|
return;
|
||||||
}
|
}
|
||||||
if(node.initializedAt > event.getDate()) {
|
if(node.initializedAt > event.getDate()) {
|
||||||
node.log("Ignoring" + (event.isEncrypted() ? ' encrypted' : '') +" timeline event [" + (event.getContent()['msgtype'] || event.getType()) + "]: (" + room.name + ") " + event.getId() + " for reason: old message before init");
|
node.log("Ignoring" + (event.isEncrypted() ? ' encrypted' : '') +" timeline event [" + (event.getContent()['msgtype'] || event.getType()) + "]: (" + room.name + ") " + event.getId() + " for reason: old message before init");
|
||||||
return; // skip events that occurred before our client initialized
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -377,7 +396,6 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
node.matrixClient.on(HttpApiEvent.SessionLoggedOut, async function(errorObj){
|
node.matrixClient.on(HttpApiEvent.SessionLoggedOut, async function(errorObj){
|
||||||
// Example if user auth token incorrect:
|
// Example if user auth token incorrect:
|
||||||
// {
|
// {
|
||||||
@ -450,7 +468,7 @@ module.exports = function(RED) {
|
|||||||
node.error("Auth check failed: " + err, {});
|
node.error("Auth check failed: " + err, {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -475,19 +493,21 @@ module.exports = function(RED) {
|
|||||||
deviceId = req.body.deviceId || undefined,
|
deviceId = req.body.deviceId || undefined,
|
||||||
displayName = req.body.displayName || undefined;
|
displayName = req.body.displayName || undefined;
|
||||||
|
|
||||||
const matrixClient = sdk.createClient({
|
(async () => {
|
||||||
|
const mod = await import("matrix-js-sdk");
|
||||||
|
const matrixClient = mod.createClient({
|
||||||
baseUrl: baseUrl,
|
baseUrl: baseUrl,
|
||||||
deviceId: deviceId,
|
deviceId: deviceId,
|
||||||
timelineSupport: true,
|
timelineSupport: true,
|
||||||
localTimeoutMs: '30000'
|
localTimeoutMs: '30000'
|
||||||
});
|
});
|
||||||
|
|
||||||
new TimelineWindow()
|
new TimelineWindow(); // from our top-level variable, but to keep minimal changes,
|
||||||
|
// you can just do: (await import("matrix-js-sdk")).TimelineWindow();
|
||||||
|
|
||||||
matrixClient.timelineSupport = true;
|
matrixClient.timelineSupport = true;
|
||||||
|
|
||||||
matrixClient.login(
|
matrixClient.login('m.login.password', {
|
||||||
'm.login.password', {
|
|
||||||
identifier: {
|
identifier: {
|
||||||
type: 'm.id.user',
|
type: 'm.id.user',
|
||||||
user: userId,
|
user: userId,
|
||||||
@ -511,7 +531,11 @@ module.exports = function(RED) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
})().catch(err => {
|
||||||
|
res.json({ result: 'error', message: err.toString() });
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
function upgradeDirectoryIfNecessary(node, storageDir) {
|
function upgradeDirectoryIfNecessary(node, storageDir) {
|
||||||
let oldStorageDir = './matrix-local-storage',
|
let oldStorageDir = './matrix-local-storage',
|
||||||
@ -552,9 +576,6 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* If a device ID is stored we will use that for the client
|
|
||||||
*/
|
|
||||||
function getStoredDeviceId(localStorage) {
|
function getStoredDeviceId(localStorage) {
|
||||||
let deviceId = localStorage.getItem('my_device_id');
|
let deviceId = localStorage.getItem('my_device_id');
|
||||||
if(deviceId === "null" || !deviceId) {
|
if(deviceId === "null" || !deviceId) {
|
||||||
@ -570,4 +591,4 @@ module.exports = function(RED) {
|
|||||||
localStorage.setItem('my_device_id', deviceId);
|
localStorage.setItem('my_device_id', deviceId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
};
|
Loading…
x
Reference in New Issue
Block a user