1
1
var Duplex = require ( 'stream' ) . Duplex
2
2
3
- var inherits = require ( 'inherits' )
4
- var Telegram = require ( 'telegram-bot-api' )
5
-
6
-
7
- function emitError ( message , data )
8
- {
9
- var error = new Error ( message )
10
- error . data = data
11
-
12
- this . emit ( 'error' , error )
13
- }
14
-
15
- /**
16
- * Process a single received Telegram `Update` object
17
- *
18
- * @param {Object } update
19
- *
20
- * @return Boolean - more `Update` objects can be fetch
21
- */
22
- function processUpdate ( update )
23
- {
24
- var message = update . message
25
- if ( message == null )
26
- return emitError . call ( this , 'Inline queries are not supported' , update )
27
-
28
- if ( message . chat . id !== this . chat_id )
29
- return emitError . call ( this , 'Received message for not-listening chat' , message )
30
-
31
- var text = message . text
32
- if ( text == null )
33
- return emitError . call ( this , 'Only text messages are supported' , message )
34
-
35
- return this . push ( message . text )
36
- }
3
+ var inherits = require ( 'inherits' )
4
+ var Telegram = require ( 'telegram-bot-api' )
5
+ var WebhookPost = require ( 'WebhookPost' )
37
6
38
7
39
8
/**
@@ -59,41 +28,131 @@ function TelegramLog(token, chat_id, options)
59
28
if ( ! token ) throw 'Missing token'
60
29
if ( ! chat_id ) throw 'Missing chat_id'
61
30
62
- Object . defineProperties ( this ,
63
- {
64
- token : { value : token } ,
65
- chat_id : { value : chat_id }
66
- } )
67
-
68
31
var _updatesOffset = 0
69
32
70
- var inFlight
71
- var req
72
-
73
33
var api = new Telegram ( { token : token } )
74
34
75
35
76
36
//
77
37
// Private functions
78
38
//
79
39
40
+ function emitError ( message , data )
41
+ {
42
+ var error = new Error ( message )
43
+ error . data = data
44
+
45
+ self . emit ( 'error' , error )
46
+ }
47
+
80
48
/**
81
- * Process a Telegram `Update` object and check if it should do more requests
49
+ * Process a single received Telegram `Update` object
82
50
*
83
- * @param {Boolean } fetchMoreDate
84
51
* @param {Object } update
85
52
*
86
53
* @return Boolean - more `Update` objects can be fetch
87
54
*/
88
- function processUpdate_reduce ( fetchMoreDate , update )
55
+ function processUpdate ( update )
89
56
{
90
57
// Account update_id as next offset
91
58
// to avoid dublicated updates
92
59
var update_id = update . update_id
93
60
if ( update_id >= _updatesOffset )
94
61
_updatesOffset = update_id + 1
95
62
96
- return processUpdate . call ( self , update ) && fetchMoreDate
63
+ var message = update . message
64
+ if ( message == null )
65
+ return emitError ( 'Inline queries are not supported' , update )
66
+
67
+ if ( message . chat . id !== chat_id )
68
+ return emitError ( 'Received message for not-listening chat' , message )
69
+
70
+ var text = message . text
71
+ if ( text == null )
72
+ return emitError ( 'Only text messages are supported' , message )
73
+
74
+ return self . push ( message . text )
75
+ }
76
+
77
+ var end = this . push . bind ( this , null )
78
+
79
+
80
+ //
81
+ // Webhook
82
+ //
83
+
84
+ var webhook = options . webhook
85
+ if ( webhook )
86
+ {
87
+ var certificate = options . certificate || ''
88
+
89
+ function closeWebhook ( )
90
+ {
91
+ if ( ! webhook ) return
92
+
93
+ webhook . close ( )
94
+ webhook = null
95
+
96
+ api . setWebhook ( { certificate : certificate } ) . then ( end , end )
97
+ }
98
+
99
+ // Telegram only support ports 80, 88, 443 and 8443
100
+ var port
101
+ if ( webhook ) port = webhook . port
102
+ else port = webhook
103
+
104
+ if ( ! ( port === 80 || port === 88 || port === 443 || port === 8443 ) )
105
+ {
106
+ var error = new RangeError ( 'Port must be one of 80, 88, 443 or 8443' )
107
+ error . port = webhook
108
+
109
+ throw error
110
+ }
111
+
112
+ // Create webhook
113
+ webhook = WebhookPost ( webhook , options )
114
+ . on ( 'open' , function ( url )
115
+ {
116
+ api
117
+ . setWebhook ( { url : url , certificate : certificate } )
118
+ . catch ( function ( error )
119
+ {
120
+ self . emit ( 'error' , error )
121
+
122
+ webhook = null
123
+ end ( )
124
+ } )
125
+ } )
126
+ . on ( 'data' , function ( data )
127
+ {
128
+ var update = JSON . parse ( data )
129
+
130
+ // Ignore duplicated updates
131
+ if ( update . update_id >= _updatesOffset ) processUpdate ( update )
132
+ } )
133
+ . on ( 'error' , this . emit . bind ( this , 'error' ) )
134
+ . on ( 'end' , closeWebhook )
135
+ }
136
+
137
+
138
+ //
139
+ // Polling
140
+ //
141
+
142
+ var polling
143
+ var inFlight
144
+
145
+ /**
146
+ * Process a Telegram `Update` object and check if it should do more requests
147
+ *
148
+ * @param {Boolean } fetchMoreDate
149
+ * @param {Object } update
150
+ *
151
+ * @return Boolean - more `Update` objects can be fetch
152
+ */
153
+ function processUpdate_reduce ( fetchMoreDate , update )
154
+ {
155
+ return processUpdate ( update ) && fetchMoreDate
97
156
}
98
157
99
158
/**
@@ -122,7 +181,7 @@ function TelegramLog(token, chat_id, options)
122
181
123
182
124
183
/**
125
- * Request new updates
184
+ * Request new updates. This will not work when using a webhook
126
185
*
127
186
* @private
128
187
*/
@@ -131,11 +190,13 @@ function TelegramLog(token, chat_id, options)
131
190
var state = self . _readableState
132
191
var limit = state . highWaterMark - state . length
133
192
134
- if ( inFlight || state . ended || ! limit ) return
193
+ if ( inFlight || state . ended || ! limit
194
+ || polling === null || webhook !== undefined )
195
+ return
135
196
136
197
inFlight = true
137
198
138
- req = api . getUpdates ( {
199
+ polling = api . getUpdates ( {
139
200
offset : _updatesOffset ,
140
201
limit : limit ,
141
202
timeout : 0
@@ -144,8 +205,13 @@ function TelegramLog(token, chat_id, options)
144
205
. catch ( onError )
145
206
}
146
207
208
+
209
+ //
210
+ // Duplex API
211
+ //
212
+
147
213
/**
148
- * Write a streamed row on the worksheet
214
+ * Write a data message
149
215
*
150
216
* @param {Object } chunk
151
217
* @param {* } _ - ignored
@@ -165,18 +231,22 @@ function TelegramLog(token, chat_id, options)
165
231
. then ( done . bind ( null , null ) , done )
166
232
}
167
233
234
+
235
+ //
236
+ // Public API
237
+ //
238
+
168
239
/**
169
240
* Close the connection and stop emitting more data updates
170
241
*/
171
242
this . close = function ( )
172
243
{
173
- if ( req )
244
+ if ( webhook !== undefined ) return closeWebhook ( )
245
+ if ( polling )
174
246
{
175
- // req.abort( )
176
- req = null
247
+ polling . then ( end , end )
248
+ polling = null
177
249
}
178
-
179
- this . push ( null )
180
250
}
181
251
}
182
252
inherits ( TelegramLog , Duplex )
0 commit comments