From 31524068b6143eedd9c3662266c831af0b572823 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 2 May 2015 03:43:53 -0700 Subject: [PATCH 01/29] Adding preliminary python files based on lua bindings. --- ax_python.m4 | 98 ++++ configure.ac | 12 + python-tg.c | 1497 ++++++++++++++++++++++++++++++++++++++++++++++++++ python-tg.h | 35 ++ 4 files changed, 1642 insertions(+) create mode 100644 ax_python.m4 create mode 100644 python-tg.c create mode 100644 python-tg.h diff --git a/ax_python.m4 b/ax_python.m4 new file mode 100644 index 0000000..ebfb8d6 --- /dev/null +++ b/ax_python.m4 @@ -0,0 +1,98 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_python.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PYTHON +# +# DESCRIPTION +# +# This macro does a complete Python development environment check. +# +# It recurses through several python versions (from 2.1 to 2.6 in this +# version), looking for an executable. When it finds an executable, it +# looks to find the header files and library. +# +# It sets PYTHON_BIN to the name of the python executable, +# PYTHON_INCLUDE_DIR to the directory holding the header files, and +# PYTHON_LIB to the name of the Python library. +# +# This macro calls AC_SUBST on PYTHON_BIN (via AC_CHECK_PROG), +# PYTHON_INCLUDE_DIR and PYTHON_LIB. +# +# LICENSE +# +# Copyright (c) 2008 Michael Tindal +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 14 + +AC_DEFUN([AX_PYTHON], +[AC_MSG_CHECKING(for python build information) +AC_MSG_RESULT([]) +for python in python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python; do +AC_CHECK_PROGS(PYTHON_BIN, [$python]) +ax_python_bin=$PYTHON_BIN +if test x$ax_python_bin != x; then + AC_CHECK_LIB($ax_python_bin, main, ax_python_lib=$ax_python_bin, ax_python_lib=no) + if test x$ax_python_lib == xno; then + AC_CHECK_LIB(${ax_python_bin}m, main, ax_python_lib=${ax_python_bin}m, ax_python_lib=no) + fi + if test x$ax_python_lib != xno; then + ax_python_header=`$ax_python_bin -c "from distutils.sysconfig import *; print(get_config_var('CONFINCLUDEPY'))"` + if test x$ax_python_header != x; then + break; + fi + fi +fi +done +if test x$ax_python_bin = x; then + ax_python_bin=no +fi +if test x$ax_python_header = x; then + ax_python_header=no +fi +if test x$ax_python_lib = x; then + ax_python_lib=no +fi + +AC_MSG_RESULT([ results of the Python check:]) +AC_MSG_RESULT([ Binary: $ax_python_bin]) +AC_MSG_RESULT([ Library: $ax_python_lib]) +AC_MSG_RESULT([ Include Dir: $ax_python_header]) + +if test x$ax_python_header != xno; then + PYTHON_INCLUDE_DIR=$ax_python_header + AC_SUBST(PYTHON_INCLUDE_DIR) +fi +if test x$ax_python_lib != xno; then + PYTHON_LIB=$ax_python_lib + AC_SUBST(PYTHON_LIB) +fi +])dnl diff --git a/configure.ac b/configure.ac index 27393e8..e6f1b95 100644 --- a/configure.ac +++ b/configure.ac @@ -4,6 +4,7 @@ AC_CONFIG_SRCDIR([config.h.in]) AC_CONFIG_HEADERS([config.h]) m4_include([ax_lua.m4]) +m4_include([ax_python.m4]) m4_include([m4_ax_check_openssl.m4]) m4_include([m4_ax_check_zlib.m4]) m4_include([m4-ax_gcc_builtin.m4]) @@ -94,6 +95,17 @@ AC_ARG_ENABLE(liblua,[--enable-liblua/--disable-liblua], ]) ]) +AC_ARG_ENABLE(python,[--enable-python/--disable-python], + [ + dnl python checks (you can change the required python version bellow) + AM_PATH_PYTHON(2.7.0) + PY_PREFIX=`$PYTHON -c 'import sys ; print sys.prefix'` + PYTHON_LIBS="-lpython$PYTHON_VERSION" + PYTHON_CFLAGS="-I$PY_PREFIX/include/python$PYTHON_VERSION" + AC_SUBST([PYTHON_LIBS]) + AC_SUBST([PYTHON_CFLAGS]) + ]) + #check for custom prog name AC_ARG_WITH(progname,[--with-progname=], [ diff --git a/python-tg.c b/python-tg.c new file mode 100644 index 0000000..bb55972 --- /dev/null +++ b/python-tg.c @@ -0,0 +1,1497 @@ +/* + This file is part of telegram-cli. + + Telegram-cli is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + Telegram-cli is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this telegram-cli. If not, see . + + Copyright Vitaly Valtman 2013-2015 + Copyright Vincent Castellano 2015 +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef USE_PYTHON +#include "python-tg.h" + +#include +#include + + +#include +#ifdef EVENT_V2 +#include +#else +#include +#include "event-old.h" +#endif + +//#include "interface.h" +//#include "auto/constants.h" +#include +#include "interface.h" + +#include +extern int verbosity; +extern struct tgl_state *TLS; + +static int have_file; + +#define my_lua_checkstack(L,x) assert (lua_checkstack (L, x)) +void push_user (tgl_peer_t *P); +void push_peer (tgl_peer_id_t id, tgl_peer_t *P); + +void lua_add_string_field (const char *name, const char *value) { + assert (name && strlen (name)); + if (!value || !strlen (value)) { return; } + my_lua_checkstack (luaState, 3); + lua_pushstring (luaState, name); + lua_pushstring (luaState, value); + lua_settable (luaState, -3); +} + +void lua_add_string_field_arr (int num, const char *value) { + if (!value || !strlen (value)) { return; } + my_lua_checkstack (luaState, 3); + lua_pushnumber (luaState, num); + lua_pushstring (luaState, value); + lua_settable (luaState, -3); +} + +void lua_add_num_field (const char *name, double value) { + assert (name && strlen (name)); + my_lua_checkstack (luaState, 3); + lua_pushstring (luaState, name); + lua_pushnumber (luaState, value); + lua_settable (luaState, -3); +} + +void push_tgl_peer_type (int x) { + switch (x) { + case TGL_PEER_USER: + lua_pushstring (luaState, "user"); + break; + case TGL_PEER_CHAT: + lua_pushstring (luaState, "chat"); + break; + case TGL_PEER_ENCR_CHAT: + lua_pushstring (luaState, "encr_chat"); + break; + default: + assert (0); + } +} + +void push_user (tgl_peer_t *P) { + my_lua_checkstack (luaState, 4); + lua_add_string_field ("first_name", P->user.first_name); + lua_add_string_field ("last_name", P->user.last_name); + lua_add_string_field ("real_first_name", P->user.real_first_name); + lua_add_string_field ("real_last_name", P->user.real_last_name); + lua_add_string_field ("phone", P->user.phone); + if (P->user.access_hash) { + lua_add_num_field ("access_hash", 1); + } +} + +void push_chat (tgl_peer_t *P) { + my_lua_checkstack (luaState, 4); + assert (P->chat.title); + lua_add_string_field ("title", P->chat.title); + lua_add_num_field ("members_num", P->chat.users_num); + if (P->chat.user_list) { + lua_pushstring (luaState, "members"); + lua_newtable (luaState); + int i; + for (i = 0; i < P->chat.users_num; i++) { + lua_pushnumber (luaState, i); + tgl_peer_id_t id = TGL_MK_USER (P->chat.user_list[i].user_id); + push_peer (id, tgl_peer_get (TLS, id)); + lua_settable (luaState, -3); + } + lua_settable (luaState, -3); + } +} + +void push_encr_chat (tgl_peer_t *P) { + my_lua_checkstack (luaState, 4); + lua_pushstring (luaState, "user"); + push_peer (TGL_MK_USER (P->encr_chat.user_id), tgl_peer_get (TLS, TGL_MK_USER (P->encr_chat.user_id))); + lua_settable (luaState, -3); +} + +void push_update_types (unsigned flags) { + my_lua_checkstack (luaState, 4); + lua_newtable (luaState); + int cc = 0; + + + if (flags & TGL_UPDATE_CREATED) { + lua_add_string_field_arr (cc++, "created"); + } + if (flags & TGL_UPDATE_DELETED) { + lua_add_string_field_arr (cc++, "deleted"); + } + if (flags & TGL_UPDATE_PHONE) { + lua_add_string_field_arr (cc++, "phone"); + } + if (flags & TGL_UPDATE_CONTACT) { + lua_add_string_field_arr (cc++, "contact"); + } + if (flags & TGL_UPDATE_PHOTO) { + lua_add_string_field_arr (cc++, "photo"); + } + if (flags & TGL_UPDATE_BLOCKED) { + lua_add_string_field_arr (cc++, "blocked"); + } + if (flags & TGL_UPDATE_REAL_NAME) { + lua_add_string_field_arr (cc++, "real_name"); + } + if (flags & TGL_UPDATE_NAME) { + lua_add_string_field_arr (cc++, "name"); + } + if (flags & TGL_UPDATE_REQUESTED) { + lua_add_string_field_arr (cc++, "requested"); + } + if (flags & TGL_UPDATE_WORKING) { + lua_add_string_field_arr (cc++, "working"); + } + if (flags & TGL_UPDATE_FLAGS) { + lua_add_string_field_arr (cc++, "flags"); + } + if (flags & TGL_UPDATE_TITLE) { + lua_add_string_field_arr (cc++, "title"); + } + if (flags & TGL_UPDATE_ADMIN) { + lua_add_string_field_arr (cc++, "admin"); + } + if (flags & TGL_UPDATE_MEMBERS) { + lua_add_string_field_arr (cc++, "members"); + } + if (flags & TGL_UPDATE_ACCESS_HASH) { + lua_add_string_field_arr (cc++, "access_hash"); + } + if (flags & TGL_UPDATE_USERNAME) { + lua_add_string_field_arr (cc++, "username"); + } + +} + +void push_peer (tgl_peer_id_t id, tgl_peer_t *P) { + lua_newtable (luaState); + + lua_add_num_field ("id", tgl_get_peer_id (id)); + lua_pushstring (luaState, "type"); + push_tgl_peer_type (tgl_get_peer_type (id)); + lua_settable (luaState, -3); + + + if (!P || !(P->flags & FLAG_CREATED)) { + lua_pushstring (luaState, "print_name"); + static char s[100]; + switch (tgl_get_peer_type (id)) { + case TGL_PEER_USER: + sprintf (s, "user#%d", tgl_get_peer_id (id)); + break; + case TGL_PEER_CHAT: + sprintf (s, "chat#%d", tgl_get_peer_id (id)); + break; + case TGL_PEER_ENCR_CHAT: + sprintf (s, "encr_chat#%d", tgl_get_peer_id (id)); + break; + default: + assert (0); + } + lua_pushstring (luaState, s); + lua_settable (luaState, -3); // flags + + return; + } + + lua_add_string_field ("print_name", P->print_name); + lua_add_num_field ("flags", P->flags); + + switch (tgl_get_peer_type (id)) { + case TGL_PEER_USER: + push_user (P); + break; + case TGL_PEER_CHAT: + push_chat (P); + break; + case TGL_PEER_ENCR_CHAT: + push_encr_chat (P); + break; + default: + assert (0); + } +} + +void push_media (struct tgl_message_media *M) { + my_lua_checkstack (luaState, 4); + + switch (M->type) { + case tgl_message_media_photo: + case tgl_message_media_photo_encr: + lua_newtable (luaState); + lua_add_string_field ("type", "photo"); + break; + /*case tgl_message_media_video: + case tgl_message_media_video_encr: + lua_newtable (luaState); + lua_add_string_field ("type", "video"); + break; + case tgl_message_media_audio: + case tgl_message_media_audio_encr: + lua_newtable (luaState); + lua_add_string_field ("type", "audio"); + break;*/ + case tgl_message_media_document: + case tgl_message_media_document_encr: + lua_newtable (luaState); + lua_add_string_field ("type", "document"); + break; + case tgl_message_media_unsupported: + lua_newtable (luaState); + lua_add_string_field ("type", "unsupported"); + break; + case tgl_message_media_geo: + lua_newtable (luaState); + lua_add_string_field ("type", "geo"); + lua_add_num_field ("longitude", M->geo.longitude); + lua_add_num_field ("latitude", M->geo.latitude); + break; + case tgl_message_media_contact: + lua_newtable (luaState); + lua_add_string_field ("type", "contact"); + lua_add_string_field ("phone", M->phone); + lua_add_string_field ("first_name", M->first_name); + lua_add_string_field ("last_name", M->last_name); + lua_add_num_field ("user_id", M->user_id); + break; + default: + lua_pushstring (luaState, "???"); + } +} + +void push_message (struct tgl_message *M) { + assert (M); + my_lua_checkstack (luaState, 10); + lua_newtable (luaState); + + static char s[30]; + snprintf (s, 30, "%lld", M->id); + lua_add_string_field ("id", s); + if (!(M->flags & FLAG_CREATED)) { return; } + lua_add_num_field ("flags", M->flags); + + if (tgl_get_peer_type (M->fwd_from_id)) { + lua_pushstring (luaState, "fwd_from"); + push_peer (M->fwd_from_id, tgl_peer_get (TLS, M->fwd_from_id)); + lua_settable (luaState, -3); // fwd_from + + lua_add_num_field ("fwd_date", M->fwd_date); + } + + lua_pushstring (luaState, "from"); + push_peer (M->from_id, tgl_peer_get (TLS, M->from_id)); + lua_settable (luaState, -3); + + lua_pushstring (luaState, "to"); + push_peer (M->to_id, tgl_peer_get (TLS, M->to_id)); + lua_settable (luaState, -3); + + lua_pushstring (luaState, "out"); + lua_pushboolean (luaState, M->out); + lua_settable (luaState, -3); + + lua_pushstring (luaState, "unread"); + lua_pushboolean (luaState, M->unread); + lua_settable (luaState, -3); + + lua_pushstring (luaState, "date"); + lua_pushnumber (luaState, M->date); + lua_settable (luaState, -3); + + lua_pushstring (luaState, "service"); + lua_pushboolean (luaState, M->service); + lua_settable (luaState, -3); + + if (!M->service) { + if (M->message_len && M->message) { + lua_pushstring (luaState, "text"); + lua_pushlstring (luaState, M->message, M->message_len); + lua_settable (luaState, -3); + } + if (M->media.type && M->media.type != tgl_message_media_none) { + lua_pushstring (luaState, "media"); + push_media (&M->media); + lua_settable (luaState, -3); + } + } +} + +void lua_binlog_end (void) { + if (!have_file) { return; } + lua_settop (luaState, 0); + //lua_checkstack (luaState, 20); + my_lua_checkstack (luaState, 20); + lua_getglobal (luaState, "on_binlog_replay_end"); + assert (lua_gettop (luaState) == 1); + + int r = lua_pcall (luaState, 0, 0, 0); + if (r) { + logprintf ("lua: %s\n", lua_tostring (luaState, -1)); + } +} + +void lua_diff_end (void) { + if (!have_file) { return; } + lua_settop (luaState, 0); + //lua_checkstack (luaState, 20); + my_lua_checkstack (luaState, 20); + lua_getglobal (luaState, "on_get_difference_end"); + assert (lua_gettop (luaState) == 1); + + int r = lua_pcall (luaState, 0, 0, 0); + if (r) { + logprintf ("lua: %s\n", lua_tostring (luaState, -1)); + } +} + +void lua_our_id (int id) { + if (!have_file) { return; } + lua_settop (luaState, 0); + //lua_checkstack (luaState, 20); + my_lua_checkstack (luaState, 20); + lua_getglobal (luaState, "on_our_id"); + lua_pushnumber (luaState, id); + assert (lua_gettop (luaState) == 2); + + int r = lua_pcall (luaState, 1, 0, 0); + if (r) { + logprintf ("lua: %s\n", lua_tostring (luaState, -1)); + } +} + +void lua_new_msg (struct tgl_message *M) { + if (!have_file) { return; } + lua_settop (luaState, 0); + //lua_checkstack (luaState, 20); + my_lua_checkstack (luaState, 20); + lua_getglobal (luaState, "on_msg_receive"); + push_message (M); + assert (lua_gettop (luaState) == 2); + + int r = lua_pcall (luaState, 1, 0, 0); + if (r) { + logprintf ("lua: %s\n", lua_tostring (luaState, -1)); + } +} + +void lua_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) { + if (!have_file) { return; } + lua_settop (luaState, 0); + //lua_checkstack (luaState, 20); + my_lua_checkstack (luaState, 20); + lua_getglobal (luaState, "on_secret_chat_update"); + push_peer (C->id, (void *)C); + push_update_types (flags); + assert (lua_gettop (luaState) == 3); + + int r = lua_pcall (luaState, 2, 0, 0); + if (r) { + logprintf ("lua: %s\n", lua_tostring (luaState, -1)); + } +} + +void lua_user_update (struct tgl_user *U, unsigned flags) { + if (!have_file) { return; } + lua_settop (luaState, 0); + //lua_checkstack (luaState, 20); + my_lua_checkstack (luaState, 20); + lua_getglobal (luaState, "on_user_update"); + push_peer (U->id, (void *)U); + push_update_types (flags); + assert (lua_gettop (luaState) == 3); + + int r = lua_pcall (luaState, 2, 0, 0); + if (r) { + logprintf ("lua: %s\n", lua_tostring (luaState, -1)); + } +} + +void lua_chat_update (struct tgl_chat *C, unsigned flags) { + if (!have_file) { return; } + lua_settop (luaState, 0); + //lua_checkstack (luaState, 20); + my_lua_checkstack (luaState, 20); + lua_getglobal (luaState, "on_chat_update"); + push_peer (C->id, (void *)C); + push_update_types (flags); + assert (lua_gettop (luaState) == 3); + + int r = lua_pcall (luaState, 2, 0, 0); + if (r) { + logprintf ("lua: %s\n", lua_tostring (luaState, -1)); + } +} + +//extern tgl_peer_t *Peers[]; +//extern int peer_num; + +#define MAX_LUA_COMMANDS 1000 +void *lua_ptr[MAX_LUA_COMMANDS]; +static int pos; + +static inline tgl_peer_t *get_peer (const char *s) { + return tgl_peer_get_by_name (TLS, s); +} + +enum lua_query_type { + lq_contact_list, + lq_dialog_list, + lq_msg, + lq_send_typing, + lq_send_typing_abort, + lq_rename_chat, + lq_send_photo, + lq_chat_set_photo, + lq_set_profile_photo, + lq_set_profile_name, + lq_send_video, + lq_send_text, + lq_fwd, + lq_fwd_media, + lq_load_photo, + lq_load_video_thumb, + lq_load_video, + lq_chat_info, + lq_user_info, + lq_history, + lq_chat_add_user, + lq_chat_del_user, + lq_add_contact, + lq_del_contact, + lq_rename_contact, + lq_search, + lq_global_search, + lq_mark_read, + lq_create_secret_chat, + lq_create_group_chat, + lq_send_audio, + lq_send_document, + lq_send_file, + lq_load_audio, + lq_load_document, + lq_load_document_thumb, + lq_delete_msg, + lq_restore_msg, + lq_accept_secret_chat, + lq_send_contact, + lq_status_online, + lq_status_offline, + lq_send_location, + lq_extf +}; + +struct lua_query_extra { + int func; + int param; +}; + +void lua_empty_cb (struct tgl_state *TLSR, void *cb_extra, int success) { + assert (TLSR == TLS); + struct lua_query_extra *cb = cb_extra; + lua_settop (luaState, 0); + //lua_checkstack (luaState, 20); + my_lua_checkstack (luaState, 20); + + lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); + lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); + + lua_pushnumber (luaState, success); + + assert (lua_gettop (luaState) == 3); + + int r = lua_pcall (luaState, 2, 0, 0); + + luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); + luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); + + if (r) { + logprintf ("lua: %s\n", lua_tostring (luaState, -1)); + } + + free (cb); +} + +void lua_contact_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_user **UL) { + assert (TLSR == TLS); + struct lua_query_extra *cb = cb_extra; + lua_settop (luaState, 0); + //lua_checkstack (luaState, 20); + my_lua_checkstack (luaState, 20); + + lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); + lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); + + lua_pushnumber (luaState, success); + + if (success) { + lua_newtable (luaState); + int i; + for (i = 0; i < num; i++) { + lua_pushnumber (luaState, i); + push_peer (UL[i]->id, (void *)UL[i]); + lua_settable (luaState, -3); + } + } else { + lua_pushboolean (luaState, 0); + } + + assert (lua_gettop (luaState) == 4); + + int r = lua_pcall (luaState, 3, 0, 0); + + luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); + luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); + + if (r) { + logprintf ("lua: %s\n", lua_tostring (luaState, -1)); + } + + free (cb); +} + +void lua_dialog_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, tgl_peer_id_t peers[], int msgs[], int unread[]) { + assert (TLSR == TLS); + struct lua_query_extra *cb = cb_extra; + lua_settop (luaState, 0); + //lua_checkstack (luaState, 20); + my_lua_checkstack (luaState, 20); + + lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); + lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); + + lua_pushnumber (luaState, success); + if (success) { + lua_newtable (luaState); + int i; + for (i = 0; i < num; i++) { + lua_pushnumber (luaState, i); + + lua_newtable (luaState); + + lua_pushstring (luaState, "peer"); + push_peer (peers[i], tgl_peer_get (TLS, peers[i])); + lua_settable (luaState, -3); + + struct tgl_message *M = tgl_message_get (TLS, msgs[i]); + if (M && (M->flags & FLAG_CREATED)) { + lua_pushstring (luaState, "message"); + push_message (M); + lua_settable (luaState, -3); + } + + lua_pushstring (luaState, "unread"); + lua_pushnumber (luaState, unread[i]); + lua_settable (luaState, -3); + + lua_settable (luaState, -3); + } + } else { + lua_pushboolean (luaState, 0); + } + assert (lua_gettop (luaState) == 4); + + + int r = lua_pcall (luaState, 3, 0, 0); + + luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); + luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); + + if (r) { + logprintf ("lua: %s\n", lua_tostring (luaState, -1)); + } + + free (cb); +} + +void lua_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_message *M) { + assert (TLSR == TLS); + struct lua_query_extra *cb = cb_extra; + lua_settop (luaState, 0); + //lua_checkstack (luaState, 20); + my_lua_checkstack (luaState, 20); + + lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); + lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); + + lua_pushnumber (luaState, success); + + if (success) { + push_message (M); + } else { + lua_pushboolean (luaState, 0); + } + + assert (lua_gettop (luaState) == 4); + + int r = lua_pcall (luaState, 3, 0, 0); + + luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); + luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); + + if (r) { + logprintf ("lua: %s\n", lua_tostring (luaState, -1)); + } + + free (cb); +} + +void lua_msg_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_message *M[]) { + assert (TLSR == TLS); + struct lua_query_extra *cb = cb_extra; + lua_settop (luaState, 0); + //lua_checkstack (luaState, 20); + my_lua_checkstack (luaState, 20); + + lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); + lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); + + lua_pushnumber (luaState, success); + + if (success) { + lua_newtable (luaState); + int i; + for (i = 0; i < num; i++) { + lua_pushnumber (luaState, i); + push_message (M[i]); + lua_settable (luaState, -3); + } + } else { + lua_pushboolean (luaState, 0); + } + + assert (lua_gettop (luaState) == 4); + + int r = lua_pcall (luaState, 3, 0, 0); + + luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); + luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); + + if (r) { + logprintf ("lua: %s\n", lua_tostring (luaState, -1)); + } + + free (cb); +} + +void lua_file_cb (struct tgl_state *TLSR, void *cb_extra, int success, char *file_name) { + assert (TLSR == TLS); + struct lua_query_extra *cb = cb_extra; + lua_settop (luaState, 0); + //lua_checkstack (luaState, 20); + my_lua_checkstack (luaState, 20); + + lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); + lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); + + lua_pushnumber (luaState, success); + + if (success) { + lua_pushstring (luaState, file_name); + } else { + lua_pushboolean (luaState, 0); + } + + assert (lua_gettop (luaState) == 4); + + int r = lua_pcall (luaState, 3, 0, 0); + + luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); + luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); + + if (r) { + logprintf ("lua: %s\n", lua_tostring (luaState, -1)); + } + + free (cb); +} + +void lua_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_chat *C) { + assert (TLSR == TLS); + struct lua_query_extra *cb = cb_extra; + lua_settop (luaState, 0); + //lua_checkstack (luaState, 20); + my_lua_checkstack (luaState, 20); + + lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); + lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); + + lua_pushnumber (luaState, success); + + if (success) { + push_peer (C->id, (void *)C); + } else { + lua_pushboolean (luaState, 0); + } + + assert (lua_gettop (luaState) == 4); + + int r = lua_pcall (luaState, 3, 0, 0); + + luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); + luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); + + if (r) { + logprintf ("lua: %s\n", lua_tostring (luaState, -1)); + } + + free (cb); +} + +void lua_secret_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_secret_chat *C) { + assert (TLSR == TLS); + struct lua_query_extra *cb = cb_extra; + lua_settop (luaState, 0); + //lua_checkstack (luaState, 20); + my_lua_checkstack (luaState, 20); + + lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); + lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); + + lua_pushnumber (luaState, success); + + if (success) { + push_peer (C->id, (void *)C); + } else { + lua_pushboolean (luaState, 0); + } + + assert (lua_gettop (luaState) == 4); + + int r = lua_pcall (luaState, 3, 0, 0); + + luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); + luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); + + if (r) { + logprintf ("lua: %s\n", lua_tostring (luaState, -1)); + } + + free (cb); +} + +void lua_user_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_user *C) { + assert (TLSR == TLS); + struct lua_query_extra *cb = cb_extra; + lua_settop (luaState, 0); + //lua_checkstack (luaState, 20); + my_lua_checkstack (luaState, 20); + + lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); + lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); + + lua_pushnumber (luaState, success); + + if (success) { + push_peer (C->id, (void *)C); + } else { + lua_pushboolean (luaState, 0); + } + + assert (lua_gettop (luaState) == 4); + + int r = lua_pcall (luaState, 3, 0, 0); + + luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); + luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); + + if (r) { + logprintf ("lua: %s\n", lua_tostring (luaState, -1)); + } + + free (cb); +} + +void lua_str_cb (struct tgl_state *TLSR, void *cb_extra, int success, char *data) { + assert (TLSR == TLS); + struct lua_query_extra *cb = cb_extra; + lua_settop (luaState, 0); + //lua_checkstack (luaState, 20); + my_lua_checkstack (luaState, 20); + + lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); + lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); + + lua_pushnumber (luaState, success); + + if (success) { + lua_pushstring (luaState, data); + } else { + lua_pushboolean (luaState, 0); + } + + assert (lua_gettop (luaState) == 4); + + int r = lua_pcall (luaState, 3, 0, 0); + + luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); + luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); + + if (r) { + logprintf ("lua: %s\n", lua_tostring (luaState, -1)); + } + + free (cb); +} + +void lua_do_all (void) { + int p = 0; + while (p < pos) { + int l = (long)lua_ptr[p ++]; + assert (p + l + 1 <= pos); + enum lua_query_type f = (long)lua_ptr[p ++]; + struct tgl_message *M; + char *s, *s1, *s2, *s3; + switch (f) { + case lq_contact_list: + tgl_do_update_contact_list (TLS, lua_contact_list_cb, lua_ptr[p ++]); + break; + case lq_dialog_list: + tgl_do_get_dialog_list (TLS, lua_dialog_list_cb, lua_ptr[p ++]); + break; + case lq_msg: + tgl_do_send_message (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], strlen (lua_ptr[p + 2]), lua_msg_cb, lua_ptr[p]); + free (lua_ptr[p + 2]); + p += 3; + break; + case lq_send_typing: + tgl_do_send_typing (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, tgl_typing_typing, lua_empty_cb, lua_ptr[p]); + p += 2; + break; + case lq_send_typing_abort: + tgl_do_send_typing (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, tgl_typing_cancel, lua_empty_cb, lua_ptr[p]); + p += 2; + break; + case lq_rename_chat: + tgl_do_rename_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); + free (lua_ptr[p + 2]); + p += 3; + break; + case lq_send_photo: + tgl_do_send_document (TLS, -1, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); + free (lua_ptr[p + 2]); + p += 3; + break; + case lq_send_video: + tgl_do_send_document (TLS, FLAG_DOCUMENT_VIDEO, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); + free (lua_ptr[p + 2]); + p += 3; + break; + case lq_send_audio: + tgl_do_send_document (TLS, FLAG_DOCUMENT_AUDIO, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); + free (lua_ptr[p + 2]); + p += 3; + break; + case lq_send_document: + tgl_do_send_document (TLS, 0, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); + free (lua_ptr[p + 2]); + p += 3; + break; + case lq_send_file: + tgl_do_send_document (TLS, -2, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); + free (lua_ptr[p + 2]); + p += 3; + break; + case lq_send_text: + tgl_do_send_text (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); + free (lua_ptr[p + 2]); + p += 3; + break; + case lq_chat_set_photo: + tgl_do_set_chat_photo (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); + free (lua_ptr[p + 2]); + p += 3; + break; + case lq_load_photo: + case lq_load_video: + case lq_load_audio: + case lq_load_document: + M = lua_ptr[p + 1]; + if (!M || (M->media.type != tgl_message_media_photo && M->media.type != tgl_message_media_photo_encr && M->media.type != tgl_message_media_document && M->media.type != tgl_message_media_document_encr)) { + lua_file_cb (TLS, lua_ptr[p], 0, 0); + } else { + if (M->media.type == tgl_message_media_photo) { + tgl_do_load_photo (TLS, &M->media.photo, lua_file_cb, lua_ptr[p]); + } else if (M->media.type == tgl_message_media_document) { + tgl_do_load_document (TLS, &M->media.document, lua_file_cb, lua_ptr[p]); + } else { + tgl_do_load_encr_document (TLS, &M->media.encr_document, lua_file_cb, lua_ptr[p]); + } + } + p += 2; + break; + case lq_load_video_thumb: + case lq_load_document_thumb: + M = lua_ptr[p + 1]; + if (!M || (M->media.type != tgl_message_media_document)) { + lua_file_cb (TLS, lua_ptr[p], 0, 0); + } else { + tgl_do_load_document_thumb (TLS, &M->media.document, lua_file_cb, lua_ptr[p]); + } + p += 2; + break; + case lq_fwd: + tgl_do_forward_message (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, ((struct tgl_message *)lua_ptr[p + 2])->id, lua_msg_cb, lua_ptr[p]); + p += 3; + break; + case lq_fwd_media: + tgl_do_forward_media (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, ((struct tgl_message *)lua_ptr[p + 2])->id, lua_msg_cb, lua_ptr[p]); + p += 3; + break; + case lq_chat_info: + tgl_do_get_chat_info (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, 0, lua_chat_cb, lua_ptr[p]); + p += 2; + break; + case lq_user_info: + tgl_do_get_user_info (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, 0, lua_user_cb, lua_ptr[p]); + p += 2; + break; + case lq_history: + tgl_do_get_history (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, (long)lua_ptr[p + 2], 0, lua_msg_list_cb, lua_ptr[p]); + p += 3; + break; + case lq_chat_add_user: + tgl_do_add_user_to_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, ((tgl_peer_t *)lua_ptr[p + 2])->id, 10, lua_msg_cb, lua_ptr[p]); + p += 3; + break; + case lq_chat_del_user: + tgl_do_del_user_from_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, ((tgl_peer_t *)lua_ptr[p + 2])->id, lua_msg_cb, lua_ptr[p]); + p += 3; + break; + case lq_add_contact: + s1 = lua_ptr[p + 1]; + s2 = lua_ptr[p + 2]; + s3 = lua_ptr[p + 3]; + tgl_do_add_contact (TLS, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), 0, lua_contact_list_cb, lua_ptr[p]); + free (s1); + free (s2); + free (s3); + p += 4; + break; + case lq_del_contact: + tgl_do_del_contact (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_empty_cb, lua_ptr[p]); + p += 2; + break; + case lq_rename_contact: + s1 = lua_ptr[p + 1]; + s2 = lua_ptr[p + 2]; + s3 = lua_ptr[p + 3]; + tgl_do_add_contact (TLS, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), 1, lua_contact_list_cb, lua_ptr[p]); + free (s1); + free (s2); + free (s3); + p += 4; + break; + case lq_search: + s = lua_ptr[p + 2]; + tgl_do_msg_search (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, 0, 0, 40, 0, s, lua_msg_list_cb, lua_ptr[p]); + free (s); + p += 3; + break; + case lq_global_search: + s = lua_ptr[p + 1]; + tgl_do_msg_search (TLS, tgl_set_peer_id (TGL_PEER_UNKNOWN, 0), 0, 0, 40, 0, s, lua_msg_list_cb, lua_ptr[p]); + free (s); + p += 2; + break; + case lq_mark_read: + tgl_do_mark_read (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_empty_cb, lua_ptr[p]); + p += 2; + break; + case lq_set_profile_photo: + s = lua_ptr[p + 1]; + tgl_do_set_profile_photo (TLS, s, lua_empty_cb, lua_ptr[p]); + free (s); + p += 2; + break; + case lq_set_profile_name: + s1 = lua_ptr[p + 1]; + s2 = lua_ptr[p + 1]; + tgl_do_set_profile_name (TLS, s1, s2, lua_user_cb, lua_ptr[p]); + free (s1); + free (s2); + p += 3; + break; + case lq_create_secret_chat: + tgl_do_create_secret_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_secret_chat_cb, lua_ptr[p]); + p += 2; + break; + case lq_create_group_chat: + s = lua_ptr[p + 2]; + tgl_do_create_group_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, s, lua_msg_cb, lua_ptr[p]); + free (s); + p += 3; + break; + case lq_delete_msg: + tgl_do_delete_msg (TLS, ((struct tgl_message *)lua_ptr[p + 1])->id, lua_empty_cb, lua_ptr[p]); + p += 2; + break; + case lq_restore_msg: + tgl_do_delete_msg (TLS, (long)lua_ptr[p + 1], lua_empty_cb, lua_ptr[p]); + p += 2; + break; + case lq_accept_secret_chat: + tgl_do_accept_encr_chat_request (TLS, lua_ptr[p + 1], lua_secret_chat_cb, lua_ptr[p]); + p += 2; + break; + case lq_send_contact: + s1 = lua_ptr[p + 2]; + s2 = lua_ptr[p + 3]; + s3 = lua_ptr[p + 4]; + tgl_do_send_contact (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), lua_msg_cb, lua_ptr[p]); + free (s1); + free (s2); + free (s3); + p += 5; + break; + case lq_status_online: + tgl_do_update_status (TLS, 1, lua_empty_cb, lua_ptr[p]); + p ++; + break; + case lq_status_offline: + tgl_do_update_status (TLS, 0, lua_empty_cb, lua_ptr[p]); + p ++; + break; + case lq_extf: + s = lua_ptr[p + 1]; + tgl_do_send_extf (TLS, s, strlen (s), lua_str_cb, lua_ptr[p]); + free (s); + p += 2; + break; + case lq_send_location: + if (sizeof (void *) == 4) { + tgl_do_send_location (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id , *(float *)(lua_ptr + p + 2), *(float *)(lua_ptr + p + 3), lua_msg_cb, lua_ptr[p]); + } else { + tgl_do_send_location (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id , *(double *)(lua_ptr + p + 2), *(double *)(lua_ptr + p + 3), lua_msg_cb, lua_ptr[p]); + } + p += 4; + break; + /* + lq_delete_msg, + lq_restore_msg, + case 0: + tgl_do_send_message (((tgl_peer_t *)lua_ptr[p])->id, lua_ptr[p + 1], strlen (lua_ptr[p + 1]), 0, 0); + free (lua_ptr[p + 1]); + p += 2; + break; + case 1: + tgl_do_forward_message (((tgl_peer_t *)lua_ptr[p])->id, (long)lua_ptr[p + 1], 0, 0); + p += 2; + break; + case 2: + tgl_do_mark_read (((tgl_peer_t *)lua_ptr[p])->id, 0, 0); + p += 1; + break;*/ + default: + assert (0); + } + } + pos = 0; +} + + +enum lua_function_param { + lfp_none, + lfp_peer, + lfp_chat, + lfp_user, + lfp_secret_chat, + lfp_string, + lfp_number, + lfp_positive_number, + lfp_nonnegative_number, + lfp_msg, + lfp_double +}; + +struct lua_function { + char *name; + enum lua_query_type type; + enum lua_function_param params[10]; +}; + +struct lua_function functions[] = { + {"get_contact_list", lq_contact_list, { lfp_none }}, + {"get_dialog_list", lq_dialog_list, { lfp_none }}, + {"rename_chat", lq_rename_chat, { lfp_chat, lfp_string, lfp_none }}, + {"send_msg", lq_msg, { lfp_peer, lfp_string, lfp_none }}, + {"send_typing", lq_send_typing, { lfp_peer, lfp_none }}, + {"send_typing_abort", lq_send_typing_abort, { lfp_peer, lfp_none }}, + {"send_photo", lq_send_photo, { lfp_peer, lfp_string, lfp_none }}, + {"send_video", lq_send_video, { lfp_peer, lfp_string, lfp_none }}, + {"send_audio", lq_send_audio, { lfp_peer, lfp_string, lfp_none }}, + {"send_document", lq_send_document, { lfp_peer, lfp_string, lfp_none }}, + {"send_file", lq_send_file, { lfp_peer, lfp_string, lfp_none }}, + {"send_text", lq_send_text, { lfp_peer, lfp_string, lfp_none }}, + {"chat_set_photo", lq_chat_set_photo, { lfp_chat, lfp_string, lfp_none }}, + {"load_photo", lq_load_photo, { lfp_msg, lfp_none }}, + {"load_video", lq_load_video, { lfp_msg, lfp_none }}, + {"load_video_thumb", lq_load_video_thumb, { lfp_msg, lfp_none }}, + {"load_audio", lq_load_audio, { lfp_msg, lfp_none }}, + {"load_document", lq_load_document, { lfp_msg, lfp_none }}, + {"load_document_thumb", lq_load_document_thumb, { lfp_msg, lfp_none }}, + {"fwd_msg", lq_fwd, { lfp_peer, lfp_msg, lfp_none }}, + {"fwd_media", lq_fwd_media, { lfp_peer, lfp_msg, lfp_none }}, + {"chat_info", lq_chat_info, { lfp_chat, lfp_none }}, + {"user_info", lq_user_info, { lfp_user, lfp_none }}, + {"get_history", lq_history, { lfp_peer, lfp_nonnegative_number, lfp_none }}, + {"chat_add_user", lq_chat_add_user, { lfp_chat, lfp_user, lfp_none }}, + {"chat_del_user", lq_chat_del_user, { lfp_chat, lfp_user, lfp_none }}, + {"add_contact", lq_add_contact, { lfp_string, lfp_string, lfp_string, lfp_none }}, + {"del_contact", lq_del_contact, { lfp_user, lfp_none }}, + {"rename_contact", lq_rename_contact, { lfp_string, lfp_string, lfp_string, lfp_none }}, + {"msg_search", lq_search, { lfp_peer, lfp_string, lfp_none }}, + {"msg_global_search", lq_global_search, { lfp_string, lfp_none }}, + {"mark_read", lq_mark_read, { lfp_peer, lfp_none }}, + {"set_profile_photo", lq_set_profile_photo, { lfp_string, lfp_none }}, + {"set_profile_name", lq_set_profile_name, { lfp_string, lfp_none }}, + {"create_secret_chat", lq_create_secret_chat, { lfp_user, lfp_none }}, + {"create_group_chat", lq_create_group_chat, { lfp_user, lfp_string, lfp_none }}, + {"delete_msg", lq_delete_msg, { lfp_msg, lfp_none }}, + {"restore_msg", lq_restore_msg, { lfp_positive_number, lfp_none }}, + {"accept_secret_chat", lq_accept_secret_chat, { lfp_secret_chat, lfp_none }}, + {"send_contact", lq_send_contact, { lfp_peer, lfp_string, lfp_string, lfp_string, lfp_none }}, + {"status_online", lq_status_online, { lfp_none }}, + {"status_offline", lq_status_offline, { lfp_none }}, + {"send_location", lq_send_location, { lfp_peer, lfp_double, lfp_double, lfp_none }}, + {"ext_function", lq_extf, { lfp_string, lfp_none }}, + { 0, 0, { lfp_none}} +}; + +static int parse_lua_function (lua_State *L, struct lua_function *F) { + int p = 0; + while (F->params[p] != lfp_none) { p ++; } + if (lua_gettop (L) != p + 2) { + lua_pushboolean (L, 0); + return 1; + } + + int a1 = luaL_ref (L, LUA_REGISTRYINDEX); + int a2 = luaL_ref (L, LUA_REGISTRYINDEX); + + struct lua_query_extra *e = malloc (sizeof (*e)); + assert (e); + e->func = a2; + e->param = a1; + + assert (pos + 3 + p < MAX_LUA_COMMANDS); + + lua_ptr[pos ++] = (void *)(long)(p + 1); + lua_ptr[pos ++] = (void *)(long)F->type; + lua_ptr[pos ++] = e; + + int sp = p; + int ok = 1; + int cc = 0; + while (p > 0) { + p --; + cc ++; + const char *s; + tgl_peer_t *P; + long long num; + double dval; + struct tgl_message *M; + switch (F->params[p]) { + case lfp_none: + assert (0); + break; + case lfp_peer: + case lfp_user: + case lfp_chat: + case lfp_secret_chat: + s = lua_tostring (L, -cc); + if (!s) { + ok = 0; + break; + } + if (sscanf (s, "user#id%lld", &num) == 1 && num > 0) { + tgl_insert_empty_user (TLS, num); + P = tgl_peer_get (TLS, TGL_MK_USER (num)); + } else if (sscanf (s, "chat#id%lld", &num) == 1 && num > 0) { + tgl_insert_empty_chat (TLS, num); + P = tgl_peer_get (TLS, TGL_MK_CHAT (num)); + } else { + P = get_peer (s); + } + if (!P/* || !(P->flags & FLAG_CREATED)*/) { + ok = 0; + break; + } + if (F->params[p] != lfp_peer) { + if ((tgl_get_peer_type (P->id) == TGL_PEER_USER && F->params[p] != lfp_user) || + (tgl_get_peer_type (P->id) == TGL_PEER_CHAT && F->params[p] != lfp_chat) || + (tgl_get_peer_type (P->id) == TGL_PEER_ENCR_CHAT && F->params[p] != lfp_secret_chat)) { + ok = 0; + break; + } + } + lua_ptr[pos + p] = P; + break; + + case lfp_string: + s = lua_tostring (L, -cc); + if (!s) { + ok = 0; + break; + } + lua_ptr[pos + p] = (void *)s; + break; + + case lfp_number: + num = lua_tonumber (L, -cc); + + lua_ptr[pos + p] = (void *)(long)num; + break; + + case lfp_double: + dval = lua_tonumber (L, -cc); + + if (sizeof (void *) == 4) { + *(float *)(lua_ptr + pos + p) = dval; + } else { + assert (sizeof (void *) >= 8); + *(double *)(lua_ptr + pos + p) = dval; + } + break; + + case lfp_positive_number: + num = lua_tonumber (L, -cc); + if (num <= 0) { + ok = 0; + break; + } + + lua_ptr[pos + p] = (void *)(long)num; + break; + + case lfp_nonnegative_number: + num = lua_tonumber (L, -cc); + if (num < 0) { + ok = 0; + break; + } + + lua_ptr[pos + p] = (void *)(long)num; + break; + + case lfp_msg: + s = lua_tostring (L, -cc); + if (!s || !strlen (s)) { + ok = 0; + break; + } + + num = atoll (s); + + M = tgl_message_get (TLS, num); + + if (!M || !(M->flags & FLAG_CREATED)) { + ok = 0; + break; + } + + lua_ptr[pos + p] = M; + break; + + default: + assert (0); + } + } + if (!ok) { + luaL_unref (luaState, LUA_REGISTRYINDEX, a1); + luaL_unref (luaState, LUA_REGISTRYINDEX, a2); + free (e); + pos -= 3; + lua_pushboolean (L, 0); + return 1; + } + + for (p = 0; p < sp; p++) { + if (F->params[p] == lfp_string) { + lua_ptr[pos + p] = strdup (lua_ptr[pos + p]); + } + } + pos += p; + + lua_pushboolean (L, 1); + return 1; +} + + +static void lua_postpone_alarm (evutil_socket_t fd, short what, void *arg) { + int *t = arg; + + lua_settop (luaState, 0); + //lua_checkstack (luaState, 20); + my_lua_checkstack (luaState, 20); + + lua_rawgeti (luaState, LUA_REGISTRYINDEX, t[1]); + lua_rawgeti (luaState, LUA_REGISTRYINDEX, t[0]); + assert (lua_gettop (luaState) == 2); + + int r = lua_pcall (luaState, 1, 0, 0); + + luaL_unref (luaState, LUA_REGISTRYINDEX, t[0]); + luaL_unref (luaState, LUA_REGISTRYINDEX, t[1]); + + if (r) { + logprintf ("lua: %s\n", lua_tostring (luaState, -1)); + } + +} + +static int postpone_from_lua (lua_State *L) { + int n = lua_gettop (L); + if (n != 3) { + lua_pushboolean (L, 0); + return 1; + } + + double timeout = lua_tonumber (L, -1); + if (timeout < 0) { + lua_pushboolean (L, 0); + return 1; + } + + lua_pop (L, 1); + int a1 = luaL_ref (L, LUA_REGISTRYINDEX); + int a2 = luaL_ref (L, LUA_REGISTRYINDEX); + + + int *t = malloc (16); + assert (t); + struct event *ev = evtimer_new (TLS->ev_base, lua_postpone_alarm, t); + t[0] = a1; + t[1] = a2; + *(void **)(t + 2) = ev; + + struct timeval ts= { + .tv_sec = (long)timeout, + .tv_usec = (timeout - ((long)timeout)) * 1000000 + }; + event_add (ev, &ts); + + lua_pushboolean (L, 1); + return 1; +} + +extern int safe_quit; +static int safe_quit_from_lua (lua_State *L) { + int n = lua_gettop (L); + if (n != 0) { + lua_pushboolean (L, 0); + return 1; + } + safe_quit = 1; + + lua_pushboolean (L, 1); + return 1; +} + +static int universal_from_lua (lua_State *L) { + const char *s = lua_tostring(L, lua_upvalueindex(1)); + if (!s) { + lua_pushboolean (L, 0); + return 1; + } + int i = 0; + while (functions[i].name) { + if (!strcmp (functions[i].name, s)) { + return parse_lua_function (L, &functions[i]); + } + i ++; + } + lua_pushboolean (L, 0); + return 1; +} + + +static void my_python_register (const char *name, lua_CFunction f) { + lua_pushstring(L, name); + lua_pushcclosure(L, f, 1); + lua_setglobal(L, name); +} + + +void py_init (const char *file) { + if (!file) { return; } + have_file = 1; + + PyObject *pName, *pModule; + + Py_Initialize() + + pName = PyFile_FromFile(file, "telegram.py", 'r', null); + + err = PyErr_Occurred(); + if (err != NULL) { + logprintf("python error occurred"); // TODO: implement the backtrace + exit(1); + } + + int i = 0; + while (functions[i].name) { + my_lua_register (luaState, functions[i].name, universal_from_lua); + i ++; + } + //lua_register (luaState, "fwd_msg", fwd_msg_from_lua); + //lua_register (luaState, "mark_read", mark_read_from_lua); + lua_register (luaState, "postpone", postpone_from_lua); + lua_register (luaState, "safe_quit", safe_quit_from_lua); + //lua_register (luaState, "get_contact_list", get_contacts_from_lua); + /*lua_register (luaState, "get_dialog_list", get_dialog_list_from_lua); + lua_register (luaState, "send_msg", send_msg_from_lua); + lua_register (luaState, "rename_chat", rename_chat_from_lua); + lua_register (luaState, "send_photo", send_photo_from_lua); + lua_register (luaState, "send_video", send_video_from_lua); + lua_register (luaState, "send_audio", send_audio_from_lua); + lua_register (luaState, "send_document", send_document_from_lua); + lua_register (luaState, "send_text", send_text_from_lua); + lua_register (luaState, "chat_set_photo", chat_set_photo_from_lua); + lua_register (luaState, "load_photo", load_photo_from_lua); + lua_register (luaState, "load_video", load_video_from_lua); + lua_register (luaState, "load_video_thumb", load_video_thumb_from_lua); + lua_register (luaState, "load_audio", load_audio_from_lua); + lua_register (luaState, "load_document", load_document_from_lua); + lua_register (luaState, "load_document_thumb", load_document_thumb_from_lua); + lua_register (luaState, "fwd_msg", message_forward_from_lua); + lua_register (luaState, "chat_info", chat_info_from_lua); + lua_register (luaState, "user_info", user_info_from_lua); + lua_register (luaState, "get_history", get_history_from_lua); + lua_register (luaState, "chat_add_user", chat_add_user_from_lua); + lua_register (luaState, "chat_del_user", chat_del_user_from_lua); + lua_register (luaState, "add_contact", add_contact_from_lua); + lua_register (luaState, "rename_contact", rename_contact_from_lua);*/ + + int ret = luaL_dofile (luaState, file); + if (ret) { + logprintf ("lua: %s\n", lua_tostring (luaState, -1)); + exit (1); + } +} + +#endif diff --git a/python-tg.h b/python-tg.h new file mode 100644 index 0000000..2fb84ab --- /dev/null +++ b/python-tg.h @@ -0,0 +1,35 @@ +/* + This file is part of telegram-cli. + + Telegram-cli is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + Telegram-cli is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this telegram-cli. If not, see . + + Copyright Vitaly Valtman 2013-2015 + Copyright Vincent Castellano 2015 +*/ +#ifndef __PYTHON_TG_H__ +#define __PYTHON_TG_H__ + +#include +#include + +void py_init (const char *file); +void py_new_msg (struct tgl_message *M); +void py_our_id (int id); +void py_secret_chat_update (struct tgl_secret_chat *U, unsigned flags); +void py_user_update (struct tgl_user *U, unsigned flags); +void py_chat_update (struct tgl_chat *C, unsigned flags); +void py_binlog_end (void); +void py_diff_end (void); +void py_do_all (void); +#endif From 76d1ee247504a4ce434bfffb7751155492b1853d Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 2 May 2015 04:45:49 -0700 Subject: [PATCH 02/29] Added preliminary autotools support for pyton, TODO improve. --- autotools.sh | 1 + 1 file changed, 1 insertion(+) create mode 100755 autotools.sh diff --git a/autotools.sh b/autotools.sh new file mode 100755 index 0000000..e180398 --- /dev/null +++ b/autotools.sh @@ -0,0 +1 @@ +aclocal ; autoheader; automake ; autoconf From 35b5623eb17f49a3753b5780cdd04f118a772051 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 2 May 2015 04:48:02 -0700 Subject: [PATCH 03/29] Missing changes to python-tg.c --- python-tg.c | 2796 +++++++++++++++++++++++++-------------------------- 1 file changed, 1395 insertions(+), 1401 deletions(-) diff --git a/python-tg.c b/python-tg.c index bb55972..4432996 100644 --- a/python-tg.c +++ b/python-tg.c @@ -47,1421 +47,1420 @@ extern int verbosity; extern struct tgl_state *TLS; static int have_file; - -#define my_lua_checkstack(L,x) assert (lua_checkstack (L, x)) -void push_user (tgl_peer_t *P); -void push_peer (tgl_peer_id_t id, tgl_peer_t *P); - -void lua_add_string_field (const char *name, const char *value) { - assert (name && strlen (name)); - if (!value || !strlen (value)) { return; } - my_lua_checkstack (luaState, 3); - lua_pushstring (luaState, name); - lua_pushstring (luaState, value); - lua_settable (luaState, -3); +// +//void push_user (tgl_peer_t *P); +//void push_peer (tgl_peer_id_t id, tgl_peer_t *P); +// +//void lua_add_string_field (const char *name, const char *value) { +// assert (name && strlen (name)); +// if (!value || !strlen (value)) { return; } +// my_lua_checkstack (luaState, 3); +// lua_pushstring (luaState, name); +// lua_pushstring (luaState, value); +// lua_settable (luaState, -3); +//} +// +//void lua_add_string_field_arr (int num, const char *value) { +// if (!value || !strlen (value)) { return; } +// my_lua_checkstack (luaState, 3); +// lua_pushnumber (luaState, num); +// lua_pushstring (luaState, value); +// lua_settable (luaState, -3); +//} +// +//void lua_add_num_field (const char *name, double value) { +// assert (name && strlen (name)); +// my_lua_checkstack (luaState, 3); +// lua_pushstring (luaState, name); +// lua_pushnumber (luaState, value); +// lua_settable (luaState, -3); +//} +// +//void push_tgl_peer_type (int x) { +// switch (x) { +// case TGL_PEER_USER: +// lua_pushstring (luaState, "user"); +// break; +// case TGL_PEER_CHAT: +// lua_pushstring (luaState, "chat"); +// break; +// case TGL_PEER_ENCR_CHAT: +// lua_pushstring (luaState, "encr_chat"); +// break; +// default: +// assert (0); +// } +//} +// +//void push_user (tgl_peer_t *P) { +// my_lua_checkstack (luaState, 4); +// lua_add_string_field ("first_name", P->user.first_name); +// lua_add_string_field ("last_name", P->user.last_name); +// lua_add_string_field ("real_first_name", P->user.real_first_name); +// lua_add_string_field ("real_last_name", P->user.real_last_name); +// lua_add_string_field ("phone", P->user.phone); +// if (P->user.access_hash) { +// lua_add_num_field ("access_hash", 1); +// } +//} +// +//void push_chat (tgl_peer_t *P) { +// my_lua_checkstack (luaState, 4); +// assert (P->chat.title); +// lua_add_string_field ("title", P->chat.title); +// lua_add_num_field ("members_num", P->chat.users_num); +// if (P->chat.user_list) { +// lua_pushstring (luaState, "members"); +// lua_newtable (luaState); +// int i; +// for (i = 0; i < P->chat.users_num; i++) { +// lua_pushnumber (luaState, i); +// tgl_peer_id_t id = TGL_MK_USER (P->chat.user_list[i].user_id); +// push_peer (id, tgl_peer_get (TLS, id)); +// lua_settable (luaState, -3); +// } +// lua_settable (luaState, -3); +// } +//} +// +//void push_encr_chat (tgl_peer_t *P) { +// my_lua_checkstack (luaState, 4); +// lua_pushstring (luaState, "user"); +// push_peer (TGL_MK_USER (P->encr_chat.user_id), tgl_peer_get (TLS, TGL_MK_USER (P->encr_chat.user_id))); +// lua_settable (luaState, -3); +//} +// +//void push_update_types (unsigned flags) { +// my_lua_checkstack (luaState, 4); +// lua_newtable (luaState); +// int cc = 0; +// +// +// if (flags & TGL_UPDATE_CREATED) { +// lua_add_string_field_arr (cc++, "created"); +// } +// if (flags & TGL_UPDATE_DELETED) { +// lua_add_string_field_arr (cc++, "deleted"); +// } +// if (flags & TGL_UPDATE_PHONE) { +// lua_add_string_field_arr (cc++, "phone"); +// } +// if (flags & TGL_UPDATE_CONTACT) { +// lua_add_string_field_arr (cc++, "contact"); +// } +// if (flags & TGL_UPDATE_PHOTO) { +// lua_add_string_field_arr (cc++, "photo"); +// } +// if (flags & TGL_UPDATE_BLOCKED) { +// lua_add_string_field_arr (cc++, "blocked"); +// } +// if (flags & TGL_UPDATE_REAL_NAME) { +// lua_add_string_field_arr (cc++, "real_name"); +// } +// if (flags & TGL_UPDATE_NAME) { +// lua_add_string_field_arr (cc++, "name"); +// } +// if (flags & TGL_UPDATE_REQUESTED) { +// lua_add_string_field_arr (cc++, "requested"); +// } +// if (flags & TGL_UPDATE_WORKING) { +// lua_add_string_field_arr (cc++, "working"); +// } +// if (flags & TGL_UPDATE_FLAGS) { +// lua_add_string_field_arr (cc++, "flags"); +// } +// if (flags & TGL_UPDATE_TITLE) { +// lua_add_string_field_arr (cc++, "title"); +// } +// if (flags & TGL_UPDATE_ADMIN) { +// lua_add_string_field_arr (cc++, "admin"); +// } +// if (flags & TGL_UPDATE_MEMBERS) { +// lua_add_string_field_arr (cc++, "members"); +// } +// if (flags & TGL_UPDATE_ACCESS_HASH) { +// lua_add_string_field_arr (cc++, "access_hash"); +// } +// if (flags & TGL_UPDATE_USERNAME) { +// lua_add_string_field_arr (cc++, "username"); +// } +// +//} +// +//void push_peer (tgl_peer_id_t id, tgl_peer_t *P) { +// lua_newtable (luaState); +// +// lua_add_num_field ("id", tgl_get_peer_id (id)); +// lua_pushstring (luaState, "type"); +// push_tgl_peer_type (tgl_get_peer_type (id)); +// lua_settable (luaState, -3); +// +// +// if (!P || !(P->flags & FLAG_CREATED)) { +// lua_pushstring (luaState, "print_name"); +// static char s[100]; +// switch (tgl_get_peer_type (id)) { +// case TGL_PEER_USER: +// sprintf (s, "user#%d", tgl_get_peer_id (id)); +// break; +// case TGL_PEER_CHAT: +// sprintf (s, "chat#%d", tgl_get_peer_id (id)); +// break; +// case TGL_PEER_ENCR_CHAT: +// sprintf (s, "encr_chat#%d", tgl_get_peer_id (id)); +// break; +// default: +// assert (0); +// } +// lua_pushstring (luaState, s); +// lua_settable (luaState, -3); // flags +// +// return; +// } +// +// lua_add_string_field ("print_name", P->print_name); +// lua_add_num_field ("flags", P->flags); +// +// switch (tgl_get_peer_type (id)) { +// case TGL_PEER_USER: +// push_user (P); +// break; +// case TGL_PEER_CHAT: +// push_chat (P); +// break; +// case TGL_PEER_ENCR_CHAT: +// push_encr_chat (P); +// break; +// default: +// assert (0); +// } +//} +// +//void push_media (struct tgl_message_media *M) { +// my_lua_checkstack (luaState, 4); +// +// switch (M->type) { +// case tgl_message_media_photo: +// case tgl_message_media_photo_encr: +// lua_newtable (luaState); +// lua_add_string_field ("type", "photo"); +// break; +// /*case tgl_message_media_video: +// case tgl_message_media_video_encr: +// lua_newtable (luaState); +// lua_add_string_field ("type", "video"); +// break; +// case tgl_message_media_audio: +// case tgl_message_media_audio_encr: +// lua_newtable (luaState); +// lua_add_string_field ("type", "audio"); +// break;*/ +// case tgl_message_media_document: +// case tgl_message_media_document_encr: +// lua_newtable (luaState); +// lua_add_string_field ("type", "document"); +// break; +// case tgl_message_media_unsupported: +// lua_newtable (luaState); +// lua_add_string_field ("type", "unsupported"); +// break; +// case tgl_message_media_geo: +// lua_newtable (luaState); +// lua_add_string_field ("type", "geo"); +// lua_add_num_field ("longitude", M->geo.longitude); +// lua_add_num_field ("latitude", M->geo.latitude); +// break; +// case tgl_message_media_contact: +// lua_newtable (luaState); +// lua_add_string_field ("type", "contact"); +// lua_add_string_field ("phone", M->phone); +// lua_add_string_field ("first_name", M->first_name); +// lua_add_string_field ("last_name", M->last_name); +// lua_add_num_field ("user_id", M->user_id); +// break; +// default: +// lua_pushstring (luaState, "???"); +// } +//} +// +//void push_message (struct tgl_message *M) { +// assert (M); +// my_lua_checkstack (luaState, 10); +// lua_newtable (luaState); +// +// static char s[30]; +// snprintf (s, 30, "%lld", M->id); +// lua_add_string_field ("id", s); +// if (!(M->flags & FLAG_CREATED)) { return; } +// lua_add_num_field ("flags", M->flags); +// +// if (tgl_get_peer_type (M->fwd_from_id)) { +// lua_pushstring (luaState, "fwd_from"); +// push_peer (M->fwd_from_id, tgl_peer_get (TLS, M->fwd_from_id)); +// lua_settable (luaState, -3); // fwd_from +// +// lua_add_num_field ("fwd_date", M->fwd_date); +// } +// +// lua_pushstring (luaState, "from"); +// push_peer (M->from_id, tgl_peer_get (TLS, M->from_id)); +// lua_settable (luaState, -3); +// +// lua_pushstring (luaState, "to"); +// push_peer (M->to_id, tgl_peer_get (TLS, M->to_id)); +// lua_settable (luaState, -3); +// +// lua_pushstring (luaState, "out"); +// lua_pushboolean (luaState, M->out); +// lua_settable (luaState, -3); +// +// lua_pushstring (luaState, "unread"); +// lua_pushboolean (luaState, M->unread); +// lua_settable (luaState, -3); +// +// lua_pushstring (luaState, "date"); +// lua_pushnumber (luaState, M->date); +// lua_settable (luaState, -3); +// +// lua_pushstring (luaState, "service"); +// lua_pushboolean (luaState, M->service); +// lua_settable (luaState, -3); +// +// if (!M->service) { +// if (M->message_len && M->message) { +// lua_pushstring (luaState, "text"); +// lua_pushlstring (luaState, M->message, M->message_len); +// lua_settable (luaState, -3); +// } +// if (M->media.type && M->media.type != tgl_message_media_none) { +// lua_pushstring (luaState, "media"); +// push_media (&M->media); +// lua_settable (luaState, -3); +// } +// } +//} +// +//void lua_binlog_end (void) { +// if (!have_file) { return; } +// lua_settop (luaState, 0); +// //lua_checkstack (luaState, 20); +// my_lua_checkstack (luaState, 20); +// lua_getglobal (luaState, "on_binlog_replay_end"); +// assert (lua_gettop (luaState) == 1); +// +// int r = lua_pcall (luaState, 0, 0, 0); +// if (r) { +// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); +// } +//} +// +//void lua_diff_end (void) { +// if (!have_file) { return; } +// lua_settop (luaState, 0); +// //lua_checkstack (luaState, 20); +// my_lua_checkstack (luaState, 20); +// lua_getglobal (luaState, "on_get_difference_end"); +// assert (lua_gettop (luaState) == 1); +// +// int r = lua_pcall (luaState, 0, 0, 0); +// if (r) { +// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); +// } +//} +// +void py_our_id (int id) { +// if (!have_file) { return; } +// lua_settop (luaState, 0); +// //lua_checkstack (luaState, 20); +// my_lua_checkstack (luaState, 20); +// lua_getglobal (luaState, "on_our_id"); +// lua_pushnumber (luaState, id); +// assert (lua_gettop (luaState) == 2); +// +// int r = lua_pcall (luaState, 1, 0, 0); +// if (r) { +// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); +// } } -void lua_add_string_field_arr (int num, const char *value) { - if (!value || !strlen (value)) { return; } - my_lua_checkstack (luaState, 3); - lua_pushnumber (luaState, num); - lua_pushstring (luaState, value); - lua_settable (luaState, -3); +void py_new_msg (struct tgl_message *M) { +// if (!have_file) { return; } +// lua_settop (luaState, 0); +// //lua_checkstack (luaState, 20); +// my_lua_checkstack (luaState, 20); +// lua_getglobal (luaState, "on_msg_receive"); +// push_message (M); +// assert (lua_gettop (luaState) == 2); +// +// int r = lua_pcall (luaState, 1, 0, 0); +// if (r) { +// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); +// } } -void lua_add_num_field (const char *name, double value) { - assert (name && strlen (name)); - my_lua_checkstack (luaState, 3); - lua_pushstring (luaState, name); - lua_pushnumber (luaState, value); - lua_settable (luaState, -3); +void py_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) { +// if (!have_file) { return; } +// lua_settop (luaState, 0); +// //lua_checkstack (luaState, 20); +// my_lua_checkstack (luaState, 20); +// lua_getglobal (luaState, "on_secret_chat_update"); +// push_peer (C->id, (void *)C); +// push_update_types (flags); +// assert (lua_gettop (luaState) == 3); +// +// int r = lua_pcall (luaState, 2, 0, 0); +// if (r) { +// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); +// } } -void push_tgl_peer_type (int x) { - switch (x) { - case TGL_PEER_USER: - lua_pushstring (luaState, "user"); - break; - case TGL_PEER_CHAT: - lua_pushstring (luaState, "chat"); - break; - case TGL_PEER_ENCR_CHAT: - lua_pushstring (luaState, "encr_chat"); - break; - default: - assert (0); - } +void py_user_update (struct tgl_user *U, unsigned flags) { +// if (!have_file) { return; } +// lua_settop (luaState, 0); +// //lua_checkstack (luaState, 20); +// my_lua_checkstack (luaState, 20); +// lua_getglobal (luaState, "on_user_update"); +// push_peer (U->id, (void *)U); +// push_update_types (flags); +// assert (lua_gettop (luaState) == 3); +// +// int r = lua_pcall (luaState, 2, 0, 0); +// if (r) { +// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); +// } } -void push_user (tgl_peer_t *P) { - my_lua_checkstack (luaState, 4); - lua_add_string_field ("first_name", P->user.first_name); - lua_add_string_field ("last_name", P->user.last_name); - lua_add_string_field ("real_first_name", P->user.real_first_name); - lua_add_string_field ("real_last_name", P->user.real_last_name); - lua_add_string_field ("phone", P->user.phone); - if (P->user.access_hash) { - lua_add_num_field ("access_hash", 1); - } +void py_chat_update (struct tgl_chat *C, unsigned flags) { +// if (!have_file) { return; } +// lua_settop (luaState, 0); +// //lua_checkstack (luaState, 20); +// my_lua_checkstack (luaState, 20); +// lua_getglobal (luaState, "on_chat_update"); +// push_peer (C->id, (void *)C); +// push_update_types (flags); +// assert (lua_gettop (luaState) == 3); +// +// int r = lua_pcall (luaState, 2, 0, 0); +// if (r) { +// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); +// } } - -void push_chat (tgl_peer_t *P) { - my_lua_checkstack (luaState, 4); - assert (P->chat.title); - lua_add_string_field ("title", P->chat.title); - lua_add_num_field ("members_num", P->chat.users_num); - if (P->chat.user_list) { - lua_pushstring (luaState, "members"); - lua_newtable (luaState); - int i; - for (i = 0; i < P->chat.users_num; i++) { - lua_pushnumber (luaState, i); - tgl_peer_id_t id = TGL_MK_USER (P->chat.user_list[i].user_id); - push_peer (id, tgl_peer_get (TLS, id)); - lua_settable (luaState, -3); - } - lua_settable (luaState, -3); - } -} - -void push_encr_chat (tgl_peer_t *P) { - my_lua_checkstack (luaState, 4); - lua_pushstring (luaState, "user"); - push_peer (TGL_MK_USER (P->encr_chat.user_id), tgl_peer_get (TLS, TGL_MK_USER (P->encr_chat.user_id))); - lua_settable (luaState, -3); -} - -void push_update_types (unsigned flags) { - my_lua_checkstack (luaState, 4); - lua_newtable (luaState); - int cc = 0; - - - if (flags & TGL_UPDATE_CREATED) { - lua_add_string_field_arr (cc++, "created"); - } - if (flags & TGL_UPDATE_DELETED) { - lua_add_string_field_arr (cc++, "deleted"); - } - if (flags & TGL_UPDATE_PHONE) { - lua_add_string_field_arr (cc++, "phone"); - } - if (flags & TGL_UPDATE_CONTACT) { - lua_add_string_field_arr (cc++, "contact"); - } - if (flags & TGL_UPDATE_PHOTO) { - lua_add_string_field_arr (cc++, "photo"); - } - if (flags & TGL_UPDATE_BLOCKED) { - lua_add_string_field_arr (cc++, "blocked"); - } - if (flags & TGL_UPDATE_REAL_NAME) { - lua_add_string_field_arr (cc++, "real_name"); - } - if (flags & TGL_UPDATE_NAME) { - lua_add_string_field_arr (cc++, "name"); - } - if (flags & TGL_UPDATE_REQUESTED) { - lua_add_string_field_arr (cc++, "requested"); - } - if (flags & TGL_UPDATE_WORKING) { - lua_add_string_field_arr (cc++, "working"); - } - if (flags & TGL_UPDATE_FLAGS) { - lua_add_string_field_arr (cc++, "flags"); - } - if (flags & TGL_UPDATE_TITLE) { - lua_add_string_field_arr (cc++, "title"); - } - if (flags & TGL_UPDATE_ADMIN) { - lua_add_string_field_arr (cc++, "admin"); - } - if (flags & TGL_UPDATE_MEMBERS) { - lua_add_string_field_arr (cc++, "members"); - } - if (flags & TGL_UPDATE_ACCESS_HASH) { - lua_add_string_field_arr (cc++, "access_hash"); - } - if (flags & TGL_UPDATE_USERNAME) { - lua_add_string_field_arr (cc++, "username"); - } - -} - -void push_peer (tgl_peer_id_t id, tgl_peer_t *P) { - lua_newtable (luaState); - - lua_add_num_field ("id", tgl_get_peer_id (id)); - lua_pushstring (luaState, "type"); - push_tgl_peer_type (tgl_get_peer_type (id)); - lua_settable (luaState, -3); - - - if (!P || !(P->flags & FLAG_CREATED)) { - lua_pushstring (luaState, "print_name"); - static char s[100]; - switch (tgl_get_peer_type (id)) { - case TGL_PEER_USER: - sprintf (s, "user#%d", tgl_get_peer_id (id)); - break; - case TGL_PEER_CHAT: - sprintf (s, "chat#%d", tgl_get_peer_id (id)); - break; - case TGL_PEER_ENCR_CHAT: - sprintf (s, "encr_chat#%d", tgl_get_peer_id (id)); - break; - default: - assert (0); - } - lua_pushstring (luaState, s); - lua_settable (luaState, -3); // flags - - return; - } - - lua_add_string_field ("print_name", P->print_name); - lua_add_num_field ("flags", P->flags); - - switch (tgl_get_peer_type (id)) { - case TGL_PEER_USER: - push_user (P); - break; - case TGL_PEER_CHAT: - push_chat (P); - break; - case TGL_PEER_ENCR_CHAT: - push_encr_chat (P); - break; - default: - assert (0); - } -} - -void push_media (struct tgl_message_media *M) { - my_lua_checkstack (luaState, 4); - - switch (M->type) { - case tgl_message_media_photo: - case tgl_message_media_photo_encr: - lua_newtable (luaState); - lua_add_string_field ("type", "photo"); - break; - /*case tgl_message_media_video: - case tgl_message_media_video_encr: - lua_newtable (luaState); - lua_add_string_field ("type", "video"); - break; - case tgl_message_media_audio: - case tgl_message_media_audio_encr: - lua_newtable (luaState); - lua_add_string_field ("type", "audio"); - break;*/ - case tgl_message_media_document: - case tgl_message_media_document_encr: - lua_newtable (luaState); - lua_add_string_field ("type", "document"); - break; - case tgl_message_media_unsupported: - lua_newtable (luaState); - lua_add_string_field ("type", "unsupported"); - break; - case tgl_message_media_geo: - lua_newtable (luaState); - lua_add_string_field ("type", "geo"); - lua_add_num_field ("longitude", M->geo.longitude); - lua_add_num_field ("latitude", M->geo.latitude); - break; - case tgl_message_media_contact: - lua_newtable (luaState); - lua_add_string_field ("type", "contact"); - lua_add_string_field ("phone", M->phone); - lua_add_string_field ("first_name", M->first_name); - lua_add_string_field ("last_name", M->last_name); - lua_add_num_field ("user_id", M->user_id); - break; - default: - lua_pushstring (luaState, "???"); - } -} - -void push_message (struct tgl_message *M) { - assert (M); - my_lua_checkstack (luaState, 10); - lua_newtable (luaState); - - static char s[30]; - snprintf (s, 30, "%lld", M->id); - lua_add_string_field ("id", s); - if (!(M->flags & FLAG_CREATED)) { return; } - lua_add_num_field ("flags", M->flags); - - if (tgl_get_peer_type (M->fwd_from_id)) { - lua_pushstring (luaState, "fwd_from"); - push_peer (M->fwd_from_id, tgl_peer_get (TLS, M->fwd_from_id)); - lua_settable (luaState, -3); // fwd_from - - lua_add_num_field ("fwd_date", M->fwd_date); - } - - lua_pushstring (luaState, "from"); - push_peer (M->from_id, tgl_peer_get (TLS, M->from_id)); - lua_settable (luaState, -3); - - lua_pushstring (luaState, "to"); - push_peer (M->to_id, tgl_peer_get (TLS, M->to_id)); - lua_settable (luaState, -3); - - lua_pushstring (luaState, "out"); - lua_pushboolean (luaState, M->out); - lua_settable (luaState, -3); - - lua_pushstring (luaState, "unread"); - lua_pushboolean (luaState, M->unread); - lua_settable (luaState, -3); - - lua_pushstring (luaState, "date"); - lua_pushnumber (luaState, M->date); - lua_settable (luaState, -3); - - lua_pushstring (luaState, "service"); - lua_pushboolean (luaState, M->service); - lua_settable (luaState, -3); - - if (!M->service) { - if (M->message_len && M->message) { - lua_pushstring (luaState, "text"); - lua_pushlstring (luaState, M->message, M->message_len); - lua_settable (luaState, -3); - } - if (M->media.type && M->media.type != tgl_message_media_none) { - lua_pushstring (luaState, "media"); - push_media (&M->media); - lua_settable (luaState, -3); - } - } -} - -void lua_binlog_end (void) { - if (!have_file) { return; } - lua_settop (luaState, 0); - //lua_checkstack (luaState, 20); - my_lua_checkstack (luaState, 20); - lua_getglobal (luaState, "on_binlog_replay_end"); - assert (lua_gettop (luaState) == 1); - - int r = lua_pcall (luaState, 0, 0, 0); - if (r) { - logprintf ("lua: %s\n", lua_tostring (luaState, -1)); - } -} - -void lua_diff_end (void) { - if (!have_file) { return; } - lua_settop (luaState, 0); - //lua_checkstack (luaState, 20); - my_lua_checkstack (luaState, 20); - lua_getglobal (luaState, "on_get_difference_end"); - assert (lua_gettop (luaState) == 1); - - int r = lua_pcall (luaState, 0, 0, 0); - if (r) { - logprintf ("lua: %s\n", lua_tostring (luaState, -1)); - } -} - -void lua_our_id (int id) { - if (!have_file) { return; } - lua_settop (luaState, 0); - //lua_checkstack (luaState, 20); - my_lua_checkstack (luaState, 20); - lua_getglobal (luaState, "on_our_id"); - lua_pushnumber (luaState, id); - assert (lua_gettop (luaState) == 2); - - int r = lua_pcall (luaState, 1, 0, 0); - if (r) { - logprintf ("lua: %s\n", lua_tostring (luaState, -1)); - } -} - -void lua_new_msg (struct tgl_message *M) { - if (!have_file) { return; } - lua_settop (luaState, 0); - //lua_checkstack (luaState, 20); - my_lua_checkstack (luaState, 20); - lua_getglobal (luaState, "on_msg_receive"); - push_message (M); - assert (lua_gettop (luaState) == 2); - - int r = lua_pcall (luaState, 1, 0, 0); - if (r) { - logprintf ("lua: %s\n", lua_tostring (luaState, -1)); - } -} - -void lua_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) { - if (!have_file) { return; } - lua_settop (luaState, 0); - //lua_checkstack (luaState, 20); - my_lua_checkstack (luaState, 20); - lua_getglobal (luaState, "on_secret_chat_update"); - push_peer (C->id, (void *)C); - push_update_types (flags); - assert (lua_gettop (luaState) == 3); - - int r = lua_pcall (luaState, 2, 0, 0); - if (r) { - logprintf ("lua: %s\n", lua_tostring (luaState, -1)); - } -} - -void lua_user_update (struct tgl_user *U, unsigned flags) { - if (!have_file) { return; } - lua_settop (luaState, 0); - //lua_checkstack (luaState, 20); - my_lua_checkstack (luaState, 20); - lua_getglobal (luaState, "on_user_update"); - push_peer (U->id, (void *)U); - push_update_types (flags); - assert (lua_gettop (luaState) == 3); - - int r = lua_pcall (luaState, 2, 0, 0); - if (r) { - logprintf ("lua: %s\n", lua_tostring (luaState, -1)); - } -} - -void lua_chat_update (struct tgl_chat *C, unsigned flags) { - if (!have_file) { return; } - lua_settop (luaState, 0); - //lua_checkstack (luaState, 20); - my_lua_checkstack (luaState, 20); - lua_getglobal (luaState, "on_chat_update"); - push_peer (C->id, (void *)C); - push_update_types (flags); - assert (lua_gettop (luaState) == 3); - - int r = lua_pcall (luaState, 2, 0, 0); - if (r) { - logprintf ("lua: %s\n", lua_tostring (luaState, -1)); - } -} - -//extern tgl_peer_t *Peers[]; -//extern int peer_num; - -#define MAX_LUA_COMMANDS 1000 -void *lua_ptr[MAX_LUA_COMMANDS]; -static int pos; - -static inline tgl_peer_t *get_peer (const char *s) { - return tgl_peer_get_by_name (TLS, s); -} - -enum lua_query_type { - lq_contact_list, - lq_dialog_list, - lq_msg, - lq_send_typing, - lq_send_typing_abort, - lq_rename_chat, - lq_send_photo, - lq_chat_set_photo, - lq_set_profile_photo, - lq_set_profile_name, - lq_send_video, - lq_send_text, - lq_fwd, - lq_fwd_media, - lq_load_photo, - lq_load_video_thumb, - lq_load_video, - lq_chat_info, - lq_user_info, - lq_history, - lq_chat_add_user, - lq_chat_del_user, - lq_add_contact, - lq_del_contact, - lq_rename_contact, - lq_search, - lq_global_search, - lq_mark_read, - lq_create_secret_chat, - lq_create_group_chat, - lq_send_audio, - lq_send_document, - lq_send_file, - lq_load_audio, - lq_load_document, - lq_load_document_thumb, - lq_delete_msg, - lq_restore_msg, - lq_accept_secret_chat, - lq_send_contact, - lq_status_online, - lq_status_offline, - lq_send_location, - lq_extf -}; - -struct lua_query_extra { - int func; - int param; -}; - -void lua_empty_cb (struct tgl_state *TLSR, void *cb_extra, int success) { - assert (TLSR == TLS); - struct lua_query_extra *cb = cb_extra; - lua_settop (luaState, 0); - //lua_checkstack (luaState, 20); - my_lua_checkstack (luaState, 20); - - lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); - lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); - - lua_pushnumber (luaState, success); - - assert (lua_gettop (luaState) == 3); - - int r = lua_pcall (luaState, 2, 0, 0); - - luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); - luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); - - if (r) { - logprintf ("lua: %s\n", lua_tostring (luaState, -1)); - } - - free (cb); -} - -void lua_contact_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_user **UL) { - assert (TLSR == TLS); - struct lua_query_extra *cb = cb_extra; - lua_settop (luaState, 0); - //lua_checkstack (luaState, 20); - my_lua_checkstack (luaState, 20); - - lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); - lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); - - lua_pushnumber (luaState, success); - - if (success) { - lua_newtable (luaState); - int i; - for (i = 0; i < num; i++) { - lua_pushnumber (luaState, i); - push_peer (UL[i]->id, (void *)UL[i]); - lua_settable (luaState, -3); - } - } else { - lua_pushboolean (luaState, 0); - } - - assert (lua_gettop (luaState) == 4); - - int r = lua_pcall (luaState, 3, 0, 0); - - luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); - luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); - - if (r) { - logprintf ("lua: %s\n", lua_tostring (luaState, -1)); - } - - free (cb); -} - -void lua_dialog_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, tgl_peer_id_t peers[], int msgs[], int unread[]) { - assert (TLSR == TLS); - struct lua_query_extra *cb = cb_extra; - lua_settop (luaState, 0); - //lua_checkstack (luaState, 20); - my_lua_checkstack (luaState, 20); - - lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); - lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); - - lua_pushnumber (luaState, success); - if (success) { - lua_newtable (luaState); - int i; - for (i = 0; i < num; i++) { - lua_pushnumber (luaState, i); - - lua_newtable (luaState); - - lua_pushstring (luaState, "peer"); - push_peer (peers[i], tgl_peer_get (TLS, peers[i])); - lua_settable (luaState, -3); - - struct tgl_message *M = tgl_message_get (TLS, msgs[i]); - if (M && (M->flags & FLAG_CREATED)) { - lua_pushstring (luaState, "message"); - push_message (M); - lua_settable (luaState, -3); - } - - lua_pushstring (luaState, "unread"); - lua_pushnumber (luaState, unread[i]); - lua_settable (luaState, -3); - - lua_settable (luaState, -3); - } - } else { - lua_pushboolean (luaState, 0); - } - assert (lua_gettop (luaState) == 4); - - - int r = lua_pcall (luaState, 3, 0, 0); - - luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); - luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); - - if (r) { - logprintf ("lua: %s\n", lua_tostring (luaState, -1)); - } - - free (cb); -} - -void lua_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_message *M) { - assert (TLSR == TLS); - struct lua_query_extra *cb = cb_extra; - lua_settop (luaState, 0); - //lua_checkstack (luaState, 20); - my_lua_checkstack (luaState, 20); - - lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); - lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); - - lua_pushnumber (luaState, success); - - if (success) { - push_message (M); - } else { - lua_pushboolean (luaState, 0); - } - - assert (lua_gettop (luaState) == 4); - - int r = lua_pcall (luaState, 3, 0, 0); - - luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); - luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); - - if (r) { - logprintf ("lua: %s\n", lua_tostring (luaState, -1)); - } - - free (cb); -} - -void lua_msg_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_message *M[]) { - assert (TLSR == TLS); - struct lua_query_extra *cb = cb_extra; - lua_settop (luaState, 0); - //lua_checkstack (luaState, 20); - my_lua_checkstack (luaState, 20); - - lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); - lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); - - lua_pushnumber (luaState, success); - - if (success) { - lua_newtable (luaState); - int i; - for (i = 0; i < num; i++) { - lua_pushnumber (luaState, i); - push_message (M[i]); - lua_settable (luaState, -3); - } - } else { - lua_pushboolean (luaState, 0); - } - - assert (lua_gettop (luaState) == 4); - - int r = lua_pcall (luaState, 3, 0, 0); - - luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); - luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); - - if (r) { - logprintf ("lua: %s\n", lua_tostring (luaState, -1)); - } - - free (cb); -} - -void lua_file_cb (struct tgl_state *TLSR, void *cb_extra, int success, char *file_name) { - assert (TLSR == TLS); - struct lua_query_extra *cb = cb_extra; - lua_settop (luaState, 0); - //lua_checkstack (luaState, 20); - my_lua_checkstack (luaState, 20); - - lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); - lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); - - lua_pushnumber (luaState, success); - - if (success) { - lua_pushstring (luaState, file_name); - } else { - lua_pushboolean (luaState, 0); - } - - assert (lua_gettop (luaState) == 4); - - int r = lua_pcall (luaState, 3, 0, 0); - - luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); - luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); - - if (r) { - logprintf ("lua: %s\n", lua_tostring (luaState, -1)); - } - - free (cb); -} - -void lua_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_chat *C) { - assert (TLSR == TLS); - struct lua_query_extra *cb = cb_extra; - lua_settop (luaState, 0); - //lua_checkstack (luaState, 20); - my_lua_checkstack (luaState, 20); - - lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); - lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); - - lua_pushnumber (luaState, success); - - if (success) { - push_peer (C->id, (void *)C); - } else { - lua_pushboolean (luaState, 0); - } - - assert (lua_gettop (luaState) == 4); - - int r = lua_pcall (luaState, 3, 0, 0); - - luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); - luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); - - if (r) { - logprintf ("lua: %s\n", lua_tostring (luaState, -1)); - } - - free (cb); -} - -void lua_secret_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_secret_chat *C) { - assert (TLSR == TLS); - struct lua_query_extra *cb = cb_extra; - lua_settop (luaState, 0); - //lua_checkstack (luaState, 20); - my_lua_checkstack (luaState, 20); - - lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); - lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); - - lua_pushnumber (luaState, success); - - if (success) { - push_peer (C->id, (void *)C); - } else { - lua_pushboolean (luaState, 0); - } - - assert (lua_gettop (luaState) == 4); - - int r = lua_pcall (luaState, 3, 0, 0); - - luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); - luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); - - if (r) { - logprintf ("lua: %s\n", lua_tostring (luaState, -1)); - } - - free (cb); -} - -void lua_user_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_user *C) { - assert (TLSR == TLS); - struct lua_query_extra *cb = cb_extra; - lua_settop (luaState, 0); - //lua_checkstack (luaState, 20); - my_lua_checkstack (luaState, 20); - - lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); - lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); - - lua_pushnumber (luaState, success); - - if (success) { - push_peer (C->id, (void *)C); - } else { - lua_pushboolean (luaState, 0); - } - - assert (lua_gettop (luaState) == 4); - - int r = lua_pcall (luaState, 3, 0, 0); - - luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); - luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); - - if (r) { - logprintf ("lua: %s\n", lua_tostring (luaState, -1)); - } - - free (cb); -} - -void lua_str_cb (struct tgl_state *TLSR, void *cb_extra, int success, char *data) { - assert (TLSR == TLS); - struct lua_query_extra *cb = cb_extra; - lua_settop (luaState, 0); - //lua_checkstack (luaState, 20); - my_lua_checkstack (luaState, 20); - - lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); - lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); - - lua_pushnumber (luaState, success); - - if (success) { - lua_pushstring (luaState, data); - } else { - lua_pushboolean (luaState, 0); - } - - assert (lua_gettop (luaState) == 4); - - int r = lua_pcall (luaState, 3, 0, 0); - - luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); - luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); - - if (r) { - logprintf ("lua: %s\n", lua_tostring (luaState, -1)); - } - - free (cb); -} - -void lua_do_all (void) { - int p = 0; - while (p < pos) { - int l = (long)lua_ptr[p ++]; - assert (p + l + 1 <= pos); - enum lua_query_type f = (long)lua_ptr[p ++]; - struct tgl_message *M; - char *s, *s1, *s2, *s3; - switch (f) { - case lq_contact_list: - tgl_do_update_contact_list (TLS, lua_contact_list_cb, lua_ptr[p ++]); - break; - case lq_dialog_list: - tgl_do_get_dialog_list (TLS, lua_dialog_list_cb, lua_ptr[p ++]); - break; - case lq_msg: - tgl_do_send_message (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], strlen (lua_ptr[p + 2]), lua_msg_cb, lua_ptr[p]); - free (lua_ptr[p + 2]); - p += 3; - break; - case lq_send_typing: - tgl_do_send_typing (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, tgl_typing_typing, lua_empty_cb, lua_ptr[p]); - p += 2; - break; - case lq_send_typing_abort: - tgl_do_send_typing (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, tgl_typing_cancel, lua_empty_cb, lua_ptr[p]); - p += 2; - break; - case lq_rename_chat: - tgl_do_rename_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); - free (lua_ptr[p + 2]); - p += 3; - break; - case lq_send_photo: - tgl_do_send_document (TLS, -1, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); - free (lua_ptr[p + 2]); - p += 3; - break; - case lq_send_video: - tgl_do_send_document (TLS, FLAG_DOCUMENT_VIDEO, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); - free (lua_ptr[p + 2]); - p += 3; - break; - case lq_send_audio: - tgl_do_send_document (TLS, FLAG_DOCUMENT_AUDIO, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); - free (lua_ptr[p + 2]); - p += 3; - break; - case lq_send_document: - tgl_do_send_document (TLS, 0, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); - free (lua_ptr[p + 2]); - p += 3; - break; - case lq_send_file: - tgl_do_send_document (TLS, -2, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); - free (lua_ptr[p + 2]); - p += 3; - break; - case lq_send_text: - tgl_do_send_text (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); - free (lua_ptr[p + 2]); - p += 3; - break; - case lq_chat_set_photo: - tgl_do_set_chat_photo (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); - free (lua_ptr[p + 2]); - p += 3; - break; - case lq_load_photo: - case lq_load_video: - case lq_load_audio: - case lq_load_document: - M = lua_ptr[p + 1]; - if (!M || (M->media.type != tgl_message_media_photo && M->media.type != tgl_message_media_photo_encr && M->media.type != tgl_message_media_document && M->media.type != tgl_message_media_document_encr)) { - lua_file_cb (TLS, lua_ptr[p], 0, 0); - } else { - if (M->media.type == tgl_message_media_photo) { - tgl_do_load_photo (TLS, &M->media.photo, lua_file_cb, lua_ptr[p]); - } else if (M->media.type == tgl_message_media_document) { - tgl_do_load_document (TLS, &M->media.document, lua_file_cb, lua_ptr[p]); - } else { - tgl_do_load_encr_document (TLS, &M->media.encr_document, lua_file_cb, lua_ptr[p]); - } - } - p += 2; - break; - case lq_load_video_thumb: - case lq_load_document_thumb: - M = lua_ptr[p + 1]; - if (!M || (M->media.type != tgl_message_media_document)) { - lua_file_cb (TLS, lua_ptr[p], 0, 0); - } else { - tgl_do_load_document_thumb (TLS, &M->media.document, lua_file_cb, lua_ptr[p]); - } - p += 2; - break; - case lq_fwd: - tgl_do_forward_message (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, ((struct tgl_message *)lua_ptr[p + 2])->id, lua_msg_cb, lua_ptr[p]); - p += 3; - break; - case lq_fwd_media: - tgl_do_forward_media (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, ((struct tgl_message *)lua_ptr[p + 2])->id, lua_msg_cb, lua_ptr[p]); - p += 3; - break; - case lq_chat_info: - tgl_do_get_chat_info (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, 0, lua_chat_cb, lua_ptr[p]); - p += 2; - break; - case lq_user_info: - tgl_do_get_user_info (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, 0, lua_user_cb, lua_ptr[p]); - p += 2; - break; - case lq_history: - tgl_do_get_history (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, (long)lua_ptr[p + 2], 0, lua_msg_list_cb, lua_ptr[p]); - p += 3; - break; - case lq_chat_add_user: - tgl_do_add_user_to_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, ((tgl_peer_t *)lua_ptr[p + 2])->id, 10, lua_msg_cb, lua_ptr[p]); - p += 3; - break; - case lq_chat_del_user: - tgl_do_del_user_from_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, ((tgl_peer_t *)lua_ptr[p + 2])->id, lua_msg_cb, lua_ptr[p]); - p += 3; - break; - case lq_add_contact: - s1 = lua_ptr[p + 1]; - s2 = lua_ptr[p + 2]; - s3 = lua_ptr[p + 3]; - tgl_do_add_contact (TLS, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), 0, lua_contact_list_cb, lua_ptr[p]); - free (s1); - free (s2); - free (s3); - p += 4; - break; - case lq_del_contact: - tgl_do_del_contact (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_empty_cb, lua_ptr[p]); - p += 2; - break; - case lq_rename_contact: - s1 = lua_ptr[p + 1]; - s2 = lua_ptr[p + 2]; - s3 = lua_ptr[p + 3]; - tgl_do_add_contact (TLS, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), 1, lua_contact_list_cb, lua_ptr[p]); - free (s1); - free (s2); - free (s3); - p += 4; - break; - case lq_search: - s = lua_ptr[p + 2]; - tgl_do_msg_search (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, 0, 0, 40, 0, s, lua_msg_list_cb, lua_ptr[p]); - free (s); - p += 3; - break; - case lq_global_search: - s = lua_ptr[p + 1]; - tgl_do_msg_search (TLS, tgl_set_peer_id (TGL_PEER_UNKNOWN, 0), 0, 0, 40, 0, s, lua_msg_list_cb, lua_ptr[p]); - free (s); - p += 2; - break; - case lq_mark_read: - tgl_do_mark_read (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_empty_cb, lua_ptr[p]); - p += 2; - break; - case lq_set_profile_photo: - s = lua_ptr[p + 1]; - tgl_do_set_profile_photo (TLS, s, lua_empty_cb, lua_ptr[p]); - free (s); - p += 2; - break; - case lq_set_profile_name: - s1 = lua_ptr[p + 1]; - s2 = lua_ptr[p + 1]; - tgl_do_set_profile_name (TLS, s1, s2, lua_user_cb, lua_ptr[p]); - free (s1); - free (s2); - p += 3; - break; - case lq_create_secret_chat: - tgl_do_create_secret_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_secret_chat_cb, lua_ptr[p]); - p += 2; - break; - case lq_create_group_chat: - s = lua_ptr[p + 2]; - tgl_do_create_group_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, s, lua_msg_cb, lua_ptr[p]); - free (s); - p += 3; - break; - case lq_delete_msg: - tgl_do_delete_msg (TLS, ((struct tgl_message *)lua_ptr[p + 1])->id, lua_empty_cb, lua_ptr[p]); - p += 2; - break; - case lq_restore_msg: - tgl_do_delete_msg (TLS, (long)lua_ptr[p + 1], lua_empty_cb, lua_ptr[p]); - p += 2; - break; - case lq_accept_secret_chat: - tgl_do_accept_encr_chat_request (TLS, lua_ptr[p + 1], lua_secret_chat_cb, lua_ptr[p]); - p += 2; - break; - case lq_send_contact: - s1 = lua_ptr[p + 2]; - s2 = lua_ptr[p + 3]; - s3 = lua_ptr[p + 4]; - tgl_do_send_contact (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), lua_msg_cb, lua_ptr[p]); - free (s1); - free (s2); - free (s3); - p += 5; - break; - case lq_status_online: - tgl_do_update_status (TLS, 1, lua_empty_cb, lua_ptr[p]); - p ++; - break; - case lq_status_offline: - tgl_do_update_status (TLS, 0, lua_empty_cb, lua_ptr[p]); - p ++; - break; - case lq_extf: - s = lua_ptr[p + 1]; - tgl_do_send_extf (TLS, s, strlen (s), lua_str_cb, lua_ptr[p]); - free (s); - p += 2; - break; - case lq_send_location: - if (sizeof (void *) == 4) { - tgl_do_send_location (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id , *(float *)(lua_ptr + p + 2), *(float *)(lua_ptr + p + 3), lua_msg_cb, lua_ptr[p]); - } else { - tgl_do_send_location (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id , *(double *)(lua_ptr + p + 2), *(double *)(lua_ptr + p + 3), lua_msg_cb, lua_ptr[p]); - } - p += 4; - break; - /* - lq_delete_msg, - lq_restore_msg, - case 0: - tgl_do_send_message (((tgl_peer_t *)lua_ptr[p])->id, lua_ptr[p + 1], strlen (lua_ptr[p + 1]), 0, 0); - free (lua_ptr[p + 1]); - p += 2; - break; - case 1: - tgl_do_forward_message (((tgl_peer_t *)lua_ptr[p])->id, (long)lua_ptr[p + 1], 0, 0); - p += 2; - break; - case 2: - tgl_do_mark_read (((tgl_peer_t *)lua_ptr[p])->id, 0, 0); - p += 1; - break;*/ - default: - assert (0); - } - } - pos = 0; -} - - -enum lua_function_param { - lfp_none, - lfp_peer, - lfp_chat, - lfp_user, - lfp_secret_chat, - lfp_string, - lfp_number, - lfp_positive_number, - lfp_nonnegative_number, - lfp_msg, - lfp_double -}; - -struct lua_function { - char *name; - enum lua_query_type type; - enum lua_function_param params[10]; -}; - -struct lua_function functions[] = { - {"get_contact_list", lq_contact_list, { lfp_none }}, - {"get_dialog_list", lq_dialog_list, { lfp_none }}, - {"rename_chat", lq_rename_chat, { lfp_chat, lfp_string, lfp_none }}, - {"send_msg", lq_msg, { lfp_peer, lfp_string, lfp_none }}, - {"send_typing", lq_send_typing, { lfp_peer, lfp_none }}, - {"send_typing_abort", lq_send_typing_abort, { lfp_peer, lfp_none }}, - {"send_photo", lq_send_photo, { lfp_peer, lfp_string, lfp_none }}, - {"send_video", lq_send_video, { lfp_peer, lfp_string, lfp_none }}, - {"send_audio", lq_send_audio, { lfp_peer, lfp_string, lfp_none }}, - {"send_document", lq_send_document, { lfp_peer, lfp_string, lfp_none }}, - {"send_file", lq_send_file, { lfp_peer, lfp_string, lfp_none }}, - {"send_text", lq_send_text, { lfp_peer, lfp_string, lfp_none }}, - {"chat_set_photo", lq_chat_set_photo, { lfp_chat, lfp_string, lfp_none }}, - {"load_photo", lq_load_photo, { lfp_msg, lfp_none }}, - {"load_video", lq_load_video, { lfp_msg, lfp_none }}, - {"load_video_thumb", lq_load_video_thumb, { lfp_msg, lfp_none }}, - {"load_audio", lq_load_audio, { lfp_msg, lfp_none }}, - {"load_document", lq_load_document, { lfp_msg, lfp_none }}, - {"load_document_thumb", lq_load_document_thumb, { lfp_msg, lfp_none }}, - {"fwd_msg", lq_fwd, { lfp_peer, lfp_msg, lfp_none }}, - {"fwd_media", lq_fwd_media, { lfp_peer, lfp_msg, lfp_none }}, - {"chat_info", lq_chat_info, { lfp_chat, lfp_none }}, - {"user_info", lq_user_info, { lfp_user, lfp_none }}, - {"get_history", lq_history, { lfp_peer, lfp_nonnegative_number, lfp_none }}, - {"chat_add_user", lq_chat_add_user, { lfp_chat, lfp_user, lfp_none }}, - {"chat_del_user", lq_chat_del_user, { lfp_chat, lfp_user, lfp_none }}, - {"add_contact", lq_add_contact, { lfp_string, lfp_string, lfp_string, lfp_none }}, - {"del_contact", lq_del_contact, { lfp_user, lfp_none }}, - {"rename_contact", lq_rename_contact, { lfp_string, lfp_string, lfp_string, lfp_none }}, - {"msg_search", lq_search, { lfp_peer, lfp_string, lfp_none }}, - {"msg_global_search", lq_global_search, { lfp_string, lfp_none }}, - {"mark_read", lq_mark_read, { lfp_peer, lfp_none }}, - {"set_profile_photo", lq_set_profile_photo, { lfp_string, lfp_none }}, - {"set_profile_name", lq_set_profile_name, { lfp_string, lfp_none }}, - {"create_secret_chat", lq_create_secret_chat, { lfp_user, lfp_none }}, - {"create_group_chat", lq_create_group_chat, { lfp_user, lfp_string, lfp_none }}, - {"delete_msg", lq_delete_msg, { lfp_msg, lfp_none }}, - {"restore_msg", lq_restore_msg, { lfp_positive_number, lfp_none }}, - {"accept_secret_chat", lq_accept_secret_chat, { lfp_secret_chat, lfp_none }}, - {"send_contact", lq_send_contact, { lfp_peer, lfp_string, lfp_string, lfp_string, lfp_none }}, - {"status_online", lq_status_online, { lfp_none }}, - {"status_offline", lq_status_offline, { lfp_none }}, - {"send_location", lq_send_location, { lfp_peer, lfp_double, lfp_double, lfp_none }}, - {"ext_function", lq_extf, { lfp_string, lfp_none }}, - { 0, 0, { lfp_none}} -}; - -static int parse_lua_function (lua_State *L, struct lua_function *F) { - int p = 0; - while (F->params[p] != lfp_none) { p ++; } - if (lua_gettop (L) != p + 2) { - lua_pushboolean (L, 0); - return 1; - } - - int a1 = luaL_ref (L, LUA_REGISTRYINDEX); - int a2 = luaL_ref (L, LUA_REGISTRYINDEX); - - struct lua_query_extra *e = malloc (sizeof (*e)); - assert (e); - e->func = a2; - e->param = a1; - - assert (pos + 3 + p < MAX_LUA_COMMANDS); - - lua_ptr[pos ++] = (void *)(long)(p + 1); - lua_ptr[pos ++] = (void *)(long)F->type; - lua_ptr[pos ++] = e; - - int sp = p; - int ok = 1; - int cc = 0; - while (p > 0) { - p --; - cc ++; - const char *s; - tgl_peer_t *P; - long long num; - double dval; - struct tgl_message *M; - switch (F->params[p]) { - case lfp_none: - assert (0); - break; - case lfp_peer: - case lfp_user: - case lfp_chat: - case lfp_secret_chat: - s = lua_tostring (L, -cc); - if (!s) { - ok = 0; - break; - } - if (sscanf (s, "user#id%lld", &num) == 1 && num > 0) { - tgl_insert_empty_user (TLS, num); - P = tgl_peer_get (TLS, TGL_MK_USER (num)); - } else if (sscanf (s, "chat#id%lld", &num) == 1 && num > 0) { - tgl_insert_empty_chat (TLS, num); - P = tgl_peer_get (TLS, TGL_MK_CHAT (num)); - } else { - P = get_peer (s); - } - if (!P/* || !(P->flags & FLAG_CREATED)*/) { - ok = 0; - break; - } - if (F->params[p] != lfp_peer) { - if ((tgl_get_peer_type (P->id) == TGL_PEER_USER && F->params[p] != lfp_user) || - (tgl_get_peer_type (P->id) == TGL_PEER_CHAT && F->params[p] != lfp_chat) || - (tgl_get_peer_type (P->id) == TGL_PEER_ENCR_CHAT && F->params[p] != lfp_secret_chat)) { - ok = 0; - break; - } - } - lua_ptr[pos + p] = P; - break; - - case lfp_string: - s = lua_tostring (L, -cc); - if (!s) { - ok = 0; - break; - } - lua_ptr[pos + p] = (void *)s; - break; - - case lfp_number: - num = lua_tonumber (L, -cc); - - lua_ptr[pos + p] = (void *)(long)num; - break; - - case lfp_double: - dval = lua_tonumber (L, -cc); - - if (sizeof (void *) == 4) { - *(float *)(lua_ptr + pos + p) = dval; - } else { - assert (sizeof (void *) >= 8); - *(double *)(lua_ptr + pos + p) = dval; - } - break; - - case lfp_positive_number: - num = lua_tonumber (L, -cc); - if (num <= 0) { - ok = 0; - break; - } - - lua_ptr[pos + p] = (void *)(long)num; - break; - - case lfp_nonnegative_number: - num = lua_tonumber (L, -cc); - if (num < 0) { - ok = 0; - break; - } - - lua_ptr[pos + p] = (void *)(long)num; - break; - - case lfp_msg: - s = lua_tostring (L, -cc); - if (!s || !strlen (s)) { - ok = 0; - break; - } - - num = atoll (s); - - M = tgl_message_get (TLS, num); - - if (!M || !(M->flags & FLAG_CREATED)) { - ok = 0; - break; - } - - lua_ptr[pos + p] = M; - break; - - default: - assert (0); - } - } - if (!ok) { - luaL_unref (luaState, LUA_REGISTRYINDEX, a1); - luaL_unref (luaState, LUA_REGISTRYINDEX, a2); - free (e); - pos -= 3; - lua_pushboolean (L, 0); - return 1; - } - - for (p = 0; p < sp; p++) { - if (F->params[p] == lfp_string) { - lua_ptr[pos + p] = strdup (lua_ptr[pos + p]); - } - } - pos += p; - - lua_pushboolean (L, 1); - return 1; -} - - -static void lua_postpone_alarm (evutil_socket_t fd, short what, void *arg) { - int *t = arg; - - lua_settop (luaState, 0); - //lua_checkstack (luaState, 20); - my_lua_checkstack (luaState, 20); - - lua_rawgeti (luaState, LUA_REGISTRYINDEX, t[1]); - lua_rawgeti (luaState, LUA_REGISTRYINDEX, t[0]); - assert (lua_gettop (luaState) == 2); - - int r = lua_pcall (luaState, 1, 0, 0); - - luaL_unref (luaState, LUA_REGISTRYINDEX, t[0]); - luaL_unref (luaState, LUA_REGISTRYINDEX, t[1]); - - if (r) { - logprintf ("lua: %s\n", lua_tostring (luaState, -1)); - } - -} - -static int postpone_from_lua (lua_State *L) { - int n = lua_gettop (L); - if (n != 3) { - lua_pushboolean (L, 0); - return 1; - } - - double timeout = lua_tonumber (L, -1); - if (timeout < 0) { - lua_pushboolean (L, 0); - return 1; - } - - lua_pop (L, 1); - int a1 = luaL_ref (L, LUA_REGISTRYINDEX); - int a2 = luaL_ref (L, LUA_REGISTRYINDEX); - - - int *t = malloc (16); - assert (t); - struct event *ev = evtimer_new (TLS->ev_base, lua_postpone_alarm, t); - t[0] = a1; - t[1] = a2; - *(void **)(t + 2) = ev; - - struct timeval ts= { - .tv_sec = (long)timeout, - .tv_usec = (timeout - ((long)timeout)) * 1000000 - }; - event_add (ev, &ts); - - lua_pushboolean (L, 1); - return 1; -} - -extern int safe_quit; -static int safe_quit_from_lua (lua_State *L) { - int n = lua_gettop (L); - if (n != 0) { - lua_pushboolean (L, 0); - return 1; - } - safe_quit = 1; - - lua_pushboolean (L, 1); - return 1; -} - -static int universal_from_lua (lua_State *L) { - const char *s = lua_tostring(L, lua_upvalueindex(1)); - if (!s) { - lua_pushboolean (L, 0); - return 1; - } - int i = 0; - while (functions[i].name) { - if (!strcmp (functions[i].name, s)) { - return parse_lua_function (L, &functions[i]); - } - i ++; - } - lua_pushboolean (L, 0); - return 1; -} - - -static void my_python_register (const char *name, lua_CFunction f) { - lua_pushstring(L, name); - lua_pushcclosure(L, f, 1); - lua_setglobal(L, name); -} - - +// +////extern tgl_peer_t *Peers[]; +////extern int peer_num; +// +//#define MAX_LUA_COMMANDS 1000 +//void *lua_ptr[MAX_LUA_COMMANDS]; +//static int pos; +// +//static inline tgl_peer_t *get_peer (const char *s) { +// return tgl_peer_get_by_name (TLS, s); +//} +// +//enum lua_query_type { +// lq_contact_list, +// lq_dialog_list, +// lq_msg, +// lq_send_typing, +// lq_send_typing_abort, +// lq_rename_chat, +// lq_send_photo, +// lq_chat_set_photo, +// lq_set_profile_photo, +// lq_set_profile_name, +// lq_send_video, +// lq_send_text, +// lq_fwd, +// lq_fwd_media, +// lq_load_photo, +// lq_load_video_thumb, +// lq_load_video, +// lq_chat_info, +// lq_user_info, +// lq_history, +// lq_chat_add_user, +// lq_chat_del_user, +// lq_add_contact, +// lq_del_contact, +// lq_rename_contact, +// lq_search, +// lq_global_search, +// lq_mark_read, +// lq_create_secret_chat, +// lq_create_group_chat, +// lq_send_audio, +// lq_send_document, +// lq_send_file, +// lq_load_audio, +// lq_load_document, +// lq_load_document_thumb, +// lq_delete_msg, +// lq_restore_msg, +// lq_accept_secret_chat, +// lq_send_contact, +// lq_status_online, +// lq_status_offline, +// lq_send_location, +// lq_extf +//}; +// +//struct lua_query_extra { +// int func; +// int param; +//}; +// +//void lua_empty_cb (struct tgl_state *TLSR, void *cb_extra, int success) { +// assert (TLSR == TLS); +// struct lua_query_extra *cb = cb_extra; +// lua_settop (luaState, 0); +// //lua_checkstack (luaState, 20); +// my_lua_checkstack (luaState, 20); +// +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); +// +// lua_pushnumber (luaState, success); +// +// assert (lua_gettop (luaState) == 3); +// +// int r = lua_pcall (luaState, 2, 0, 0); +// +// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); +// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); +// +// if (r) { +// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); +// } +// +// free (cb); +//} +// +//void lua_contact_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_user **UL) { +// assert (TLSR == TLS); +// struct lua_query_extra *cb = cb_extra; +// lua_settop (luaState, 0); +// //lua_checkstack (luaState, 20); +// my_lua_checkstack (luaState, 20); +// +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); +// +// lua_pushnumber (luaState, success); +// +// if (success) { +// lua_newtable (luaState); +// int i; +// for (i = 0; i < num; i++) { +// lua_pushnumber (luaState, i); +// push_peer (UL[i]->id, (void *)UL[i]); +// lua_settable (luaState, -3); +// } +// } else { +// lua_pushboolean (luaState, 0); +// } +// +// assert (lua_gettop (luaState) == 4); +// +// int r = lua_pcall (luaState, 3, 0, 0); +// +// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); +// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); +// +// if (r) { +// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); +// } +// +// free (cb); +//} +// +//void lua_dialog_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, tgl_peer_id_t peers[], int msgs[], int unread[]) { +// assert (TLSR == TLS); +// struct lua_query_extra *cb = cb_extra; +// lua_settop (luaState, 0); +// //lua_checkstack (luaState, 20); +// my_lua_checkstack (luaState, 20); +// +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); +// +// lua_pushnumber (luaState, success); +// if (success) { +// lua_newtable (luaState); +// int i; +// for (i = 0; i < num; i++) { +// lua_pushnumber (luaState, i); +// +// lua_newtable (luaState); +// +// lua_pushstring (luaState, "peer"); +// push_peer (peers[i], tgl_peer_get (TLS, peers[i])); +// lua_settable (luaState, -3); +// +// struct tgl_message *M = tgl_message_get (TLS, msgs[i]); +// if (M && (M->flags & FLAG_CREATED)) { +// lua_pushstring (luaState, "message"); +// push_message (M); +// lua_settable (luaState, -3); +// } +// +// lua_pushstring (luaState, "unread"); +// lua_pushnumber (luaState, unread[i]); +// lua_settable (luaState, -3); +// +// lua_settable (luaState, -3); +// } +// } else { +// lua_pushboolean (luaState, 0); +// } +// assert (lua_gettop (luaState) == 4); +// +// +// int r = lua_pcall (luaState, 3, 0, 0); +// +// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); +// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); +// +// if (r) { +// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); +// } +// +// free (cb); +//} +// +//void lua_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_message *M) { +// assert (TLSR == TLS); +// struct lua_query_extra *cb = cb_extra; +// lua_settop (luaState, 0); +// //lua_checkstack (luaState, 20); +// my_lua_checkstack (luaState, 20); +// +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); +// +// lua_pushnumber (luaState, success); +// +// if (success) { +// push_message (M); +// } else { +// lua_pushboolean (luaState, 0); +// } +// +// assert (lua_gettop (luaState) == 4); +// +// int r = lua_pcall (luaState, 3, 0, 0); +// +// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); +// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); +// +// if (r) { +// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); +// } +// +// free (cb); +//} +// +//void lua_msg_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_message *M[]) { +// assert (TLSR == TLS); +// struct lua_query_extra *cb = cb_extra; +// lua_settop (luaState, 0); +// //lua_checkstack (luaState, 20); +// my_lua_checkstack (luaState, 20); +// +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); +// +// lua_pushnumber (luaState, success); +// +// if (success) { +// lua_newtable (luaState); +// int i; +// for (i = 0; i < num; i++) { +// lua_pushnumber (luaState, i); +// push_message (M[i]); +// lua_settable (luaState, -3); +// } +// } else { +// lua_pushboolean (luaState, 0); +// } +// +// assert (lua_gettop (luaState) == 4); +// +// int r = lua_pcall (luaState, 3, 0, 0); +// +// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); +// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); +// +// if (r) { +// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); +// } +// +// free (cb); +//} +// +//void lua_file_cb (struct tgl_state *TLSR, void *cb_extra, int success, char *file_name) { +// assert (TLSR == TLS); +// struct lua_query_extra *cb = cb_extra; +// lua_settop (luaState, 0); +// //lua_checkstack (luaState, 20); +// my_lua_checkstack (luaState, 20); +// +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); +// +// lua_pushnumber (luaState, success); +// +// if (success) { +// lua_pushstring (luaState, file_name); +// } else { +// lua_pushboolean (luaState, 0); +// } +// +// assert (lua_gettop (luaState) == 4); +// +// int r = lua_pcall (luaState, 3, 0, 0); +// +// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); +// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); +// +// if (r) { +// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); +// } +// +// free (cb); +//} +// +//void lua_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_chat *C) { +// assert (TLSR == TLS); +// struct lua_query_extra *cb = cb_extra; +// lua_settop (luaState, 0); +// //lua_checkstack (luaState, 20); +// my_lua_checkstack (luaState, 20); +// +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); +// +// lua_pushnumber (luaState, success); +// +// if (success) { +// push_peer (C->id, (void *)C); +// } else { +// lua_pushboolean (luaState, 0); +// } +// +// assert (lua_gettop (luaState) == 4); +// +// int r = lua_pcall (luaState, 3, 0, 0); +// +// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); +// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); +// +// if (r) { +// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); +// } +// +// free (cb); +//} +// +//void lua_secret_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_secret_chat *C) { +// assert (TLSR == TLS); +// struct lua_query_extra *cb = cb_extra; +// lua_settop (luaState, 0); +// //lua_checkstack (luaState, 20); +// my_lua_checkstack (luaState, 20); +// +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); +// +// lua_pushnumber (luaState, success); +// +// if (success) { +// push_peer (C->id, (void *)C); +// } else { +// lua_pushboolean (luaState, 0); +// } +// +// assert (lua_gettop (luaState) == 4); +// +// int r = lua_pcall (luaState, 3, 0, 0); +// +// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); +// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); +// +// if (r) { +// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); +// } +// +// free (cb); +//} +// +//void lua_user_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_user *C) { +// assert (TLSR == TLS); +// struct lua_query_extra *cb = cb_extra; +// lua_settop (luaState, 0); +// //lua_checkstack (luaState, 20); +// my_lua_checkstack (luaState, 20); +// +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); +// +// lua_pushnumber (luaState, success); +// +// if (success) { +// push_peer (C->id, (void *)C); +// } else { +// lua_pushboolean (luaState, 0); +// } +// +// assert (lua_gettop (luaState) == 4); +// +// int r = lua_pcall (luaState, 3, 0, 0); +// +// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); +// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); +// +// if (r) { +// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); +// } +// +// free (cb); +//} +// +//void lua_str_cb (struct tgl_state *TLSR, void *cb_extra, int success, char *data) { +// assert (TLSR == TLS); +// struct lua_query_extra *cb = cb_extra; +// lua_settop (luaState, 0); +// //lua_checkstack (luaState, 20); +// my_lua_checkstack (luaState, 20); +// +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); +// +// lua_pushnumber (luaState, success); +// +// if (success) { +// lua_pushstring (luaState, data); +// } else { +// lua_pushboolean (luaState, 0); +// } +// +// assert (lua_gettop (luaState) == 4); +// +// int r = lua_pcall (luaState, 3, 0, 0); +// +// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); +// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); +// +// if (r) { +// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); +// } +// +// free (cb); +//} +// +//void lua_do_all (void) { +// int p = 0; +// while (p < pos) { +// int l = (long)lua_ptr[p ++]; +// assert (p + l + 1 <= pos); +// enum lua_query_type f = (long)lua_ptr[p ++]; +// struct tgl_message *M; +// char *s, *s1, *s2, *s3; +// switch (f) { +// case lq_contact_list: +// tgl_do_update_contact_list (TLS, lua_contact_list_cb, lua_ptr[p ++]); +// break; +// case lq_dialog_list: +// tgl_do_get_dialog_list (TLS, lua_dialog_list_cb, lua_ptr[p ++]); +// break; +// case lq_msg: +// tgl_do_send_message (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], strlen (lua_ptr[p + 2]), lua_msg_cb, lua_ptr[p]); +// free (lua_ptr[p + 2]); +// p += 3; +// break; +// case lq_send_typing: +// tgl_do_send_typing (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, tgl_typing_typing, lua_empty_cb, lua_ptr[p]); +// p += 2; +// break; +// case lq_send_typing_abort: +// tgl_do_send_typing (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, tgl_typing_cancel, lua_empty_cb, lua_ptr[p]); +// p += 2; +// break; +// case lq_rename_chat: +// tgl_do_rename_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); +// free (lua_ptr[p + 2]); +// p += 3; +// break; +// case lq_send_photo: +// tgl_do_send_document (TLS, -1, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); +// free (lua_ptr[p + 2]); +// p += 3; +// break; +// case lq_send_video: +// tgl_do_send_document (TLS, FLAG_DOCUMENT_VIDEO, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); +// free (lua_ptr[p + 2]); +// p += 3; +// break; +// case lq_send_audio: +// tgl_do_send_document (TLS, FLAG_DOCUMENT_AUDIO, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); +// free (lua_ptr[p + 2]); +// p += 3; +// break; +// case lq_send_document: +// tgl_do_send_document (TLS, 0, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); +// free (lua_ptr[p + 2]); +// p += 3; +// break; +// case lq_send_file: +// tgl_do_send_document (TLS, -2, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); +// free (lua_ptr[p + 2]); +// p += 3; +// break; +// case lq_send_text: +// tgl_do_send_text (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); +// free (lua_ptr[p + 2]); +// p += 3; +// break; +// case lq_chat_set_photo: +// tgl_do_set_chat_photo (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); +// free (lua_ptr[p + 2]); +// p += 3; +// break; +// case lq_load_photo: +// case lq_load_video: +// case lq_load_audio: +// case lq_load_document: +// M = lua_ptr[p + 1]; +// if (!M || (M->media.type != tgl_message_media_photo && M->media.type != tgl_message_media_photo_encr && M->media.type != tgl_message_media_document && M->media.type != tgl_message_media_document_encr)) { +// lua_file_cb (TLS, lua_ptr[p], 0, 0); +// } else { +// if (M->media.type == tgl_message_media_photo) { +// tgl_do_load_photo (TLS, &M->media.photo, lua_file_cb, lua_ptr[p]); +// } else if (M->media.type == tgl_message_media_document) { +// tgl_do_load_document (TLS, &M->media.document, lua_file_cb, lua_ptr[p]); +// } else { +// tgl_do_load_encr_document (TLS, &M->media.encr_document, lua_file_cb, lua_ptr[p]); +// } +// } +// p += 2; +// break; +// case lq_load_video_thumb: +// case lq_load_document_thumb: +// M = lua_ptr[p + 1]; +// if (!M || (M->media.type != tgl_message_media_document)) { +// lua_file_cb (TLS, lua_ptr[p], 0, 0); +// } else { +// tgl_do_load_document_thumb (TLS, &M->media.document, lua_file_cb, lua_ptr[p]); +// } +// p += 2; +// break; +// case lq_fwd: +// tgl_do_forward_message (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, ((struct tgl_message *)lua_ptr[p + 2])->id, lua_msg_cb, lua_ptr[p]); +// p += 3; +// break; +// case lq_fwd_media: +// tgl_do_forward_media (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, ((struct tgl_message *)lua_ptr[p + 2])->id, lua_msg_cb, lua_ptr[p]); +// p += 3; +// break; +// case lq_chat_info: +// tgl_do_get_chat_info (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, 0, lua_chat_cb, lua_ptr[p]); +// p += 2; +// break; +// case lq_user_info: +// tgl_do_get_user_info (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, 0, lua_user_cb, lua_ptr[p]); +// p += 2; +// break; +// case lq_history: +// tgl_do_get_history (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, (long)lua_ptr[p + 2], 0, lua_msg_list_cb, lua_ptr[p]); +// p += 3; +// break; +// case lq_chat_add_user: +// tgl_do_add_user_to_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, ((tgl_peer_t *)lua_ptr[p + 2])->id, 10, lua_msg_cb, lua_ptr[p]); +// p += 3; +// break; +// case lq_chat_del_user: +// tgl_do_del_user_from_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, ((tgl_peer_t *)lua_ptr[p + 2])->id, lua_msg_cb, lua_ptr[p]); +// p += 3; +// break; +// case lq_add_contact: +// s1 = lua_ptr[p + 1]; +// s2 = lua_ptr[p + 2]; +// s3 = lua_ptr[p + 3]; +// tgl_do_add_contact (TLS, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), 0, lua_contact_list_cb, lua_ptr[p]); +// free (s1); +// free (s2); +// free (s3); +// p += 4; +// break; +// case lq_del_contact: +// tgl_do_del_contact (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_empty_cb, lua_ptr[p]); +// p += 2; +// break; +// case lq_rename_contact: +// s1 = lua_ptr[p + 1]; +// s2 = lua_ptr[p + 2]; +// s3 = lua_ptr[p + 3]; +// tgl_do_add_contact (TLS, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), 1, lua_contact_list_cb, lua_ptr[p]); +// free (s1); +// free (s2); +// free (s3); +// p += 4; +// break; +// case lq_search: +// s = lua_ptr[p + 2]; +// tgl_do_msg_search (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, 0, 0, 40, 0, s, lua_msg_list_cb, lua_ptr[p]); +// free (s); +// p += 3; +// break; +// case lq_global_search: +// s = lua_ptr[p + 1]; +// tgl_do_msg_search (TLS, tgl_set_peer_id (TGL_PEER_UNKNOWN, 0), 0, 0, 40, 0, s, lua_msg_list_cb, lua_ptr[p]); +// free (s); +// p += 2; +// break; +// case lq_mark_read: +// tgl_do_mark_read (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_empty_cb, lua_ptr[p]); +// p += 2; +// break; +// case lq_set_profile_photo: +// s = lua_ptr[p + 1]; +// tgl_do_set_profile_photo (TLS, s, lua_empty_cb, lua_ptr[p]); +// free (s); +// p += 2; +// break; +// case lq_set_profile_name: +// s1 = lua_ptr[p + 1]; +// s2 = lua_ptr[p + 1]; +// tgl_do_set_profile_name (TLS, s1, s2, lua_user_cb, lua_ptr[p]); +// free (s1); +// free (s2); +// p += 3; +// break; +// case lq_create_secret_chat: +// tgl_do_create_secret_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_secret_chat_cb, lua_ptr[p]); +// p += 2; +// break; +// case lq_create_group_chat: +// s = lua_ptr[p + 2]; +// tgl_do_create_group_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, s, lua_msg_cb, lua_ptr[p]); +// free (s); +// p += 3; +// break; +// case lq_delete_msg: +// tgl_do_delete_msg (TLS, ((struct tgl_message *)lua_ptr[p + 1])->id, lua_empty_cb, lua_ptr[p]); +// p += 2; +// break; +// case lq_restore_msg: +// tgl_do_delete_msg (TLS, (long)lua_ptr[p + 1], lua_empty_cb, lua_ptr[p]); +// p += 2; +// break; +// case lq_accept_secret_chat: +// tgl_do_accept_encr_chat_request (TLS, lua_ptr[p + 1], lua_secret_chat_cb, lua_ptr[p]); +// p += 2; +// break; +// case lq_send_contact: +// s1 = lua_ptr[p + 2]; +// s2 = lua_ptr[p + 3]; +// s3 = lua_ptr[p + 4]; +// tgl_do_send_contact (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), lua_msg_cb, lua_ptr[p]); +// free (s1); +// free (s2); +// free (s3); +// p += 5; +// break; +// case lq_status_online: +// tgl_do_update_status (TLS, 1, lua_empty_cb, lua_ptr[p]); +// p ++; +// break; +// case lq_status_offline: +// tgl_do_update_status (TLS, 0, lua_empty_cb, lua_ptr[p]); +// p ++; +// break; +// case lq_extf: +// s = lua_ptr[p + 1]; +// tgl_do_send_extf (TLS, s, strlen (s), lua_str_cb, lua_ptr[p]); +// free (s); +// p += 2; +// break; +// case lq_send_location: +// if (sizeof (void *) == 4) { +// tgl_do_send_location (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id , *(float *)(lua_ptr + p + 2), *(float *)(lua_ptr + p + 3), lua_msg_cb, lua_ptr[p]); +// } else { +// tgl_do_send_location (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id , *(double *)(lua_ptr + p + 2), *(double *)(lua_ptr + p + 3), lua_msg_cb, lua_ptr[p]); +// } +// p += 4; +// break; +// /* +// lq_delete_msg, +// lq_restore_msg, +// case 0: +// tgl_do_send_message (((tgl_peer_t *)lua_ptr[p])->id, lua_ptr[p + 1], strlen (lua_ptr[p + 1]), 0, 0); +// free (lua_ptr[p + 1]); +// p += 2; +// break; +// case 1: +// tgl_do_forward_message (((tgl_peer_t *)lua_ptr[p])->id, (long)lua_ptr[p + 1], 0, 0); +// p += 2; +// break; +// case 2: +// tgl_do_mark_read (((tgl_peer_t *)lua_ptr[p])->id, 0, 0); +// p += 1; +// break;*/ +// default: +// assert (0); +// } +// } +// pos = 0; +//} +// +// +//enum lua_function_param { +// lfp_none, +// lfp_peer, +// lfp_chat, +// lfp_user, +// lfp_secret_chat, +// lfp_string, +// lfp_number, +// lfp_positive_number, +// lfp_nonnegative_number, +// lfp_msg, +// lfp_double +//}; +// +//struct lua_function { +// char *name; +// enum lua_query_type type; +// enum lua_function_param params[10]; +//}; +// +//struct lua_function functions[] = { +// {"get_contact_list", lq_contact_list, { lfp_none }}, +// {"get_dialog_list", lq_dialog_list, { lfp_none }}, +// {"rename_chat", lq_rename_chat, { lfp_chat, lfp_string, lfp_none }}, +// {"send_msg", lq_msg, { lfp_peer, lfp_string, lfp_none }}, +// {"send_typing", lq_send_typing, { lfp_peer, lfp_none }}, +// {"send_typing_abort", lq_send_typing_abort, { lfp_peer, lfp_none }}, +// {"send_photo", lq_send_photo, { lfp_peer, lfp_string, lfp_none }}, +// {"send_video", lq_send_video, { lfp_peer, lfp_string, lfp_none }}, +// {"send_audio", lq_send_audio, { lfp_peer, lfp_string, lfp_none }}, +// {"send_document", lq_send_document, { lfp_peer, lfp_string, lfp_none }}, +// {"send_file", lq_send_file, { lfp_peer, lfp_string, lfp_none }}, +// {"send_text", lq_send_text, { lfp_peer, lfp_string, lfp_none }}, +// {"chat_set_photo", lq_chat_set_photo, { lfp_chat, lfp_string, lfp_none }}, +// {"load_photo", lq_load_photo, { lfp_msg, lfp_none }}, +// {"load_video", lq_load_video, { lfp_msg, lfp_none }}, +// {"load_video_thumb", lq_load_video_thumb, { lfp_msg, lfp_none }}, +// {"load_audio", lq_load_audio, { lfp_msg, lfp_none }}, +// {"load_document", lq_load_document, { lfp_msg, lfp_none }}, +// {"load_document_thumb", lq_load_document_thumb, { lfp_msg, lfp_none }}, +// {"fwd_msg", lq_fwd, { lfp_peer, lfp_msg, lfp_none }}, +// {"fwd_media", lq_fwd_media, { lfp_peer, lfp_msg, lfp_none }}, +// {"chat_info", lq_chat_info, { lfp_chat, lfp_none }}, +// {"user_info", lq_user_info, { lfp_user, lfp_none }}, +// {"get_history", lq_history, { lfp_peer, lfp_nonnegative_number, lfp_none }}, +// {"chat_add_user", lq_chat_add_user, { lfp_chat, lfp_user, lfp_none }}, +// {"chat_del_user", lq_chat_del_user, { lfp_chat, lfp_user, lfp_none }}, +// {"add_contact", lq_add_contact, { lfp_string, lfp_string, lfp_string, lfp_none }}, +// {"del_contact", lq_del_contact, { lfp_user, lfp_none }}, +// {"rename_contact", lq_rename_contact, { lfp_string, lfp_string, lfp_string, lfp_none }}, +// {"msg_search", lq_search, { lfp_peer, lfp_string, lfp_none }}, +// {"msg_global_search", lq_global_search, { lfp_string, lfp_none }}, +// {"mark_read", lq_mark_read, { lfp_peer, lfp_none }}, +// {"set_profile_photo", lq_set_profile_photo, { lfp_string, lfp_none }}, +// {"set_profile_name", lq_set_profile_name, { lfp_string, lfp_none }}, +// {"create_secret_chat", lq_create_secret_chat, { lfp_user, lfp_none }}, +// {"create_group_chat", lq_create_group_chat, { lfp_user, lfp_string, lfp_none }}, +// {"delete_msg", lq_delete_msg, { lfp_msg, lfp_none }}, +// {"restore_msg", lq_restore_msg, { lfp_positive_number, lfp_none }}, +// {"accept_secret_chat", lq_accept_secret_chat, { lfp_secret_chat, lfp_none }}, +// {"send_contact", lq_send_contact, { lfp_peer, lfp_string, lfp_string, lfp_string, lfp_none }}, +// {"status_online", lq_status_online, { lfp_none }}, +// {"status_offline", lq_status_offline, { lfp_none }}, +// {"send_location", lq_send_location, { lfp_peer, lfp_double, lfp_double, lfp_none }}, +// {"ext_function", lq_extf, { lfp_string, lfp_none }}, +// { 0, 0, { lfp_none}} +//}; +// +//static int parse_lua_function (lua_State *L, struct lua_function *F) { +// int p = 0; +// while (F->params[p] != lfp_none) { p ++; } +// if (lua_gettop (L) != p + 2) { +// lua_pushboolean (L, 0); +// return 1; +// } +// +// int a1 = luaL_ref (L, LUA_REGISTRYINDEX); +// int a2 = luaL_ref (L, LUA_REGISTRYINDEX); +// +// struct lua_query_extra *e = malloc (sizeof (*e)); +// assert (e); +// e->func = a2; +// e->param = a1; +// +// assert (pos + 3 + p < MAX_LUA_COMMANDS); +// +// lua_ptr[pos ++] = (void *)(long)(p + 1); +// lua_ptr[pos ++] = (void *)(long)F->type; +// lua_ptr[pos ++] = e; +// +// int sp = p; +// int ok = 1; +// int cc = 0; +// while (p > 0) { +// p --; +// cc ++; +// const char *s; +// tgl_peer_t *P; +// long long num; +// double dval; +// struct tgl_message *M; +// switch (F->params[p]) { +// case lfp_none: +// assert (0); +// break; +// case lfp_peer: +// case lfp_user: +// case lfp_chat: +// case lfp_secret_chat: +// s = lua_tostring (L, -cc); +// if (!s) { +// ok = 0; +// break; +// } +// if (sscanf (s, "user#id%lld", &num) == 1 && num > 0) { +// tgl_insert_empty_user (TLS, num); +// P = tgl_peer_get (TLS, TGL_MK_USER (num)); +// } else if (sscanf (s, "chat#id%lld", &num) == 1 && num > 0) { +// tgl_insert_empty_chat (TLS, num); +// P = tgl_peer_get (TLS, TGL_MK_CHAT (num)); +// } else { +// P = get_peer (s); +// } +// if (!P/* || !(P->flags & FLAG_CREATED)*/) { +// ok = 0; +// break; +// } +// if (F->params[p] != lfp_peer) { +// if ((tgl_get_peer_type (P->id) == TGL_PEER_USER && F->params[p] != lfp_user) || +// (tgl_get_peer_type (P->id) == TGL_PEER_CHAT && F->params[p] != lfp_chat) || +// (tgl_get_peer_type (P->id) == TGL_PEER_ENCR_CHAT && F->params[p] != lfp_secret_chat)) { +// ok = 0; +// break; +// } +// } +// lua_ptr[pos + p] = P; +// break; +// +// case lfp_string: +// s = lua_tostring (L, -cc); +// if (!s) { +// ok = 0; +// break; +// } +// lua_ptr[pos + p] = (void *)s; +// break; +// +// case lfp_number: +// num = lua_tonumber (L, -cc); +// +// lua_ptr[pos + p] = (void *)(long)num; +// break; +// +// case lfp_double: +// dval = lua_tonumber (L, -cc); +// +// if (sizeof (void *) == 4) { +// *(float *)(lua_ptr + pos + p) = dval; +// } else { +// assert (sizeof (void *) >= 8); +// *(double *)(lua_ptr + pos + p) = dval; +// } +// break; +// +// case lfp_positive_number: +// num = lua_tonumber (L, -cc); +// if (num <= 0) { +// ok = 0; +// break; +// } +// +// lua_ptr[pos + p] = (void *)(long)num; +// break; +// +// case lfp_nonnegative_number: +// num = lua_tonumber (L, -cc); +// if (num < 0) { +// ok = 0; +// break; +// } +// +// lua_ptr[pos + p] = (void *)(long)num; +// break; +// +// case lfp_msg: +// s = lua_tostring (L, -cc); +// if (!s || !strlen (s)) { +// ok = 0; +// break; +// } +// +// num = atoll (s); +// +// M = tgl_message_get (TLS, num); +// +// if (!M || !(M->flags & FLAG_CREATED)) { +// ok = 0; +// break; +// } +// +// lua_ptr[pos + p] = M; +// break; +// +// default: +// assert (0); +// } +// } +// if (!ok) { +// luaL_unref (luaState, LUA_REGISTRYINDEX, a1); +// luaL_unref (luaState, LUA_REGISTRYINDEX, a2); +// free (e); +// pos -= 3; +// lua_pushboolean (L, 0); +// return 1; +// } +// +// for (p = 0; p < sp; p++) { +// if (F->params[p] == lfp_string) { +// lua_ptr[pos + p] = strdup (lua_ptr[pos + p]); +// } +// } +// pos += p; +// +// lua_pushboolean (L, 1); +// return 1; +//} +// +// +//static void lua_postpone_alarm (evutil_socket_t fd, short what, void *arg) { +// int *t = arg; +// +// lua_settop (luaState, 0); +// //lua_checkstack (luaState, 20); +// my_lua_checkstack (luaState, 20); +// +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, t[1]); +// lua_rawgeti (luaState, LUA_REGISTRYINDEX, t[0]); +// assert (lua_gettop (luaState) == 2); +// +// int r = lua_pcall (luaState, 1, 0, 0); +// +// luaL_unref (luaState, LUA_REGISTRYINDEX, t[0]); +// luaL_unref (luaState, LUA_REGISTRYINDEX, t[1]); +// +// if (r) { +// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); +// } +// +//} +// +//static int postpone_from_lua (lua_State *L) { +// int n = lua_gettop (L); +// if (n != 3) { +// lua_pushboolean (L, 0); +// return 1; +// } +// +// double timeout = lua_tonumber (L, -1); +// if (timeout < 0) { +// lua_pushboolean (L, 0); +// return 1; +// } +// +// lua_pop (L, 1); +// int a1 = luaL_ref (L, LUA_REGISTRYINDEX); +// int a2 = luaL_ref (L, LUA_REGISTRYINDEX); +// +// +// int *t = malloc (16); +// assert (t); +// struct event *ev = evtimer_new (TLS->ev_base, lua_postpone_alarm, t); +// t[0] = a1; +// t[1] = a2; +// *(void **)(t + 2) = ev; +// +// struct timeval ts= { +// .tv_sec = (long)timeout, +// .tv_usec = (timeout - ((long)timeout)) * 1000000 +// }; +// event_add (ev, &ts); +// +// lua_pushboolean (L, 1); +// return 1; +//} +// +//extern int safe_quit; +//static int safe_quit_from_lua (lua_State *L) { +// int n = lua_gettop (L); +// if (n != 0) { +// lua_pushboolean (L, 0); +// return 1; +// } +// safe_quit = 1; +// +// lua_pushboolean (L, 1); +// return 1; +//} +// +//static int universal_from_lua (lua_State *L) { +// const char *s = lua_tostring(L, lua_upvalueindex(1)); +// if (!s) { +// lua_pushboolean (L, 0); +// return 1; +// } +// int i = 0; +// while (functions[i].name) { +// if (!strcmp (functions[i].name, s)) { +// return parse_lua_function (L, &functions[i]); +// } +// i ++; +// } +// lua_pushboolean (L, 0); +// return 1; +//} +// +// +//static void my_python_register (const char *name, lua_CFunction f) { +// lua_pushstring(L, name); +// lua_pushcclosure(L, f, 1); +// lua_setglobal(L, name); +//} +// +// void py_init (const char *file) { if (!file) { return; } have_file = 1; - PyObject *pName, *pModule; +// PyObject *pName;//, *pModule; - Py_Initialize() + Py_Initialize(); - pName = PyFile_FromFile(file, "telegram.py", 'r', null); +// pName = PyFile_FromFile(file, "telegram.py", 'r', null); - err = PyErr_Occurred(); - if (err != NULL) { - logprintf("python error occurred"); // TODO: implement the backtrace - exit(1); - } +// PyObject* err = PyErr_Occurred(); +// if (err != NULL) { +// logprintf("python error occurred"); // TODO: implement the backtrace +// exit(1); +// } - int i = 0; - while (functions[i].name) { - my_lua_register (luaState, functions[i].name, universal_from_lua); - i ++; - } +// int i = 0; +// while (functions[i].name) { +// my_lua_register (luaState, functions[i].name, universal_from_lua); +// i ++; +// } //lua_register (luaState, "fwd_msg", fwd_msg_from_lua); //lua_register (luaState, "mark_read", mark_read_from_lua); - lua_register (luaState, "postpone", postpone_from_lua); - lua_register (luaState, "safe_quit", safe_quit_from_lua); +// lua_register (luaState, "postpone", postpone_from_lua); +// lua_register (luaState, "safe_quit", safe_quit_from_lua); //lua_register (luaState, "get_contact_list", get_contacts_from_lua); /*lua_register (luaState, "get_dialog_list", get_dialog_list_from_lua); lua_register (luaState, "send_msg", send_msg_from_lua); @@ -1487,11 +1486,6 @@ void py_init (const char *file) { lua_register (luaState, "add_contact", add_contact_from_lua); lua_register (luaState, "rename_contact", rename_contact_from_lua);*/ - int ret = luaL_dofile (luaState, file); - if (ret) { - logprintf ("lua: %s\n", lua_tostring (luaState, -1)); - exit (1); - } } #endif From 0f4ceaa2006309d25d343054f0fe83ae3517916c Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 2 May 2015 04:48:31 -0700 Subject: [PATCH 04/29] Adding missing changes to configure.ac --- configure.ac | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index e6f1b95..f0786f3 100644 --- a/configure.ac +++ b/configure.ac @@ -94,17 +94,19 @@ AC_ARG_ENABLE(liblua,[--enable-liblua/--disable-liblua], AC_MSG_ERROR([No lua found. Try --disable-liblua]) ]) ]) - AC_ARG_ENABLE(python,[--enable-python/--disable-python], [ + AX_PYTHON() dnl python checks (you can change the required python version bellow) AM_PATH_PYTHON(2.7.0) PY_PREFIX=`$PYTHON -c 'import sys ; print sys.prefix'` - PYTHON_LIBS="-lpython$PYTHON_VERSION" - PYTHON_CFLAGS="-I$PY_PREFIX/include/python$PYTHON_VERSION" AC_SUBST([PYTHON_LIBS]) AC_SUBST([PYTHON_CFLAGS]) - ]) + EXTRA_LIBS="${EXTRA_LIBS} -l${PYTHON_LIB}" + CPPFLAGS="${CPPFLAGS} -I${PYTHON_INCLUDE_DIR}" + + AC_DEFINE(USE_PYTHON,1,[use python]) + ]) #check for custom prog name AC_ARG_WITH(progname,[--with-progname=], From 7d2cac9ea41ee30ad97c61d55bc9ebb08008f317 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 2 May 2015 04:49:21 -0700 Subject: [PATCH 05/29] Merging to remove bad branch --- Makefile.in | 2 +- config.h.in | 3 + configure | 515 +++++++++++++++++++++++++++++++++++++++++++++++++++- interface.c | 27 ++- main.c | 20 ++ 5 files changed, 563 insertions(+), 4 deletions(-) diff --git a/Makefile.in b/Makefile.in index 340c069..4af1ba8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -19,7 +19,7 @@ DIR_LIST=${DEP} ${AUTO} ${EXE} ${OBJ} ${LIB} ${DEP}/auto ${OBJ}/auto EXE_LIST=${EXE}/telegram-cli -TG_OBJECTS=${OBJ}/main.o ${OBJ}/loop.o ${OBJ}/interface.o ${OBJ}/lua-tg.o +TG_OBJECTS=${OBJ}/main.o ${OBJ}/loop.o ${OBJ}/interface.o ${OBJ}/lua-tg.o ${OBJ}/python-tg.o INCLUDE=-I. -I${srcdir} CC=@CC@ diff --git a/config.h.in b/config.h.in index 47e7e60..c78d16d 100644 --- a/config.h.in +++ b/config.h.in @@ -158,6 +158,9 @@ /* use lua */ #undef USE_LUA +/* use python */ +#undef USE_PYTHON + /* Define to `int' if doesn't define. */ #undef gid_t diff --git a/configure b/configure index 5cf26fd..3458182 100755 --- a/configure +++ b/configure @@ -622,6 +622,20 @@ ac_includes_default="\ ac_subst_vars='LTLIBOBJS EXTRA_LIBS LIBOBJS +PYTHON_CFLAGS +PYTHON_LIBS +pkgpyexecdir +pyexecdir +pkgpythondir +pythondir +PYTHON_PLATFORM +PYTHON_EXEC_PREFIX +PYTHON_PREFIX +PYTHON_VERSION +PYTHON +PYTHON_LIB +PYTHON_INCLUDE_DIR +PYTHON_BIN LUA_LIB LUA_INCLUDE pkgluaexecdir @@ -694,6 +708,7 @@ with_zlib enable_libconfig enable_extf enable_liblua +enable_python with_progname ' ac_precious_vars='build_alias @@ -707,7 +722,8 @@ CPPFLAGS CPP LUA LUA_INCLUDE -LUA_LIB' +LUA_LIB +PYTHON' # Initialize some variables set by options. @@ -1320,6 +1336,7 @@ Optional Features: --enable-libconfig/--disable-libconfig --enable-extf/--disable-extf --enable-liblua/--disable-liblua +--enable-python/--disable-python Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -1342,6 +1359,7 @@ Some influential environment variables: LUA The Lua interpreter, e.g. /usr/bin/lua5.1 LUA_INCLUDE The Lua includes, e.g. -I/usr/include/lua5.1 LUA_LIB The Lua library, e.g. -llua5.1 + PYTHON the Python interpreter Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -2389,6 +2407,62 @@ ac_config_headers="$ac_config_headers config.h" + + +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_python.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PYTHON +# +# DESCRIPTION +# +# This macro does a complete Python development environment check. +# +# It recurses through several python versions (from 2.1 to 2.6 in this +# version), looking for an executable. When it finds an executable, it +# looks to find the header files and library. +# +# It sets PYTHON_BIN to the name of the python executable, +# PYTHON_INCLUDE_DIR to the directory holding the header files, and +# PYTHON_LIB to the name of the Python library. +# +# This macro calls AC_SUBST on PYTHON_BIN (via AC_CHECK_PROG), +# PYTHON_INCLUDE_DIR and PYTHON_LIB. +# +# LICENSE +# +# Copyright (c) 2008 Michael Tindal +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 14 # =========================================================================== @@ -5860,6 +5934,445 @@ $as_echo "#define USE_LUA 1" >>confdefs.h fi +fi + +# Check whether --enable-python was given. +if test "${enable_python+set}" = set; then : + enableval=$enable_python; + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for python build information" >&5 +$as_echo_n "checking for python build information... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 +$as_echo "" >&6; } +for python in python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python; do +for ac_prog in $python +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PYTHON_BIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PYTHON_BIN"; then + ac_cv_prog_PYTHON_BIN="$PYTHON_BIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PYTHON_BIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PYTHON_BIN=$ac_cv_prog_PYTHON_BIN +if test -n "$PYTHON_BIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_BIN" >&5 +$as_echo "$PYTHON_BIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$PYTHON_BIN" && break +done + +ax_python_bin=$PYTHON_BIN +if test x$ax_python_bin != x; then + as_ac_Lib=`$as_echo "ac_cv_lib_$ax_python_bin''_main" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -l$ax_python_bin" >&5 +$as_echo_n "checking for main in -l$ax_python_bin... " >&6; } +if eval \${$as_ac_Lib+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-l$ax_python_bin $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$as_ac_Lib=yes" +else + eval "$as_ac_Lib=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + ax_python_lib=$ax_python_bin +else + ax_python_lib=no +fi + + if test x$ax_python_lib == xno; then + as_ac_Lib=`$as_echo "ac_cv_lib_${ax_python_bin}m''_main" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -l${ax_python_bin}m" >&5 +$as_echo_n "checking for main in -l${ax_python_bin}m... " >&6; } +if eval \${$as_ac_Lib+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-l${ax_python_bin}m $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$as_ac_Lib=yes" +else + eval "$as_ac_Lib=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + ax_python_lib=${ax_python_bin}m +else + ax_python_lib=no +fi + + fi + if test x$ax_python_lib != xno; then + ax_python_header=`$ax_python_bin -c "from distutils.sysconfig import *; print(get_config_var('CONFINCLUDEPY'))"` + if test x$ax_python_header != x; then + break; + fi + fi +fi +done +if test x$ax_python_bin = x; then + ax_python_bin=no +fi +if test x$ax_python_header = x; then + ax_python_header=no +fi +if test x$ax_python_lib = x; then + ax_python_lib=no +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: results of the Python check:" >&5 +$as_echo " results of the Python check:" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Binary: $ax_python_bin" >&5 +$as_echo " Binary: $ax_python_bin" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Library: $ax_python_lib" >&5 +$as_echo " Library: $ax_python_lib" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Include Dir: $ax_python_header" >&5 +$as_echo " Include Dir: $ax_python_header" >&6; } + +if test x$ax_python_header != xno; then + PYTHON_INCLUDE_DIR=$ax_python_header + +fi +if test x$ax_python_lib != xno; then + PYTHON_LIB=$ax_python_lib + +fi + + + + + + + + if test -n "$PYTHON"; then + # If the user set $PYTHON, use it and don't search something else. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $PYTHON version is >= 2.7.0" >&5 +$as_echo_n "checking whether $PYTHON version is >= 2.7.0... " >&6; } + prog="import sys +# split strings by '.' and convert to numeric. Append some zeros +# because we need at least 4 digits for the hex conversion. +# map returns an iterator in Python 3.0 and a list in 2.x +minver = list(map(int, '2.7.0'.split('.'))) + [0, 0, 0] +minverhex = 0 +# xrange is not present in Python 3.0 and range returns an iterator +for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i] +sys.exit(sys.hexversion < minverhex)" + if { echo "$as_me:$LINENO: $PYTHON -c "$prog"" >&5 + ($PYTHON -c "$prog") >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "Python interpreter is too old" "$LINENO" 5 +fi + am_display_PYTHON=$PYTHON + else + # Otherwise, try each interpreter until we find one that satisfies + # VERSION. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a Python interpreter with version >= 2.7.0" >&5 +$as_echo_n "checking for a Python interpreter with version >= 2.7.0... " >&6; } +if ${am_cv_pathless_PYTHON+:} false; then : + $as_echo_n "(cached) " >&6 +else + + for am_cv_pathless_PYTHON in python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 none; do + test "$am_cv_pathless_PYTHON" = none && break + prog="import sys +# split strings by '.' and convert to numeric. Append some zeros +# because we need at least 4 digits for the hex conversion. +# map returns an iterator in Python 3.0 and a list in 2.x +minver = list(map(int, '2.7.0'.split('.'))) + [0, 0, 0] +minverhex = 0 +# xrange is not present in Python 3.0 and range returns an iterator +for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i] +sys.exit(sys.hexversion < minverhex)" + if { echo "$as_me:$LINENO: $am_cv_pathless_PYTHON -c "$prog"" >&5 + ($am_cv_pathless_PYTHON -c "$prog") >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then : + break +fi + done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_pathless_PYTHON" >&5 +$as_echo "$am_cv_pathless_PYTHON" >&6; } + # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. + if test "$am_cv_pathless_PYTHON" = none; then + PYTHON=: + else + # Extract the first word of "$am_cv_pathless_PYTHON", so it can be a program name with args. +set dummy $am_cv_pathless_PYTHON; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PYTHON+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PYTHON in + [\\/]* | ?:[\\/]*) + ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PYTHON=$ac_cv_path_PYTHON +if test -n "$PYTHON"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5 +$as_echo "$PYTHON" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi + am_display_PYTHON=$am_cv_pathless_PYTHON + fi + + + if test "$PYTHON" = :; then + as_fn_error $? "no suitable Python interpreter found" "$LINENO" 5 + else + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON version" >&5 +$as_echo_n "checking for $am_display_PYTHON version... " >&6; } +if ${am_cv_python_version+:} false; then : + $as_echo_n "(cached) " >&6 +else + am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[:3])"` +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_version" >&5 +$as_echo "$am_cv_python_version" >&6; } + PYTHON_VERSION=$am_cv_python_version + + + + PYTHON_PREFIX='${prefix}' + + PYTHON_EXEC_PREFIX='${exec_prefix}' + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON platform" >&5 +$as_echo_n "checking for $am_display_PYTHON platform... " >&6; } +if ${am_cv_python_platform+:} false; then : + $as_echo_n "(cached) " >&6 +else + am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"` +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_platform" >&5 +$as_echo "$am_cv_python_platform" >&6; } + PYTHON_PLATFORM=$am_cv_python_platform + + + # Just factor out some code duplication. + am_python_setup_sysconfig="\ +import sys +# Prefer sysconfig over distutils.sysconfig, for better compatibility +# with python 3.x. See automake bug#10227. +try: + import sysconfig +except ImportError: + can_use_sysconfig = 0 +else: + can_use_sysconfig = 1 +# Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: +# +try: + from platform import python_implementation + if python_implementation() == 'CPython' and sys.version[:3] == '2.7': + can_use_sysconfig = 0 +except ImportError: + pass" + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON script directory" >&5 +$as_echo_n "checking for $am_display_PYTHON script directory... " >&6; } +if ${am_cv_python_pythondir+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$prefix" = xNONE + then + am_py_prefix=$ac_default_prefix + else + am_py_prefix=$prefix + fi + am_cv_python_pythondir=`$PYTHON -c " +$am_python_setup_sysconfig +if can_use_sysconfig: + sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) +else: + from distutils import sysconfig + sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') +sys.stdout.write(sitedir)"` + case $am_cv_python_pythondir in + $am_py_prefix*) + am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` + am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` + ;; + *) + case $am_py_prefix in + /usr|/System*) ;; + *) + am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages + ;; + esac + ;; + esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pythondir" >&5 +$as_echo "$am_cv_python_pythondir" >&6; } + pythondir=$am_cv_python_pythondir + + + + pkgpythondir=\${pythondir}/$PACKAGE + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory" >&5 +$as_echo_n "checking for $am_display_PYTHON extension module directory... " >&6; } +if ${am_cv_python_pyexecdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$exec_prefix" = xNONE + then + am_py_exec_prefix=$am_py_prefix + else + am_py_exec_prefix=$exec_prefix + fi + am_cv_python_pyexecdir=`$PYTHON -c " +$am_python_setup_sysconfig +if can_use_sysconfig: + sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) +else: + from distutils import sysconfig + sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') +sys.stdout.write(sitedir)"` + case $am_cv_python_pyexecdir in + $am_py_exec_prefix*) + am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` + am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` + ;; + *) + case $am_py_exec_prefix in + /usr|/System*) ;; + *) + am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages + ;; + esac + ;; + esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pyexecdir" >&5 +$as_echo "$am_cv_python_pyexecdir" >&6; } + pyexecdir=$am_cv_python_pyexecdir + + + + pkgpyexecdir=\${pyexecdir}/$PACKAGE + + + + fi + + + PY_PREFIX=`$PYTHON -c 'import sys ; print sys.prefix'` + + + EXTRA_LIBS="${EXTRA_LIBS} -l${PYTHON_LIB}" + CPPFLAGS="${CPPFLAGS} -I${PYTHON_INCLUDE_DIR}" + + +$as_echo "#define USE_PYTHON 1" >>confdefs.h + + fi diff --git a/interface.c b/interface.c index 63bee0c..1033c58 100644 --- a/interface.c +++ b/interface.c @@ -59,6 +59,10 @@ # include "lua-tg.h" #endif +#ifdef USE_PYTHON +# include "python-tg.h" +#endif + //#include "mtproto-common.h" #include @@ -1116,6 +1120,7 @@ extern char *downloads_directory; extern char *config_directory; extern char *binlog_file_name; extern char *lua_file; +extern char *python_file; extern struct event *term_ev; void do_clear (int arg_num, struct arg args[], struct in_ev *ev) { @@ -1130,6 +1135,7 @@ void do_clear (int arg_num, struct arg args[], struct in_ev *ev) { free (config_directory); free (binlog_file_name); free (lua_file); + free (python_file); clear_history (); event_free (term_ev); event_base_free (TLS->ev_base); @@ -1933,6 +1939,9 @@ void print_message_gw (struct tgl_state *TLSR, struct tgl_message *M) { #ifdef USE_LUA lua_new_msg (M); #endif + #ifdef USE_PYTHON + py_new_msg (M); + #endif if (!binlog_read) { return; } if (tgl_get_peer_type (M->to_id) == TGL_PEER_ENCR_CHAT) { write_secret_chat_file (); @@ -1952,6 +1961,9 @@ void our_id_gw (struct tgl_state *TLSR, int id) { #ifdef USE_LUA lua_our_id (id); #endif + #ifdef USE_PYTHON + py_our_id (id); + #endif } void print_peer_updates (struct in_ev *ev, int flags) { @@ -2004,7 +2016,10 @@ void user_update_gw (struct tgl_state *TLSR, struct tgl_user *U, unsigned flags) #ifdef USE_LUA lua_user_update (U, flags); #endif - + #ifdef USE_PYTHON + py_user_update (U, flags); + #endif + if (disable_output && !notify_ev) { return; } if (!binlog_read) { return; } struct in_ev *ev = notify_ev; @@ -2031,7 +2046,10 @@ void chat_update_gw (struct tgl_state *TLSR, struct tgl_chat *U, unsigned flags) #ifdef USE_LUA lua_chat_update (U, flags); #endif - + #ifdef USE_PYTHON + py_chat_update (U, flags); + #endif + if (disable_output && !notify_ev) { return; } if (!binlog_read) { return; } struct in_ev *ev = notify_ev; @@ -2058,7 +2076,12 @@ void secret_chat_update_gw (struct tgl_state *TLSR, struct tgl_secret_chat *U, u #ifdef USE_LUA lua_secret_chat_update (U, flags); #endif + #ifdef USE_PYTHON + py_secret_chat_update (U, flags); + #endif + + if ((flags & TGL_UPDATE_WORKING) || (flags & TGL_UPDATE_DELETED)) { write_secret_chat_file (); } diff --git a/main.c b/main.c index 8fe7da1..9fb5b96 100644 --- a/main.c +++ b/main.c @@ -74,6 +74,10 @@ # include "lua-tg.h" #endif +#ifdef USE_PYTHON +# include "python-tg.h" +#endif + #include #define PROGNAME "telegram-cli" @@ -106,6 +110,7 @@ char *downloads_directory; char *config_directory; char *binlog_file_name; char *lua_file; +char *python_file; int binlog_enabled; extern int log_level; int sync_from_start; @@ -378,6 +383,10 @@ void parse_config (void) { parse_config_val (&conf, &lua_file, "lua_script", 0, config_directory); } + if (!python_file) { + parse_config_val (&conf, &python_file, "python_script", 0, config_directory); + } + strcpy (buf + l, "binlog_enabled"); config_lookup_bool (&conf, buf, &binlog_enabled); @@ -640,6 +649,11 @@ void args_parse (int argc, char **argv) { break; #endif case 'W': +#ifdef USE_PYTHON + case 'Z': + python_file = strdup (optarg); + break; +#endif wait_dialog_list = 1; break; case 'C': @@ -878,6 +892,12 @@ int main (int argc, char **argv) { lua_init (lua_file); } #endif + #ifdef USE_PYTHON + if (python_file) { + py_init (python_file); + } + #endif + inner_main (); From 0bf997969747267adc26bd7b83624a8e74fc9d82 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 2 May 2015 04:58:48 -0700 Subject: [PATCH 06/29] Remove -Werror for dev --- Makefile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.in b/Makefile.in index 4af1ba8..5f7ae40 100644 --- a/Makefile.in +++ b/Makefile.in @@ -4,8 +4,8 @@ CFLAGS=@CFLAGS@ LDFLAGS=@LDFLAGS@ @OPENSSL_LDFLAGS@ CPPFLAGS=@CPPFLAGS@ @OPENSSL_INCLUDES@ DEFS=@DEFS@ -COMPILE_FLAGS=${CFLAGS} ${CPFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Wextra -Werror -Wno-deprecated-declarations -fno-strict-aliasing -fno-omit-frame-pointer -ggdb -Wno-unused-parameter -fPIC - +COMPILE_FLAGS=${CFLAGS} ${CPFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Wextra -Wno-deprecated-declarations -fno-strict-aliasing -fno-omit-frame-pointer -ggdb -Wno-unused-parameter -fPIC +#TODO re-add -Werror EXTRA_LIBS=@LIBS@ @EXTRA_LIBS@ @OPENSSL_LIBS@ LOCAL_LDFLAGS=-rdynamic -ggdb -levent ${EXTRA_LIBS} LINK_FLAGS=${LDFLAGS} ${LOCAL_LDFLAGS} From 2a99ce59d1aabd9a8fbfd965d3ff7aefe258b73c Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 2 May 2015 05:03:13 -0700 Subject: [PATCH 07/29] Initialize module --- python-tg.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python-tg.c b/python-tg.c index 4432996..4da0961 100644 --- a/python-tg.c +++ b/python-tg.c @@ -1440,11 +1440,12 @@ void py_init (const char *file) { if (!file) { return; } have_file = 1; -// PyObject *pName;//, *pModule; + PyObject *pName, *pModule; Py_Initialize(); -// pName = PyFile_FromFile(file, "telegram.py", 'r', null); + pName = PyString_FromString(file); + pModule = PyImport_Import(pName); // PyObject* err = PyErr_Occurred(); // if (err != NULL) { From a240097bbb16460c71cc9780527fba78bb173147 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 2 May 2015 21:32:30 -0700 Subject: [PATCH 08/29] progress commit on python support --- main.c | 3 + python-tg.c | 698 ++++++++++++++++++++++++++++------------------------ test.py | 23 ++ 3 files changed, 398 insertions(+), 326 deletions(-) create mode 100644 test.py diff --git a/main.c b/main.c index 9fb5b96..3ee259d 100644 --- a/main.c +++ b/main.c @@ -471,6 +471,9 @@ void usage (void) { #ifdef USE_LUA printf (" -s lua script file\n"); #endif + #ifdef USE_PYTHON + printf (" -Z python script file\n"); + #endif printf (" -W send dialog_list query and wait for answer before reading input\n"); printf (" -C disable color output\n"); printf (" -R disable readline\n"); diff --git a/python-tg.c b/python-tg.c index 4da0961..844c9ea 100644 --- a/python-tg.c +++ b/python-tg.c @@ -47,299 +47,331 @@ extern int verbosity; extern struct tgl_state *TLS; static int have_file; -// -//void push_user (tgl_peer_t *P); -//void push_peer (tgl_peer_id_t id, tgl_peer_t *P); -// -//void lua_add_string_field (const char *name, const char *value) { -// assert (name && strlen (name)); -// if (!value || !strlen (value)) { return; } -// my_lua_checkstack (luaState, 3); -// lua_pushstring (luaState, name); -// lua_pushstring (luaState, value); -// lua_settable (luaState, -3); -//} -// -//void lua_add_string_field_arr (int num, const char *value) { -// if (!value || !strlen (value)) { return; } -// my_lua_checkstack (luaState, 3); -// lua_pushnumber (luaState, num); -// lua_pushstring (luaState, value); -// lua_settable (luaState, -3); -//} -// -//void lua_add_num_field (const char *name, double value) { -// assert (name && strlen (name)); -// my_lua_checkstack (luaState, 3); -// lua_pushstring (luaState, name); -// lua_pushnumber (luaState, value); -// lua_settable (luaState, -3); -//} -// -//void push_tgl_peer_type (int x) { -// switch (x) { -// case TGL_PEER_USER: -// lua_pushstring (luaState, "user"); -// break; -// case TGL_PEER_CHAT: -// lua_pushstring (luaState, "chat"); -// break; -// case TGL_PEER_ENCR_CHAT: -// lua_pushstring (luaState, "encr_chat"); -// break; -// default: -// assert (0); -// } -//} -// -//void push_user (tgl_peer_t *P) { -// my_lua_checkstack (luaState, 4); -// lua_add_string_field ("first_name", P->user.first_name); -// lua_add_string_field ("last_name", P->user.last_name); -// lua_add_string_field ("real_first_name", P->user.real_first_name); -// lua_add_string_field ("real_last_name", P->user.real_last_name); -// lua_add_string_field ("phone", P->user.phone); -// if (P->user.access_hash) { -// lua_add_num_field ("access_hash", 1); -// } -//} -// -//void push_chat (tgl_peer_t *P) { -// my_lua_checkstack (luaState, 4); -// assert (P->chat.title); -// lua_add_string_field ("title", P->chat.title); -// lua_add_num_field ("members_num", P->chat.users_num); -// if (P->chat.user_list) { -// lua_pushstring (luaState, "members"); -// lua_newtable (luaState); -// int i; -// for (i = 0; i < P->chat.users_num; i++) { -// lua_pushnumber (luaState, i); -// tgl_peer_id_t id = TGL_MK_USER (P->chat.user_list[i].user_id); -// push_peer (id, tgl_peer_get (TLS, id)); -// lua_settable (luaState, -3); -// } -// lua_settable (luaState, -3); -// } -//} -// -//void push_encr_chat (tgl_peer_t *P) { -// my_lua_checkstack (luaState, 4); -// lua_pushstring (luaState, "user"); -// push_peer (TGL_MK_USER (P->encr_chat.user_id), tgl_peer_get (TLS, TGL_MK_USER (P->encr_chat.user_id))); -// lua_settable (luaState, -3); -//} -// -//void push_update_types (unsigned flags) { -// my_lua_checkstack (luaState, 4); -// lua_newtable (luaState); -// int cc = 0; -// -// -// if (flags & TGL_UPDATE_CREATED) { -// lua_add_string_field_arr (cc++, "created"); -// } -// if (flags & TGL_UPDATE_DELETED) { -// lua_add_string_field_arr (cc++, "deleted"); -// } -// if (flags & TGL_UPDATE_PHONE) { -// lua_add_string_field_arr (cc++, "phone"); -// } -// if (flags & TGL_UPDATE_CONTACT) { -// lua_add_string_field_arr (cc++, "contact"); -// } -// if (flags & TGL_UPDATE_PHOTO) { -// lua_add_string_field_arr (cc++, "photo"); -// } -// if (flags & TGL_UPDATE_BLOCKED) { -// lua_add_string_field_arr (cc++, "blocked"); -// } -// if (flags & TGL_UPDATE_REAL_NAME) { -// lua_add_string_field_arr (cc++, "real_name"); -// } -// if (flags & TGL_UPDATE_NAME) { -// lua_add_string_field_arr (cc++, "name"); -// } -// if (flags & TGL_UPDATE_REQUESTED) { -// lua_add_string_field_arr (cc++, "requested"); -// } -// if (flags & TGL_UPDATE_WORKING) { -// lua_add_string_field_arr (cc++, "working"); -// } -// if (flags & TGL_UPDATE_FLAGS) { -// lua_add_string_field_arr (cc++, "flags"); -// } -// if (flags & TGL_UPDATE_TITLE) { -// lua_add_string_field_arr (cc++, "title"); -// } -// if (flags & TGL_UPDATE_ADMIN) { -// lua_add_string_field_arr (cc++, "admin"); -// } -// if (flags & TGL_UPDATE_MEMBERS) { -// lua_add_string_field_arr (cc++, "members"); -// } -// if (flags & TGL_UPDATE_ACCESS_HASH) { -// lua_add_string_field_arr (cc++, "access_hash"); -// } -// if (flags & TGL_UPDATE_USERNAME) { -// lua_add_string_field_arr (cc++, "username"); -// } -// -//} -// -//void push_peer (tgl_peer_id_t id, tgl_peer_t *P) { -// lua_newtable (luaState); -// -// lua_add_num_field ("id", tgl_get_peer_id (id)); -// lua_pushstring (luaState, "type"); -// push_tgl_peer_type (tgl_get_peer_type (id)); -// lua_settable (luaState, -3); -// -// -// if (!P || !(P->flags & FLAG_CREATED)) { -// lua_pushstring (luaState, "print_name"); -// static char s[100]; -// switch (tgl_get_peer_type (id)) { -// case TGL_PEER_USER: -// sprintf (s, "user#%d", tgl_get_peer_id (id)); -// break; -// case TGL_PEER_CHAT: -// sprintf (s, "chat#%d", tgl_get_peer_id (id)); -// break; -// case TGL_PEER_ENCR_CHAT: -// sprintf (s, "encr_chat#%d", tgl_get_peer_id (id)); -// break; -// default: -// assert (0); -// } -// lua_pushstring (luaState, s); -// lua_settable (luaState, -3); // flags -// -// return; -// } -// -// lua_add_string_field ("print_name", P->print_name); -// lua_add_num_field ("flags", P->flags); -// -// switch (tgl_get_peer_type (id)) { -// case TGL_PEER_USER: -// push_user (P); -// break; -// case TGL_PEER_CHAT: -// push_chat (P); -// break; -// case TGL_PEER_ENCR_CHAT: -// push_encr_chat (P); -// break; -// default: -// assert (0); -// } -//} -// -//void push_media (struct tgl_message_media *M) { -// my_lua_checkstack (luaState, 4); -// -// switch (M->type) { -// case tgl_message_media_photo: -// case tgl_message_media_photo_encr: -// lua_newtable (luaState); -// lua_add_string_field ("type", "photo"); -// break; -// /*case tgl_message_media_video: -// case tgl_message_media_video_encr: -// lua_newtable (luaState); -// lua_add_string_field ("type", "video"); -// break; -// case tgl_message_media_audio: -// case tgl_message_media_audio_encr: -// lua_newtable (luaState); -// lua_add_string_field ("type", "audio"); -// break;*/ -// case tgl_message_media_document: -// case tgl_message_media_document_encr: -// lua_newtable (luaState); -// lua_add_string_field ("type", "document"); -// break; -// case tgl_message_media_unsupported: -// lua_newtable (luaState); -// lua_add_string_field ("type", "unsupported"); -// break; -// case tgl_message_media_geo: -// lua_newtable (luaState); -// lua_add_string_field ("type", "geo"); -// lua_add_num_field ("longitude", M->geo.longitude); -// lua_add_num_field ("latitude", M->geo.latitude); -// break; -// case tgl_message_media_contact: -// lua_newtable (luaState); -// lua_add_string_field ("type", "contact"); -// lua_add_string_field ("phone", M->phone); -// lua_add_string_field ("first_name", M->first_name); -// lua_add_string_field ("last_name", M->last_name); -// lua_add_num_field ("user_id", M->user_id); -// break; -// default: -// lua_pushstring (luaState, "???"); -// } -//} -// -//void push_message (struct tgl_message *M) { -// assert (M); -// my_lua_checkstack (luaState, 10); -// lua_newtable (luaState); -// -// static char s[30]; -// snprintf (s, 30, "%lld", M->id); -// lua_add_string_field ("id", s); -// if (!(M->flags & FLAG_CREATED)) { return; } -// lua_add_num_field ("flags", M->flags); -// -// if (tgl_get_peer_type (M->fwd_from_id)) { -// lua_pushstring (luaState, "fwd_from"); -// push_peer (M->fwd_from_id, tgl_peer_get (TLS, M->fwd_from_id)); -// lua_settable (luaState, -3); // fwd_from -// -// lua_add_num_field ("fwd_date", M->fwd_date); -// } -// -// lua_pushstring (luaState, "from"); -// push_peer (M->from_id, tgl_peer_get (TLS, M->from_id)); -// lua_settable (luaState, -3); -// -// lua_pushstring (luaState, "to"); -// push_peer (M->to_id, tgl_peer_get (TLS, M->to_id)); -// lua_settable (luaState, -3); -// -// lua_pushstring (luaState, "out"); -// lua_pushboolean (luaState, M->out); -// lua_settable (luaState, -3); -// -// lua_pushstring (luaState, "unread"); -// lua_pushboolean (luaState, M->unread); -// lua_settable (luaState, -3); -// -// lua_pushstring (luaState, "date"); -// lua_pushnumber (luaState, M->date); -// lua_settable (luaState, -3); -// -// lua_pushstring (luaState, "service"); -// lua_pushboolean (luaState, M->service); -// lua_settable (luaState, -3); -// -// if (!M->service) { -// if (M->message_len && M->message) { -// lua_pushstring (luaState, "text"); -// lua_pushlstring (luaState, M->message, M->message_len); -// lua_settable (luaState, -3); -// } -// if (M->media.type && M->media.type != tgl_message_media_none) { -// lua_pushstring (luaState, "media"); -// push_media (&M->media); -// lua_settable (luaState, -3); -// } -// } -//} -// + +// Python update function callables +PyObject *_py_binlog_end; +PyObject *_py_diff_end; +PyObject *_py_our_id; +PyObject *_py_new_msg; +PyObject *_py_secret_chat_update; +PyObject *_py_user_update; +PyObject *_py_chat_update; + +// Python callback callables +PyObject *_py_empty_cb; +PyObject *_py_contact_list_cb; +PyObject *_py_dialog_list_cb; +PyObject *_py_msg_cb; +PyObject *_py_msg_list_cb; +PyObject *_py_file_cb; +PyObject *_py_chat_cb; +PyObject *_py_secret_chat_cb; +PyObject *_py_user_cb; +PyObject *_py_str_cb; + + +PyObject* get_user (tgl_peer_t *P); +PyObject* get_peer (tgl_peer_id_t id, tgl_peer_t *P); + +void py_add_string_field (PyObject* dict, char *name, const char *value) { + assert (PyDict_Check(dict)); + assert (name && strlen (name)); + if (!value || !strlen (value)) { return; } + PyDict_SetItemString (dict, name, PyString_FromString(value)); +} + +void py_add_string_field_arr (PyObject* list, int num, const char *value) { + assert(PyList_Check(list)); + if (!value || !strlen (value)) { return; } + if(num >= 0) + PyList_SetItem (list, num, PyString_FromString (value)); + else // Append + PyList_Append (list, PyString_FromString (value)); +} + +void py_add_num_field (PyObject* dict, const char *name, double value) { + assert (PyDict_Check(dict)); + assert (name && strlen (name)); + PyDict_SetItemString (dict, name, PyFloat_FromDouble(value)); +} + +PyObject* get_tgl_peer_type (int x) { + PyObject *type; + + switch (x) { + case TGL_PEER_USER: + type = PyString_FromString("user"); + break; + case TGL_PEER_CHAT: + type = PyString_FromString("chat"); + break; + case TGL_PEER_ENCR_CHAT: + type = PyString_FromString("encr_chat"); + break; + default: + assert (0); + } + + return type; +} + +PyObject* get_user (tgl_peer_t *P) { + PyObject *user; + + user = PyDict_New(); + if(user == NULL) + assert(0); // TODO handle python exception + + py_add_string_field (user, "first_name", P->user.first_name); + py_add_string_field (user, "last_name", P->user.last_name); + py_add_string_field (user, "real_first_name", P->user.real_first_name); + py_add_string_field (user, "real_last_name", P->user.real_last_name); + py_add_string_field (user, "phone", P->user.phone); + if (P->user.access_hash) { + py_add_num_field (user, "access_hash", 1); + } + + return user; +} + +PyObject* get_chat (tgl_peer_t *P) { + PyObject *chat, *members; + + chat = PyDict_New(); + if(chat == NULL) + assert(0); // TODO handle python exception + + assert (P->chat.title); + + py_add_string_field (chat, "title", P->chat.title); + py_add_num_field (chat, "members_num", P->chat.users_num); + if (P->chat.user_list) { + members = PyList_New(P->chat.users_num); + if(members == NULL) + assert(0); // TODO handle python exception + + int i; + for (i = 0; i < P->chat.users_num; i++) { + tgl_peer_id_t id = TGL_MK_USER (P->chat.user_list[i].user_id); + PyList_SetItem (members, i, get_peer(id, tgl_peer_get (TLS, id))); + } + PyDict_SetItemString (chat, "members", members); + } + + return chat; +} + +PyObject* get_encr_chat (tgl_peer_t *P) { + PyObject *encr_chat, *user; + + encr_chat = PyDict_New(); + if(encr_chat == NULL) + assert(0); // TODO handle python exception + + user = get_peer (TGL_MK_USER (P->encr_chat.user_id), tgl_peer_get (TLS, TGL_MK_USER (P->encr_chat.user_id))); + PyDict_SetItemString (encr_chat, "user", user); + + return encr_chat; +} + +PyObject* get_update_types (unsigned flags) { + PyObject* types; + types = PyList_New(0); + if(types == NULL) + assert(0); // TODO handle python exception + + if (flags & TGL_UPDATE_CREATED) { + py_add_string_field_arr(types, -1, "created"); + } + if (flags & TGL_UPDATE_DELETED) { + py_add_string_field_arr(types, -1, "deleted"); + } + if (flags & TGL_UPDATE_PHONE) { + py_add_string_field_arr(types, -1, "phone"); + } + if (flags & TGL_UPDATE_CONTACT) { + py_add_string_field_arr(types, -1, "contact"); + } + if (flags & TGL_UPDATE_PHOTO) { + py_add_string_field_arr(types, -1, "photo"); + } + if (flags & TGL_UPDATE_BLOCKED) { + py_add_string_field_arr(types, -1, "blocked"); + } + if (flags & TGL_UPDATE_REAL_NAME) { + py_add_string_field_arr(types, -1, "real_name"); + } + if (flags & TGL_UPDATE_NAME) { + py_add_string_field_arr(types, -1, "name"); + } + if (flags & TGL_UPDATE_REQUESTED) { + py_add_string_field_arr(types, -1, "requested"); + } + if (flags & TGL_UPDATE_WORKING) { + py_add_string_field_arr(types, -1, "working"); + } + if (flags & TGL_UPDATE_FLAGS) { + py_add_string_field_arr(types, -1, "flags"); + } + if (flags & TGL_UPDATE_TITLE) { + py_add_string_field_arr(types, -1, "title"); + } + if (flags & TGL_UPDATE_ADMIN) { + py_add_string_field_arr(types, -1, "admin"); + } + if (flags & TGL_UPDATE_MEMBERS) { + py_add_string_field_arr(types, -1, "members"); + } + if (flags & TGL_UPDATE_ACCESS_HASH) { + py_add_string_field_arr(types, -1, "access_hash"); + } + if (flags & TGL_UPDATE_USERNAME) { + py_add_string_field_arr(types, -1, "username"); + } + return types; +} + +PyObject* get_peer (tgl_peer_id_t id, tgl_peer_t *P) { + PyObject *peer; + + peer = PyDict_New(); + if(peer == NULL) + assert(0); // TODO handle python exception; + + PyDict_SetItemString (peer, "type", get_tgl_peer_type (tgl_get_peer_type(id))); + + if (!P || !(P->flags & FLAG_CREATED)) { + PyObject *name; + + static char s[100]; + switch (tgl_get_peer_type (id)) { + case TGL_PEER_USER: + sprintf (s, "user#%d", tgl_get_peer_id (id)); + break; + case TGL_PEER_CHAT: + sprintf (s, "chat#%d", tgl_get_peer_id (id)); + break; + case TGL_PEER_ENCR_CHAT: + sprintf (s, "encr_chat#%d", tgl_get_peer_id (id)); + break; + default: + assert (0); + } + + name = PyDict_New(); + if(name == NULL) + assert(0); // TODO handle python exception; + + PyDict_SetItemString (name, "print_name", PyString_FromString(s)); + PyDict_SetItemString (peer, "peer", name); + } else { + PyObject *peer_obj; + + switch (tgl_get_peer_type (id)) { + case TGL_PEER_USER: + peer_obj = get_user (P); + break; + case TGL_PEER_CHAT: + peer_obj = get_chat (P); + break; + case TGL_PEER_ENCR_CHAT: + peer_obj = get_encr_chat (P); + break; + default: + assert (0); + } + PyDict_SetItemString (peer, "peer", peer_obj); + } + + return peer; +} + +PyObject* get_media (struct tgl_message_media *M) { + PyObject *media; + + media = PyDict_New(); + if(media == NULL) + assert(0); // TODO handle python exception + + switch (M->type) { + case tgl_message_media_photo: + case tgl_message_media_photo_encr: + py_add_string_field (media, "type", "photo"); + break; + /*case tgl_message_media_video: + case tgl_message_media_video_encr: + lua_newtable (luaState); + lua_add_string_field ("type", "video"); + break; + case tgl_message_media_audio: + case tgl_message_media_audio_encr: + lua_newtable (luaState); + lua_add_string_field ("type", "audio"); + break;*/ + case tgl_message_media_document: + case tgl_message_media_document_encr: + py_add_string_field (media, "type", "document"); + break; + case tgl_message_media_unsupported: + py_add_string_field (media, "type", "unsupported"); + break; + case tgl_message_media_geo: + py_add_string_field (media, "type", "geo"); + py_add_num_field (media, "longitude", M->geo.longitude); + py_add_num_field (media, "latitude", M->geo.latitude); + break; + case tgl_message_media_contact: + py_add_string_field (media, "type", "contact"); + py_add_string_field (media, "phone", M->phone); + py_add_string_field (media, "first_name", M->first_name); + py_add_string_field (media, "last_name", M->last_name); + py_add_num_field (media, "user_id", M->user_id); + break; + default: + py_add_string_field (media, "type", "unknown"); + } + + return media; +} + +PyObject* get_message (struct tgl_message *M) { + assert (M); + PyObject *msg; + + msg = PyDict_New(); + if(msg == NULL) + assert(0); // TODO handle python exception + + static char s[30]; + snprintf (s, 30, "%lld", M->id); + py_add_string_field (msg, "id", s); + if (!(M->flags & FLAG_CREATED)) { return msg; } + py_add_num_field (msg, "flags", M->flags); + + if (tgl_get_peer_type (M->fwd_from_id)) { + PyDict_SetItemString(msg, "fwd_from", get_peer(M->fwd_from_id, tgl_peer_get (TLS, M->fwd_from_id))); + py_add_num_field (msg, "fwd_date", M->fwd_date); + } + + PyDict_SetItemString(msg, "from", get_peer(M->from_id, tgl_peer_get (TLS, M->from_id))); + PyDict_SetItemString(msg, "to", get_peer(M->to_id, tgl_peer_get (TLS, M->to_id))); + PyDict_SetItemString(msg, "out", (M->out ? Py_True : Py_False)); + PyDict_SetItemString(msg, "unread", (M->unread ? Py_True : Py_False)); + PyDict_SetItemString(msg, "service", (M->service ? Py_True : Py_False)); + PyDict_SetItemString(msg, "date", PyLong_FromLong(M->date)); // TODO put this into PyDate object + + if (!M->service) { + if (M->message_len && M->message) { + PyDict_SetItemString(msg, "text", PyString_FromStringAndSize(M->message, M->message_len)); + } + if (M->media.type && M->media.type != tgl_message_media_none) { + PyDict_SetItemString(msg, "media", get_media(&M->media)); + } + } + + return msg; +} + //void lua_binlog_end (void) { // if (!have_file) { return; } // lua_settop (luaState, 0); @@ -384,36 +416,37 @@ void py_our_id (int id) { } void py_new_msg (struct tgl_message *M) { -// if (!have_file) { return; } -// lua_settop (luaState, 0); -// //lua_checkstack (luaState, 20); -// my_lua_checkstack (luaState, 20); -// lua_getglobal (luaState, "on_msg_receive"); -// push_message (M); -// assert (lua_gettop (luaState) == 2); -// -// int r = lua_pcall (luaState, 1, 0, 0); -// if (r) { -// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); -// } + if (!have_file) { return; } + PyObject *msg; + PyObject *arglist, *result; + + msg = get_message (M); + + arglist = Py_BuildValue("O", msg); + result = PyEval_CallObject(_py_new_msg, arglist); + Py_DECREF(arglist); + + assert(result && PyString_Check(result)); // TODO handle python exception + logprintf ("python: %s\n", PyString_AsString(result)); } void py_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) { -// if (!have_file) { return; } -// lua_settop (luaState, 0); -// //lua_checkstack (luaState, 20); -// my_lua_checkstack (luaState, 20); -// lua_getglobal (luaState, "on_secret_chat_update"); -// push_peer (C->id, (void *)C); -// push_update_types (flags); -// assert (lua_gettop (luaState) == 3); -// -// int r = lua_pcall (luaState, 2, 0, 0); -// if (r) { -// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); -// } + if (!have_file) { return; } + PyObject *peer, *types; + PyObject *arglist, *result; + + peer = get_peer (C->id, (void *)C); + types = get_update_types (flags); + + arglist = Py_BuildValue("OO", peer, types); + result = PyEval_CallObject(_py_secret_chat_update, arglist); + Py_DECREF(arglist); + + assert(result && PyString_Check(result)); // TODO handle python exception + logprintf ("python: %s\n", PyString_AsString(result)); } + void py_user_update (struct tgl_user *U, unsigned flags) { // if (!have_file) { return; } // lua_settop (luaState, 0); @@ -1429,23 +1462,36 @@ void py_chat_update (struct tgl_chat *C, unsigned flags) { //} // // -//static void my_python_register (const char *name, lua_CFunction f) { -// lua_pushstring(L, name); -// lua_pushcclosure(L, f, 1); -// lua_setglobal(L, name); -//} -// -// +static void my_python_register (PyObject *dict, const char *name, PyObject *f) { + // Store callables for python functions + f = PyDict_GetItemString(dict, name); + assert(PyCallable_Check(f)); // TODO handle this +} + + + + void py_init (const char *file) { if (!file) { return; } have_file = 1; - PyObject *pName, *pModule; + PyObject *pName, *pModule, *pDict; Py_Initialize(); pName = PyString_FromString(file); pModule = PyImport_Import(pName); + pDict = PyModule_GetDict(pModule); + + // Store callables for python functions + my_python_register(pDict, "on_binlog_replay_end", _py_binlog_end); + my_python_register(pDict, "on_get_difference_end", _py_diff_end); + my_python_register(pDict, "on_our_id", _py_our_id); + my_python_register(pDict, "on_msg_receive", _py_new_msg); + my_python_register(pDict, "on_secret_chat_update", _py_secret_chat_update); + my_python_register(pDict, "on_user_update", _py_user_update); + my_python_register(pDict, "on_chat_update", _py_chat_update); + // PyObject* err = PyErr_Occurred(); // if (err != NULL) { diff --git a/test.py b/test.py new file mode 100644 index 0000000..acdc61c --- /dev/null +++ b/test.py @@ -0,0 +1,23 @@ + + +def on_binlog_replay_end(): + pass + +def on_get_difference_end(): + pass + +def on_our_id(): + pass + +def on_msg_receive(msg): + return "Got msg!" + +def on_secret_chat_update(peer, types): + return "on_secret_chat_update" + +def on_user_update(): + pass + +def on_chat_update(): + pass + From 3f2c13b93f4513dcc8cd022a6d11714b1a6eeea0 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 2 May 2015 23:29:50 -0700 Subject: [PATCH 09/29] Got on_msg_receive working --- main.c | 3 +++ test.py => pytest.py | 2 +- python-tg.c | 15 ++++++++------- 3 files changed, 12 insertions(+), 8 deletions(-) rename test.py => pytest.py (81%) diff --git a/main.c b/main.c index 3ee259d..ff655cc 100644 --- a/main.c +++ b/main.c @@ -604,6 +604,9 @@ void args_parse (int argc, char **argv) { #ifdef USE_LUA "s:" #endif +#ifdef USE_PYTHON + "Z:" +#endif )) != -1) { switch (opt) { diff --git a/test.py b/pytest.py similarity index 81% rename from test.py rename to pytest.py index acdc61c..9a0d8e0 100644 --- a/test.py +++ b/pytest.py @@ -10,7 +10,7 @@ def on_our_id(): pass def on_msg_receive(msg): - return "Got msg!" + return "Got msg from " + msg["from"]["peer"]["first_name"] def on_secret_chat_update(peer, types): return "on_secret_chat_update" diff --git a/python-tg.c b/python-tg.c index 844c9ea..8dfa8a4 100644 --- a/python-tg.c +++ b/python-tg.c @@ -422,7 +422,7 @@ void py_new_msg (struct tgl_message *M) { msg = get_message (M); - arglist = Py_BuildValue("O", msg); + arglist = Py_BuildValue("(O)", msg); result = PyEval_CallObject(_py_new_msg, arglist); Py_DECREF(arglist); @@ -438,7 +438,7 @@ void py_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) { peer = get_peer (C->id, (void *)C); types = get_update_types (flags); - arglist = Py_BuildValue("OO", peer, types); + arglist = Py_BuildValue("(OO)", peer, types); result = PyEval_CallObject(_py_secret_chat_update, arglist); Py_DECREF(arglist); @@ -1462,11 +1462,8 @@ void py_chat_update (struct tgl_chat *C, unsigned flags) { //} // // -static void my_python_register (PyObject *dict, const char *name, PyObject *f) { - // Store callables for python functions - f = PyDict_GetItemString(dict, name); - assert(PyCallable_Check(f)); // TODO handle this -} +#define my_python_register(dict, name, f) \ + f = PyDict_GetItemString(dict, name); @@ -1479,6 +1476,10 @@ void py_init (const char *file) { Py_Initialize(); + PyObject* sysPath = PySys_GetObject((char*)"path"); + PyList_Append(sysPath, PyString_FromString(".")); + + pName = PyString_FromString(file); pModule = PyImport_Import(pName); pDict = PyModule_GetDict(pModule); From c7a66e649f1d2f332fd167814170b41a6960aa38 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sun, 3 May 2015 09:53:29 -0700 Subject: [PATCH 10/29] Implement calling from python into C. Need to implement command queue to execute during netloop. --- pytest.py | 12 ++- python-tg.c | 219 ++++++++++++++++++++++++++++------------------------ 2 files changed, 127 insertions(+), 104 deletions(-) diff --git a/pytest.py b/pytest.py index 9a0d8e0..3f6e3a1 100644 --- a/pytest.py +++ b/pytest.py @@ -1,15 +1,23 @@ +import tgl +import pprint +our_id = 0 +pp = pprint.PrettyPrinter(indent=4) + def on_binlog_replay_end(): pass def on_get_difference_end(): pass -def on_our_id(): - pass +def on_our_id(id): + our_id = id + return "Set ID: " + str(our_id) def on_msg_receive(msg): + pp.pprint(msg) + tgl.send_msg(msg["from"]["type"], msg["from"]["id"], "PONG!") return "Got msg from " + msg["from"]["peer"]["first_name"] def on_secret_chat_update(peer, types): diff --git a/python-tg.c b/python-tg.c index 8dfa8a4..9471f38 100644 --- a/python-tg.c +++ b/python-tg.c @@ -57,19 +57,6 @@ PyObject *_py_secret_chat_update; PyObject *_py_user_update; PyObject *_py_chat_update; -// Python callback callables -PyObject *_py_empty_cb; -PyObject *_py_contact_list_cb; -PyObject *_py_dialog_list_cb; -PyObject *_py_msg_cb; -PyObject *_py_msg_list_cb; -PyObject *_py_file_cb; -PyObject *_py_chat_cb; -PyObject *_py_secret_chat_cb; -PyObject *_py_user_cb; -PyObject *_py_str_cb; - - PyObject* get_user (tgl_peer_t *P); PyObject* get_peer (tgl_peer_id_t id, tgl_peer_t *P); @@ -238,7 +225,9 @@ PyObject* get_peer (tgl_peer_id_t id, tgl_peer_t *P) { if(peer == NULL) assert(0); // TODO handle python exception; - PyDict_SetItemString (peer, "type", get_tgl_peer_type (tgl_get_peer_type(id))); + PyDict_SetItemString (peer, "type_str", get_tgl_peer_type (tgl_get_peer_type(id))); + PyDict_SetItemString (peer, "type", PyInt_FromLong(tgl_get_peer_type(id))); + PyDict_SetItemString (peer, "id", PyInt_FromLong(tgl_get_peer_id(id))); if (!P || !(P->flags & FLAG_CREATED)) { PyObject *name; @@ -372,47 +361,44 @@ PyObject* get_message (struct tgl_message *M) { return msg; } -//void lua_binlog_end (void) { -// if (!have_file) { return; } -// lua_settop (luaState, 0); -// //lua_checkstack (luaState, 20); -// my_lua_checkstack (luaState, 20); -// lua_getglobal (luaState, "on_binlog_replay_end"); -// assert (lua_gettop (luaState) == 1); -// -// int r = lua_pcall (luaState, 0, 0, 0); -// if (r) { -// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); -// } -//} -// -//void lua_diff_end (void) { -// if (!have_file) { return; } -// lua_settop (luaState, 0); -// //lua_checkstack (luaState, 20); -// my_lua_checkstack (luaState, 20); -// lua_getglobal (luaState, "on_get_difference_end"); -// assert (lua_gettop (luaState) == 1); -// -// int r = lua_pcall (luaState, 0, 0, 0); -// if (r) { -// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); -// } -//} -// +void py_binlog_end (void) { + if (!have_file) { return; } + + PyObject *arglist, *result; + + arglist = Py_BuildValue("()"); + result = PyEval_CallObject(_py_binlog_end, arglist); + Py_DECREF(arglist); if(result == NULL) + PyErr_Print(); + else + logprintf ("python: %s\n", PyString_AsString(result)); + +} + +void py_diff_end (void) { + if (!have_file) { return; } + + PyObject *arglist, *result; + + arglist = Py_BuildValue("()"); + result = PyEval_CallObject(_py_diff_end, arglist); + Py_DECREF(arglist); if(result == NULL) + PyErr_Print(); + else + logprintf ("python: %s\n", PyString_AsString(result)); +} + void py_our_id (int id) { -// if (!have_file) { return; } -// lua_settop (luaState, 0); -// //lua_checkstack (luaState, 20); -// my_lua_checkstack (luaState, 20); -// lua_getglobal (luaState, "on_our_id"); -// lua_pushnumber (luaState, id); -// assert (lua_gettop (luaState) == 2); -// -// int r = lua_pcall (luaState, 1, 0, 0); -// if (r) { -// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); -// } + if (!have_file) { return; } + + PyObject *arglist, *result; + + arglist = Py_BuildValue("(i)", id); + result = PyEval_CallObject(_py_our_id, arglist); + Py_DECREF(arglist); if(result == NULL) + PyErr_Print(); + else + logprintf ("python: %s\n", PyString_AsString(result)); } void py_new_msg (struct tgl_message *M) { @@ -426,8 +412,10 @@ void py_new_msg (struct tgl_message *M) { result = PyEval_CallObject(_py_new_msg, arglist); Py_DECREF(arglist); - assert(result && PyString_Check(result)); // TODO handle python exception - logprintf ("python: %s\n", PyString_AsString(result)); + if(result == NULL) + PyErr_Print(); + else + logprintf ("python: %s\n", PyString_AsString(result)); } void py_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) { @@ -442,43 +430,50 @@ void py_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) { result = PyEval_CallObject(_py_secret_chat_update, arglist); Py_DECREF(arglist); - assert(result && PyString_Check(result)); // TODO handle python exception - logprintf ("python: %s\n", PyString_AsString(result)); + if(result == NULL) + PyErr_Print(); + else + logprintf ("python: %s\n", PyString_AsString(result)); } void py_user_update (struct tgl_user *U, unsigned flags) { -// if (!have_file) { return; } -// lua_settop (luaState, 0); -// //lua_checkstack (luaState, 20); -// my_lua_checkstack (luaState, 20); -// lua_getglobal (luaState, "on_user_update"); -// push_peer (U->id, (void *)U); -// push_update_types (flags); -// assert (lua_gettop (luaState) == 3); -// -// int r = lua_pcall (luaState, 2, 0, 0); -// if (r) { -// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); -// } + if (!have_file) { return; } + PyObject *peer, *types; + PyObject *arglist, *result; + + peer = get_peer (U->id, (void *)U); + types = get_update_types (flags); + + arglist = Py_BuildValue("(OO)", peer, types); + result = PyEval_CallObject(_py_user_update, arglist); + Py_DECREF(arglist); + + if(result == NULL) + PyErr_Print(); + else + logprintf ("python: %s\n", PyString_AsString(result)); } void py_chat_update (struct tgl_chat *C, unsigned flags) { -// if (!have_file) { return; } -// lua_settop (luaState, 0); -// //lua_checkstack (luaState, 20); -// my_lua_checkstack (luaState, 20); -// lua_getglobal (luaState, "on_chat_update"); -// push_peer (C->id, (void *)C); -// push_update_types (flags); -// assert (lua_gettop (luaState) == 3); -// -// int r = lua_pcall (luaState, 2, 0, 0); -// if (r) { -// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); -// } + if (!have_file) { return; } + + PyObject *peer, *types; + PyObject *arglist, *result; + + peer = get_peer (C->id, (void *)C); + types = get_update_types (flags); + + arglist = Py_BuildValue("(OO)", peer, types); + result = PyEval_CallObject(_py_chat_update, arglist); + Py_DECREF(arglist); + + if(result == NULL) + PyErr_Print(); + else + logprintf ("python: %s\n", PyString_AsString(result)); } -// + ////extern tgl_peer_t *Peers[]; ////extern int peer_num; // @@ -537,12 +532,12 @@ void py_chat_update (struct tgl_chat *C, unsigned flags) { // lq_extf //}; // -//struct lua_query_extra { +//struct py_query_extra { // int func; // int param; //}; // -//void lua_empty_cb (struct tgl_state *TLSR, void *cb_extra, int success) { +//void py_empty_cb (struct tgl_state *TLSR, void *cb_extra, int success) { // assert (TLSR == TLS); // struct lua_query_extra *cb = cb_extra; // lua_settop (luaState, 0); @@ -660,8 +655,8 @@ void py_chat_update (struct tgl_chat *C, unsigned flags) { // free (cb); //} // -//void lua_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_message *M) { -// assert (TLSR == TLS); +void py_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_message *M) { + assert (TLSR == TLS); // struct lua_query_extra *cb = cb_extra; // lua_settop (luaState, 0); // //lua_checkstack (luaState, 20); @@ -690,8 +685,8 @@ void py_chat_update (struct tgl_chat *C, unsigned flags) { // } // // free (cb); -//} -// +} + //void lua_msg_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_message *M[]) { // assert (TLSR == TLS); // struct lua_query_extra *cb = cb_extra; @@ -1166,13 +1161,27 @@ void py_chat_update (struct tgl_chat *C, unsigned flags) { // enum lua_function_param params[10]; //}; // -//struct lua_function functions[] = { -// {"get_contact_list", lq_contact_list, { lfp_none }}, -// {"get_dialog_list", lq_dialog_list, { lfp_none }}, -// {"rename_chat", lq_rename_chat, { lfp_chat, lfp_string, lfp_none }}, -// {"send_msg", lq_msg, { lfp_peer, lfp_string, lfp_none }}, -// {"send_typing", lq_send_typing, { lfp_peer, lfp_none }}, -// {"send_typing_abort", lq_send_typing_abort, { lfp_peer, lfp_none }}, + +PyObject* py_send_msg(PyObject *self, PyObject *args) { + const char *msg; + tgl_peer_id_t id; + + if (!PyArg_ParseTuple(args, "iis", &id.type, &id.id, &msg)) + return NULL; + + tgl_do_send_message (TLS, (tgl_peer_id_t) id, msg, strlen (msg), py_msg_cb, args); + + return PyString_FromString("sent!"); +} + + +static PyMethodDef py_tgl_methods[] = { +// {"get_contact_list", lq_contact_list, METH_VARARGS}, +// {"get_dialog_list", lq_dialog_list, METH_VARARGS}, +// {"rename_chat", lq_rename_chat, METH_VARARGS}, + {"send_msg", py_send_msg, METH_VARARGS, "send message to user or chat"}, +// {"send_typing", lq_send_typing, METH_VARARGS}, +// {"send_typing_abort", lq_send_typing_abort, METH_VARARGS}, // {"send_photo", lq_send_photo, { lfp_peer, lfp_string, lfp_none }}, // {"send_video", lq_send_video, { lfp_peer, lfp_string, lfp_none }}, // {"send_audio", lq_send_audio, { lfp_peer, lfp_string, lfp_none }}, @@ -1211,9 +1220,9 @@ void py_chat_update (struct tgl_chat *C, unsigned flags) { // {"status_offline", lq_status_offline, { lfp_none }}, // {"send_location", lq_send_location, { lfp_peer, lfp_double, lfp_double, lfp_none }}, // {"ext_function", lq_extf, { lfp_string, lfp_none }}, -// { 0, 0, { lfp_none}} -//}; -// + { NULL, NULL, 0, NULL } +}; + //static int parse_lua_function (lua_State *L, struct lua_function *F) { // int p = 0; // while (F->params[p] != lfp_none) { p ++; } @@ -1466,7 +1475,10 @@ void py_chat_update (struct tgl_chat *C, unsigned flags) { f = PyDict_GetItemString(dict, name); - +void inittgl() +{ + (void) Py_InitModule("tgl", py_tgl_methods); +} void py_init (const char *file) { if (!file) { return; } @@ -1475,6 +1487,8 @@ void py_init (const char *file) { PyObject *pName, *pModule, *pDict; Py_Initialize(); + inittgl(); + PyObject* sysPath = PySys_GetObject((char*)"path"); PyList_Append(sysPath, PyString_FromString(".")); @@ -1484,6 +1498,7 @@ void py_init (const char *file) { pModule = PyImport_Import(pName); pDict = PyModule_GetDict(pModule); + // Store callables for python functions my_python_register(pDict, "on_binlog_replay_end", _py_binlog_end); my_python_register(pDict, "on_get_difference_end", _py_diff_end); From 96325e2ecd043caac3d1f7e7902735184b9f9458 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sun, 3 May 2015 22:42:11 -0700 Subject: [PATCH 11/29] send_msg implemented --- loop.c | 5 + pytest.py | 5 +- python-tg.c | 994 +++++++++++++++++++--------------------------------- test.lua | 12 - 4 files changed, 370 insertions(+), 646 deletions(-) diff --git a/loop.c b/loop.c index b914336..653aae6 100644 --- a/loop.c +++ b/loop.c @@ -57,6 +57,7 @@ #include "telegram.h" #include "loop.h" #include "lua-tg.h" +#include "python-tg.h" #include #include #include @@ -214,6 +215,10 @@ void net_loop (void) { lua_do_all (); #endif + #ifdef USE_PYTHON + py_do_all (); + #endif + if (safe_quit && !TLS->active_queries) { printf ("All done. Exit\n"); do_halt (0); diff --git a/pytest.py b/pytest.py index 3f6e3a1..85de40a 100644 --- a/pytest.py +++ b/pytest.py @@ -16,9 +16,10 @@ def on_our_id(id): return "Set ID: " + str(our_id) def on_msg_receive(msg): - pp.pprint(msg) + if msg["out"]: + return; + tgl.send_msg(msg["from"]["type"], msg["from"]["id"], "PONG!") - return "Got msg from " + msg["from"]["peer"]["first_name"] def on_secret_chat_update(peer, types): return "on_secret_chat_update" diff --git a/python-tg.c b/python-tg.c index 9471f38..28f4f8f 100644 --- a/python-tg.c +++ b/python-tg.c @@ -24,6 +24,7 @@ #ifdef USE_PYTHON #include "python-tg.h" +#endif #include #include @@ -477,67 +478,67 @@ void py_chat_update (struct tgl_chat *C, unsigned flags) { ////extern tgl_peer_t *Peers[]; ////extern int peer_num; // -//#define MAX_LUA_COMMANDS 1000 -//void *lua_ptr[MAX_LUA_COMMANDS]; -//static int pos; +#define MAX_PY_COMMANDS 1000 +void *py_ptr[MAX_PY_COMMANDS]; +static int pos; // //static inline tgl_peer_t *get_peer (const char *s) { // return tgl_peer_get_by_name (TLS, s); //} -// -//enum lua_query_type { -// lq_contact_list, -// lq_dialog_list, -// lq_msg, -// lq_send_typing, -// lq_send_typing_abort, -// lq_rename_chat, -// lq_send_photo, -// lq_chat_set_photo, -// lq_set_profile_photo, -// lq_set_profile_name, -// lq_send_video, -// lq_send_text, -// lq_fwd, -// lq_fwd_media, -// lq_load_photo, -// lq_load_video_thumb, -// lq_load_video, -// lq_chat_info, -// lq_user_info, -// lq_history, -// lq_chat_add_user, -// lq_chat_del_user, -// lq_add_contact, -// lq_del_contact, -// lq_rename_contact, -// lq_search, -// lq_global_search, -// lq_mark_read, -// lq_create_secret_chat, -// lq_create_group_chat, -// lq_send_audio, -// lq_send_document, -// lq_send_file, -// lq_load_audio, -// lq_load_document, -// lq_load_document_thumb, -// lq_delete_msg, -// lq_restore_msg, -// lq_accept_secret_chat, -// lq_send_contact, -// lq_status_online, -// lq_status_offline, -// lq_send_location, -// lq_extf -//}; -// -//struct py_query_extra { -// int func; -// int param; -//}; -// -//void py_empty_cb (struct tgl_state *TLSR, void *cb_extra, int success) { + +enum py_query_type { + pq_contact_list, + pq_dialog_list, + pq_msg, + pq_send_typing, + pq_send_typing_abort, + pq_rename_chat, + pq_send_photo, + pq_chat_set_photo, + pq_set_profile_photo, + pq_set_profile_name, + pq_send_video, + pq_send_text, + pq_fwd, + pq_fwd_media, + pq_load_photo, + pq_load_video_thumb, + pq_load_video, + pq_chat_info, + pq_user_info, + pq_history, + pq_chat_add_user, + pq_chat_del_user, + pq_add_contact, + pq_del_contact, + pq_rename_contact, + pq_search, + pq_global_search, + pq_mark_read, + pq_create_secret_chat, + pq_create_group_chat, + pq_send_audio, + pq_send_document, + pq_send_file, + pq_load_audio, + pq_load_document, + pq_load_document_thumb, + pq_delete_msg, + pq_restore_msg, + pq_accept_secret_chat, + pq_send_contact, + pq_status_online, + pq_status_offline, + pq_send_location, + pq_extf +}; + +struct py_query_extra { + int func; + int param; +}; + +void py_empty_cb (struct tgl_state *TLSR, void *cb_extra, int success) { // assert (TLSR == TLS); // struct lua_query_extra *cb = cb_extra; // lua_settop (luaState, 0); @@ -561,9 +562,9 @@ void py_chat_update (struct tgl_chat *C, unsigned flags) { // } // // free (cb); -//} -// -//void lua_contact_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_user **UL) { +} + +void py_contact_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_user **UL) { // assert (TLSR == TLS); // struct lua_query_extra *cb = cb_extra; // lua_settop (luaState, 0); @@ -599,9 +600,9 @@ void py_chat_update (struct tgl_chat *C, unsigned flags) { // } // // free (cb); -//} -// -//void lua_dialog_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, tgl_peer_id_t peers[], int msgs[], int unread[]) { +} + +void py_dialog_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, tgl_peer_id_t peers[], int msgs[], int unread[]) { // assert (TLSR == TLS); // struct lua_query_extra *cb = cb_extra; // lua_settop (luaState, 0); @@ -653,8 +654,8 @@ void py_chat_update (struct tgl_chat *C, unsigned flags) { // } // // free (cb); -//} -// +} + void py_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_message *M) { assert (TLSR == TLS); // struct lua_query_extra *cb = cb_extra; @@ -687,7 +688,7 @@ void py_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_ // free (cb); } -//void lua_msg_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_message *M[]) { +void py_msg_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_message *M[]) { // assert (TLSR == TLS); // struct lua_query_extra *cb = cb_extra; // lua_settop (luaState, 0); @@ -723,9 +724,9 @@ void py_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_ // } // // free (cb); -//} -// -//void lua_file_cb (struct tgl_state *TLSR, void *cb_extra, int success, char *file_name) { +} + +void py_file_cb (struct tgl_state *TLSR, void *cb_extra, int success, char *file_name) { // assert (TLSR == TLS); // struct lua_query_extra *cb = cb_extra; // lua_settop (luaState, 0); @@ -755,9 +756,9 @@ void py_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_ // } // // free (cb); -//} -// -//void lua_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_chat *C) { +} + +void py_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_chat *C) { // assert (TLSR == TLS); // struct lua_query_extra *cb = cb_extra; // lua_settop (luaState, 0); @@ -787,9 +788,9 @@ void py_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_ // } // // free (cb); -//} -// -//void lua_secret_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_secret_chat *C) { +} + +void py_secret_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_secret_chat *C) { // assert (TLSR == TLS); // struct lua_query_extra *cb = cb_extra; // lua_settop (luaState, 0); @@ -819,9 +820,9 @@ void py_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_ // } // // free (cb); -//} -// -//void lua_user_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_user *C) { +} + +void py_user_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_user *C) { // assert (TLSR == TLS); // struct lua_query_extra *cb = cb_extra; // lua_settop (luaState, 0); @@ -851,9 +852,9 @@ void py_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_ // } // // free (cb); -//} -// -//void lua_str_cb (struct tgl_state *TLSR, void *cb_extra, int success, char *data) { +} + +void py_str_cb (struct tgl_state *TLSR, void *cb_extra, int success, char *data) { // assert (TLSR == TLS); // struct lua_query_extra *cb = cb_extra; // lua_settop (luaState, 0); @@ -883,506 +884,295 @@ void py_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_ // } // // free (cb); -//} -// -//void lua_do_all (void) { -// int p = 0; -// while (p < pos) { -// int l = (long)lua_ptr[p ++]; -// assert (p + l + 1 <= pos); -// enum lua_query_type f = (long)lua_ptr[p ++]; -// struct tgl_message *M; -// char *s, *s1, *s2, *s3; -// switch (f) { -// case lq_contact_list: -// tgl_do_update_contact_list (TLS, lua_contact_list_cb, lua_ptr[p ++]); -// break; -// case lq_dialog_list: -// tgl_do_get_dialog_list (TLS, lua_dialog_list_cb, lua_ptr[p ++]); -// break; -// case lq_msg: -// tgl_do_send_message (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], strlen (lua_ptr[p + 2]), lua_msg_cb, lua_ptr[p]); -// free (lua_ptr[p + 2]); -// p += 3; -// break; -// case lq_send_typing: -// tgl_do_send_typing (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, tgl_typing_typing, lua_empty_cb, lua_ptr[p]); -// p += 2; -// break; -// case lq_send_typing_abort: -// tgl_do_send_typing (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, tgl_typing_cancel, lua_empty_cb, lua_ptr[p]); -// p += 2; -// break; -// case lq_rename_chat: -// tgl_do_rename_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); -// free (lua_ptr[p + 2]); -// p += 3; -// break; -// case lq_send_photo: -// tgl_do_send_document (TLS, -1, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); -// free (lua_ptr[p + 2]); -// p += 3; -// break; -// case lq_send_video: -// tgl_do_send_document (TLS, FLAG_DOCUMENT_VIDEO, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); -// free (lua_ptr[p + 2]); -// p += 3; -// break; -// case lq_send_audio: -// tgl_do_send_document (TLS, FLAG_DOCUMENT_AUDIO, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); -// free (lua_ptr[p + 2]); -// p += 3; -// break; -// case lq_send_document: -// tgl_do_send_document (TLS, 0, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); -// free (lua_ptr[p + 2]); -// p += 3; -// break; -// case lq_send_file: -// tgl_do_send_document (TLS, -2, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); -// free (lua_ptr[p + 2]); -// p += 3; -// break; -// case lq_send_text: -// tgl_do_send_text (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); -// free (lua_ptr[p + 2]); -// p += 3; -// break; -// case lq_chat_set_photo: -// tgl_do_set_chat_photo (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_msg_cb, lua_ptr[p]); -// free (lua_ptr[p + 2]); -// p += 3; -// break; -// case lq_load_photo: -// case lq_load_video: -// case lq_load_audio: -// case lq_load_document: -// M = lua_ptr[p + 1]; -// if (!M || (M->media.type != tgl_message_media_photo && M->media.type != tgl_message_media_photo_encr && M->media.type != tgl_message_media_document && M->media.type != tgl_message_media_document_encr)) { -// lua_file_cb (TLS, lua_ptr[p], 0, 0); -// } else { -// if (M->media.type == tgl_message_media_photo) { -// tgl_do_load_photo (TLS, &M->media.photo, lua_file_cb, lua_ptr[p]); -// } else if (M->media.type == tgl_message_media_document) { -// tgl_do_load_document (TLS, &M->media.document, lua_file_cb, lua_ptr[p]); -// } else { -// tgl_do_load_encr_document (TLS, &M->media.encr_document, lua_file_cb, lua_ptr[p]); -// } -// } -// p += 2; -// break; -// case lq_load_video_thumb: -// case lq_load_document_thumb: -// M = lua_ptr[p + 1]; -// if (!M || (M->media.type != tgl_message_media_document)) { -// lua_file_cb (TLS, lua_ptr[p], 0, 0); -// } else { -// tgl_do_load_document_thumb (TLS, &M->media.document, lua_file_cb, lua_ptr[p]); -// } -// p += 2; -// break; -// case lq_fwd: -// tgl_do_forward_message (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, ((struct tgl_message *)lua_ptr[p + 2])->id, lua_msg_cb, lua_ptr[p]); -// p += 3; -// break; -// case lq_fwd_media: -// tgl_do_forward_media (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, ((struct tgl_message *)lua_ptr[p + 2])->id, lua_msg_cb, lua_ptr[p]); -// p += 3; -// break; -// case lq_chat_info: -// tgl_do_get_chat_info (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, 0, lua_chat_cb, lua_ptr[p]); -// p += 2; -// break; -// case lq_user_info: -// tgl_do_get_user_info (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, 0, lua_user_cb, lua_ptr[p]); -// p += 2; -// break; -// case lq_history: -// tgl_do_get_history (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, (long)lua_ptr[p + 2], 0, lua_msg_list_cb, lua_ptr[p]); -// p += 3; -// break; -// case lq_chat_add_user: -// tgl_do_add_user_to_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, ((tgl_peer_t *)lua_ptr[p + 2])->id, 10, lua_msg_cb, lua_ptr[p]); -// p += 3; -// break; -// case lq_chat_del_user: -// tgl_do_del_user_from_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, ((tgl_peer_t *)lua_ptr[p + 2])->id, lua_msg_cb, lua_ptr[p]); -// p += 3; -// break; -// case lq_add_contact: -// s1 = lua_ptr[p + 1]; -// s2 = lua_ptr[p + 2]; -// s3 = lua_ptr[p + 3]; -// tgl_do_add_contact (TLS, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), 0, lua_contact_list_cb, lua_ptr[p]); -// free (s1); -// free (s2); -// free (s3); -// p += 4; -// break; -// case lq_del_contact: -// tgl_do_del_contact (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_empty_cb, lua_ptr[p]); -// p += 2; -// break; -// case lq_rename_contact: -// s1 = lua_ptr[p + 1]; -// s2 = lua_ptr[p + 2]; -// s3 = lua_ptr[p + 3]; -// tgl_do_add_contact (TLS, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), 1, lua_contact_list_cb, lua_ptr[p]); -// free (s1); -// free (s2); -// free (s3); -// p += 4; -// break; -// case lq_search: -// s = lua_ptr[p + 2]; -// tgl_do_msg_search (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, 0, 0, 40, 0, s, lua_msg_list_cb, lua_ptr[p]); -// free (s); -// p += 3; -// break; -// case lq_global_search: -// s = lua_ptr[p + 1]; -// tgl_do_msg_search (TLS, tgl_set_peer_id (TGL_PEER_UNKNOWN, 0), 0, 0, 40, 0, s, lua_msg_list_cb, lua_ptr[p]); -// free (s); -// p += 2; -// break; -// case lq_mark_read: -// tgl_do_mark_read (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_empty_cb, lua_ptr[p]); -// p += 2; -// break; -// case lq_set_profile_photo: -// s = lua_ptr[p + 1]; -// tgl_do_set_profile_photo (TLS, s, lua_empty_cb, lua_ptr[p]); -// free (s); -// p += 2; -// break; -// case lq_set_profile_name: -// s1 = lua_ptr[p + 1]; -// s2 = lua_ptr[p + 1]; -// tgl_do_set_profile_name (TLS, s1, s2, lua_user_cb, lua_ptr[p]); -// free (s1); -// free (s2); -// p += 3; -// break; -// case lq_create_secret_chat: -// tgl_do_create_secret_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_secret_chat_cb, lua_ptr[p]); -// p += 2; -// break; -// case lq_create_group_chat: -// s = lua_ptr[p + 2]; -// tgl_do_create_group_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, s, lua_msg_cb, lua_ptr[p]); -// free (s); -// p += 3; -// break; -// case lq_delete_msg: -// tgl_do_delete_msg (TLS, ((struct tgl_message *)lua_ptr[p + 1])->id, lua_empty_cb, lua_ptr[p]); -// p += 2; -// break; -// case lq_restore_msg: -// tgl_do_delete_msg (TLS, (long)lua_ptr[p + 1], lua_empty_cb, lua_ptr[p]); -// p += 2; -// break; -// case lq_accept_secret_chat: -// tgl_do_accept_encr_chat_request (TLS, lua_ptr[p + 1], lua_secret_chat_cb, lua_ptr[p]); -// p += 2; -// break; -// case lq_send_contact: -// s1 = lua_ptr[p + 2]; -// s2 = lua_ptr[p + 3]; -// s3 = lua_ptr[p + 4]; -// tgl_do_send_contact (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), lua_msg_cb, lua_ptr[p]); -// free (s1); -// free (s2); -// free (s3); -// p += 5; -// break; -// case lq_status_online: -// tgl_do_update_status (TLS, 1, lua_empty_cb, lua_ptr[p]); -// p ++; -// break; -// case lq_status_offline: -// tgl_do_update_status (TLS, 0, lua_empty_cb, lua_ptr[p]); -// p ++; -// break; -// case lq_extf: -// s = lua_ptr[p + 1]; -// tgl_do_send_extf (TLS, s, strlen (s), lua_str_cb, lua_ptr[p]); -// free (s); -// p += 2; -// break; -// case lq_send_location: -// if (sizeof (void *) == 4) { -// tgl_do_send_location (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id , *(float *)(lua_ptr + p + 2), *(float *)(lua_ptr + p + 3), lua_msg_cb, lua_ptr[p]); -// } else { -// tgl_do_send_location (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id , *(double *)(lua_ptr + p + 2), *(double *)(lua_ptr + p + 3), lua_msg_cb, lua_ptr[p]); -// } -// p += 4; -// break; -// /* -// lq_delete_msg, -// lq_restore_msg, -// case 0: -// tgl_do_send_message (((tgl_peer_t *)lua_ptr[p])->id, lua_ptr[p + 1], strlen (lua_ptr[p + 1]), 0, 0); -// free (lua_ptr[p + 1]); -// p += 2; -// break; -// case 1: -// tgl_do_forward_message (((tgl_peer_t *)lua_ptr[p])->id, (long)lua_ptr[p + 1], 0, 0); -// p += 2; -// break; -// case 2: -// tgl_do_mark_read (((tgl_peer_t *)lua_ptr[p])->id, 0, 0); -// p += 1; -// break;*/ -// default: -// assert (0); -// } -// } -// pos = 0; -//} -// -// -//enum lua_function_param { -// lfp_none, -// lfp_peer, -// lfp_chat, -// lfp_user, -// lfp_secret_chat, -// lfp_string, -// lfp_number, -// lfp_positive_number, -// lfp_nonnegative_number, -// lfp_msg, -// lfp_double -//}; -// -//struct lua_function { -// char *name; -// enum lua_query_type type; -// enum lua_function_param params[10]; -//}; -// +} -PyObject* py_send_msg(PyObject *self, PyObject *args) { - const char *msg; - tgl_peer_id_t id; +void py_do_all (void) { + int p = 0; + while (p < pos) { + assert (p + 1 <= pos); - if (!PyArg_ParseTuple(args, "iis", &id.type, &id.id, &msg)) - return NULL; + enum py_query_type f = (long)py_ptr[p ++]; + PyObject *args = (PyObject *)py_ptr[p ++]; + char *s, *s1, *s2, *s3, *s4; + struct tgl_message *M; + tgl_peer_id_t peer; - tgl_do_send_message (TLS, (tgl_peer_id_t) id, msg, strlen (msg), py_msg_cb, args); + switch (f) { + case pq_contact_list: + tgl_do_update_contact_list (TLS, py_contact_list_cb, NULL); + break; + case pq_dialog_list: + tgl_do_get_dialog_list (TLS, py_dialog_list_cb, NULL); + break; + case pq_msg: + PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &s1); + + tgl_do_send_message (TLS, peer, s1, strlen (s1), py_msg_cb, NULL); + break; + case pq_send_typing: + tgl_do_send_typing (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, tgl_typing_typing, py_empty_cb, py_ptr[p]); + break; + case pq_send_typing_abort: + tgl_do_send_typing (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, tgl_typing_cancel, py_empty_cb, py_ptr[p]); + break; + case pq_rename_chat: + tgl_do_rename_chat (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, py_ptr[p + 2], py_msg_cb, py_ptr[p]); + break; + case pq_send_photo: + tgl_do_send_document (TLS, -1, ((tgl_peer_t *)py_ptr[p + 1])->id, py_ptr[p + 2], py_msg_cb, py_ptr[p]); + break; + case pq_send_video: + tgl_do_send_document (TLS, FLAG_DOCUMENT_VIDEO, ((tgl_peer_t *)py_ptr[p + 1])->id, py_ptr[p + 2], py_msg_cb, py_ptr[p]); + break; + case pq_send_audio: + tgl_do_send_document (TLS, FLAG_DOCUMENT_AUDIO, ((tgl_peer_t *)py_ptr[p + 1])->id, py_ptr[p + 2], py_msg_cb, py_ptr[p]); + break; + case pq_send_document: + tgl_do_send_document (TLS, 0, ((tgl_peer_t *)py_ptr[p + 1])->id, py_ptr[p + 2], py_msg_cb, py_ptr[p]); + break; + case pq_send_file: + tgl_do_send_document (TLS, -2, ((tgl_peer_t *)py_ptr[p + 1])->id, py_ptr[p + 2], py_msg_cb, py_ptr[p]); + break; + case pq_send_text: + tgl_do_send_text (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, py_ptr[p + 2], py_msg_cb, py_ptr[p]); + break; + case pq_chat_set_photo: + tgl_do_set_chat_photo (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, py_ptr[p + 2], py_msg_cb, py_ptr[p]); + break; + case pq_load_photo: + case pq_load_video: + case pq_load_audio: + case pq_load_document: + M = py_ptr[p + 1]; + if (!M || (M->media.type != tgl_message_media_photo && M->media.type != tgl_message_media_photo_encr && M->media.type != tgl_message_media_document && M->media.type != tgl_message_media_document_encr)) { + py_file_cb (TLS, py_ptr[p], 0, 0); + } else { + if (M->media.type == tgl_message_media_photo) { + tgl_do_load_photo (TLS, &M->media.photo, py_file_cb, py_ptr[p]); + } else if (M->media.type == tgl_message_media_document) { + tgl_do_load_document (TLS, &M->media.document, py_file_cb, py_ptr[p]); + } else { + tgl_do_load_encr_document (TLS, &M->media.encr_document, py_file_cb, py_ptr[p]); + } + } + break; + case pq_load_video_thumb: + case pq_load_document_thumb: + M = py_ptr[p + 1]; + if (!M || (M->media.type != tgl_message_media_document)) { + py_file_cb (TLS, py_ptr[p], 0, 0); + } else { + tgl_do_load_document_thumb (TLS, &M->media.document, py_file_cb, py_ptr[p]); + } + break; + case pq_fwd: + tgl_do_forward_message (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, ((struct tgl_message *)py_ptr[p + 2])->id, py_msg_cb, py_ptr[p]); + break; + case pq_fwd_media: + tgl_do_forward_media (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, ((struct tgl_message *)py_ptr[p + 2])->id, py_msg_cb, py_ptr[p]); + break; + case pq_chat_info: + tgl_do_get_chat_info (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, 0, py_chat_cb, py_ptr[p]); + break; + case pq_user_info: + tgl_do_get_user_info (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, 0, py_user_cb, py_ptr[p]); + break; + case pq_history: + tgl_do_get_history (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, (long)py_ptr[p + 2], 0, py_msg_list_cb, py_ptr[p]); + break; + case pq_chat_add_user: + tgl_do_add_user_to_chat (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, ((tgl_peer_t *)py_ptr[p + 2])->id, 10, py_msg_cb, py_ptr[p]); + break; + case pq_chat_del_user: + tgl_do_del_user_from_chat (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, ((tgl_peer_t *)py_ptr[p + 2])->id, py_msg_cb, py_ptr[p]); + break; + case pq_add_contact: + tgl_do_add_contact (TLS, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), 0, py_contact_list_cb, py_ptr[p]); + break; + case pq_del_contact: + tgl_do_del_contact (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, py_empty_cb, py_ptr[p]); + break; + case pq_rename_contact: + tgl_do_add_contact (TLS, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), 1, py_contact_list_cb, py_ptr[p]); + break; + case pq_search: + tgl_do_msg_search (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, 0, 0, 40, 0, s, py_msg_list_cb, py_ptr[p]); + break; + case pq_global_search: + tgl_do_msg_search (TLS, tgl_set_peer_id (TGL_PEER_UNKNOWN, 0), 0, 0, 40, 0, s, py_msg_list_cb, py_ptr[p]); + break; + case pq_mark_read: + tgl_do_mark_read (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, py_empty_cb, py_ptr[p]); + break; + case pq_set_profile_photo: + tgl_do_set_profile_photo (TLS, s, py_empty_cb, py_ptr[p]); + break; + case pq_set_profile_name: + tgl_do_set_profile_name (TLS, s1, s2, py_user_cb, py_ptr[p]); + break; + case pq_create_secret_chat: + tgl_do_create_secret_chat (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, py_secret_chat_cb, py_ptr[p]); + break; + case pq_create_group_chat: + tgl_do_create_group_chat (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, s, py_msg_cb, py_ptr[p]); + break; + case pq_delete_msg: + tgl_do_delete_msg (TLS, ((struct tgl_message *)py_ptr[p + 1])->id, py_empty_cb, py_ptr[p]); + break; + case pq_restore_msg: + tgl_do_delete_msg (TLS, (long)py_ptr[p + 1], py_empty_cb, py_ptr[p]); + break; + case pq_accept_secret_chat: + tgl_do_accept_encr_chat_request (TLS, py_ptr[p + 1], py_secret_chat_cb, py_ptr[p]); + break; + case pq_send_contact: + tgl_do_send_contact (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), py_msg_cb, py_ptr[p]); + break; + case pq_status_online: + tgl_do_update_status (TLS, 1, py_empty_cb, py_ptr[p]); + break; + case pq_status_offline: + tgl_do_update_status (TLS, 0, py_empty_cb, py_ptr[p]); + break; + case pq_extf: + tgl_do_send_extf (TLS, s, strlen (s), py_str_cb, py_ptr[p]); + break; + case pq_send_location: + if (sizeof (void *) == 4) { + tgl_do_send_location (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id , *(float *)(py_ptr + p + 2), *(float *)(py_ptr + p + 3), py_msg_cb, py_ptr[p]); + } else { + tgl_do_send_location (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id , *(double *)(py_ptr + p + 2), *(double *)(py_ptr + p + 3), py_msg_cb, py_ptr[p]); + } + break; + /* + pq_delete_msg, + pq_restore_msg, + case 0: + tgl_do_send_message (((tgl_peer_t *)py_ptr[p])->id, py_ptr[p + 1], strlen (py_ptr[p + 1]), 0, 0); + free (py_ptr[p + 1]); + p += 2; + break; + case 1: + tgl_do_forward_message (((tgl_peer_t *)py_ptr[p])->id, (long)py_ptr[p + 1], 0, 0); + p += 2; + break; + case 2: + tgl_do_mark_read (((tgl_peer_t *)py_ptr[p])->id, 0, 0); + p += 1; + break;*/ + default: + assert (0); + } + Py_DECREF(args); + } + pos = 0; +} - return PyString_FromString("sent!"); -} +PyObject* push_py_func(enum py_query_type type, PyObject *args) { + assert(pos + 2 < MAX_PY_COMMANDS); + py_ptr[pos ++] = (void *)(long)type; + py_ptr[pos ++] = (void *)args; + + Py_INCREF(args); + Py_RETURN_TRUE; +} + +// Register functions to push commands on the queue +PyObject* py_contact_list(PyObject *self, PyObject *args) { return push_py_func(pq_contact_list, args); } +PyObject* py_dialog_list(PyObject *self, PyObject *args) { return push_py_func(pq_dialog_list, args); } +PyObject* py_rename_chat(PyObject *self, PyObject *args) { return push_py_func(pq_rename_chat, args); } +PyObject* py_send_msg(PyObject *self, PyObject *args) { return push_py_func(pq_msg, args); } +PyObject* py_send_typing(PyObject *self, PyObject *args) { return push_py_func(pq_send_typing, args); } +PyObject* py_send_typing_abort(PyObject *self, PyObject *args) { return push_py_func(pq_send_typing_abort, args); } +PyObject* py_send_photo(PyObject *self, PyObject *args) { return push_py_func(pq_send_photo, args); } +PyObject* py_send_video(PyObject *self, PyObject *args) { return push_py_func(pq_send_video, args); } +PyObject* py_send_audio(PyObject *self, PyObject *args) { return push_py_func(pq_send_audio, args); } +PyObject* py_send_document(PyObject *self, PyObject *args) { return push_py_func(pq_send_document, args); } +PyObject* py_send_file(PyObject *self, PyObject *args) { return push_py_func(pq_send_file, args); } +PyObject* py_send_text(PyObject *self, PyObject *args) { return push_py_func(pq_send_text, args); } +PyObject* py_chat_set_photo(PyObject *self, PyObject *args) { return push_py_func(pq_chat_set_photo, args); } +PyObject* py_load_photo(PyObject *self, PyObject *args) { return push_py_func(pq_load_photo, args); } +PyObject* py_load_video(PyObject *self, PyObject *args) { return push_py_func(pq_load_video, args); } +PyObject* py_load_video_thumb(PyObject *self, PyObject *args) { return push_py_func(pq_load_video_thumb, args); } +PyObject* py_load_audio(PyObject *self, PyObject *args) { return push_py_func(pq_load_audio, args); } +PyObject* py_load_document(PyObject *self, PyObject *args) { return push_py_func(pq_load_document, args); } +PyObject* py_load_document_thumb(PyObject *self, PyObject *args) { return push_py_func(pq_load_document_thumb, args); } +PyObject* py_fwd(PyObject *self, PyObject *args) { return push_py_func(pq_fwd, args); } +PyObject* py_fwd_media(PyObject *self, PyObject *args) { return push_py_func(pq_fwd_media, args); } +PyObject* py_chat_info(PyObject *self, PyObject *args) { return push_py_func(pq_chat_info, args); } +PyObject* py_user_info(PyObject *self, PyObject *args) { return push_py_func(pq_chat_info, args); } +PyObject* py_history(PyObject *self, PyObject *args) { return push_py_func(pq_history, args); } +PyObject* py_chat_add_user(PyObject *self, PyObject *args) { return push_py_func(pq_chat_add_user, args); } +PyObject* py_chat_del_user(PyObject *self, PyObject *args) { return push_py_func(pq_chat_del_user, args); } +PyObject* py_add_contact(PyObject *self, PyObject *args) { return push_py_func(pq_add_contact, args); } +PyObject* py_del_contact(PyObject *self, PyObject *args) { return push_py_func(pq_del_contact, args); } +PyObject* py_rename_contact(PyObject *self, PyObject *args) { return push_py_func(pq_rename_contact, args); } +PyObject* py_search(PyObject *self, PyObject *args) { return push_py_func(pq_search, args); } +PyObject* py_global_search(PyObject *self, PyObject *args) { return push_py_func(pq_global_search, args); } +PyObject* py_mark_read(PyObject *self, PyObject *args) { return push_py_func(pq_mark_read, args); } +PyObject* py_set_profile_photo(PyObject *self, PyObject *args) { return push_py_func(pq_set_profile_photo, args); } +PyObject* py_set_profile_name(PyObject *self, PyObject *args) { return push_py_func(pq_set_profile_name, args); } +PyObject* py_create_secret_chat(PyObject *self, PyObject *args) { return push_py_func(pq_create_secret_chat, args); } +PyObject* py_create_group_chat(PyObject *self, PyObject *args) { return push_py_func(pq_create_group_chat, args); } +PyObject* py_delete_msg(PyObject *self, PyObject *args) { return push_py_func(pq_delete_msg, args); } +PyObject* py_restore_msg(PyObject *self, PyObject *args) { return push_py_func(pq_restore_msg, args); } +PyObject* py_accept_secret_chat(PyObject *self, PyObject *args) { return push_py_func(pq_accept_secret_chat, args); } +PyObject* py_send_contact(PyObject *self, PyObject *args) { return push_py_func(pq_send_contact, args); } +PyObject* py_status_online(PyObject *self, PyObject *args) { return push_py_func(pq_status_online, args); } +PyObject* py_status_offline(PyObject *self, PyObject *args) { return push_py_func(pq_status_offline, args); } +PyObject* py_send_location(PyObject *self, PyObject *args) { return push_py_func(pq_send_location, args); } +PyObject* py_extf(PyObject *self, PyObject *args) { return push_py_func(pq_extf, args); } static PyMethodDef py_tgl_methods[] = { -// {"get_contact_list", lq_contact_list, METH_VARARGS}, -// {"get_dialog_list", lq_dialog_list, METH_VARARGS}, -// {"rename_chat", lq_rename_chat, METH_VARARGS}, + {"get_contact_list", py_contact_list, METH_VARARGS, "retrieve contact list"}, + {"get_dialog_list", py_dialog_list, METH_VARARGS, ""}, + {"rename_chat", py_rename_chat, METH_VARARGS, ""}, {"send_msg", py_send_msg, METH_VARARGS, "send message to user or chat"}, -// {"send_typing", lq_send_typing, METH_VARARGS}, -// {"send_typing_abort", lq_send_typing_abort, METH_VARARGS}, -// {"send_photo", lq_send_photo, { lfp_peer, lfp_string, lfp_none }}, -// {"send_video", lq_send_video, { lfp_peer, lfp_string, lfp_none }}, -// {"send_audio", lq_send_audio, { lfp_peer, lfp_string, lfp_none }}, -// {"send_document", lq_send_document, { lfp_peer, lfp_string, lfp_none }}, -// {"send_file", lq_send_file, { lfp_peer, lfp_string, lfp_none }}, -// {"send_text", lq_send_text, { lfp_peer, lfp_string, lfp_none }}, -// {"chat_set_photo", lq_chat_set_photo, { lfp_chat, lfp_string, lfp_none }}, -// {"load_photo", lq_load_photo, { lfp_msg, lfp_none }}, -// {"load_video", lq_load_video, { lfp_msg, lfp_none }}, -// {"load_video_thumb", lq_load_video_thumb, { lfp_msg, lfp_none }}, -// {"load_audio", lq_load_audio, { lfp_msg, lfp_none }}, -// {"load_document", lq_load_document, { lfp_msg, lfp_none }}, -// {"load_document_thumb", lq_load_document_thumb, { lfp_msg, lfp_none }}, -// {"fwd_msg", lq_fwd, { lfp_peer, lfp_msg, lfp_none }}, -// {"fwd_media", lq_fwd_media, { lfp_peer, lfp_msg, lfp_none }}, -// {"chat_info", lq_chat_info, { lfp_chat, lfp_none }}, -// {"user_info", lq_user_info, { lfp_user, lfp_none }}, -// {"get_history", lq_history, { lfp_peer, lfp_nonnegative_number, lfp_none }}, -// {"chat_add_user", lq_chat_add_user, { lfp_chat, lfp_user, lfp_none }}, -// {"chat_del_user", lq_chat_del_user, { lfp_chat, lfp_user, lfp_none }}, -// {"add_contact", lq_add_contact, { lfp_string, lfp_string, lfp_string, lfp_none }}, -// {"del_contact", lq_del_contact, { lfp_user, lfp_none }}, -// {"rename_contact", lq_rename_contact, { lfp_string, lfp_string, lfp_string, lfp_none }}, -// {"msg_search", lq_search, { lfp_peer, lfp_string, lfp_none }}, -// {"msg_global_search", lq_global_search, { lfp_string, lfp_none }}, -// {"mark_read", lq_mark_read, { lfp_peer, lfp_none }}, -// {"set_profile_photo", lq_set_profile_photo, { lfp_string, lfp_none }}, -// {"set_profile_name", lq_set_profile_name, { lfp_string, lfp_none }}, -// {"create_secret_chat", lq_create_secret_chat, { lfp_user, lfp_none }}, -// {"create_group_chat", lq_create_group_chat, { lfp_user, lfp_string, lfp_none }}, -// {"delete_msg", lq_delete_msg, { lfp_msg, lfp_none }}, -// {"restore_msg", lq_restore_msg, { lfp_positive_number, lfp_none }}, -// {"accept_secret_chat", lq_accept_secret_chat, { lfp_secret_chat, lfp_none }}, -// {"send_contact", lq_send_contact, { lfp_peer, lfp_string, lfp_string, lfp_string, lfp_none }}, -// {"status_online", lq_status_online, { lfp_none }}, -// {"status_offline", lq_status_offline, { lfp_none }}, -// {"send_location", lq_send_location, { lfp_peer, lfp_double, lfp_double, lfp_none }}, -// {"ext_function", lq_extf, { lfp_string, lfp_none }}, + {"send_typing", py_send_typing, METH_VARARGS, ""}, + {"send_typing_abort", py_send_typing_abort, METH_VARARGS, ""}, + {"send_photo", py_send_photo, METH_VARARGS, ""}, + {"send_video", py_send_video, METH_VARARGS, ""}, + {"send_audio", py_send_audio, METH_VARARGS, ""}, + {"send_document", py_send_document, METH_VARARGS, ""}, + {"send_file", py_send_file, METH_VARARGS, ""}, + {"send_text", py_send_text, METH_VARARGS, ""}, + {"chat_set_photo", py_chat_set_photo, METH_VARARGS, ""}, + {"load_photo", py_load_photo, METH_VARARGS, ""}, + {"load_video", py_load_video, METH_VARARGS, ""}, + {"load_video_thumb", py_load_video_thumb, METH_VARARGS, ""}, + {"load_audio", py_load_audio, METH_VARARGS, ""}, + {"load_document", py_load_document, METH_VARARGS, ""}, + {"load_document_thumb", py_load_document_thumb, METH_VARARGS, ""}, + {"fwd_msg", py_fwd, METH_VARARGS, ""}, + {"fwd_media", py_fwd_media, METH_VARARGS, ""}, + {"chat_info", py_chat_info, METH_VARARGS, ""}, + {"user_info", py_user_info, METH_VARARGS, ""}, + {"get_history", py_history, METH_VARARGS, ""}, + {"chat_add_user", py_chat_add_user, METH_VARARGS, ""}, + {"chat_del_user", py_chat_del_user, METH_VARARGS, ""}, + {"add_contact", py_add_contact, METH_VARARGS, ""}, + {"del_contact", py_del_contact, METH_VARARGS, ""}, + {"rename_contact", py_rename_contact, METH_VARARGS, ""}, + {"msg_search", py_search, METH_VARARGS, ""}, + {"msg_global_search", py_global_search, METH_VARARGS, ""}, + {"mark_read", py_mark_read, METH_VARARGS, ""}, + {"set_profile_photo", py_set_profile_photo, METH_VARARGS, ""}, + {"set_profile_name", py_set_profile_name, METH_VARARGS, ""}, + {"create_secret_chat", py_create_secret_chat, METH_VARARGS, ""}, + {"create_group_chat", py_create_group_chat, METH_VARARGS, ""}, + {"delete_msg", py_delete_msg, METH_VARARGS, ""}, + {"restore_msg", py_restore_msg, METH_VARARGS, ""}, + {"accept_secret_chat", py_accept_secret_chat, METH_VARARGS, ""}, + {"send_contact", py_send_contact, METH_VARARGS, ""}, + {"status_online", py_status_online, METH_VARARGS, ""}, + {"status_offline", py_status_offline, METH_VARARGS, ""}, + {"send_location", py_send_location, METH_VARARGS, ""}, + {"ext_function", py_extf, METH_VARARGS, ""}, { NULL, NULL, 0, NULL } }; -//static int parse_lua_function (lua_State *L, struct lua_function *F) { -// int p = 0; -// while (F->params[p] != lfp_none) { p ++; } -// if (lua_gettop (L) != p + 2) { -// lua_pushboolean (L, 0); -// return 1; -// } -// -// int a1 = luaL_ref (L, LUA_REGISTRYINDEX); -// int a2 = luaL_ref (L, LUA_REGISTRYINDEX); -// -// struct lua_query_extra *e = malloc (sizeof (*e)); -// assert (e); -// e->func = a2; -// e->param = a1; -// -// assert (pos + 3 + p < MAX_LUA_COMMANDS); -// -// lua_ptr[pos ++] = (void *)(long)(p + 1); -// lua_ptr[pos ++] = (void *)(long)F->type; -// lua_ptr[pos ++] = e; -// -// int sp = p; -// int ok = 1; -// int cc = 0; -// while (p > 0) { -// p --; -// cc ++; -// const char *s; -// tgl_peer_t *P; -// long long num; -// double dval; -// struct tgl_message *M; -// switch (F->params[p]) { -// case lfp_none: -// assert (0); -// break; -// case lfp_peer: -// case lfp_user: -// case lfp_chat: -// case lfp_secret_chat: -// s = lua_tostring (L, -cc); -// if (!s) { -// ok = 0; -// break; -// } -// if (sscanf (s, "user#id%lld", &num) == 1 && num > 0) { -// tgl_insert_empty_user (TLS, num); -// P = tgl_peer_get (TLS, TGL_MK_USER (num)); -// } else if (sscanf (s, "chat#id%lld", &num) == 1 && num > 0) { -// tgl_insert_empty_chat (TLS, num); -// P = tgl_peer_get (TLS, TGL_MK_CHAT (num)); -// } else { -// P = get_peer (s); -// } -// if (!P/* || !(P->flags & FLAG_CREATED)*/) { -// ok = 0; -// break; -// } -// if (F->params[p] != lfp_peer) { -// if ((tgl_get_peer_type (P->id) == TGL_PEER_USER && F->params[p] != lfp_user) || -// (tgl_get_peer_type (P->id) == TGL_PEER_CHAT && F->params[p] != lfp_chat) || -// (tgl_get_peer_type (P->id) == TGL_PEER_ENCR_CHAT && F->params[p] != lfp_secret_chat)) { -// ok = 0; -// break; -// } -// } -// lua_ptr[pos + p] = P; -// break; -// -// case lfp_string: -// s = lua_tostring (L, -cc); -// if (!s) { -// ok = 0; -// break; -// } -// lua_ptr[pos + p] = (void *)s; -// break; -// -// case lfp_number: -// num = lua_tonumber (L, -cc); -// -// lua_ptr[pos + p] = (void *)(long)num; -// break; -// -// case lfp_double: -// dval = lua_tonumber (L, -cc); -// -// if (sizeof (void *) == 4) { -// *(float *)(lua_ptr + pos + p) = dval; -// } else { -// assert (sizeof (void *) >= 8); -// *(double *)(lua_ptr + pos + p) = dval; -// } -// break; -// -// case lfp_positive_number: -// num = lua_tonumber (L, -cc); -// if (num <= 0) { -// ok = 0; -// break; -// } -// -// lua_ptr[pos + p] = (void *)(long)num; -// break; -// -// case lfp_nonnegative_number: -// num = lua_tonumber (L, -cc); -// if (num < 0) { -// ok = 0; -// break; -// } -// -// lua_ptr[pos + p] = (void *)(long)num; -// break; -// -// case lfp_msg: -// s = lua_tostring (L, -cc); -// if (!s || !strlen (s)) { -// ok = 0; -// break; -// } -// -// num = atoll (s); -// -// M = tgl_message_get (TLS, num); -// -// if (!M || !(M->flags & FLAG_CREATED)) { -// ok = 0; -// break; -// } -// -// lua_ptr[pos + p] = M; -// break; -// -// default: -// assert (0); -// } -// } -// if (!ok) { -// luaL_unref (luaState, LUA_REGISTRYINDEX, a1); -// luaL_unref (luaState, LUA_REGISTRYINDEX, a2); -// free (e); -// pos -= 3; -// lua_pushboolean (L, 0); -// return 1; -// } -// -// for (p = 0; p < sp; p++) { -// if (F->params[p] == lfp_string) { -// lua_ptr[pos + p] = strdup (lua_ptr[pos + p]); -// } -// } -// pos += p; -// -// lua_pushboolean (L, 1); -// return 1; -//} -// -// + //static void lua_postpone_alarm (evutil_socket_t fd, short what, void *arg) { // int *t = arg; // @@ -1439,7 +1229,7 @@ static PyMethodDef py_tgl_methods[] = { // lua_pushboolean (L, 1); // return 1; //} -// + //extern int safe_quit; //static int safe_quit_from_lua (lua_State *L) { // int n = lua_gettop (L); @@ -1453,24 +1243,7 @@ static PyMethodDef py_tgl_methods[] = { // return 1; //} // -//static int universal_from_lua (lua_State *L) { -// const char *s = lua_tostring(L, lua_upvalueindex(1)); -// if (!s) { -// lua_pushboolean (L, 0); -// return 1; -// } -// int i = 0; -// while (functions[i].name) { -// if (!strcmp (functions[i].name, s)) { -// return parse_lua_function (L, &functions[i]); -// } -// i ++; -// } -// lua_pushboolean (L, 0); -// return 1; -//} -// -// + #define my_python_register(dict, name, f) \ f = PyDict_GetItemString(dict, name); @@ -1507,48 +1280,5 @@ void py_init (const char *file) { my_python_register(pDict, "on_secret_chat_update", _py_secret_chat_update); my_python_register(pDict, "on_user_update", _py_user_update); my_python_register(pDict, "on_chat_update", _py_chat_update); - - -// PyObject* err = PyErr_Occurred(); -// if (err != NULL) { -// logprintf("python error occurred"); // TODO: implement the backtrace -// exit(1); -// } - -// int i = 0; -// while (functions[i].name) { -// my_lua_register (luaState, functions[i].name, universal_from_lua); -// i ++; -// } - //lua_register (luaState, "fwd_msg", fwd_msg_from_lua); - //lua_register (luaState, "mark_read", mark_read_from_lua); -// lua_register (luaState, "postpone", postpone_from_lua); -// lua_register (luaState, "safe_quit", safe_quit_from_lua); - //lua_register (luaState, "get_contact_list", get_contacts_from_lua); - /*lua_register (luaState, "get_dialog_list", get_dialog_list_from_lua); - lua_register (luaState, "send_msg", send_msg_from_lua); - lua_register (luaState, "rename_chat", rename_chat_from_lua); - lua_register (luaState, "send_photo", send_photo_from_lua); - lua_register (luaState, "send_video", send_video_from_lua); - lua_register (luaState, "send_audio", send_audio_from_lua); - lua_register (luaState, "send_document", send_document_from_lua); - lua_register (luaState, "send_text", send_text_from_lua); - lua_register (luaState, "chat_set_photo", chat_set_photo_from_lua); - lua_register (luaState, "load_photo", load_photo_from_lua); - lua_register (luaState, "load_video", load_video_from_lua); - lua_register (luaState, "load_video_thumb", load_video_thumb_from_lua); - lua_register (luaState, "load_audio", load_audio_from_lua); - lua_register (luaState, "load_document", load_document_from_lua); - lua_register (luaState, "load_document_thumb", load_document_thumb_from_lua); - lua_register (luaState, "fwd_msg", message_forward_from_lua); - lua_register (luaState, "chat_info", chat_info_from_lua); - lua_register (luaState, "user_info", user_info_from_lua); - lua_register (luaState, "get_history", get_history_from_lua); - lua_register (luaState, "chat_add_user", chat_add_user_from_lua); - lua_register (luaState, "chat_del_user", chat_del_user_from_lua); - lua_register (luaState, "add_contact", add_contact_from_lua); - lua_register (luaState, "rename_contact", rename_contact_from_lua);*/ - } -#endif diff --git a/test.lua b/test.lua index 00d2a6b..321f345 100644 --- a/test.lua +++ b/test.lua @@ -57,17 +57,6 @@ function get_title (P, Q) end end -local lgi = require ('lgi') -local notify = lgi.require('Notify') -notify.init ("Telegram updates") -local icon = os.getenv("HOME") .. "/.telegram-cli/telegram-pics/telegram_64.png" - -function do_notify (user, msg) - local n = notify.Notification.new(user, msg, icon) - n:show () -end - --- }}} function on_msg_receive (msg) if started == 0 then @@ -76,7 +65,6 @@ function on_msg_receive (msg) if msg.out then return end - do_notify (get_title (msg.from, msg.to), msg.text) if (msg.text == 'ping') then if (msg.to.id == our_id) then From f1c8af606fa35f372340d87d248e938990ff9ee6 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Wed, 6 May 2015 23:54:31 -0700 Subject: [PATCH 12/29] Complete basic API implementation. Callbacks and various functions TODO --- loop.c | 8 ++++ pytest.py | 27 +++++++++-- python-tg.c | 135 ++++++++++++++++++++++++++++++---------------------- 3 files changed, 109 insertions(+), 61 deletions(-) diff --git a/loop.c b/loop.c index 653aae6..87cbfe6 100644 --- a/loop.c +++ b/loop.c @@ -656,6 +656,10 @@ void on_started (struct tgl_state *TLS) { lua_diff_end (); #endif + #ifdef USE_PYTHON + py_diff_end (); + #endif + if (start_command) { safe_quit = 1; while (*start_command) { @@ -708,6 +712,10 @@ int loop (void) { lua_binlog_end (); #endif + #ifdef USE_PYTHON + py_binlog_end (); + #endif + if (sfd >= 0) { struct event *ev = event_new (TLS->ev_base, sfd, EV_READ | EV_PERSIST, accept_incoming, 0); event_add (ev, 0); diff --git a/pytest.py b/pytest.py index 85de40a..d890292 100644 --- a/pytest.py +++ b/pytest.py @@ -1,12 +1,16 @@ import tgl +import geopy import pprint +from geopy.geocoders import Nominatim our_id = 0 pp = pprint.PrettyPrinter(indent=4) +binlog_done = False; + def on_binlog_replay_end(): - pass + binlog_done = True; def on_get_difference_end(): pass @@ -16,10 +20,27 @@ def on_our_id(id): return "Set ID: " + str(our_id) def on_msg_receive(msg): - if msg["out"]: + if msg["out"] and not binlog_done: return; - tgl.send_msg(msg["from"]["type"], msg["from"]["id"], "PONG!") + if msg["to"]["id"] == our_id: # direct message + ptype = msg["from"]["type"] + pid = msg["from"]["id"] + else: # chatroom + ptype = msg["to"]["type"] + pid = msg["to"]["id"] + + text = msg["text"] + + if text.startswith("!ping"): + tgl.send_msg(ptype, pid, "PONG!") +d + + if text.startswith("!location"): + geolocator = Nominatim() + location = geolocator.geocode(msg["text"][9:]) + pp.pprint(location) + tgl.send_location(ptype, pid, location.latitude, location.longitude) def on_secret_chat_update(peer, types): return "on_secret_chat_update" diff --git a/python-tg.c b/python-tg.c index 28f4f8f..5800620 100644 --- a/python-tg.c +++ b/python-tg.c @@ -47,7 +47,7 @@ extern int verbosity; extern struct tgl_state *TLS; -static int have_file; +static int python_loaded; // Python update function callables PyObject *_py_binlog_end; @@ -363,7 +363,7 @@ PyObject* get_message (struct tgl_message *M) { } void py_binlog_end (void) { - if (!have_file) { return; } + if (!python_loaded) { return; } PyObject *arglist, *result; @@ -371,13 +371,13 @@ void py_binlog_end (void) { result = PyEval_CallObject(_py_binlog_end, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); - else + else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); } void py_diff_end (void) { - if (!have_file) { return; } + if (!python_loaded) { return; } PyObject *arglist, *result; @@ -385,12 +385,12 @@ void py_diff_end (void) { result = PyEval_CallObject(_py_diff_end, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); - else + else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); } void py_our_id (int id) { - if (!have_file) { return; } + if (!python_loaded) { return; } PyObject *arglist, *result; @@ -398,12 +398,12 @@ void py_our_id (int id) { result = PyEval_CallObject(_py_our_id, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); - else + else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); } void py_new_msg (struct tgl_message *M) { - if (!have_file) { return; } + if (!python_loaded) { return; } PyObject *msg; PyObject *arglist, *result; @@ -415,12 +415,13 @@ void py_new_msg (struct tgl_message *M) { if(result == NULL) PyErr_Print(); - else + else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); + } void py_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) { - if (!have_file) { return; } + if (!python_loaded) { return; } PyObject *peer, *types; PyObject *arglist, *result; @@ -433,13 +434,14 @@ void py_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) { if(result == NULL) PyErr_Print(); - else + else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); + } void py_user_update (struct tgl_user *U, unsigned flags) { - if (!have_file) { return; } + if (!python_loaded) { return; } PyObject *peer, *types; PyObject *arglist, *result; @@ -452,12 +454,13 @@ void py_user_update (struct tgl_user *U, unsigned flags) { if(result == NULL) PyErr_Print(); - else + else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); + } void py_chat_update (struct tgl_chat *C, unsigned flags) { - if (!have_file) { return; } + if (!python_loaded) { return; } PyObject *peer, *types; PyObject *arglist, *result; @@ -471,7 +474,7 @@ void py_chat_update (struct tgl_chat *C, unsigned flags) { if(result == NULL) PyErr_Print(); - else + else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); } @@ -893,9 +896,10 @@ void py_do_all (void) { enum py_query_type f = (long)py_ptr[p ++]; PyObject *args = (PyObject *)py_ptr[p ++]; - char *s, *s1, *s2, *s3, *s4; - struct tgl_message *M; - tgl_peer_id_t peer; + PyObject *pyObj1, *pyObj2; + char *s; + //struct tgl_message *M; + tgl_peer_id_t peer, peer1; switch (f) { case pq_contact_list: @@ -905,41 +909,50 @@ void py_do_all (void) { tgl_do_get_dialog_list (TLS, py_dialog_list_cb, NULL); break; case pq_msg: - PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &s1); - - tgl_do_send_message (TLS, peer, s1, strlen (s1), py_msg_cb, NULL); + PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &s); + tgl_do_send_message (TLS, peer, s, strlen (s), py_msg_cb, NULL); break; case pq_send_typing: - tgl_do_send_typing (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, tgl_typing_typing, py_empty_cb, py_ptr[p]); + PyArg_ParseTuple(args, "ii", &peer.type, &peer.id); + tgl_do_send_typing (TLS, peer, tgl_typing_typing, py_empty_cb, NULL); break; case pq_send_typing_abort: - tgl_do_send_typing (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, tgl_typing_cancel, py_empty_cb, py_ptr[p]); + PyArg_ParseTuple(args, "ii", &peer.type, &peer.id); + tgl_do_send_typing (TLS, peer, tgl_typing_cancel, py_empty_cb, NULL); break; case pq_rename_chat: - tgl_do_rename_chat (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, py_ptr[p + 2], py_msg_cb, py_ptr[p]); + PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &s); + tgl_do_rename_chat (TLS, peer, s, py_msg_cb, NULL); break; case pq_send_photo: - tgl_do_send_document (TLS, -1, ((tgl_peer_t *)py_ptr[p + 1])->id, py_ptr[p + 2], py_msg_cb, py_ptr[p]); + PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &s); + tgl_do_send_document (TLS, -1, peer, s, py_msg_cb, NULL); break; case pq_send_video: - tgl_do_send_document (TLS, FLAG_DOCUMENT_VIDEO, ((tgl_peer_t *)py_ptr[p + 1])->id, py_ptr[p + 2], py_msg_cb, py_ptr[p]); + PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &s); + tgl_do_send_document (TLS, FLAG_DOCUMENT_VIDEO, peer, s, py_msg_cb, NULL); break; case pq_send_audio: - tgl_do_send_document (TLS, FLAG_DOCUMENT_AUDIO, ((tgl_peer_t *)py_ptr[p + 1])->id, py_ptr[p + 2], py_msg_cb, py_ptr[p]); + PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &s); + tgl_do_send_document (TLS, FLAG_DOCUMENT_AUDIO, peer, s, py_msg_cb, NULL); break; case pq_send_document: - tgl_do_send_document (TLS, 0, ((tgl_peer_t *)py_ptr[p + 1])->id, py_ptr[p + 2], py_msg_cb, py_ptr[p]); + PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &s); + tgl_do_send_document (TLS, 0, peer, s, py_msg_cb, NULL); break; case pq_send_file: - tgl_do_send_document (TLS, -2, ((tgl_peer_t *)py_ptr[p + 1])->id, py_ptr[p + 2], py_msg_cb, py_ptr[p]); + PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &s); + tgl_do_send_document (TLS, -2, peer, s, py_msg_cb, NULL); break; case pq_send_text: - tgl_do_send_text (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, py_ptr[p + 2], py_msg_cb, py_ptr[p]); + PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &s); + tgl_do_send_text (TLS, peer, s, py_msg_cb, NULL); break; case pq_chat_set_photo: - tgl_do_set_chat_photo (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, py_ptr[p + 2], py_msg_cb, py_ptr[p]); + PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &s); + tgl_do_set_chat_photo (TLS, peer, s, py_msg_cb, NULL); break; - case pq_load_photo: +/* case pq_load_photo: case pq_load_video: case pq_load_audio: case pq_load_document: @@ -980,13 +993,16 @@ void py_do_all (void) { case pq_history: tgl_do_get_history (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, (long)py_ptr[p + 2], 0, py_msg_list_cb, py_ptr[p]); break; +*/ case pq_chat_add_user: - tgl_do_add_user_to_chat (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, ((tgl_peer_t *)py_ptr[p + 2])->id, 10, py_msg_cb, py_ptr[p]); + PyArg_ParseTuple(args, "iiii", &peer.type, &peer.id, &peer1.type, &peer1.id); + tgl_do_add_user_to_chat (TLS, peer, peer1, 100, py_msg_cb, NULL); break; case pq_chat_del_user: - tgl_do_del_user_from_chat (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, ((tgl_peer_t *)py_ptr[p + 2])->id, py_msg_cb, py_ptr[p]); + PyArg_ParseTuple(args, "iiii", &peer.type, &peer.id, &peer.type, &peer.id); + tgl_do_del_user_from_chat (TLS, peer, peer1, py_msg_cb, NULL); break; - case pq_add_contact: +/* case pq_add_contact: tgl_do_add_contact (TLS, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), 0, py_contact_list_cb, py_ptr[p]); break; case pq_del_contact: @@ -1028,21 +1044,20 @@ void py_do_all (void) { case pq_send_contact: tgl_do_send_contact (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), py_msg_cb, py_ptr[p]); break; +*/ case pq_status_online: - tgl_do_update_status (TLS, 1, py_empty_cb, py_ptr[p]); + tgl_do_update_status (TLS, 1, py_empty_cb, NULL); break; case pq_status_offline: - tgl_do_update_status (TLS, 0, py_empty_cb, py_ptr[p]); + tgl_do_update_status (TLS, 0, py_empty_cb, NULL); break; - case pq_extf: +/* case pq_extf: tgl_do_send_extf (TLS, s, strlen (s), py_str_cb, py_ptr[p]); break; +*/ case pq_send_location: - if (sizeof (void *) == 4) { - tgl_do_send_location (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id , *(float *)(py_ptr + p + 2), *(float *)(py_ptr + p + 3), py_msg_cb, py_ptr[p]); - } else { - tgl_do_send_location (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id , *(double *)(py_ptr + p + 2), *(double *)(py_ptr + p + 3), py_msg_cb, py_ptr[p]); - } + PyArg_ParseTuple(args, "iiOO", &peer.type, &peer.id, &pyObj1, &pyObj2); + tgl_do_send_location (TLS, peer, PyFloat_AsDouble(pyObj1), PyFloat_AsDouble(pyObj2), py_msg_cb, NULL); break; /* pq_delete_msg, @@ -1255,9 +1270,8 @@ void inittgl() void py_init (const char *file) { if (!file) { return; } - have_file = 1; - - PyObject *pName, *pModule, *pDict; + python_loaded = 0; + PyObject *pModule, *pDict; Py_Initialize(); inittgl(); @@ -1267,18 +1281,23 @@ void py_init (const char *file) { PyList_Append(sysPath, PyString_FromString(".")); - pName = PyString_FromString(file); - pModule = PyImport_Import(pName); - pDict = PyModule_GetDict(pModule); + pModule = PyImport_Import(PyString_FromString(file)); + if(PyErr_Occurred()) { // Error loading script + logprintf("Failed to load python script\n"); + PyErr_Print(); + exit(1); + } else { + python_loaded = 1; + pDict = PyModule_GetDict(pModule); - - // Store callables for python functions - my_python_register(pDict, "on_binlog_replay_end", _py_binlog_end); - my_python_register(pDict, "on_get_difference_end", _py_diff_end); - my_python_register(pDict, "on_our_id", _py_our_id); - my_python_register(pDict, "on_msg_receive", _py_new_msg); - my_python_register(pDict, "on_secret_chat_update", _py_secret_chat_update); - my_python_register(pDict, "on_user_update", _py_user_update); - my_python_register(pDict, "on_chat_update", _py_chat_update); + // Store callables for python functions + my_python_register(pDict, "on_binlog_replay_end", _py_binlog_end); + my_python_register(pDict, "on_get_difference_end", _py_diff_end); + my_python_register(pDict, "on_our_id", _py_our_id); + my_python_register(pDict, "on_msg_receive", _py_new_msg); + my_python_register(pDict, "on_secret_chat_update", _py_secret_chat_update); + my_python_register(pDict, "on_user_update", _py_user_update); + my_python_register(pDict, "on_chat_update", _py_chat_update); + } } From b3fbcaeb0afa89c7bee2ec70b185cdeb554fa162 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Thu, 7 May 2015 00:04:15 -0700 Subject: [PATCH 13/29] Fix broken -W wait command. Thanks @phoudoin --- main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.c b/main.c index ff655cc..7b1ef69 100644 --- a/main.c +++ b/main.c @@ -655,13 +655,13 @@ void args_parse (int argc, char **argv) { break; #endif case 'W': + wait_dialog_list = 1; + break; #ifdef USE_PYTHON case 'Z': python_file = strdup (optarg); break; #endif - wait_dialog_list = 1; - break; case 'C': disable_colors ++; break; From 8679ab2e0d179af8f9781a830f84902f9277cd70 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Thu, 7 May 2015 00:20:13 -0700 Subject: [PATCH 14/29] Support loading the script from any path, truncate .py if needed. --- python-tg.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/python-tg.c b/python-tg.c index 5800620..3229043 100644 --- a/python-tg.c +++ b/python-tg.c @@ -28,7 +28,7 @@ #include #include - +#include #include #ifdef EVENT_V2 @@ -1271,18 +1271,26 @@ void inittgl() void py_init (const char *file) { if (!file) { return; } python_loaded = 0; - PyObject *pModule, *pDict; + PyObject *pModule, *pDict; + + // Get a copy of the filename for dirname, which may modify the string. + char filename[100]; + strncpy(filename, file, 100); + Py_Initialize(); inittgl(); - PyObject* sysPath = PySys_GetObject((char*)"path"); - PyList_Append(sysPath, PyString_FromString(".")); - - + PyList_Append(sysPath, PyString_FromString(dirname(filename))); + + // remove .py extension from file, if any + char* dot = strrchr(file, '.'); + if (dot && strcmp(dot, ".py") == 0) + *dot = 0; pModule = PyImport_Import(PyString_FromString(file)); - if(PyErr_Occurred()) { // Error loading script + + if(pModule == NULL || PyErr_Occurred()) { // Error loading script logprintf("Failed to load python script\n"); PyErr_Print(); exit(1); From 434ccdd5f8a8ae9a4ff1a6c7eb837d0506ee4de0 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Thu, 7 May 2015 00:24:45 -0700 Subject: [PATCH 15/29] Py_DECREF the results from python calls in callbacks --- python-tg.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/python-tg.c b/python-tg.c index 3229043..da2564b 100644 --- a/python-tg.c +++ b/python-tg.c @@ -374,6 +374,7 @@ void py_binlog_end (void) { else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); + Py_DECREF(result); } void py_diff_end (void) { @@ -387,6 +388,8 @@ void py_diff_end (void) { PyErr_Print(); else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); + + Py_DECREF(result); } void py_our_id (int id) { @@ -400,6 +403,8 @@ void py_our_id (int id) { PyErr_Print(); else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); + + Py_DECREF(result); } void py_new_msg (struct tgl_message *M) { @@ -418,6 +423,7 @@ void py_new_msg (struct tgl_message *M) { else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); + Py_DECREF(result); } void py_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) { @@ -437,6 +443,7 @@ void py_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) { else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); + Py_DECREF(result); } @@ -457,6 +464,7 @@ void py_user_update (struct tgl_user *U, unsigned flags) { else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); + Py_DECREF(result); } void py_chat_update (struct tgl_chat *C, unsigned flags) { @@ -476,6 +484,8 @@ void py_chat_update (struct tgl_chat *C, unsigned flags) { PyErr_Print(); else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); + + Py_DECREF(result); } ////extern tgl_peer_t *Peers[]; From 2ea0da50f0ea8576c9914b4471a59198743cd7ac Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Thu, 7 May 2015 00:34:47 -0700 Subject: [PATCH 16/29] Fix test script --- pytest.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pytest.py b/pytest.py index d890292..2041de5 100644 --- a/pytest.py +++ b/pytest.py @@ -34,7 +34,6 @@ def on_msg_receive(msg): if text.startswith("!ping"): tgl.send_msg(ptype, pid, "PONG!") -d if text.startswith("!location"): geolocator = Nominatim() From 8995e45862c4ad421970d0531fdc7084f65f75dd Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Thu, 7 May 2015 00:44:39 -0700 Subject: [PATCH 17/29] Protect against Py_DECREFing nulls. Add datetime support --- pytest.py | 2 ++ python-tg.c | 31 +++++++++++++++++++++---------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/pytest.py b/pytest.py index 2041de5..d89d4f6 100644 --- a/pytest.py +++ b/pytest.py @@ -30,6 +30,8 @@ def on_msg_receive(msg): ptype = msg["to"]["type"] pid = msg["to"]["id"] + pp.pprint(msg) + text = msg["text"] if text.startswith("!ping"): diff --git a/python-tg.c b/python-tg.c index da2564b..d7468b8 100644 --- a/python-tg.c +++ b/python-tg.c @@ -38,6 +38,9 @@ #include "event-old.h" #endif +// Python Imports +#include "datetime.h" + //#include "interface.h" //#include "auto/constants.h" #include @@ -47,6 +50,7 @@ extern int verbosity; extern struct tgl_state *TLS; + static int python_loaded; // Python update function callables @@ -61,6 +65,12 @@ PyObject *_py_chat_update; PyObject* get_user (tgl_peer_t *P); PyObject* get_peer (tgl_peer_id_t id, tgl_peer_t *P); +// Utility functions +PyObject* get_datetime(long datetime) +{ + return PyDateTime_FromTimestamp(Py_BuildValue("(O)", PyLong_FromLong(datetime))); +} + void py_add_string_field (PyObject* dict, char *name, const char *value) { assert (PyDict_Check(dict)); assert (name && strlen (name)); @@ -340,7 +350,7 @@ PyObject* get_message (struct tgl_message *M) { if (tgl_get_peer_type (M->fwd_from_id)) { PyDict_SetItemString(msg, "fwd_from", get_peer(M->fwd_from_id, tgl_peer_get (TLS, M->fwd_from_id))); - py_add_num_field (msg, "fwd_date", M->fwd_date); + PyDict_SetItemString (msg, "fwd_date", get_datetime(M->fwd_date)); } PyDict_SetItemString(msg, "from", get_peer(M->from_id, tgl_peer_get (TLS, M->from_id))); @@ -348,7 +358,7 @@ PyObject* get_message (struct tgl_message *M) { PyDict_SetItemString(msg, "out", (M->out ? Py_True : Py_False)); PyDict_SetItemString(msg, "unread", (M->unread ? Py_True : Py_False)); PyDict_SetItemString(msg, "service", (M->service ? Py_True : Py_False)); - PyDict_SetItemString(msg, "date", PyLong_FromLong(M->date)); // TODO put this into PyDate object + PyDict_SetItemString(msg, "date", get_datetime(M->date)); if (!M->service) { if (M->message_len && M->message) { @@ -374,7 +384,7 @@ void py_binlog_end (void) { else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); - Py_DECREF(result); + Py_XDECREF(result); } void py_diff_end (void) { @@ -389,7 +399,7 @@ void py_diff_end (void) { else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); - Py_DECREF(result); + Py_XDECREF(result); } void py_our_id (int id) { @@ -404,7 +414,7 @@ void py_our_id (int id) { else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); - Py_DECREF(result); + Py_XDECREF(result); } void py_new_msg (struct tgl_message *M) { @@ -423,7 +433,7 @@ void py_new_msg (struct tgl_message *M) { else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); - Py_DECREF(result); + Py_XDECREF(result); } void py_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) { @@ -443,7 +453,7 @@ void py_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) { else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); - Py_DECREF(result); + Py_XDECREF(result); } @@ -464,7 +474,7 @@ void py_user_update (struct tgl_user *U, unsigned flags) { else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); - Py_DECREF(result); + Py_XDECREF(result); } void py_chat_update (struct tgl_chat *C, unsigned flags) { @@ -485,7 +495,7 @@ void py_chat_update (struct tgl_chat *C, unsigned flags) { else if(PyString_Check(result)) logprintf ("python: %s\n", PyString_AsString(result)); - Py_DECREF(result); + Py_XDECREF(result); } ////extern tgl_peer_t *Peers[]; @@ -1306,8 +1316,9 @@ void py_init (const char *file) { exit(1); } else { python_loaded = 1; + PyDateTime_IMPORT; pDict = PyModule_GetDict(pModule); - + // Store callables for python functions my_python_register(pDict, "on_binlog_replay_end", _py_binlog_end); my_python_register(pDict, "on_get_difference_end", _py_diff_end); From 87f014d3c20008e6b90bcf702a378c19b87248ea Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Thu, 7 May 2015 00:51:29 -0700 Subject: [PATCH 18/29] Added commented out reply support, missing from tgl library. --- python-tg.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/python-tg.c b/python-tg.c index d7468b8..eb8e801 100644 --- a/python-tg.c +++ b/python-tg.c @@ -352,7 +352,17 @@ PyObject* get_message (struct tgl_message *M) { PyDict_SetItemString(msg, "fwd_from", get_peer(M->fwd_from_id, tgl_peer_get (TLS, M->fwd_from_id))); PyDict_SetItemString (msg, "fwd_date", get_datetime(M->fwd_date)); } - + +/* Need reply_id from https://github.com/vysheng/tgl/blob/master/tgl-layout.h#L471 + if (M->reply_id) { + py_add_num_field ("reply_to_id", M->reply_id); + struct tgl_message *MR = tgl_message_get (TLS, M->reply_id); + // Message details available only within session for now + if (MR) { + PyDict_SetItemString(msg, "reply_to", get_message(MR)); + } + } +*/ PyDict_SetItemString(msg, "from", get_peer(M->from_id, tgl_peer_get (TLS, M->from_id))); PyDict_SetItemString(msg, "to", get_peer(M->to_id, tgl_peer_get (TLS, M->to_id))); PyDict_SetItemString(msg, "out", (M->out ? Py_True : Py_False)); From e2edb7cc267785886ce5b79f9cdd6c4d6dd077f4 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Thu, 7 May 2015 00:53:39 -0700 Subject: [PATCH 19/29] Added username to the user dict --- python-tg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python-tg.c b/python-tg.c index eb8e801..b1977a4 100644 --- a/python-tg.c +++ b/python-tg.c @@ -128,7 +128,9 @@ PyObject* get_user (tgl_peer_t *P) { if (P->user.access_hash) { py_add_num_field (user, "access_hash", 1); } - + if (P->user.username) { + py_add_string_field ( user, "username", P->user.username); + } return user; } From caacc3c5841d467630ad377c633ed03192ae98d9 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Thu, 7 May 2015 01:54:17 -0700 Subject: [PATCH 20/29] support a path to the python script. TODO: get rid of gcc warn --- python-tg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python-tg.c b/python-tg.c index b1977a4..131c754 100644 --- a/python-tg.c +++ b/python-tg.c @@ -1320,7 +1320,7 @@ void py_init (const char *file) { char* dot = strrchr(file, '.'); if (dot && strcmp(dot, ".py") == 0) *dot = 0; - pModule = PyImport_Import(PyString_FromString(file)); + pModule = PyImport_Import(PyString_FromString(basename(file))); if(pModule == NULL || PyErr_Occurred()) { // Error loading script logprintf("Failed to load python script\n"); From 89d5b7f262e0f9ef99675e21782c37cfa529cb0c Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 9 May 2015 02:10:24 -0700 Subject: [PATCH 21/29] Implement Python >=3.3 support --- .gitignore | 3 +- ax_python.m4 | 2 +- configure | 2 +- python-tg.c | 300 +++++++++++++++++++++++++++++---------- pytest.py => tgl-test.py | 11 +- 5 files changed, 239 insertions(+), 79 deletions(-) rename pytest.py => tgl-test.py (77%) diff --git a/.gitignore b/.gitignore index 7cee62d..90dcfa1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ telegram *.o Makefile +aclocal.m4 autom4te.cache config.h config.log @@ -16,4 +17,4 @@ debian/telegram-cli.[a-z] debian/files debian/telegram-cli/* debian/telegram-cli.debhelper.log -debian/telegram-cli.substvars \ No newline at end of file +debian/telegram-cli.substvars diff --git a/ax_python.m4 b/ax_python.m4 index ebfb8d6..5739922 100644 --- a/ax_python.m4 +++ b/ax_python.m4 @@ -56,7 +56,7 @@ AC_DEFUN([AX_PYTHON], [AC_MSG_CHECKING(for python build information) AC_MSG_RESULT([]) -for python in python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python; do +for python in python3.4 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python; do AC_CHECK_PROGS(PYTHON_BIN, [$python]) ax_python_bin=$PYTHON_BIN if test x$ax_python_bin != x; then diff --git a/configure b/configure index 3458182..7068004 100755 --- a/configure +++ b/configure @@ -5943,7 +5943,7 @@ if test "${enable_python+set}" = set; then : $as_echo_n "checking for python build information... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 $as_echo "" >&6; } -for python in python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python; do +for python in python3.4 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python; do for ac_prog in $python do # Extract the first word of "$ac_prog", so it can be a program name with args. diff --git a/python-tg.c b/python-tg.c index 131c754..147d768 100644 --- a/python-tg.c +++ b/python-tg.c @@ -31,13 +31,45 @@ #include #include -#ifdef EVENT_V2 -#include +#include "bytesobject.h" + +// Python 2/3 compat macros +#if PY_MAJOR_VERSION >= 3 + #define MOD_ERROR_VAL NULL + #define MOD_SUCCESS_VAL(val) val + #define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void) + #define MOD_DEF(ob, name, doc, methods) \ + static struct PyModuleDef moduledef = { \ + PyModuleDef_HEAD_INIT, name, doc, -1, methods, NULL, NULL, NULL, NULL,}; \ + ob = PyModule_Create(&moduledef); + #define PyInt_FromLong PyLong_FromLong #else -#include -#include "event-old.h" + #define MOD_ERROR_VAL + #define MOD_SUCCESS_VAL(val) + #define MOD_INIT(name) void init##name(void) + #define MOD_DEF(ob, name, doc, methods) \ + ob = Py_InitModule3(name, methods, doc); #endif +#define TGL_PYTHON_CALLBACK(name, func) \ + PyObject *set##func(PyObject *dummy, PyObject *args) { \ + PyObject *result = NULL; \ + PyObject *temp; \ + if (PyArg_ParseTuple(args, "O:set_##name", &temp)) { \ + if (!PyCallable_Check(temp)) { \ + PyErr_SetString(PyExc_TypeError, "parameter must be callable");\ + return NULL;\ + }\ + Py_XINCREF(temp);\ + Py_XDECREF(func);\ + func = temp;\ + Py_INCREF(Py_None);\ + result = Py_None;\ + }\ + return result;\ + } + + // Python Imports #include "datetime.h" @@ -75,16 +107,16 @@ void py_add_string_field (PyObject* dict, char *name, const char *value) { assert (PyDict_Check(dict)); assert (name && strlen (name)); if (!value || !strlen (value)) { return; } - PyDict_SetItemString (dict, name, PyString_FromString(value)); + PyDict_SetItemString (dict, name, PyUnicode_FromString(value)); } void py_add_string_field_arr (PyObject* list, int num, const char *value) { assert(PyList_Check(list)); if (!value || !strlen (value)) { return; } if(num >= 0) - PyList_SetItem (list, num, PyString_FromString (value)); + PyList_SetItem (list, num, PyUnicode_FromString (value)); else // Append - PyList_Append (list, PyString_FromString (value)); + PyList_Append (list, PyUnicode_FromString (value)); } void py_add_num_field (PyObject* dict, const char *name, double value) { @@ -98,13 +130,13 @@ PyObject* get_tgl_peer_type (int x) { switch (x) { case TGL_PEER_USER: - type = PyString_FromString("user"); + type = PyUnicode_FromString("user"); break; case TGL_PEER_CHAT: - type = PyString_FromString("chat"); + type = PyUnicode_FromString("chat"); break; case TGL_PEER_ENCR_CHAT: - type = PyString_FromString("encr_chat"); + type = PyUnicode_FromString("encr_chat"); break; default: assert (0); @@ -264,7 +296,7 @@ PyObject* get_peer (tgl_peer_id_t id, tgl_peer_t *P) { if(name == NULL) assert(0); // TODO handle python exception; - PyDict_SetItemString (name, "print_name", PyString_FromString(s)); + PyDict_SetItemString (name, "print_name", PyUnicode_FromString(s)); PyDict_SetItemString (peer, "peer", name); } else { PyObject *peer_obj; @@ -374,7 +406,7 @@ PyObject* get_message (struct tgl_message *M) { if (!M->service) { if (M->message_len && M->message) { - PyDict_SetItemString(msg, "text", PyString_FromStringAndSize(M->message, M->message_len)); + PyDict_SetItemString(msg, "text", PyUnicode_FromStringAndSize(M->message, M->message_len)); } if (M->media.type && M->media.type != tgl_message_media_none) { PyDict_SetItemString(msg, "media", get_media(&M->media)); @@ -389,12 +421,19 @@ void py_binlog_end (void) { PyObject *arglist, *result; + if(_py_binlog_end == NULL) { + logprintf("Callback not set for on_binlog_end"); + return; + } + arglist = Py_BuildValue("()"); result = PyEval_CallObject(_py_binlog_end, arglist); - Py_DECREF(arglist); if(result == NULL) + Py_DECREF(arglist); + + if(result == NULL) PyErr_Print(); - else if(PyString_Check(result)) - logprintf ("python: %s\n", PyString_AsString(result)); + else if(PyUnicode_Check(result)) + logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result))); Py_XDECREF(result); } @@ -404,12 +443,18 @@ void py_diff_end (void) { PyObject *arglist, *result; + if(_py_diff_end == NULL) { + logprintf("Callback not set for on_diff_end"); + return; + } + arglist = Py_BuildValue("()"); result = PyEval_CallObject(_py_diff_end, arglist); - Py_DECREF(arglist); if(result == NULL) + Py_DECREF(arglist); + if(result == NULL) PyErr_Print(); - else if(PyString_Check(result)) - logprintf ("python: %s\n", PyString_AsString(result)); + else if(PyUnicode_Check(result)) + logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result))); Py_XDECREF(result); } @@ -419,12 +464,17 @@ void py_our_id (int id) { PyObject *arglist, *result; + if(_py_our_id == NULL) { + logprintf("Callback not set for on_our_id"); + return; + } + arglist = Py_BuildValue("(i)", id); result = PyEval_CallObject(_py_our_id, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); - else if(PyString_Check(result)) - logprintf ("python: %s\n", PyString_AsString(result)); + else if(PyUnicode_Check(result)) + logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result))); Py_XDECREF(result); } @@ -434,6 +484,11 @@ void py_new_msg (struct tgl_message *M) { PyObject *msg; PyObject *arglist, *result; + if(_py_new_msg == NULL) { + logprintf("Callback not set for on_new_msg"); + return; + } + msg = get_message (M); arglist = Py_BuildValue("(O)", msg); @@ -442,8 +497,8 @@ void py_new_msg (struct tgl_message *M) { if(result == NULL) PyErr_Print(); - else if(PyString_Check(result)) - logprintf ("python: %s\n", PyString_AsString(result)); + else if(PyUnicode_Check(result)) + logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result))); Py_XDECREF(result); } @@ -453,6 +508,11 @@ void py_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) { PyObject *peer, *types; PyObject *arglist, *result; + if(_py_secret_chat_update == NULL) { + logprintf("Callback not set for on_secret_chat_update"); + return; + } + peer = get_peer (C->id, (void *)C); types = get_update_types (flags); @@ -462,8 +522,8 @@ void py_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) { if(result == NULL) PyErr_Print(); - else if(PyString_Check(result)) - logprintf ("python: %s\n", PyString_AsString(result)); + else if(PyUnicode_Check(result)) + logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result))); Py_XDECREF(result); } @@ -474,6 +534,11 @@ void py_user_update (struct tgl_user *U, unsigned flags) { PyObject *peer, *types; PyObject *arglist, *result; + if(_py_user_update == NULL) { + logprintf("Callback not set for on_user_update"); + return; + } + peer = get_peer (U->id, (void *)U); types = get_update_types (flags); @@ -483,8 +548,8 @@ void py_user_update (struct tgl_user *U, unsigned flags) { if(result == NULL) PyErr_Print(); - else if(PyString_Check(result)) - logprintf ("python: %s\n", PyString_AsString(result)); + else if(PyUnicode_Check(result)) + logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result))); Py_XDECREF(result); } @@ -495,6 +560,11 @@ void py_chat_update (struct tgl_chat *C, unsigned flags) { PyObject *peer, *types; PyObject *arglist, *result; + if(_py_chat_update == NULL) { + logprintf("Callback not set for on_chat_update"); + return; + } + peer = get_peer (C->id, (void *)C); types = get_update_types (flags); @@ -504,8 +574,8 @@ void py_chat_update (struct tgl_chat *C, unsigned flags) { if(result == NULL) PyErr_Print(); - else if(PyString_Check(result)) - logprintf ("python: %s\n", PyString_AsString(result)); + else if(PyUnicode_Check(result)) + logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result))); Py_XDECREF(result); } @@ -929,7 +999,9 @@ void py_do_all (void) { enum py_query_type f = (long)py_ptr[p ++]; PyObject *args = (PyObject *)py_ptr[p ++]; PyObject *pyObj1, *pyObj2; - char *s; + PyObject *ustr, *str; + str = NULL; + //struct tgl_message *M; tgl_peer_id_t peer, peer1; @@ -941,8 +1013,12 @@ void py_do_all (void) { tgl_do_get_dialog_list (TLS, py_dialog_list_cb, NULL); break; case pq_msg: - PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &s); - tgl_do_send_message (TLS, peer, s, strlen (s), py_msg_cb, NULL); + PyArg_ParseTuple(args, "iiU", &peer.type, &peer.id, &ustr); + str = PyUnicode_AsUnicodeEscapeString(ustr); + if(str == NULL) + PyErr_Print(); + else + tgl_do_send_message (TLS, peer, PyBytes_AsString(str), PyBytes_Size (str), py_msg_cb, NULL); break; case pq_send_typing: PyArg_ParseTuple(args, "ii", &peer.type, &peer.id); @@ -953,36 +1029,68 @@ void py_do_all (void) { tgl_do_send_typing (TLS, peer, tgl_typing_cancel, py_empty_cb, NULL); break; case pq_rename_chat: - PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &s); - tgl_do_rename_chat (TLS, peer, s, py_msg_cb, NULL); + PyArg_ParseTuple(args, "iiU", &peer.type, &peer.id, &ustr); + str = PyUnicode_AsUnicodeEscapeString(ustr); + if(str == NULL) + PyErr_Print(); + else + tgl_do_rename_chat (TLS, peer, PyBytes_AsString(str), py_msg_cb, NULL); break; case pq_send_photo: - PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &s); - tgl_do_send_document (TLS, -1, peer, s, py_msg_cb, NULL); + PyArg_ParseTuple(args, "iiU", &peer.type, &peer.id, &ustr); + str = PyUnicode_AsUnicodeEscapeString(ustr); + if(str == NULL) + PyErr_Print(); + else + tgl_do_send_document (TLS, -1, peer, PyBytes_AsString(str), py_msg_cb, NULL); break; case pq_send_video: - PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &s); - tgl_do_send_document (TLS, FLAG_DOCUMENT_VIDEO, peer, s, py_msg_cb, NULL); + PyArg_ParseTuple(args, "iiU", &peer.type, &peer.id, &ustr); + str = PyUnicode_AsUnicodeEscapeString(ustr); + if(str == NULL) + PyErr_Print(); + else + tgl_do_send_document (TLS, FLAG_DOCUMENT_VIDEO, peer, PyBytes_AsString(str), py_msg_cb, NULL); break; case pq_send_audio: - PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &s); - tgl_do_send_document (TLS, FLAG_DOCUMENT_AUDIO, peer, s, py_msg_cb, NULL); + PyArg_ParseTuple(args, "iiU", &peer.type, &peer.id, &ustr); + str = PyUnicode_AsUnicodeEscapeString(ustr); + if(str == NULL) + PyErr_Print(); + else + tgl_do_send_document (TLS, FLAG_DOCUMENT_AUDIO, peer, PyBytes_AsString(str), py_msg_cb, NULL); break; case pq_send_document: - PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &s); - tgl_do_send_document (TLS, 0, peer, s, py_msg_cb, NULL); + PyArg_ParseTuple(args, "iiU", &peer.type, &peer.id, &ustr); + str = PyUnicode_AsUnicodeEscapeString(ustr); + if(str == NULL) + PyErr_Print(); + else + tgl_do_send_document (TLS, 0, peer, PyBytes_AsString(str), py_msg_cb, NULL); break; case pq_send_file: - PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &s); - tgl_do_send_document (TLS, -2, peer, s, py_msg_cb, NULL); + PyArg_ParseTuple(args, "iiU", &peer.type, &peer.id, &ustr); + str = PyUnicode_AsUnicodeEscapeString(ustr); + if(str == NULL) + PyErr_Print(); + else + tgl_do_send_document (TLS, -2, peer, PyBytes_AsString(str), py_msg_cb, NULL); break; case pq_send_text: - PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &s); - tgl_do_send_text (TLS, peer, s, py_msg_cb, NULL); + PyArg_ParseTuple(args, "iiU", &peer.type, &peer.id, &ustr); + str = PyUnicode_AsUnicodeEscapeString(ustr); + if(str == NULL) + PyErr_Print(); + else + tgl_do_send_text (TLS, peer, PyBytes_AsString(str), py_msg_cb, NULL); break; case pq_chat_set_photo: - PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &s); - tgl_do_set_chat_photo (TLS, peer, s, py_msg_cb, NULL); + PyArg_ParseTuple(args, "iiU", &peer.type, &peer.id, &ustr); + str = PyUnicode_AsUnicodeEscapeString(ustr); + if(str == NULL) + PyErr_Print(); + else + tgl_do_set_chat_photo (TLS, peer, PyBytes_AsString(str), py_msg_cb, NULL); break; /* case pq_load_photo: case pq_load_video: @@ -1110,7 +1218,14 @@ void py_do_all (void) { default: assert (0); } - Py_DECREF(args); + + // Clean up any arg variables we could have used. + Py_XDECREF(args); + Py_XDECREF(pyObj1); + Py_XDECREF(pyObj2); + Py_XDECREF(str); + Py_XDECREF(ustr); + } pos = 0; } @@ -1171,6 +1286,34 @@ PyObject* py_status_offline(PyObject *self, PyObject *args) { return push_py_fun PyObject* py_send_location(PyObject *self, PyObject *args) { return push_py_func(pq_send_location, args); } PyObject* py_extf(PyObject *self, PyObject *args) { return push_py_func(pq_extf, args); } + +// Store callables for python functions +TGL_PYTHON_CALLBACK("on_binlog_replay_end", _py_binlog_end); +TGL_PYTHON_CALLBACK("on_get_difference_end", _py_diff_end); +//TGL_PYTHON_CALLBACK("on_our_id", _py_our_id); +TGL_PYTHON_CALLBACK("on_msg_receive", _py_new_msg); +TGL_PYTHON_CALLBACK("on_secret_chat_update", _py_secret_chat_update); +TGL_PYTHON_CALLBACK("on_user_update", _py_user_update); +TGL_PYTHON_CALLBACK("on_chat_update", _py_chat_update); + +PyObject *set_py_our_id(PyObject *dummy, PyObject *args) { + PyObject *result = NULL; + PyObject *temp; + if (PyArg_ParseTuple(args, "O:set_on_our_id", &temp)) { + if (!PyCallable_Check(temp)) { + PyErr_SetString(PyExc_TypeError, "parameter must be callable"); + return NULL; + } + Py_XINCREF(temp); + Py_XDECREF(_py_our_id); + _py_our_id = temp; + Py_INCREF(Py_None); + result = Py_None; + } + return result; +} + + static PyMethodDef py_tgl_methods[] = { {"get_contact_list", py_contact_list, METH_VARARGS, "retrieve contact list"}, {"get_dialog_list", py_dialog_list, METH_VARARGS, ""}, @@ -1216,9 +1359,28 @@ static PyMethodDef py_tgl_methods[] = { {"status_offline", py_status_offline, METH_VARARGS, ""}, {"send_location", py_send_location, METH_VARARGS, ""}, {"ext_function", py_extf, METH_VARARGS, ""}, + {"set_on_binlog_replay_end", set_py_binlog_end, METH_VARARGS, ""}, + {"set_on_get_difference_end", set_py_diff_end, METH_VARARGS, ""}, + {"set_on_our_id", set_py_our_id, METH_VARARGS, ""}, + {"set_on_msg_receive", set_py_new_msg, METH_VARARGS, ""}, + {"set_on_secret_chat_update", set_py_secret_chat_update, METH_VARARGS, ""}, + {"set_on_user_update", set_py_user_update, METH_VARARGS, ""}, + {"set_on_chat_update", set_py_chat_update, METH_VARARGS, ""}, { NULL, NULL, 0, NULL } }; +MOD_INIT(tgl) +{ + PyObject *m; + + MOD_DEF(m, "tgl", NULL, py_tgl_methods) + + if (m == NULL) + return MOD_ERROR_VAL; + + return MOD_SUCCESS_VAL(m); +} + //static void lua_postpone_alarm (evutil_socket_t fd, short what, void *arg) { // int *t = arg; @@ -1291,54 +1453,42 @@ static PyMethodDef py_tgl_methods[] = { //} // -#define my_python_register(dict, name, f) \ - f = PyDict_GetItemString(dict, name); - - -void inittgl() -{ - (void) Py_InitModule("tgl", py_tgl_methods); -} - void py_init (const char *file) { if (!file) { return; } python_loaded = 0; - PyObject *pModule, *pDict; + PyObject *pModule; // Get a copy of the filename for dirname, which may modify the string. char filename[100]; strncpy(filename, file, 100); - Py_Initialize(); +#if PY_MAJOR_VERSION >= 3 + PyImport_AppendInittab("tgl", &PyInit_tgl); +#else inittgl(); +#endif + + Py_Initialize(); PyObject* sysPath = PySys_GetObject((char*)"path"); - PyList_Append(sysPath, PyString_FromString(dirname(filename))); + PyList_Append(sysPath, PyUnicode_FromString(dirname(filename))); // remove .py extension from file, if any char* dot = strrchr(file, '.'); if (dot && strcmp(dot, ".py") == 0) *dot = 0; - pModule = PyImport_Import(PyString_FromString(basename(file))); - + pModule = PyImport_Import(PyUnicode_FromString(basename(file))); + if(pModule == NULL || PyErr_Occurred()) { // Error loading script logprintf("Failed to load python script\n"); PyErr_Print(); exit(1); - } else { - python_loaded = 1; - PyDateTime_IMPORT; - pDict = PyModule_GetDict(pModule); - - // Store callables for python functions - my_python_register(pDict, "on_binlog_replay_end", _py_binlog_end); - my_python_register(pDict, "on_get_difference_end", _py_diff_end); - my_python_register(pDict, "on_our_id", _py_our_id); - my_python_register(pDict, "on_msg_receive", _py_new_msg); - my_python_register(pDict, "on_secret_chat_update", _py_secret_chat_update); - my_python_register(pDict, "on_user_update", _py_user_update); - my_python_register(pDict, "on_chat_update", _py_chat_update); } + + + python_loaded = 1; + PyDateTime_IMPORT; + logprintf("Python Initialized"); } diff --git a/pytest.py b/tgl-test.py similarity index 77% rename from pytest.py rename to tgl-test.py index d89d4f6..83b14f1 100644 --- a/pytest.py +++ b/tgl-test.py @@ -3,7 +3,6 @@ import geopy import pprint from geopy.geocoders import Nominatim - our_id = 0 pp = pprint.PrettyPrinter(indent=4) @@ -52,3 +51,13 @@ def on_user_update(): def on_chat_update(): pass + +# Set callbacks +tgl.set_on_binlog_replay_end(on_binlog_replay_end) +tgl.set_on_get_difference_end(on_get_difference_end) +tgl.set_on_our_id(on_our_id) +tgl.set_on_msg_receive(on_msg_receive) +tgl.set_on_secret_chat_update(on_secret_chat_update) +tgl.set_on_user_update(on_user_update) +tgl.set_on_chat_update(on_chat_update) + From fe0ae2a87f537326d3101276a71c3b7cedf3a432 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 9 May 2015 02:16:29 -0700 Subject: [PATCH 22/29] Remove debug function and replace with macro --- python-tg.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/python-tg.c b/python-tg.c index 147d768..f726fa2 100644 --- a/python-tg.c +++ b/python-tg.c @@ -1290,30 +1290,12 @@ PyObject* py_extf(PyObject *self, PyObject *args) { return push_py_func(pq_extf, // Store callables for python functions TGL_PYTHON_CALLBACK("on_binlog_replay_end", _py_binlog_end); TGL_PYTHON_CALLBACK("on_get_difference_end", _py_diff_end); -//TGL_PYTHON_CALLBACK("on_our_id", _py_our_id); +TGL_PYTHON_CALLBACK("on_our_id", _py_our_id); TGL_PYTHON_CALLBACK("on_msg_receive", _py_new_msg); TGL_PYTHON_CALLBACK("on_secret_chat_update", _py_secret_chat_update); TGL_PYTHON_CALLBACK("on_user_update", _py_user_update); TGL_PYTHON_CALLBACK("on_chat_update", _py_chat_update); -PyObject *set_py_our_id(PyObject *dummy, PyObject *args) { - PyObject *result = NULL; - PyObject *temp; - if (PyArg_ParseTuple(args, "O:set_on_our_id", &temp)) { - if (!PyCallable_Check(temp)) { - PyErr_SetString(PyExc_TypeError, "parameter must be callable"); - return NULL; - } - Py_XINCREF(temp); - Py_XDECREF(_py_our_id); - _py_our_id = temp; - Py_INCREF(Py_None); - result = Py_None; - } - return result; -} - - static PyMethodDef py_tgl_methods[] = { {"get_contact_list", py_contact_list, METH_VARARGS, "retrieve contact list"}, {"get_dialog_list", py_dialog_list, METH_VARARGS, ""}, From 38d0b97179caa0afdefefba528831911f5d995e4 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sun, 10 May 2015 04:09:39 -0700 Subject: [PATCH 23/29] Implement fixes for string handling in py2/3 --- python-tg.c | 97 ++++++++++++++++++----------------------------------- tgl-test.py | 9 +---- 2 files changed, 33 insertions(+), 73 deletions(-) diff --git a/python-tg.c b/python-tg.c index f726fa2..e7fb51e 100644 --- a/python-tg.c +++ b/python-tg.c @@ -100,14 +100,17 @@ PyObject* get_peer (tgl_peer_id_t id, tgl_peer_t *P); // Utility functions PyObject* get_datetime(long datetime) { - return PyDateTime_FromTimestamp(Py_BuildValue("(O)", PyLong_FromLong(datetime))); + return PyDateTime_FromTimestamp(Py_BuildValue("(O)", PyLong_FromLong(datetime))); } void py_add_string_field (PyObject* dict, char *name, const char *value) { assert (PyDict_Check(dict)); assert (name && strlen (name)); if (!value || !strlen (value)) { return; } - PyDict_SetItemString (dict, name, PyUnicode_FromString(value)); + PyObject *str = PyUnicode_FromString(value); + + if(PyUnicode_Check(str)) + PyDict_SetItemString (dict, name, str); } void py_add_string_field_arr (PyObject* list, int num, const char *value) { @@ -998,9 +1001,10 @@ void py_do_all (void) { enum py_query_type f = (long)py_ptr[p ++]; PyObject *args = (PyObject *)py_ptr[p ++]; - PyObject *pyObj1, *pyObj2; - PyObject *ustr, *str; - str = NULL; + const char *str; + int len; + PyObject *pyObj1 = NULL; + PyObject *pyObj2 = NULL; //struct tgl_message *M; tgl_peer_id_t peer, peer1; @@ -1013,12 +1017,8 @@ void py_do_all (void) { tgl_do_get_dialog_list (TLS, py_dialog_list_cb, NULL); break; case pq_msg: - PyArg_ParseTuple(args, "iiU", &peer.type, &peer.id, &ustr); - str = PyUnicode_AsUnicodeEscapeString(ustr); - if(str == NULL) - PyErr_Print(); - else - tgl_do_send_message (TLS, peer, PyBytes_AsString(str), PyBytes_Size (str), py_msg_cb, NULL); + PyArg_ParseTuple(args, "iis#", &peer.type, &peer.id, &str, &len); + tgl_do_send_message (TLS, peer, str, len, py_msg_cb, NULL); break; case pq_send_typing: PyArg_ParseTuple(args, "ii", &peer.type, &peer.id); @@ -1029,68 +1029,36 @@ void py_do_all (void) { tgl_do_send_typing (TLS, peer, tgl_typing_cancel, py_empty_cb, NULL); break; case pq_rename_chat: - PyArg_ParseTuple(args, "iiU", &peer.type, &peer.id, &ustr); - str = PyUnicode_AsUnicodeEscapeString(ustr); - if(str == NULL) - PyErr_Print(); - else - tgl_do_rename_chat (TLS, peer, PyBytes_AsString(str), py_msg_cb, NULL); + PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &str); + tgl_do_rename_chat (TLS, peer, str, py_msg_cb, NULL); break; case pq_send_photo: - PyArg_ParseTuple(args, "iiU", &peer.type, &peer.id, &ustr); - str = PyUnicode_AsUnicodeEscapeString(ustr); - if(str == NULL) - PyErr_Print(); - else - tgl_do_send_document (TLS, -1, peer, PyBytes_AsString(str), py_msg_cb, NULL); + PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &str); + tgl_do_send_document (TLS, -1, peer, str, py_msg_cb, NULL); break; case pq_send_video: - PyArg_ParseTuple(args, "iiU", &peer.type, &peer.id, &ustr); - str = PyUnicode_AsUnicodeEscapeString(ustr); - if(str == NULL) - PyErr_Print(); - else - tgl_do_send_document (TLS, FLAG_DOCUMENT_VIDEO, peer, PyBytes_AsString(str), py_msg_cb, NULL); + PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &str); + tgl_do_send_document (TLS, FLAG_DOCUMENT_VIDEO, peer, str, py_msg_cb, NULL); break; case pq_send_audio: - PyArg_ParseTuple(args, "iiU", &peer.type, &peer.id, &ustr); - str = PyUnicode_AsUnicodeEscapeString(ustr); - if(str == NULL) - PyErr_Print(); - else - tgl_do_send_document (TLS, FLAG_DOCUMENT_AUDIO, peer, PyBytes_AsString(str), py_msg_cb, NULL); + PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &str); + tgl_do_send_document (TLS, FLAG_DOCUMENT_AUDIO, peer, str, py_msg_cb, NULL); break; case pq_send_document: - PyArg_ParseTuple(args, "iiU", &peer.type, &peer.id, &ustr); - str = PyUnicode_AsUnicodeEscapeString(ustr); - if(str == NULL) - PyErr_Print(); - else - tgl_do_send_document (TLS, 0, peer, PyBytes_AsString(str), py_msg_cb, NULL); + PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &str); + tgl_do_send_document (TLS, 0, peer, str, py_msg_cb, NULL); break; case pq_send_file: - PyArg_ParseTuple(args, "iiU", &peer.type, &peer.id, &ustr); - str = PyUnicode_AsUnicodeEscapeString(ustr); - if(str == NULL) - PyErr_Print(); - else - tgl_do_send_document (TLS, -2, peer, PyBytes_AsString(str), py_msg_cb, NULL); + PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &str); + tgl_do_send_document (TLS, -2, peer, str, py_msg_cb, NULL); break; case pq_send_text: - PyArg_ParseTuple(args, "iiU", &peer.type, &peer.id, &ustr); - str = PyUnicode_AsUnicodeEscapeString(ustr); - if(str == NULL) - PyErr_Print(); - else - tgl_do_send_text (TLS, peer, PyBytes_AsString(str), py_msg_cb, NULL); + PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &str); + tgl_do_send_text (TLS, peer, str, py_msg_cb, NULL); break; case pq_chat_set_photo: - PyArg_ParseTuple(args, "iiU", &peer.type, &peer.id, &ustr); - str = PyUnicode_AsUnicodeEscapeString(ustr); - if(str == NULL) - PyErr_Print(); - else - tgl_do_set_chat_photo (TLS, peer, PyBytes_AsString(str), py_msg_cb, NULL); + PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &str); + tgl_do_set_chat_photo (TLS, peer, str, py_msg_cb, NULL); break; /* case pq_load_photo: case pq_load_video: @@ -1198,6 +1166,8 @@ void py_do_all (void) { case pq_send_location: PyArg_ParseTuple(args, "iiOO", &peer.type, &peer.id, &pyObj1, &pyObj2); tgl_do_send_location (TLS, peer, PyFloat_AsDouble(pyObj1), PyFloat_AsDouble(pyObj2), py_msg_cb, NULL); + Py_XDECREF(pyObj1); + Py_XDECREF(pyObj2); break; /* pq_delete_msg, @@ -1220,11 +1190,7 @@ void py_do_all (void) { } // Clean up any arg variables we could have used. - Py_XDECREF(args); - Py_XDECREF(pyObj1); - Py_XDECREF(pyObj2); - Py_XDECREF(str); - Py_XDECREF(ustr); + //Py_XDECREF(args); // TODO: this is going negative ref and causing segfaults } pos = 0; @@ -1447,11 +1413,12 @@ void py_init (const char *file) { #if PY_MAJOR_VERSION >= 3 PyImport_AppendInittab("tgl", &PyInit_tgl); + Py_Initialize(); #else + Py_Initialize(); inittgl(); #endif - Py_Initialize(); PyObject* sysPath = PySys_GetObject((char*)"path"); PyList_Append(sysPath, PyUnicode_FromString(dirname(filename))); diff --git a/tgl-test.py b/tgl-test.py index 83b14f1..4c0e3b5 100644 --- a/tgl-test.py +++ b/tgl-test.py @@ -1,7 +1,5 @@ import tgl -import geopy import pprint -from geopy.geocoders import Nominatim our_id = 0 pp = pprint.PrettyPrinter(indent=4) @@ -34,14 +32,9 @@ def on_msg_receive(msg): text = msg["text"] if text.startswith("!ping"): + print("SENDING PONG") tgl.send_msg(ptype, pid, "PONG!") - if text.startswith("!location"): - geolocator = Nominatim() - location = geolocator.geocode(msg["text"][9:]) - pp.pprint(location) - tgl.send_location(ptype, pid, location.latitude, location.longitude) - def on_secret_chat_update(peer, types): return "on_secret_chat_update" From c263a93a8bd6e9f74255686cfbca18721cf5edb9 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Mon, 11 May 2015 22:02:18 -0700 Subject: [PATCH 24/29] More const correctness issues. --- python-tg.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/python-tg.c b/python-tg.c index e7fb51e..14abad3 100644 --- a/python-tg.c +++ b/python-tg.c @@ -1407,9 +1407,11 @@ void py_init (const char *file) { PyObject *pModule; - // Get a copy of the filename for dirname, which may modify the string. - char filename[100]; - strncpy(filename, file, 100); + // Get a copy of the filename for dirname/basename, which may modify the string, and break const correctness + char filename[1024]; + strncpy(filename, file, 1024); + + #if PY_MAJOR_VERSION >= 3 PyImport_AppendInittab("tgl", &PyInit_tgl); @@ -1424,10 +1426,10 @@ void py_init (const char *file) { PyList_Append(sysPath, PyUnicode_FromString(dirname(filename))); // remove .py extension from file, if any - char* dot = strrchr(file, '.'); + char* dot = strrchr(filename, '.'); if (dot && strcmp(dot, ".py") == 0) *dot = 0; - pModule = PyImport_Import(PyUnicode_FromString(basename(file))); + pModule = PyImport_Import(PyUnicode_FromString(basename(filename))); if(pModule == NULL || PyErr_Occurred()) { // Error loading script logprintf("Failed to load python script\n"); From 871fc440b7c6488c281fa0ee5603241f3344bda0 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Tue, 12 May 2015 01:04:47 -0700 Subject: [PATCH 25/29] Add Callback support for async calls. --- python-tg.c | 729 ++++++++++++++++++++++------------------------------ tgl-test.py | 6 +- 2 files changed, 309 insertions(+), 426 deletions(-) diff --git a/python-tg.c b/python-tg.c index 14abad3..3053818 100644 --- a/python-tg.c +++ b/python-tg.c @@ -641,424 +641,362 @@ enum py_query_type { pq_extf }; -struct py_query_extra { - int func; - int param; -}; - void py_empty_cb (struct tgl_state *TLSR, void *cb_extra, int success) { -// assert (TLSR == TLS); -// struct lua_query_extra *cb = cb_extra; -// lua_settop (luaState, 0); -// //lua_checkstack (luaState, 20); -// my_lua_checkstack (luaState, 20); -// -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); -// -// lua_pushnumber (luaState, success); -// -// assert (lua_gettop (luaState) == 3); -// -// int r = lua_pcall (luaState, 2, 0, 0); -// -// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); -// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); -// -// if (r) { -// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); -// } -// -// free (cb); + assert (TLSR == TLS); + PyObject *callable = cb_extra; + PyObject *arglist = NULL; + PyObject *result = NULL; + + if(PyCallable_Check(callable)) { + arglist = Py_BuildValue("(O)", success ? Py_True : Py_False); + result = PyEval_CallObject(callable, arglist); + Py_DECREF(arglist); + + if(result == NULL) + PyErr_Print(); + + Py_XDECREF(result); + } + + Py_XDECREF(callable); } void py_contact_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_user **UL) { -// assert (TLSR == TLS); -// struct lua_query_extra *cb = cb_extra; -// lua_settop (luaState, 0); -// //lua_checkstack (luaState, 20); -// my_lua_checkstack (luaState, 20); -// -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); -// -// lua_pushnumber (luaState, success); -// -// if (success) { -// lua_newtable (luaState); -// int i; -// for (i = 0; i < num; i++) { -// lua_pushnumber (luaState, i); -// push_peer (UL[i]->id, (void *)UL[i]); -// lua_settable (luaState, -3); -// } -// } else { -// lua_pushboolean (luaState, 0); -// } -// -// assert (lua_gettop (luaState) == 4); -// -// int r = lua_pcall (luaState, 3, 0, 0); -// -// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); -// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); -// -// if (r) { -// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); -// } -// -// free (cb); + assert (TLSR == TLS); + PyObject *callable = cb_extra; + PyObject *arglist = NULL; + PyObject *peers = NULL; + PyObject *result = NULL; + + if(PyCallable_Check(callable)) { + peers = PyList_New(0); + if (success) { + int i; + for (i = 0; i < num; i++) { + PyList_Append(peers, get_peer (UL[i]->id, (void *)UL[i])); + } + } + + arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, peers); + result = PyEval_CallObject(callable, arglist); + Py_DECREF(arglist); + + if(result == NULL) + PyErr_Print(); + + Py_XDECREF(result); + } + + Py_XDECREF(callable); } void py_dialog_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, tgl_peer_id_t peers[], int msgs[], int unread[]) { -// assert (TLSR == TLS); -// struct lua_query_extra *cb = cb_extra; -// lua_settop (luaState, 0); -// //lua_checkstack (luaState, 20); -// my_lua_checkstack (luaState, 20); -// -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); -// -// lua_pushnumber (luaState, success); -// if (success) { -// lua_newtable (luaState); -// int i; -// for (i = 0; i < num; i++) { -// lua_pushnumber (luaState, i); -// -// lua_newtable (luaState); -// -// lua_pushstring (luaState, "peer"); -// push_peer (peers[i], tgl_peer_get (TLS, peers[i])); -// lua_settable (luaState, -3); -// -// struct tgl_message *M = tgl_message_get (TLS, msgs[i]); -// if (M && (M->flags & FLAG_CREATED)) { -// lua_pushstring (luaState, "message"); -// push_message (M); -// lua_settable (luaState, -3); -// } -// -// lua_pushstring (luaState, "unread"); -// lua_pushnumber (luaState, unread[i]); -// lua_settable (luaState, -3); -// -// lua_settable (luaState, -3); -// } -// } else { -// lua_pushboolean (luaState, 0); -// } -// assert (lua_gettop (luaState) == 4); -// -// -// int r = lua_pcall (luaState, 3, 0, 0); -// -// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); -// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); -// -// if (r) { -// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); -// } -// -// free (cb); + assert (TLSR == TLS); + PyObject *callable = cb_extra; + PyObject *arglist = NULL; + PyObject *dialog_list = NULL; + PyObject *dialog = NULL; + PyObject *result = NULL; + + if(PyCallable_Check(callable)) { + dialog_list = PyList_New(0); + if (success) { + int i; + for (i = 0; i < num; i++) { + dialog = PyDict_New(); + PyDict_SetItemString(dialog, "peer", get_peer(peers[i], tgl_peer_get (TLS, peers[i]))); + + struct tgl_message *M = tgl_message_get (TLS, msgs[i]); + if (M && (M->flags & FLAG_CREATED)) { + PyDict_SetItemString(dialog, "message", get_message(M)); + } + PyDict_SetItemString(dialog, "unread", unread[i] ? Py_True : Py_False); + + PyList_Append(dialog_list, dialog); + } + } + + arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, dialog_list); + result = PyEval_CallObject(callable, arglist); + Py_DECREF(arglist); + + if(result == NULL) + PyErr_Print(); + + Py_XDECREF(result); + } + + Py_XDECREF(callable); } void py_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_message *M) { assert (TLSR == TLS); -// struct lua_query_extra *cb = cb_extra; -// lua_settop (luaState, 0); -// //lua_checkstack (luaState, 20); -// my_lua_checkstack (luaState, 20); -// -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); -// -// lua_pushnumber (luaState, success); -// -// if (success) { -// push_message (M); -// } else { -// lua_pushboolean (luaState, 0); -// } -// -// assert (lua_gettop (luaState) == 4); -// -// int r = lua_pcall (luaState, 3, 0, 0); -// -// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); -// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); -// -// if (r) { -// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); -// } -// -// free (cb); + PyObject *callable = cb_extra; + PyObject *arglist = NULL; + PyObject *msg = NULL; + PyObject *result = NULL; + + if(PyCallable_Check(callable)) { + if (success) { + msg = get_message(M); + } else { + Py_INCREF(Py_None); + msg = Py_None; + } + + arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, msg); + result = PyEval_CallObject(callable, arglist); + Py_DECREF(arglist); + + if(result == NULL) + PyErr_Print(); + + Py_XDECREF(result); + } + + Py_XDECREF(callable); } void py_msg_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_message *M[]) { -// assert (TLSR == TLS); -// struct lua_query_extra *cb = cb_extra; -// lua_settop (luaState, 0); -// //lua_checkstack (luaState, 20); -// my_lua_checkstack (luaState, 20); -// -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); -// -// lua_pushnumber (luaState, success); -// -// if (success) { -// lua_newtable (luaState); -// int i; -// for (i = 0; i < num; i++) { -// lua_pushnumber (luaState, i); -// push_message (M[i]); -// lua_settable (luaState, -3); -// } -// } else { -// lua_pushboolean (luaState, 0); -// } -// -// assert (lua_gettop (luaState) == 4); -// -// int r = lua_pcall (luaState, 3, 0, 0); -// -// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); -// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); -// -// if (r) { -// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); -// } -// -// free (cb); + assert (TLSR == TLS); + PyObject *callable = cb_extra; + PyObject *arglist = NULL; + PyObject *msgs = NULL; + PyObject *result = NULL; + + if(PyCallable_Check(callable)) { + msgs = PyList_New(0); + if (success) { + int i; + for (i = 0; i < num; i++) { + PyList_Append(msgs, get_message (M[i])); + } + } + + arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, msgs); + result = PyEval_CallObject(callable, arglist); + Py_DECREF(arglist); + + if(result == NULL) + PyErr_Print(); + + Py_XDECREF(result); + } + + Py_XDECREF(callable); } void py_file_cb (struct tgl_state *TLSR, void *cb_extra, int success, char *file_name) { -// assert (TLSR == TLS); -// struct lua_query_extra *cb = cb_extra; -// lua_settop (luaState, 0); -// //lua_checkstack (luaState, 20); -// my_lua_checkstack (luaState, 20); -// -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); -// -// lua_pushnumber (luaState, success); -// -// if (success) { -// lua_pushstring (luaState, file_name); -// } else { -// lua_pushboolean (luaState, 0); -// } -// -// assert (lua_gettop (luaState) == 4); -// -// int r = lua_pcall (luaState, 3, 0, 0); -// -// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); -// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); -// -// if (r) { -// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); -// } -// -// free (cb); + assert (TLSR == TLS); + PyObject *callable = cb_extra; + PyObject *arglist = NULL; + PyObject *filename = NULL; + PyObject *result = NULL; + + if(PyCallable_Check(callable)) { + if(success) + filename = PyUnicode_FromString(file_name); + else { + Py_INCREF(Py_None); + filename = Py_None; + } + + arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, filename); + result = PyEval_CallObject(callable, arglist); + Py_DECREF(arglist); + + if(result == NULL) + PyErr_Print(); + + Py_XDECREF(result); + } + + Py_XDECREF(callable); } void py_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_chat *C) { -// assert (TLSR == TLS); -// struct lua_query_extra *cb = cb_extra; -// lua_settop (luaState, 0); -// //lua_checkstack (luaState, 20); -// my_lua_checkstack (luaState, 20); -// -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); -// -// lua_pushnumber (luaState, success); -// -// if (success) { -// push_peer (C->id, (void *)C); -// } else { -// lua_pushboolean (luaState, 0); -// } -// -// assert (lua_gettop (luaState) == 4); -// -// int r = lua_pcall (luaState, 3, 0, 0); -// -// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); -// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); -// -// if (r) { -// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); -// } -// -// free (cb); + assert (TLSR == TLS); + PyObject *callable = cb_extra; + PyObject *arglist = NULL; + PyObject *peer = NULL; + PyObject *result = NULL; + + if(PyCallable_Check(callable)) { + if (success) { + peer = get_peer(C->id, (void *)C); + } else { + Py_INCREF(Py_None); + peer = Py_None; + } + + arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, peer); + result = PyEval_CallObject(callable, arglist); + Py_DECREF(arglist); + + if(result == NULL) + PyErr_Print(); + + Py_XDECREF(result); + } + + Py_XDECREF(callable); } void py_secret_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_secret_chat *C) { -// assert (TLSR == TLS); -// struct lua_query_extra *cb = cb_extra; -// lua_settop (luaState, 0); -// //lua_checkstack (luaState, 20); -// my_lua_checkstack (luaState, 20); -// -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); -// -// lua_pushnumber (luaState, success); -// -// if (success) { -// push_peer (C->id, (void *)C); -// } else { -// lua_pushboolean (luaState, 0); -// } -// -// assert (lua_gettop (luaState) == 4); -// -// int r = lua_pcall (luaState, 3, 0, 0); -// -// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); -// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); -// -// if (r) { -// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); -// } -// -// free (cb); + assert (TLSR == TLS); + PyObject *callable = cb_extra; + PyObject *arglist = NULL; + PyObject *peer = NULL; + PyObject *result = NULL; + + if(PyCallable_Check(callable)) { + if (success) { + peer = get_peer(C->id, (void *)C); + } else { + Py_INCREF(Py_None); + peer = Py_None; + } + + arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, peer); + result = PyEval_CallObject(callable, arglist); + Py_DECREF(arglist); + + if(result == NULL) + PyErr_Print(); + + Py_XDECREF(result); + } + + Py_XDECREF(callable); } void py_user_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_user *C) { -// assert (TLSR == TLS); -// struct lua_query_extra *cb = cb_extra; -// lua_settop (luaState, 0); -// //lua_checkstack (luaState, 20); -// my_lua_checkstack (luaState, 20); -// -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); -// -// lua_pushnumber (luaState, success); -// -// if (success) { -// push_peer (C->id, (void *)C); -// } else { -// lua_pushboolean (luaState, 0); -// } -// -// assert (lua_gettop (luaState) == 4); -// -// int r = lua_pcall (luaState, 3, 0, 0); -// -// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); -// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); -// -// if (r) { -// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); -// } -// -// free (cb); + assert (TLSR == TLS); + PyObject *callable = cb_extra; + PyObject *arglist = NULL; + PyObject *peer = NULL; + PyObject *result = NULL; + + if(PyCallable_Check(callable)) { + if (success) { + peer = get_peer(C->id, (void *)C); + } else { + Py_INCREF(Py_None); + peer = Py_None; + } + + arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, peer); + result = PyEval_CallObject(callable, arglist); + Py_DECREF(arglist); + + if(result == NULL) + PyErr_Print(); + + Py_XDECREF(result); + } + + Py_XDECREF(callable); } void py_str_cb (struct tgl_state *TLSR, void *cb_extra, int success, char *data) { -// assert (TLSR == TLS); -// struct lua_query_extra *cb = cb_extra; -// lua_settop (luaState, 0); -// //lua_checkstack (luaState, 20); -// my_lua_checkstack (luaState, 20); -// -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); -// -// lua_pushnumber (luaState, success); -// -// if (success) { -// lua_pushstring (luaState, data); -// } else { -// lua_pushboolean (luaState, 0); -// } -// -// assert (lua_gettop (luaState) == 4); -// -// int r = lua_pcall (luaState, 3, 0, 0); -// -// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); -// luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); -// -// if (r) { -// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); -// } -// -// free (cb); + assert (TLSR == TLS); + PyObject *callable = cb_extra; + PyObject *arglist = NULL; + PyObject *str = NULL; + PyObject *result = NULL; + + if(PyCallable_Check(callable)) { + if(success) + str = PyUnicode_FromString(data); + else { + Py_INCREF(Py_None); + str = Py_None; + } + + arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, str); + result = PyEval_CallObject(callable, arglist); + Py_DECREF(arglist); + + if(result == NULL) + PyErr_Print(); + + Py_XDECREF(result); + } + + Py_XDECREF(callable); } void py_do_all (void) { int p = 0; while (p < pos) { - assert (p + 1 <= pos); + assert (p + 2 <= pos); enum py_query_type f = (long)py_ptr[p ++]; PyObject *args = (PyObject *)py_ptr[p ++]; + + + const char *str; int len; PyObject *pyObj1 = NULL; PyObject *pyObj2 = NULL; + PyObject *cb_extra; //struct tgl_message *M; tgl_peer_id_t peer, peer1; switch (f) { case pq_contact_list: - tgl_do_update_contact_list (TLS, py_contact_list_cb, NULL); + PyArg_ParseTuple(args, "O", &cb_extra); + tgl_do_update_contact_list (TLS, py_contact_list_cb, cb_extra); break; case pq_dialog_list: - tgl_do_get_dialog_list (TLS, py_dialog_list_cb, NULL); + PyArg_ParseTuple(args, "O", &cb_extra); + tgl_do_get_dialog_list (TLS, py_dialog_list_cb, cb_extra); break; case pq_msg: - PyArg_ParseTuple(args, "iis#", &peer.type, &peer.id, &str, &len); - tgl_do_send_message (TLS, peer, str, len, py_msg_cb, NULL); + PyArg_ParseTuple(args, "iis#O", &peer.type, &peer.id, &str, &len, &cb_extra); + tgl_do_send_message (TLS, peer, str, len, py_msg_cb, cb_extra); break; case pq_send_typing: - PyArg_ParseTuple(args, "ii", &peer.type, &peer.id); - tgl_do_send_typing (TLS, peer, tgl_typing_typing, py_empty_cb, NULL); + PyArg_ParseTuple(args, "iiO", &peer.type, &peer.id, &cb_extra); + tgl_do_send_typing (TLS, peer, tgl_typing_typing, py_empty_cb, cb_extra); break; case pq_send_typing_abort: - PyArg_ParseTuple(args, "ii", &peer.type, &peer.id); - tgl_do_send_typing (TLS, peer, tgl_typing_cancel, py_empty_cb, NULL); + PyArg_ParseTuple(args, "iiO", &peer.type, &peer.id, &cb_extra); + tgl_do_send_typing (TLS, peer, tgl_typing_cancel, py_empty_cb, cb_extra); break; case pq_rename_chat: - PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &str); - tgl_do_rename_chat (TLS, peer, str, py_msg_cb, NULL); + PyArg_ParseTuple(args, "iisO", &peer.type, &peer.id, &str, &cb_extra); + tgl_do_rename_chat (TLS, peer, str, py_msg_cb, cb_extra); break; case pq_send_photo: - PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &str); - tgl_do_send_document (TLS, -1, peer, str, py_msg_cb, NULL); + PyArg_ParseTuple(args, "iisO", &peer.type, &peer.id, &str, &cb_extra); + tgl_do_send_document (TLS, -1, peer, str, py_msg_cb, cb_extra); break; case pq_send_video: - PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &str); - tgl_do_send_document (TLS, FLAG_DOCUMENT_VIDEO, peer, str, py_msg_cb, NULL); + PyArg_ParseTuple(args, "iisO", &peer.type, &peer.id, &str, &cb_extra); + tgl_do_send_document (TLS, FLAG_DOCUMENT_VIDEO, peer, str, py_msg_cb, cb_extra); break; case pq_send_audio: - PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &str); - tgl_do_send_document (TLS, FLAG_DOCUMENT_AUDIO, peer, str, py_msg_cb, NULL); + PyArg_ParseTuple(args, "iisO", &peer.type, &peer.id, &str, &cb_extra); + tgl_do_send_document (TLS, FLAG_DOCUMENT_AUDIO, peer, str, py_msg_cb, cb_extra); break; case pq_send_document: - PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &str); - tgl_do_send_document (TLS, 0, peer, str, py_msg_cb, NULL); + PyArg_ParseTuple(args, "iisO", &peer.type, &peer.id, &str, &cb_extra); + tgl_do_send_document (TLS, 0, peer, str, py_msg_cb, cb_extra); break; case pq_send_file: - PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &str); - tgl_do_send_document (TLS, -2, peer, str, py_msg_cb, NULL); + PyArg_ParseTuple(args, "iisO", &peer.type, &peer.id, &str, &cb_extra); + tgl_do_send_document (TLS, -2, peer, str, py_msg_cb, cb_extra); break; case pq_send_text: - PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &str); - tgl_do_send_text (TLS, peer, str, py_msg_cb, NULL); + PyArg_ParseTuple(args, "iisO", &peer.type, &peer.id, &str, &cb_extra); + tgl_do_send_text (TLS, peer, str, py_msg_cb, cb_extra); break; case pq_chat_set_photo: - PyArg_ParseTuple(args, "iis", &peer.type, &peer.id, &str); - tgl_do_set_chat_photo (TLS, peer, str, py_msg_cb, NULL); + PyArg_ParseTuple(args, "iisO", &peer.type, &peer.id, &str, &cb_extra); + tgl_do_set_chat_photo (TLS, peer, str, py_msg_cb, cb_extra); break; /* case pq_load_photo: case pq_load_video: @@ -1103,12 +1041,12 @@ void py_do_all (void) { break; */ case pq_chat_add_user: - PyArg_ParseTuple(args, "iiii", &peer.type, &peer.id, &peer1.type, &peer1.id); - tgl_do_add_user_to_chat (TLS, peer, peer1, 100, py_msg_cb, NULL); + PyArg_ParseTuple(args, "iiiiO", &peer.type, &peer.id, &peer1.type, &peer1.id, &cb_extra); + tgl_do_add_user_to_chat (TLS, peer, peer1, 100, py_msg_cb, cb_extra); break; case pq_chat_del_user: - PyArg_ParseTuple(args, "iiii", &peer.type, &peer.id, &peer.type, &peer.id); - tgl_do_del_user_from_chat (TLS, peer, peer1, py_msg_cb, NULL); + PyArg_ParseTuple(args, "iiiiO", &peer.type, &peer.id, &peer.type, &peer.id, &cb_extra); + tgl_do_del_user_from_chat (TLS, peer, peer1, py_msg_cb, cb_extra); break; /* case pq_add_contact: tgl_do_add_contact (TLS, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), 0, py_contact_list_cb, py_ptr[p]); @@ -1154,18 +1092,20 @@ void py_do_all (void) { break; */ case pq_status_online: - tgl_do_update_status (TLS, 1, py_empty_cb, NULL); + PyArg_ParseTuple(args, "O", &cb_extra); + tgl_do_update_status (TLS, 1, py_empty_cb, cb_extra); break; case pq_status_offline: - tgl_do_update_status (TLS, 0, py_empty_cb, NULL); + PyArg_ParseTuple(args, "O", &cb_extra); + tgl_do_update_status (TLS, 0, py_empty_cb, cb_extra); break; /* case pq_extf: tgl_do_send_extf (TLS, s, strlen (s), py_str_cb, py_ptr[p]); break; */ case pq_send_location: - PyArg_ParseTuple(args, "iiOO", &peer.type, &peer.id, &pyObj1, &pyObj2); - tgl_do_send_location (TLS, peer, PyFloat_AsDouble(pyObj1), PyFloat_AsDouble(pyObj2), py_msg_cb, NULL); + PyArg_ParseTuple(args, "iiOOO", &peer.type, &peer.id, &pyObj1, &pyObj2, &cb_extra); + tgl_do_send_location (TLS, peer, PyFloat_AsDouble(pyObj1), PyFloat_AsDouble(pyObj2), py_msg_cb, cb_extra); Py_XDECREF(pyObj1); Py_XDECREF(pyObj2); break; @@ -1189,6 +1129,9 @@ void py_do_all (void) { assert (0); } + // Increment reference on cb_extra as it is passed on to the callback to use + Py_XINCREF(cb_extra); + // Clean up any arg variables we could have used. //Py_XDECREF(args); // TODO: this is going negative ref and causing segfaults @@ -1330,76 +1273,12 @@ MOD_INIT(tgl) } -//static void lua_postpone_alarm (evutil_socket_t fd, short what, void *arg) { -// int *t = arg; -// -// lua_settop (luaState, 0); -// //lua_checkstack (luaState, 20); -// my_lua_checkstack (luaState, 20); -// -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, t[1]); -// lua_rawgeti (luaState, LUA_REGISTRYINDEX, t[0]); -// assert (lua_gettop (luaState) == 2); -// -// int r = lua_pcall (luaState, 1, 0, 0); -// -// luaL_unref (luaState, LUA_REGISTRYINDEX, t[0]); -// luaL_unref (luaState, LUA_REGISTRYINDEX, t[1]); -// -// if (r) { -// logprintf ("lua: %s\n", lua_tostring (luaState, -1)); -// } -// -//} -// -//static int postpone_from_lua (lua_State *L) { -// int n = lua_gettop (L); -// if (n != 3) { -// lua_pushboolean (L, 0); -// return 1; -// } -// -// double timeout = lua_tonumber (L, -1); -// if (timeout < 0) { -// lua_pushboolean (L, 0); -// return 1; -// } -// -// lua_pop (L, 1); -// int a1 = luaL_ref (L, LUA_REGISTRYINDEX); -// int a2 = luaL_ref (L, LUA_REGISTRYINDEX); -// -// -// int *t = malloc (16); -// assert (t); -// struct event *ev = evtimer_new (TLS->ev_base, lua_postpone_alarm, t); -// t[0] = a1; -// t[1] = a2; -// *(void **)(t + 2) = ev; -// -// struct timeval ts= { -// .tv_sec = (long)timeout, -// .tv_usec = (timeout - ((long)timeout)) * 1000000 -// }; -// event_add (ev, &ts); -// -// lua_pushboolean (L, 1); -// return 1; -//} - -//extern int safe_quit; -//static int safe_quit_from_lua (lua_State *L) { -// int n = lua_gettop (L); -// if (n != 0) { -// lua_pushboolean (L, 0); -// return 1; -// } -// safe_quit = 1; -// -// lua_pushboolean (L, 1); -// return 1; -//} -// +extern int safe_quit; +static int safe_quit_from_py() { + Py_Finalize(); + safe_quit = 1; + return 1; +} void py_init (const char *file) { if (!file) { return; } diff --git a/tgl-test.py b/tgl-test.py index 4c0e3b5..fb0c885 100644 --- a/tgl-test.py +++ b/tgl-test.py @@ -16,6 +16,10 @@ def on_our_id(id): our_id = id return "Set ID: " + str(our_id) +def msg_cb(success, msg): + pp.pprint(success) + pp.pprint(msg) + def on_msg_receive(msg): if msg["out"] and not binlog_done: return; @@ -33,7 +37,7 @@ def on_msg_receive(msg): if text.startswith("!ping"): print("SENDING PONG") - tgl.send_msg(ptype, pid, "PONG!") + tgl.send_msg(ptype, pid, "PONG!", msg_cb) def on_secret_chat_update(peer, types): return "on_secret_chat_update" From 2ab3feb392a6fb8f65e9b9f96171a8f1140745e9 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Tue, 12 May 2015 01:51:59 -0700 Subject: [PATCH 26/29] Added get_history and get_history_ex to python bindings --- python-tg.c | 21 +++++++++++++++------ tgl-test.py | 16 +++++++++++++++- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/python-tg.c b/python-tg.c index 3053818..b3bbf8d 100644 --- a/python-tg.c +++ b/python-tg.c @@ -615,6 +615,7 @@ enum py_query_type { pq_chat_info, pq_user_info, pq_history, + pq_history_ext, pq_chat_add_user, pq_chat_del_user, pq_add_contact, @@ -937,7 +938,7 @@ void py_do_all (void) { const char *str; - int len; + int len, limit, offset; PyObject *pyObj1 = NULL; PyObject *pyObj2 = NULL; PyObject *cb_extra; @@ -1006,7 +1007,7 @@ void py_do_all (void) { if (!M || (M->media.type != tgl_message_media_photo && M->media.type != tgl_message_media_photo_encr && M->media.type != tgl_message_media_document && M->media.type != tgl_message_media_document_encr)) { py_file_cb (TLS, py_ptr[p], 0, 0); } else { - if (M->media.type == tgl_message_media_photo) { + , limit, offse, limit, offsettif (M->media.type == tgl_message_media_photo) { tgl_do_load_photo (TLS, &M->media.photo, py_file_cb, py_ptr[p]); } else if (M->media.type == tgl_message_media_document) { tgl_do_load_document (TLS, &M->media.document, py_file_cb, py_ptr[p]); @@ -1036,10 +1037,15 @@ void py_do_all (void) { case pq_user_info: tgl_do_get_user_info (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, 0, py_user_cb, py_ptr[p]); break; - case pq_history: - tgl_do_get_history (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, (long)py_ptr[p + 2], 0, py_msg_list_cb, py_ptr[p]); - break; */ + case pq_history: + PyArg_ParseTuple(args, "iiiO", &peer.type, &peer.id, &limit, &cb_extra); + tgl_do_get_history (TLS, peer, limit, 0, py_msg_list_cb, cb_extra); + break; + case pq_history_ext: + PyArg_ParseTuple(args, "iiiiO", &peer.type, &peer.id, &offset, &limit, &cb_extra); + tgl_do_get_history_ext (TLS, peer, offset, limit, 0, py_msg_list_cb, cb_extra); + break; case pq_chat_add_user: PyArg_ParseTuple(args, "iiiiO", &peer.type, &peer.id, &peer1.type, &peer1.id, &cb_extra); tgl_do_add_user_to_chat (TLS, peer, peer1, 100, py_msg_cb, cb_extra); @@ -1174,6 +1180,7 @@ PyObject* py_fwd_media(PyObject *self, PyObject *args) { return push_py_func(pq_ PyObject* py_chat_info(PyObject *self, PyObject *args) { return push_py_func(pq_chat_info, args); } PyObject* py_user_info(PyObject *self, PyObject *args) { return push_py_func(pq_chat_info, args); } PyObject* py_history(PyObject *self, PyObject *args) { return push_py_func(pq_history, args); } +PyObject* py_history_ext(PyObject *self, PyObject *args) { return push_py_func(pq_history_ext, args); } PyObject* py_chat_add_user(PyObject *self, PyObject *args) { return push_py_func(pq_chat_add_user, args); } PyObject* py_chat_del_user(PyObject *self, PyObject *args) { return push_py_func(pq_chat_del_user, args); } PyObject* py_add_contact(PyObject *self, PyObject *args) { return push_py_func(pq_add_contact, args); } @@ -1230,6 +1237,7 @@ static PyMethodDef py_tgl_methods[] = { {"chat_info", py_chat_info, METH_VARARGS, ""}, {"user_info", py_user_info, METH_VARARGS, ""}, {"get_history", py_history, METH_VARARGS, ""}, + {"get_history_ext", py_history_ext, METH_VARARGS, ""}, {"chat_add_user", py_chat_add_user, METH_VARARGS, ""}, {"chat_del_user", py_chat_del_user, METH_VARARGS, ""}, {"add_contact", py_add_contact, METH_VARARGS, ""}, @@ -1272,13 +1280,14 @@ MOD_INIT(tgl) return MOD_SUCCESS_VAL(m); } - +/* extern int safe_quit; static int safe_quit_from_py() { Py_Finalize(); safe_quit = 1; return 1; } +*/ void py_init (const char *file) { if (!file) { return; } diff --git a/tgl-test.py b/tgl-test.py index fb0c885..3c07062 100644 --- a/tgl-test.py +++ b/tgl-test.py @@ -1,5 +1,7 @@ import tgl import pprint +from functools import partial + our_id = 0 pp = pprint.PrettyPrinter(indent=4) @@ -20,6 +22,15 @@ def msg_cb(success, msg): pp.pprint(success) pp.pprint(msg) +HISTORY_QUERY_SIZE = 100 + +def history_cb(msg_list, ptype, pid, success, msgs): + print(len(msgs)) + msg_list.extend(msgs) + print(len(msg_list)) + if len(msgs) == HISTORY_QUERY_SIZE: + tgl.get_history_ext(ptype, pid, len(msg_list), HISTORY_QUERY_SIZE, partial(history_cb, msg_list, ptype, pid)); + def on_msg_receive(msg): if msg["out"] and not binlog_done: return; @@ -39,6 +50,10 @@ def on_msg_receive(msg): print("SENDING PONG") tgl.send_msg(ptype, pid, "PONG!", msg_cb) + if text.startswith("!loadhistory"): + msg_list = [] + tgl.get_history_ext(ptype, pid, 0, HISTORY_QUERY_SIZE, partial(history_cb, msg_list, ptype, pid)); + def on_secret_chat_update(peer, types): return "on_secret_chat_update" @@ -48,7 +63,6 @@ def on_user_update(): def on_chat_update(): pass - # Set callbacks tgl.set_on_binlog_replay_end(on_binlog_replay_end) tgl.set_on_get_difference_end(on_get_difference_end) From aad54b4c83b1ab1957fb82c6a9c71d250eaefc64 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Tue, 12 May 2015 02:05:30 -0700 Subject: [PATCH 27/29] Implement mark_read --- python-tg.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python-tg.c b/python-tg.c index b3bbf8d..c0e55e4 100644 --- a/python-tg.c +++ b/python-tg.c @@ -1069,9 +1069,12 @@ void py_do_all (void) { case pq_global_search: tgl_do_msg_search (TLS, tgl_set_peer_id (TGL_PEER_UNKNOWN, 0), 0, 0, 40, 0, s, py_msg_list_cb, py_ptr[p]); break; +*/ case pq_mark_read: - tgl_do_mark_read (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, py_empty_cb, py_ptr[p]); + PyArg_ParseTuple(args, "iiO", &peer.type, &peer.id, &cb_extra); + tgl_do_mark_read (TLS, peer, py_empty_cb, cb_extra); break; +/* case pq_set_profile_photo: tgl_do_set_profile_photo (TLS, s, py_empty_cb, py_ptr[p]); break; From 4daf7781bee5b0077e2704f7eb935d71b4d9229c Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Wed, 13 May 2015 00:55:08 -0700 Subject: [PATCH 28/29] Fix import error, still have const warnings. Implement mark_read --- python-tg.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/python-tg.c b/python-tg.c index b3bbf8d..0784687 100644 --- a/python-tg.c +++ b/python-tg.c @@ -1069,9 +1069,12 @@ void py_do_all (void) { case pq_global_search: tgl_do_msg_search (TLS, tgl_set_peer_id (TGL_PEER_UNKNOWN, 0), 0, 0, 40, 0, s, py_msg_list_cb, py_ptr[p]); break; +*/ case pq_mark_read: - tgl_do_mark_read (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, py_empty_cb, py_ptr[p]); + PyArg_ParseTuple(args, "iiO", &peer.type, &peer.id, &cb_extra); + tgl_do_mark_read (TLS, peer, py_empty_cb, cb_extra); break; +/* case pq_set_profile_photo: tgl_do_set_profile_photo (TLS, s, py_empty_cb, py_ptr[p]); break; @@ -1314,10 +1317,10 @@ void py_init (const char *file) { PyList_Append(sysPath, PyUnicode_FromString(dirname(filename))); // remove .py extension from file, if any - char* dot = strrchr(filename, '.'); + char* dot = strrchr(file, '.'); if (dot && strcmp(dot, ".py") == 0) *dot = 0; - pModule = PyImport_Import(PyUnicode_FromString(basename(filename))); + pModule = PyImport_Import(PyUnicode_FromString(basename(file))); if(pModule == NULL || PyErr_Occurred()) { // Error loading script logprintf("Failed to load python script\n"); From 89e0a1e275029f24627a22cef67fb6f6c44bffa0 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Wed, 13 May 2015 21:10:15 -0700 Subject: [PATCH 29/29] Make tgl callbacks optional --- python-tg.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/python-tg.c b/python-tg.c index 0784687..16cf89f 100644 --- a/python-tg.c +++ b/python-tg.c @@ -941,62 +941,62 @@ void py_do_all (void) { int len, limit, offset; PyObject *pyObj1 = NULL; PyObject *pyObj2 = NULL; - PyObject *cb_extra; + PyObject *cb_extra = NULL; //struct tgl_message *M; tgl_peer_id_t peer, peer1; switch (f) { case pq_contact_list: - PyArg_ParseTuple(args, "O", &cb_extra); + PyArg_ParseTuple(args, "|O", &cb_extra); tgl_do_update_contact_list (TLS, py_contact_list_cb, cb_extra); break; case pq_dialog_list: - PyArg_ParseTuple(args, "O", &cb_extra); + PyArg_ParseTuple(args, "|O", &cb_extra); tgl_do_get_dialog_list (TLS, py_dialog_list_cb, cb_extra); break; case pq_msg: - PyArg_ParseTuple(args, "iis#O", &peer.type, &peer.id, &str, &len, &cb_extra); + PyArg_ParseTuple(args, "iis#|O", &peer.type, &peer.id, &str, &len, &cb_extra); tgl_do_send_message (TLS, peer, str, len, py_msg_cb, cb_extra); break; case pq_send_typing: - PyArg_ParseTuple(args, "iiO", &peer.type, &peer.id, &cb_extra); + PyArg_ParseTuple(args, "ii|O", &peer.type, &peer.id, &cb_extra); tgl_do_send_typing (TLS, peer, tgl_typing_typing, py_empty_cb, cb_extra); break; case pq_send_typing_abort: - PyArg_ParseTuple(args, "iiO", &peer.type, &peer.id, &cb_extra); + PyArg_ParseTuple(args, "ii|O", &peer.type, &peer.id, &cb_extra); tgl_do_send_typing (TLS, peer, tgl_typing_cancel, py_empty_cb, cb_extra); break; case pq_rename_chat: - PyArg_ParseTuple(args, "iisO", &peer.type, &peer.id, &str, &cb_extra); + PyArg_ParseTuple(args, "iis|O", &peer.type, &peer.id, &str, &cb_extra); tgl_do_rename_chat (TLS, peer, str, py_msg_cb, cb_extra); break; case pq_send_photo: - PyArg_ParseTuple(args, "iisO", &peer.type, &peer.id, &str, &cb_extra); + PyArg_ParseTuple(args, "iis|O", &peer.type, &peer.id, &str, &cb_extra); tgl_do_send_document (TLS, -1, peer, str, py_msg_cb, cb_extra); break; case pq_send_video: - PyArg_ParseTuple(args, "iisO", &peer.type, &peer.id, &str, &cb_extra); + PyArg_ParseTuple(args, "iis|O", &peer.type, &peer.id, &str, &cb_extra); tgl_do_send_document (TLS, FLAG_DOCUMENT_VIDEO, peer, str, py_msg_cb, cb_extra); break; case pq_send_audio: - PyArg_ParseTuple(args, "iisO", &peer.type, &peer.id, &str, &cb_extra); + PyArg_ParseTuple(args, "iis|O", &peer.type, &peer.id, &str, &cb_extra); tgl_do_send_document (TLS, FLAG_DOCUMENT_AUDIO, peer, str, py_msg_cb, cb_extra); break; case pq_send_document: - PyArg_ParseTuple(args, "iisO", &peer.type, &peer.id, &str, &cb_extra); + PyArg_ParseTuple(args, "iis|O", &peer.type, &peer.id, &str, &cb_extra); tgl_do_send_document (TLS, 0, peer, str, py_msg_cb, cb_extra); break; case pq_send_file: - PyArg_ParseTuple(args, "iisO", &peer.type, &peer.id, &str, &cb_extra); + PyArg_ParseTuple(args, "iis|O", &peer.type, &peer.id, &str, &cb_extra); tgl_do_send_document (TLS, -2, peer, str, py_msg_cb, cb_extra); break; case pq_send_text: - PyArg_ParseTuple(args, "iisO", &peer.type, &peer.id, &str, &cb_extra); + PyArg_ParseTuple(args, "iis|O", &peer.type, &peer.id, &str, &cb_extra); tgl_do_send_text (TLS, peer, str, py_msg_cb, cb_extra); break; case pq_chat_set_photo: - PyArg_ParseTuple(args, "iisO", &peer.type, &peer.id, &str, &cb_extra); + PyArg_ParseTuple(args, "iis|O", &peer.type, &peer.id, &str, &cb_extra); tgl_do_set_chat_photo (TLS, peer, str, py_msg_cb, cb_extra); break; /* case pq_load_photo: @@ -1039,19 +1039,19 @@ void py_do_all (void) { break; */ case pq_history: - PyArg_ParseTuple(args, "iiiO", &peer.type, &peer.id, &limit, &cb_extra); + PyArg_ParseTuple(args, "iii|O", &peer.type, &peer.id, &limit, &cb_extra); tgl_do_get_history (TLS, peer, limit, 0, py_msg_list_cb, cb_extra); break; case pq_history_ext: - PyArg_ParseTuple(args, "iiiiO", &peer.type, &peer.id, &offset, &limit, &cb_extra); + PyArg_ParseTuple(args, "iiii|O", &peer.type, &peer.id, &offset, &limit, &cb_extra); tgl_do_get_history_ext (TLS, peer, offset, limit, 0, py_msg_list_cb, cb_extra); break; case pq_chat_add_user: - PyArg_ParseTuple(args, "iiiiO", &peer.type, &peer.id, &peer1.type, &peer1.id, &cb_extra); + PyArg_ParseTuple(args, "iiii|O", &peer.type, &peer.id, &peer1.type, &peer1.id, &cb_extra); tgl_do_add_user_to_chat (TLS, peer, peer1, 100, py_msg_cb, cb_extra); break; case pq_chat_del_user: - PyArg_ParseTuple(args, "iiiiO", &peer.type, &peer.id, &peer.type, &peer.id, &cb_extra); + PyArg_ParseTuple(args, "iiii|O", &peer.type, &peer.id, &peer.type, &peer.id, &cb_extra); tgl_do_del_user_from_chat (TLS, peer, peer1, py_msg_cb, cb_extra); break; /* case pq_add_contact: @@ -1071,7 +1071,7 @@ void py_do_all (void) { break; */ case pq_mark_read: - PyArg_ParseTuple(args, "iiO", &peer.type, &peer.id, &cb_extra); + PyArg_ParseTuple(args, "ii|O", &peer.type, &peer.id, &cb_extra); tgl_do_mark_read (TLS, peer, py_empty_cb, cb_extra); break; /* @@ -1101,11 +1101,11 @@ void py_do_all (void) { break; */ case pq_status_online: - PyArg_ParseTuple(args, "O", &cb_extra); + PyArg_ParseTuple(args, "|O", &cb_extra); tgl_do_update_status (TLS, 1, py_empty_cb, cb_extra); break; case pq_status_offline: - PyArg_ParseTuple(args, "O", &cb_extra); + PyArg_ParseTuple(args, "|O", &cb_extra); tgl_do_update_status (TLS, 0, py_empty_cb, cb_extra); break; /* case pq_extf: @@ -1113,7 +1113,7 @@ void py_do_all (void) { break; */ case pq_send_location: - PyArg_ParseTuple(args, "iiOOO", &peer.type, &peer.id, &pyObj1, &pyObj2, &cb_extra); + PyArg_ParseTuple(args, "iiOO|O", &peer.type, &peer.id, &pyObj1, &pyObj2, &cb_extra); tgl_do_send_location (TLS, peer, PyFloat_AsDouble(pyObj1), PyFloat_AsDouble(pyObj2), py_msg_cb, cb_extra); Py_XDECREF(pyObj1); Py_XDECREF(pyObj2);