@patricktobias86/node-red-telegram-account 1.0.6
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/.gitattributes +2 -0
- package/.github/workflows/npm-publish.yml +33 -0
- package/README.md +1 -0
- package/icons/tg.png +0 -0
- package/nodes/auth.html +138 -0
- package/nodes/auth.js +60 -0
- package/nodes/command.html +135 -0
- package/nodes/command.js +53 -0
- package/nodes/config.html +131 -0
- package/nodes/config.js +58 -0
- package/nodes/delete-message.html +96 -0
- package/nodes/delete-message.js +27 -0
- package/nodes/get-entity.html +87 -0
- package/nodes/get-entity.js +36 -0
- package/nodes/iter-dialogs.html +212 -0
- package/nodes/iter-dialogs.js +54 -0
- package/nodes/iter-messages.html +365 -0
- package/nodes/iter-messages.js +94 -0
- package/nodes/promote-admin.html +24 -0
- package/nodes/promote-admin.js +55 -0
- package/nodes/receiver.html +128 -0
- package/nodes/receiver.js +32 -0
- package/nodes/send-file.html +463 -0
- package/nodes/send-file.js +72 -0
- package/nodes/send-message.html +300 -0
- package/nodes/send-message.js +83 -0
- package/package.json +50 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
RED.nodes.registerType('iter-messages', {
|
|
3
|
+
category: 'telegram',
|
|
4
|
+
color: '#32a3e0',
|
|
5
|
+
defaults: {
|
|
6
|
+
name: { value: '' },
|
|
7
|
+
config: { type: 'config', required: true },
|
|
8
|
+
chatId: { value: '', required: false },
|
|
9
|
+
limit: { value: '', required: false },
|
|
10
|
+
offsetDate: { value: '', required: false },
|
|
11
|
+
offsetId: { value: '', required: false },
|
|
12
|
+
maxId: { value: '', required: false },
|
|
13
|
+
minId: { value: '', required: false },
|
|
14
|
+
addOffset: { value: '', required: false },
|
|
15
|
+
search: { value: '', required: false },
|
|
16
|
+
filter: { value: '', required: false },
|
|
17
|
+
fromUser: { value: '', required: false },
|
|
18
|
+
waitTime: { value: '', required: false },
|
|
19
|
+
messageIds: { value: '', required: false },
|
|
20
|
+
reverse: { value: '', required: false },
|
|
21
|
+
replyTo: { value: '', required: false },
|
|
22
|
+
scheduled: { value: '', required: false }
|
|
23
|
+
},
|
|
24
|
+
inputs: 1,
|
|
25
|
+
outputs: 1,
|
|
26
|
+
paletteLabel: 'Iterate Messages',
|
|
27
|
+
label: function () {
|
|
28
|
+
return this.name || 'Iterate Messages';
|
|
29
|
+
},
|
|
30
|
+
oneditprepare: function(){
|
|
31
|
+
const node = this;
|
|
32
|
+
$("#node-input-messageIds").val((node.messageIds || []).join(","))
|
|
33
|
+
},
|
|
34
|
+
oneditsave:function(){
|
|
35
|
+
const node = this;
|
|
36
|
+
const messageIds = $("#node-input-messageIds").val();
|
|
37
|
+
if(messageIds){
|
|
38
|
+
node.messageIds = messageIds.split(",").map(id => parseInt(id))
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<script type="text/html" data-template-name="iter-messages">
|
|
45
|
+
<div class="form-row">
|
|
46
|
+
<label for="node-input-name">
|
|
47
|
+
<i class="fa fa-tag"></i> Name
|
|
48
|
+
</label>
|
|
49
|
+
<input
|
|
50
|
+
type="text"
|
|
51
|
+
id="node-input-name"
|
|
52
|
+
placeholder="Name"
|
|
53
|
+
style="width: 60%"
|
|
54
|
+
ng-model="name"
|
|
55
|
+
/>
|
|
56
|
+
</div>
|
|
57
|
+
<div class="form-row">
|
|
58
|
+
<label for="node-input-config">
|
|
59
|
+
<i class="fa fa-tag"></i> Config
|
|
60
|
+
</label>
|
|
61
|
+
<input
|
|
62
|
+
type="text"
|
|
63
|
+
id="node-input-config"
|
|
64
|
+
placeholder="Config"
|
|
65
|
+
style="width: 60%"
|
|
66
|
+
ng-model="config"
|
|
67
|
+
/>
|
|
68
|
+
</div>
|
|
69
|
+
<div class="form-row">
|
|
70
|
+
<label for="node-input-chatId">
|
|
71
|
+
<i class="fa fa-tag"></i> Chat ID
|
|
72
|
+
</label>
|
|
73
|
+
<input
|
|
74
|
+
type="text"
|
|
75
|
+
id="node-input-chatId"
|
|
76
|
+
placeholder="Chat ID"
|
|
77
|
+
style="width: 60%"
|
|
78
|
+
ng-model="chatId"
|
|
79
|
+
/>
|
|
80
|
+
</div>
|
|
81
|
+
<div class="form-row">
|
|
82
|
+
<label for="node-input-limit">
|
|
83
|
+
<i class="fa fa-tag"></i> Limit
|
|
84
|
+
</label>
|
|
85
|
+
<input
|
|
86
|
+
type="number"
|
|
87
|
+
id="node-input-limit"
|
|
88
|
+
placeholder="Limit"
|
|
89
|
+
style="width: 60%"
|
|
90
|
+
ng-model="limit"
|
|
91
|
+
/>
|
|
92
|
+
</div>
|
|
93
|
+
<div class="form-row">
|
|
94
|
+
<label for="node-input-offsetDate">
|
|
95
|
+
<i class="fa fa-tag"></i> Offset Date
|
|
96
|
+
</label>
|
|
97
|
+
<input
|
|
98
|
+
type="datetime-local"
|
|
99
|
+
id="node-input-offsetDate"
|
|
100
|
+
placeholder="Offset Date"
|
|
101
|
+
style="width: 60%"
|
|
102
|
+
ng-model="offsetDate"
|
|
103
|
+
/>
|
|
104
|
+
</div>
|
|
105
|
+
<div class="form-row">
|
|
106
|
+
<label for="node-input-offsetId">
|
|
107
|
+
<i class="fa fa-tag"></i> Offset ID
|
|
108
|
+
</label>
|
|
109
|
+
<input
|
|
110
|
+
type="number"
|
|
111
|
+
id="node-input-offsetId"
|
|
112
|
+
placeholder="Offset ID"
|
|
113
|
+
style="width: 60%"
|
|
114
|
+
ng-model="offsetId"
|
|
115
|
+
/>
|
|
116
|
+
</div>
|
|
117
|
+
<div class="form-row">
|
|
118
|
+
<label for="node-input-maxId">
|
|
119
|
+
<i class="fa fa-tag"></i> Max ID
|
|
120
|
+
</label>
|
|
121
|
+
<input
|
|
122
|
+
type="number"
|
|
123
|
+
id="node-input-maxId"
|
|
124
|
+
placeholder="Max ID"
|
|
125
|
+
style="width: 60%"
|
|
126
|
+
ng-model="maxId"
|
|
127
|
+
/>
|
|
128
|
+
</div>
|
|
129
|
+
<div class="form-row">
|
|
130
|
+
<label for="node-input-minId">
|
|
131
|
+
<i class="fa fa-tag"></i> Min ID
|
|
132
|
+
</label>
|
|
133
|
+
<input
|
|
134
|
+
type="number"
|
|
135
|
+
id="node-input-minId"
|
|
136
|
+
placeholder="Min ID"
|
|
137
|
+
style="width: 60%"
|
|
138
|
+
ng-model="minId"
|
|
139
|
+
/>
|
|
140
|
+
</div>
|
|
141
|
+
<div class="form-row">
|
|
142
|
+
<label for="node-input-addOffset">
|
|
143
|
+
<i class="fa fa-tag"></i> Add Offset
|
|
144
|
+
</label>
|
|
145
|
+
<input
|
|
146
|
+
type="number"
|
|
147
|
+
id="node-input-addOffset"
|
|
148
|
+
placeholder="Add Offset"
|
|
149
|
+
style="width: 60%"
|
|
150
|
+
ng-model="addOffset"
|
|
151
|
+
/>
|
|
152
|
+
</div>
|
|
153
|
+
<div class="form-row">
|
|
154
|
+
<label for="node-input-search">
|
|
155
|
+
<i class="fa fa-tag"></i> Search
|
|
156
|
+
</label>
|
|
157
|
+
<input
|
|
158
|
+
type="text"
|
|
159
|
+
id="node-input-search"
|
|
160
|
+
placeholder="Search"
|
|
161
|
+
style="width: 60%"
|
|
162
|
+
ng-model="search"
|
|
163
|
+
/>
|
|
164
|
+
</div>
|
|
165
|
+
<div class="form-row">
|
|
166
|
+
<label for="node-input-filter">
|
|
167
|
+
<i class="fa fa-tag"></i> Filter
|
|
168
|
+
</label>
|
|
169
|
+
<input type="checkbox" name="filter" value="InputMessagesFilterEmpty">Empty<br>
|
|
170
|
+
<input type="checkbox" name="filter" value="InputMessagesFilterPhotos">Photos<br>
|
|
171
|
+
<input type="checkbox" name="filter" value="InputMessagesFilterVideo">Video<br>
|
|
172
|
+
<input type="checkbox" name="filter" value="InputMessagesFilterPhotoVideo">Photo and Video<br>
|
|
173
|
+
<input type="checkbox" name="filter" value="InputMessagesFilterDocument">Document<br>
|
|
174
|
+
<input type="checkbox" name="filter" value="InputMessagesFilterUrl">URL<br>
|
|
175
|
+
<input type="checkbox" name="filter" value="InputMessagesFilterGif">GIF<br>
|
|
176
|
+
<input type="checkbox" name="filter" value="InputMessagesFilterVoice">Voice<br>
|
|
177
|
+
<input type="checkbox" name="filter" value="InputMessagesFilterMusic">Music<br>
|
|
178
|
+
<input type="checkbox" name="filter" value="InputMessagesFilterChatPhotos">Chat Photos<br>
|
|
179
|
+
<input type="checkbox" name="filter" value="InputMessagesFilterPhoneCalls">Phone Calls<br>
|
|
180
|
+
<input type="checkbox" name="filter" value="InputMessagesFilterRoundVoice">Round Voice<br>
|
|
181
|
+
<input type="checkbox" name="filter" value="InputMessagesFilterRoundVideo">Round Video<br>
|
|
182
|
+
<input type="checkbox" name="filter" value="InputMessagesFilterMyMentions">My Mentions<br>
|
|
183
|
+
<input type="checkbox" name="filter" value="InputMessagesFilterGeo">Geo<br>
|
|
184
|
+
<input type="checkbox" name="filter" value="InputMessagesFilterContacts">Contacts<br>
|
|
185
|
+
<input type="checkbox" name="filter" value="InputMessagesFilterPinned">Pinned<br>
|
|
186
|
+
|
|
187
|
+
</div>
|
|
188
|
+
<div class="form-row">
|
|
189
|
+
<label for="node-input-fromUser">
|
|
190
|
+
<i class="fa fa-tag"></i> From User
|
|
191
|
+
</label>
|
|
192
|
+
<input
|
|
193
|
+
type="text"
|
|
194
|
+
id="node-input-fromUser"
|
|
195
|
+
placeholder="From User"
|
|
196
|
+
style="width: 60%"
|
|
197
|
+
ng-model="fromUser"
|
|
198
|
+
/>
|
|
199
|
+
</div>
|
|
200
|
+
<div class="form-row">
|
|
201
|
+
<label for="node-input-waitTime">
|
|
202
|
+
<i class="fa fa-tag"></i> Wait Time
|
|
203
|
+
</label>
|
|
204
|
+
<input
|
|
205
|
+
type="number"
|
|
206
|
+
id="node-input-waitTime"
|
|
207
|
+
placeholder="Wait Time"
|
|
208
|
+
style="width: 60%"
|
|
209
|
+
ng-model="waitTime"
|
|
210
|
+
/>
|
|
211
|
+
</div>
|
|
212
|
+
<div class="form-row">
|
|
213
|
+
<label for="node-input-messageIds">
|
|
214
|
+
<i class="fa fa-tag"></i> Message IDs
|
|
215
|
+
</label>
|
|
216
|
+
<input
|
|
217
|
+
type="text"
|
|
218
|
+
id="node-input-messageIds"
|
|
219
|
+
placeholder="123,1245"
|
|
220
|
+
style="width: 60%"
|
|
221
|
+
ng-model="messageIds"
|
|
222
|
+
/>
|
|
223
|
+
</div>
|
|
224
|
+
<div class="form-row">
|
|
225
|
+
<label for="node-input-reverse">
|
|
226
|
+
<i class="fa fa-tag"></i> Reverse
|
|
227
|
+
</label>
|
|
228
|
+
<input
|
|
229
|
+
type="checkbox"
|
|
230
|
+
id="node-input-reverse"
|
|
231
|
+
ng-model="reverse"
|
|
232
|
+
/>
|
|
233
|
+
</div>
|
|
234
|
+
<div class="form-row">
|
|
235
|
+
<label for="node-input-replyTo">
|
|
236
|
+
<i class="fa fa-tag"></i> Reply To
|
|
237
|
+
</label>
|
|
238
|
+
<input
|
|
239
|
+
type="number"
|
|
240
|
+
id="node-input-replyTo"
|
|
241
|
+
placeholder="Reply To"
|
|
242
|
+
style="width: 60%"
|
|
243
|
+
ng-model="replyTo"
|
|
244
|
+
/>
|
|
245
|
+
</div>
|
|
246
|
+
<div class="form-row">
|
|
247
|
+
<label for="node-input-scheduled">
|
|
248
|
+
<i class="fa fa-tag"></i> Scheduled
|
|
249
|
+
</label>
|
|
250
|
+
<input
|
|
251
|
+
type="checkbox"
|
|
252
|
+
id="node-input-scheduled"
|
|
253
|
+
ng-model="scheduled"
|
|
254
|
+
/>
|
|
255
|
+
</div>
|
|
256
|
+
</script>
|
|
257
|
+
|
|
258
|
+
<script type="text/html" data-help-name="iter-messages">
|
|
259
|
+
<p>The <b>iter-messages</b> node retrieves messages from a specified chat or user using the Telegram API. It supports a wide range of filtering and pagination options, allowing for efficient message iteration.</p>
|
|
260
|
+
|
|
261
|
+
<h3>Inputs</h3>
|
|
262
|
+
<dl class="message-properties">
|
|
263
|
+
<dt>payload.client
|
|
264
|
+
<span class="property-type">object</span>
|
|
265
|
+
</dt>
|
|
266
|
+
<dd>An optional Telegram client instance if not configured globally.</dd>
|
|
267
|
+
|
|
268
|
+
<dt>payload.chatId
|
|
269
|
+
<span class="property-type">string</span>
|
|
270
|
+
</dt>
|
|
271
|
+
<dd>The ID or username of the chat or user to retrieve messages from. Use "me" for personal messages.</dd>
|
|
272
|
+
|
|
273
|
+
<dt>payload.limit
|
|
274
|
+
<span class="property-type">number</span>
|
|
275
|
+
</dt>
|
|
276
|
+
<dd>Maximum number of messages to retrieve.</dd>
|
|
277
|
+
|
|
278
|
+
<dt>payload.offsetDate
|
|
279
|
+
<span class="property-type">string | number</span>
|
|
280
|
+
</dt>
|
|
281
|
+
<dd>Fetch messages starting from this date. Accepts a UNIX timestamp or a date string.</dd>
|
|
282
|
+
|
|
283
|
+
<dt>payload.offsetId
|
|
284
|
+
<span class="property-type">number</span>
|
|
285
|
+
</dt>
|
|
286
|
+
<dd>Fetch messages starting from this message ID.</dd>
|
|
287
|
+
|
|
288
|
+
<dt>payload.maxId
|
|
289
|
+
<span class="property-type">number</span>
|
|
290
|
+
</dt>
|
|
291
|
+
<dd>Fetch messages with IDs less than or equal to this value.</dd>
|
|
292
|
+
|
|
293
|
+
<dt>payload.minId
|
|
294
|
+
<span class="property-type">number</span>
|
|
295
|
+
</dt>
|
|
296
|
+
<dd>Fetch messages with IDs greater than or equal to this value.</dd>
|
|
297
|
+
|
|
298
|
+
<dt>payload.addOffset
|
|
299
|
+
<span class="property-type">number</span>
|
|
300
|
+
</dt>
|
|
301
|
+
<dd>An additional offset to apply when retrieving messages.</dd>
|
|
302
|
+
|
|
303
|
+
<dt>payload.search
|
|
304
|
+
<span class="property-type">string</span>
|
|
305
|
+
</dt>
|
|
306
|
+
<dd>Filters messages containing the specified search term.</dd>
|
|
307
|
+
|
|
308
|
+
<dt>payload.filter
|
|
309
|
+
<span class="property-type">object</span>
|
|
310
|
+
</dt>
|
|
311
|
+
<dd>Applies a specific message filter (e.g., photos, videos, documents).</dd>
|
|
312
|
+
|
|
313
|
+
<dt>payload.filters
|
|
314
|
+
<span class="property-type">array</span>
|
|
315
|
+
</dt>
|
|
316
|
+
<dd>Applies multiple message filters using Telegram API filter classes (e.g., <code>Api.InputMessagesFilterPhotos</code>).</dd>
|
|
317
|
+
|
|
318
|
+
<dt>payload.reverse
|
|
319
|
+
<span class="property-type">boolean</span>
|
|
320
|
+
</dt>
|
|
321
|
+
<dd>Retrieves messages in reverse order if set to <code>true</code>. Default is <code>false</code>.</dd>
|
|
322
|
+
|
|
323
|
+
<dt>payload.replyTo
|
|
324
|
+
<span class="property-type">number</span>
|
|
325
|
+
</dt>
|
|
326
|
+
<dd>Fetches messages replying to the specified message ID.</dd>
|
|
327
|
+
|
|
328
|
+
<dt>payload.scheduled
|
|
329
|
+
<span class="property-type">boolean</span>
|
|
330
|
+
</dt>
|
|
331
|
+
<dd>Includes scheduled messages if set to <code>true</code>.</dd>
|
|
332
|
+
</dl>
|
|
333
|
+
|
|
334
|
+
<h3>Outputs</h3>
|
|
335
|
+
<dl class="message-properties">
|
|
336
|
+
<dt>payload.messages
|
|
337
|
+
<span class="property-type">object</span>
|
|
338
|
+
</dt>
|
|
339
|
+
<dd>An object containing messages, where keys are message IDs and values are message details.</dd>
|
|
340
|
+
</dl>
|
|
341
|
+
|
|
342
|
+
<h3>Details</h3>
|
|
343
|
+
<p>The <b>iter-messages</b> node provides a flexible way to retrieve messages from a Telegram chat or user. It allows advanced configurations such as filtering messages by type, searching for specific terms, and paginating results using offsets and IDs.</p>
|
|
344
|
+
|
|
345
|
+
<p>The node also handles cases where a chat username needs to be resolved into an entity or peer ID. It supports using multiple filters in conjunction, enabling precise control over the messages to process.</p>
|
|
346
|
+
|
|
347
|
+
<h3>Example</h3>
|
|
348
|
+
<pre>
|
|
349
|
+
{
|
|
350
|
+
"payload": {
|
|
351
|
+
"chatId": "@examplechannel",
|
|
352
|
+
"limit": 50,
|
|
353
|
+
"search": "announcement",
|
|
354
|
+
"filters": ["InputMessagesFilterPhotos"]
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
</pre>
|
|
358
|
+
<p>This input retrieves up to 50 messages containing the term "announcement" and filters them to include only photos from the specified channel.</p>
|
|
359
|
+
|
|
360
|
+
<h3>Error Handling</h3>
|
|
361
|
+
<p>If an error occurs during message retrieval (e.g., invalid chat ID or API errors), the node logs an error message and does not return a payload.</p>
|
|
362
|
+
|
|
363
|
+
<h3>Configuration</h3>
|
|
364
|
+
<p>The node can use a globally configured Telegram client or a client instance provided in the message payload. Ensure the client has access to the specified chat or user.</p>
|
|
365
|
+
</script>
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
const { TelegramClient, utils, Api } = require("telegram");
|
|
2
|
+
|
|
3
|
+
module.exports = function (RED) {
|
|
4
|
+
function IterMessages(config) {
|
|
5
|
+
RED.nodes.createNode(this, config);
|
|
6
|
+
this.config = RED.nodes.getNode(config.config);
|
|
7
|
+
var node = this;
|
|
8
|
+
|
|
9
|
+
this.on('input', async function (msg) {
|
|
10
|
+
|
|
11
|
+
/** @type {TelegramClient} */
|
|
12
|
+
const client = msg.payload?.client ? msg.payload.client : this.config.client;
|
|
13
|
+
const chatId = msg.payload?.chatId ? msg.payload.chatId : config.chatId;
|
|
14
|
+
let peerId = chatId === "me" ? chatId : utils.parseID(chatId);
|
|
15
|
+
|
|
16
|
+
// Получаем параметры из входного сообщения или из конфигурации узла
|
|
17
|
+
const limit = msg.payload?.limit || config.limit;
|
|
18
|
+
const offsetDate = msg.payload?.offsetDate || config.offsetDate;
|
|
19
|
+
const offsetId = msg.payload?.offsetId || config.offsetId;
|
|
20
|
+
const maxId = msg.payload?.maxId || config.maxId;
|
|
21
|
+
const minId = msg.payload?.minId || config.minId;
|
|
22
|
+
const addOffset = msg.payload?.addOffset || config.addOffset;
|
|
23
|
+
const search = msg.payload?.search || config.search;
|
|
24
|
+
const filter = msg.payload?.filter || config.filter;
|
|
25
|
+
const fromUser = msg.payload?.fromUser || config.fromUser;
|
|
26
|
+
const waitTime = msg.payload?.waitTime || config.waitTime;
|
|
27
|
+
const messageIds = msg.payload?.messageIds || config.messageIds;
|
|
28
|
+
const reverse = msg.payload?.reverse || config.reverse;
|
|
29
|
+
const replyTo = msg.payload?.replyTo || config.replyTo;
|
|
30
|
+
const scheduled = msg.payload?.scheduled || config.scheduled;
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
|
|
34
|
+
const params = {
|
|
35
|
+
limit: limit !== ""? parseInt(limit) : undefined,
|
|
36
|
+
offsetDate: offsetDate !== "" ? offsetDate:undefined,
|
|
37
|
+
offsetId: offsetId !== "" ? parseInt(offsetId):undefined,
|
|
38
|
+
maxId: maxId,
|
|
39
|
+
minId: minId,
|
|
40
|
+
addOffset: addOffset,
|
|
41
|
+
search: search !== "" ? search : undefined,
|
|
42
|
+
filter: filter,
|
|
43
|
+
// fromUser: fromUser,
|
|
44
|
+
waitTime: waitTime,
|
|
45
|
+
ids: messageIds,
|
|
46
|
+
reverse: reverse,
|
|
47
|
+
replyTo: replyTo,
|
|
48
|
+
scheduled: scheduled,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
if (offsetDate) {
|
|
52
|
+
params.offsetDate = new Date(offsetDate).getTime() / 1000;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (chatId[0] === "@") {
|
|
56
|
+
peerId = await client.getEntity(chatId);
|
|
57
|
+
}
|
|
58
|
+
const messages = {};
|
|
59
|
+
|
|
60
|
+
const filters = msg.payload?.filters || config.filters || [];
|
|
61
|
+
|
|
62
|
+
// Обработка выбранных фильтров
|
|
63
|
+
if (filters.length > 0) {
|
|
64
|
+
params.filter = [];
|
|
65
|
+
filters.forEach((filter) => {
|
|
66
|
+
params.filter.push( Api[filter]);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
for await (const message of client.iterMessages(peerId, params)){
|
|
72
|
+
messages[message.id] = message;
|
|
73
|
+
console.log(message.id, message.text);
|
|
74
|
+
}
|
|
75
|
+
} catch (error) {
|
|
76
|
+
const entity = await client.getInputEntity(peerId)
|
|
77
|
+
for await (const message of client.iterMessages(entity, params)){
|
|
78
|
+
messages[message.id] = message;
|
|
79
|
+
console.log(message.id, message.text);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
node.send({
|
|
84
|
+
payload: { messages },
|
|
85
|
+
});
|
|
86
|
+
} catch (err) {
|
|
87
|
+
node.error('Error iter messages: ' + err.message);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
RED.nodes.registerType('iter-messages', IterMessages);
|
|
94
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
RED.nodes.registerType('promote-admin', {
|
|
3
|
+
category: 'telegram-account',
|
|
4
|
+
color: '#229ED9',
|
|
5
|
+
icon: 'tg.png',
|
|
6
|
+
align: "right",
|
|
7
|
+
defaults: {
|
|
8
|
+
name: { value: '' },
|
|
9
|
+
config: { type: 'config', required: false },
|
|
10
|
+
chatId: { value: '' },
|
|
11
|
+
userId: { value: '' },
|
|
12
|
+
rank: { value: 'Admin' },
|
|
13
|
+
adminRights: { value: '' }, // JSON string of ChatAdminRights
|
|
14
|
+
},
|
|
15
|
+
inputs: 1,
|
|
16
|
+
outputs: 1,
|
|
17
|
+
label: function () {
|
|
18
|
+
return this.name || 'Promote Admin';
|
|
19
|
+
},
|
|
20
|
+
oneditprepare: function () {
|
|
21
|
+
// Nothing special here yet — could validate JSON if needed
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
</script>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const { TelegramClient } = require("telegram");
|
|
2
|
+
const { parseID } = require("telegram/Utils");
|
|
3
|
+
const { Api } = require("telegram");
|
|
4
|
+
|
|
5
|
+
module.exports = function (RED) {
|
|
6
|
+
function PromoteAdmin(config) {
|
|
7
|
+
RED.nodes.createNode(this, config);
|
|
8
|
+
this.config = RED.nodes.getNode(config.config);
|
|
9
|
+
var node = this;
|
|
10
|
+
|
|
11
|
+
this.on('input', async function (msg) {
|
|
12
|
+
let chatId = msg.payload.chatId || config.chatId;
|
|
13
|
+
let userId = msg.payload.userId || config.userId;
|
|
14
|
+
let rank = msg.payload.rank || config.rank || "Admin";
|
|
15
|
+
const customRights = msg.payload.adminRights || config.adminRights;
|
|
16
|
+
|
|
17
|
+
/** @type {TelegramClient} */
|
|
18
|
+
const client = msg.payload?.client ? msg.payload.client : this.config.client;
|
|
19
|
+
let group, user;
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
group = chatId[0] === "@" ? await client.getEntity(chatId) : parseID(chatId);
|
|
23
|
+
user = userId[0] === "@" ? await client.getEntity(userId) : parseID(userId);
|
|
24
|
+
|
|
25
|
+
const adminRights = customRights || new Api.ChatAdminRights({
|
|
26
|
+
changeInfo: true,
|
|
27
|
+
postMessages: true,
|
|
28
|
+
editMessages: true,
|
|
29
|
+
deleteMessages: true,
|
|
30
|
+
banUsers: true,
|
|
31
|
+
inviteUsers: true,
|
|
32
|
+
pinMessages: true,
|
|
33
|
+
addAdmins: true,
|
|
34
|
+
manageCall: true,
|
|
35
|
+
anonymous: false,
|
|
36
|
+
manageTopics: true,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const result = await client.invoke(new Api.channels.EditAdmin({
|
|
40
|
+
channel: group,
|
|
41
|
+
userId: user,
|
|
42
|
+
adminRights,
|
|
43
|
+
rank,
|
|
44
|
+
}));
|
|
45
|
+
|
|
46
|
+
node.send({ payload: result });
|
|
47
|
+
|
|
48
|
+
} catch (err) {
|
|
49
|
+
node.error('Error promoting admin: ' + err.message);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
RED.nodes.registerType('promote-admin', PromoteAdmin);
|
|
55
|
+
};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
RED.nodes.registerType('receiver', {
|
|
3
|
+
category: 'telegram-account',
|
|
4
|
+
color: '#229ED9',
|
|
5
|
+
icon: 'tg.png',
|
|
6
|
+
align:"right",
|
|
7
|
+
defaults: {
|
|
8
|
+
name: { value: '' },
|
|
9
|
+
config: { type: 'config', required: false },
|
|
10
|
+
ignore: { value:""}
|
|
11
|
+
},
|
|
12
|
+
inputs: 1,
|
|
13
|
+
outputs: 1,
|
|
14
|
+
label: function () {
|
|
15
|
+
return this.name || 'Receiver';
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
});
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<script type="text/html" data-template-name="receiver">
|
|
22
|
+
<div class="form-row">
|
|
23
|
+
<label for="node-input-name">
|
|
24
|
+
<i class="fa fa-tag"></i> Name
|
|
25
|
+
</label>
|
|
26
|
+
<input
|
|
27
|
+
type="text"
|
|
28
|
+
id="node-input-name"
|
|
29
|
+
placeholder="Name"
|
|
30
|
+
style="width: 60%"
|
|
31
|
+
/>
|
|
32
|
+
</div>
|
|
33
|
+
<div class="form-row">
|
|
34
|
+
<label for="node-input-config">
|
|
35
|
+
<i class="fa fa-tag"></i> Config
|
|
36
|
+
</label>
|
|
37
|
+
<input
|
|
38
|
+
type="text"
|
|
39
|
+
id="node-input-config"
|
|
40
|
+
placeholder="Config"
|
|
41
|
+
style="width: 60%"
|
|
42
|
+
/>
|
|
43
|
+
</div>
|
|
44
|
+
<div class="form-row">
|
|
45
|
+
<label for="node-input-ignore">
|
|
46
|
+
<i class="fa fa-tag"></i> Config
|
|
47
|
+
</label>
|
|
48
|
+
<textarea
|
|
49
|
+
type="text"
|
|
50
|
+
id="node-input-ignore"
|
|
51
|
+
placeholder="Config"
|
|
52
|
+
style="width: 60%"
|
|
53
|
+
></textarea>
|
|
54
|
+
</div>
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
<script type="text/html" data-help-name="receiver">
|
|
58
|
+
<p>The <b>receiver</b> node listens for incoming Telegram messages and forwards them as output messages in Node-RED. It supports filtering messages based on sender IDs to ignore specific users.</p>
|
|
59
|
+
|
|
60
|
+
<h3>Inputs</h3>
|
|
61
|
+
<p>This node does not take any direct inputs. It listens to all incoming messages from the configured Telegram client.</p>
|
|
62
|
+
|
|
63
|
+
<h3>Outputs</h3>
|
|
64
|
+
<dl class="message-properties">
|
|
65
|
+
<dt>payload.update
|
|
66
|
+
<span class="property-type">object</span>
|
|
67
|
+
</dt>
|
|
68
|
+
<dd>The raw Telegram update object containing details about the incoming message, sender, chat, and metadata.</dd>
|
|
69
|
+
</dl>
|
|
70
|
+
|
|
71
|
+
<h3>Configuration</h3>
|
|
72
|
+
<dl class="message-properties">
|
|
73
|
+
<dt>Telegram Configuration
|
|
74
|
+
<span class="property-type">node</span>
|
|
75
|
+
</dt>
|
|
76
|
+
<dd>A configured Telegram client node to receive messages. Ensure the client is authenticated and has necessary permissions.</dd>
|
|
77
|
+
|
|
78
|
+
<dt>Ignore List
|
|
79
|
+
<span class="property-type">string</span>
|
|
80
|
+
</dt>
|
|
81
|
+
<dd>A newline-separated list of user IDs to ignore. Messages from these users will not trigger the output.</dd>
|
|
82
|
+
</dl>
|
|
83
|
+
|
|
84
|
+
<h3>Details</h3>
|
|
85
|
+
<p>The <b>receiver</b> node uses the Telegram client to listen for all new messages in real-time. It emits a message to the next connected Node-RED node whenever a new Telegram message is received, provided the sender's user ID is not in the ignore list.</p>
|
|
86
|
+
|
|
87
|
+
<h3>Example</h3>
|
|
88
|
+
<pre>
|
|
89
|
+
{
|
|
90
|
+
"payload": {
|
|
91
|
+
"update": {
|
|
92
|
+
"message": {
|
|
93
|
+
"message": "Hello, bot!",
|
|
94
|
+
"sender": {
|
|
95
|
+
"id": 123456789,
|
|
96
|
+
"username": "exampleuser"
|
|
97
|
+
},
|
|
98
|
+
"chat": {
|
|
99
|
+
"id": 987654321,
|
|
100
|
+
"type": "private"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
</pre>
|
|
107
|
+
<p>In this example, the node outputs the raw Telegram update object when a user sends the message "Hello, bot!" to the Telegram bot.</p>
|
|
108
|
+
|
|
109
|
+
<h3>Error Handling</h3>
|
|
110
|
+
<p>If the Telegram client encounters an authentication issue or configuration error, the node logs an error message and stops listening for messages.</p>
|
|
111
|
+
|
|
112
|
+
<h3>Advanced Usage</h3>
|
|
113
|
+
<p>By configuring the <b>Ignore List</b>, you can filter out messages from specific users. For example:</p>
|
|
114
|
+
<pre>
|
|
115
|
+
123456789
|
|
116
|
+
987654321
|
|
117
|
+
</pre>
|
|
118
|
+
<p>In this case, messages from user IDs <code>123456789</code> and <code>987654321</code> will be ignored.</p>
|
|
119
|
+
|
|
120
|
+
<h3>Notes</h3>
|
|
121
|
+
<ul>
|
|
122
|
+
<li>Ensure the Telegram bot has sufficient permissions to receive messages in the configured chat or channel.</li>
|
|
123
|
+
<li>The <b>Ignore List</b> only filters messages based on the sender's user ID.</li>
|
|
124
|
+
<li>For advanced filtering based on message content, consider chaining this node with additional processing nodes in Node-RED.</li>
|
|
125
|
+
</ul>
|
|
126
|
+
</script>
|
|
127
|
+
|
|
128
|
+
|