Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73d802ff0d | ||
|
|
cf1bd78ee1 | ||
|
|
a10667a0e8 | ||
|
|
aaecaaec39 | ||
|
|
be5416a68e | ||
|
|
f8c5344a4e | ||
|
|
3c99bf21a9 | ||
|
|
63728d86a5 | ||
|
|
ff66222687 | ||
|
|
fa92f79304 | ||
|
|
f70d73b011 | ||
|
|
6a310de708 | ||
|
|
d5519a6828 | ||
|
|
2cf8ba1e67 | ||
|
|
9d080b6c1a | ||
|
|
755e18da50 | ||
|
|
4bd2dce434 | ||
|
|
b698389491 | ||
|
|
14badaeeb5 | ||
|
|
ae7e766a98 | ||
|
|
daafe33e86 |
21
README.md
21
README.md
@@ -3,6 +3,8 @@ Matrix chat server client for [Node-RED](https://nodered.org/)
|
||||
|
||||
***Currently we are in beta. We ask that you open any issues you have on our repository to help us reach a stable well tested version. Things may change & break before our first release so check changelog before updating.***
|
||||
|
||||
If you need help with this feel free to join our public matrix room at [#node-red-contrib-matrix-chat:skylar.tech](https://app.element.io/#/room/#node-red-contrib-matrix-chat:skylar.tech)
|
||||
|
||||
### Features
|
||||
|
||||
The following is supported from this package:
|
||||
@@ -30,9 +32,6 @@ The following is supported from this package:
|
||||
|
||||
Therefore, you can easily build a bot, chat relay, or administrate your Matrix server from within [Node-RED](https://nodered.org/).
|
||||
|
||||
### Usage
|
||||
We have examples! [Check them out](https://github.com/Skylar-Tech/node-red-contrib-matrix-chat/tree/master/examples#readme)
|
||||
|
||||
### Installing
|
||||
|
||||
You can either install from within Node-RED by searching for `node-red-contrib-matrix-chat` or run this from within your Node-RED directory:
|
||||
@@ -40,10 +39,18 @@ You can either install from within Node-RED by searching for `node-red-contrib-m
|
||||
npm install node-red-contrib-matrix-chat
|
||||
```
|
||||
|
||||
### End-to-End Encryption Notes
|
||||
Currently this module has no way of getting encryption keys from other devices on the same account. Therefore it is recommended you use the bot exclusively with Node-RED after it's creation. Failure to do so will lead to your bot being unable to receive messages from e2ee rooms it joined from another client. Shared secret registration makes this super easy since it returns a token and device ID.
|
||||
### Usage
|
||||
We have examples! [Check them out](https://github.com/Skylar-Tech/node-red-contrib-matrix-chat/tree/master/examples#readme)
|
||||
|
||||
This module stores a folder in your Node-RED directory called `matrix-local-storage` and is it vital that you periodically back this up if you are using e2ee. This is where the client stores all the keys necessary to decrypt messages and if lost you will lose access to e2e rooms. If you move your client to another NR install make sure to migrate this folder as well (and do not let both the old and new client run at same time).
|
||||
#### Extra functionality
|
||||
You are not limited by just the nodes we have created. If you turn on global access when setting up your Matrix Client you can access the client directly from any function node to write your own logic.
|
||||
|
||||
View an example [here](https://github.com/Skylar-Tech/node-red-contrib-matrix-chat/tree/master/examples#use-function-node-to-run-any-command)
|
||||
|
||||
### End-to-End Encryption Notes
|
||||
Currently, this module has no way of getting encryption keys from other devices on the same account. Therefore it is recommended you use the bot exclusively with Node-RED after it's creation. Failure to do so will lead to your bot being unable to receive messages from e2ee rooms it joined from another client. Shared secret registration makes this super easy since it returns a token and device ID.
|
||||
|
||||
This module stores a folder in your Node-RED directory called `matrix-client-storage` and is it vital that you periodically back this up if you are using e2ee. This is where the client stores all the keys necessary to decrypt messages and if lost you will lose access to e2e rooms. If you move your client to another NR install make sure to migrate this folder as well (and do not let both the old and new client run at same time).
|
||||
|
||||
Want to contribute? Any help on getting the last pieces of e2ee figured out would be greatly appreciated :)
|
||||
|
||||
@@ -61,4 +68,4 @@ You will need a user to use this module. Luckily this module comes with a node t
|
||||
### Contributing
|
||||
All contributions are welcome! If you do add a feature please do a pull request so that everyone benefits :)
|
||||
|
||||
Sharing is caring!
|
||||
Sharing is caring!
|
||||
|
||||
@@ -9,6 +9,7 @@ Build something cool with these nodes? Feel free to submit a pull request to sha
|
||||
|
||||
- [Create User with Shared Secret Registration](#create-user-with-shared-secret-registration)
|
||||
- [Create/Edit Synapse User](#createedit-synapse-user)
|
||||
- [Use function node to run any command](#use-function-node-to-run-any-command)
|
||||
- [Respond to "ping" with "pong"](#respond-to-ping-with-pong)
|
||||
- [Respond to "html" with an HTML message](#respond-to-html-with-an-html-message)
|
||||
- [Respond to "image" with an uploaded image](#respond-to-image-with-an-uploaded-image)
|
||||
@@ -39,6 +40,18 @@ Allows an administrator to create or modify a user account with a specified `msg
|
||||

|
||||
|
||||
|
||||
### Use function node to run any command
|
||||
|
||||
[View JSON](custom-redact-function-node.json)
|
||||
|
||||
If we do not have a node for something you want to do (such as redacting events/messages) you can do this manually with a function node.
|
||||
|
||||
**Note:** You should make sure to catch any errors in your function node otherwise you could cause Node-RED to crash.
|
||||
|
||||
To view what sort of functions you have access to check out the `client.ts` file from `matrix-js-sdk` [here](https://github.com/matrix-org/matrix-js-sdk/blob/master/src/client.ts).
|
||||
|
||||

|
||||
|
||||
### Respond to "ping" with "pong"
|
||||
|
||||
[View JSON](respond-to-html-with-html.json)
|
||||
|
||||
113
examples/custom-redact-function-node.json
Normal file
113
examples/custom-redact-function-node.json
Normal file
@@ -0,0 +1,113 @@
|
||||
[
|
||||
{
|
||||
"id": "89eed7ddf7a96070",
|
||||
"type": "function",
|
||||
"z": "f025a8b9fbd1b054",
|
||||
"name": "Redact Message",
|
||||
"func": "let matrixClient = global.get(\"matrixClient['@bot:example.com']\"),\n matrixOnline = global.get(\"matrixClientOnline['@bot:example.com']\");\n\nif(!matrixOnline) {\n msg.error = 'Matrix client not connected.';\n return [null, msg];\n}\n \nmatrixClient.redactEvent(msg.topic, msg.eventId, undefined, {\n reason: 'Redacted, muhahaha!'\n})\n .then(function(e) {\n msg.eventId = e.eventId;\n node.send([msg, null]);\n })\n .catch(function(e){\n node.warn(\"Error sending message \" + e);\n msg.error = e;\n node.send([null, msg]);\n });",
|
||||
"outputs": 2,
|
||||
"noerr": 0,
|
||||
"initialize": "",
|
||||
"finalize": "",
|
||||
"libs": [],
|
||||
"x": 730,
|
||||
"y": 1580,
|
||||
"wires": [
|
||||
[
|
||||
"5decd492e2da79d9"
|
||||
],
|
||||
[
|
||||
"fadcf8c32bdfd8be"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "5decd492e2da79d9",
|
||||
"type": "debug",
|
||||
"z": "f025a8b9fbd1b054",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "true",
|
||||
"targetType": "full",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 890,
|
||||
"y": 1560,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "f3636f4221511a81",
|
||||
"type": "comment",
|
||||
"z": "f025a8b9fbd1b054",
|
||||
"name": "If message is \"redact\" then redact the message.",
|
||||
"info": "",
|
||||
"x": 420,
|
||||
"y": 1540,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "9f777828840bb9a2",
|
||||
"type": "matrix-receive",
|
||||
"z": "f025a8b9fbd1b054",
|
||||
"name": "",
|
||||
"roomId": "",
|
||||
"acceptText": true,
|
||||
"acceptEmotes": false,
|
||||
"acceptStickers": false,
|
||||
"acceptReactions": false,
|
||||
"acceptFiles": false,
|
||||
"acceptImages": false,
|
||||
"x": 320,
|
||||
"y": 1580,
|
||||
"wires": [
|
||||
[
|
||||
"21a00b09f8c85399"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "21a00b09f8c85399",
|
||||
"type": "switch",
|
||||
"z": "f025a8b9fbd1b054",
|
||||
"name": "filter on msg.payload",
|
||||
"property": "payload",
|
||||
"propertyType": "msg",
|
||||
"rules": [
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "redact",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"checkall": "true",
|
||||
"repair": false,
|
||||
"outputs": 1,
|
||||
"x": 520,
|
||||
"y": 1580,
|
||||
"wires": [
|
||||
[
|
||||
"89eed7ddf7a96070"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "fadcf8c32bdfd8be",
|
||||
"type": "debug",
|
||||
"z": "f025a8b9fbd1b054",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "true",
|
||||
"targetType": "full",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 890,
|
||||
"y": 1600,
|
||||
"wires": []
|
||||
}
|
||||
]
|
||||
BIN
examples/custom-redact-function-node.png
Normal file
BIN
examples/custom-redact-function-node.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
1310
package-lock.json
generated
1310
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@@ -1,14 +1,16 @@
|
||||
{
|
||||
"name": "node-red-contrib-matrix-chat",
|
||||
"version": "0.1.8",
|
||||
"version": "0.2.4",
|
||||
"description": "Matrix chat server client for Node-RED",
|
||||
"dependencies": {
|
||||
"fs-extra": "^9.1.0",
|
||||
"got": "^11.8.2",
|
||||
"isomorphic-webcrypto": "^2.3.8",
|
||||
"matrix-js-sdk": "^12.2.0",
|
||||
"olm": "https://packages.matrix.org/npm/olm/olm-3.1.4.tgz",
|
||||
"utf8": "^3.0.0",
|
||||
"node-localstorage": "^2.2.1"
|
||||
"node-localstorage": "^2.2.1",
|
||||
"olm": "https://packages.matrix.org/npm/olm/olm-3.2.1.tgz",
|
||||
"process": "^0.11.10",
|
||||
"utf8": "^3.0.0"
|
||||
},
|
||||
"node-red": {
|
||||
"nodes": {
|
||||
|
||||
@@ -27,30 +27,19 @@
|
||||
<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-tips" style="margin-bottom: 12px;">
|
||||
User must be an admin to use this endpoint.
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="matrix-create-room">
|
||||
<h3>Details</h3>
|
||||
<p>
|
||||
Create a room with the defined options in <code>msg.payload</code>
|
||||
</p>
|
||||
<a href="https://matrix-org.github.io/synapse/develop/admin_api/room_membership.html#edit-room-membership-api" target="_blank">Synapse API Endpoint Information</a>
|
||||
<p>Create a Matrix room</p>
|
||||
<a href="https://matrix.org/docs/spec/client_server/r0.4.0#id266" target="_blank">Matrix API Endpoint Information</a>
|
||||
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>msg.payload
|
||||
<span class="property-type">string</span>
|
||||
<dt class="optional">msg.payload
|
||||
<span class="property-type">string | object | null</span>
|
||||
</dt>
|
||||
<dd> a list of options to pass to the /createRoom API. <a href="https://matrix.org/docs/spec/client_server/r0.4.0#id266">Click here</a> for information about what can be passed.</dd>
|
||||
|
||||
<dt>msg.userId
|
||||
<span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd> User's ID that will be set into the room.</dd>
|
||||
<dd> a list of options to pass to the /createRoom API. <a href="https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-createroom">Click here</a> for information about what can be passed. If this is a string it just sets the room name and ignores other options.</dd>
|
||||
</dl>
|
||||
|
||||
<h3>Outputs</h3>
|
||||
|
||||
@@ -53,7 +53,6 @@ module.exports = function(RED) {
|
||||
};
|
||||
}
|
||||
|
||||
// we need the status code, so set onlydata to false for this request
|
||||
node.server.matrixClient
|
||||
.createRoom(msg.payload || {})
|
||||
.then(function(e){
|
||||
|
||||
@@ -25,22 +25,22 @@
|
||||
|
||||
<script type="text/html" data-help-name="matrix-decrypt-file">
|
||||
<h3>Details</h3>
|
||||
<p>Files sent in an encrypted room are themselves encrypted. Use this node to encrypt/decrypt files. Note: This node will download the encryted file (required to decrypt)</p>
|
||||
<p>Files sent in an encrypted room are themselves encrypted. Use this node to encrypt/decrypt files. Note: This node will download the encrypted file so be cautious of large downloads.</p>
|
||||
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>msg.content
|
||||
<span class="property-type">Object</span>
|
||||
<span class="property-type">object</span>
|
||||
</dt>
|
||||
<dd> content of the decrypted message</dd>
|
||||
|
||||
<dt>msg.content.file
|
||||
<span class="property-type">Object</span>
|
||||
<span class="property-type">object</span>
|
||||
</dt>
|
||||
<dd> the information needed to decode the file</dd>
|
||||
|
||||
<dt>msg.url
|
||||
<span class="property-type">String | Null</span>
|
||||
<span class="property-type">string | null</span>
|
||||
</dt>
|
||||
<dd> the decoded mxc url.</dd>
|
||||
</dl>
|
||||
@@ -57,6 +57,9 @@
|
||||
|
||||
<dt>msg.filename <span class="property-type">string</span></dt>
|
||||
<dd>filename of the decoded file (if content.filename isn't defined on the message we fallback to content.body).</dd>
|
||||
|
||||
<dt>msg.thumbnail_payload <span class="property-type">buffer</span></dt>
|
||||
<dd>If the file is an image then this property is set to the buffer of the thumbnail. If not an image this is left off.</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>Error
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
outputs: 2,
|
||||
defaults: {
|
||||
name: { value: null },
|
||||
server: { value: "", type: "matrix-server-config" }
|
||||
server: { value: "", type: "matrix-server-config" },
|
||||
roomId: { value: null },
|
||||
},
|
||||
label: function() {
|
||||
return this.name || "Room Invite";
|
||||
@@ -27,12 +28,17 @@
|
||||
<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-user"></i> Room ID</label>
|
||||
<input type="text" id="node-input-roomId" placeholder="msg.topic">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="matrix-invite-room">
|
||||
<h3>Details</h3>
|
||||
<p>
|
||||
This API invites a user to participate in a particular room. They do not start participating in the room until they actually join the room.
|
||||
This node invites a user to participate in a particular room. They do not start participating in the room until they actually join the room. The client must be in the room and have permissions to invite.
|
||||
</p>
|
||||
<a href="https://matrix-org.github.io/synapse/develop/admin_api/room_membership.html#edit-room-membership-api" target="_blank">Synapse API Endpoint Information</a>
|
||||
|
||||
@@ -41,7 +47,7 @@
|
||||
<dt>msg.topic
|
||||
<span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd> The room identifier to invite to: for example, <code>!h8zld9j31:example.com. If configured on the node it overrides this input and is no longer required.</code>.</dd>
|
||||
<dd> The room identifier to invite to: for example, <code>!h8zld9j31:example.com</code>. Ignored if configured on the node, otherwise required.</dd>
|
||||
|
||||
<dt>msg.userId
|
||||
<span class="property-type">string</span>
|
||||
|
||||
@@ -6,6 +6,7 @@ module.exports = function(RED) {
|
||||
|
||||
this.name = n.name;
|
||||
this.server = RED.nodes.getNode(n.server);
|
||||
this.roomId = n.roomId;
|
||||
|
||||
if(!this.server) {
|
||||
node.error('Server must be configured on the node.');
|
||||
@@ -47,7 +48,7 @@ module.exports = function(RED) {
|
||||
|
||||
msg.topic = node.roomId || msg.topic;
|
||||
if(!msg.topic) {
|
||||
node.error("msg.topic must be defined or configured on the node.");
|
||||
node.error("room must be defined in either msg.topic or in node config");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -58,7 +59,7 @@ module.exports = function(RED) {
|
||||
msg.payload = e;
|
||||
node.send([msg, null]);
|
||||
}).catch(function(e){
|
||||
node.warn("Error creating room " + e);
|
||||
node.warn("Error inviting to room " + e);
|
||||
msg.error = e;
|
||||
node.send([null, msg]);
|
||||
});
|
||||
|
||||
@@ -26,25 +26,22 @@
|
||||
<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-tips">
|
||||
Room ID must either be defined here or passed in via <code>msg.topic</code>. The config takes precedence over the input.
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="matrix-join-room">
|
||||
<h3>Details</h3>
|
||||
<p>This API starts a user participating in a particular room, if that user is allowed to participate in that room. After this call, the client is allowed to see all current state events in the room, and all subsequent events associated with the room until the user leaves the room.</p>
|
||||
<p>This node starts the client participating in a particular room, if the client is allowed to participate in that room. After this call, the client is allowed to see all current state events in the room, and all subsequent events associated with the room until the user leaves the room.</p>
|
||||
<a href="https://matrix.org/docs/spec/client_server/latest#id291" target="_blank">Matrix API Endpoint Information</a>
|
||||
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>msg.topic
|
||||
<span class="property-type">String</span>
|
||||
<span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd> The room identifier or alias to join.</dd>
|
||||
|
||||
<dt class="optional">msg.joinOpts
|
||||
<span class="property-type">Object</span>
|
||||
<span class="property-type">object | null</span>
|
||||
</dt>
|
||||
<dd> Extra options that can be passed when joining a room.</dd>
|
||||
|
||||
@@ -62,11 +59,6 @@
|
||||
<span class="property-type">[string]</span>
|
||||
</dt>
|
||||
<dd> The servers to attempt to join the room through. One of the servers must be participating in the room.</dd>
|
||||
|
||||
<dt class="optional">msg.reason
|
||||
<span class="property-type">String</span>
|
||||
</dt>
|
||||
<dd> Reason for kicking the user.</dd>
|
||||
</dl>
|
||||
|
||||
<h3>Outputs</h3>
|
||||
|
||||
@@ -29,33 +29,7 @@
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-roomId"><i class="fa fa-user"></i> Room ID</label>
|
||||
<input type="text" id="node-input-roomId">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-messageType">
|
||||
Message Type
|
||||
</label>
|
||||
<select id="node-input-messageType">
|
||||
<option value="m.text">m.text</option>
|
||||
<option value="m.notice">m.notice</option>
|
||||
<option value="msg.type">msg.type input</option>
|
||||
</select>
|
||||
<div class="form-tips">
|
||||
It's recommended to use m.notice for bots because the message will render in a lighter text (at least in Element client) for users to distinguish bot and real user messages.
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-messageFormat">
|
||||
Message Format
|
||||
</label>
|
||||
<select id="node-input-messageFormat">
|
||||
<option value="">Default (plaintext)</option>
|
||||
<option value="html">HTML</option>
|
||||
<option value="msg.format">msg.format input</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-tips">
|
||||
Must be a valid <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types" target="_blank">MIME Type</a>
|
||||
<input type="text" id="node-input-roomId" placeholder="msg.topic">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
@@ -66,18 +40,18 @@
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>msg.payload
|
||||
<span class="property-type">String</span>
|
||||
<span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd> Usually an emoji but can also be text. </dd>
|
||||
|
||||
<dt>msg.topic
|
||||
<span class="property-type">String | Null</span>
|
||||
<span class="property-type">string | null</span>
|
||||
</dt>
|
||||
<dd> Room ID to send image to. Optional if configured on the node. If configured on the node this will be ignored.</dd>
|
||||
|
||||
<dt>msg.referenceEventId<br />
|
||||
msg.eventId
|
||||
<span class="property-type">String</span>
|
||||
<span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd> One of these is required. This is the eventId of the message to react to. Uses <code>msg.referenceEventId</code> first and falls back to <code>msg.eventId</code>.</dd>
|
||||
</dl>
|
||||
@@ -86,8 +60,6 @@
|
||||
<ol class="node-ports">
|
||||
<li>Success
|
||||
<dl class="message-properties">
|
||||
<dd>original msg object preserved.</dd>
|
||||
|
||||
<dt>msg.eventId <span class="property-type">string</span></dt>
|
||||
<dd>the eventId from the posted reaction.</dd>
|
||||
</dl>
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
<p>Receive events from Matrix.</p>
|
||||
|
||||
<h3>Outputs</h3>
|
||||
<ol class="node-ports">
|
||||
<ul class="node-ports">
|
||||
<li>Always Returned
|
||||
<dl class="message-properties">
|
||||
<dt>msg.type <span class="property-type">string</span></dt>
|
||||
@@ -146,6 +146,11 @@
|
||||
<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>
|
||||
@@ -159,11 +164,6 @@
|
||||
</li>
|
||||
|
||||
<li><code>msg.type</code> == '<strong>m.reaction</strong>'
|
||||
<dl class="message-properties">
|
||||
<dt>msg.info <span class="property-type">object</span></dt>
|
||||
<dd>the content's info.</dd>
|
||||
</dl>
|
||||
|
||||
<dl class="message-properties">
|
||||
<dt>msg.referenceEventId <span class="property-type">string</span></dt>
|
||||
<dd>the message that the reaction relates to</dd>
|
||||
@@ -187,39 +187,54 @@
|
||||
<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.file.info <span class="property-type">string</span></dt>
|
||||
<dd>the content's info.</dd>
|
||||
<dt>msg.url <span class="property-type">string</span></dt>
|
||||
<dd>the file's URL</dd>
|
||||
</dl>
|
||||
|
||||
<dl class="message-properties">
|
||||
<dt>msg.file.url <span class="property-type">string</span></dt>
|
||||
<dd>the file's URL</dd>
|
||||
<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.image</strong>'
|
||||
<dl class="message-properties">
|
||||
<dt>msg.image.info <span class="property-type">string</span></dt>
|
||||
<dd>the image info.</dd>
|
||||
</dl>
|
||||
|
||||
<dl class="message-properties">
|
||||
<dt>msg.file.url <span class="property-type">string</span></dt>
|
||||
<dt>msg.url <span class="property-type">string</span></dt>
|
||||
<dd>the image's URL</dd>
|
||||
</dl>
|
||||
|
||||
<dl class="message-properties">
|
||||
<dt>msg.file.thumbnail_url <span class="property-type">string</span></dt>
|
||||
<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>
|
||||
</ol>
|
||||
</ul>
|
||||
</script>
|
||||
@@ -81,10 +81,12 @@ module.exports = function(RED) {
|
||||
if(msg.content.info) {
|
||||
if(msg.content.info.thumbnail_url) {
|
||||
msg.thumbnail_url = node.server.matrixClient.mxcUrlToHttp(msg.content.info.thumbnail_url);
|
||||
msg.thumbnail_mxc_url = msg.content.info.thumbnail_url;
|
||||
}
|
||||
|
||||
if(msg.content.url) {
|
||||
msg.url = node.server.matrixClient.mxcUrlToHttp(msg.content.url);
|
||||
msg.mxc_url = msg.content.url;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -31,9 +31,6 @@
|
||||
<label for="node-input-roomId"><i class="fa fa-user"></i> Room ID</label>
|
||||
<input type="text" id="node-input-roomId" placeholder="msg.topic">
|
||||
</div>
|
||||
<div class="form-tips">
|
||||
Room ID must either be defined here or passed in via <code>msg.topic</code>. The config takes precedence over the input.
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="matrix-room-ban">
|
||||
@@ -42,18 +39,18 @@
|
||||
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt class="optional">msg.userId
|
||||
<span class="property-type">String</span>
|
||||
<dt>msg.userId
|
||||
<span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd> The ID of the user to ban.</dd>
|
||||
|
||||
<dt class="optional">msg.topic
|
||||
<span class="property-type">String | Null</span>
|
||||
<span class="property-type">string | null</span>
|
||||
</dt>
|
||||
<dd> The room to ban the user from. Required if not defined on the config. Config takes precedence.</dd>
|
||||
<dd> The room to ban the user from. Ignored if configured on the node, otherwise required.</dd>
|
||||
|
||||
<dt class="optional">msg.reason
|
||||
<span class="property-type">String</span>
|
||||
<span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd> Reason for banning the user.</dd>
|
||||
</dl>
|
||||
@@ -62,7 +59,8 @@
|
||||
<ol class="node-ports">
|
||||
<li>Success
|
||||
<dl class="message-properties">
|
||||
<dd>original msg object preserved. Node doesn't set anything.</dd>
|
||||
<dt>msg.eventId <span class="property-type">string</span></dt>
|
||||
<dd>the eventId from the ban event.</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>Error
|
||||
|
||||
@@ -31,9 +31,6 @@
|
||||
<label for="node-input-roomId"><i class="fa fa-user"></i> Room ID</label>
|
||||
<input type="text" id="node-input-roomId" placeholder="msg.topic">
|
||||
</div>
|
||||
<div class="form-tips">
|
||||
Room ID must either be defined here or passed in via <code>msg.topic</code>. The config takes precedence over the input.
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="matrix-room-kick">
|
||||
@@ -43,17 +40,17 @@
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>msg.userId
|
||||
<span class="property-type">String</span>
|
||||
<span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd> The ID of the user to kick.</dd>
|
||||
|
||||
<dt class="optional">msg.topic
|
||||
<span class="property-type">String | Null</span>
|
||||
<span class="property-type">string | null</span>
|
||||
</dt>
|
||||
<dd> The room to kick the user from. Required if not defined on the config. Config takes precedence.</dd>
|
||||
<dd> The room to kick the user from. Ignored if configured on the node, otherwise required.</dd>
|
||||
|
||||
<dt class="optional">msg.reason
|
||||
<span class="property-type">String</span>
|
||||
<span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd> Reason for kicking the user.</dd>
|
||||
</dl>
|
||||
@@ -62,7 +59,8 @@
|
||||
<ol class="node-ports">
|
||||
<li>Success
|
||||
<dl class="message-properties">
|
||||
<dd>original msg object preserved. Node doesn't set anything.</dd>
|
||||
<dt>msg.eventId <span class="property-type">string</span></dt>
|
||||
<dd>the eventId from the kick event.</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>Error
|
||||
|
||||
@@ -38,15 +38,15 @@
|
||||
|
||||
<script type="text/html" data-help-name="matrix-room-users">
|
||||
<h3>Details</h3>
|
||||
<p>A list of members of the room. If you are joined to the room then this will be the current members of the room. If you have left the room then this will be the members of the room when you left.</p>
|
||||
<p>This node returns a map of MXIDs to member info objects for members of the room. The current user must be in the room for it to work, unless it is an Application Service in which case any of the AS's users must be in the room. This API is primarily for Application Services and should be faster to respond than /members as it can be implemented more efficiently on the server.</p>
|
||||
<a href="https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-rooms-roomid-joined-members" target="_blank">Matrix API Endpoint Information</a>
|
||||
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt class="optional">msg.topic
|
||||
<span class="property-type">Integer</span>
|
||||
<span class="property-type">integer</span>
|
||||
</dt>
|
||||
<dd> Room ID to get member list from. Required if not configured on the node.</dd>
|
||||
<dd> Room ID to get member list from. Ignored if configured on the node, otherwise it's required.</dd>
|
||||
</dl>
|
||||
|
||||
<h3>Outputs</h3>
|
||||
|
||||
@@ -30,14 +30,14 @@
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-roomId"><i class="fa fa-user"></i> Room ID</label>
|
||||
<input type="text" id="node-input-roomId">
|
||||
<input type="text" id="node-input-roomId" placeholder="msg.topic">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-contentType"><i class="fa fa-user"></i> Content-Type</label>
|
||||
<input type="text" id="node-input-contentType" placeholder="application/pdf">
|
||||
<input type="text" id="node-input-contentType" placeholder="msg.contentType">
|
||||
</div>
|
||||
<div class="form-tips">
|
||||
Must be a valid <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types" target="_blank">MIME Type</a>
|
||||
Must be a valid <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types" target="_blank">MIME Type</a> (ex: application/pdf) or left empty
|
||||
</div>
|
||||
</script>
|
||||
|
||||
@@ -48,36 +48,42 @@
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>msg.payload
|
||||
<span class="property-type">File | String | Buffer | ReadStream | Blob</span>
|
||||
<span class="property-type">File | string | Buffer | ReadStream | Blob</span>
|
||||
</dt>
|
||||
<dd> the contents of the file to upload. </dd>
|
||||
|
||||
<dt>msg.topic
|
||||
<span class="property-type">String | Null</span>
|
||||
<span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd> Room ID to send file to. Optional if configured on the node. Overrides node configuration if set.</dd>
|
||||
<dd> Room ID to send file to. Ignored if configured on the node, otherwise required.</dd>
|
||||
|
||||
<dt class="optional">msg.filename
|
||||
<span class="property-type">String | Null</span>
|
||||
<span class="property-type">string | null</span>
|
||||
</dt>
|
||||
<dd> name of the file to upload (optional). Overrides node configuration.</dd>
|
||||
|
||||
<dt class="optional">msg.contentType
|
||||
<span class="property-type">String | Null</span>
|
||||
</dt>
|
||||
<dd> Content <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types" target="_blank">MIME Type</a>. Optional if configured on the node. Overrides node configuration if set.</dd>
|
||||
<dd> name of the file to upload (optional). Note: If this is not defined the file will receive a randomly generated name (without an extension).</dd>
|
||||
|
||||
<dt class="optional">msg.body
|
||||
<span class="property-type">String | Null</span>
|
||||
<span class="property-type">string | null</span>
|
||||
</dt>
|
||||
<dd> this will be the display name the client will see when rendered in their chat client. If this is left empty the it uses <code>msg.filename</code>. If <code>msg.filename</code> is also undefined it sets it to empty string</dd>
|
||||
<dd> this will be the display name the client will see when rendered in their chat client. If this is left empty it will just display as "Attachment".</dd>
|
||||
|
||||
<dt class="optional">msg.contentType
|
||||
<span class="property-type">string | null</span>
|
||||
</dt>
|
||||
<dd> Content <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types" target="_blank">MIME Type</a>. Optional but highly recommended (so the client receiving knows what type of file it is).</dd>
|
||||
|
||||
<dt class="optional">msg.content
|
||||
<span class="property-type">object | null</span>
|
||||
</dt>
|
||||
<dd> craft your own msg.content to send to the server. If defined then <code>msg.filename</code>, <code>msg.contentType</code>, <code>msg.body</code>, and <code>msg.payload</code> aren't required since the file already exists.</dd>
|
||||
</dl>
|
||||
|
||||
<h3>Outputs</h3>
|
||||
<ol class="node-ports">
|
||||
<li>Success
|
||||
<dl class="message-properties">
|
||||
<dd>original msg object preserved.</dd>
|
||||
<dt>msg.eventId <span class="property-type">string</span></dt>
|
||||
<dd>the eventId from the posted message.</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>Error
|
||||
|
||||
@@ -61,17 +61,12 @@ module.exports = function(RED) {
|
||||
return;
|
||||
}
|
||||
|
||||
msg.contentType = msg.contentType || node.contentType;
|
||||
if(!msg.contentType) {
|
||||
node.error('msg.contentType is required');
|
||||
return;
|
||||
}
|
||||
|
||||
msg.contentType = node.contentType || msg.contentType || null;
|
||||
node.log("Uploading file " + msg.filename);
|
||||
node.server.matrixClient.uploadContent(
|
||||
msg.payload, {
|
||||
name: msg.filename || null, // Name to give the file on the server.
|
||||
rawResponse: (msg.rawResponse || false), // Return the raw body, rather than parsing the JSON.
|
||||
rawResponse: false, // Return the raw body, rather than parsing the JSON.
|
||||
type: msg.contentType, // Content-type for the upload. Defaults to file.type, or applicaton/octet-stream.
|
||||
onlyContentUri: false // Just return the content URI, rather than the whole body. Defaults to false. Ignored if opts.rawResponse is true.
|
||||
})
|
||||
@@ -79,18 +74,18 @@ module.exports = function(RED) {
|
||||
const content = {
|
||||
msgtype: 'm.file',
|
||||
url: file.content_uri,
|
||||
body: (msg.body || msg.filename) || "",
|
||||
body: msg.body || "",
|
||||
};
|
||||
node.server.matrixClient
|
||||
.sendMessage(msg.topic, content)
|
||||
.then(function(imgResp) {
|
||||
node.log("File message sent: " + imgResp);
|
||||
.then(function(e) {
|
||||
node.log("File message sent: " + e);
|
||||
msg.eventId = e.eventId;
|
||||
node.send([msg, null]);
|
||||
})
|
||||
.catch(function(e){
|
||||
node.warn("Error sending file message " + e);
|
||||
msg.matrixError = e;
|
||||
msg.error = e;
|
||||
node.send([null, msg]);
|
||||
});
|
||||
}).catch(function(e){
|
||||
|
||||
@@ -30,50 +30,50 @@
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-roomId"><i class="fa fa-user"></i> Room ID</label>
|
||||
<input type="text" id="node-input-roomId">
|
||||
<input type="text" id="node-input-roomId" placeholder="msg.topic">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-contentType"><i class="fa fa-user"></i> Content-Type</label>
|
||||
<input type="text" id="node-input-contentType" placeholder="application/png">
|
||||
<input type="text" id="node-input-contentType" placeholder="msg.contentType">
|
||||
</div>
|
||||
<div class="form-tips">
|
||||
Must be a valid <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types" target="_blank">MIME Type</a>
|
||||
Must be a valid <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types" target="_blank">MIME Type</a> (ex: image/png) or left empty
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="matrix-send-image">
|
||||
<h3>Details</h3>
|
||||
<p>This node will send an image to a Matrix chat room. You can link this directly to a File In node.</p>
|
||||
<p>This node will send an image to a Matrix chat room. Supports direct linking to a File In node.</p>
|
||||
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>msg.payload
|
||||
<span class="property-type">File | String | Buffer | ReadStream | Blob</span>
|
||||
<span class="property-type">File | string | Buffer | ReadStream | Blob</span>
|
||||
</dt>
|
||||
<dd> the contents of the image to upload. </dd>
|
||||
|
||||
<dt>msg.topic
|
||||
<span class="property-type">String | Null</span>
|
||||
<span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd> Room ID to send image to. Optional if configured on the node. Overrides node configuration if set.</dd>
|
||||
<dd> Room ID to send image to. Ignored if configured on the node, otherwise required.</dd>
|
||||
|
||||
<dt class="optional">msg.filename
|
||||
<span class="property-type">String | Null</span>
|
||||
<span class="property-type">string | null</span>
|
||||
</dt>
|
||||
<dd> name of the image file to upload (optional). Overrides node configuration.</dd>
|
||||
|
||||
<dt class="optional">msg.contentType
|
||||
<span class="property-type">String | Null</span>
|
||||
</dt>
|
||||
<dd> Content <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types" target="_blank">MIME Type</a>. Optional if configured on the node. Overrides node configuration if set.</dd>
|
||||
<dd> name of the image to upload (optional). Note: If this is not defined the file will receive a randomly generated name (without an extension).</dd>
|
||||
|
||||
<dt class="optional">msg.body
|
||||
<span class="property-type">String | Null</span>
|
||||
<span class="property-type">string | null</span>
|
||||
</dt>
|
||||
<dd> this will be the display name the client will see when rendered in their chat client. If this is left empty the it uses <code>msg.filename</code>. If <code>msg.filename</code> is also undefined it sets it to empty string</dd>
|
||||
<dd> this will be the display name the client will see when rendered in their chat client. If this is left empty it will just display as "Attachment".</dd>
|
||||
|
||||
<dt class="optional">msg.contentType
|
||||
<span class="property-type">string | null</span>
|
||||
</dt>
|
||||
<dd> Content <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types" target="_blank">MIME Type</a>. Overridden if configured on the node. Optional but highly recommended (so the client receiving knows what type of file it is).</dd>
|
||||
|
||||
<dt class="optional">msg.content
|
||||
<span class="property-type">Object | Null</span>
|
||||
<span class="property-type">object | null</span>
|
||||
</dt>
|
||||
<dd> craft your own msg.content to send to the server. If defined then <code>msg.filename</code>, <code>msg.contentType</code>, <code>msg.body</code>, and <code>msg.payload</code> aren't required since the file already exists.</dd>
|
||||
</dl>
|
||||
@@ -82,8 +82,6 @@
|
||||
<ol class="node-ports">
|
||||
<li>Success
|
||||
<dl class="message-properties">
|
||||
<dd>original msg object preserved.</dd>
|
||||
|
||||
<dt>msg.eventId <span class="property-type">string</span></dt>
|
||||
<dd>the eventId from the posted message.</dd>
|
||||
</dl>
|
||||
|
||||
@@ -61,17 +61,12 @@ module.exports = function(RED) {
|
||||
return;
|
||||
}
|
||||
|
||||
msg.contentType = msg.contentType || node.contentType;
|
||||
if(!msg.contentType) {
|
||||
node.error('msg.contentType is required');
|
||||
return;
|
||||
}
|
||||
|
||||
msg.contentType = node.contentType || msg.contentType || null;
|
||||
node.log("Uploading image " + msg.filename);
|
||||
node.server.matrixClient.uploadContent(
|
||||
msg.payload, {
|
||||
name: msg.filename || null, // Name to give the file on the server.
|
||||
rawResponse: (msg.rawResponse || false), // Return the raw body, rather than parsing the JSON.
|
||||
rawResponse: false, // Return the raw body, rather than parsing the JSON.
|
||||
type: msg.contentType, // Content-type for the upload. Defaults to file.type, or applicaton/octet-stream.
|
||||
onlyContentUri: false // Just return the content URI, rather than the whole body. Defaults to false. Ignored if opts.rawResponse is true.
|
||||
})
|
||||
@@ -91,7 +86,7 @@ module.exports = function(RED) {
|
||||
})
|
||||
.catch(function(e){
|
||||
node.warn("Error uploading image message " + e);
|
||||
msg.matrixError = e;
|
||||
msg.error = e;
|
||||
node.send([null, msg]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -25,14 +25,17 @@
|
||||
<label for="node-input-name"><i class="icon-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-user"></i> Room ID</label>
|
||||
<input type="text" id="node-input-roomId">
|
||||
<input type="text" id="node-input-roomId" placeholder="msg.topic">
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-messageType">
|
||||
Message Type
|
||||
@@ -42,10 +45,11 @@
|
||||
<option value="m.notice">m.notice</option>
|
||||
<option value="msg.type">msg.type input</option>
|
||||
</select>
|
||||
<div class="form-tips">
|
||||
It's recommended to use m.notice for bots because the message will render in a lighter text (at least in Element client) for users to distinguish bot and real user messages.
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row form-tips">
|
||||
It's recommended to use m.notice for bots because the message will render in a lighter text (at least in Element client) for users to distinguish bot and real user messages.
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-messageFormat">
|
||||
Message Format
|
||||
@@ -56,49 +60,44 @@
|
||||
<option value="msg.format">msg.format input</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-tips">
|
||||
Must be a valid <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types" target="_blank">MIME Type</a>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="matrix-send-message">
|
||||
<h3>Details</h3>
|
||||
<p>Sends a message to a Matrix room.</p>
|
||||
<p>Sends a message to a Matrix room. Messages are auto encrypted if necessary.</p>
|
||||
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>msg.topic
|
||||
<span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd> Room ID to send image to. Optional if configured on the node. If configured on the node this input will be overridden.</dd>
|
||||
|
||||
<dt>msg.payload
|
||||
<span class="property-type">String</span>
|
||||
<span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd> the message text. </dd>
|
||||
|
||||
<dt class="optional">msg.formatted_payload
|
||||
<span class="property-type">String</span>
|
||||
<span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd> the formatted HTML message (uses msg.payload if not defined). This only affects HTML messages.</dd>
|
||||
|
||||
<dt>msg.topic
|
||||
<span class="property-type">String | Null</span>
|
||||
</dt>
|
||||
<dd> Room ID to send image to. Optional if configured on the node. Overrides node configuration if set.</dd>
|
||||
|
||||
<dt class="optional">msg.type
|
||||
<span class="property-type">String | Null</span>
|
||||
<span class="property-type">string | null</span>
|
||||
</dt>
|
||||
<dd> This is only used and required when configured so on the node. Must be set to either 'm.text' or 'm.notice'</dd>
|
||||
<dd> This is only used and required when configured so on the node. Must be set to either <code>'m.text'</code> or <code>'m.notice'</code></dd>
|
||||
|
||||
<dt class="optional">msg.format
|
||||
<span class="property-type">String | Null</span>
|
||||
<span class="property-type">string | null</span>
|
||||
</dt>
|
||||
<dd> This is only used and required when configured so on the node. Set to null for plain text and 'html' for HTML.</dd>
|
||||
<dd> This is only used and required when configured so on the node. Set to <code>null</code> for plain text and <code>'html'</code> for HTML.</dd>
|
||||
</dl>
|
||||
|
||||
<h3>Outputs</h3>
|
||||
<ol class="node-ports">
|
||||
<li>Success
|
||||
<dl class="message-properties">
|
||||
<dd>original msg object preserved.</dd>
|
||||
|
||||
<dt>msg.eventId <span class="property-type">string</span></dt>
|
||||
<dd>the eventId from the posted message.</dd>
|
||||
</dl>
|
||||
|
||||
@@ -109,7 +109,10 @@ module.exports = function(RED) {
|
||||
|
||||
if(msgFormat === 'html') {
|
||||
content.format = "org.matrix.custom.html";
|
||||
content.formatted_body = msg.formatted_payload || msg.payload;
|
||||
content.formatted_body =
|
||||
(typeof msg.formatted_payload !== 'undefined' && msg.formatted_payload)
|
||||
? msg.formatted_payload.toString()
|
||||
: msg.payload.toString();
|
||||
}
|
||||
|
||||
node.server.matrixClient.sendMessage(msg.topic, content)
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
defaults: {
|
||||
name: { value: null },
|
||||
autoAcceptRoomInvites: { value: true },
|
||||
enableE2ee: { type: "checkbox", value: true }
|
||||
enableE2ee: { type: "checkbox", value: true },
|
||||
global: { type: "checkbox", value: true }
|
||||
},
|
||||
icon: "matrix.png",
|
||||
label: function() {
|
||||
@@ -53,7 +54,7 @@
|
||||
id="node-config-input-autoAcceptRoomInvites"
|
||||
style="width: auto; margin-left: 125px; vertical-align: top"
|
||||
/>
|
||||
<label for="node-config-input-autoAcceptRoomInvites" style="width: auto">
|
||||
<label for="node-config-input-autoAcceptRoomInvites" style="width: auto;max-width:50%;">
|
||||
Auto join invited rooms
|
||||
</label>
|
||||
</div>
|
||||
@@ -63,17 +64,38 @@
|
||||
id="node-config-input-enableE2ee"
|
||||
style="width: auto; margin-left: 125px; vertical-align: top"
|
||||
/>
|
||||
<label for="node-config-input-enableE2ee" style="width: auto">
|
||||
Enable end-to-end encryption (requires DeviceID)
|
||||
<label for="node-config-input-enableE2ee" style="width: auto;max-width:50%;">
|
||||
Enable end-to-end encryption (requires a Device ID to be set.)
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-tips" style="margin-bottom: 12px;">
|
||||
E2ee requires a Device ID to be set.
|
||||
<div class="form-row">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="node-config-input-global"
|
||||
style="width: auto; margin-left: 125px; vertical-align: top"
|
||||
/>
|
||||
<label for="node-config-input-global" style="width: auto">
|
||||
Global access to Matrix Client
|
||||
</label>
|
||||
<div class="form-tips" style="margin-bottom: 12px;">
|
||||
If enabled this allows you to access the matrix client directly with a Function node. This way you can do <a href="https://github.com/Skylar-Tech/node-red-contrib-matrix-chat/tree/master/examples#use-function-node-to-run-any-command" target="_blank">whatever you want</a> with the client. Example:<br>
|
||||
<code style="white-space: normal;">let client = global.get("matrixClient['@bot:example.com']");</code>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="matrix-server-config">
|
||||
<h3>Details</h3>
|
||||
<p>Matrix client configuration node</p>
|
||||
<p>Matrix client connection configuration</p>
|
||||
|
||||
<h3>Setting up an account</h3>
|
||||
<div>
|
||||
<p>
|
||||
You need an account for your client to use. If you are going to be using End-to-End Encryption you should generate the bot and only use it within Node-RED otherwise if you have other clients connected on the same user it could cause problems with e2ee (key sharing is currently not supported).
|
||||
</p>
|
||||
<p>If you have access to the server directly you can use Shared Secret Registration as described <a href="https://github.com/Skylar-Tech/node-red-contrib-matrix-chat/tree/master/examples#create-user-with-shared-secret-registration" target="_blank" style="text-decoration: underline;">here</a>.</p>
|
||||
<p>If this is a server you do not administrate/have access to follow these instructions:</p>
|
||||
<ol><li>In a private/incognito browser window, open Element.</li><li>Log in to the account you want to get the access token for, such as the bot's account. <strong>Do not setup key storage</strong>.</li><li>Click on the bot's name in the top left corner then "Settings".</li><li>(Optional) Set your bot's display name and avatar.</li><li>Click the "Help & About" tab (left side of the dialog).</li><li>Scroll to the bottom and click the <code><click to reveal></code> part of <code>Access Token: <click to reveal></code>.</li><li>Copy your access token to a safe place, like the bot's configuration file.</li><li><strong>Do not log out.</strong> Instead, just close the window. If you used a private browsing session, you should be able to still use Element for your own account. Logging out deletes the access token from the server, making the bot unable to use it.</li></ol>
|
||||
</div>
|
||||
</script>
|
||||
@@ -1,12 +1,17 @@
|
||||
global.Olm = require('olm');
|
||||
const fs = require("fs-extra");
|
||||
const sdk = require("matrix-js-sdk");
|
||||
const { LocalStorage } = require('node-localstorage');
|
||||
const { LocalStorageCryptoStore } = require('matrix-js-sdk/lib/crypto/store/localStorage-crypto-store');
|
||||
|
||||
module.exports = function(RED) {
|
||||
const sdk = require("matrix-js-sdk");
|
||||
const { LocalStorage } = require('node-localstorage');
|
||||
const localStorage = new LocalStorage('./matrix-local-storage');
|
||||
const { LocalStorageCryptoStore } = require('matrix-js-sdk/lib/crypto/store/localStorage-crypto-store');
|
||||
function MatrixFolderNameFromUserId(name) {
|
||||
return name.replace(/[^a-z0-9]/gi, '_').toLowerCase();
|
||||
}
|
||||
|
||||
function MatrixServerNode(n) {
|
||||
let storageDir = './matrix-client-storage';
|
||||
|
||||
// we should add support for getting access token automatically from username/password
|
||||
// ref: https://matrix.org/docs/guides/usage-of-the-matrix-js-sdk#login-with-an-access-token
|
||||
|
||||
@@ -21,7 +26,7 @@ module.exports = function(RED) {
|
||||
|
||||
node.setMaxListeners(1000);
|
||||
|
||||
this.connected = false;
|
||||
this.connected = null;
|
||||
this.name = n.name;
|
||||
this.userId = this.credentials.userId;
|
||||
this.deviceId = this.credentials.deviceId || null;
|
||||
@@ -29,6 +34,7 @@ module.exports = function(RED) {
|
||||
this.autoAcceptRoomInvites = n.autoAcceptRoomInvites;
|
||||
this.enableE2ee = n.enableE2ee || false;
|
||||
this.e2ee = (this.enableE2ee && this.deviceId);
|
||||
this.globalAccess = n.global;
|
||||
|
||||
if(!this.credentials.accessToken) {
|
||||
node.log("Matrix connection failed: missing access token.");
|
||||
@@ -37,6 +43,32 @@ module.exports = function(RED) {
|
||||
} else if(!this.userId) {
|
||||
node.log("Matrix connection failed: missing user ID.");
|
||||
} else {
|
||||
node.setConnected = function(connected, cb) {
|
||||
if (node.connected !== connected) {
|
||||
node.connected = connected;
|
||||
if(typeof cb === 'function') {
|
||||
cb(connected);
|
||||
}
|
||||
|
||||
if (connected) {
|
||||
node.log("Matrix server connection ready.");
|
||||
node.emit("connected");
|
||||
} else {
|
||||
node.emit("disconnected");
|
||||
}
|
||||
|
||||
if(this.globalAccess) {
|
||||
this.context().global.set('matrixClientOnline["'+this.userId+'"]', connected);
|
||||
}
|
||||
}
|
||||
};
|
||||
node.setConnected(false);
|
||||
|
||||
let localStorageDir = storageDir + '/' + MatrixFolderNameFromUserId(this.userId);
|
||||
|
||||
fs.ensureDirSync(storageDir); // create storage directory if it doesn't exist
|
||||
upgradeDirectoryIfNecessary(node, storageDir);
|
||||
const localStorage = new LocalStorage(localStorageDir);
|
||||
node.matrixClient = sdk.createClient({
|
||||
baseUrl: this.url,
|
||||
accessToken: this.credentials.accessToken,
|
||||
@@ -46,6 +78,11 @@ module.exports = function(RED) {
|
||||
deviceId: this.deviceId || undefined,
|
||||
});
|
||||
|
||||
// set globally if configured to do so
|
||||
if(this.globalAccess) {
|
||||
this.context().global.set('matrixClient["'+this.userId+'"]', node.matrixClient);
|
||||
}
|
||||
|
||||
node.on('close', function(done) {
|
||||
if(node.matrixClient) {
|
||||
node.matrixClient.close();
|
||||
@@ -56,18 +93,6 @@ module.exports = function(RED) {
|
||||
done();
|
||||
});
|
||||
|
||||
node.setConnected = function(connected) {
|
||||
if (node.connected !== connected) {
|
||||
node.connected = connected;
|
||||
if (connected) {
|
||||
node.log("Matrix server connection ready.");
|
||||
node.emit("connected");
|
||||
} else {
|
||||
node.emit("disconnected");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
node.isConnected = function() {
|
||||
return node.connected;
|
||||
};
|
||||
@@ -110,20 +135,27 @@ module.exports = function(RED) {
|
||||
node.matrixClient.on("sync", async function(state, prevState, data) {
|
||||
switch (state) {
|
||||
case "ERROR":
|
||||
node.error("Connection to Matrix server lost");
|
||||
node.setConnected(false);
|
||||
node.setConnected(false, function(){
|
||||
node.error("Connection to Matrix server lost");
|
||||
});
|
||||
break;
|
||||
|
||||
case "RECONNECTING":
|
||||
node.setConnected(false, function(){
|
||||
node.log("Trying to reconnect to matrix server");
|
||||
});
|
||||
break;
|
||||
case "STOPPED":
|
||||
node.setConnected(false);
|
||||
node.setConnected(false, function(){
|
||||
node.log("Matrix client stopped");
|
||||
});
|
||||
break;
|
||||
|
||||
case "SYNCING":
|
||||
break;
|
||||
|
||||
case "PREPARED":
|
||||
node.setConnected(true);
|
||||
node.setConnected(true, function(){
|
||||
node.log("Matrix client connected");
|
||||
});
|
||||
break;
|
||||
|
||||
// case "PREPARED":
|
||||
@@ -150,25 +182,19 @@ module.exports = function(RED) {
|
||||
});
|
||||
|
||||
async function run() {
|
||||
if(node.e2ee){
|
||||
const initCrypto = ms => new Promise(res => node.matrixClient.initCrypto());
|
||||
try {
|
||||
await initCrypto();
|
||||
} catch(error){
|
||||
node.error(error);
|
||||
}
|
||||
node.matrixClient.setGlobalErrorOnUnknownDevices(false);
|
||||
}
|
||||
|
||||
const startClient = ms => new Promise(res => node.matrixClient.startClient({ initialSyncLimit: 8 }));
|
||||
try {
|
||||
await startClient();
|
||||
if(node.e2ee){
|
||||
node.log("Initializing crypto...");
|
||||
await node.matrixClient.initCrypto();
|
||||
node.matrixClient.setGlobalErrorOnUnknownDevices(false);
|
||||
}
|
||||
node.log("Connecting to Matrix server...");
|
||||
await node.matrixClient.startClient({ initialSyncLimit: 8 });
|
||||
} catch(error){
|
||||
node.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
node.log("Connecting to Matrix server...");
|
||||
run().catch((error) => node.error(error));
|
||||
}
|
||||
}
|
||||
@@ -181,4 +207,30 @@ module.exports = function(RED) {
|
||||
url: { type: "text", required: true },
|
||||
}
|
||||
});
|
||||
|
||||
function upgradeDirectoryIfNecessary(node, storageDir) {
|
||||
let oldStorageDir = './matrix-local-storage';
|
||||
|
||||
// if the old storage location exists lets move it to it's new location
|
||||
if(fs.pathExistsSync(oldStorageDir)){
|
||||
RED.nodes.eachNode(function(n){
|
||||
try {
|
||||
if(n.type !== 'matrix-server-config') return;
|
||||
let { userId } = RED.nodes.getCredentials(n.id);
|
||||
let dir = storageDir + '/' + MatrixFolderNameFromUserId(userId);
|
||||
if(!fs.pathExistsSync(dir)) {
|
||||
fs.ensureDirSync(dir);
|
||||
node.log("found old '" + oldStorageDir + "' path, copying to new location '" + dir);
|
||||
fs.copySync(oldStorageDir, dir);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
});
|
||||
|
||||
// rename folder to keep as a backup (and so we don't run again)
|
||||
node.log("archiving old config folder '" + oldStorageDir + "' to '" + oldStorageDir + "-backup");
|
||||
fs.renameSync(oldStorageDir, oldStorageDir + "-backup");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@
|
||||
<dd> ID of user to create/edit (ex: @bob:example.com)</dd>
|
||||
|
||||
<dt>msg.payload
|
||||
<span class="property-type">Object</span>
|
||||
<span class="property-type">object</span>
|
||||
</dt>
|
||||
<dd> Details of the new user to create. <a href="https://matrix-org.github.io/synapse/develop/admin_api/user_admin_api.html#create-or-modify-account" target="_blank">Click here</a> to see what valid data you can pass via this input. If the user already exists then optional parameters default to the current value.</dd>
|
||||
</dl>
|
||||
@@ -55,8 +55,6 @@
|
||||
<ol class="node-ports">
|
||||
<li>Success
|
||||
<dl class="message-properties">
|
||||
<dd>original msg object preserved.</dd>
|
||||
|
||||
<dt>msg.payload <span class="property-type">string</span></dt>
|
||||
<dd>the eventId from the posted message.</dd>
|
||||
</dl>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
</div>
|
||||
|
||||
<div class="form-tips" style="margin-bottom: 12px;">
|
||||
User must be an admin to use this endpoint. Only works with Synapse servers. This is permanent so make sure you actually want to do it.
|
||||
User must be an admin to use this endpoint. Only works with Synapse servers. This is permanent so be cautious.
|
||||
</div>
|
||||
</script>
|
||||
|
||||
@@ -79,7 +79,8 @@
|
||||
<ol class="node-ports">
|
||||
<li>Success
|
||||
<dl class="message-properties">
|
||||
<dd>original msg object preserved.</dd>
|
||||
<dt>msg.error <span class="property-type">object</span></dt>
|
||||
<dd>empty object response</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>Error
|
||||
|
||||
@@ -55,7 +55,13 @@ module.exports = function(RED) {
|
||||
{ $userId: msg.userId },
|
||||
);
|
||||
node.server.matrixClient.http
|
||||
.authedRequest(undefined, 'POST', path, undefined, { "erase": (msg.erase || false) }, { prefix: '' })
|
||||
.authedRequest(
|
||||
undefined,
|
||||
'POST',
|
||||
path,
|
||||
undefined,
|
||||
{"erase": (msg.erase || false)},
|
||||
{"prefix": '' })
|
||||
.then(function(e){
|
||||
msg.payload = e;
|
||||
node.send([msg, null]);
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
<dt>msg.topic
|
||||
<span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd> The room identifier or alias to join: for example, <code>!h8zld9j31:example.com.</code>. Not required if set in the config and will be ignored even if set.</dd>
|
||||
<dd> The room identifier or alias to join: for example, <code>!h8zld9j31:example.com.</code>. Ignored if configured on the node, otherwise required.</dd>
|
||||
|
||||
<dt>msg.userId
|
||||
<span class="property-type">string</span>
|
||||
@@ -63,8 +63,8 @@
|
||||
<ol class="node-ports">
|
||||
<li>Success
|
||||
<dl class="message-properties">
|
||||
<dt>msg.payload <span class="property-type">string</span></dt>
|
||||
<dd>This returns data directly from the API endpoint. <a href="https://matrix-org.github.io/synapse/develop/admin_api/user_admin_api.html#query-current-sessions-for-a-user" target="_blank">Click here</a> to see what this returns.</dd>
|
||||
<dt>msg.topic <span class="property-type">string</span></dt>
|
||||
<dd> the ID of the room we just added the user to.</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>Error
|
||||
|
||||
@@ -46,8 +46,8 @@ module.exports = function(RED) {
|
||||
node.send([null, msg]);
|
||||
}
|
||||
|
||||
let roomId = node.roomId || msg.topic;
|
||||
if(!roomId) {
|
||||
msg.topic = node.roomId || msg.topic;
|
||||
if(!msg.topic) {
|
||||
node.error("room must be defined in either msg.topic or in node config");
|
||||
return;
|
||||
}
|
||||
@@ -64,13 +64,13 @@ module.exports = function(RED) {
|
||||
'POST',
|
||||
node.encodeUri(
|
||||
"/_synapse/admin/v1/join/$room_id_or_alias",
|
||||
{ $room_id_or_alias: roomId },
|
||||
{ $room_id_or_alias: msg.topic },
|
||||
),
|
||||
undefined,
|
||||
{ "user_id": msg.userId },
|
||||
{ prefix: '' }
|
||||
).then(function(e){
|
||||
msg.payload = e;
|
||||
msg.topic = e.room_id;
|
||||
node.send([msg, null]);
|
||||
}).catch(function(e){
|
||||
node.warn("Error joining user to room " + e);
|
||||
|
||||
@@ -51,32 +51,32 @@
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>msg.payload
|
||||
<span class="property-type">Object</span>
|
||||
<span class="property-type">object</span>
|
||||
</dt>
|
||||
<dd> Details of the new user to create. </dd>
|
||||
|
||||
<dt class="optional">msg.payload.displayname
|
||||
<span class="property-type">String | null</span>
|
||||
<span class="property-type">string | null</span>
|
||||
</dt>
|
||||
<dd> Set the displayname for the user (default to username if not set). </dd>
|
||||
|
||||
<dt>msg.payload.username
|
||||
<span class="property-type">Object</span>
|
||||
<span class="property-type">object</span>
|
||||
</dt>
|
||||
<dd> Username for the new user. </dd>
|
||||
|
||||
<dt>msg.payload.password
|
||||
<span class="property-type">String</span>
|
||||
<span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd> Password for the new user. </dd>
|
||||
|
||||
<dt>msg.payload.admin
|
||||
<span class="property-type">Bool</span>
|
||||
<span class="property-type">bool</span>
|
||||
</dt>
|
||||
<dd> If true, the new user will be an admin. Default to false. </dd>
|
||||
|
||||
<dt class="optional">msg.payload.user_type
|
||||
<span class="property-type">String | null</span>
|
||||
<span class="property-type">string | null</span>
|
||||
</dt>
|
||||
<dd> Set the user type. Leave this to null if you don't know what it is for. Check <a href="https://github.com/matrix-org/synapse/blob/master/synapse/api/constants.py">here</a> and look for <code>class UserTypes</code> to figure out what is valid.</dd>
|
||||
</dl>
|
||||
@@ -84,9 +84,7 @@
|
||||
<h3>Outputs</h3>
|
||||
<ol class="node-ports">
|
||||
<li>Success
|
||||
<dl class="message-properties">
|
||||
<dd>original msg object preserved.</dd>
|
||||
|
||||
<dl class="message-properties">`
|
||||
<dt>msg.eventId <span class="property-type">string</span></dt>
|
||||
<dd>the eventId from the posted message.</dd>
|
||||
</dl>
|
||||
|
||||
@@ -39,22 +39,22 @@
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt class="optional">msg.from
|
||||
<span class="property-type">Integer</span>
|
||||
<span class="property-type">integer</span>
|
||||
</dt>
|
||||
<dd> Is optional but used for pagination, denoting the offset in the returned results. This should be treated as an opaque value and not explicitly set to anything other than the return value of next_token from a previous call. Defaults to 0.</dd>
|
||||
<dd> Is optional but used for pagination, denoting the offset in the returned results. This should be treated as an opaque value and not explicitly set to anything other than the return value of <code>msg.next_token</code> from a previous call. Defaults to 0.</dd>
|
||||
|
||||
<dt class="optional">msg.limit
|
||||
<span class="property-type">Integer</span>
|
||||
<span class="property-type">integer</span>
|
||||
</dt>
|
||||
<dd> limit - representing a positive integer - Is optional but is used for pagination, denoting the maximum number of items to return in this call. Defaults to 100.</dd>
|
||||
|
||||
<dt class="optional">msg.guests
|
||||
<span class="property-type">Bool</span>
|
||||
<span class="property-type">bool</span>
|
||||
</dt>
|
||||
<dd> Is optional and if false will exclude guest users. Defaults to true to include guest users.</dd>
|
||||
|
||||
<dt class="optional">msg.order_by
|
||||
<span class="property-type">String</span>
|
||||
<span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd>
|
||||
The method by which to sort the returned list of users.
|
||||
@@ -85,14 +85,41 @@
|
||||
<dt>msg.payload <span class="property-type">object</span></dt>
|
||||
<dd>the response object from the server.</dd>
|
||||
|
||||
<dt>msg.payload.next_token <span class="property-type">string</span></dt>
|
||||
<dd>string representing a positive integer - Indication for pagination. If this is unset then there are no more users to paginate through.</dd>
|
||||
|
||||
<dt>msg.payload.total <span class="property-type">integer</span></dt>
|
||||
<dd>Total number of users.</dd>
|
||||
|
||||
<dt>msg.payload.users <span class="property-type">array</span></dt>
|
||||
<dd>list of users from the Matrix server. <a href="https://matrix-org.github.io/synapse/develop/admin_api/user_admin_api.html#list-accounts" target="_blank">Click here</a> for details on what this contains (or do a test and dump the output). We would put the details here in the doc but Synapse is constantly changing so it's best to reference the official Synapse docs.</dd>
|
||||
<dd>list of users from the Matrix server. <a href="https://matrix-org.github.io/synapse/develop/admin_api/user_admin_api.html#list-accounts" target="_blank">Click here</a> for details on what this contains (or do a debug on the output).</dd>
|
||||
|
||||
<dt>msg.next_token <span class="property-type">string</span></dt>
|
||||
<dd>string representing a positive integer - Indication for pagination. See above (input msg.from)</dd>
|
||||
<dt>msg.payload.users[].name <span class="property-type">string</span></dt>
|
||||
<dd>Fully-qualified user ID (ex. <code>@user:server.com</code>).</dd>
|
||||
|
||||
<dt>msg.total <span class="property-type">integer</span></dt>
|
||||
<dd>Total number of media.</dd>
|
||||
<dt>msg.payload.users[].is_guest <span class="property-type">bool</span></dt>
|
||||
<dd>Status if that user is a guest account.</dd>
|
||||
|
||||
<dt>msg.payload.users[].admin <span class="property-type">string</span></dt>
|
||||
<dd>Status if that user is a server administrator.</dd>
|
||||
|
||||
<dt>msg.payload.users[].user_type <span class="property-type">string</span></dt>
|
||||
<dd>Type of the user. Normal users are type <code>None</code>. This allows user type specific behaviour. There are also types <code>support</code> and <code>bot</code>.</dd>
|
||||
|
||||
<dt>msg.payload.users[].deactivated <span class="property-type">bool</span></dt>
|
||||
<dd>Status if that user has been marked as deactivated.</dd>
|
||||
|
||||
<dt>msg.payload.users[].shadow_banned <span class="property-type">bool</span></dt>
|
||||
<dd>Status if that user has been marked as shadow banned.</dd>
|
||||
|
||||
<dt>msg.payload.users[].displayname <span class="property-type">string</span></dt>
|
||||
<dd>The user's display name if they have set one.</dd>
|
||||
|
||||
<dt>msg.payload.users[].avatar_url <span class="property-type">string</span></dt>
|
||||
<dd>The user's avatar URL if they have set one.</dd>
|
||||
|
||||
<dt>msg.payload.users[].creation_ts <span class="property-type">integer</span></dt>
|
||||
<dd>The user's creation timestamp in ms.</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>Error
|
||||
|
||||
@@ -39,7 +39,7 @@ module.exports = function(RED) {
|
||||
};
|
||||
|
||||
if(msg.guests) {
|
||||
queryParams['guests'] = msg.guests;
|
||||
queryParams['guests'] = msg.guests ? 'true' : 'false';
|
||||
}
|
||||
|
||||
if(msg.order_by) {
|
||||
@@ -58,7 +58,7 @@ module.exports = function(RED) {
|
||||
msg.payload = e;
|
||||
node.send([msg, null]);
|
||||
}).catch(function(e){
|
||||
node.warn("Error fetching user list " + e);
|
||||
node.warn("Error fetching server user list " + e);
|
||||
msg.error = e;
|
||||
node.send([null, msg]);
|
||||
});
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
<script type="text/html" data-help-name="matrix-whois-user">
|
||||
<h3>Details</h3>
|
||||
<p>This node returns information about the active sessions for a specific user.</p>
|
||||
<a href="https://matrix-org.github.io/synapse/develop/admin_api/user_admin_api.html#query-current-sessions-for-a-user" target="_blank">Matrix API Endpoint Information</a>
|
||||
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
@@ -49,8 +50,29 @@
|
||||
<ol class="node-ports">
|
||||
<li>Success
|
||||
<dl class="message-properties">
|
||||
<dt>msg.payload <span class="property-type">string</span></dt>
|
||||
<dd>This returns data directly from the API endpoint. <a href="https://matrix-org.github.io/synapse/develop/admin_api/user_admin_api.html#query-current-sessions-for-a-user" target="_blank">Click here</a> to see what this returns.</dd>
|
||||
<dt>msg.payload <span class="property-type">object</span></dt>
|
||||
<dd>This returns data directly from the API endpoint. <a href="https://matrix-org.github.io/synapse/develop/admin_api/user_admin_api.html#query-current-sessions-for-a-user" target="_blank">Click here</a> to see more info.</dd>
|
||||
|
||||
<dt>msg.payload.user_id <span class="property-type">string</span></dt>
|
||||
<dd>The Matrix user ID of the user.</dd>
|
||||
|
||||
<dt>msg.payload.devices <span class="property-type">object</span></dt>
|
||||
<dd>Each key in this object is an identifier for one of the user's devices.</dd>
|
||||
|
||||
<dt>msg.payload.devices.X.sessions <span class="property-type">array</span></dt>
|
||||
<dd>A user's sessions (i.e. what they did with an access token from one login).</dd>
|
||||
|
||||
<dt>msg.payload.devices.X.sessions[].connections <span class="property-type">array</span></dt>
|
||||
<dd>Information about particular connections in the session.</dd>
|
||||
|
||||
<dt>msg.payload.devices.X.sessions[].connections[].ip <span class="property-type">string</span></dt>
|
||||
<dd>Most recently seen IP address of the session.</dd>
|
||||
|
||||
<dt>msg.payload.devices.X.sessions[].connections[].last_seen <span class="property-type">integer</span></dt>
|
||||
<dd>Unix timestamp that the session was last active.</dd>
|
||||
|
||||
<dt>msg.payload.devices.X.sessions[].connections[].user_agent <span class="property-type">string</span></dt>
|
||||
<dd>User agent string last seen in the session.</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>Error
|
||||
|
||||
@@ -63,13 +63,13 @@ module.exports = function(RED) {
|
||||
msg.payload,
|
||||
{ prefix: '' }
|
||||
).then(function(e){
|
||||
msg.payload = e;
|
||||
node.send([msg, null]);
|
||||
}).catch(function(e){
|
||||
node.warn("Error creating/editing user " + e);
|
||||
msg.error = e;
|
||||
node.send([null, msg]);
|
||||
});
|
||||
msg.payload = e;
|
||||
node.send([msg, null]);
|
||||
}).catch(function(e){
|
||||
node.warn("Error fetching user whois information " + e);
|
||||
msg.error = e;
|
||||
node.send([null, msg]);
|
||||
});
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("matrix-whois-user", MatrixWhoIsUser);
|
||||
|
||||
Reference in New Issue
Block a user