├── .files
├── about.txt
└── schema.txt
├── .gitignore
├── LICENSE
├── README.md
├── bower.json
├── dist
├── telegramApi.js
└── telegramApi.min.js
├── docs
├── API.md
├── build.js
├── examples
│ ├── createChannel.js
│ ├── createChat.js
│ ├── downloadDocument.js
│ ├── editChatAdmin.js
│ ├── editChatTitle.js
│ ├── getChatLink.js
│ ├── getHistory.js
│ ├── getUserInfo.js
│ ├── getUserPhoto.js
│ ├── invokeApi.js
│ ├── joinChat.js
│ ├── logOut.js
│ ├── sendCode.js
│ ├── sendFile.js
│ ├── sendMessage.js
│ ├── sendSms.js
│ ├── setConfig.js
│ ├── signIn.js
│ ├── signUp.js
│ └── startBot.js
└── jsdoc-options.json
├── example
├── index.html
├── script.js
└── style.css
├── gulpfile.js
├── package.json
└── src
├── IoC.js
├── js
├── App
│ ├── AppChatsManager.js
│ ├── AppPeersManager.js
│ ├── AppProfileManager.js
│ └── AppUsersManager.js
├── Etc
│ ├── CryptoWorker.js
│ ├── FileSaver.js
│ ├── Helper.js
│ ├── IdleManager.js
│ ├── Storage.js
│ ├── TelegramMeWebService.js
│ ├── angular
│ │ ├── $http.js
│ │ ├── $interval.js
│ │ ├── $q.js
│ │ ├── $rootScope.js
│ │ └── $timeout.js
│ ├── jQuery.js
│ └── qSync.js
├── Mtp
│ ├── MtpApiFileManager.js
│ ├── MtpApiManager.js
│ ├── MtpAuthorizer.js
│ ├── MtpDcConfigurator.js
│ ├── MtpNetworkerFactory.js
│ ├── MtpRsaKeysManager.js
│ ├── MtpSecureRandom.js
│ ├── MtpSingleInstanceService.js
│ └── MtpTimeManager.js
└── lib
│ ├── bin_utils.js
│ ├── config.js
│ ├── polyfill.js
│ ├── tl_utils.js
│ └── utils.js
├── telegramApi.js
└── vendor
├── cryptoJS
├── THIRDPARTY_LICENSE
└── crypto.min.js
└── jsbn
├── THIRDPARTY_LICENSE
└── jsbn_combined.min.js
/.files/about.txt:
--------------------------------------------------------------------------------
1 | /**
2 | * telegram-api v{VERSION}
3 | * Infinnity Solutions
4 | */
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | node_modules
3 | example/js/
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TelegramApi
2 |
3 | Based on [**webogram**](https://github.com/zhukov/webogram)
4 |
5 | ## Getting started
6 |
7 | 1) Install package via npm
8 | ```
9 | npm install telegram-api-js
10 | ```
11 | Or bower
12 | ```
13 | bower install telegram-api-js
14 | ```
15 |
16 | 2) Add a ```
24 |
25 |
26 |
27 | ```
28 |
29 | 3) Set your app configuration
30 | ```
31 | /* You should register your application on https://my.telegram.org/ */
32 | telegramApi.setConfig({
33 | app: {
34 | id: 0, /* App ID */
35 | hash: 'qwertyasdfghzxcvbnqwertyasd', /* App hash */
36 | version: '0.0.0' /* App version */
37 | },
38 | server: {
39 | test: [
40 | {
41 | id: 2, /* DC ID */
42 | host: '0.0.0.0',
43 | port: 443
44 | }
45 | ],
46 | production: [
47 | {
48 | id: 2, /* DC ID */
49 | host: '0.0.0.0',
50 | port: 123
51 | }
52 | ]
53 | }
54 | });
55 | ```
56 |
57 | 4) Check your status
58 | ```
59 | telegramApi.getUserInfo().then(function(user) {
60 | if (user.id) {
61 | // You have already signed in
62 | } else {
63 | // Log in
64 | }
65 | });
66 | ```
67 |
68 | [API documentation](./docs/API.md)
69 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "telegram-api",
3 | "license": "GPL-3.0",
4 | "ignore": [
5 | "example",
6 | "src",
7 | "gulpfile.js",
8 | "package.json"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/docs/API.md:
--------------------------------------------------------------------------------
1 | # Methods
2 |
3 |
4 |
5 |
6 | - invokeApi(method, [params])
7 | Invoke any method from .files/schema.txt
8 |
9 | - sendCode(phone_number)
10 | Send code by phone number
11 |
12 | - signIn(phone_number, phone_code_hash, phone_code)
13 | Sign in
14 |
15 | - signUp(phone_number, phone_code_hash, phone_code, first_name, [last_name])
16 | Sign up
17 |
18 | - sendMessage(id, message)
19 | Send message
20 |
21 | - startBot(botName)
22 | Send bot command /start
23 |
24 | - sendSms(phone_number, phone_code_hash)
25 | Send code via SMS
26 |
27 | - setConfig(config)
28 | Configure your application
29 |
30 | - createChat(title, userIDs)
31 | Create telegram chat (By default only creator will admin. In the future it will be changed)
32 |
33 | - getChatLink(chatID, [force])
34 | Get chat invite link
35 |
36 | - getUserInfo()
37 | Get self information
38 |
39 | - getUserPhoto([type], [size])
40 | Get user photo
41 |
42 | - logOut()
43 | Logout from Telegram
44 |
45 | - createChannel(title, [about])
46 | Create channel (use carefully)
47 |
48 | - getHistory(params)
49 | Get chat messages
50 |
51 | - sendFile(params)
52 | Send file
53 |
54 | - downloadDocument(doc, [progress], [autosave])
55 | Download Telegram document
56 |
57 | - joinChat(link)
58 | Join to chat by link or hash
59 |
60 | - editChatAdmin(chatID, userID, [isAdmin])
61 | Edit chat administrator
62 |
63 | - editChatTitle(chat_id, title)
64 | Edit chat title
65 |
66 |
67 |
68 |
69 |
70 | ## invokeApi(method, [params])
71 | Invoke any method from .files/schema.txt
72 |
73 |
74 |
75 | | Param | Type | Description |
76 | | --- | --- | --- |
77 | | method | String
| Method name |
78 | | [params] | Object
| Parameters |
79 |
80 | **Example**
81 | ```js
82 | telegramApi.invokeApi('messages.getDialogs', {
83 | offset_peer: {_: 'inputPeerEmpty'},
84 | offset_date: 0,
85 | limit: 20
86 | }).then(function(dialogResult) {
87 | /* Do something */
88 | });
89 | ```
90 |
91 |
92 | ## sendCode(phone_number)
93 | Send code by phone number
94 |
95 |
96 |
97 | | Param | Type | Description |
98 | | --- | --- | --- |
99 | | phone_number | String
| Phone number |
100 |
101 | **Example**
102 | ```js
103 | telegramApi.sendCode('some_phone_number').then(function(sent_code) {
104 | if (!sent_code.phone_registered) {
105 | // New user
106 | }
107 |
108 | // phone_code_hash will need to sign in or sign up
109 | window.phone_code_hash = sent_code.phone_code_hash;
110 | });
111 | ```
112 |
113 |
114 | ## signIn(phone_number, phone_code_hash, phone_code)
115 | Sign in
116 |
117 |
118 |
119 | | Param | Type | Description |
120 | | --- | --- | --- |
121 | | phone_number | String
| Phone number |
122 | | phone_code_hash | String
| Code hash (was received in sendCode method) |
123 | | phone_code | String
| Code by Telegram |
124 |
125 | **Example**
126 | ```js
127 | telegramApi.signIn('some_phone_number', window.phone_code_hash, '000000').then(function() {
128 | // Sign in complete
129 | delete window.phone_code_hash;
130 | }, function(err) {
131 | switch (err.type) {
132 | case 'PHONE_CODE_INVALID':
133 | // alert "Phone code invalid"
134 | break;
135 | case 'PHONE_NUMBER_UNOCCUPIED':
136 | // User not registered, you should use signUp method
137 | break;
138 | }
139 | });
140 | ```
141 |
142 |
143 | ## signUp(phone_number, phone_code_hash, phone_code, first_name, [last_name])
144 | Sign up
145 |
146 |
147 |
148 | | Param | Type | Description |
149 | | --- | --- | --- |
150 | | phone_number | String
| Phone number |
151 | | phone_code_hash | String
| Code hash (was received in sendCode method) |
152 | | phone_code | String
| Code by Telegram |
153 | | first_name | String
| User first name |
154 | | [last_name] | String
| User last name |
155 |
156 | **Example**
157 | ```js
158 | telegramApi.signUp('some_phone_number', window.phone_code_hash, '000000', 'John', 'Doe').then(function() {
159 | // Sign up complete
160 | delete window.phone_code_hash;
161 | });
162 | ```
163 |
164 |
165 | ## sendMessage(id, message)
166 | Send message
167 |
168 |
169 |
170 | | Param | Type | Description |
171 | | --- | --- | --- |
172 | | id | Number
| Peer ID |
173 | | message | String
| Message text |
174 |
175 | **Example**
176 | ```js
177 | telegramApi.sendMessage(9999999999, 'Hey man!').then(function(updates) {
178 | // Do something
179 | });
180 | ```
181 |
182 |
183 | ## startBot(botName)
184 | Send bot command /start
185 |
186 |
187 |
188 | | Param | Type | Description |
189 | | --- | --- | --- |
190 | | botName | String
| Bot name |
191 |
192 | **Example**
193 | ```js
194 | telegramApi.startBot('exampleBot').then(function(updates) {
195 | // Was invoked telegramApi.sendMessage(bot.id, '/start');
196 | });
197 | ```
198 |
199 |
200 | ## sendSms(phone_number, phone_code_hash)
201 | Send code via SMS
202 |
203 |
204 |
205 | | Param | Type | Description |
206 | | --- | --- | --- |
207 | | phone_number | String
| Phone number |
208 | | phone_code_hash | String
| Code hash (was received in sendCode method) |
209 |
210 | **Example**
211 | ```js
212 | telegramApi.sendSms('some_phone_number', window.phone_code_hash).then(function() {
213 | // Do something
214 | });
215 | ```
216 |
217 |
218 | ## setConfig(config)
219 | Configure your application
220 |
221 |
222 |
223 | | Param | Type | Description |
224 | | --- | --- | --- |
225 | | config | Object
| Configuration object |
226 | | config.app.id | Number
| Application ID |
227 | | config.app.hash | String
| App hash |
228 | | config.app.version | String
| App version |
229 | | config.server.test | Array.<Object>
| List test servers |
230 | | config.server.production | Array.<Object>
| List production servers |
231 |
232 | **Example**
233 | ```js
234 | telegramApi.setConfig({
235 | app: {
236 | id: 0, /* App ID */
237 | hash: 'qwertyasdfghzxcvbnqwertyasd', /* App hash */
238 | version: '0.0.0' /* App version */
239 | },
240 | server: {
241 | test: [
242 | {
243 | id: 2, /* DC ID */
244 | host: '0.0.0.0',
245 | port: 443
246 | }
247 | ],
248 | production: [
249 | {
250 | id: 2, /* DC ID */
251 | host: '0.0.0.0',
252 | port: 123
253 | }
254 | ]
255 | }
256 | });
257 | ```
258 |
259 |
260 | ## createChat(title, userIDs)
261 | Create telegram chat (By default only creator will admin. In the future it will be changed)
262 |
263 |
264 |
265 | | Param | Type | Description |
266 | | --- | --- | --- |
267 | | title | String
| Chat title |
268 | | userIDs | Array.<Number>
| User ids list |
269 |
270 | **Example**
271 | ```js
272 | telegramApi.createChat('Chat title', [123456789]).then(function(updates) {
273 | // If you want all users to be administrators, use it
274 | return telegramApi.invokeApi('messages.toggleChatAdmins', {
275 | chat_id: updates.chats[0].id,
276 | enabled: false
277 | });
278 | });
279 | ```
280 |
281 |
282 | ## getChatLink(chatID, [force])
283 | Get chat invite link
284 |
285 |
286 |
287 | | Param | Type | Description |
288 | | --- | --- | --- |
289 | | chatID | Number
| String
| Chat id |
290 | | [force] | Boolean
| Force generate |
291 |
292 | **Example**
293 | ```js
294 | telegramApi.getChatLink(12456789, true).then(function(link) {
295 | // Do something
296 | });
297 | ```
298 |
299 |
300 | ## getUserInfo()
301 | Get self information
302 |
303 |
304 | **Example**
305 | ```js
306 | telegramApi.getUserInfo().then(function(user) {
307 | if (user.id) {
308 | // You have already signed in
309 | } else {
310 | // Open log in page
311 | }
312 | });
313 | ```
314 |
315 |
316 | ## getUserPhoto([type], [size])
317 | Get user photo
318 |
319 |
320 |
321 | | Param | Type | Description |
322 | | --- | --- | --- |
323 | | [type] | String
| Photo type (values: byteArray (default), base64, blob) |
324 | | [size] | String
| Photo size (values: big (default), small) |
325 |
326 | **Example**
327 | ```js
328 | telegramApi.getUserPhoto('base64', 'small').then(function(base64) {
329 | $('img#avatar').attr('src', base64);
330 | });
331 | ```
332 |
333 |
334 | ## logOut()
335 | Logout from Telegram
336 |
337 |
338 | **Example**
339 | ```js
340 | telegramApi.logOut().then(function() {
341 | setTimeout(function() {
342 | // Do something after logouts
343 | // Use setTimeout (It will be fixed)
344 | }, 1500);
345 | });
346 | ```
347 |
348 |
349 | ## createChannel(title, [about])
350 | Create channel (use carefully)
351 |
352 |
353 |
354 | | Param | Type | Description |
355 | | --- | --- | --- |
356 | | title | String
| Channel title |
357 | | [about] | String
| About text |
358 |
359 | **Example**
360 | ```js
361 | telegramApi.createChannel('New channel', 'This is example channel').then(function(updates) {
362 | var channel = updates.chats[0];
363 |
364 | /**
365 | * WARNING!
366 | * If you often call this method, you will receive a reply FLOOD_WAIT_{seconds}
367 | */
368 | });
369 | ```
370 |
371 |
372 | ## getHistory(params)
373 | Get chat messages
374 |
375 |
376 |
377 | | Param | Type | Description |
378 | | --- | --- | --- |
379 | | params | Object
| Parameters |
380 | | params.id | Number
| Chat ID |
381 | | [params.take] | Number
| How much messages you will receive (default: 15) |
382 | | [params.skip] | Number
| How much messages you will skip (default: 0) |
383 | | [params.type] | String
| Chat type (for chat and channel use 'chat' (default)) |
384 |
385 | **Example**
386 | ```js
387 | telegramApi.getHistory({
388 | id: 12345678,
389 | take: 50,
390 | type: 'user'
391 | }).then(function(data) {
392 | var totalCount = data.count || data.messages.length;
393 |
394 | data.messages.forEach(function(message) {
395 | /**
396 | * message.from_id - Sender ID
397 | * message.date - Date
398 | * message.media - If message is Document or Photo
399 | * message.message - Message text
400 | */
401 | });
402 | });
403 | ```
404 |
405 |
406 | ## sendFile(params)
407 | Send file
408 |
409 |
410 |
411 | | Param | Type | Description |
412 | | --- | --- | --- |
413 | | params | Object
| Parameters |
414 | | params.id | Number
| Peer ID |
415 | | params.type | String
| Chat type (for chat and channel use 'chat' (default)) |
416 | | params.file | File
| File |
417 | | [params.caption] | String
| File caption |
418 |
419 | **Example**
420 | ```js
421 | telegramApi.sendFile({
422 | id: 123456789,
423 | type: 'user',
424 | file: $('input[type=file]').val(),
425 | caption: 'This is file'
426 | }).then(function(updates) {
427 | // Do something
428 | });
429 | ```
430 |
431 |
432 | ## downloadDocument(doc, [progress], [autosave])
433 | Download Telegram document
434 |
435 |
436 |
437 | | Param | Type | Description |
438 | | --- | --- | --- |
439 | | doc | Object
| Telegram document |
440 | | [progress] | function
| Progress callback |
441 | | [autosave] | Boolean
| Save file on device |
442 |
443 | **Example**
444 | ```js
445 | telegramApi.getHistory({
446 | id: 123456789,
447 | type: 'user',
448 | take: 1,
449 | skip: 0
450 | }).then(function(data) {
451 | var message = data.messages[0];
452 | var doc = message.media.document;
453 |
454 | telegramApi.downloadDocument(doc, function(downloaded, total) {
455 | console.log('Loaded ' + downloaded + ' bytes. Total ' + total + ' bytes');
456 | }).then(function(result) {
457 | /**
458 | * result.bytes - file data
459 | * result.fileName - file name
460 | * result.type - file MIME-type
461 | */
462 | });
463 | });
464 | ```
465 |
466 |
467 | ## joinChat(link)
468 | Join to chat by link or hash
469 |
470 |
471 |
472 | | Param | Type | Description |
473 | | --- | --- | --- |
474 | | link | String
| Chat invite link or hash |
475 |
476 | **Example**
477 | ```js
478 | telegramApi.joinChat('https://telegram.me/joinchat/some-hash').then(function(updates) {
479 | // Do something
480 | });
481 | ```
482 |
483 |
484 | ## editChatAdmin(chatID, userID, [isAdmin])
485 | Edit chat administrator
486 |
487 |
488 |
489 | | Param | Type | Description |
490 | | --- | --- | --- |
491 | | chatID | Number
| Chat ID |
492 | | userID | Number
| User ID |
493 | | [isAdmin] | Boolean
| Admin status (default: true) |
494 |
495 | **Example**
496 | ```js
497 | telegramApi.editChatAdmin(123456789, 987654321, false).then(function() {
498 | // Do something
499 | });
500 | ```
501 |
502 |
503 | ## editChatTitle(chat_id, title)
504 | Edit chat title
505 |
506 |
507 |
508 | | Param | Type | Description |
509 | | --- | --- | --- |
510 | | chat_id | Number
| Chat ID |
511 | | title | String
| New title |
512 |
513 | **Example**
514 | ```js
515 | telegramApi.editChatTitle(123456789, 'New title').then(function() {
516 | // Do something
517 | });
518 | ```
519 |
520 |
521 | ## To be continued
--------------------------------------------------------------------------------
/docs/build.js:
--------------------------------------------------------------------------------
1 | const jsdoc2md = require('jsdoc-to-markdown');
2 | const fs = require('fs');
3 |
4 | const output = './docs/API.md';
5 | const examplesPath = './docs/examples/';
6 |
7 | let options = require('./jsdoc-options.json');
8 |
9 | jsdoc2md.render(options).then(result => {
10 | result = result
11 | .replace(/\*\*Kind\*\*: global function/g, '')
12 | .replace(/## Functions/g, '')
13 | .replace(/<%example:(\w+\.js)%>/g, function(str, fileName) {
14 | return fs.readFileSync(examplesPath + fileName, 'utf8').replace(/\n$/, '');
15 | });
16 |
17 | fs.writeFileSync(output, '# Methods\n\n' + result + '\n\n## To be continued');
18 | });
19 |
--------------------------------------------------------------------------------
/docs/examples/createChannel.js:
--------------------------------------------------------------------------------
1 | telegramApi.createChannel('New channel', 'This is example channel').then(function(updates) {
2 | var channel = updates.chats[0];
3 |
4 | /**
5 | * WARNING!
6 | * If you often call this method, you will receive a reply FLOOD_WAIT_{seconds}
7 | */
8 | });
9 |
--------------------------------------------------------------------------------
/docs/examples/createChat.js:
--------------------------------------------------------------------------------
1 | telegramApi.createChat('Chat title', [123456789]).then(function(updates) {
2 | // If you want all users to be administrators, use it
3 | return telegramApi.invokeApi('messages.toggleChatAdmins', {
4 | chat_id: updates.chats[0].id,
5 | enabled: false
6 | });
7 | });
8 |
--------------------------------------------------------------------------------
/docs/examples/downloadDocument.js:
--------------------------------------------------------------------------------
1 | telegramApi.getHistory({
2 | id: 123456789,
3 | type: 'user',
4 | take: 1,
5 | skip: 0
6 | }).then(function(data) {
7 | var message = data.messages[0];
8 | var doc = message.media.document;
9 |
10 | telegramApi.downloadDocument(doc, function(downloaded, total) {
11 | console.log('Loaded ' + downloaded + ' bytes. Total ' + total + ' bytes');
12 | }).then(function(result) {
13 | /**
14 | * result.bytes - file data
15 | * result.fileName - file name
16 | * result.type - file MIME-type
17 | */
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/docs/examples/editChatAdmin.js:
--------------------------------------------------------------------------------
1 | telegramApi.editChatAdmin(123456789, 987654321, false).then(function() {
2 | // Do something
3 | });
4 |
--------------------------------------------------------------------------------
/docs/examples/editChatTitle.js:
--------------------------------------------------------------------------------
1 | telegramApi.editChatTitle(123456789, 'New title').then(function() {
2 | // Do something
3 | });
4 |
--------------------------------------------------------------------------------
/docs/examples/getChatLink.js:
--------------------------------------------------------------------------------
1 | telegramApi.getChatLink(12456789, true).then(function(link) {
2 | // Do something
3 | });
4 |
--------------------------------------------------------------------------------
/docs/examples/getHistory.js:
--------------------------------------------------------------------------------
1 | telegramApi.getHistory({
2 | id: 12345678,
3 | take: 50,
4 | type: 'user'
5 | }).then(function(data) {
6 | var totalCount = data.count || data.messages.length;
7 |
8 | data.messages.forEach(function(message) {
9 | /**
10 | * message.from_id - Sender ID
11 | * message.date - Date
12 | * message.media - If message is Document or Photo
13 | * message.message - Message text
14 | */
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/docs/examples/getUserInfo.js:
--------------------------------------------------------------------------------
1 | telegramApi.getUserInfo().then(function(user) {
2 | if (user.id) {
3 | // You have already signed in
4 | } else {
5 | // Open log in page
6 | }
7 | });
8 |
--------------------------------------------------------------------------------
/docs/examples/getUserPhoto.js:
--------------------------------------------------------------------------------
1 | telegramApi.getUserPhoto('base64', 'small').then(function(base64) {
2 | $('img#avatar').attr('src', base64);
3 | });
4 |
--------------------------------------------------------------------------------
/docs/examples/invokeApi.js:
--------------------------------------------------------------------------------
1 | telegramApi.invokeApi('messages.getDialogs', {
2 | offset_peer: {_: 'inputPeerEmpty'},
3 | offset_date: 0,
4 | limit: 20
5 | }).then(function(dialogResult) {
6 | /* Do something */
7 | });
8 |
--------------------------------------------------------------------------------
/docs/examples/joinChat.js:
--------------------------------------------------------------------------------
1 | telegramApi.joinChat('https://telegram.me/joinchat/some-hash').then(function(updates) {
2 | // Do something
3 | });
4 |
--------------------------------------------------------------------------------
/docs/examples/logOut.js:
--------------------------------------------------------------------------------
1 | telegramApi.logOut().then(function() {
2 | setTimeout(function() {
3 | // Do something after logouts
4 | // Use setTimeout (It will be fixed)
5 | }, 1500);
6 | });
7 |
--------------------------------------------------------------------------------
/docs/examples/sendCode.js:
--------------------------------------------------------------------------------
1 | telegramApi.sendCode('some_phone_number').then(function(sent_code) {
2 | if (!sent_code.phone_registered) {
3 | // New user
4 | }
5 |
6 | // phone_code_hash will need to sign in or sign up
7 | window.phone_code_hash = sent_code.phone_code_hash;
8 | });
9 |
--------------------------------------------------------------------------------
/docs/examples/sendFile.js:
--------------------------------------------------------------------------------
1 | telegramApi.sendFile({
2 | id: 123456789,
3 | type: 'user',
4 | file: $('input[type=file]').val(),
5 | caption: 'This is file'
6 | }).then(function(updates) {
7 | // Do something
8 | });
9 |
--------------------------------------------------------------------------------
/docs/examples/sendMessage.js:
--------------------------------------------------------------------------------
1 | telegramApi.sendMessage(9999999999, 'Hey man!').then(function(updates) {
2 | // Do something
3 | });
4 |
--------------------------------------------------------------------------------
/docs/examples/sendSms.js:
--------------------------------------------------------------------------------
1 | telegramApi.sendSms('some_phone_number', window.phone_code_hash).then(function() {
2 | // Do something
3 | });
4 |
--------------------------------------------------------------------------------
/docs/examples/setConfig.js:
--------------------------------------------------------------------------------
1 | telegramApi.setConfig({
2 | app: {
3 | id: 0, /* App ID */
4 | hash: 'qwertyasdfghzxcvbnqwertyasd', /* App hash */
5 | version: '0.0.0' /* App version */
6 | },
7 | server: {
8 | test: [
9 | {
10 | id: 2, /* DC ID */
11 | host: '0.0.0.0',
12 | port: 443
13 | }
14 | ],
15 | production: [
16 | {
17 | id: 2, /* DC ID */
18 | host: '0.0.0.0',
19 | port: 123
20 | }
21 | ]
22 | }
23 | });
24 |
--------------------------------------------------------------------------------
/docs/examples/signIn.js:
--------------------------------------------------------------------------------
1 | telegramApi.signIn('some_phone_number', window.phone_code_hash, '000000').then(function() {
2 | // Sign in complete
3 | delete window.phone_code_hash;
4 | }, function(err) {
5 | switch (err.type) {
6 | case 'PHONE_CODE_INVALID':
7 | // alert "Phone code invalid"
8 | break;
9 | case 'PHONE_NUMBER_UNOCCUPIED':
10 | // User not registered, you should use signUp method
11 | break;
12 | }
13 | });
14 |
--------------------------------------------------------------------------------
/docs/examples/signUp.js:
--------------------------------------------------------------------------------
1 | telegramApi.signUp('some_phone_number', window.phone_code_hash, '000000', 'John', 'Doe').then(function() {
2 | // Sign up complete
3 | delete window.phone_code_hash;
4 | });
5 |
--------------------------------------------------------------------------------
/docs/examples/startBot.js:
--------------------------------------------------------------------------------
1 | telegramApi.startBot('exampleBot').then(function(updates) {
2 | // Was invoked telegramApi.sendMessage(bot.id, '/start');
3 | });
4 |
--------------------------------------------------------------------------------
/docs/jsdoc-options.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": "src/telegramApi.js",
3 | "param-list-format": "table"
4 | }
5 |
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Test Telegram App
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Auth panel
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
Info panel
35 |
36 |
37 |
38 | ID |
39 | |
40 |
41 |
42 |
43 |
44 | Photo |
45 | ![]() |
46 |
47 |
48 | First Name |
49 | |
50 |
51 |
52 | Last Name |
53 | |
54 |
55 |
56 | Username |
57 | |
58 |
59 |
60 | Phone |
61 | |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
76 |
79 |
80 |
81 |
82 |
Operations
83 |
84 |
85 |
Success
86 |
87 | -
88 | {{item._}}
89 | A
90 | C
91 |
92 |
93 |
94 |
95 |
Failed
96 |
97 | -
98 | {{item.description}}
99 | A
100 | C
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
Logs
110 |
111 | -
112 | {{log._}}
113 | A
114 | C
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
--------------------------------------------------------------------------------
/example/script.js:
--------------------------------------------------------------------------------
1 | telegramApi.setConfig({
2 | app: {
3 | id: 24939,
4 | hash: 'cf2f9913563b63810ca02d77d5d44f92',
5 | version: telegramApi.VERSION
6 | },
7 | server: {
8 | test: [
9 | {
10 | id: 2,
11 | host: '149.154.167.40',
12 | port: '443'
13 | }
14 | ],
15 | production: [
16 | {
17 | id: 2,
18 | host: '149.154.167.50',
19 | port: '443'
20 | }
21 | ]
22 | }
23 | });
24 |
25 | angular.module('myApp', [])
26 | .controller('mainCtrl', function ($scope) {
27 | angular.extend($scope, {
28 | update: function () {
29 | if ($scope._timeout) {
30 | return;
31 | }
32 |
33 | $scope._timeout = setTimeout(function () {
34 | delete $scope._timeout;
35 | $scope.$apply();
36 | }, 0);
37 | },
38 | visible: {
39 | auth: false,
40 | info: false
41 | },
42 | auth: {},
43 | info: {},
44 | logs: [],
45 | success: [],
46 | failed: [],
47 | methods: [],
48 | json: function (obj, indent) {
49 | return JSON.stringify(obj, null, indent ? 4 : 0);
50 | },
51 | showLog: function (log, type) {
52 | switch (type) {
53 | case 'console':
54 | console.log(log);
55 | break;
56 | case 'alert':
57 | alert(this.json(log, true));
58 | break;
59 | }
60 | },
61 | invokeMethod: function (method, params, onSuccess, onError) {
62 | telegramApi[method].apply(telegramApi, params).then(function (result) {
63 | $scope.success.push(result);
64 | $scope.update();
65 | onSuccess && onSuccess(result);
66 | }, function (err) {
67 | $scope.failed.push(err);
68 | $scope.update();
69 | onError && onError(err);
70 | });
71 | }
72 | });
73 |
74 | /* Auth methods */
75 | $scope.auth.sendCode = function () {
76 | $scope.invokeMethod('sendCode', [$scope.auth.phone], function (sent_code) {
77 | $scope.phone_code_hash = sent_code.phone_code_hash;
78 | });
79 | };
80 |
81 | $scope.auth.signIn = function () {
82 | $scope.invokeMethod('signIn', [$scope.auth.phone, $scope.phone_code_hash, $scope.auth.code], function () {
83 | setTimeout(function () {
84 | window.location.reload();
85 | }, 1000);
86 | });
87 | };
88 |
89 | /* Other methods */
90 | $scope.info.logOut = function () {
91 | telegramApi.logOut().then(function () {
92 | // TODO: Без setTimeout
93 | setTimeout(function () {
94 | window.location.reload();
95 | }, 1500);
96 | });
97 | };
98 |
99 | $scope.info.checkPhone = function (phone) {
100 | $scope.invokeMethod('checkPhone', [phone]);
101 | };
102 |
103 | for (var key in telegramApi) {
104 | if (telegramApi.hasOwnProperty(key) && typeof telegramApi[key] == 'function') {
105 | $scope.methods.push(key);
106 | }
107 | }
108 |
109 | /* Initialize */
110 | telegramApi.getUserInfo().then(function (user) {
111 | if (!user.id) {
112 | $scope.visible.auth = true;
113 | $scope.update();
114 | } else {
115 | angular.extend($scope.info, user);
116 | $scope.visible.info = true;
117 |
118 | telegramApi.getUserPhoto('base64', 'small').then(function (base64) {
119 | $scope.info.photoBase64 = base64;
120 | $scope.update();
121 | });
122 | }
123 | });
124 |
125 | telegramApi.subscribe('Test', function (message) {
126 | $scope.logs.push(message);
127 | $scope.update();
128 | });
129 | });
--------------------------------------------------------------------------------
/example/style.css:
--------------------------------------------------------------------------------
1 | .list-group, .dropdown-menu {
2 | max-height: 300px;
3 | overflow-y: scroll;
4 | }
5 |
6 | .badge {
7 | cursor: pointer;
8 | }
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var $ = require('gulp-load-plugins')();
3 | var version = require('./package.json').version;
4 | var about = require('fs')
5 | .readFileSync('./.files/about.txt', 'utf8')
6 | .replace('{VERSION}', version);
7 |
8 | gulp.task('clean', function () {
9 | return gulp.src([
10 | 'example/js',
11 | 'dist/'
12 | ]).pipe($.clean({force: true}));
13 | });
14 |
15 | gulp.task('js', function () {
16 | return gulp.src([
17 | 'node_modules/long/dist/long.min.js',
18 | 'node_modules/zlibjs/bin/gunzip.min.js',
19 | 'node_modules/rusha/rusha.min.js',
20 | 'node_modules/ioc-js/dist/ioc-js.min.js',
21 |
22 | 'src/vendor/**/*.js',
23 | 'src/js/**/*.js',
24 |
25 | 'src/telegramApi.js',
26 | 'src/IoC.js'
27 | ])
28 | .pipe($.concat('telegramApi.js'))
29 | .pipe($.replace(/<%TELEGRAM-API-VERSION%>/g, version))
30 | .pipe($.wrapper({
31 | header: about + '(function(){\n',
32 | footer: '\n})();'
33 | }))
34 | .pipe(gulp.dest('dist'))
35 |
36 | .pipe($.rename({suffix: '.min'}))
37 | .pipe($.uglify())
38 | .pipe($.wrapper({header: about}))
39 | .pipe(gulp.dest('dist'));
40 | });
41 |
42 | gulp.task('copy', function () {
43 | gulp.src('dist/**/*.js')
44 | .pipe(gulp.dest('example/js'));
45 | });
46 |
47 | gulp.task('server', function () {
48 | gulp.src('example')
49 | .pipe($.webserver({open: true}));
50 | });
51 |
52 | gulp.task('build', ['clean', 'js']);
53 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "telegram-api-js",
3 | "version": "1.2.9",
4 | "description": "JavaScript library for using Telegram API.",
5 | "repository": {
6 | "type": "git",
7 | "url": "https://github.com/sunriselink/TelegramApi.git"
8 | },
9 | "author": {
10 | "name": "Infinnity Solutions",
11 | "email": "info@infinnity.ru"
12 | },
13 | "contributors": [
14 | {
15 | "name": "Maxim Sadofyev",
16 | "email": "m.sadofyev@infinnity.ru"
17 | },
18 | {
19 | "name": "Dinara Zaripova",
20 | "email": "d.zaripova@infinnity.ru"
21 | }
22 | ],
23 | "license": "GPL-3.0",
24 | "keywords": [
25 | "telegram",
26 | "telegramapi",
27 | "webogram",
28 | "infinnity",
29 | "infinnitysolutions"
30 | ],
31 | "scripts": {
32 | "build": "gulp build",
33 | "build-lib": "npm i && npm run build",
34 | "build-doc": "node docs/build.js",
35 | "example": "npm run build && gulp copy",
36 | "start": "npm run example && gulp server"
37 | },
38 | "devDependencies": {
39 | "gulp": "^3.9.1",
40 | "gulp-clean": "^0.3.2",
41 | "gulp-concat": "^2.6.0",
42 | "gulp-load-plugins": "^1.3.0",
43 | "gulp-rename": "^1.2.2",
44 | "gulp-replace": "^0.5.4",
45 | "gulp-uglify": "^2.0.0",
46 | "gulp-webserver": "^0.9.1",
47 | "gulp-wrapper": "^1.0.0",
48 | "ioc-js": "0.0.4",
49 | "jsdoc-to-markdown": "^2.0.1",
50 | "long": "3.2.0",
51 | "rusha": "0.8.4",
52 | "zlibjs": "0.2.0"
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/IoC.js:
--------------------------------------------------------------------------------
1 | // Create container
2 | var builder = new ContainerModule();
3 |
4 | // Register App modules
5 | builder.register('AppChatsManager', AppChatsManagerModule);
6 | builder.register('AppPeersManager', AppPeersManagerModule);
7 | builder.register('AppProfileManager', AppProfileManagerModule);
8 | builder.register('AppUsersManager', AppUsersManagerModule);
9 |
10 | // Register Mtp modules
11 | builder.register('MtpApiFileManager', MtpApiFileManagerModule);
12 | builder.register('MtpApiManager', MtpApiManagerModule);
13 | builder.register('MtpAuthorizer', MtpAuthorizerModule);
14 | builder.register('MtpDcConfigurator', MtpDcConfiguratorModule);
15 | builder.register('MtpNetworkerFactory', MtpNetworkerFactoryModule);
16 | builder.register('MtpRsaKeysManager', MtpRsaKeysManagerModule);
17 | builder.register('MtpSecureRandom', MtpSecureRandomModule);
18 | builder.register('MtpSingleInstanceService', MtpSingleInstanceServiceModule);
19 | builder.register('MtpTimeManager', MtpTimeManagerModule);
20 |
21 | // Register Angular modules
22 | builder.register('$http', $httpModule);
23 | builder.register('$interval', $intervalModule);
24 | builder.register('$q', $qModule);
25 | builder.register('$rootScope', $rootScopeModule);
26 | builder.register('$timeout', $timeoutModule);
27 |
28 | // Register other modules
29 | builder.register('CryptoWorker', CryptoWorkerModule);
30 | builder.register('IdleManager', IdleManagerModule);
31 | builder.register('qSync', qSyncModule);
32 | builder.register('Storage', StorageModule);
33 | builder.register('TelegramMeWebService', TelegramMeWebServiceModule);
34 | builder.register('jQuery', jQueryModule);
35 | builder.register('FileSaver', FileSaverModule);
36 |
37 | // Register TelegramApi module
38 | builder.register('TelegramApi', TelegramApiModule);
39 |
40 | // Initialize modules
41 | builder.init();
42 |
43 | // Resolve TelegramApi
44 | window.telegramApi = builder.resolve('TelegramApi');
45 |
--------------------------------------------------------------------------------
/src/js/App/AppChatsManager.js:
--------------------------------------------------------------------------------
1 | function AppChatsManagerModule() {
2 | var chats = {},
3 | channelAccess = {};
4 |
5 | function saveApiChats(apiChats) {
6 | forEach(apiChats, saveApiChat);
7 | }
8 |
9 | function saveApiChat(apiChat) {
10 | if (!isObject(apiChat)) {
11 | return;
12 | }
13 |
14 | apiChat.num = (Math.abs(apiChat.id >> 1) % 8) + 1;
15 |
16 | if (apiChat.pFlags === undefined) {
17 | apiChat.pFlags = {};
18 | }
19 |
20 | if (chats[apiChat.id] === undefined) {
21 | chats[apiChat.id] = apiChat;
22 | } else {
23 | safeReplaceObject(chats[apiChat.id], apiChat);
24 | }
25 | }
26 |
27 | function getChat(id) {
28 | return chats[id] || {id: id, deleted: true, access_hash: channelAccess[id]};
29 | }
30 |
31 | function isChannel(id) {
32 | var chat = chats[id];
33 |
34 | return chat && (chat._ == 'channel' || chat._ == 'channelForbidden') || channelAccess[id];
35 | }
36 |
37 | function getChatInput(id) {
38 | return id || 0;
39 | }
40 |
41 | function getChannelInput(id) {
42 | if (!id) {
43 | return {_: 'inputChannelEmpty'};
44 | }
45 | return {
46 | _: 'inputChannel',
47 | channel_id: id,
48 | access_hash: getChat(id).access_hash || channelAccess[id] || 0
49 | }
50 | }
51 |
52 | return {
53 | saveApiChats: saveApiChats,
54 | saveApiChat: saveApiChat,
55 | getChat: getChat,
56 | isChannel: isChannel,
57 | getChatInput: getChatInput,
58 | getChannelInput: getChannelInput
59 | };
60 | }
61 |
62 | AppChatsManagerModule.dependencies = [];
63 |
--------------------------------------------------------------------------------
/src/js/App/AppPeersManager.js:
--------------------------------------------------------------------------------
1 | function AppPeersManagerModule(AppChatsManager, AppUsersManager) {
2 | function getInputPeerByID(peerID) {
3 | if (!peerID) {
4 | return {_: 'inputPeerEmpty'};
5 | }
6 | if (peerID < 0) {
7 | var chatID = -peerID;
8 | if (!AppChatsManager.isChannel(chatID)) {
9 | return {
10 | _: 'inputPeerChat',
11 | chat_id: chatID
12 | };
13 | } else {
14 | return {
15 | _: 'inputPeerChannel',
16 | channel_id: chatID,
17 | access_hash: AppChatsManager.getChat(chatID).access_hash || 0
18 | }
19 | }
20 | }
21 | return {
22 | _: 'inputPeerUser',
23 | user_id: peerID,
24 | access_hash: AppUsersManager.getUser(peerID).access_hash || 0
25 | };
26 | }
27 |
28 | function getPeerID(peerString) {
29 | if (isObject(peerString)) {
30 | return peerString.user_id
31 | ? peerString.user_id
32 | : -(peerString.channel_id || peerString.chat_id);
33 | }
34 | var isUser = peerString.charAt(0) == 'u',
35 | peerParams = peerString.substr(1).split('_');
36 |
37 | return isUser ? peerParams[0] : -peerParams[0] || 0;
38 | }
39 |
40 | function getPeer(peerID) {
41 | return peerID > 0
42 | ? AppUsersManager.getUser(peerID)
43 | : AppChatsManager.getChat(-peerID);
44 | }
45 |
46 | function isChannel(peerID) {
47 | return (peerID < 0) && AppChatsManager.isChannel(-peerID);
48 | }
49 |
50 | return {
51 | getInputPeerByID: getInputPeerByID,
52 | getPeerID: getPeerID,
53 | getPeer: getPeer,
54 | isChannel: isChannel
55 | };
56 | }
57 |
58 | AppPeersManagerModule.dependencies = [
59 | 'AppChatsManager',
60 | 'AppUsersManager'
61 | ];
62 |
--------------------------------------------------------------------------------
/src/js/App/AppProfileManager.js:
--------------------------------------------------------------------------------
1 | function AppProfileManagerModule(AppChatsManager, AppUsersManager, MtpApiManager, $q) {
2 | var chatsFull = {};
3 | var chatFullPromises = {};
4 |
5 | function getChatFull(id) {
6 | if (AppChatsManager.isChannel(id)) {
7 | return getChannelFull(id);
8 | }
9 | if (chatsFull[id] !== undefined) {
10 | var chat = AppChatsManager.getChat(id);
11 | if (chat.version == chatsFull[id].participants.version ||
12 | chat.pFlags.left) {
13 | return $q.when(chatsFull[id]);
14 | }
15 | }
16 | if (chatFullPromises[id] !== undefined) {
17 | return chatFullPromises[id];
18 | }
19 | console.trace(dT(), 'Get chat full', id, AppChatsManager.getChat(id));
20 | return chatFullPromises[id] = MtpApiManager.invokeApi('messages.getFullChat', {
21 | chat_id: AppChatsManager.getChatInput(id)
22 | }).then(function (result) {
23 | AppChatsManager.saveApiChats(result.chats);
24 | AppUsersManager.saveApiUsers(result.users);
25 | var fullChat = result.full_chat;
26 | delete chatFullPromises[id];
27 | chatsFull[id] = fullChat;
28 |
29 | return fullChat;
30 | });
31 | }
32 |
33 | function getChatInviteLink(id, force) {
34 | return getChatFull(id).then(function (chatFull) {
35 | if (!force &&
36 | chatFull.exported_invite &&
37 | chatFull.exported_invite._ == 'chatInviteExported') {
38 | return chatFull.exported_invite.link;
39 | }
40 | var promise;
41 | if (AppChatsManager.isChannel(id)) {
42 | promise = MtpApiManager.invokeApi('channels.exportInvite', {
43 | channel: AppChatsManager.getChannelInput(id)
44 | });
45 | } else {
46 | promise = MtpApiManager.invokeApi('messages.exportChatInvite', {
47 | chat_id: AppChatsManager.getChatInput(id)
48 | });
49 | }
50 | return promise.then(function (exportedInvite) {
51 | if (chatsFull[id] !== undefined) {
52 | chatsFull[id].exported_invite = exportedInvite;
53 | }
54 | return exportedInvite.link;
55 | });
56 | });
57 | }
58 |
59 | function getChannelParticipants(id) {
60 | return MtpApiManager.invokeApi('channels.getParticipants', {
61 | channel: AppChatsManager.getChannelInput(id),
62 | filter: {_: 'channelParticipantsRecent'},
63 | offset: 0,
64 | limit: 200
65 | }).then(function (result) {
66 | AppUsersManager.saveApiUsers(result.users);
67 | var participants = result.participants;
68 |
69 | var chat = AppChatsManager.getChat(id);
70 | if (!chat.pFlags.kicked && !chat.pFlags.left) {
71 | var myID = AppUsersManager.getSelf().id;
72 | var myIndex = false;
73 | var myParticipant;
74 | for (var i = 0, len = participants.length; i < len; i++) {
75 | if (participants[i].user_id == myID) {
76 | myIndex = i;
77 | break;
78 | }
79 | }
80 | if (myIndex !== false) {
81 | myParticipant = participants[i];
82 | participants.splice(i, 1);
83 | } else {
84 | myParticipant = {_: 'channelParticipantSelf', user_id: myID};
85 | }
86 | participants.unshift(myParticipant);
87 | }
88 |
89 | return participants;
90 | });
91 | }
92 |
93 | function getChannelFull(id, force) {
94 | if (chatsFull[id] !== undefined && !force) {
95 | return $q.when(chatsFull[id]);
96 | }
97 | if (chatFullPromises[id] !== undefined) {
98 | return chatFullPromises[id];
99 | }
100 |
101 | return chatFullPromises[id] = MtpApiManager.invokeApi('channels.getFullChannel', {
102 | channel: AppChatsManager.getChannelInput(id)
103 | }).then(function (result) {
104 | AppChatsManager.saveApiChats(result.chats);
105 | AppUsersManager.saveApiUsers(result.users);
106 | var fullChannel = result.full_chat;
107 | var chat = AppChatsManager.getChat(id);
108 | var participantsPromise;
109 | if (fullChannel.flags & 8) {
110 | participantsPromise = getChannelParticipants(id).then(function (participants) {
111 | delete chatFullPromises[id];
112 | fullChannel.participants = {
113 | _: 'channelParticipants',
114 | participants: participants
115 | };
116 | }, function (error) {
117 | error.handled = true;
118 | });
119 | } else {
120 | participantsPromise = $q.when();
121 | }
122 | return participantsPromise.then(function () {
123 | delete chatFullPromises[id];
124 | chatsFull[id] = fullChannel;
125 |
126 | return fullChannel;
127 | });
128 | }, function (error) {
129 | return $q.reject(error);
130 | });
131 | }
132 |
133 | return {
134 | getChatInviteLink: getChatInviteLink
135 | };
136 | }
137 |
138 | AppProfileManagerModule.dependencies = [
139 | 'AppChatsManager',
140 | 'AppUsersManager',
141 | 'MtpApiManager',
142 | '$q'
143 | ];
144 |
--------------------------------------------------------------------------------
/src/js/App/AppUsersManager.js:
--------------------------------------------------------------------------------
1 | function AppUsersManagerModule(Storage, MtpApiManager) {
2 | var users = {},
3 | userAccess = {},
4 | myID,
5 | serverTimeOffset = 0;
6 |
7 | Storage.get('server_time_offset').then(function (to) {
8 | if (to) {
9 | serverTimeOffset = to;
10 | }
11 | });
12 |
13 | MtpApiManager.getUserID().then(function (id) {
14 | myID = id;
15 | });
16 |
17 | function saveApiUsers(apiUsers) {
18 | forEach(apiUsers, saveApiUser);
19 | }
20 |
21 | function saveApiUser(apiUser, noReplace) {
22 | if (!isObject(apiUser) || noReplace && isObject(users[apiUser.id]) && users[apiUser.id].first_name) {
23 | return;
24 | }
25 |
26 | var userID = apiUser.id;
27 |
28 | apiUser.num = (Math.abs(userID) % 8) + 1;
29 |
30 | if (apiUser.pFlags === undefined) {
31 | apiUser.pFlags = {};
32 | }
33 |
34 | if (apiUser.status) {
35 | if (apiUser.status.expires) {
36 | apiUser.status.expires -= serverTimeOffset;
37 | }
38 | if (apiUser.status.was_online) {
39 | apiUser.status.was_online -= serverTimeOffset;
40 | }
41 | }
42 | if (apiUser.pFlags.bot) {
43 | apiUser.sortStatus = -1;
44 | } else {
45 | apiUser.sortStatus = getUserStatusForSort(apiUser.status);
46 | }
47 |
48 | var result = users[userID];
49 |
50 | if (result === undefined) {
51 | result = users[userID] = apiUser;
52 | } else {
53 | safeReplaceObject(result, apiUser);
54 | }
55 | }
56 |
57 | function getUserStatusForSort(status) {
58 | if (status) {
59 | var expires = status.expires || status.was_online;
60 | if (expires) {
61 | return expires;
62 | }
63 | var timeNow = tsNow(true);
64 | switch (status._) {
65 | case 'userStatusRecently':
66 | return timeNow - 86400 * 3;
67 | case 'userStatusLastWeek':
68 | return timeNow - 86400 * 7;
69 | case 'userStatusLastMonth':
70 | return timeNow - 86400 * 30;
71 | }
72 | }
73 |
74 | return 0;
75 | }
76 |
77 | function getUser(id) {
78 | if (isObject(id)) {
79 | return id;
80 | }
81 | return users[id] || {id: id, deleted: true, num: 1, access_hash: userAccess[id]};
82 | }
83 |
84 | function getSelf() {
85 | return getUser(myID);
86 | }
87 |
88 | function getUserInput(id) {
89 | var user = getUser(id);
90 | if (user.pFlags.self) {
91 | return {_: 'inputUserSelf'};
92 | }
93 | return {
94 | _: 'inputUser',
95 | user_id: id,
96 | access_hash: user.access_hash || 0
97 | };
98 | }
99 |
100 | return {
101 | saveApiUsers: saveApiUsers,
102 | saveApiUser: saveApiUser,
103 | getUser: getUser,
104 | getSelf: getSelf,
105 | getUserInput: getUserInput
106 | };
107 | }
108 |
109 | AppUsersManagerModule.dependencies = [
110 | 'Storage',
111 | 'MtpApiManager'
112 | ];
113 |
--------------------------------------------------------------------------------
/src/js/Etc/CryptoWorker.js:
--------------------------------------------------------------------------------
1 | function CryptoWorkerModule($timeout) {
2 | return {
3 | sha1Hash: function (bytes) {
4 | return $timeout(function () {
5 | return sha1HashSync(bytes);
6 | });
7 | },
8 | sha256Hash: function (bytes) {
9 | return $timeout(function () {
10 | return sha256HashSync(bytes);
11 | });
12 | },
13 | aesEncrypt: function (bytes, keyBytes, ivBytes) {
14 | return $timeout(function () {
15 | return convertToArrayBuffer(aesEncryptSync(bytes, keyBytes, ivBytes));
16 | });
17 | },
18 | aesDecrypt: function (encryptedBytes, keyBytes, ivBytes) {
19 | return $timeout(function () {
20 | return convertToArrayBuffer(aesDecryptSync(encryptedBytes, keyBytes, ivBytes));
21 | });
22 | },
23 | factorize: function (bytes) {
24 | bytes = convertToByteArray(bytes);
25 |
26 | return $timeout(function () {
27 | return pqPrimeFactorization(bytes);
28 | });
29 | },
30 | modPow: function (x, y, m) {
31 | return $timeout(function () {
32 | return bytesModPow(x, y, m);
33 | });
34 | }
35 | };
36 | }
37 |
38 | CryptoWorkerModule.dependencies = [
39 | '$timeout'
40 | ];
41 |
--------------------------------------------------------------------------------
/src/js/Etc/FileSaver.js:
--------------------------------------------------------------------------------
1 | function FileSaverModule($timeout) {
2 | function save(bytes, fileName) {
3 | // TODO: Improve
4 | var a = document.createElement('a');
5 | var blob = new Blob(bytes, {type: 'octet/stream'});
6 |
7 | if (window.navigator && window.navigator.msSaveBlob) {
8 | window.navigator.msSaveBlob(blob, fileName);
9 | return;
10 | }
11 |
12 | document.body.appendChild(a);
13 |
14 | a.style = 'display: none';
15 | a.href = window.URL.createObjectURL(blob);
16 | a.download = fileName;
17 | a.click();
18 |
19 | $timeout(function() {
20 | window.URL.revokeObjectURL(a.href);
21 | a.remove();
22 | }, 100);
23 | }
24 |
25 | return {
26 | save: save
27 | };
28 | }
29 |
30 | FileSaverModule.dependencies = [
31 | '$timeout'
32 | ];
33 |
--------------------------------------------------------------------------------
/src/js/Etc/Helper.js:
--------------------------------------------------------------------------------
1 | function forEach(obj, iterator, context) {
2 | if (!obj) {
3 | return;
4 | }
5 |
6 | if (isArray(obj)) {
7 | if (obj.forEach) {
8 | obj.forEach(iterator, context, obj);
9 | } else {
10 | for (var i = 0; i < obj.length; i++) {
11 | iterator.call(context, obj[i], i, obj);
12 | }
13 | }
14 | } else if (isObject(obj)) {
15 | for (var key in obj) {
16 | iterator.call(context, obj[key], key, obj);
17 | }
18 | }
19 | }
20 |
21 | function isObject(value) {
22 | return value !== null && typeof value === 'object';
23 | }
24 |
25 | function isString(value) {
26 | return typeof value == 'string';
27 | }
28 |
29 | function isArray(value) {
30 | return Array.isArray(value);
31 | }
32 |
33 | function isFunction(value) {
34 | return typeof value == 'function';
35 | }
36 |
37 | function extend() {
38 | var objects = toArray(arguments);
39 | var obj = objects[0];
40 |
41 | for (var i = 1; i < objects.length; i++) {
42 | for (var key in objects[i]) {
43 | obj[key] = objects[i][key];
44 | }
45 | }
46 |
47 | return obj;
48 | }
49 |
50 | function map(array, iterator) {
51 | var result = [];
52 |
53 | forEach(array, function (obj) {
54 | result.push(iterator(obj));
55 | });
56 |
57 | return result;
58 | }
59 |
60 | function min(array) {
61 | var min = array[0];
62 |
63 | forEach(array, function (obj) {
64 | if (obj < min) {
65 | min = obj;
66 | }
67 | });
68 |
69 | return min;
70 | }
71 | function toArray(obj) {
72 | return Array.prototype.slice.call(obj);
73 | }
74 |
75 | function noop() {
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/src/js/Etc/IdleManager.js:
--------------------------------------------------------------------------------
1 | function IdleManagerModule($rootScope, $timeout, $) {
2 | $rootScope.idle = {isIDLE: false};
3 |
4 | var toPromise, started = false;
5 | var hidden = 'hidden';
6 | var visibilityChange = 'visibilitychange';
7 |
8 | if (typeof document.hidden !== 'undefined') {
9 | // default
10 | } else if (typeof document.mozHidden !== 'undefined') {
11 | hidden = 'mozHidden';
12 | visibilityChange = 'mozvisibilitychange';
13 | } else if (typeof document.msHidden !== 'undefined') {
14 | hidden = 'msHidden';
15 | visibilityChange = 'msvisibilitychange';
16 | } else if (typeof document.webkitHidden !== 'undefined') {
17 | hidden = 'webkitHidden';
18 | visibilityChange = 'webkitvisibilitychange';
19 | }
20 |
21 | return {
22 | start: start
23 | };
24 |
25 | function start() {
26 | if (!started) {
27 | started = true;
28 | $(window).on(visibilityChange + ' blur focus keydown mousedown touchstart', onEvent);
29 |
30 | setTimeout(function () {
31 | onEvent({type: 'blur'});
32 | }, 0);
33 | }
34 | }
35 |
36 | function onEvent(e) {
37 | // console.log('event', e.type);
38 | if (e.type == 'mousemove') {
39 | var e = e.originalEvent || e;
40 | if (e && e.movementX === 0 && e.movementY === 0) {
41 | return;
42 | }
43 | $(window).off('mousemove', onEvent);
44 | }
45 |
46 | var isIDLE = e.type == 'blur' || e.type == 'timeout' ? true : false;
47 | if (hidden && document[hidden]) {
48 | isIDLE = true;
49 | }
50 |
51 | $timeout.cancel(toPromise);
52 | if (!isIDLE) {
53 | // console.log('update timeout');
54 | toPromise = $timeout(function () {
55 | onEvent({type: 'timeout'});
56 | }, 30000);
57 | }
58 |
59 | if (isIDLE && e.type == 'timeout') {
60 | $(window).on('mousemove', onEvent);
61 | }
62 | }
63 | }
64 |
65 | IdleManagerModule.dependencies = [
66 | '$rootScope',
67 | '$timeout',
68 | 'jQuery'
69 | ];
70 |
--------------------------------------------------------------------------------
/src/js/Etc/Storage.js:
--------------------------------------------------------------------------------
1 | function StorageModule($q) {
2 | var methods = {};
3 |
4 | forEach(['get', 'set', 'remove'], function (methodName) {
5 | methods[methodName] = function () {
6 | var deferred = $q.defer(),
7 | args = toArray(arguments);
8 |
9 | args.push(function (result) {
10 | deferred.resolve(result);
11 | });
12 |
13 | ConfigStorage[methodName].apply(ConfigStorage, args);
14 |
15 | return deferred.promise;
16 | };
17 | });
18 |
19 | return methods;
20 | }
21 |
22 | StorageModule.dependencies = [
23 | '$q'
24 | ];
25 |
--------------------------------------------------------------------------------
/src/js/Etc/TelegramMeWebService.js:
--------------------------------------------------------------------------------
1 | function TelegramMeWebServiceModule(Storage, $) {
2 | var disabled = location.protocol != 'http:' && location.protocol != 'https:';
3 |
4 | function sendAsyncRequest(canRedirect) {
5 | if (disabled) {
6 | return false;
7 | }
8 |
9 | Storage.get('tgme_sync').then(function (curValue) {
10 | var ts = tsNow(true);
11 | if (canRedirect &&
12 | curValue &&
13 | curValue.canRedirect == canRedirect &&
14 | curValue.ts + 86400 > ts) {
15 | return false;
16 | }
17 | Storage.set({tgme_sync: {canRedirect: canRedirect, ts: ts}});
18 |
19 | var script = $('