@alemonjs/telegram 0.2.2 → 2.1.0-alpha.0
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/README.md +22 -5
- package/lib/config.d.ts +3 -0
- package/lib/config.js +20 -0
- package/lib/hook.d.ts +37 -0
- package/lib/hook.js +24 -0
- package/lib/index.d.ts +9 -0
- package/lib/index.js +96 -136
- package/package.json +12 -10
package/README.md
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
# [https://alemonjs.com/](https://alemonjs.com/)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[文档 https://core.telegram.org/bots ](https://core.telegram.org/bots)
|
|
4
|
+
|
|
5
|
+
## 创建机器人
|
|
6
|
+
|
|
7
|
+
[访问 https://core.telegram.org/bots/tutorial#obtain-your-bot-token](https://core.telegram.org/bots/tutorial#obtain-your-bot-token)
|
|
8
|
+
|
|
9
|
+
点击添加`@BotFather`并发送`/newbot`,并继续发送 `NameXBot` 得以生产 `token`
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
79179797979:AAAAAAAAAAAAAABBBBBBCCCCCCCCCC
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
- NameXdBot 即自定义的 bot 名
|
|
16
|
+
|
|
17
|
+
[访问 https://web.telegram.org/k/#@NameXdBot 以添加](https://web.telegram.org/k/#@NameXdBot)
|
|
4
18
|
|
|
5
19
|
## USE
|
|
6
20
|
|
|
@@ -22,9 +36,12 @@ telegram:
|
|
|
22
36
|
master_key: null
|
|
23
37
|
# other
|
|
24
38
|
base_api_url: null
|
|
39
|
+
#
|
|
25
40
|
request_url: null
|
|
41
|
+
# 使用 user_key
|
|
42
|
+
master_key:
|
|
43
|
+
- 'xxx'
|
|
44
|
+
# 使用 user_id
|
|
45
|
+
master_id:
|
|
46
|
+
- 'yyy'
|
|
26
47
|
```
|
|
27
|
-
|
|
28
|
-
## Community
|
|
29
|
-
|
|
30
|
-
QQ Group 806943302
|
package/lib/config.d.ts
ADDED
package/lib/config.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { getConfigValue, useUserHashKey } from 'alemonjs';
|
|
2
|
+
|
|
3
|
+
const platform = 'telegram';
|
|
4
|
+
const getTGConfig = () => {
|
|
5
|
+
const value = getConfigValue() || {};
|
|
6
|
+
return value[platform] || {};
|
|
7
|
+
};
|
|
8
|
+
const getMaster = (UserId) => {
|
|
9
|
+
const config = getTGConfig();
|
|
10
|
+
const master_key = config.master_key || [];
|
|
11
|
+
const master_id = config.master_id || [];
|
|
12
|
+
const UserKey = useUserHashKey({
|
|
13
|
+
Platform: platform,
|
|
14
|
+
UserId: UserId
|
|
15
|
+
});
|
|
16
|
+
const is = master_key.includes(UserKey) || master_id.includes(UserId);
|
|
17
|
+
return [is, UserKey];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export { getMaster, getTGConfig, platform };
|
package/lib/hook.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { EventKeys, Events } from 'alemonjs';
|
|
2
|
+
import TelegramClient from 'node-telegram-bot-api';
|
|
3
|
+
|
|
4
|
+
type MAP = {
|
|
5
|
+
'message.create': TelegramClient.Message;
|
|
6
|
+
'private.message.create': undefined;
|
|
7
|
+
'interaction.create': undefined;
|
|
8
|
+
'private.interaction.create': undefined;
|
|
9
|
+
'message.update': undefined;
|
|
10
|
+
'message.delete': undefined;
|
|
11
|
+
'message.reaction.add': undefined;
|
|
12
|
+
'message.reaction.remove': undefined;
|
|
13
|
+
'channal.create': undefined;
|
|
14
|
+
'channal.delete': undefined;
|
|
15
|
+
'guild.join': undefined;
|
|
16
|
+
'guild.exit': undefined;
|
|
17
|
+
'member.add': undefined;
|
|
18
|
+
'member.remove': undefined;
|
|
19
|
+
'private.message.update': undefined;
|
|
20
|
+
'private.message.delete': undefined;
|
|
21
|
+
'private.friend.add': undefined;
|
|
22
|
+
'private.guild.add': undefined;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
*
|
|
26
|
+
* @param event
|
|
27
|
+
* @returns
|
|
28
|
+
*/
|
|
29
|
+
declare const useValue: <T extends EventKeys>(event: Events[T]) => readonly [MAP[T]];
|
|
30
|
+
/**
|
|
31
|
+
*
|
|
32
|
+
* @param event
|
|
33
|
+
* @returns
|
|
34
|
+
*/
|
|
35
|
+
declare const useClient: <T extends EventKeys>(event: Events[T]) => readonly [TelegramClient, MAP[T]];
|
|
36
|
+
|
|
37
|
+
export { useClient, useValue };
|
package/lib/hook.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createEventValue, useClient as useClient$1 } from 'alemonjs';
|
|
2
|
+
import TelegramClient from 'node-telegram-bot-api';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param event
|
|
7
|
+
* @returns
|
|
8
|
+
*/
|
|
9
|
+
const useValue = (event) => {
|
|
10
|
+
const value = createEventValue(event);
|
|
11
|
+
return [value];
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
* @param event
|
|
16
|
+
* @returns
|
|
17
|
+
*/
|
|
18
|
+
const useClient = (event) => {
|
|
19
|
+
const [client] = useClient$1(event, TelegramClient);
|
|
20
|
+
const value = createEventValue(event);
|
|
21
|
+
return [client, value];
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export { useClient, useValue };
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import TelegramClient from 'node-telegram-bot-api';
|
|
2
|
+
export { platform } from './config.js';
|
|
3
|
+
export { useClient, useValue } from './hook.js';
|
|
4
|
+
|
|
5
|
+
declare const API: typeof TelegramClient;
|
|
6
|
+
|
|
7
|
+
declare const _default: () => void;
|
|
8
|
+
|
|
9
|
+
export { API, _default as default };
|
package/lib/index.js
CHANGED
|
@@ -1,20 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { cbpPlatform, createResult, ResultCode } from 'alemonjs';
|
|
2
|
+
import { getBufferByURL } from 'alemonjs/utils';
|
|
2
3
|
import TelegramClient from 'node-telegram-bot-api';
|
|
4
|
+
import { getTGConfig, getMaster, platform } from './config.js';
|
|
5
|
+
import { readFileSync } from 'fs';
|
|
6
|
+
export { useClient, useValue } from './hook.js';
|
|
3
7
|
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const original = global.client[prop];
|
|
8
|
-
// 防止函数内this丢失
|
|
9
|
-
return typeof original === 'function' ? original.bind(global.client) : original;
|
|
10
|
-
}
|
|
11
|
-
return undefined;
|
|
12
|
-
}
|
|
13
|
-
});
|
|
14
|
-
const platform = 'telegram';
|
|
15
|
-
var index = defineBot(() => {
|
|
16
|
-
const value = getConfigValue();
|
|
17
|
-
const config = value[platform];
|
|
8
|
+
const API = TelegramClient;
|
|
9
|
+
var index = () => {
|
|
10
|
+
const config = getTGConfig();
|
|
18
11
|
const client = new TelegramClient(config.token, {
|
|
19
12
|
polling: true,
|
|
20
13
|
baseApiUrl: config?.base_api_url ?? '',
|
|
@@ -23,6 +16,8 @@ var index = defineBot(() => {
|
|
|
23
16
|
proxy: config?.proxy ?? ''
|
|
24
17
|
}
|
|
25
18
|
});
|
|
19
|
+
const url = `ws://127.0.0.1:${process.env?.port || config?.port || 17117}`;
|
|
20
|
+
const cbp = cbpPlatform(url);
|
|
26
21
|
/**
|
|
27
22
|
*
|
|
28
23
|
* @param UserId
|
|
@@ -58,41 +53,8 @@ var index = defineBot(() => {
|
|
|
58
53
|
};
|
|
59
54
|
client.on('text', async (event) => {
|
|
60
55
|
const UserId = String(event?.from?.id);
|
|
61
|
-
const UserKey =
|
|
62
|
-
|
|
63
|
-
UserId: UserId
|
|
64
|
-
});
|
|
65
|
-
const UserAvatar = {
|
|
66
|
-
toBuffer: async () => {
|
|
67
|
-
if (event?.chat.type == 'supergroup' || event?.chat.type == 'private') {
|
|
68
|
-
const photo = await getUserProfilePhotosUrl(event?.from?.id).catch(console.error);
|
|
69
|
-
if (typeof photo == 'string') {
|
|
70
|
-
const arrayBuffer = await fetch(photo).then(res => res.arrayBuffer());
|
|
71
|
-
return Buffer.from(arrayBuffer);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return;
|
|
75
|
-
},
|
|
76
|
-
toURL: async () => {
|
|
77
|
-
if (event?.chat.type == 'supergroup' || event?.chat.type == 'private') {
|
|
78
|
-
const photo = await getUserProfilePhotosUrl(event?.from?.id).catch(console.error);
|
|
79
|
-
if (typeof photo == 'string') {
|
|
80
|
-
return photo;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return;
|
|
84
|
-
},
|
|
85
|
-
toBase64: async () => {
|
|
86
|
-
if (event?.chat.type == 'supergroup' || event?.chat.type == 'private') {
|
|
87
|
-
const photo = await getUserProfilePhotosUrl(event?.from?.id).catch(console.error);
|
|
88
|
-
if (typeof photo == 'string') {
|
|
89
|
-
const arrayBuffer = await fetch(photo).then(res => res.arrayBuffer());
|
|
90
|
-
return Buffer.from(arrayBuffer).toString('base64');
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
};
|
|
56
|
+
const [isMaster, UserKey] = getMaster(UserId);
|
|
57
|
+
const UserAvatar = (await getUserProfilePhotosUrl(event?.from?.id));
|
|
96
58
|
if (event?.chat.type == 'channel' || event?.chat.type == 'supergroup') {
|
|
97
59
|
// 机器人消息不处理
|
|
98
60
|
if (event?.from?.is_bot)
|
|
@@ -101,37 +63,35 @@ var index = defineBot(() => {
|
|
|
101
63
|
const e = {
|
|
102
64
|
// 事件类型
|
|
103
65
|
Platform: platform,
|
|
66
|
+
name: 'message.create',
|
|
104
67
|
// 频道
|
|
105
68
|
GuildId: String(event?.chat.id),
|
|
106
69
|
ChannelId: String(event?.chat.id),
|
|
70
|
+
SpaceId: String(event?.chat.id),
|
|
107
71
|
// user
|
|
108
72
|
UserId: UserId,
|
|
109
73
|
UserKey: UserKey,
|
|
110
74
|
UserName: event?.chat.username,
|
|
111
75
|
UserAvatar: UserAvatar,
|
|
112
|
-
IsMaster:
|
|
76
|
+
IsMaster: isMaster,
|
|
113
77
|
IsBot: false,
|
|
114
78
|
// message
|
|
115
79
|
MessageId: String(event?.message_id),
|
|
80
|
+
MessageText: event?.text,
|
|
116
81
|
OpenId: String(event?.chat?.id),
|
|
117
82
|
CreateAt: Date.now(),
|
|
118
83
|
// other
|
|
119
84
|
tag: 'txt',
|
|
120
|
-
value:
|
|
85
|
+
value: event
|
|
121
86
|
};
|
|
122
|
-
//
|
|
123
|
-
|
|
124
|
-
get() {
|
|
125
|
-
return event;
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
//
|
|
129
|
-
OnProcessor(e, 'message.create');
|
|
87
|
+
// 发送消息
|
|
88
|
+
cbp.send(e);
|
|
130
89
|
//
|
|
131
90
|
}
|
|
132
91
|
else if (event?.chat.type == 'private') {
|
|
133
92
|
// 定义消
|
|
134
93
|
const e = {
|
|
94
|
+
name: 'private.message.create',
|
|
135
95
|
// 事件类型
|
|
136
96
|
Platform: platform,
|
|
137
97
|
// 用户Id
|
|
@@ -139,7 +99,7 @@ var index = defineBot(() => {
|
|
|
139
99
|
UserKey: UserKey,
|
|
140
100
|
UserName: event?.from?.username,
|
|
141
101
|
UserAvatar: UserAvatar,
|
|
142
|
-
IsMaster:
|
|
102
|
+
IsMaster: isMaster,
|
|
143
103
|
IsBot: false,
|
|
144
104
|
// message
|
|
145
105
|
MessageId: String(event?.message_id),
|
|
@@ -148,16 +108,9 @@ var index = defineBot(() => {
|
|
|
148
108
|
CreateAt: Date.now(),
|
|
149
109
|
// other
|
|
150
110
|
tag: 'txt',
|
|
151
|
-
value:
|
|
111
|
+
value: event
|
|
152
112
|
};
|
|
153
|
-
|
|
154
|
-
Object.defineProperty(e, 'value', {
|
|
155
|
-
get() {
|
|
156
|
-
return event;
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
// 处理消息
|
|
160
|
-
OnProcessor(e, 'private.message.create');
|
|
113
|
+
cbp.send(e);
|
|
161
114
|
}
|
|
162
115
|
});
|
|
163
116
|
client.on('new_chat_members', async (event) => {
|
|
@@ -165,96 +118,103 @@ var index = defineBot(() => {
|
|
|
165
118
|
if (event?.from.is_bot)
|
|
166
119
|
return;
|
|
167
120
|
const UserId = String(event?.from?.id);
|
|
168
|
-
const UserKey =
|
|
169
|
-
|
|
170
|
-
UserId: UserId
|
|
171
|
-
});
|
|
172
|
-
const UserAvatar = {
|
|
173
|
-
toBuffer: async () => {
|
|
174
|
-
const photo = await getUserProfilePhotosUrl(event?.from?.id).catch(console.error);
|
|
175
|
-
if (typeof photo == 'string') {
|
|
176
|
-
const arrayBuffer = await fetch(photo).then(res => res.arrayBuffer());
|
|
177
|
-
return Buffer.from(arrayBuffer);
|
|
178
|
-
}
|
|
179
|
-
return;
|
|
180
|
-
},
|
|
181
|
-
toURL: async () => {
|
|
182
|
-
const photo = await getUserProfilePhotosUrl(event?.from?.id).catch(console.error);
|
|
183
|
-
if (typeof photo == 'string') {
|
|
184
|
-
return photo;
|
|
185
|
-
}
|
|
186
|
-
return;
|
|
187
|
-
},
|
|
188
|
-
toBase64: async () => {
|
|
189
|
-
const photo = await getUserProfilePhotosUrl(event?.from?.id).catch(console.error);
|
|
190
|
-
if (typeof photo == 'string') {
|
|
191
|
-
const arrayBuffer = await fetch(photo).then(res => res.arrayBuffer());
|
|
192
|
-
return Buffer.from(arrayBuffer).toString('base64');
|
|
193
|
-
}
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
};
|
|
121
|
+
const [isMaster, UserKey] = getMaster(UserId);
|
|
122
|
+
const UserAvatar = (await getUserProfilePhotosUrl(event?.from?.id));
|
|
197
123
|
// 定义消
|
|
198
124
|
const e = {
|
|
125
|
+
naem: 'member.add',
|
|
199
126
|
// 事件类型
|
|
200
127
|
Platform: platform,
|
|
201
128
|
// guild
|
|
202
129
|
GuildId: String(event?.chat.id),
|
|
203
130
|
ChannelId: String(event?.chat.id),
|
|
204
|
-
|
|
131
|
+
SpaceId: String(event?.chat.id),
|
|
205
132
|
// user
|
|
206
133
|
UserId: UserId,
|
|
207
134
|
UserKey: UserKey,
|
|
208
135
|
UserName: event?.chat.username,
|
|
209
136
|
UserAvatar: UserAvatar,
|
|
210
|
-
IsMaster:
|
|
137
|
+
IsMaster: isMaster,
|
|
211
138
|
IsBot: false,
|
|
212
|
-
// message
|
|
213
139
|
MessageId: String(event?.message_id),
|
|
214
|
-
MessageText: event?.text,
|
|
215
|
-
OpenId: String(event?.chat?.id),
|
|
216
140
|
CreateAt: Date.now(),
|
|
217
141
|
// othder
|
|
218
142
|
tag: 'txt',
|
|
219
|
-
value:
|
|
143
|
+
value: event
|
|
220
144
|
};
|
|
221
|
-
|
|
222
|
-
Object.defineProperty(e, 'value', {
|
|
223
|
-
get() {
|
|
224
|
-
return event;
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
//
|
|
228
|
-
OnProcessor(e, 'member.add');
|
|
145
|
+
cbp.send(e);
|
|
229
146
|
});
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
const e = event?.value;
|
|
147
|
+
const api = {
|
|
148
|
+
use: {
|
|
149
|
+
send: async (event, val) => {
|
|
150
|
+
if (val.length < 0)
|
|
151
|
+
return [];
|
|
152
|
+
const content = val
|
|
153
|
+
.filter(item => item.type == 'Link' || item.type == 'Mention' || item.type == 'Text')
|
|
154
|
+
.map(item => item.value)
|
|
155
|
+
.join('');
|
|
156
|
+
const e = event?.value;
|
|
157
|
+
try {
|
|
242
158
|
if (content) {
|
|
243
|
-
|
|
159
|
+
const res = await client.sendMessage(e.chat.id, content);
|
|
160
|
+
return [createResult(ResultCode.Ok, 'message.send', res)];
|
|
244
161
|
}
|
|
245
|
-
const images = val.filter(item => item.type == 'Image'
|
|
246
|
-
if (images) {
|
|
247
|
-
|
|
162
|
+
const images = val.filter(item => item.type == 'Image' || item.type == 'ImageFile' || item.type == 'ImageURL');
|
|
163
|
+
if (images.length > 1) {
|
|
164
|
+
let data = null;
|
|
165
|
+
for (let i = 0; i < images.length; i++) {
|
|
166
|
+
if (data)
|
|
167
|
+
break;
|
|
168
|
+
const item = images[i];
|
|
169
|
+
if (item.type === 'Image') {
|
|
170
|
+
data = item.value;
|
|
171
|
+
}
|
|
172
|
+
else if (item.type === 'ImageFile') {
|
|
173
|
+
data = readFileSync(item.value);
|
|
174
|
+
}
|
|
175
|
+
else if (item.type === 'ImageURL') {
|
|
176
|
+
data = await getBufferByURL(item.value);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
const res = await client.sendPhoto(e.chat.id, data);
|
|
180
|
+
return [createResult(ResultCode.Ok, 'message.send', res)];
|
|
248
181
|
}
|
|
249
|
-
return Promise.all([]);
|
|
250
|
-
},
|
|
251
|
-
mention: async () => {
|
|
252
|
-
// const event: TelegramClient.Message = e.value
|
|
253
|
-
return [];
|
|
254
182
|
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
return [createResult(ResultCode.Fail, err?.response?.data ?? err?.message ?? err, null)];
|
|
185
|
+
}
|
|
186
|
+
return [];
|
|
187
|
+
},
|
|
188
|
+
mention: async () => {
|
|
189
|
+
return [];
|
|
255
190
|
}
|
|
256
191
|
}
|
|
257
192
|
};
|
|
258
|
-
|
|
193
|
+
cbp.onactions(async (data, consume) => {
|
|
194
|
+
if (data.action === 'message.send') {
|
|
195
|
+
const event = data.payload.event;
|
|
196
|
+
const paramFormat = data.payload.params.format;
|
|
197
|
+
const res = await api.use.send(event, paramFormat);
|
|
198
|
+
consume(res);
|
|
199
|
+
}
|
|
200
|
+
else if (data.action === 'message.send.channel') {
|
|
201
|
+
consume([]);
|
|
202
|
+
}
|
|
203
|
+
else if (data.action === 'message.send.user') {
|
|
204
|
+
consume([]);
|
|
205
|
+
}
|
|
206
|
+
else if (data.action === 'mention.get') {
|
|
207
|
+
consume([]);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
cbp.onapis(async (data, consume) => {
|
|
211
|
+
const key = data.payload?.key;
|
|
212
|
+
if (client[key]) {
|
|
213
|
+
const params = data.payload.params;
|
|
214
|
+
const res = await client[key](...params);
|
|
215
|
+
consume([createResult(ResultCode.Ok, '请求完成', res)]);
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
};
|
|
259
219
|
|
|
260
|
-
export {
|
|
220
|
+
export { API, index as default, platform };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alemonjs/telegram",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "telegram
|
|
3
|
+
"version": "2.1.0-alpha.0",
|
|
4
|
+
"description": "telegram platform connection",
|
|
5
5
|
"author": "lemonade",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"type": "module",
|
|
@@ -11,17 +11,10 @@
|
|
|
11
11
|
"build": "node bundle.js"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
+
"@types/node-telegram-bot-api": "^0.64.9",
|
|
14
15
|
"grammy": "^1.30.0",
|
|
15
16
|
"node-telegram-bot-api": "^0.66.0"
|
|
16
17
|
},
|
|
17
|
-
"devDependencies": {
|
|
18
|
-
"@rollup/plugin-typescript": "^11.1.6",
|
|
19
|
-
"lvyjs": "^0.2.13",
|
|
20
|
-
"rollup": "^4.18.1",
|
|
21
|
-
"rollup-plugin-dts": "^6.1.1",
|
|
22
|
-
"tsx": "^4.19.1",
|
|
23
|
-
"@types/node-telegram-bot-api": "^0.64.7"
|
|
24
|
-
},
|
|
25
18
|
"exports": {
|
|
26
19
|
".": {
|
|
27
20
|
"import": "./lib/index.js",
|
|
@@ -29,6 +22,15 @@
|
|
|
29
22
|
},
|
|
30
23
|
"./package": "./package.json"
|
|
31
24
|
},
|
|
25
|
+
"alemonjs": {
|
|
26
|
+
"desktop": {
|
|
27
|
+
"platform": [
|
|
28
|
+
{
|
|
29
|
+
"name": "telegram"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
32
34
|
"keywords": [
|
|
33
35
|
"alemonjs"
|
|
34
36
|
],
|