@es-labs/jslib 0.0.1

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.
Files changed (72) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +42 -0
  3. package/__test__/services.test.js +32 -0
  4. package/auth/index.js +226 -0
  5. package/auth/keyv.js +23 -0
  6. package/auth/knex.js +29 -0
  7. package/auth/redis.js +23 -0
  8. package/comms/email.js +123 -0
  9. package/comms/nexmo.js +44 -0
  10. package/comms/telegram.js +43 -0
  11. package/comms/telegram2/inbound.js +314 -0
  12. package/comms/telegram2/outbound.js +574 -0
  13. package/comms/webpush.js +60 -0
  14. package/config.js +37 -0
  15. package/express/controller/auth/oauth.js +39 -0
  16. package/express/controller/auth/oidc.js +87 -0
  17. package/express/controller/auth/own.js +100 -0
  18. package/express/controller/auth/saml.js +74 -0
  19. package/express/upload.js +48 -0
  20. package/index.js +1 -0
  21. package/iso/README.md +4 -0
  22. package/iso/__tests__/csv-utils.spec.js +128 -0
  23. package/iso/__tests__/datetime.spec.js +101 -0
  24. package/iso/__tests__/fetch.spec.js +270 -0
  25. package/iso/csv-utils.js +206 -0
  26. package/iso/datetime.js +103 -0
  27. package/iso/fetch.js +129 -0
  28. package/iso/fetch2.js +180 -0
  29. package/iso/log-filter.js +17 -0
  30. package/iso/sleep.js +6 -0
  31. package/iso/ws.js +63 -0
  32. package/node/oss-files/oss-uploader-client-fetch.js +258 -0
  33. package/node/oss-files/oss-uploader-client-fetch.md +31 -0
  34. package/node/oss-files/oss-uploader-client.js +219 -0
  35. package/node/oss-files/oss-uploader-server.js +199 -0
  36. package/node/oss-files/oss-uploader-usage.js +121 -0
  37. package/node/oss-files/oss-uploader-usage.md +34 -0
  38. package/node/oss-files/s3-uploader-client.js +217 -0
  39. package/node/oss-files/s3-uploader-server.js +123 -0
  40. package/node/oss-files/s3-uploader-usage.js +77 -0
  41. package/node/oss-files/s3-uploader-usage.md +34 -0
  42. package/package.json +53 -0
  43. package/packageInfo.js +9 -0
  44. package/services/ali.js +279 -0
  45. package/services/aws.js +194 -0
  46. package/services/db/__tests__/keyv.spec.js +31 -0
  47. package/services/db/keyv.js +14 -0
  48. package/services/db/knex.js +67 -0
  49. package/services/db/redis.js +51 -0
  50. package/services/index.js +57 -0
  51. package/services/mq/README.md +8 -0
  52. package/services/websocket.js +139 -0
  53. package/t4t/README.md +1 -0
  54. package/traps.js +20 -0
  55. package/utils/__tests__/aes.spec.js +52 -0
  56. package/utils/aes.js +23 -0
  57. package/web/UI.md +71 -0
  58. package/web/bwc-autocomplete.js +211 -0
  59. package/web/bwc-combobox.js +343 -0
  60. package/web/bwc-fileupload.js +87 -0
  61. package/web/bwc-loading-overlay.js +54 -0
  62. package/web/bwc-t4t-form.js +511 -0
  63. package/web/bwc-table.js +756 -0
  64. package/web/fetch.js +129 -0
  65. package/web/i18n.js +24 -0
  66. package/web/idle.js +49 -0
  67. package/web/parse-jwt.js +15 -0
  68. package/web/pwa.js +84 -0
  69. package/web/sign-pad.js +164 -0
  70. package/web/t4t-fe.js +164 -0
  71. package/web/util.js +126 -0
  72. package/web/web-cam.js +182 -0
