mirror of
https://github.com/Skylar-Tech/node-red-contrib-matrix-chat.git
synced 2025-07-01 16:11:17 -06:00
- #109 get own events
- #28 paginate room history - #111 manual read markers - fix clearing global storage - update node docs for upload file
This commit is contained in:
parent
a08709265e
commit
51e649b4cf
@ -24,11 +24,15 @@
|
|||||||
"matrix-server-config": "src/matrix-server-config.js",
|
"matrix-server-config": "src/matrix-server-config.js",
|
||||||
"matrix-receive": "src/matrix-receive.js",
|
"matrix-receive": "src/matrix-receive.js",
|
||||||
"matrix-send-message": "src/matrix-send-message.js",
|
"matrix-send-message": "src/matrix-send-message.js",
|
||||||
|
"matrix-typing": "src/matrix-typing.js",
|
||||||
|
"matrix-mark-read": "src/matrix-mark-read.js",
|
||||||
"matrix-delete-event": "src/matrix-delete-event.js",
|
"matrix-delete-event": "src/matrix-delete-event.js",
|
||||||
"matrix-send-file": "src/matrix-send-file.js",
|
"matrix-send-file": "src/matrix-send-file.js",
|
||||||
"matrix-send-image": "src/matrix-send-image.js",
|
"matrix-send-image": "src/matrix-send-image.js",
|
||||||
"matrix-upload-file": "src/matrix-upload-file.js",
|
"matrix-upload-file": "src/matrix-upload-file.js",
|
||||||
"matrix-react": "src/matrix-react.js",
|
"matrix-react": "src/matrix-react.js",
|
||||||
|
"matrix-user-settings": "src/matrix-user-settings.js",
|
||||||
|
"matrix-get-user": "src/matrix-get-user.js",
|
||||||
"matrix-create-room": "src/matrix-create-room.js",
|
"matrix-create-room": "src/matrix-create-room.js",
|
||||||
"matrix-invite-room": "src/matrix-invite-room.js",
|
"matrix-invite-room": "src/matrix-invite-room.js",
|
||||||
"matrix-room-invite": "src/matrix-room-invite.js",
|
"matrix-room-invite": "src/matrix-room-invite.js",
|
||||||
@ -45,9 +49,7 @@
|
|||||||
"matrix-synapse-deactivate-user": "src/matrix-synapse-deactivate-user.js",
|
"matrix-synapse-deactivate-user": "src/matrix-synapse-deactivate-user.js",
|
||||||
"matrix-synapse-join-room": "src/matrix-synapse-join-room.js",
|
"matrix-synapse-join-room": "src/matrix-synapse-join-room.js",
|
||||||
"matrix-whois-user": "src/matrix-whois-user.js",
|
"matrix-whois-user": "src/matrix-whois-user.js",
|
||||||
"matrix-typing": "src/matrix-typing.js",
|
"matrix-paginate-room": "src/matrix-paginate-room.js"
|
||||||
"matrix-user-settings": "src/matrix-user-settings.js",
|
|
||||||
"matrix-get-user": "src/matrix-get-user.js"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
254
src/matrix-mark-read.html
Normal file
254
src/matrix-mark-read.html
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('matrix-mark-read',{
|
||||||
|
category: 'matrix',
|
||||||
|
color: '#00b7ca',
|
||||||
|
icon: "matrix.png",
|
||||||
|
outputLabels: ["message"],
|
||||||
|
inputs: 1,
|
||||||
|
outputs: 2,
|
||||||
|
defaults: {
|
||||||
|
name: { value: null },
|
||||||
|
server: { type: "matrix-server-config" },
|
||||||
|
roomType: { value: "msg" },
|
||||||
|
roomValue: { value: "topic" },
|
||||||
|
eventIdType: { value: "msg" },
|
||||||
|
eventIdValue: { value: "eventId" }
|
||||||
|
},
|
||||||
|
label: function() {
|
||||||
|
return this.name || "Mark Read";
|
||||||
|
},
|
||||||
|
paletteLabel: 'Mark Read',
|
||||||
|
oneditprepare: function() {
|
||||||
|
$("#node-input-room").typedInput({
|
||||||
|
type: this.roomType,
|
||||||
|
types:['msg','flow','global','str'],
|
||||||
|
})
|
||||||
|
.typedInput('value', this.roomValue)
|
||||||
|
.typedInput('type', this.roomType);
|
||||||
|
|
||||||
|
$("#node-input-eventId").typedInput({
|
||||||
|
types:['msg','flow','global','bool'],
|
||||||
|
})
|
||||||
|
.typedInput('value', this.eventIdValue)
|
||||||
|
.typedInput('type', this.eventIdType);
|
||||||
|
},
|
||||||
|
oneditsave: function() {
|
||||||
|
this.roomType = $("#node-input-room").typedInput('type');
|
||||||
|
this.roomValue = $("#node-input-room").typedInput('value');
|
||||||
|
this.eventIdType = $("#node-input-eventId").typedInput('type');
|
||||||
|
this.eventIdValue = $("#node-input-eventId").typedInput('value');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/html" data-template-name="matrix-mark-read">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-server"><i class="fa fa-server"></i> Matrix Server</label>
|
||||||
|
<input type="text" id="node-input-server">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-room"><i class="fa fa-comments"></i> Room</label>
|
||||||
|
<input type="text" id="node-input-room">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-eventId"><i class="fa fa-comments"></i> Event Id</label>
|
||||||
|
<input type="text" id="node-input-eventId">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/html" data-help-name="matrix-mark-read">
|
||||||
|
<p>Mark an event in a room as read.</p>
|
||||||
|
|
||||||
|
<h3>Outputs</h3>
|
||||||
|
<ul class="node-ports">
|
||||||
|
<li>Always Returned
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.type <span class="property-type">string</span></dt>
|
||||||
|
<dd>
|
||||||
|
the message type. For example this will be either m.text, m.reaction, m.file, m.image, etc
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.isDM <span class="property-type">bool</span></dt>
|
||||||
|
<dd> returns true if message is from a direct message room.</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.encrypted <span class="property-type">bool</span></dt>
|
||||||
|
<dd> returns true if message was encrypted (e2ee).</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.redacted <span class="property-type">bool</span></dt>
|
||||||
|
<dd> returns true if the message was redacted (such as deleted by the user).</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.payload <span class="property-type">string</span></dt>
|
||||||
|
<dd>the body from the message's content.</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.userId <span class="property-type">string</span></dt>
|
||||||
|
<dd>the User ID of the message sender. Example: @john:matrix.org</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.topic <span class="property-type">string</span></dt>
|
||||||
|
<dd>the ID of the room. Example: !OGEhHVWSdvArJzumhm:matrix.org</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.event <span class="property-type">object</span></dt>
|
||||||
|
<dd>the event object returned by the Matrix server</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.eventId <span class="property-type">object</span></dt>
|
||||||
|
<dd>The event ID, e.g. $143350589368169JsLZx:localhost</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.content <span class="property-type">object</span></dt>
|
||||||
|
<dd>the message's content object</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><code>msg.type</code> == '<strong>m.text</strong>'
|
||||||
|
<div class="form-tips" style="margin-bottom: 12px;">
|
||||||
|
Doesn't return anything extra
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><code>msg.type</code> == '<strong>m.reaction</strong>'
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.referenceEventId <span class="property-type">string</span></dt>
|
||||||
|
<dd>the message that the reaction relates to</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.payload <span class="property-type">string</span></dt>
|
||||||
|
<dd>the key of the reaction's content</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><code>msg.type</code> == '<strong>m.emote</strong>'
|
||||||
|
<div class="form-tips" style="margin-bottom: 12px;">
|
||||||
|
Doesn't return anything extra
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><code>msg.type</code> == '<strong>m.sticker</strong>'
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.url <span class="property-type">string</span></dt>
|
||||||
|
<dd>URL to the sticker image</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.mxc_url <span class="property-type">string</span></dt>
|
||||||
|
<dd>Matrix URL to the sticker image</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.thumbnail_url <span class="property-type">string</span></dt>
|
||||||
|
<dd>URL to the thumbnail of the sticker</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.thumbnail_mxc_url <span class="property-type">string</span></dt>
|
||||||
|
<dd>Matrix URL to the thumbnail of the sticker</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><code>msg.type</code> == '<strong>m.file</strong>'
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.filename <span class="property-type">string</span></dt>
|
||||||
|
<dd>the file's parsed filename</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.url <span class="property-type">string</span></dt>
|
||||||
|
<dd>the file's URL</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.mxc_url <span class="property-type">string</span></dt>
|
||||||
|
<dd>the file's Matrix URL</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><code>msg.type</code> == '<strong>m.audio</strong>'
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.filename <span class="property-type">string</span></dt>
|
||||||
|
<dd>the image's parsed filename</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.mimetype <span class="property-type">string</span></dt>
|
||||||
|
<dd>audio file mimetype (ex: audio/ogg)</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.url <span class="property-type">string</span></dt>
|
||||||
|
<dd>the file's URL</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.mxc_url <span class="property-type">string</span></dt>
|
||||||
|
<dd>the file's Matrix URL</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.duration <span class="property-type">integer</span></dt>
|
||||||
|
<dd>duration of audio file in milliseconds</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.waveform <span class="property-type">array[int]</span></dt>
|
||||||
|
<dd>waveform of the audio clip</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><code>msg.type</code> == '<strong>m.image</strong>'
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.filename <span class="property-type">string</span></dt>
|
||||||
|
<dd>the image's parsed filename</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.url <span class="property-type">string</span></dt>
|
||||||
|
<dd>the image's URL</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.mxc_url <span class="property-type">string</span></dt>
|
||||||
|
<dd>the image's Matrix URL</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.thumbnail_url <span class="property-type">string</span></dt>
|
||||||
|
<dd>the image's thumbnail URL</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.thumbnail_mxc_url <span class="property-type">string</span></dt>
|
||||||
|
<dd>the image's thumbnail Matrix URL</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><code>msg.type</code> == '<strong>m.location</strong>'
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.geo_uri <span class="property-type">string</span></dt>
|
||||||
|
<dd>URI format of the geolocation</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</script>
|
73
src/matrix-mark-read.js
Normal file
73
src/matrix-mark-read.js
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
const {TimelineWindow, RelationType, Filter} = require("matrix-js-sdk");
|
||||||
|
const crypto = require('crypto');
|
||||||
|
module.exports = function(RED) {
|
||||||
|
function MatrixReceiveMessage(n) {
|
||||||
|
RED.nodes.createNode(this, n);
|
||||||
|
|
||||||
|
let node = this;
|
||||||
|
this.name = n.name;
|
||||||
|
this.server = RED.nodes.getNode(n.server);
|
||||||
|
this.roomType = n.roomType;
|
||||||
|
this.roomValue = n.roomValue;
|
||||||
|
this.eventIdType = n.eventIdType;
|
||||||
|
this.eventIdValue = n.eventIdValue;
|
||||||
|
|
||||||
|
node.status({ fill: "red", shape: "ring", text: "disconnected" });
|
||||||
|
|
||||||
|
if (!node.server) {
|
||||||
|
node.error("No configuration node", {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
node.server.register(node);
|
||||||
|
|
||||||
|
node.server.on("disconnected", function(){
|
||||||
|
node.status({ fill: "red", shape: "ring", text: "disconnected" });
|
||||||
|
});
|
||||||
|
|
||||||
|
node.server.on("connected", function() {
|
||||||
|
node.status({ fill: "green", shape: "ring", text: "connected" });
|
||||||
|
});
|
||||||
|
|
||||||
|
node.on("input", async function (msg) {
|
||||||
|
if (! node.server || ! node.server.matrixClient) {
|
||||||
|
node.error("No matrix server selected", msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getToValue(msg, type, property) {
|
||||||
|
let value = property;
|
||||||
|
if (type === "msg") {
|
||||||
|
value = RED.util.getMessageProperty(msg, property);
|
||||||
|
} else if ((type === 'flow') || (type === 'global')) {
|
||||||
|
try {
|
||||||
|
value = RED.util.evaluateNodeProperty(property, type, node, msg);
|
||||||
|
} catch(e2) {
|
||||||
|
throw new Error("Invalid value evaluation");
|
||||||
|
}
|
||||||
|
} else if(type === "bool") {
|
||||||
|
value = (property === 'true');
|
||||||
|
} else if(type === "num") {
|
||||||
|
value = Number(property);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let roomId = getToValue(msg, node.roomType, node.roomValue),
|
||||||
|
eventId = getToValue(msg, node.eventIdType, node.eventIdValue);
|
||||||
|
|
||||||
|
msg.payload = await node.server.matrixClient.setRoomReadMarkers(roomId, eventId);
|
||||||
|
node.send([msg, null]);
|
||||||
|
} catch(e) {
|
||||||
|
msg.error = `Room pagination error: ${e}`;
|
||||||
|
node.error(msg.error, msg);
|
||||||
|
node.send([null, msg]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
node.on("close", function() {
|
||||||
|
node.server.deregister(node);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("matrix-mark-read", MatrixReceiveMessage);
|
||||||
|
}
|
284
src/matrix-paginate-room.html
Normal file
284
src/matrix-paginate-room.html
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('matrix-paginate-room',{
|
||||||
|
category: 'matrix',
|
||||||
|
color: '#00b7ca',
|
||||||
|
icon: "matrix.png",
|
||||||
|
outputLabels: ["message"],
|
||||||
|
inputs: 1,
|
||||||
|
outputs: 2,
|
||||||
|
defaults: {
|
||||||
|
name: { value: null },
|
||||||
|
server: { type: "matrix-server-config" },
|
||||||
|
roomType: { value: "msg" },
|
||||||
|
roomValue: { value: "topic" },
|
||||||
|
paginateKeyType: { value: "msg" },
|
||||||
|
paginateKeyValue: { value: "paginationKey" },
|
||||||
|
paginateBackwardsType: { value: "bool" },
|
||||||
|
paginateBackwardsValue: { value: "true" },
|
||||||
|
pageSizeType: { value: "num" },
|
||||||
|
pageSizeValue: { value: "25" }
|
||||||
|
},
|
||||||
|
label: function() {
|
||||||
|
return this.name || "Paginate Room";
|
||||||
|
},
|
||||||
|
paletteLabel: 'Paginate Room',
|
||||||
|
oneditprepare: function() {
|
||||||
|
$("#node-input-room").typedInput({
|
||||||
|
type: this.roomType,
|
||||||
|
types:['msg','flow','global','str'],
|
||||||
|
})
|
||||||
|
.typedInput('value', this.roomValue)
|
||||||
|
.typedInput('type', this.roomType);
|
||||||
|
|
||||||
|
$("#node-input-paginateBackwards").typedInput({
|
||||||
|
types:['msg','flow','global','bool'],
|
||||||
|
})
|
||||||
|
.typedInput('value', this.paginateBackwardsValue)
|
||||||
|
.typedInput('type', this.paginateBackwardsType);
|
||||||
|
|
||||||
|
$("#node-input-paginateKey").typedInput({
|
||||||
|
types:['msg','flow','global'],
|
||||||
|
})
|
||||||
|
.typedInput('value', this.paginateKeyValue)
|
||||||
|
.typedInput('type', this.paginateKeyType);
|
||||||
|
|
||||||
|
$("#node-input-pageSize").typedInput({
|
||||||
|
types:['msg','flow','global','num'],
|
||||||
|
})
|
||||||
|
.typedInput('value', this.pageSizeValue)
|
||||||
|
.typedInput('type', this.pageSizeType);
|
||||||
|
},
|
||||||
|
oneditsave: function() {
|
||||||
|
this.roomType = $("#node-input-room").typedInput('type');
|
||||||
|
this.roomValue = $("#node-input-room").typedInput('value');
|
||||||
|
this.paginateBackwardsType = $("#node-input-paginateBackwards").typedInput('type');
|
||||||
|
this.paginateBackwardsValue = $("#node-input-paginateBackwards").typedInput('value');
|
||||||
|
this.paginateKeyType = $("#node-input-paginateKey").typedInput('type');
|
||||||
|
this.paginateKeyValue = $("#node-input-paginateKey").typedInput('value');
|
||||||
|
this.pageSizeType = $("#node-input-pageSize").typedInput('type');
|
||||||
|
this.pageSizeValue = $("#node-input-pageSize").typedInput('value');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/html" data-template-name="matrix-paginate-room">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-server"><i class="fa fa-server"></i> Matrix Server</label>
|
||||||
|
<input type="text" id="node-input-server">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-room"><i class="fa fa-comments"></i> Room</label>
|
||||||
|
<input type="text" id="node-input-room">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-paginateKey"><i class="fa fa-comments"></i> Pagination Key</label>
|
||||||
|
<input type="text" id="node-input-paginateKey">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-paginateBackwards"><i class="fa fa-commenting-o"></i> Paginate Backwards</label>
|
||||||
|
<input type="text" id="node-input-paginateBackwards">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-pageSize"><i class="fa fa-commenting-o"></i> Page Size</label>
|
||||||
|
<input type="text" id="node-input-pageSize">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/html" data-help-name="matrix-paginate-room">
|
||||||
|
<p>Receive events from Matrix.</p>
|
||||||
|
|
||||||
|
<h3>Outputs</h3>
|
||||||
|
<ul class="node-ports">
|
||||||
|
<li>Always Returned
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.type <span class="property-type">string</span></dt>
|
||||||
|
<dd>
|
||||||
|
the message type. For example this will be either m.text, m.reaction, m.file, m.image, etc
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.isDM <span class="property-type">bool</span></dt>
|
||||||
|
<dd> returns true if message is from a direct message room.</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.encrypted <span class="property-type">bool</span></dt>
|
||||||
|
<dd> returns true if message was encrypted (e2ee).</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.redacted <span class="property-type">bool</span></dt>
|
||||||
|
<dd> returns true if the message was redacted (such as deleted by the user).</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.payload <span class="property-type">string</span></dt>
|
||||||
|
<dd>the body from the message's content.</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.userId <span class="property-type">string</span></dt>
|
||||||
|
<dd>the User ID of the message sender. Example: @john:matrix.org</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.topic <span class="property-type">string</span></dt>
|
||||||
|
<dd>the ID of the room. Example: !OGEhHVWSdvArJzumhm:matrix.org</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.event <span class="property-type">object</span></dt>
|
||||||
|
<dd>the event object returned by the Matrix server</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.eventId <span class="property-type">object</span></dt>
|
||||||
|
<dd>The event ID, e.g. $143350589368169JsLZx:localhost</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.content <span class="property-type">object</span></dt>
|
||||||
|
<dd>the message's content object</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><code>msg.type</code> == '<strong>m.text</strong>'
|
||||||
|
<div class="form-tips" style="margin-bottom: 12px;">
|
||||||
|
Doesn't return anything extra
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><code>msg.type</code> == '<strong>m.reaction</strong>'
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.referenceEventId <span class="property-type">string</span></dt>
|
||||||
|
<dd>the message that the reaction relates to</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.payload <span class="property-type">string</span></dt>
|
||||||
|
<dd>the key of the reaction's content</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><code>msg.type</code> == '<strong>m.emote</strong>'
|
||||||
|
<div class="form-tips" style="margin-bottom: 12px;">
|
||||||
|
Doesn't return anything extra
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><code>msg.type</code> == '<strong>m.sticker</strong>'
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.url <span class="property-type">string</span></dt>
|
||||||
|
<dd>URL to the sticker image</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.mxc_url <span class="property-type">string</span></dt>
|
||||||
|
<dd>Matrix URL to the sticker image</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.thumbnail_url <span class="property-type">string</span></dt>
|
||||||
|
<dd>URL to the thumbnail of the sticker</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.thumbnail_mxc_url <span class="property-type">string</span></dt>
|
||||||
|
<dd>Matrix URL to the thumbnail of the sticker</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><code>msg.type</code> == '<strong>m.file</strong>'
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.filename <span class="property-type">string</span></dt>
|
||||||
|
<dd>the file's parsed filename</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.url <span class="property-type">string</span></dt>
|
||||||
|
<dd>the file's URL</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.mxc_url <span class="property-type">string</span></dt>
|
||||||
|
<dd>the file's Matrix URL</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><code>msg.type</code> == '<strong>m.audio</strong>'
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.filename <span class="property-type">string</span></dt>
|
||||||
|
<dd>the image's parsed filename</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.mimetype <span class="property-type">string</span></dt>
|
||||||
|
<dd>audio file mimetype (ex: audio/ogg)</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.url <span class="property-type">string</span></dt>
|
||||||
|
<dd>the file's URL</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.mxc_url <span class="property-type">string</span></dt>
|
||||||
|
<dd>the file's Matrix URL</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.duration <span class="property-type">integer</span></dt>
|
||||||
|
<dd>duration of audio file in milliseconds</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.waveform <span class="property-type">array[int]</span></dt>
|
||||||
|
<dd>waveform of the audio clip</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><code>msg.type</code> == '<strong>m.image</strong>'
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.filename <span class="property-type">string</span></dt>
|
||||||
|
<dd>the image's parsed filename</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.url <span class="property-type">string</span></dt>
|
||||||
|
<dd>the image's URL</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.mxc_url <span class="property-type">string</span></dt>
|
||||||
|
<dd>the image's Matrix URL</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.thumbnail_url <span class="property-type">string</span></dt>
|
||||||
|
<dd>the image's thumbnail URL</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.thumbnail_mxc_url <span class="property-type">string</span></dt>
|
||||||
|
<dd>the image's thumbnail Matrix URL</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><code>msg.type</code> == '<strong>m.location</strong>'
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.geo_uri <span class="property-type">string</span></dt>
|
||||||
|
<dd>URI format of the geolocation</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</script>
|
155
src/matrix-paginate-room.js
Normal file
155
src/matrix-paginate-room.js
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
const {TimelineWindow, RelationType, Filter} = require("matrix-js-sdk");
|
||||||
|
const crypto = require('crypto');
|
||||||
|
module.exports = function(RED) {
|
||||||
|
function MatrixReceiveMessage(n) {
|
||||||
|
RED.nodes.createNode(this, n);
|
||||||
|
|
||||||
|
let node = this;
|
||||||
|
this.name = n.name;
|
||||||
|
this.server = RED.nodes.getNode(n.server);
|
||||||
|
this.roomType = n.roomType;
|
||||||
|
this.roomValue = n.roomValue;
|
||||||
|
this.paginateBackwardsType = n.paginateBackwardsType;
|
||||||
|
this.paginateBackwardsValue = n.paginateBackwardsValue;
|
||||||
|
this.paginateKeyType = n.paginateKeyType;
|
||||||
|
this.paginateKeyValue = n.paginateKeyValue;
|
||||||
|
this.pageSizeType = n.pageSizeType;
|
||||||
|
this.pageSizeValue = n.pageSizeValue;
|
||||||
|
this.timelineWindows = new Map();
|
||||||
|
|
||||||
|
node.status({ fill: "red", shape: "ring", text: "disconnected" });
|
||||||
|
|
||||||
|
if (!node.server) {
|
||||||
|
node.error("No configuration node", {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
node.server.register(node);
|
||||||
|
|
||||||
|
node.server.on("disconnected", function(){
|
||||||
|
node.status({ fill: "red", shape: "ring", text: "disconnected" });
|
||||||
|
});
|
||||||
|
|
||||||
|
node.server.on("connected", function() {
|
||||||
|
node.status({ fill: "green", shape: "ring", text: "connected" });
|
||||||
|
});
|
||||||
|
|
||||||
|
node.on("input", async function (msg) {
|
||||||
|
if (! node.server || ! node.server.matrixClient) {
|
||||||
|
node.error("No matrix server selected", msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getToValue(msg, type, property) {
|
||||||
|
let value = property;
|
||||||
|
if (type === "msg") {
|
||||||
|
value = RED.util.getMessageProperty(msg, property);
|
||||||
|
} else if ((type === 'flow') || (type === 'global')) {
|
||||||
|
try {
|
||||||
|
value = RED.util.evaluateNodeProperty(property, type, node, msg);
|
||||||
|
} catch(e2) {
|
||||||
|
throw new Error("Invalid value evaluation");
|
||||||
|
}
|
||||||
|
} else if(type === "bool") {
|
||||||
|
value = (property === 'true');
|
||||||
|
} else if(type === "num") {
|
||||||
|
value = Number(property);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setToValue(value, type, property) {
|
||||||
|
if(type === 'global' || type === 'flow') {
|
||||||
|
var contextKey = RED.util.parseContextStore(property);
|
||||||
|
if (/\[msg/.test(contextKey.key)) {
|
||||||
|
// The key has a nest msg. reference to evaluate first
|
||||||
|
contextKey.key = RED.util.normalisePropertyExpression(contextKey.key, msg, true)
|
||||||
|
}
|
||||||
|
var target = node.context()[type];
|
||||||
|
var callback = err => {
|
||||||
|
if (err) {
|
||||||
|
node.error(err, msg);
|
||||||
|
getterErrors[rule.p] = err.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
target.set(contextKey.key, value, contextKey.store, callback);
|
||||||
|
} else if(type === 'msg') {
|
||||||
|
if (!RED.util.setMessageProperty(msg, property, value)) {
|
||||||
|
node.warn(RED._("change.errors.no-override",{property:property}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let roomId = getToValue(msg, node.roomType, node.roomValue),
|
||||||
|
paginateBackwards = getToValue(msg, node.paginateBackwardsType, node.paginateBackwardsValue),
|
||||||
|
pageSize = getToValue(msg, node.pageSizeType, node.pageSizeValue),
|
||||||
|
pageKey = getToValue(msg, node.paginateKeyType, node.paginateKeyValue);
|
||||||
|
|
||||||
|
let room = node.server.matrixClient.getRoom(roomId);
|
||||||
|
|
||||||
|
if(!room) {
|
||||||
|
throw new Error(`Room ${roomId} does not exist`);
|
||||||
|
}
|
||||||
|
if(pageSize > node.server.initialSyncLimit) {
|
||||||
|
throw new Error(`Page size=${pageSize} cannot exceed initialSyncLimit=${node.server.initialSyncLimit}`);
|
||||||
|
}
|
||||||
|
if(!pageKey) {
|
||||||
|
pageKey = crypto.randomUUID();
|
||||||
|
setToValue(pageKey, node.paginateKeyType, node.paginateKeyValue);
|
||||||
|
}
|
||||||
|
let timelineWindow = node.timelineWindows.get(pageKey),
|
||||||
|
moreMessages = true;
|
||||||
|
if(!timelineWindow) {
|
||||||
|
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
|
||||||
|
timelineWindow = new TimelineWindow(node.server.matrixClient, timelineSet);
|
||||||
|
await timelineWindow.load(msg.eventId || null, pageSize);
|
||||||
|
node.timelineWindows.set(pageKey, timelineWindow);
|
||||||
|
} else {
|
||||||
|
moreMessages = await timelineWindow.paginate(paginateBackwards ? 'b' : 'f', pageSize); // b for backwards f for forwards
|
||||||
|
if(moreMessages) {
|
||||||
|
await timelineWindow.unpaginate(pageSize, !paginateBackwards);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MatrixEvent objects are massive so this throws an encode error for the string being too long
|
||||||
|
// since msg objects convert to JSON
|
||||||
|
// msg.payload = moreMessages ? timelineWindow.getEvents() : false;
|
||||||
|
|
||||||
|
msg.payload = false;
|
||||||
|
msg.start = timelineWindow.getTimelineIndex('b')?.index;
|
||||||
|
msg.end = timelineWindow.getTimelineIndex('f')?.index;
|
||||||
|
if(moreMessages) {
|
||||||
|
msg.payload = timelineWindow.getEvents().map(function(event) {
|
||||||
|
return {
|
||||||
|
encrypted : event.isEncrypted(),
|
||||||
|
redacted : event.isRedacted(),
|
||||||
|
content : event.getContent(),
|
||||||
|
type : (event.getContent()['msgtype'] || event.getType()) || null,
|
||||||
|
payload : (event.getContent()['body'] || event.getContent()) || null,
|
||||||
|
isThread : event.getContent()?.['m.relates_to']?.rel_type === RelationType.Thread,
|
||||||
|
mentions : event.getContent()["m.mentions"] || null,
|
||||||
|
userId : event.getSender(),
|
||||||
|
// user : node.matrixClient.getUser(event.getSender()),
|
||||||
|
topic : event.getRoomId(),
|
||||||
|
eventId : event.getId(),
|
||||||
|
event : event,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
node.send([msg, null]);
|
||||||
|
} catch(e) {
|
||||||
|
msg.error = `Room pagination error: ${e}`;
|
||||||
|
node.error(msg.error, msg);
|
||||||
|
node.send([null, msg]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
node.on("close", function() {
|
||||||
|
node.server.deregister(node);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("matrix-paginate-room", MatrixReceiveMessage);
|
||||||
|
}
|
@ -10,6 +10,7 @@
|
|||||||
name: { value: null },
|
name: { value: null },
|
||||||
server: { type: "matrix-server-config" },
|
server: { type: "matrix-server-config" },
|
||||||
roomId: {"value": null},
|
roomId: {"value": null},
|
||||||
|
acceptOwnEvents: {"value": false},
|
||||||
acceptText: {"value": true},
|
acceptText: {"value": true},
|
||||||
acceptEmotes: {"value": true},
|
acceptEmotes: {"value": true},
|
||||||
acceptStickers: {"value": true},
|
acceptStickers: {"value": true},
|
||||||
@ -45,6 +46,16 @@
|
|||||||
<div class="form-row" style="margin-left: 100px;margin-top:10px;font-weight:bold;">
|
<div class="form-row" style="margin-left: 100px;margin-top:10px;font-weight:bold;">
|
||||||
Timeline event filters
|
Timeline event filters
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-row" style="margin-bottom:0;">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="node-input-acceptOwnEvents"
|
||||||
|
style="width: auto; margin-left: 125px; vertical-align: top"
|
||||||
|
/>
|
||||||
|
<label for="node-input-acceptOwnEvents" style="width: auto">
|
||||||
|
Receive own events
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<div class="form-row" style="margin-bottom:0;">
|
<div class="form-row" style="margin-bottom:0;">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
|
@ -7,6 +7,7 @@ module.exports = function(RED) {
|
|||||||
|
|
||||||
this.name = n.name;
|
this.name = n.name;
|
||||||
this.server = RED.nodes.getNode(n.server);
|
this.server = RED.nodes.getNode(n.server);
|
||||||
|
this.acceptOwnEvents = n.acceptOwnEvents;
|
||||||
this.acceptText = n.acceptText;
|
this.acceptText = n.acceptText;
|
||||||
this.acceptEmotes = n.acceptEmotes;
|
this.acceptEmotes = n.acceptEmotes;
|
||||||
this.acceptStickers = n.acceptStickers;
|
this.acceptStickers = n.acceptStickers;
|
||||||
@ -41,6 +42,11 @@ module.exports = function(RED) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!node.acceptOwnEvents && ( !event.getSender() || event.getSender() === node.userId ) ) {
|
||||||
|
node.log("Ignoring" + (msg.encrypted ? ' encrypted' : '') +" timeline event [" + msg.type + "]: (" + room.name + ") " + event.getId() + " for reason: own event");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch(msg.type) {
|
switch(msg.type) {
|
||||||
case 'm.emote':
|
case 'm.emote':
|
||||||
if(!node.acceptEmotes) return;
|
if(!node.acceptEmotes) return;
|
||||||
|
@ -167,9 +167,6 @@ module.exports = function(RED) {
|
|||||||
} 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 the m.relates_to property
|
||||||
// otherwise fallback to msg.eventId
|
// otherwise fallback to msg.eventId
|
||||||
console.log(msg);
|
|
||||||
console.log(msg?.content?.['m.relates_to']?.rel_type);
|
|
||||||
console.log(msg?.content?.['m.relates_to']?.event_id);
|
|
||||||
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 ? msg?.content?.['m.relates_to']?.event_id : null) || msg.eventId;
|
||||||
if(threadParent) {
|
if(threadParent) {
|
||||||
content["m.relates_to"] = {
|
content["m.relates_to"] = {
|
||||||
@ -190,6 +187,7 @@ module.exports = function(RED) {
|
|||||||
.then(function(e) {
|
.then(function(e) {
|
||||||
node.log("Message sent: " + payload);
|
node.log("Message sent: " + payload);
|
||||||
msg.eventId = e.event_id;
|
msg.eventId = e.event_id;
|
||||||
|
node.log(JSON.stringify(e));
|
||||||
node.send([msg, null]);
|
node.send([msg, null]);
|
||||||
})
|
})
|
||||||
.catch(function(e){
|
.catch(function(e){
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
const {RelationType} = require("matrix-js-sdk");
|
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");
|
||||||
@ -55,9 +55,9 @@ module.exports = function(RED) {
|
|||||||
this.url = this.credentials.url;
|
this.url = this.credentials.url;
|
||||||
this.autoAcceptRoomInvites = n.autoAcceptRoomInvites;
|
this.autoAcceptRoomInvites = n.autoAcceptRoomInvites;
|
||||||
this.e2ee = n.enableE2ee || false;
|
this.e2ee = n.enableE2ee || false;
|
||||||
|
|
||||||
this.globalAccess = n.global;
|
this.globalAccess = n.global;
|
||||||
this.initializedAt = new Date();
|
this.initializedAt = new Date();
|
||||||
|
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 be able to catch errors
|
||||||
node.register = function(consumerNode) {
|
node.register = function(consumerNode) {
|
||||||
@ -158,6 +158,8 @@ module.exports = function(RED) {
|
|||||||
// verificationMethods: ["m.sas.v1"]
|
// verificationMethods: ["m.sas.v1"]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
node.debug(`hasLazyLoadMembersEnabled=${node.matrixClient.hasLazyLoadMembersEnabled()}`);
|
||||||
|
|
||||||
// set globally if configured to do so
|
// set globally if configured to do so
|
||||||
if(this.globalAccess) {
|
if(this.globalAccess) {
|
||||||
this.context().global.set('matrixClient["'+this.userId+'"]', node.matrixClient);
|
this.context().global.set('matrixClient["'+this.userId+'"]', node.matrixClient);
|
||||||
@ -178,7 +180,7 @@ module.exports = function(RED) {
|
|||||||
stopClient();
|
stopClient();
|
||||||
if(node.globalAccess) {
|
if(node.globalAccess) {
|
||||||
try {
|
try {
|
||||||
node.context().global.delete('matrixClient["'+node.userId+'"]');
|
node.context().global.set('matrixClient["'+node.userId+'"]', undefined);
|
||||||
} catch(e){
|
} catch(e){
|
||||||
node.error(e.message, {});
|
node.error(e.message, {});
|
||||||
}
|
}
|
||||||
@ -192,15 +194,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");
|
||||||
return; // ignore paginated results
|
return; // ignore paginated results
|
||||||
}
|
}
|
||||||
if (!event.getSender() || event.getSender() === node.userId) {
|
|
||||||
return; // ignore our own messages
|
|
||||||
}
|
|
||||||
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");
|
||||||
return; // ignore old message (we only want live events)
|
return; // ignore old message (we only want live events)
|
||||||
}
|
}
|
||||||
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");
|
||||||
return; // skip events that occurred before our client initialized
|
return; // skip events that occurred before our client initialized
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,7 +251,7 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
node.log("Received" + (msg.encrypted ? ' encrypted' : '') +" timeline event [" + msg.type + "]: (" + room.name + ") " + event.getSender() + " :: " + msg.content.body + (toStartOfTimeline ? ' [PAGINATED]' : ''));
|
node.log(`Received ${msg.encrypted ? 'encrypted ' : ''}timeline event [${msg.type}]: (${room.name}) ${event.getSender()} :: ${msg.content.body} ${toStartOfTimeline ? ' [PAGINATED]' : ''}`);
|
||||||
node.emit("Room.timeline", event, room, toStartOfTimeline, removed, data, msg);
|
node.emit("Room.timeline", event, room, toStartOfTimeline, removed, data, msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -402,7 +404,7 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
node.log("Connecting to Matrix server...");
|
node.log("Connecting to Matrix server...");
|
||||||
await node.matrixClient.startClient({
|
await node.matrixClient.startClient({
|
||||||
initialSyncLimit: 8
|
initialSyncLimit: node.initialSyncLimit
|
||||||
});
|
});
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
node.error(error, {});
|
node.error(error, {});
|
||||||
@ -476,10 +478,15 @@ module.exports = function(RED) {
|
|||||||
const matrixClient = sdk.createClient({
|
const matrixClient = sdk.createClient({
|
||||||
baseUrl: baseUrl,
|
baseUrl: baseUrl,
|
||||||
deviceId: deviceId,
|
deviceId: deviceId,
|
||||||
|
timelineSupport: true,
|
||||||
localTimeoutMs: '30000',
|
localTimeoutMs: '30000',
|
||||||
request
|
request
|
||||||
});
|
});
|
||||||
|
|
||||||
|
new TimelineWindow()
|
||||||
|
|
||||||
|
matrixClient.timelineSupport = true;
|
||||||
|
|
||||||
matrixClient.login(
|
matrixClient.login(
|
||||||
'm.login.password', {
|
'm.login.password', {
|
||||||
user: userId,
|
user: userId,
|
||||||
|
@ -105,7 +105,7 @@
|
|||||||
|
|
||||||
<script type="text/html" data-help-name="matrix-upload-file">
|
<script type="text/html" data-help-name="matrix-upload-file">
|
||||||
<h3>Details</h3>
|
<h3>Details</h3>
|
||||||
<p>This node will send a file to a Matrix chat room. Supports direct linking to a File In node.</p>
|
<p>Upload a file to the matrix homeserver. Returns a payload that can then be chained to a Send Message node to post the file to a room, or you can use the mxc_url to update a user or room avatar.</p>
|
||||||
|
|
||||||
<h3>Inputs</h3>
|
<h3>Inputs</h3>
|
||||||
<dl class="message-properties">
|
<dl class="message-properties">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user