1 /*
2 This file is part of telegram-cli.
3
4 Telegram-cli is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 Telegram-cli is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this telegram-cli. If not, see <http://www.gnu.org/licenses/>.
16
17 Copyright Vitaly Valtman 2013-2015
18 Copyright Vincent Castellano 2015
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #ifdef USE_PYTHON
26 #include "python-tg.h"
27
28 #include <string.h>
29 #include <stdlib.h>
30 #include <libgen.h>
31
32 #include <Python.h>
33 #include "bytesobject.h"
34
35 // Python 2/3 compat macros
36 #if PY_MAJOR_VERSION >= 3
37 #define MOD_ERROR_VAL NULL
38 #define MOD_SUCCESS_VAL(val) val
39 #define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void)
40 #define MOD_DEF(ob, name, doc, methods) \
41 static struct PyModuleDef moduledef = { \
42 PyModuleDef_HEAD_INIT, name, doc, -1, methods, NULL, NULL, NULL, NULL,}; \
43 ob = PyModule_Create(&moduledef);
44 #define PyInt_FromLong PyLong_FromLong
45 #else
46 #define MOD_ERROR_VAL
47 #define MOD_SUCCESS_VAL(val)
48 #define MOD_INIT(name) void init##name(void)
49 #define MOD_DEF(ob, name, doc, methods) \
50 ob = Py_InitModule3(name, methods, doc);
51 #endif
52
53 #define TGL_PYTHON_CALLBACK(name, func) \
54 PyObject *set##func(PyObject *dummy, PyObject *args) { \
55 PyObject *result = NULL; \
56 PyObject *temp; \
57 if (PyArg_ParseTuple(args, "O:set_##name", &temp)) { \
58 if (!PyCallable_Check(temp)) { \
59 PyErr_SetString(PyExc_TypeError, "parameter must be callable");\
60 return NULL;\
61 }\
62 Py_XINCREF(temp);\
63 Py_XDECREF(func);\
64 func = temp;\
65 Py_INCREF(Py_None);\
66 result = Py_None;\
67 }\
68 return result;\
69 }
70
71
72 // Python Imports
73 #include "datetime.h"
74
75 // Custom Types
76 #include "python-types.h"
77
78
79 extern PyTypeObject tgl_PeerType;
80 extern PyTypeObject tgl_MsgType;
81
82 //#include "interface.h"
83 //#include "auto/constants.h"
84 #include <tgl/tgl.h>
85 #include <tgl/tgl-queries.h>
86 #include "interface.h"
87
88 #include <assert.h>
89 extern int verbosity;
90 extern struct tgl_state *TLS;
91
92
93 static int python_loaded;
94
95 // TGL Python Exceptions
96 PyObject *TglError;
97 PyObject *PeerError;
98 PyObject *MsgError;
99
100
101 // Python update function callables
102 PyObject *_py_binlog_end;
103 PyObject *_py_diff_end;
104 PyObject *_py_our_id;
105 PyObject *_py_new_msg;
106 PyObject *_py_list_msg;
107 PyObject *_py_secret_chat_update;
108 PyObject *_py_user_update;
109 PyObject *_py_chat_update;
110 PyObject *_py_on_loop;
111
112 PyObject* get_peer (tgl_peer_id_t id, tgl_peer_t *P);
113
py_add_string_field(PyObject * dict,char * name,const char * value)114 void py_add_string_field (PyObject* dict, char *name, const char *value) {
115 assert (PyDict_Check(dict));
116 assert (name && strlen (name));
117 if (!value || !strlen (value)) { return; }
118 PyObject *str = PyUnicode_FromString(value);
119
120 if(PyUnicode_Check(str))
121 PyDict_SetItemString (dict, name, str);
122 }
123
py_add_string_field_arr(PyObject * list,int num,const char * value)124 void py_add_string_field_arr (PyObject* list, int num, const char *value) {
125 assert(PyList_Check(list));
126 if (!value || !strlen (value)) { return; }
127 if(num >= 0)
128 PyList_SetItem (list, num, PyUnicode_FromString (value));
129 else // Append
130 PyList_Append (list, PyUnicode_FromString (value));
131 }
132
py_add_num_field(PyObject * dict,const char * name,double value)133 void py_add_num_field (PyObject* dict, const char *name, double value) {
134 assert (PyDict_Check(dict));
135 assert (name && strlen (name));
136 PyDict_SetItemString (dict, name, PyFloat_FromDouble(value));
137 }
138
get_tgl_peer_type(int x)139 PyObject* get_tgl_peer_type (int x) {
140 PyObject *type;
141
142 switch (x) {
143 case TGL_PEER_USER:
144 type = PyUnicode_FromString("user");
145 break;
146 case TGL_PEER_CHAT:
147 type = PyUnicode_FromString("chat");
148 break;
149 case TGL_PEER_ENCR_CHAT:
150 type = PyUnicode_FromString("encr_chat");
151 break;
152 default:
153 assert (0);
154 }
155
156 return type;
157 }
158
get_update_types(unsigned flags)159 PyObject* get_update_types (unsigned flags) {
160 PyObject* types;
161 types = PyList_New(0);
162 if(types == NULL)
163 assert(0); // TODO handle python exception
164
165 if (flags & TGL_UPDATE_CREATED) {
166 py_add_string_field_arr(types, -1, "created");
167 }
168 if (flags & TGL_UPDATE_DELETED) {
169 py_add_string_field_arr(types, -1, "deleted");
170 }
171 if (flags & TGL_UPDATE_PHONE) {
172 py_add_string_field_arr(types, -1, "phone");
173 }
174 if (flags & TGL_UPDATE_CONTACT) {
175 py_add_string_field_arr(types, -1, "contact");
176 }
177 if (flags & TGL_UPDATE_PHOTO) {
178 py_add_string_field_arr(types, -1, "photo");
179 }
180 if (flags & TGL_UPDATE_BLOCKED) {
181 py_add_string_field_arr(types, -1, "blocked");
182 }
183 if (flags & TGL_UPDATE_REAL_NAME) {
184 py_add_string_field_arr(types, -1, "real_name");
185 }
186 if (flags & TGL_UPDATE_NAME) {
187 py_add_string_field_arr(types, -1, "name");
188 }
189 if (flags & TGL_UPDATE_REQUESTED) {
190 py_add_string_field_arr(types, -1, "requested");
191 }
192 if (flags & TGL_UPDATE_WORKING) {
193 py_add_string_field_arr(types, -1, "working");
194 }
195 if (flags & TGL_UPDATE_FLAGS) {
196 py_add_string_field_arr(types, -1, "flags");
197 }
198 if (flags & TGL_UPDATE_TITLE) {
199 py_add_string_field_arr(types, -1, "title");
200 }
201 if (flags & TGL_UPDATE_ADMIN) {
202 py_add_string_field_arr(types, -1, "admin");
203 }
204 if (flags & TGL_UPDATE_MEMBERS) {
205 py_add_string_field_arr(types, -1, "members");
206 }
207 if (flags & TGL_UPDATE_ACCESS_HASH) {
208 py_add_string_field_arr(types, -1, "access_hash");
209 }
210 if (flags & TGL_UPDATE_USERNAME) {
211 py_add_string_field_arr(types, -1, "username");
212 }
213 return types;
214 }
215
get_peer(tgl_peer_id_t id,tgl_peer_t * P)216 PyObject* get_peer (tgl_peer_id_t id, tgl_peer_t *P) {
217 PyObject *peer;
218
219 peer = tgl_Peer_FromTglPeer(P);
220 return peer;
221 }
222
get_message(struct tgl_message * M)223 PyObject* get_message (struct tgl_message *M) {
224 assert (M);
225 PyObject *msg;
226
227 msg = tgl_Msg_FromTglMsg(M);
228 return msg;
229 }
230
py_binlog_end(void)231 void py_binlog_end (void) {
232 if (!python_loaded) { return; }
233
234 PyObject *arglist, *result;
235
236 if(_py_binlog_end == NULL) {
237 logprintf("Callback not set for on_binlog_end\n");
238 return;
239 }
240
241 arglist = Py_BuildValue("()");
242 result = PyEval_CallObject(_py_binlog_end, arglist);
243 Py_DECREF(arglist);
244
245 if(result == NULL)
246 PyErr_Print();
247 else if(PyUnicode_Check(result))
248 logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result)));
249
250 Py_XDECREF(result);
251 }
252
py_diff_end(void)253 void py_diff_end (void) {
254 if (!python_loaded) { return; }
255
256 PyObject *arglist, *result;
257
258 if(_py_diff_end == NULL) {
259 logprintf("Callback not set for on_diff_end\n");
260 return;
261 }
262
263 arglist = Py_BuildValue("()");
264 result = PyEval_CallObject(_py_diff_end, arglist);
265 Py_DECREF(arglist);
266 if(result == NULL)
267 PyErr_Print();
268 else if(PyUnicode_Check(result))
269 logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result)));
270
271 Py_XDECREF(result);
272 }
273
py_our_id(int id)274 void py_our_id (int id) {
275 if (!python_loaded) { return; }
276
277 PyObject *arglist, *result;
278
279 if(_py_our_id == NULL) {
280 logprintf("Callback not set for on_our_id\n");
281 return;
282 }
283
284 arglist = Py_BuildValue("(i)", id);
285 result = PyEval_CallObject(_py_our_id, arglist);
286 Py_DECREF(arglist);
287 if(result == NULL)
288 PyErr_Print();
289 else if(PyUnicode_Check(result))
290 logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result)));
291
292 Py_XDECREF(result);
293 }
294
py_new_msg(struct tgl_message * M)295 void py_new_msg (struct tgl_message *M) {
296 if (!python_loaded) { return; }
297 PyObject *msg;
298 PyObject *arglist, *result;
299
300 if(_py_new_msg == NULL) {
301 logprintf("Callback not set for on_new_msg\n");
302 return;
303 }
304
305 msg = get_message (M);
306
307 arglist = Py_BuildValue("(O)", msg);
308 result = PyEval_CallObject(_py_new_msg, arglist);
309 Py_DECREF(arglist);
310
311 if(result == NULL)
312 PyErr_Print();
313 else if(PyUnicode_Check(result))
314 logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result)));
315
316 Py_XDECREF(result);
317 }
318
py_list_msg(struct tgl_message * M)319 void py_list_msg (struct tgl_message *M) {
320 if (!python_loaded) { return; }
321 PyObject *msg;
322 PyObject *arglist, *result;
323
324 if(_py_list_msg == NULL) {
325 logprintf("Callback not set for on_msg_history");
326 return;
327 }
328
329 msg = get_message (M);
330
331 arglist = Py_BuildValue("(O)", msg);
332 result = PyEval_CallObject(_py_list_msg, arglist);
333 Py_DECREF(arglist);
334
335 if(result == NULL)
336 PyErr_Print();
337 else if(PyUnicode_Check(result))
338 logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result)));
339
340 Py_XDECREF(result);
341 }
342
py_secret_chat_update(struct tgl_secret_chat * C,unsigned flags)343 void py_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) {
344 if (!python_loaded) { return; }
345 PyObject *peer, *types;
346 PyObject *arglist, *result;
347
348 if(_py_secret_chat_update == NULL) {
349 logprintf("Callback not set for on_secret_chat_update\n");
350 return;
351 }
352
353 peer = get_peer (C->id, (void *)C);
354 types = get_update_types (flags);
355
356 arglist = Py_BuildValue("(OO)", peer, types);
357 result = PyEval_CallObject(_py_secret_chat_update, arglist);
358 Py_DECREF(arglist);
359
360 if(result == NULL)
361 PyErr_Print();
362 else if(PyUnicode_Check(result))
363 logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result)));
364
365 Py_XDECREF(result);
366 }
367
368
py_user_update(struct tgl_user * U,unsigned flags)369 void py_user_update (struct tgl_user *U, unsigned flags) {
370 if (!python_loaded) { return; }
371 PyObject *peer, *types;
372 PyObject *arglist, *result;
373
374 if(_py_user_update == NULL) {
375 logprintf("Callback not set for on_user_update\n");
376 return;
377 }
378
379 peer = get_peer (U->id, (void *)U);
380 types = get_update_types (flags);
381
382 arglist = Py_BuildValue("(OO)", peer, types);
383 result = PyEval_CallObject(_py_user_update, arglist);
384 Py_DECREF(arglist);
385
386 if(result == NULL)
387 PyErr_Print();
388 else if(PyUnicode_Check(result))
389 logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result)));
390
391 Py_XDECREF(result);
392 }
393
py_chat_update(struct tgl_chat * C,unsigned flags)394 void py_chat_update (struct tgl_chat *C, unsigned flags) {
395 if (!python_loaded) { return; }
396
397 PyObject *peer, *types;
398 PyObject *arglist, *result;
399
400 if(_py_chat_update == NULL) {
401 logprintf("Callback not set for on_chat_update\n");
402 return;
403 }
404
405 peer = get_peer (C->id, (void *)C);
406 types = get_update_types (flags);
407
408 arglist = Py_BuildValue("(OO)", peer, types);
409 result = PyEval_CallObject(_py_chat_update, arglist);
410 Py_DECREF(arglist);
411
412 if(result == NULL)
413 PyErr_Print();
414 else if(PyUnicode_Check(result))
415 logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result)));
416
417 Py_XDECREF(result);
418 }
419
py_on_loop()420 void py_on_loop () {
421 if (!python_loaded) { return; }
422
423 PyObject *result;
424
425 if(_py_on_loop == NULL) {
426 logprintf("Callback not set for on_loop\n");
427 return;
428 }
429
430 result = PyEval_CallObject(_py_on_loop, Py_BuildValue("()"));
431
432 if(result == NULL)
433 PyErr_Print();
434 else if(PyUnicode_Check(result))
435 logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result)));
436
437 Py_XDECREF(result);
438 }
439
440
441 ////extern tgl_peer_t *Peers[];
442 ////extern int peer_num;
443 //
444 #define MAX_PY_COMMANDS 1000
445 void *py_ptr[MAX_PY_COMMANDS];
446 static int pos;
447 //
448 //static inline tgl_peer_t *get_peer (const char *s) {
449 // return tgl_peer_get_by_name (TLS, s);
450 //}
451
452 enum py_query_type {
453 pq_contact_list,
454 pq_dialog_list,
455 pq_msg,
456 pq_send_typing,
457 pq_send_typing_abort,
458 pq_rename_chat,
459 pq_send_photo,
460 pq_chat_set_photo,
461 pq_set_profile_photo,
462 pq_set_profile_name,
463 pq_send_video,
464 pq_send_text,
465 pq_fwd,
466 pq_fwd_media,
467 pq_load_photo,
468 pq_load_video_thumb,
469 pq_load_video,
470 pq_chat_info,
471 pq_user_info,
472 pq_history,
473 pq_chat_add_user,
474 pq_chat_del_user,
475 pq_add_contact,
476 pq_del_contact,
477 pq_rename_contact,
478 pq_search,
479 pq_global_search,
480 pq_mark_read,
481 pq_create_secret_chat,
482 pq_create_group_chat,
483 pq_send_audio,
484 pq_send_document,
485 pq_send_file,
486 pq_load_audio,
487 pq_load_document,
488 pq_load_document_thumb,
489 pq_delete_msg,
490 pq_restore_msg,
491 pq_accept_secret_chat,
492 pq_send_contact,
493 pq_status_online,
494 pq_status_offline,
495 pq_send_location,
496 pq_extf,
497 pq_import_chat_link
498 };
499
py_empty_cb(struct tgl_state * TLSR,void * cb_extra,int success)500 void py_empty_cb (struct tgl_state *TLSR, void *cb_extra, int success) {
501 assert (TLSR == TLS);
502 PyObject *callable = cb_extra;
503 PyObject *arglist = NULL;
504 PyObject *result = NULL;
505
506 if(PyCallable_Check(callable)) {
507 arglist = Py_BuildValue("(O)", success ? Py_True : Py_False);
508 result = PyEval_CallObject(callable, arglist);
509 Py_DECREF(arglist);
510
511 if(result == NULL)
512 PyErr_Print();
513
514 Py_XDECREF(result);
515 }
516
517 Py_XDECREF(callable);
518 }
519
py_contact_list_cb(struct tgl_state * TLSR,void * cb_extra,int success,int num,struct tgl_user ** UL)520 void py_contact_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_user **UL) {
521 assert (TLSR == TLS);
522 PyObject *callable = cb_extra;
523 PyObject *arglist = NULL;
524 PyObject *peers = NULL;
525 PyObject *result = NULL;
526
527 if(PyCallable_Check(callable)) {
528 peers = PyList_New(0);
529 if (success) {
530 int i;
531 for (i = 0; i < num; i++) {
532 PyList_Append(peers, get_peer (UL[i]->id, (void *)UL[i]));
533 }
534 }
535
536 arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, peers);
537 result = PyEval_CallObject(callable, arglist);
538 Py_DECREF(arglist);
539
540 if(result == NULL)
541 PyErr_Print();
542
543 Py_XDECREF(result);
544 }
545
546 Py_XDECREF(callable);
547 }
548
py_dialog_list_cb(struct tgl_state * TLSR,void * cb_extra,int success,int num,tgl_peer_id_t peers[],tgl_message_id_t * msgs[],int unread[])549 void py_dialog_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, tgl_peer_id_t peers[], tgl_message_id_t *msgs[], int unread[]) {
550 assert (TLSR == TLS);
551 PyObject *callable = cb_extra;
552 PyObject *arglist = NULL;
553 PyObject *dialog_list = NULL;
554 PyObject *dialog = NULL;
555 PyObject *result = NULL;
556
557 if(PyCallable_Check(callable)) {
558 dialog_list = PyList_New(0);
559 if (success) {
560 int i;
561 for (i = 0; i < num; i++) {
562 dialog = PyDict_New();
563 PyDict_SetItemString(dialog, "peer", get_peer(peers[i], tgl_peer_get (TLS, peers[i])));
564
565 struct tgl_message *M = tgl_message_get (TLS, msgs[i]);
566 if (M && (M->flags & TGLMF_CREATED)) {
567 PyDict_SetItemString(dialog, "message", get_message(M));
568 }
569 PyDict_SetItemString(dialog, "unread", unread[i] ? Py_True : Py_False);
570
571 PyList_Append(dialog_list, dialog);
572 }
573 }
574
575 arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, dialog_list);
576 result = PyEval_CallObject(callable, arglist);
577 Py_DECREF(arglist);
578
579 if(result == NULL)
580 PyErr_Print();
581
582 Py_XDECREF(result);
583 }
584
585 Py_XDECREF(callable);
586 }
587
py_msg_cb(struct tgl_state * TLSR,void * cb_extra,int success,struct tgl_message * M)588 void py_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_message *M) {
589 assert (TLSR == TLS);
590 PyObject *callable = cb_extra;
591 PyObject *arglist = NULL;
592 PyObject *msg = NULL;
593 PyObject *result = NULL;
594
595 if(PyCallable_Check(callable)) {
596 if (success && M && (M->flags & TGLMF_CREATED)) {
597 msg = get_message(M);
598 } else {
599 Py_INCREF(Py_None);
600 msg = Py_None;
601 }
602
603 arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, msg);
604 result = PyEval_CallObject(callable, arglist);
605 Py_DECREF(arglist);
606
607 if(result == NULL)
608 PyErr_Print();
609
610 Py_XDECREF(result);
611 }
612
613 Py_XDECREF(callable);
614 }
615
py_msg_list_cb(struct tgl_state * TLSR,void * cb_extra,int success,int num,struct tgl_message * M[])616 void py_msg_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_message *M[]) {
617 assert (TLSR == TLS);
618 PyObject *callable = cb_extra;
619 PyObject *arglist = NULL;
620 PyObject *msgs = NULL;
621 PyObject *result = NULL;
622
623 if(PyCallable_Check(callable)) {
624 msgs = PyList_New(0);
625 if (success) {
626 int i;
627 for (i = 0; i < num; i++) {
628 PyList_Append(msgs, get_message (M[i]));
629 }
630 }
631
632 arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, msgs);
633 result = PyEval_CallObject(callable, arglist);
634 Py_DECREF(arglist);
635
636 if(result == NULL)
637 PyErr_Print();
638
639 Py_XDECREF(result);
640 }
641
642 Py_XDECREF(callable);
643 }
644
py_file_cb(struct tgl_state * TLSR,void * cb_extra,int success,const char * file_name)645 void py_file_cb (struct tgl_state *TLSR, void *cb_extra, int success, const char *file_name) {
646 assert (TLSR == TLS);
647 PyObject *callable = cb_extra;
648 PyObject *arglist = NULL;
649 PyObject *filename = NULL;
650 PyObject *result = NULL;
651
652 if(PyCallable_Check(callable)) {
653 if(success)
654 filename = PyUnicode_FromString(file_name);
655 else {
656 Py_INCREF(Py_None);
657 filename = Py_None;
658 }
659
660 arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, filename);
661 result = PyEval_CallObject(callable, arglist);
662 Py_DECREF(arglist);
663
664 if(result == NULL)
665 PyErr_Print();
666
667 Py_XDECREF(result);
668 }
669
670 Py_XDECREF(callable);
671 }
672
py_chat_cb(struct tgl_state * TLSR,void * cb_extra,int success,struct tgl_chat * C)673 void py_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_chat *C) {
674 assert (TLSR == TLS);
675 PyObject *callable = cb_extra;
676 PyObject *arglist = NULL;
677 PyObject *peer = NULL;
678 PyObject *result = NULL;
679
680 if(PyCallable_Check(callable)) {
681 if (success) {
682 peer = get_peer(C->id, (void *)C);
683 } else {
684 Py_INCREF(Py_None);
685 peer = Py_None;
686 }
687
688 arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, peer);
689 result = PyEval_CallObject(callable, arglist);
690 Py_DECREF(arglist);
691
692 if(result == NULL)
693 PyErr_Print();
694
695 Py_XDECREF(result);
696 }
697
698 Py_XDECREF(callable);
699 }
700
py_secret_chat_cb(struct tgl_state * TLSR,void * cb_extra,int success,struct tgl_secret_chat * C)701 void py_secret_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_secret_chat *C) {
702 assert (TLSR == TLS);
703 PyObject *callable = cb_extra;
704 PyObject *arglist = NULL;
705 PyObject *peer = NULL;
706 PyObject *result = NULL;
707
708 if(PyCallable_Check(callable)) {
709 if (success) {
710 peer = get_peer(C->id, (void *)C);
711 } else {
712 Py_INCREF(Py_None);
713 peer = Py_None;
714 }
715
716 arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, peer);
717 result = PyEval_CallObject(callable, arglist);
718 Py_DECREF(arglist);
719
720 if(result == NULL)
721 PyErr_Print();
722
723 Py_XDECREF(result);
724 }
725
726 Py_XDECREF(callable);
727 }
728
py_user_cb(struct tgl_state * TLSR,void * cb_extra,int success,struct tgl_user * C)729 void py_user_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_user *C) {
730 assert (TLSR == TLS);
731 PyObject *callable = cb_extra;
732 PyObject *arglist = NULL;
733 PyObject *peer = NULL;
734 PyObject *result = NULL;
735
736 if(PyCallable_Check(callable)) {
737 if (success) {
738 peer = get_peer(C->id, (void *)C);
739 } else {
740 Py_INCREF(Py_None);
741 peer = Py_None;
742 }
743
744 arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, peer);
745 result = PyEval_CallObject(callable, arglist);
746 Py_DECREF(arglist);
747
748 if(result == NULL)
749 PyErr_Print();
750
751 Py_XDECREF(result);
752 }
753
754 Py_XDECREF(callable);
755 }
756
py_str_cb(struct tgl_state * TLSR,void * cb_extra,int success,const char * data)757 void py_str_cb (struct tgl_state *TLSR, void *cb_extra, int success, const char *data) {
758 assert (TLSR == TLS);
759 PyObject *callable = cb_extra;
760 PyObject *arglist = NULL;
761 PyObject *str = NULL;
762 PyObject *result = NULL;
763
764 if(PyCallable_Check(callable)) {
765 if(success)
766 str = PyUnicode_FromString(data);
767 else {
768 Py_INCREF(Py_None);
769 str = Py_None;
770 }
771
772 arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, str);
773 result = PyEval_CallObject(callable, arglist);
774 Py_DECREF(arglist);
775
776 if(result == NULL)
777 PyErr_Print();
778
779 Py_XDECREF(result);
780 }
781
782 Py_XDECREF(callable);
783 }
784
785 #define PY_PEER_ID(x) (tgl_peer_id_t)((tgl_Peer*)x)->peer->id
786 #define PY_MSG_ID(x) (tgl_message_id_t*)x
787
py_do_all(void)788 void py_do_all (void) {
789 int p = 0;
790
791 // ping the python thread that we're doing the loop
792 py_on_loop();
793
794 while (p < pos) {
795 assert (p + 2 <= pos);
796
797 enum py_query_type f = (long)py_ptr[p ++];
798 PyObject *args = (PyObject *)py_ptr[p ++];
799
800 const char *str, *str1, *str2, *str3;
801
802 int preview = 0;
803 int reply_id = 0;
804 unsigned long long flags = 0;
805
806 Py_ssize_t i;
807 tgl_user_id_t *ids;
808
809 struct tgl_message *M;
810
811 int len, len1, len2, len3;
812 int limit, offset;
813 long msg_id = 0;
814
815 PyObject *pyObj1 = NULL;
816 PyObject *pyObj2 = NULL;
817 PyObject *cb_extra = NULL;
818
819 PyObject *msg = NULL;
820 PyObject *peer = NULL;
821 PyObject *peer1 = NULL;
822
823 switch (f) {
824 case pq_contact_list:
825 if(PyArg_ParseTuple(args, "|O", &cb_extra))
826 tgl_do_update_contact_list (TLS, py_contact_list_cb, cb_extra);
827 else
828 PyErr_Print();
829 break;
830 case pq_dialog_list:
831 if(PyArg_ParseTuple(args, "|O", &cb_extra))
832 tgl_do_get_dialog_list (TLS, 100, 0, py_dialog_list_cb, cb_extra);
833 else
834 PyErr_Print();
835 break;
836 case pq_msg:
837 if(PyArg_ParseTuple(args, "O!s#|OO", &tgl_PeerType, &peer, &str, &len, &cb_extra, &pyObj1)) {
838 if(pyObj1 && PyArg_ParseTuple(pyObj1, "ii", &preview, &reply_id)) {
839 if(preview != -1) {
840 if(preview)
841 flags |= TGL_SEND_MSG_FLAG_ENABLE_PREVIEW;
842 else
843 flags |= TGL_SEND_MSG_FLAG_DISABLE_PREVIEW;
844 }
845 flags |= TGL_SEND_MSG_FLAG_REPLY (reply_id);
846 }
847 tgl_do_send_message (TLS, PY_PEER_ID(peer), str, len, flags, NULL, py_msg_cb, cb_extra);
848 } else
849 PyErr_Print();
850
851 Py_XDECREF(pyObj1);
852 break;
853 case pq_send_typing:
854 if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra))
855 tgl_do_send_typing (TLS, PY_PEER_ID(peer), tgl_typing_typing, py_empty_cb, cb_extra);
856 else
857 PyErr_Print();
858 break;
859 case pq_send_typing_abort:
860 if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra))
861 tgl_do_send_typing (TLS, PY_PEER_ID(peer), tgl_typing_cancel, py_empty_cb, cb_extra);
862 else
863 PyErr_Print();
864 break;
865 case pq_rename_chat:
866 if(PyArg_ParseTuple(args, "O!s#|O", &tgl_PeerType, &peer, &str, &len, &cb_extra))
867 tgl_do_rename_chat (TLS, PY_PEER_ID(peer), str, len, py_empty_cb, cb_extra);
868 else
869 PyErr_Print();
870 break;
871 case pq_send_photo:
872 if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra))
873 tgl_do_send_document (TLS, PY_PEER_ID(peer), str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_PHOTO, py_msg_cb, cb_extra);
874 else
875 PyErr_Print();
876 break;
877 case pq_send_video:
878 if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra))
879 tgl_do_send_document (TLS, PY_PEER_ID(peer), str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_VIDEO, py_msg_cb, cb_extra);
880 else
881 PyErr_Print();
882 break;
883 case pq_send_audio:
884 if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra))
885 tgl_do_send_document (TLS, PY_PEER_ID(peer), str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_AUDIO, py_msg_cb, cb_extra);
886 else
887 PyErr_Print();
888 break;
889 case pq_send_document:
890 if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra))
891 tgl_do_send_document (TLS, PY_PEER_ID(peer), str, NULL, 0, 0, py_msg_cb, cb_extra);
892 else
893 PyErr_Print();
894 break;
895 case pq_send_file:
896 if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra))
897 tgl_do_send_document (TLS, PY_PEER_ID(peer), str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_AUTO, py_msg_cb, cb_extra);
898 else
899 PyErr_Print();
900 break;
901 case pq_send_text:
902 if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra))
903 tgl_do_send_text (TLS, PY_PEER_ID(peer), str, 0, py_msg_cb, cb_extra);
904 else
905 PyErr_Print();
906 break;
907 case pq_chat_set_photo:
908 if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra))
909 tgl_do_set_chat_photo (TLS, PY_PEER_ID(peer), str, py_empty_cb, cb_extra);
910 else
911 PyErr_Print();
912 break;
913 case pq_load_photo:
914 case pq_load_video:
915 case pq_load_audio:
916 case pq_load_document:
917 if(PyArg_ParseTuple(args, "O!O", &tgl_MsgType, &msg, &cb_extra))
918 {
919 M = ((tgl_Msg*)msg)->msg;
920 if (!M || (M->media.type != tgl_message_media_photo && M->media.type != tgl_message_media_document && M->media.type != tgl_message_media_document_encr)) {
921 py_file_cb (TLS, cb_extra, 0, 0);
922 } else {
923 if (M->media.type == tgl_message_media_photo) {
924 assert (M->media.photo);
925 tgl_do_load_photo (TLS, M->media.photo, py_file_cb, cb_extra);
926 } else if (M->media.type == tgl_message_media_document) {
927 tgl_do_load_document (TLS, M->media.document, py_file_cb, cb_extra);
928 } else {
929 tgl_do_load_encr_document (TLS, M->media.encr_document, py_file_cb, cb_extra);
930 }
931 }
932 }
933 break;
934 case pq_load_video_thumb:
935 case pq_load_document_thumb:
936 if(PyArg_ParseTuple(args, "O!O", &tgl_MsgType, &msg, &cb_extra))
937 {
938 M = ((tgl_Msg*)msg)->msg;
939 if (!M || (M->media.type != tgl_message_media_document)) {
940 py_file_cb (TLS, cb_extra, 0, 0);
941 } else {
942 tgl_do_load_document_thumb (TLS, M->media.document, py_file_cb, cb_extra);
943 }
944 }
945 break;
946
947 case pq_fwd:
948 if(PyArg_ParseTuple(args, "O!l|O", &tgl_PeerType, &peer, &msg_id, &cb_extra))
949 tgl_do_forward_message (TLS, PY_PEER_ID(peer), PY_MSG_ID(msg_id), 0, py_msg_cb, cb_extra);
950 else
951 PyErr_Print();
952 break;
953 case pq_fwd_media:
954 if(PyArg_ParseTuple(args, "O!l|O", &tgl_PeerType, &peer, &msg_id, &cb_extra))
955 tgl_do_forward_media (TLS, PY_PEER_ID(peer), PY_MSG_ID(msg_id), 0, py_msg_cb, cb_extra);
956 else
957 PyErr_Print();
958 break;
959 case pq_chat_info:
960 if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra))
961 tgl_do_get_chat_info (TLS, PY_PEER_ID(peer), 0, py_chat_cb, cb_extra);
962 else
963 PyErr_Print();
964 break;
965 case pq_user_info:
966 if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra))
967 tgl_do_get_user_info (TLS, PY_PEER_ID(peer), 0, py_user_cb, cb_extra);
968 else
969 PyErr_Print();
970 break;
971 case pq_history:
972 if(PyArg_ParseTuple(args, "O!ii|O", &tgl_PeerType, &peer, &offset, &limit, &cb_extra))
973 tgl_do_get_history (TLS, PY_PEER_ID(peer), offset, limit, 0, py_msg_list_cb, cb_extra);
974 else
975 PyErr_Print();
976 break;
977 case pq_chat_add_user:
978 if(PyArg_ParseTuple(args, "O!O!|O", &tgl_PeerType, &peer, &tgl_PeerType, &peer1, &cb_extra))
979 tgl_do_add_user_to_chat (TLS, PY_PEER_ID(peer), PY_PEER_ID(peer1), 100, py_empty_cb, cb_extra);
980 else
981 PyErr_Print();
982 break;
983 case pq_chat_del_user:
984 if(PyArg_ParseTuple(args, "O!O!|O", &tgl_PeerType, &peer, &tgl_PeerType, &peer1, &cb_extra))
985 tgl_do_del_user_from_chat (TLS, PY_PEER_ID(peer), PY_PEER_ID(peer1), py_empty_cb, cb_extra);
986 else
987 PyErr_Print();
988 break;
989 case pq_add_contact:
990 if(PyArg_ParseTuple(args, "s#s#s#|O", &str1, &len1, &str2, &len2, &str3, &len3, &cb_extra))
991 tgl_do_add_contact (TLS, str1, len1, str2, len2, str3, len3, 0, py_contact_list_cb, cb_extra);
992 else
993 PyErr_Print();
994 break;
995 case pq_del_contact:
996 if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra))
997 tgl_do_del_contact (TLS, PY_PEER_ID(peer), py_empty_cb, cb_extra);
998 else
999 PyErr_Print();
1000 break;
1001 case pq_rename_contact:
1002 if(PyArg_ParseTuple(args, "s#s#s#|O", &str1, &len1, &str2, &len2, &str3, &len3, &cb_extra))
1003 tgl_do_add_contact (TLS, str1, len1, str2, len2, str3, len3, 1, py_contact_list_cb, cb_extra);
1004 else
1005 PyErr_Print();
1006 break;
1007 case pq_search:
1008 if(PyArg_ParseTuple(args, "O!s#|O", &tgl_PeerType, &peer, &str, &len, &cb_extra))
1009 tgl_do_msg_search (TLS, PY_PEER_ID(peer), 0, 0, 40, 0, str, len, py_msg_list_cb, cb_extra);
1010 else
1011 PyErr_Print();
1012 break;
1013 case pq_global_search:
1014 if(PyArg_ParseTuple(args, "s#|O", &str, &len, &cb_extra))
1015 tgl_do_msg_search (TLS, tgl_set_peer_id (TGL_PEER_UNKNOWN, 0), 0, 0, 40, 0, str, len, py_msg_list_cb, cb_extra);
1016 else
1017 PyErr_Print();
1018 break;
1019 case pq_mark_read:
1020 if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra))
1021 tgl_do_mark_read (TLS, PY_PEER_ID(peer), py_empty_cb, cb_extra);
1022 else
1023 PyErr_Print();
1024 break;
1025 case pq_set_profile_photo:
1026 if(PyArg_ParseTuple(args, "s|O", &str, &cb_extra))
1027 tgl_do_set_profile_photo (TLS, str, py_empty_cb, cb_extra);
1028 else
1029 PyErr_Print();
1030 break;
1031 case pq_set_profile_name:
1032 if(PyArg_ParseTuple(args, "s#s#|O", &str1, &len1, &str2, &len2, &cb_extra))
1033 tgl_do_set_profile_name (TLS, str1, len1, str2, len2, py_user_cb, cb_extra);
1034 else
1035 PyErr_Print();
1036 break;
1037 case pq_create_secret_chat:
1038 if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra))
1039 tgl_do_create_secret_chat (TLS, PY_PEER_ID(peer), py_secret_chat_cb, cb_extra);
1040 else
1041 PyErr_Print();
1042 break;
1043 case pq_create_group_chat:
1044 if(PyArg_ParseTuple(args, "O!s#|O", &PyList_Type, &pyObj1, &str, &len, &cb_extra)) {
1045 if(PyList_GET_SIZE(pyObj1) > 2) {
1046 ids = (tgl_user_id_t *)malloc(PyList_GET_SIZE(pyObj1) * sizeof(tgl_user_id_t));
1047 for(i = 0; i < PyList_GET_SIZE(pyObj1); i++) {
1048 peer = PyList_GetItem(pyObj1, i);
1049 *(ids+i) = PY_PEER_ID(peer);
1050 }
1051 tgl_do_create_group_chat (TLS, PyList_GET_SIZE(pyObj1), ids, str, len, py_empty_cb, cb_extra);
1052
1053 tfree(ids, PyList_GET_SIZE(pyObj1) * sizeof(tgl_user_id_t));
1054 } else {
1055 logprintf("create_group_chat: Argument 1 must be a list of at least 3 peers\n");
1056 }
1057 }
1058 Py_XDECREF(pyObj1);
1059 break;
1060 case pq_delete_msg:
1061 case pq_restore_msg:
1062 if(PyArg_ParseTuple(args, "l|O", &msg_id, &cb_extra))
1063 tgl_do_delete_msg (TLS, PY_MSG_ID(msg_id), py_empty_cb, cb_extra);
1064 else
1065 PyErr_Print();
1066 break;
1067 /*
1068 case pq_accept_secret_chat:
1069 tgl_do_accept_encr_chat_request (TLS, py_ptr[p + 1], py_secret_chat_cb, py_ptr[p]);
1070 break;
1071 */
1072 case pq_send_contact:
1073 if(PyArg_ParseTuple(args, "O!s#s#s#|O", &tgl_PeerType, &peer, &str1, &len1, &str2, &len2,
1074 &str3, &len3, &cb_extra))
1075 tgl_do_send_contact (TLS, PY_PEER_ID(peer), str1, len1, str2, len2, str3, len3, 0, py_msg_cb, cb_extra);
1076 else
1077 PyErr_Print();
1078 break;
1079 case pq_status_online:
1080 if(PyArg_ParseTuple(args, "|O", &cb_extra))
1081 tgl_do_update_status (TLS, 1, py_empty_cb, cb_extra);
1082 else
1083 PyErr_Print();
1084 break;
1085 case pq_status_offline:
1086 if(PyArg_ParseTuple(args, "|O", &cb_extra))
1087 tgl_do_update_status (TLS, 0, py_empty_cb, cb_extra);
1088 else
1089 PyErr_Print();
1090 break;
1091 case pq_extf:
1092 if(PyArg_ParseTuple(args, "s#|O", &str, &len, &cb_extra))
1093 tgl_do_send_extf (TLS, str, len, py_str_cb, cb_extra);
1094 else
1095 PyErr_Print();
1096 break;
1097 case pq_import_chat_link:
1098 if(PyArg_ParseTuple(args, "s#|O", &str, &len, &cb_extra))
1099 tgl_do_import_chat_link (TLS, str, len, py_empty_cb, cb_extra);
1100 else
1101 PyErr_Print();
1102 break;
1103 case pq_send_location:
1104 if(PyArg_ParseTuple(args, "O!O!O!|O", &tgl_PeerType, &peer, &PyFloat_Type, &pyObj1, &PyFloat_Type, &pyObj2, &cb_extra)){
1105 tgl_do_send_location (TLS, PY_PEER_ID(peer),
1106 PyFloat_AsDouble(pyObj1), PyFloat_AsDouble(pyObj2), 0, py_msg_cb, cb_extra);
1107 Py_XDECREF(pyObj1);
1108 Py_XDECREF(pyObj2);
1109 } else
1110 PyErr_Print();
1111 break;
1112 default:
1113 assert (0);
1114 }
1115
1116 // Increment reference on cb_extra as it is passed on to the callback to use
1117 Py_XINCREF(cb_extra);
1118
1119 // Clean up any arg variables we could have used.
1120 //Py_XDECREF(args); // TODO: this is going negative ref and causing segfaults
1121 Py_XDECREF(peer);
1122 Py_XDECREF(peer1);
1123
1124 }
1125 pos = 0;
1126 }
1127
push_py_func(enum py_query_type type,PyObject * args)1128 PyObject* push_py_func(enum py_query_type type, PyObject *args) {
1129 assert(pos + 2 < MAX_PY_COMMANDS);
1130
1131 py_ptr[pos ++] = (void *)(long)type;
1132 py_ptr[pos ++] = (void *)args;
1133
1134 Py_INCREF(args);
1135 Py_RETURN_TRUE;
1136 }
1137
1138 // Register functions to push commands on the queue
py_contact_list(PyObject * self,PyObject * args)1139 PyObject* py_contact_list(PyObject *self, PyObject *args) { return push_py_func(pq_contact_list, args); }
py_dialog_list(PyObject * self,PyObject * args)1140 PyObject* py_dialog_list(PyObject *self, PyObject *args) { return push_py_func(pq_dialog_list, args); }
py_rename_chat(PyObject * self,PyObject * args)1141 PyObject* py_rename_chat(PyObject *self, PyObject *args) { return push_py_func(pq_rename_chat, args); }
py_send_msg(PyObject * self,PyObject * args)1142 PyObject* py_send_msg(PyObject *self, PyObject *args) { return push_py_func(pq_msg, args); }
py_send_typing(PyObject * self,PyObject * args)1143 PyObject* py_send_typing(PyObject *self, PyObject *args) { return push_py_func(pq_send_typing, args); }
py_send_typing_abort(PyObject * self,PyObject * args)1144 PyObject* py_send_typing_abort(PyObject *self, PyObject *args) { return push_py_func(pq_send_typing_abort, args); }
py_send_photo(PyObject * self,PyObject * args)1145 PyObject* py_send_photo(PyObject *self, PyObject *args) { return push_py_func(pq_send_photo, args); }
py_send_video(PyObject * self,PyObject * args)1146 PyObject* py_send_video(PyObject *self, PyObject *args) { return push_py_func(pq_send_video, args); }
py_send_audio(PyObject * self,PyObject * args)1147 PyObject* py_send_audio(PyObject *self, PyObject *args) { return push_py_func(pq_send_audio, args); }
py_send_document(PyObject * self,PyObject * args)1148 PyObject* py_send_document(PyObject *self, PyObject *args) { return push_py_func(pq_send_document, args); }
py_send_file(PyObject * self,PyObject * args)1149 PyObject* py_send_file(PyObject *self, PyObject *args) { return push_py_func(pq_send_file, args); }
py_send_text(PyObject * self,PyObject * args)1150 PyObject* py_send_text(PyObject *self, PyObject *args) { return push_py_func(pq_send_text, args); }
py_chat_set_photo(PyObject * self,PyObject * args)1151 PyObject* py_chat_set_photo(PyObject *self, PyObject *args) { return push_py_func(pq_chat_set_photo, args); }
py_load_photo(PyObject * self,PyObject * args)1152 PyObject* py_load_photo(PyObject *self, PyObject *args) { return push_py_func(pq_load_photo, args); }
py_load_video(PyObject * self,PyObject * args)1153 PyObject* py_load_video(PyObject *self, PyObject *args) { return push_py_func(pq_load_video, args); }
py_load_video_thumb(PyObject * self,PyObject * args)1154 PyObject* py_load_video_thumb(PyObject *self, PyObject *args) { return push_py_func(pq_load_video_thumb, args); }
py_load_audio(PyObject * self,PyObject * args)1155 PyObject* py_load_audio(PyObject *self, PyObject *args) { return push_py_func(pq_load_audio, args); }
py_load_document(PyObject * self,PyObject * args)1156 PyObject* py_load_document(PyObject *self, PyObject *args) { return push_py_func(pq_load_document, args); }
py_load_document_thumb(PyObject * self,PyObject * args)1157 PyObject* py_load_document_thumb(PyObject *self, PyObject *args) { return push_py_func(pq_load_document_thumb, args); }
py_fwd(PyObject * self,PyObject * args)1158 PyObject* py_fwd(PyObject *self, PyObject *args) { return push_py_func(pq_fwd, args); }
py_fwd_media(PyObject * self,PyObject * args)1159 PyObject* py_fwd_media(PyObject *self, PyObject *args) { return push_py_func(pq_fwd_media, args); }
py_chat_info(PyObject * self,PyObject * args)1160 PyObject* py_chat_info(PyObject *self, PyObject *args) { return push_py_func(pq_chat_info, args); }
py_user_info(PyObject * self,PyObject * args)1161 PyObject* py_user_info(PyObject *self, PyObject *args) { return push_py_func(pq_chat_info, args); }
py_history(PyObject * self,PyObject * args)1162 PyObject* py_history(PyObject *self, PyObject *args) { return push_py_func(pq_history, args); }
py_chat_add_user(PyObject * self,PyObject * args)1163 PyObject* py_chat_add_user(PyObject *self, PyObject *args) { return push_py_func(pq_chat_add_user, args); }
py_chat_del_user(PyObject * self,PyObject * args)1164 PyObject* py_chat_del_user(PyObject *self, PyObject *args) { return push_py_func(pq_chat_del_user, args); }
py_add_contact(PyObject * self,PyObject * args)1165 PyObject* py_add_contact(PyObject *self, PyObject *args) { return push_py_func(pq_add_contact, args); }
py_del_contact(PyObject * self,PyObject * args)1166 PyObject* py_del_contact(PyObject *self, PyObject *args) { return push_py_func(pq_del_contact, args); }
py_rename_contact(PyObject * self,PyObject * args)1167 PyObject* py_rename_contact(PyObject *self, PyObject *args) { return push_py_func(pq_rename_contact, args); }
py_search(PyObject * self,PyObject * args)1168 PyObject* py_search(PyObject *self, PyObject *args) { return push_py_func(pq_search, args); }
py_global_search(PyObject * self,PyObject * args)1169 PyObject* py_global_search(PyObject *self, PyObject *args) { return push_py_func(pq_global_search, args); }
py_mark_read(PyObject * self,PyObject * args)1170 PyObject* py_mark_read(PyObject *self, PyObject *args) { return push_py_func(pq_mark_read, args); }
py_set_profile_photo(PyObject * self,PyObject * args)1171 PyObject* py_set_profile_photo(PyObject *self, PyObject *args) { return push_py_func(pq_set_profile_photo, args); }
py_set_profile_name(PyObject * self,PyObject * args)1172 PyObject* py_set_profile_name(PyObject *self, PyObject *args) { return push_py_func(pq_set_profile_name, args); }
py_create_secret_chat(PyObject * self,PyObject * args)1173 PyObject* py_create_secret_chat(PyObject *self, PyObject *args) { return push_py_func(pq_create_secret_chat, args); }
py_create_group_chat(PyObject * self,PyObject * args)1174 PyObject* py_create_group_chat(PyObject *self, PyObject *args) { return push_py_func(pq_create_group_chat, args); }
py_delete_msg(PyObject * self,PyObject * args)1175 PyObject* py_delete_msg(PyObject *self, PyObject *args) { return push_py_func(pq_delete_msg, args); }
py_restore_msg(PyObject * self,PyObject * args)1176 PyObject* py_restore_msg(PyObject *self, PyObject *args) { return push_py_func(pq_restore_msg, args); }
py_accept_secret_chat(PyObject * self,PyObject * args)1177 PyObject* py_accept_secret_chat(PyObject *self, PyObject *args) { return push_py_func(pq_accept_secret_chat, args); }
py_send_contact(PyObject * self,PyObject * args)1178 PyObject* py_send_contact(PyObject *self, PyObject *args) { return push_py_func(pq_send_contact, args); }
py_status_online(PyObject * self,PyObject * args)1179 PyObject* py_status_online(PyObject *self, PyObject *args) { return push_py_func(pq_status_online, args); }
py_status_offline(PyObject * self,PyObject * args)1180 PyObject* py_status_offline(PyObject *self, PyObject *args) { return push_py_func(pq_status_offline, args); }
py_send_location(PyObject * self,PyObject * args)1181 PyObject* py_send_location(PyObject *self, PyObject *args) { return push_py_func(pq_send_location, args); }
py_extf(PyObject * self,PyObject * args)1182 PyObject* py_extf(PyObject *self, PyObject *args) { return push_py_func(pq_extf, args); }
py_import_chat_link(PyObject * self,PyObject * args)1183 PyObject* py_import_chat_link(PyObject *self, PyObject *args) { return push_py_func(pq_import_chat_link, args); }
1184
1185 extern int safe_quit;
1186 extern int exit_code;
py_safe_quit(PyObject * self,PyObject * args)1187 PyObject* py_safe_quit(PyObject *self, PyObject *args)
1188 {
1189 int exit_val = 0;
1190 if(PyArg_ParseTuple(args, "|i", &exit_val)) {
1191 safe_quit = 1;
1192 exit_code = exit_val;
1193 } else {
1194 PyErr_Print();
1195 }
1196
1197 Py_RETURN_NONE;
1198 }
1199
py_set_preview(PyObject * self,PyObject * args)1200 PyObject* py_set_preview(PyObject *self, PyObject *args)
1201 {
1202 int preview = 0;
1203 if(PyArg_ParseTuple(args, "p", &preview)) {
1204 if(preview)
1205 TLS->disable_link_preview = 0;
1206 else
1207 TLS->disable_link_preview = 1;
1208 } else {
1209 PyErr_Print();
1210 }
1211
1212 Py_RETURN_NONE;
1213 }
1214
1215 // Store callables for python functions
1216 TGL_PYTHON_CALLBACK("on_binlog_replay_end", _py_binlog_end);
1217 TGL_PYTHON_CALLBACK("on_get_difference_end", _py_diff_end);
1218 TGL_PYTHON_CALLBACK("on_our_id", _py_our_id);
1219 TGL_PYTHON_CALLBACK("on_msg_receive", _py_new_msg);
1220 TGL_PYTHON_CALLBACK("on_msg_history", _py_list_msg);
1221 TGL_PYTHON_CALLBACK("on_secret_chat_update", _py_secret_chat_update);
1222 TGL_PYTHON_CALLBACK("on_user_update", _py_user_update);
1223 TGL_PYTHON_CALLBACK("on_chat_update", _py_chat_update);
1224 TGL_PYTHON_CALLBACK("on_loop", _py_on_loop);
1225
1226 static PyMethodDef py_tgl_methods[] = {
1227 {"get_contact_list", py_contact_list, METH_VARARGS, "retrieve contact list"},
1228 {"get_dialog_list", py_dialog_list, METH_VARARGS, ""},
1229 {"rename_chat", py_rename_chat, METH_VARARGS, ""},
1230 {"send_msg", py_send_msg, METH_VARARGS, "send message to user or chat"},
1231 {"send_typing", py_send_typing, METH_VARARGS, ""},
1232 {"send_typing_abort", py_send_typing_abort, METH_VARARGS, ""},
1233 {"send_photo", py_send_photo, METH_VARARGS, ""},
1234 {"send_video", py_send_video, METH_VARARGS, ""},
1235 {"send_audio", py_send_audio, METH_VARARGS, ""},
1236 {"send_document", py_send_document, METH_VARARGS, ""},
1237 {"send_file", py_send_file, METH_VARARGS, ""},
1238 {"send_text", py_send_text, METH_VARARGS, ""},
1239 {"chat_set_photo", py_chat_set_photo, METH_VARARGS, ""},
1240 {"load_photo", py_load_photo, METH_VARARGS, ""},
1241 {"load_video", py_load_video, METH_VARARGS, ""},
1242 {"load_video_thumb", py_load_video_thumb, METH_VARARGS, ""},
1243 {"load_audio", py_load_audio, METH_VARARGS, ""},
1244 {"load_document", py_load_document, METH_VARARGS, ""},
1245 {"load_document_thumb", py_load_document_thumb, METH_VARARGS, ""},
1246 {"fwd_msg", py_fwd, METH_VARARGS, ""},
1247 {"fwd_media", py_fwd_media, METH_VARARGS, ""},
1248 {"chat_info", py_chat_info, METH_VARARGS, ""},
1249 {"user_info", py_user_info, METH_VARARGS, ""},
1250 {"get_history", py_history, METH_VARARGS, ""},
1251 {"chat_add_user", py_chat_add_user, METH_VARARGS, ""},
1252 {"chat_del_user", py_chat_del_user, METH_VARARGS, ""},
1253 {"add_contact", py_add_contact, METH_VARARGS, ""},
1254 {"del_contact", py_del_contact, METH_VARARGS, ""},
1255 {"rename_contact", py_rename_contact, METH_VARARGS, ""},
1256 {"msg_search", py_search, METH_VARARGS, ""},
1257 {"msg_global_search", py_global_search, METH_VARARGS, ""},
1258 {"mark_read", py_mark_read, METH_VARARGS, ""},
1259 {"set_profile_photo", py_set_profile_photo, METH_VARARGS, ""},
1260 {"set_profile_name", py_set_profile_name, METH_VARARGS, ""},
1261 {"create_secret_chat", py_create_secret_chat, METH_VARARGS, ""},
1262 {"create_group_chat", py_create_group_chat, METH_VARARGS, ""},
1263 {"delete_msg", py_delete_msg, METH_VARARGS, ""},
1264 {"restore_msg", py_restore_msg, METH_VARARGS, ""},
1265 {"accept_secret_chat", py_accept_secret_chat, METH_VARARGS, ""},
1266 {"send_contact", py_send_contact, METH_VARARGS, ""},
1267 {"status_online", py_status_online, METH_VARARGS, ""},
1268 {"status_offline", py_status_offline, METH_VARARGS, ""},
1269 {"send_location", py_send_location, METH_VARARGS, ""},
1270 {"ext_function", py_extf, METH_VARARGS, ""},
1271 {"import_chat_link", py_import_chat_link, METH_VARARGS, ""},
1272 {"set_on_binlog_replay_end", set_py_binlog_end, METH_VARARGS, ""},
1273 {"set_on_get_difference_end", set_py_diff_end, METH_VARARGS, ""},
1274 {"set_on_our_id", set_py_our_id, METH_VARARGS, ""},
1275 {"set_on_msg_receive", set_py_new_msg, METH_VARARGS, ""},
1276 {"set_on_msg_history", set_py_list_msg, METH_VARARGS, ""},
1277 {"set_on_secret_chat_update", set_py_secret_chat_update, METH_VARARGS, ""},
1278 {"set_on_user_update", set_py_user_update, METH_VARARGS, ""},
1279 {"set_on_chat_update", set_py_chat_update, METH_VARARGS, ""},
1280 {"set_on_loop", set_py_on_loop, METH_VARARGS, ""},
1281 {"set_link_preview", py_set_preview, METH_VARARGS, ""},
1282 {"safe_quit", py_safe_quit, METH_VARARGS, ""},
1283 {"safe_exit", py_safe_quit, METH_VARARGS, ""}, // Alias to safe_quit for naming consistancy in python.
1284 { NULL, NULL, 0, NULL }
1285 };
1286
py_add_action_enums(PyObject * m)1287 void py_add_action_enums(PyObject *m)
1288 {
1289 PyModule_AddIntConstant(m, "ACTION_NONE", tgl_message_action_none);
1290 PyModule_AddIntConstant(m, "ACTION_GEO_CHAT_CREATE", tgl_message_action_geo_chat_create);
1291 PyModule_AddIntConstant(m, "ACTION_GEO_CHAT_CHECKIN", tgl_message_action_geo_chat_checkin);
1292 PyModule_AddIntConstant(m, "ACTION_CHAT_CREATE", tgl_message_action_chat_create);
1293 PyModule_AddIntConstant(m, "ACTION_CHAT_EDIT_TITLE", tgl_message_action_chat_edit_title);
1294 PyModule_AddIntConstant(m, "ACTION_CHAT_EDIT_PHOTO", tgl_message_action_chat_edit_photo);
1295 PyModule_AddIntConstant(m, "ACTION_CHAT_DELETE_PHOTO", tgl_message_action_chat_delete_photo);
1296 PyModule_AddIntConstant(m, "ACTION_CHAT_ADD_USER", tgl_message_action_chat_add_users);
1297 PyModule_AddIntConstant(m, "ACTION_CHAT_ADD_USER_BY_LINK", tgl_message_action_chat_add_user_by_link);
1298 PyModule_AddIntConstant(m, "ACTION_CHAT_DELETE_USER", tgl_message_action_chat_delete_user);
1299 PyModule_AddIntConstant(m, "ACTION_SET_MESSAGE_TTL", tgl_message_action_set_message_ttl);
1300 PyModule_AddIntConstant(m, "ACTION_READ_MESSAGES", tgl_message_action_read_messages);
1301 PyModule_AddIntConstant(m, "ACTION_DELETE_MESSAGES", tgl_message_action_delete_messages);
1302 PyModule_AddIntConstant(m, "ACTION_SCREENSHOT_MESSAGES", tgl_message_action_screenshot_messages);
1303 PyModule_AddIntConstant(m, "ACTION_FLUSH_HISTORY", tgl_message_action_flush_history);
1304 PyModule_AddIntConstant(m, "ACTION_RESEND", tgl_message_action_resend);
1305 PyModule_AddIntConstant(m, "ACTION_NOTIFY_LAYER", tgl_message_action_notify_layer);
1306 PyModule_AddIntConstant(m, "ACTION_TYPING", tgl_message_action_typing);
1307 PyModule_AddIntConstant(m, "ACTION_NOOP", tgl_message_action_noop);
1308 PyModule_AddIntConstant(m, "ACTION_COMMIT_KEY", tgl_message_action_commit_key);
1309 PyModule_AddIntConstant(m, "ACTION_ABORT_KEY", tgl_message_action_abort_key);
1310 PyModule_AddIntConstant(m, "ACTION_REQUEST_KEY", tgl_message_action_request_key);
1311 PyModule_AddIntConstant(m, "ACTION_ACCEPT_KEY", tgl_message_action_accept_key);
1312 }
1313
py_add_peer_type_enums(PyObject * m)1314 void py_add_peer_type_enums(PyObject *m)
1315 {
1316 PyModule_AddIntConstant(m, "PEER_USER", TGL_PEER_USER);
1317 PyModule_AddIntConstant(m, "PEER_CHAT", TGL_PEER_CHAT);
1318 PyModule_AddIntConstant(m, "PEER_ENCR_CHAT", TGL_PEER_ENCR_CHAT);
1319 }
1320
1321
MOD_INIT(tgl)1322 MOD_INIT(tgl)
1323 {
1324 PyObject *m;
1325
1326 MOD_DEF(m, "tgl", NULL, py_tgl_methods)
1327
1328 if (m == NULL)
1329 return MOD_ERROR_VAL;
1330
1331 py_add_action_enums(m);
1332 py_add_peer_type_enums(m);
1333
1334 if (PyType_Ready(&tgl_PeerType) < 0)
1335 return MOD_ERROR_VAL;
1336
1337 Py_INCREF(&tgl_PeerType);
1338 PyModule_AddObject(m, "Peer", (PyObject *)&tgl_PeerType);
1339
1340 if (PyType_Ready(&tgl_MsgType) < 0)
1341 return MOD_ERROR_VAL;
1342
1343 Py_INCREF(&tgl_MsgType);
1344 PyModule_AddObject(m, "Msg", (PyObject *)&tgl_MsgType);
1345
1346 TglError = PyErr_NewException("tgl.Error", NULL, NULL);
1347 Py_INCREF(TglError);
1348 PyModule_AddObject(m, "TglError", TglError);
1349
1350 PeerError = PyErr_NewException("tgl.PeerError", NULL, NULL);
1351 Py_INCREF(PeerError);
1352 PyModule_AddObject(m, "PeerError", PeerError);
1353
1354 MsgError = PyErr_NewException("tgl.MsgError", NULL, NULL);
1355 Py_INCREF(MsgError);
1356 PyModule_AddObject(m, "MsgError", MsgError);
1357
1358 return MOD_SUCCESS_VAL(m);
1359 }
1360
1361
py_init(const char * file)1362 void py_init (const char *file) {
1363 if (!file) { return; }
1364 python_loaded = 0;
1365
1366 PyObject *pModule;
1367
1368 // Get a copy of the filename for dirname/basename, which may modify the string, and break const correctness
1369 char filename[1024];
1370 strncpy(filename, file, 1024);
1371
1372
1373
1374 #if PY_MAJOR_VERSION >= 3
1375 PyImport_AppendInittab("tgl", &PyInit_tgl);
1376 Py_Initialize();
1377 #else
1378 Py_Initialize();
1379 inittgl();
1380 #endif
1381
1382
1383 PyObject* sysPath = PySys_GetObject((char*)"path");
1384 PyList_Append(sysPath, PyUnicode_FromString(dirname(filename)));
1385
1386 // Recopy the string in, since dirname modified it.
1387 strncpy(filename, file, 1024);
1388
1389 // remove .py extension from file, if any
1390 char* dot = strrchr(filename, '.');
1391 if (dot && strcmp(dot, ".py") == 0)
1392 *dot = 0;
1393 pModule = PyImport_Import(PyUnicode_FromString(basename(filename)));
1394
1395 if(pModule == NULL || PyErr_Occurred()) { // Error loading script
1396 logprintf("Failed to load python script\n");
1397 PyErr_Print();
1398 exit(1);
1399 }
1400
1401
1402 python_loaded = 1;
1403 PyDateTime_IMPORT;
1404 logprintf("Python Initialized\n");
1405 }
1406
1407 #endif
1408