@@ -0,0 +1,314 @@
1
+ import express from "express"
2
+
3
+ const app = express();
4
+ app.use(express.json());
5
+
6
+ // ─── Extractors ───────────────────────────────────────────────────────────────
7
+
8
+ function extractMessageData(message) {
9
+ if (!message) return null;
10
+
11
+ return {
12
+ // Core identifiers
13
+ messageId: message.message_id,
14
+ date: new Date(message.date * 1000).toISOString(),
15
+ editedDate: message.edit_date
16
+ ? new Date(message.edit_date * 1000).toISOString()
17
+ : null,
18
+
19
+ // Sender info
20
+ from: message.from
21
+ ? {
22
+ id: message.from.id,
23
+ isBot: message.from.is_bot,
24
+ firstName: message.from.first_name,
25
+ lastName: message.from.last_name ?? null,
26
+ username: message.from.username ?? null,
27
+ languageCode: message.from.language_code ?? null,
28
+ }
29
+ : null,
30
+
31
+ // Chat info
32
+ chat: message.chat
33
+ ? {
34
+ id: message.chat.id,
35
+ type: message.chat.type, // private | group | supergroup | channel
36
+ title: message.chat.title ?? null,
37
+ username: message.chat.username ?? null,
38
+ firstName: message.chat.first_name ?? null,
39
+ lastName: message.chat.last_name ?? null,
40
+ }
41
+ : null,
42
+
43
+ // Content
44
+ content: extractContent(message),
45
+
46
+ // Reply / forward context
47
+ replyTo: message.reply_to_message
48
+ ? extractMessageData(message.reply_to_message)
49
+ : null,
50
+ forwardFrom: extractForwardInfo(message),
51
+
52
+ // Entities (mentions, commands, links, etc.)
53
+ entities: extractEntities(message),
54
+
55
+ // Media group (album)
56
+ mediaGroupId: message.media_group_id ?? null,
57
+ };
58
+ }
59
+
60
+ function extractContent(message) {
61
+ // Text
62
+ if (message.text) return { type: "text", text: message.text };
63
+
64
+ // Photo (array of sizes — last is highest res)
65
+ if (message.photo) {
66
+ const best = message.photo.at(-1);
67
+ return {
68
+ type: "photo",
69
+ fileId: best.file_id,
70
+ fileUniqueId: best.file_unique_id,
71
+ width: best.width,
72
+ height: best.height,
73
+ fileSize: best.file_size ?? null,
74
+ caption: message.caption ?? null,
75
+ };
76
+ }
77
+
78
+ // Video
79
+ if (message.video) {
80
+ const v = message.video;
81
+ return {
82
+ type: "video",
83
+ fileId: v.file_id,
84
+ fileUniqueId: v.file_unique_id,
85
+ width: v.width,
86
+ height: v.height,
87
+ duration: v.duration,
88
+ mimeType: v.mime_type ?? null,
89
+ fileSize: v.file_size ?? null,
90
+ caption: message.caption ?? null,
91
+ };
92
+ }
93
+
94
+ // Audio
95
+ if (message.audio) {
96
+ const a = message.audio;
97
+ return {
98
+ type: "audio",
99
+ fileId: a.file_id,
100
+ fileUniqueId: a.file_unique_id,
101
+ duration: a.duration,
102
+ performer: a.performer ?? null,
103
+ title: a.title ?? null,
104
+ mimeType: a.mime_type ?? null,
105
+ fileSize: a.file_size ?? null,
106
+ caption: message.caption ?? null,
107
+ };
108
+ }
109
+
110
+ // Voice note
111
+ if (message.voice) {
112
+ const v = message.voice;
113
+ return {
114
+ type: "voice",
115
+ fileId: v.file_id,
116
+ fileUniqueId: v.file_unique_id,
117
+ duration: v.duration,
118
+ mimeType: v.mime_type ?? null,
119
+ fileSize: v.file_size ?? null,
120
+ };
121
+ }
122
+
123
+ // Document / file
124
+ if (message.document) {
125
+ const d = message.document;
126
+ return {
127
+ type: "document",
128
+ fileId: d.file_id,
129
+ fileUniqueId: d.file_unique_id,
130
+ fileName: d.file_name ?? null,
131
+ mimeType: d.mime_type ?? null,
132
+ fileSize: d.file_size ?? null,
133
+ caption: message.caption ?? null,
134
+ };
135
+ }
136
+
137
+ // Sticker
138
+ if (message.sticker) {
139
+ const s = message.sticker;
140
+ return {
141
+ type: "sticker",
142
+ fileId: s.file_id,
143
+ fileUniqueId: s.file_unique_id,
144
+ width: s.width,
145
+ height: s.height,
146
+ isAnimated: s.is_animated,
147
+ isVideo: s.is_video,
148
+ emoji: s.emoji ?? null,
149
+ setName: s.set_name ?? null,
150
+ };
151
+ }
152
+
153
+ // Location
154
+ if (message.location) {
155
+ return {
156
+ type: "location",
157
+ latitude: message.location.latitude,
158
+ longitude: message.location.longitude,
159
+ horizontalAccuracy: message.location.horizontal_accuracy ?? null,
160
+ livePeriod: message.location.live_period ?? null,
161
+ };
162
+ }
163
+
164
+ // Contact
165
+ if (message.contact) {
166
+ const c = message.contact;
167
+ return {
168
+ type: "contact",
169
+ phoneNumber: c.phone_number,
170
+ firstName: c.first_name,
171
+ lastName: c.last_name ?? null,
172
+ userId: c.user_id ?? null,
173
+ };
174
+ }
175
+
176
+ // Poll
177
+ if (message.poll) {
178
+ const p = message.poll;
179
+ return {
180
+ type: "poll",
181
+ id: p.id,
182
+ question: p.question,
183
+ options: p.options.map((o) => ({ text: o.text, voterCount: o.voter_count })),
184
+ totalVoterCount: p.total_voter_count,
185
+ isClosed: p.is_closed,
186
+ isAnonymous: p.is_anonymous,
187
+ pollType: p.type, // regular | quiz
188
+ correctOptionId: p.correct_option_id ?? null,
189
+ };
190
+ }
191
+
192
+ // Video note (round video)
193
+ if (message.video_note) {
194
+ const vn = message.video_note;
195
+ return {
196
+ type: "video_note",
197
+ fileId: vn.file_id,
198
+ fileUniqueId: vn.file_unique_id,
199
+ length: vn.length,
200
+ duration: vn.duration,
201
+ fileSize: vn.file_size ?? null,
202
+ };
203
+ }
204
+
205
+ return { type: "unknown" };
206
+ }
207
+
208
+ function extractEntities(message) {
209
+ const raw = message.entities ?? message.caption_entities ?? [];
210
+ if (!raw.length) return [];
211
+
212
+ const text = message.text ?? message.caption ?? "";
213
+
214
+ return raw.map((e) => ({
215
+ type: e.type, // mention | hashtag | cashtag | bot_command | url | email | bold | italic | etc.
216
+ offset: e.offset,
217
+ length: e.length,
218
+ value: text.slice(e.offset, e.offset + e.length),
219
+ url: e.url ?? null, // for inline links
220
+ user: e.user ?? null, // for text_mention entities
221
+ language: e.language ?? null, // for pre/code blocks
222
+ }));
223
+ }
224
+
225
+ function extractForwardInfo(message) {
226
+ if (!message.forward_date) return null;
227
+ return {
228
+ date: new Date(message.forward_date * 1000).toISOString(),
229
+ fromUser: message.forward_from ?? null,
230
+ fromChat: message.forward_from_chat ?? null,
231
+ fromMessageId: message.forward_from_message_id ?? null,
232
+ senderName: message.forward_sender_name ?? null, // when origin is hidden
233
+ };
234
+ }
235
+
236
+ // ─── Update dispatcher ────────────────────────────────────────────────────────
237
+
238
+ function handleUpdate(update) {
239
+ // Standard message (new or edited)
240
+ const message = update.message ?? update.edited_message;
241
+ if (message) return { updateType: "message", data: extractMessageData(message) };
242
+
243
+ // Channel post (new or edited)
244
+ const post = update.channel_post ?? update.edited_channel_post;
245
+ if (post) return { updateType: "channel_post", data: extractMessageData(post) };
246
+
247
+ // Inline query
248
+ if (update.inline_query) {
249
+ return {
250
+ updateType: "inline_query",
251
+ data: {
252
+ id: update.inline_query.id,
253
+ from: update.inline_query.from,
254
+ query: update.inline_query.query,
255
+ offset: update.inline_query.offset,
256
+ },
257
+ };
258
+ }
259
+
260
+ // Callback query (inline keyboard button press)
261
+ if (update.callback_query) {
262
+ const cq = update.callback_query;
263
+ return {
264
+ updateType: "callback_query",
265
+ data: {
266
+ id: cq.id,
267
+ from: cq.from,
268
+ message: cq.message ? extractMessageData(cq.message) : null,
269
+ data: cq.data ?? null,
270
+ gameShortName: cq.game_short_name ?? null,
271
+ },
272
+ };
273
+ }
274
+
275
+ // My chat member status update
276
+ if (update.my_chat_member || update.chat_member) {
277
+ const cm = update.my_chat_member ?? update.chat_member;
278
+ return {
279
+ updateType: update.my_chat_member ? "my_chat_member" : "chat_member",
280
+ data: {
281
+ chat: cm.chat,
282
+ from: cm.from,
283
+ date: new Date(cm.date * 1000).toISOString(),
284
+ oldStatus: cm.old_chat_member?.status,
285
+ newStatus: cm.new_chat_member?.status,
286
+ },
287
+ };
288
+ }
289
+
290
+ return { updateType: "unknown", data: update };
291
+ }
292
+
293
+ // ─── Webhook endpoint ─────────────────────────────────────────────────────────
294
+
295
+ app.post("/webhook", (req, res) => {
296
+ // Acknowledge Telegram immediately (must respond within 5 s)
297
+ res.sendStatus(200);
298
+
299
+ try {
300
+ const update = req.body;
301
+ const result = handleUpdate(update);
302
+
303
+ console.log("Update type :", result.updateType);
304
+ console.log("Parsed data :", JSON.stringify(result.data, null, 2));
305
+
306
+ // TODO: route to your business logic here, e.g.
307
+ // if (result.updateType === "message") processMessage(result.data);
308
+
309
+ } catch (err) {
310
+ console.error("Failed to process update:", err);
311
+ }
312
+ });
313
+
314
+ app.listen(3000, () => console.log("Webhook listening on :3000"));