@patricktobias86/node-red-telegram-account 1.1.9 → 1.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -0
- package/CHANGELOG.md +10 -0
- package/README.md +3 -1
- package/docs/NODES.md +2 -1
- package/nodes/auth.js +18 -17
- package/nodes/delete-message.html +1 -1
- package/nodes/delete-message.js +7 -5
- package/nodes/get-entity.js +2 -2
- package/nodes/iter-dialogs.js +1 -1
- package/nodes/iter-messages.js +2 -2
- package/nodes/promote-admin.js +1 -1
- package/nodes/receiver.js +3 -2
- package/nodes/resolve-userid.js +2 -2
- package/nodes/send-file.js +1 -1
- package/nodes/send-message.js +1 -1
- package/package.json +1 -1
- package/test/pass-through.test.js +41 -0
- package/test/receiver-debug.test.js +44 -0
package/AGENTS.md
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -13,3 +13,13 @@ All notable changes to this project will be documented in this file.
|
|
|
13
13
|
### Fixed
|
|
14
14
|
- Receiver and Command nodes now remove their event listeners when closed to prevent duplicate messages after redeploys.
|
|
15
15
|
|
|
16
|
+
## [1.1.10] - 2025-07-27
|
|
17
|
+
### Fixed
|
|
18
|
+
- Receiver node no longer fails when Debug is enabled and handles updates containing `BigInt` values.
|
|
19
|
+
### Changed
|
|
20
|
+
- `delete-message` now forwards the original message along with the Telegram API response.
|
|
21
|
+
|
|
22
|
+
## [1.1.11] - 2025-08-04
|
|
23
|
+
### Fixed
|
|
24
|
+
- All nodes now preserve properties on the incoming message outside of the payload.
|
|
25
|
+
|
package/README.md
CHANGED
|
@@ -23,12 +23,14 @@ See [docs/NODES.md](docs/NODES.md) for a detailed description of every node. Bel
|
|
|
23
23
|
- **send-message** – sends text or media messages with rich options.
|
|
24
24
|
- **send-files** – uploads one or more files with captions and buttons.
|
|
25
25
|
- **get-entity** – resolves usernames, IDs or t.me links into Telegram entities.
|
|
26
|
-
- **delete-message** – deletes one or more messages, optionally revoking them.
|
|
26
|
+
- **delete-message** – deletes one or more messages, optionally revoking them, and forwards the original input message with the API response.
|
|
27
27
|
- **iter-dialogs** – iterates over your dialogs (chats, groups, channels).
|
|
28
28
|
- **iter-messages** – iterates over messages in a chat with filtering options.
|
|
29
29
|
- **promote-admin** – promotes a user to admin with configurable rights.
|
|
30
30
|
- **resolve-userid** – converts a username to a numeric user ID.
|
|
31
31
|
|
|
32
|
+
All nodes preserve any properties on the incoming message outside of <code>msg.payload</code>.
|
|
33
|
+
|
|
32
34
|
All nodes include a <code>Debug</code> option that logs incoming and outgoing messages to the Node-RED log when enabled.
|
|
33
35
|
|
|
34
36
|
## Session management
|
package/docs/NODES.md
CHANGED
|
@@ -13,12 +13,13 @@ Below is a short description of each node. For a full list of configuration opti
|
|
|
13
13
|
| **send-message** | Sends text messages or media files to a chat. Supports parse mode, buttons, scheduling, and more. |
|
|
14
14
|
| **send-files** | Uploads one or more files to a chat with optional caption, thumbnails and other parameters. |
|
|
15
15
|
| **get-entity** | Resolves a username, user ID or t.me URL into a Telegram entity object. |
|
|
16
|
-
| **delete-message** | Deletes one or multiple messages from a chat. Can revoke messages for all participants. |
|
|
16
|
+
| **delete-message** | Deletes one or multiple messages from a chat while passing the original input message along with the API response. Can revoke messages for all participants. |
|
|
17
17
|
| **iter-dialogs** | Iterates through the user’s dialogs (chats, groups, channels) and outputs the collected list. |
|
|
18
18
|
| **iter-messages** | Iterates over messages in a chat with various filtering and pagination options. |
|
|
19
19
|
| **promote-admin** | Grants admin rights to a user in a group or channel with configurable permissions. |
|
|
20
20
|
| **resolve-userid** | Converts a Telegram username to its numeric user ID. |
|
|
21
21
|
|
|
22
|
+
All nodes forward any properties on the incoming `msg` outside of `msg.payload` unchanged.
|
|
22
23
|
|
|
23
24
|
All nodes provide a **Debug** checkbox. When enabled the node will log its input and output messages to aid troubleshooting.
|
|
24
25
|
|
package/nodes/auth.js
CHANGED
|
@@ -58,27 +58,28 @@ module.exports = function (RED) {
|
|
|
58
58
|
]
|
|
59
59
|
});
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
61
|
+
const out = {
|
|
62
|
+
...msg,
|
|
63
|
+
topic: "auth_success",
|
|
64
|
+
payload: {
|
|
65
|
+
stringSession,
|
|
66
|
+
message: "Authorization successful!"
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
node.send(out);
|
|
70
|
+
if (debug) {
|
|
71
|
+
node.log('auth output: ' + JSON.stringify(out));
|
|
72
|
+
}
|
|
72
73
|
|
|
73
74
|
node.status({ fill: "green", shape: "dot", text: "Authenticated" });
|
|
74
75
|
|
|
75
76
|
} catch (err) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
77
|
+
node.error("Authentication failed: " + err.message);
|
|
78
|
+
const out = { ...msg, topic: "auth_error", payload: { error: err.message } };
|
|
79
|
+
node.send(out);
|
|
80
|
+
if (debug) {
|
|
81
|
+
node.log('auth output: ' + JSON.stringify(out));
|
|
82
|
+
}
|
|
82
83
|
node.status({ fill: "red", shape: "ring", text: "Failed" });
|
|
83
84
|
}
|
|
84
85
|
});
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
<dt>payload
|
|
83
83
|
<span class="property-type">object</span>
|
|
84
84
|
</dt>
|
|
85
|
-
<dd>The response from the Telegram API, confirming the deletion.</dd>
|
|
85
|
+
<dd>The response from the Telegram API, confirming the deletion. All other properties from the input message are preserved.</dd>
|
|
86
86
|
</dl>
|
|
87
87
|
|
|
88
88
|
<h3>Details</h3>
|
package/nodes/delete-message.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const util = require("util");
|
|
2
|
+
|
|
1
3
|
module.exports = function (RED) {
|
|
2
4
|
function DeleteMessage(config) {
|
|
3
5
|
RED.nodes.createNode(this, config);
|
|
@@ -8,21 +10,21 @@ module.exports = function (RED) {
|
|
|
8
10
|
this.on('input', async function (msg) {
|
|
9
11
|
const debug = node.debugEnabled || msg.debug;
|
|
10
12
|
if (debug) {
|
|
11
|
-
node.log('delete-message input: ' +
|
|
13
|
+
node.log('delete-message input: ' + util.inspect(msg, { depth: null }));
|
|
12
14
|
}
|
|
13
15
|
const chatId = msg.payload.chatId || config.chatId;
|
|
14
16
|
const messageIds = msg.payload.messageIds || config.messageIds;
|
|
15
|
-
const revoke = msg.payload.revoke
|
|
17
|
+
const revoke = msg.payload.revoke ?? config.revoke ?? true;
|
|
16
18
|
/** @type {TelegramClient} */
|
|
17
19
|
const client = msg.payload?.client ? msg.payload.client : this.config.client;
|
|
18
20
|
|
|
19
21
|
try {
|
|
20
|
-
const response = await client.deleteMessages(chatId, messageIds, revoke);
|
|
22
|
+
const response = await client.deleteMessages(chatId, messageIds, { revoke });
|
|
21
23
|
|
|
22
|
-
const out = { payload: response };
|
|
24
|
+
const out = { ...msg, payload: response };
|
|
23
25
|
node.send(out);
|
|
24
26
|
if (debug) {
|
|
25
|
-
node.log('delete-message output: ' +
|
|
27
|
+
node.log('delete-message output: ' + util.inspect(out, { depth: null }));
|
|
26
28
|
}
|
|
27
29
|
} catch (err) {
|
|
28
30
|
node.error('Error deleting message: ' + err.message);
|
package/nodes/get-entity.js
CHANGED
|
@@ -25,14 +25,14 @@ module.exports = function (RED) {
|
|
|
25
25
|
entity = await client.getEntity(input);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
const out = { payload: { input: entity } };
|
|
28
|
+
const out = { ...msg, payload: { input: entity } };
|
|
29
29
|
node.send(out);
|
|
30
30
|
if (debug) {
|
|
31
31
|
node.log('get-entity output: ' + JSON.stringify(out));
|
|
32
32
|
}
|
|
33
33
|
} catch (err) {
|
|
34
34
|
node.error('Error getting entity: ' + err.message);
|
|
35
|
-
const out = { payload: { input: null } };
|
|
35
|
+
const out = { ...msg, payload: { input: null } };
|
|
36
36
|
node.send(out);
|
|
37
37
|
if (debug) {
|
|
38
38
|
node.log('get-entity output: ' + JSON.stringify(out));
|
package/nodes/iter-dialogs.js
CHANGED
|
@@ -45,7 +45,7 @@ module.exports = function (RED) {
|
|
|
45
45
|
dialogs[dialog.id] = dialog;
|
|
46
46
|
console.log(`${dialog.id}: ${dialog.title}`);
|
|
47
47
|
}
|
|
48
|
-
const out = { payload: { dialogs } };
|
|
48
|
+
const out = { ...msg, payload: { dialogs } };
|
|
49
49
|
node.send(out);
|
|
50
50
|
if (debug) {
|
|
51
51
|
node.log('iter-dialogs output: ' + JSON.stringify(out));
|
package/nodes/iter-messages.js
CHANGED
|
@@ -84,8 +84,8 @@ module.exports = function (RED) {
|
|
|
84
84
|
console.log(message.id, message.text);
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
|
-
|
|
88
|
-
const out = { payload: { messages } };
|
|
87
|
+
|
|
88
|
+
const out = { ...msg, payload: { messages } };
|
|
89
89
|
node.send(out);
|
|
90
90
|
if (debug) {
|
|
91
91
|
node.log('iter-messages output: ' + JSON.stringify(out));
|
package/nodes/promote-admin.js
CHANGED
|
@@ -44,7 +44,7 @@ module.exports = function (RED) {
|
|
|
44
44
|
rank: rank,
|
|
45
45
|
}));
|
|
46
46
|
|
|
47
|
-
const out = { payload: { response: result } };
|
|
47
|
+
const out = { ...msg, payload: { response: result } };
|
|
48
48
|
node.send(out);
|
|
49
49
|
if (debug) {
|
|
50
50
|
node.log('promote-admin output: ' + JSON.stringify(out));
|
package/nodes/receiver.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const { NewMessage } = require("telegram/events");
|
|
2
|
+
const util = require("util");
|
|
2
3
|
|
|
3
4
|
module.exports = function (RED) {
|
|
4
5
|
function Receiver(config) {
|
|
@@ -13,13 +14,13 @@ module.exports = function (RED) {
|
|
|
13
14
|
const handler = (update) => {
|
|
14
15
|
const debug = node.debugEnabled;
|
|
15
16
|
if (debug) {
|
|
16
|
-
node.log('receiver update: ' +
|
|
17
|
+
node.log('receiver update: ' + util.inspect(update, { depth: null }));
|
|
17
18
|
}
|
|
18
19
|
if (update.message.fromId != null && !ignore.includes(update.message.fromId.userId.toString())) {
|
|
19
20
|
const out = { payload: { update } };
|
|
20
21
|
node.send(out);
|
|
21
22
|
if (debug) {
|
|
22
|
-
node.log('receiver output: ' +
|
|
23
|
+
node.log('receiver output: ' + util.inspect(out, { depth: null }));
|
|
23
24
|
}
|
|
24
25
|
}
|
|
25
26
|
};
|
package/nodes/resolve-userid.js
CHANGED
|
@@ -30,14 +30,14 @@ module.exports = function(RED) {
|
|
|
30
30
|
} else if (entity?.userId) {
|
|
31
31
|
userId = entity.userId;
|
|
32
32
|
}
|
|
33
|
-
const out = { payload: { userId } };
|
|
33
|
+
const out = { ...msg, payload: { userId } };
|
|
34
34
|
node.send(out);
|
|
35
35
|
if (debug) {
|
|
36
36
|
node.log('resolve-userid output: ' + JSON.stringify(out));
|
|
37
37
|
}
|
|
38
38
|
} catch (err) {
|
|
39
39
|
node.error('Error resolving username: ' + err.message);
|
|
40
|
-
const out = { payload: { userId: null } };
|
|
40
|
+
const out = { ...msg, payload: { userId: null } };
|
|
41
41
|
node.send(out);
|
|
42
42
|
if (debug) {
|
|
43
43
|
node.log('resolve-userid output: ' + JSON.stringify(out));
|
package/nodes/send-file.js
CHANGED
|
@@ -64,7 +64,7 @@ module.exports = function (RED) {
|
|
|
64
64
|
|
|
65
65
|
// Send files
|
|
66
66
|
const response = await client.sendFile(chatId, params);
|
|
67
|
-
const out = { payload: response };
|
|
67
|
+
const out = { ...msg, payload: response };
|
|
68
68
|
node.send(out);
|
|
69
69
|
if (debug) {
|
|
70
70
|
node.log('send-files output: ' + JSON.stringify(out));
|
package/nodes/send-message.js
CHANGED
|
@@ -73,7 +73,7 @@ module.exports = function (RED) {
|
|
|
73
73
|
await client.sendMessage(entity, params);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
const out = { payload: { response } };
|
|
76
|
+
const out = { ...msg, payload: { response } };
|
|
77
77
|
node.send(out);
|
|
78
78
|
if (debug) {
|
|
79
79
|
node.log('send-message output: ' + JSON.stringify(out));
|
package/package.json
CHANGED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const assert = require('assert');
|
|
2
|
+
const proxyquire = require('proxyquire').noPreserveCache();
|
|
3
|
+
|
|
4
|
+
function setup() {
|
|
5
|
+
let NodeCtor;
|
|
6
|
+
let sent;
|
|
7
|
+
const configNode = { client: {} };
|
|
8
|
+
const RED = {
|
|
9
|
+
nodes: {
|
|
10
|
+
createNode(node) {
|
|
11
|
+
node._events = {};
|
|
12
|
+
node.on = (e, fn) => { node._events[e] = fn; };
|
|
13
|
+
node.send = (msg) => { sent = msg; };
|
|
14
|
+
node.log = () => {};
|
|
15
|
+
node.error = () => {};
|
|
16
|
+
},
|
|
17
|
+
registerType(name, ctor) { NodeCtor = ctor; },
|
|
18
|
+
getNode() { return configNode; }
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
proxyquire('../nodes/send-message.js', {
|
|
23
|
+
telegram: { TelegramClient: function() {} },
|
|
24
|
+
'telegram/Utils': { parseID: () => ({}) }
|
|
25
|
+
})(RED);
|
|
26
|
+
|
|
27
|
+
return { NodeCtor, getSent: () => sent };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
describe('message property relay', function() {
|
|
31
|
+
it('keeps non-payload properties on send-message output', async function() {
|
|
32
|
+
const { NodeCtor, getSent } = setup();
|
|
33
|
+
const node = new NodeCtor({ config: 'c', file: "" });
|
|
34
|
+
const client = { sendMessage: async () => 'ok' };
|
|
35
|
+
const msg = { foo: 'bar', payload: { client, chatId: 'me', message: 'hi' } };
|
|
36
|
+
await node._events['input'](msg);
|
|
37
|
+
const out = getSent();
|
|
38
|
+
assert.strictEqual(out.foo, 'bar');
|
|
39
|
+
assert.deepStrictEqual(out.payload.response, 'ok');
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const assert = require('assert');
|
|
2
|
+
const proxyquire = require('proxyquire').noPreserveCache();
|
|
3
|
+
|
|
4
|
+
function load() {
|
|
5
|
+
const addCalls = [];
|
|
6
|
+
const logs = [];
|
|
7
|
+
class TelegramClientStub {
|
|
8
|
+
addEventHandler(fn, event) { addCalls.push({fn, event}); }
|
|
9
|
+
removeEventHandler() {}
|
|
10
|
+
}
|
|
11
|
+
class NewMessageStub {}
|
|
12
|
+
|
|
13
|
+
let NodeCtor;
|
|
14
|
+
const configNode = { client: new TelegramClientStub() };
|
|
15
|
+
const RED = {
|
|
16
|
+
nodes: {
|
|
17
|
+
createNode(node) {
|
|
18
|
+
node._events = {};
|
|
19
|
+
node.on = (e, fn) => { node._events[e] = fn; };
|
|
20
|
+
node.log = (msg) => logs.push(msg);
|
|
21
|
+
node.send = () => {};
|
|
22
|
+
},
|
|
23
|
+
registerType(name, ctor) { NodeCtor = ctor; },
|
|
24
|
+
getNode() { return configNode; }
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
proxyquire('../nodes/receiver.js', {
|
|
29
|
+
'telegram/events': { NewMessage: NewMessageStub }
|
|
30
|
+
})(RED);
|
|
31
|
+
|
|
32
|
+
return { NodeCtor, addCalls, logs };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
describe('Receiver node debug with BigInt', function() {
|
|
36
|
+
it('logs update and output without throwing', function() {
|
|
37
|
+
const { NodeCtor, addCalls, logs } = load();
|
|
38
|
+
const node = new NodeCtor({config:'c', ignore:'', debug:true});
|
|
39
|
+
const handler = addCalls[0].fn;
|
|
40
|
+
assert.doesNotThrow(() => handler({ message: { fromId:{userId:1n} } }));
|
|
41
|
+
assert(logs.some(l => l.includes('receiver update')));
|
|
42
|
+
assert(logs.some(l => l.includes('receiver output')));
|
|
43
|
+
});
|
|
44
|
+
});
|