Compare commits

...

13 Commits

Author SHA1 Message Date
skylord123 fd605005d1 Closes #99
- matrix-server-config now auto populates with first option
2023-10-21 19:47:12 -06:00
skylord123 85de450a1a Merge pull request #98 from Skylar-Tech/97-room-settings
97 room settings
2023-10-21 19:43:29 -06:00
skylord123 e7e0f2967b Issue #97 Room Settings
- Remove unused returnValues config option for Room State Events node
2023-10-21 19:39:32 -06:00
skylord123 611e23b845 Issue #97 Room Settings
- Room Settings node renamed to Room State Events
- Room State Events node allows configuring inputs/outputs from config
- Fix bug with various nodes allowing execution even though matrix server isn't connected
- Replace deprecated matrixClient.setGlobalErrorOnUnknownDevices method
- Update docs for new Room State Events node
2023-10-21 19:33:44 -06:00
skylord123 9d050a0d44 Issue #97 Room Settings
- fix join_allow_rules for Room Setting node not getting correctly
- update Room Setting docs
2023-10-15 14:45:16 -06:00
skylord123 c833a40a84 Issue #97 Room Settings
- Can set room name, topic, and avatar
- Can get name, topic, avatar, encrypted, power_levels, aliases, guest_access, join_rule, and join_allow_rules
2023-10-15 04:17:12 -06:00
skylord123 0e755bc350 - Remove console.log usage 2023-10-14 23:22:38 -06:00
skylord123 c920dd12cb - Fix error with matrix-synapse-register node
- Ensure matrix-server-config's register/deregister methods are always available
2023-10-14 22:26:29 -06:00
bvmensvoort 9661922f78 Pass msg object where possible
As described on https://nodered.org/docs/user-guide/writing-functions#handling-errors
2023-10-14 21:32:46 -06:00
bvmensvoort 20c7182511 Make errors catchable and (de)register at config node of all nodes 2023-10-14 21:32:46 -06:00
bvmensvoort f48ba74a72 Make errors of config node catchable via a catch node 2023-10-14 21:32:46 -06:00
bvmensvoort 124a0cba34 (de)Register consumer nodes at config node
In order for error messages to be catchable
2023-10-14 21:32:46 -06:00
bvmensvoort 8ca11f36d8 Make errors of nodes catchable by a catch node 2023-10-14 21:32:46 -06:00
44 changed files with 846 additions and 109 deletions
+3 -2
View File
@@ -32,13 +32,14 @@
"matrix-crypt-file": "src/matrix-crypt-file.js",
"matrix-room-kick": "src/matrix-room-kick.js",
"matrix-room-ban": "src/matrix-room-ban.js",
"matrix-room-users": "src/matrix-room-users.js",
"matrix-room-state-events": "src/matrix-room-state-events.js",
"matrix-synapse-users": "src/matrix-synapse-users.js",
"matrix-synapse-register": "src/matrix-synapse-register.js",
"matrix-synapse-create-edit-user": "src/matrix-synapse-create-edit-user.js",
"matrix-synapse-deactivate-user": "src/matrix-synapse-deactivate-user.js",
"matrix-synapse-join-room": "src/matrix-synapse-join-room.js",
"matrix-whois-user": "src/matrix-whois-user.js",
"matrix-room-users": "src/matrix-room-users.js"
"matrix-whois-user": "src/matrix-whois-user.js"
}
},
"engines": {
+1 -1
View File
@@ -8,7 +8,7 @@
outputs: 2,
defaults: {
name: { value: null },
server: { value: "", type: "matrix-server-config" }
server: { type: "matrix-server-config" }
},
label: function() {
return this.name || "Create Room";
+8 -2
View File
@@ -8,9 +8,10 @@ module.exports = function(RED) {
this.server = RED.nodes.getNode(n.server);
if(!this.server) {
node.error('Server must be configured on the node.');
node.error('Server must be configured on the node.', {});
return;
}
node.server.register(node);
this.encodeUri = function(pathTemplate, variables) {
for (const key in variables) {
@@ -41,8 +42,9 @@ module.exports = function(RED) {
}
if(!node.server.isConnected()) {
node.error("Matrix server connection is currently closed");
node.error("Matrix server connection is currently closed", msg);
node.send([null, msg]);
return;
}
if(!msg.payload) {
@@ -64,6 +66,10 @@ module.exports = function(RED) {
node.send([null, msg]);
});
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-create-room", MatrixCreateRoom);
}
+4 -4
View File
@@ -12,22 +12,22 @@ module.exports = function(RED) {
const { got } = await import('got');
if(!msg.type) {
node.error('msg.type is required.');
node.error('msg.type is required.', msg);
return;
}
if(!msg.content) {
node.error('msg.content is required.');
node.error('msg.content is required.', msg);
return;
}
if(!msg.content.file) {
node.error('msg.content.file is required.');
node.error('msg.content.file is required.', msg);
return;
}
if(!msg.url) {
node.error('msg.url is required.');
node.error('msg.url is required.', msg);
return;
}
+1 -1
View File
@@ -8,7 +8,7 @@
outputs:2,
defaults: {
name: { value: null },
server: { value: "", type: "matrix-server-config" },
server: { type: "matrix-server-config" },
roomId: { value: null },
reason: { value: "" },
},
+7 -2
View File
@@ -13,6 +13,7 @@ module.exports = function(RED) {
node.warn("No configuration node");
return;
}
node.server.register(node);
node.status({ fill: "red", shape: "ring", text: "disconnected" });
@@ -27,7 +28,7 @@ module.exports = function(RED) {
node.on('input', function(msg) {
if(!msg.eventId) {
node.error("eventId is missing");
node.error("eventId is missing", msg);
node.send([null, msg])
return;
}
@@ -38,7 +39,7 @@ module.exports = function(RED) {
}
if(!node.server.isConnected()) {
node.error("Matrix server connection is currently closed");
node.error("Matrix server connection is currently closed", msg);
node.send([null, msg]);
return;
}
@@ -70,6 +71,10 @@ module.exports = function(RED) {
node.send([null, msg]);
});
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-delete-event",MatrixDeleteEvent);
}
+1 -1
View File
@@ -8,7 +8,7 @@
outputs: 2,
defaults: {
name: { value: null },
server: { value: "", type: "matrix-server-config" },
server: { type: "matrix-server-config" },
roomId: { value: null },
},
label: function() {
+10 -4
View File
@@ -9,9 +9,10 @@ module.exports = function(RED) {
this.roomId = n.roomId;
if(!this.server) {
node.error('Server must be configured on the node.');
node.error('Server must be configured on the node.', {});
return;
}
node.server.register(node);
this.encodeUri = function(pathTemplate, variables) {
for (const key in variables) {
@@ -37,18 +38,19 @@ module.exports = function(RED) {
node.on("input", function (msg) {
if (! node.server || ! node.server.matrixClient) {
node.error("No matrix server selected");
node.error("No matrix server selected", msg);
return;
}
if(!node.server.isConnected()) {
node.error("Matrix server connection is currently closed");
node.error("Matrix server connection is currently closed", msg);
node.send([null, msg]);
return;
}
msg.topic = node.roomId || msg.topic;
if(!msg.topic) {
node.error("room must be defined in either msg.topic or in node config");
node.error("room must be defined in either msg.topic or in node config", msg);
return;
}
@@ -64,6 +66,10 @@ module.exports = function(RED) {
node.send([null, msg]);
});
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-invite-room", MatrixInviteRoom);
}
+1 -1
View File
@@ -8,7 +8,7 @@
outputs:2,
defaults: {
name: { value: null },
server: { value: "", type: "matrix-server-config" }
server: { type: "matrix-server-config" }
},
label: function() {
return this.name || "Join Room";
+10 -4
View File
@@ -11,6 +11,7 @@ module.exports = function(RED) {
node.warn("No configuration node");
return;
}
node.server.register(node);
node.status({ fill: "red", shape: "ring", text: "disconnected" });
@@ -24,17 +25,18 @@ module.exports = function(RED) {
node.on("input", function (msg) {
if (! node.server || ! node.server.matrixClient) {
node.error("No matrix server selected");
node.error("No matrix server selected", msg);
return;
}
if(!node.server.isConnected()) {
node.error("Matrix server connection is currently closed");
node.error("Matrix server connection is currently closed", msg);
node.send([null, msg]);
return;
}
if(!msg.topic) {
node.error("Room must be specified in msg.topic");
node.error("Room must be specified in msg.topic", msg);
return;
}
@@ -46,11 +48,15 @@ module.exports = function(RED) {
node.send([msg, null]);
})
.catch(function(e){
node.error("Error trying to join room " + msg.topic + ":" + e);
node.error("Error trying to join room " + msg.topic + ":" + e, msg);
msg.error = e;
node.send([null, msg]);
});
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-join-room", MatrixJoinRoom);
}
+1 -1
View File
@@ -8,7 +8,7 @@
outputs: 2,
defaults: {
name: { value: null },
server: { value: "", type: "matrix-server-config" },
server: { type: "matrix-server-config" },
roomId: { value: null },
},
label: function() {
+11 -5
View File
@@ -11,9 +11,10 @@ module.exports = function(RED) {
node.status({ fill: "red", shape: "ring", text: "disconnected" });
if (!node.server) {
node.error("No configuration node");
node.error("No configuration node", {});
return;
}
node.server.register(node);
node.server.on("disconnected", function(){
node.status({ fill: "red", shape: "ring", text: "disconnected" });
@@ -25,18 +26,19 @@ module.exports = function(RED) {
node.on('input', function(msg) {
if (! node.server || ! node.server.matrixClient) {
node.error("No matrix server selected");
node.error("No matrix server selected", msg);
return;
}
if(!msg.topic) {
node.error('No room provided in msg.topic');
node.error('No room provided in msg.topic', msg);
return;
}
if(!node.server.isConnected()) {
node.error("Matrix server connection is currently closed");
node.error("Matrix server connection is currently closed", msg);
node.send([null, msg]);
return;
}
try {
@@ -44,11 +46,15 @@ module.exports = function(RED) {
node.server.matrixClient.leave(msg.topic);
node.send([msg, null]);
} catch(e) {
node.error("Failed to leave room " + msg.topic + ": " + e);
node.error("Failed to leave room " + msg.topic + ": " + e, msg);
msg.payload = e;
node.send([null, msg]);
}
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-leave-room", MatrixLeaveRoom);
}
+1 -1
View File
@@ -8,7 +8,7 @@
outputs:2,
defaults: {
name: { value: null },
server: { value: "", type: "matrix-server-config" },
server: { type: "matrix-server-config" },
roomId: { value: null },
reaction: { value: null }
},
+11 -5
View File
@@ -13,6 +13,7 @@ module.exports = function(RED) {
node.warn("No configuration node");
return;
}
node.server.register(node);
node.status({ fill: "red", shape: "ring", text: "disconnected" });
@@ -26,30 +27,31 @@ module.exports = function(RED) {
node.on("input", function (msg) {
if (!node.server || !node.server.matrixClient) {
node.error("No matrix server selected");
node.error("No matrix server selected", msg);
return;
}
if(!node.server.isConnected()) {
node.error("Matrix server connection is currently closed");
node.error("Matrix server connection is currently closed", msg);
node.send([null, msg]);
return;
}
msg.topic = node.roomId || msg.topic;
if(!msg.topic) {
node.error("Room must be specified in msg.topic or in configuration");
node.error("Room must be specified in msg.topic or in configuration", msg);
return;
}
let payload = n.reaction || msg.payload;
if(!payload) {
node.error('msg.payload must be defined or the reaction configured on the node.');
node.error('msg.payload must be defined or the reaction configured on the node.', msg);
return;
}
let eventId = msg.referenceEventId || msg.eventId;
if(!eventId) {
node.error('Either msg.referenceEventId or msg.eventId must be defined to react to a message.');
node.error('Either msg.referenceEventId or msg.eventId must be defined to react to a message.', msg);
return;
}
@@ -75,6 +77,10 @@ module.exports = function(RED) {
node.send([null, msg]);
});
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-react", MatrixReact);
}
+1 -1
View File
@@ -8,7 +8,7 @@
outputs:1,
defaults: {
name: { value: null },
server: { value: "", type: "matrix-server-config" },
server: { type: "matrix-server-config" },
roomId: {"value": null},
acceptText: {"value": true},
acceptEmotes: {"value": true},
+6 -1
View File
@@ -21,9 +21,10 @@ module.exports = function(RED) {
node.status({ fill: "red", shape: "ring", text: "disconnected" });
if (!node.server) {
node.error("No configuration node");
node.error("No configuration node", {});
return;
}
node.server.register(node);
node.server.on("disconnected", function(){
node.status({ fill: "red", shape: "ring", text: "disconnected" });
@@ -149,6 +150,10 @@ module.exports = function(RED) {
node.send(msg);
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-receive", MatrixReceiveMessage);
}
+1 -1
View File
@@ -8,7 +8,7 @@
outputs:2,
defaults: {
name: { value: null },
server: { value: "", type: "matrix-server-config" },
server: { type: "matrix-server-config" },
roomId: { value: null },
reason: { value: null }
},
+11 -5
View File
@@ -13,6 +13,7 @@ module.exports = function(RED) {
node.warn("No configuration node");
return;
}
node.server.register(node);
node.status({ fill: "red", shape: "ring", text: "disconnected" });
@@ -26,23 +27,24 @@ module.exports = function(RED) {
node.on("input", function (msg) {
if (! node.server || ! node.server.matrixClient) {
node.error("No matrix server selected");
node.error("No matrix server selected", msg);
return;
}
if(!node.server.isConnected()) {
node.error("Matrix server connection is currently closed");
node.error("Matrix server connection is currently closed", msg);
node.send([null, msg]);
return;
}
msg.topic = node.roomId || msg.topic;
if(!msg.topic) {
node.error("Room must be specified in msg.topic or in configuration");
node.error("Room must be specified in msg.topic or in configuration", msg);
return;
}
if(!msg.userId) {
node.error("msg.userId was not set.");
node.error("msg.userId was not set.", msg);
return;
}
@@ -53,11 +55,15 @@ module.exports = function(RED) {
node.send([msg, null]);
})
.catch(function(e){
node.error("Error trying to ban " + msg.userId + " from " + msg.topic);
node.error("Error trying to ban " + msg.userId + " from " + msg.topic, msg);
msg.error = e;
node.send([null, msg]);
});
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-room-ban", MatrixBan);
}
+1 -1
View File
@@ -8,7 +8,7 @@
outputs: 1,
defaults: {
name: { value: null },
server: { value: "", type: "matrix-server-config" },
server: { type: "matrix-server-config" },
roomId: { value: null },
},
label: function() {
+6 -1
View File
@@ -9,9 +9,10 @@ module.exports = function(RED) {
this.roomId = n.roomId;
if(!this.server) {
node.error('Server must be configured on the node.');
node.error('Server must be configured on the node.', {});
return;
}
node.server.register(node);
node.status({ fill: "red", shape: "ring", text: "disconnected" });
@@ -26,6 +27,10 @@ module.exports = function(RED) {
node.server.on("Room.invite", async function(msg) {
node.send(msg);
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-room-invite", MatrixRoomInvite);
}
+1 -1
View File
@@ -8,7 +8,7 @@
outputs:2,
defaults: {
name: { value: null },
server: { value: "", type: "matrix-server-config" },
server: { type: "matrix-server-config" },
roomId: { value: null },
reason: { value: null }
},
+11 -5
View File
@@ -13,6 +13,7 @@ module.exports = function(RED) {
node.warn("No configuration node");
return;
}
node.server.register(node);
node.status({ fill: "red", shape: "ring", text: "disconnected" });
@@ -26,23 +27,24 @@ module.exports = function(RED) {
node.on("input", function (msg) {
if (! node.server || ! node.server.matrixClient) {
node.error("No matrix server selected");
node.error("No matrix server selected", msg);
return;
}
if(!node.server.isConnected()) {
node.error("Matrix server connection is currently closed");
node.error("Matrix server connection is currently closed", msg);
node.send([null, msg]);
return;
}
msg.topic = node.roomId || msg.topic;
if(!msg.topic) {
node.error("Room must be specified in msg.topic or in configuration");
node.error("Room must be specified in msg.topic or in configuration", msg);
return;
}
if(!msg.userId) {
node.error("msg.userId was not set.");
node.error("msg.userId was not set.", msg);
return;
}
@@ -53,11 +55,15 @@ module.exports = function(RED) {
node.send([msg, null]);
})
.catch(function(e){
node.error("Error trying to kick " + msg.userId + " from " + msg.topic);
node.error("Error trying to kick " + msg.userId + " from " + msg.topic, msg);
msg.error = e;
node.send([null, msg]);
});
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-room-kick", MatrixKick);
}
+342
View File
@@ -0,0 +1,342 @@
<script type="text/html" data-template-name="matrix-room-state-events">
<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-user"></i> Matrix Server Config</label>
<input type="text" id="node-input-server">
</div>
<div class="form-row">
<label for="node-input-roomId"><i class="fa fa-comments"></i> Room ID</label>
<input type="text" id="node-input-roomId" placeholder="msg.topic">
<pre class="form-tips" id="node-input-roomId-error" style="color: #721c24;background-color: #f8d7da;border-color: #f5c6cb;margin-bottom: 12px;margin-top: 12px;display:none;"></pre>
</div>
<div class="form-row" style="margin-bottom:0;">
<label><i class="fa fa-list"></i> <span data-i18n="change.label.rules"></span></label>
</div>
<div class="form-row node-input-rule-container-row">
<ol id="node-input-rule-container"></ol>
</div>
<script type="text/javascript">
$(function(){
$("#node-input-roomId").on("keyup", function() {
if($(this).val() && !$(this).val().startsWith("!")) {
$("#node-input-roomId-error").html(`Room IDs start with exclamation point "!"<br />Example: !OGEhHVWSdvArJzumhm:matrix.org`).show();
} else {
$("#node-input-roomId-error").hide();
}
}).trigger('keyup');
});
</script>
</script>
<script type="text/html" data-help-name="matrix-room-state-events">
<h3>Details</h3>
<p>
Set and Get a list of room state events for a given room. Allows you to set/get room name, topic, avatar, etc.
</p>
<h3>Inputs</h3>
<dl class="message-properties">
<dt class="optional">msg.topic
<span class="property-type">string | null</span>
</dt>
<dd> The room to set/get settings for.</dd>
<dt class="optional">dynamic
<span class="property-type">string|object</span>
</dt>
<dd> You configure what room state events in the node configuration. <code style="white-space: normal;">m.room.name</code>, <code style="white-space: normal;">m.room.avatar</code>, and <code style="white-space: normal;">m.room.guest_access</code> allow you to pass a string to set their value but all other room state events will require the full content object (find this by referencing the <a href="https://spec.matrix.org/latest/client-server-api" target="_blank">Matrix Client-Server docs</a>)</dd>
</dl>
<h3>Outputs</h3>
<ol class="node-ports">
<li>Success
<dl class="message-properties">
<dt>msg <span class="property-type">object</span></dt>
<dd>Original message object with modifications based on config.</dd>
</dl>
<dl class="message-properties">
<dt>msg.setter_errors <span class="property-type">undefined|object</span></dt>
<dd>Returned if setting a room state event failed. The key of the object is the room state event type and the value is the error that occurred.</dd>
</dl>
<dl class="message-properties">
<dt>msg.getter_errors <span class="property-type">undefined|object</span></dt>
<dd>Returned if getting a room state event failed. The key of the object is the room state event type and the value is the error that occurred. Note that you will get an error if you try getting a room state event that doesn't exist (such as fetching avatar on a room that doesn't have one).</dd>
</dl>
<dt class="optional">dynamic
<span class="property-type">string|object</span>
</dt>
<dd> You configure what room state events to output in the node configuration. <code style="white-space: normal;">m.room.name</code>, <code style="white-space: normal;">m.room.avatar</code>, and <code style="white-space: normal;">m.room.guest_access</code> will come back as strings otherwise you will get the full content object of the event (find this by referencing the <a href="https://spec.matrix.org/latest/client-server-api" target="_blank">Matrix Client-Server docs</a>)</dd>
</li>
</ol>
</script>
<script type="text/javascript">
(function(){
var roomEventTypeOptions = [
{ value: "m.room.name", label: "m.room.name"},
{ value: "m.room.topic", label: "m.room.topic"},
{ value: "m.room.avatar", label: "m.room.avatar"},
{ value: "m.room.power_levels", label: "m.room.power_levels"},
{ value: "m.room.guest_access", label: "m.room.guest_access"},
{ value: "m.room.join_rules", label: "m.room.join_rules"},
{ value: "m.room.canonical_alias", label: "m.room.canonical_alias"}
];
var defaultRules = [{
t: "set",
p: roomEventTypeOptions[0].value,
to: "payload",
tot: "msg"
}];
function isInvalidProperty(v,vt) {
if (/msg|flow|global/.test(vt)) {
if (!RED.utils.validatePropertyExpression(v)) {
return "Invalid property: " + v;
}
} else if (vt === "jsonata") {
try{ jsonata(v); } catch(e) {
return "Invalid expression: " + e.message;
}
} else if (vt === "json") {
try{ JSON.parse(v); } catch(e) {
return "Invalid JSON data: " + e.message;
}
}
return false;
}
RED.nodes.registerType('matrix-room-state-events',{
category: 'matrix',
color: '#00b7ca',
icon: "matrix.png",
outputLabels: ["success", "error"],
inputs:1,
outputs:2,
defaults: {
name: { value: null },
server: { type: "matrix-server-config" },
roomId: { value: null },
reason: { value: null },
rules: {
value: defaultRules,
validate: function(rules, opt) {
let msg;
const errors = []
if (!rules || rules.length === 0) { return true }
for (let i=0;i<rules.length;i++) {
const opt = { label: "Rule"+' '+(i+1) }
const r = rules[i];
if (r.t === 'set' || r.t === 'get') {
if ((msg = isInvalidProperty(r.p,r.pt)) !== false) {
return msg;
}
if ((msg = isInvalidProperty(r.to,r.tot)) !== false) {
return msg;
}
}
}
return errors.length ? errors : true;
}
},
},
oneditprepare: function() {
var set = "Set";
var to = "to the value";
var toValueLabel = "to the property";
var search = this._("change.action.search");
var replace = this._("change.action.replace");
var regex = this._("change.label.regex");
function createPropertyValue(row2_1, row2_2, type, defaultType) {
var propValInput = $('<input/>',{class:"node-input-rule-property-value",type:"text"})
.appendTo(row2_1)
.typedInput({
default: defaultType || (type === 'set' ? 'str' : 'msg'),
types: (type === 'set' ? ['msg','flow','global','str','num','bool','json','bin','date','jsonata'] : ['msg', 'flow', 'global'])
});
var dcLabel = $('<label style="padding-left: 130px;"></label>').appendTo(row2_2);
propValInput.on("change", function(evt,type,val) {
row2_2.toggle(type === "msg" || type === "flow" || type === "global" || type === "env");
})
return [propValInput];
}
$('#node-input-rule-container').css('min-height','150px').css('min-width','450px').editableList({
addItem: function(container,i,opt) {
var rule = opt;
if (!rule.hasOwnProperty('t')) {
rule = {t:"set",p:roomEventTypeOptions[0].value,to:"payload",tot:"msg"};
}
if (rule.t === "set" && !rule.tot) {
if (rule.to.indexOf("msg.") === 0 && !rule.tot) {
rule.to = rule.to.substring(4);
rule.tot = "msg";
} else {
rule.tot = "str";
}
}
container.css({
overflow: 'hidden',
whiteSpace: 'nowrap'
});
let fragment = document.createDocumentFragment();
var row1 = $('<div/>',{style:"display:flex; align-items: center"}).appendTo(fragment);
var row2 = $('<div/>',{style:"margin-top:8px;"}).appendTo(fragment);
var row3 = $('<div/>',{style:"margin-top:8px;"}).appendTo(fragment);
var row4 = $('<div/>',{style:"display:flex;margin-top:8px;align-items: baseline"}).appendTo(fragment);
var selectField = $('<select/>',{class:"node-input-rule-type",style:"width:110px; margin-right:10px;"}).appendTo(row1);
var selectOptions = [
{v:"set",l:"Set"},
{v:"get",l:"Get"}
];
for (var x=0; x<selectOptions.length; x++) {
selectField.append($("<option></option>").val(selectOptions[x].v).text(selectOptions[x].l));
}
var propertyName = $('<input/>',{class:"node-input-rule-property-name",type:"text"})
.appendTo(row1)
.autoComplete({
minLength:0,
search: function(val) {
if(!val) {
return roomEventTypeOptions.sort(function(A,B){return A.i-B.i});
}
var matches = [];
roomEventTypeOptions.map((x) => x.value).forEach(v => {
var i = v.toLowerCase().indexOf(val.toLowerCase());
if (i > -1) {
matches.push({
value: v,
label: v,
i: i
})
}
});
matches.sort(function(A,B){return A.i-B.i})
return matches
}
})
.on('focus', function(evt){
// following is a fix so autocomplete will show list on focus
if(!evt.isTrigger) {
evt.stopPropagation();
$(this).trigger("keyup.red-ui-autoComplete");
}
}).on("keyup", function(evt) {
// following allows autocomplete to display even when backspace/delete is used
if (evt.keyCode === 8 || evt.keyCode === 46) {
evt.stopPropagation();
$(this).trigger("keyup.red-ui-autoComplete");
}
});
var row2_1 = $('<div/>', {style:"display:flex;align-items: baseline"}).appendTo(row2);
$('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
.text(toValueLabel)
.appendTo(row2_1);
var row2_2 = $('<div/>', {style:"margin-top: 4px;"}).appendTo(row2);
var row3_1 = $('<div/>', {style:"display:flex;align-items: baseline"}).appendTo(row3);
$('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
.text(search)
.appendTo(row3_1);
var row3_2 = $('<div/>',{style:"display:flex;margin-top:8px;align-items: baseline"}).appendTo(row3);
$('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
.text(replace)
.appendTo(row3_2);
$('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
.text(to)
.appendTo(row4);
let propertyValue = null;
let fromValue = null;
let toValue = null;
selectField.on("change", function() {
var type = $(this).val();
if (propertyValue) {
propertyValue.typedInput('hide');
}
if (fromValue) {
fromValue.typedInput('hide');
}
if (toValue) {
toValue.typedInput('hide');
}
if (!propertyValue) {
var parts = createPropertyValue(row2_1, row2_2, type);
propertyValue = parts[0];
} else {
propertyValue.typedInput('types', (type === 'set' ? ['msg','flow','global','str','num','bool','json','bin','date','jsonata','env'] : ['msg', 'flow', 'global']));
}
propertyValue.typedInput('show');
row2.show();
row3.hide();
row4.hide();
});
selectField.val(rule.t);
propertyName.val(rule.p);
if (rule.t === "set" || rule.t === "get") {
var parts = createPropertyValue(row2_1, row2_2, rule.t, rule.tot);
propertyValue = parts[0];
propertyValue.typedInput('value',rule.to);
}
selectField.change();
container[0].appendChild(fragment);
},
removable: true,
sortable: true
});
for (var i=0; i<this.rules.length; i++) {
var rule = this.rules[i];
$("#node-input-rule-container").editableList('addItem',rule);
}
},
oneditsave: function() {
var rules = $("#node-input-rule-container").editableList('items');
var node = this;
node.rules= [];
rules.each(function(i) {
var rule = $(this);
var type = rule.find(".node-input-rule-type").val();
var r = {
t:type,
p:rule.find(".node-input-rule-property-name").val(),
to:rule.find(".node-input-rule-property-value").typedInput('value'),
tot:rule.find(".node-input-rule-property-value").typedInput('type')
};
node.rules.push(r);
});
},
oneditresize: function(size) {
var rows = $("#dialog-form>div:not(.node-input-rule-container-row)");
var height = size.height;
for (var i=0; i<rows.length; i++) {
height -= $(rows[i]).outerHeight(true);
}
var editorRow = $("#dialog-form>div.node-input-rule-container-row");
height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
height += 16;
$("#node-input-rule-container").editableList('height',height);
},
label: function() {
return this.name || "Room State Events";
},
paletteLabel: 'Room State Events'
});
})();
</script>
+272
View File
@@ -0,0 +1,272 @@
module.exports = function(RED) {
function MatrixRoomSettings(n) {
RED.nodes.createNode(this, n);
var node = this;
this.name = n.name;
this.server = RED.nodes.getNode(n.server);
this.roomId = n.roomId;
this.rules = n.rules;
if (!node.server) {
node.warn("No configuration node");
return;
}
node.server.register(node);
node.status({ fill: "red", shape: "ring", text: "disconnected" });
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) {
msg.error = "No matrix server selected";
node.error(msg.error, msg);
node.send([null, msg]);
return;
}
if(!node.server.isConnected()) {
msg.error = "Matrix server connection is currently closed";
node.error(msg.error, msg);
node.send([null, msg]);
return;
}
msg.topic = node.roomId || msg.topic;
if(!msg.topic) {
msg.error = "Room must be specified in msg.topic or in configuration";
node.error(msg.error, msg);
node.send([null, msg]);
return;
}
let getterErrors = {},
setterErrors = {};
if(!Array.isArray(node.rules) || !node.rules.length) {
node.warn("No rules configured, skipping", msg);
return msg;
}
function getToValue(msg, rule) {
var value = rule.to;
if (rule.tot === 'json') {
try {
value = JSON.parse(rule.to);
} catch(e) {
throw new Error("Invalid JSON");
}
} else if (rule.tot === 'bin') {
try {
value = Buffer.from(JSON.parse(rule.to))
} catch(e) {
throw new Error("Invalid Binary");
}
}
if (rule.tot === "msg") {
value = RED.util.getMessageProperty(msg,rule.to);
} else if ((rule.tot === 'flow') || (rule.tot === 'global')) {
RED.util.evaluateNodeProperty(rule.to, rule.tot, node, msg, (err,value) => {
if (err) {
throw new Error("Invalid value evaluation");
} else {
return value;
}
});
return
} else if (rule.tot === 'date') {
value = Date.now();
} else if (rule.tot === 'jsonata') {
RED.util.evaluateJSONataExpression(rule.to,msg, (err, value) => {
if (err) {
throw new Error("Invalid expression");
} else {
return value;
}
});
return;
}
return value;
}
function setToValue(value, rule) {
if(rule.tot === 'global' || rule.tot === 'flow') {
var contextKey = RED.util.parseContextStore(rule.to);
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()[rule.tot];
var callback = err => {
if (err) {
node.error(err, msg);
getterErrors[rule.p] = err.message;
}
}
target.set(contextKey.key, value, contextKey.store, callback);
} else if(rule.tot === 'msg') {
if (!RED.util.setMessageProperty(msg, rule.to, value)) {
node.warn(RED._("change.errors.no-override",{property:rule.to}));
}
}
}
for(let rule of node.rules) {
// [
// {
// "t": "set",
// "p": "m.room.topic",
// "to": "asdf",
// "tot": "str"
// }, ...
// ]
let cachedGetters = {};
if(rule.t === 'set') {
let value;
try {
value = getToValue(msg, rule);
switch(rule.p) {
case "m.room.name":
await node.server.matrixClient.sendStateEvent(
msg.topic,
"m.room.name",
typeof value === "string"
? { name: value }
: value);
break;
case "m.room.topic":
if(typeof value === "string") {
await node.server.matrixClient.setRoomTopic(msg.topic, value);
} else {
await node.server.matrixClient.sendStateEvent(
msg.topic,
"m.room.topic",
value
);
}
break;
case "m.room.avatar":
await node.server.matrixClient.sendStateEvent(
msg.topic,
"m.room.avatar",
typeof value === "string"
? { "url": value }
: value,
"");
break;
case "m.room.power_levels":
if(typeof value !== 'object') {
setterErrors[rule.p] = "m.room.power_levels content must be object";
} else {
await node.server.matrixClient.sendStateEvent(
msg.topic,
"m.room.power_levels",
value,
"");
}
break;
case "m.room.guest_access":
await node.server.matrixClient.sendStateEvent(
msg.topic,
"m.room.guest_access",
typeof value === "string"
? { "guest_access": value }
: value,
"");
break;
case "m.room.join_rules":
if(typeof value !== 'object') {
setterErrors[rule.p] = "m.room.join_rules content must be object";
} else {
await node.server.matrixClient.sendStateEvent(
msg.topic,
"m.room.join_rules",
value,
"");
}
break;
case "m.room.canonical_alias":
if(typeof value !== 'object') {
setterErrors[rule.p] = "m.room.canonical_alias content must be object";
} else {
await node.server.matrixClient.sendStateEvent(
msg.topic,
"m.room.canonical_alias",
value,
"");
}
break;
default:
if(typeof value !== 'object') {
setterErrors[rule.p] = "Custom event content must be object";
} else {
await node.server.matrixClient.sendStateEvent(
msg.topic,
rule.p,
value,
"");
}
break;
}
} catch(e) {
setterErrors[rule.p] = e.message;
}
} else if(rule.t === 'get') {
let value;
if(cachedGetters.hasOwnProperty(rule.p)) {
value = cachedGetters[rule.p];
} else {
try {
// we may want to fetch from local storage in the future, this is how to do that
// const room = this.getRoom(roomId);
// const ev = room.currentState.getStateEvents(EventType.RoomEncryption, "");
value = await node.server.matrixClient.getStateEvent(msg.topic, rule.p, "");
switch(rule.p) {
case "m.room.name":
value = value?.name
break;
case "m.room.topic":
value = value?.topic
break;
case "m.room.avatar":
value = value?.url
break;
case "m.room.guest_access":
value = value?.guest_access;
break;
}
setToValue(value, rule);
} catch(e) {
getterErrors[rule.p] = e;
}
}
}
}
if(Object.keys(setterErrors).length) {
msg.setter_errors = setterErrors;
}
if(Object.keys(getterErrors).length) {
msg.getter_errors = getterErrors;
}
node.send([msg, null]);
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-room-state-events", MatrixRoomSettings);
}
+1 -1
View File
@@ -8,7 +8,7 @@
outputs:2,
defaults: {
name: { value: null },
server: { value: "", type: "matrix-server-config" },
server: { type: "matrix-server-config" },
roomId: { value: "" }
},
label: function() {
+8 -2
View File
@@ -13,6 +13,7 @@ module.exports = function(RED) {
node.warn("No configuration node");
return;
}
node.server.register(node);
node.status({ fill: "red", shape: "ring", text: "disconnected" });
@@ -31,13 +32,14 @@ module.exports = function(RED) {
}
if(!node.server.isConnected()) {
node.error("Matrix server connection is currently closed");
node.error("Matrix server connection is currently closed", msg);
node.send([null, msg]);
return;
}
let roomId = node.roomId || msg.topic;
if(!roomId) {
node.error("msg.topic is required. Specify in the input or configure the room ID on the node.");
node.error("msg.topic is required. Specify in the input or configure the room ID on the node.", msg);
return;
}
@@ -65,6 +67,10 @@ module.exports = function(RED) {
node.send([null, msg]);
});
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-room-users", MatrixRoomUsers);
}
+1 -1
View File
@@ -8,7 +8,7 @@
outputs:2,
defaults: {
name: { value: null },
server: { value: "", type: "matrix-server-config" },
server: { type: "matrix-server-config" },
roomId: { value: null },
contentType: { value: null }
},
+8 -2
View File
@@ -13,6 +13,7 @@ module.exports = function(RED) {
node.warn("No configuration node");
return;
}
node.server.register(node);
node.status({ fill: "red", shape: "ring", text: "disconnected" });
@@ -31,8 +32,9 @@ module.exports = function(RED) {
}
if(!node.server.isConnected()) {
node.error("Matrix server connection is currently closed");
node.error("Matrix server connection is currently closed", msg);
node.send([null, msg]);
return;
}
msg.topic = node.roomId || msg.topic;
@@ -57,7 +59,7 @@ module.exports = function(RED) {
}
if(!msg.payload) {
node.error('msg.payload is required');
node.error('msg.payload is required', msg);
return;
}
@@ -94,6 +96,10 @@ module.exports = function(RED) {
node.send([null, msg]);
});
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-send-file", MatrixSendFile);
}
+1 -1
View File
@@ -8,7 +8,7 @@
outputs:2,
defaults: {
name: { value: null },
server: { value: "", type: "matrix-server-config" },
server: { type: "matrix-server-config" },
roomId: { value: null },
contentType: { value: null }
},
+8 -2
View File
@@ -13,6 +13,7 @@ module.exports = function(RED) {
node.warn("No configuration node");
return;
}
node.server.register(node);
node.status({ fill: "red", shape: "ring", text: "disconnected" });
@@ -31,8 +32,9 @@ module.exports = function(RED) {
}
if(!node.server.isConnected()) {
node.error("Matrix server connection is currently closed");
node.error("Matrix server connection is currently closed", msg);
node.send([null, msg]);
return;
}
msg.topic = node.roomId || msg.topic;
@@ -57,7 +59,7 @@ module.exports = function(RED) {
}
if(!msg.payload) {
node.error('msg.payload is required');
node.error('msg.payload is required', msg);
return;
}
@@ -98,6 +100,10 @@ module.exports = function(RED) {
node.send([null, msg]);
});
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-send-image", MatrixSendImage);
}
+1 -1
View File
@@ -8,7 +8,7 @@
outputs:2,
defaults: {
name: { value: null },
server: { value: "", type: "matrix-server-config" },
server: { type: "matrix-server-config" },
roomId: { value: null },
message: { value: null },
messageType: { value: 'm.text' },
+9 -4
View File
@@ -54,6 +54,7 @@ module.exports = function(RED) {
node.warn("No configuration node");
return;
}
node.server.register(node);
node.status({ fill: "red", shape: "ring", text: "disconnected" });
@@ -71,7 +72,7 @@ module.exports = function(RED) {
if(msgType === 'msg.type') {
if(!msg.type) {
node.error("msg.type type is set to be passed in via msg.type but was not defined");
node.error("msg.type type is set to be passed in via msg.type but was not defined", msg);
return;
}
msgType = msg.type;
@@ -79,7 +80,7 @@ module.exports = function(RED) {
if(msgFormat === 'msg.format') {
if(!msg.format) {
node.error("Message format is set to be passed in via msg.format but was not defined");
node.error("Message format is set to be passed in via msg.format but was not defined", msg);
return;
}
msgFormat = msg.format;
@@ -91,7 +92,7 @@ module.exports = function(RED) {
}
if(!node.server.isConnected()) {
node.error("Matrix server connection is currently closed");
node.error("Matrix server connection is currently closed", msg);
node.send([null, msg]);
return;
}
@@ -104,7 +105,7 @@ module.exports = function(RED) {
let payload = n.message || msg.payload;
if(!payload) {
node.error('msg.payload must be defined or the message configured on the node.');
node.error('msg.payload must be defined or the message configured on the node.', msg);
return;
}
@@ -152,6 +153,10 @@ module.exports = function(RED) {
node.send([null, msg]);
});
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-send-message", MatrixSendImage);
}
+28 -20
View File
@@ -44,6 +44,7 @@ module.exports = function(RED) {
this.credentials = {};
}
this.users = {};
this.connected = null;
this.name = n.name;
this.userId = this.credentials.userId;
@@ -55,6 +56,14 @@ module.exports = function(RED) {
this.globalAccess = n.global;
this.initializedAt = new Date();
// Keep track of all consumers of this node to be able to catch errors
node.register = function(consumerNode) {
node.users[consumerNode.id] = consumerNode;
};
node.deregister = function(consumerNode) {
delete node.users[consumerNode.id];
};
if(!this.userId) {
node.log("Matrix connection failed: missing user ID in configuration.");
@@ -68,9 +77,9 @@ module.exports = function(RED) {
let retryStartTimeout = null;
if(!this.credentials.accessToken) {
node.error("Matrix connection failed: missing access token in configuration.");
node.error("Matrix connection failed: missing access token in configuration.", {});
} else if(!this.url) {
node.error("Matrix connection failed: missing server URL in configuration.");
node.error("Matrix connection failed: missing server URL in configuration.", {});
} else {
node.setConnected = async function(connected, cb) {
if (node.connected !== connected) {
@@ -88,7 +97,7 @@ module.exports = function(RED) {
device_id = this.matrixClient.getDeviceId();
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 {
if(!stored_device_id || stored_device_id !== device_id) {
node.log(`Saving Device ID (old:${stored_device_id} new:${device_id})`);
@@ -107,13 +116,13 @@ module.exports = function(RED) {
}).then(
function(response) {},
function(error) {
node.error("Failed to set device label: " + error);
node.error("Failed to set device label: " + error, {});
}
);
}
},
function(error) {
node.error("Failed to fetch device: " + error);
node.error("Failed to fetch device: " + error, {});
}
);
}
@@ -189,7 +198,7 @@ module.exports = function(RED) {
try {
await node.matrixClient.decryptEventIfNeeded(event);
} catch (error) {
node.error(error);
node.error(error, {});
return;
}
@@ -260,7 +269,6 @@ module.exports = function(RED) {
if (member.membership === "invite" && member.userId === node.userId) {
node.log("Got invite to join room " + member.roomId);
console.log(event);
if(node.autoAcceptRoomInvites) {
node.matrixClient.joinRoom(member.roomId).then(function() {
node.log("Automatically accepted invitation to join room " + member.roomId);
@@ -292,7 +300,7 @@ module.exports = function(RED) {
} else if(prevState === null && state === "ERROR") {
// Occurs when the initial sync failed first time.
node.setConnected(false, function(){
node.error("Failed to connect to Matrix server");
node.error("Failed to connect to Matrix server", {});
});
} else if(prevState === "ERROR" && state === "PREPARED") {
// Occurs when the initial sync succeeds
@@ -309,18 +317,18 @@ module.exports = function(RED) {
} else if(prevState === "SYNCING" && state === "RECONNECTING") {
// Occurs when the live update fails.
node.setConnected(false, function(){
node.error("Connection to Matrix server lost");
node.error("Connection to Matrix server lost", {});
});
} else if(prevState === "RECONNECTING" && state === "RECONNECTING") {
// Can occur if the update calls continue to fail,
// but the keepalive calls (to /versions) succeed.
node.setConnected(false, function(){
node.error("Connection to Matrix server lost");
node.error("Connection to Matrix server lost", {});
});
} else if(prevState === "RECONNECTING" && state === "ERROR") {
// Occurs when the keepalive call also fails
node.setConnected(false, function(){
node.error("Connection to Matrix server lost");
node.error("Connection to Matrix server lost", {});
});
} else if(prevState === "ERROR" && state === "SYNCING") {
// Occurs when the client has performed a
@@ -332,7 +340,7 @@ module.exports = function(RED) {
// Occurs when the client has failed to
// keepalive for a second time or more.
node.setConnected(false, function(){
node.error("Connection to Matrix server lost");
node.error("Connection to Matrix server lost", {});
});
} else if(prevState === "SYNCING" && state === "SYNCING") {
// Occurs when the client has performed a live update.
@@ -344,7 +352,7 @@ module.exports = function(RED) {
// Occurs once the client has stopped syncing or
// trying to sync after stopClient has been called.
node.setConnected(false, function(){
node.error("Connection to Matrix server lost");
node.error("Connection to Matrix server lost", {});
});
}
});
@@ -362,7 +370,7 @@ module.exports = function(RED) {
// httpStatus: 401
// }
node.error("Authentication failure: " + errorObj);
node.error("Authentication failure: " + errorObj, {});
stopClient();
});
@@ -371,14 +379,14 @@ module.exports = function(RED) {
if(node.e2ee){
node.log("Initializing crypto...");
await node.matrixClient.initCrypto();
node.matrixClient.setGlobalErrorOnUnknownDevices(false);
node.matrixClient.getCrypto().globalBlacklistUnverifiedDevices = false; // prevent errors from unverified devices
}
node.log("Connecting to Matrix server...");
await node.matrixClient.startClient({
initialSyncLimit: 8
});
} catch(error) {
node.error(error);
node.error(error, {});
}
}
@@ -399,7 +407,7 @@ module.exports = function(RED) {
.then(
function(data) {
if((typeof data['device_id'] === undefined || !data['device_id']) && !node.deviceId && !getStoredDeviceId(localStorage)) {
node.error("/whoami request did not return device_id. You will need to manually set one in your configuration because this cannot be automatically fetched.");
node.error("/whoami request did not return device_id. You will need to manually set one in your configuration because this cannot be automatically fetched.", {});
}
if('device_id' in data && data['device_id'] && !node.deviceId) {
// if we have no device_id configured lets use the one
@@ -409,7 +417,7 @@ module.exports = function(RED) {
// make sure our userId matches the access token's
if(data['user_id'].toLowerCase() !== node.userId.toLowerCase()) {
node.error(`User ID provided is ${node.userId} but token belongs to ${data['user_id']}`);
node.error(`User ID provided is ${node.userId} but token belongs to ${data['user_id']}`, {});
return;
}
run().catch((error) => node.error(error));
@@ -418,7 +426,7 @@ module.exports = function(RED) {
// if the error isn't authentication related retry in a little bit
if(err.code !== "M_UNKNOWN_TOKEN") {
retryStartTimeout = setTimeout(checkAuthTokenThenStart, 15000);
node.error("Auth check failed: " + err);
node.error("Auth check failed: " + err, {});
}
}
)
@@ -494,7 +502,7 @@ module.exports = function(RED) {
fs.copySync(oldStorageDir, dir);
}
} catch (err) {
node.error(err);
node.error(err, {});
}
});
+1 -1
View File
@@ -8,7 +8,7 @@
outputs:2,
defaults: {
name: { value: null },
server: { value: "", type: "matrix-server-config" },
server: { type: "matrix-server-config" },
},
label: function() {
return this.name || "Synapse Add/Edit User";
+9 -3
View File
@@ -8,9 +8,10 @@ module.exports = function(RED) {
this.server = RED.nodes.getNode(n.server);
if(!this.server) {
node.error('Server must be configured on the node.');
node.error('Server must be configured on the node.', {});
return;
}
node.server.register(node);
this.encodeUri = function(pathTemplate, variables) {
for (const key in variables) {
@@ -41,12 +42,13 @@ module.exports = function(RED) {
}
if(!node.server.isConnected()) {
node.error("Matrix server connection is currently closed");
node.error("Matrix server connection is currently closed", msg);
node.send([null, msg]);
return;
}
if(!msg.userId) {
node.error("msg.userId must be set to edit/create a user (ex: @user:server.com)");
node.error("msg.userId must be set to edit/create a user (ex: @user:server.com)", msg);
return;
}
@@ -69,6 +71,10 @@ module.exports = function(RED) {
node.send([null, msg]);
});
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-synapse-create-edit-user", MatrixSynapseCreateEditUser);
}
+1 -1
View File
@@ -8,7 +8,7 @@
outputs:2,
defaults: {
name: { value: null },
server: { value: "", type: "matrix-server-config" },
server: { type: "matrix-server-config" },
},
label: function() {
return this.name || "Synapse Deactivate User";
+9 -3
View File
@@ -8,9 +8,10 @@ module.exports = function(RED) {
this.server = RED.nodes.getNode(n.server);
if(!this.server) {
node.error('Server must be configured on the node.');
node.error('Server must be configured on the node.', {});
return;
}
node.server.register(node);
this.encodeUri = function(pathTemplate, variables) {
for (const key in variables) {
@@ -41,12 +42,13 @@ module.exports = function(RED) {
}
if(!node.server.isConnected()) {
node.error("Matrix server connection is currently closed");
node.error("Matrix server connection is currently closed", msg);
node.send([null, msg]);
return;
}
if(!msg.userId) {
node.error("msg.userId must be set to edit/create a user (ex: @user:server.com)");
node.error("msg.userId must be set to edit/create a user (ex: @user:server.com)", msg);
return;
}
@@ -70,6 +72,10 @@ module.exports = function(RED) {
node.send([null, msg]);
});
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-synapse-deactivate-user", MatrixSynapseDeactivateUser);
}
+1 -1
View File
@@ -8,7 +8,7 @@
outputs: 2,
defaults: {
name: { value: null },
server: { value: "", type: "matrix-server-config" },
server: { type: "matrix-server-config" },
roomId: { value: null },
},
label: function() {
+9 -5
View File
@@ -9,10 +9,9 @@ module.exports = function(RED) {
this.roomId = n.roomId;
if(!this.server) {
node.error('Server must be configured on the node.');
node.error('Server must be configured on the node.', {});
return;
}
this.encodeUri = function(pathTemplate, variables) {
for (const key in variables) {
if (!variables.hasOwnProperty(key)) {
@@ -42,18 +41,19 @@ module.exports = function(RED) {
}
if(!node.server.isConnected()) {
node.error("Matrix server connection is currently closed");
node.error("Matrix server connection is currently closed", msg);
node.send([null, msg]);
return;
}
msg.topic = node.roomId || msg.topic;
if(!msg.topic) {
node.error("room must be defined in either msg.topic or in node config");
node.error("room must be defined in either msg.topic or in node config", msg);
return;
}
if(!msg.userId) {
node.error("msg.userId is required to set user into a room");
node.error("msg.userId is required to set user into a room", msg);
return;
}
@@ -77,6 +77,10 @@ module.exports = function(RED) {
node.send([null, msg]);
});
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-synapse-join-room", MatrixJoinRoom);
}
+9 -5
View File
@@ -12,12 +12,12 @@ module.exports = function(RED) {
this.sharedSecret = this.credentials.sharedSecret;
if(!this.server) {
node.error('Server URL must be configured on the node.');
node.error('Server URL must be configured on the node.', {});
return;
}
if(!this.sharedSecret) {
node.error('Shared registration secret must be configured on the node.');
node.error('Shared registration secret must be configured on the node.', {});
return;
}
@@ -25,12 +25,12 @@ module.exports = function(RED) {
const { got } = await import('got');
if(!msg.payload.username) {
node.error("msg.payload.username is required");
node.error("msg.payload.username is required", msg);
return;
}
if(!msg.payload.password) {
node.error("msg.payload.password is required");
node.error("msg.payload.password is required", msg);
return;
}
@@ -50,7 +50,7 @@ module.exports = function(RED) {
var nonce = response.body.nonce;
if(!nonce) {
node.error('Could not get nonce from /_synapse/admin/v1/register');
node.error('Could not get nonce from /_synapse/admin/v1/register', msg);
return;
}
@@ -96,6 +96,10 @@ module.exports = function(RED) {
node.send(msg);
})();
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-synapse-register", MatrixSynapseRegister, {
credentials: {
+1 -1
View File
@@ -8,7 +8,7 @@
outputs:2,
defaults: {
name: { value: null },
server: { value: "", type: "matrix-server-config" }
server: { type: "matrix-server-config" }
},
label: function() {
return this.name || "Synapse User List";
+8 -1
View File
@@ -12,6 +12,8 @@ module.exports = function(RED) {
return;
}
node.server.register(node);
node.status({ fill: "red", shape: "ring", text: "disconnected" });
node.server.on("disconnected", function(){
@@ -29,8 +31,9 @@ module.exports = function(RED) {
}
if(!node.server.isConnected()) {
node.error("Matrix server connection is currently closed");
node.error("Matrix server connection is currently closed", msg);
node.send([null, msg]);
return;
}
let queryParams = {
@@ -62,6 +65,10 @@ module.exports = function(RED) {
node.send([null, msg]);
});
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-synapse-users", MatrixSynapseUsers);
}
+1 -1
View File
@@ -8,7 +8,7 @@
outputs:2,
defaults: {
name: { value: null },
server: { value: "", type: "matrix-server-config" },
server: { type: "matrix-server-config" },
},
label: function() {
return this.name || "WhoIs User";
+10 -3
View File
@@ -8,10 +8,12 @@ module.exports = function(RED) {
this.server = RED.nodes.getNode(n.server);
if(!this.server) {
node.error('Server must be configured on the node.');
node.error('Server must be configured on the node.', {});
return;
}
node.server.register(node);
this.encodeUri = function(pathTemplate, variables) {
for (const key in variables) {
if (!variables.hasOwnProperty(key)) {
@@ -41,12 +43,13 @@ module.exports = function(RED) {
}
if(!node.server.isConnected()) {
node.error("Matrix server connection is currently closed");
node.error("Matrix server connection is currently closed", msg);
node.send([null, msg]);
return;
}
if(!msg.userId) {
node.error("msg.userId must be set to get user whois data");
node.error("msg.userId must be set to get user whois data", msg);
return;
}
@@ -70,6 +73,10 @@ module.exports = function(RED) {
node.send([null, msg]);
});
});
node.on("close", function() {
node.server.deregister(node);
});
}
RED.nodes.registerType("matrix-whois-user", MatrixWhoIsUser);
}