From 31524068b6143eedd9c3662266c831af0b572823 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 2 May 2015 03:43:53 -0700 Subject: [PATCH 01/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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/97] 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); From 81b2a5accfe42b319db092a74ab91ffbf342513f Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 2 May 2015 03:43:53 -0700 Subject: [PATCH 30/97] 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 3e33cc2..941e883 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]) @@ -110,6 +111,17 @@ AC_ARG_ENABLE(json,[--enable-json/--disable-json], AC_DEFINE(USE_JSON,1,[use json]) ]) +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_MSG_CHECKING([progname]) 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 b290af88d3be5803bf6f2ebaa125bf2a9d69c53d Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 2 May 2015 04:45:49 -0700 Subject: [PATCH 31/97] 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 db463be5f68110087f81c5a3aeb44fa10913e919 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 2 May 2015 04:48:02 -0700 Subject: [PATCH 32/97] 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 5fcb8254dcfb904e789afd2bc3388bd39d9e4a62 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 2 May 2015 04:48:31 -0700 Subject: [PATCH 33/97] Adding missing changes to configure.ac --- configure.ac | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 941e883..333af6b 100644 --- a/configure.ac +++ b/configure.ac @@ -113,14 +113,17 @@ AC_ARG_ENABLE(json,[--enable-json/--disable-json], 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_MSG_CHECKING([progname]) From 3c6b54c6e1861e79ab863202e5676d7f07514957 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 2 May 2015 04:49:21 -0700 Subject: [PATCH 34/97] Merging to remove bad branch --- Makefile.in | 2 +- config.h.in | 3 + configure | 516 +++++++++++++++++++++++++++++++++++++++++++++++++++- interface.c | 27 ++- main.c | 20 ++ 5 files changed, 564 insertions(+), 4 deletions(-) diff --git a/Makefile.in b/Makefile.in index e1989ab..890216e 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 ${OBJ}/json-tg.o +TG_OBJECTS=${OBJ}/main.o ${OBJ}/loop.o ${OBJ}/interface.o ${OBJ}/lua-tg.o ${OBJ}/json-tg.o ${OBJ}/python-tg.o INCLUDE=-I. -I${srcdir} -I${srcdir}/tgl CC=@CC@ diff --git a/config.h.in b/config.h.in index 38bec97..72b5487 100644 --- a/config.h.in +++ b/config.h.in @@ -167,6 +167,9 @@ /* fixed for correct valgrind work */ #undef VALGRIND_FIXES +/* use python */ +#undef USE_PYTHON + /* Define to `int' if doesn't define. */ #undef gid_t diff --git a/configure b/configure index ea6dc0f..51ef044 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 @@ -695,6 +709,7 @@ enable_libconfig enable_extf enable_liblua enable_json +enable_python with_progname enable_valgrind ' @@ -709,7 +724,8 @@ CPPFLAGS CPP LUA LUA_INCLUDE -LUA_LIB' +LUA_LIB +PYTHON' # Initialize some variables set by options. @@ -1322,8 +1338,10 @@ Optional Features: --enable-libconfig/--disable-libconfig --enable-extf/--disable-extf --enable-liblua/--disable-liblua +<<<<<<< HEAD --enable-json/--disable-json --enable-valgrind/--disable-valgrind +--enable-python/--disable-python Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -1346,6 +1364,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. @@ -2393,6 +2412,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 # =========================================================================== @@ -5864,6 +5939,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 303426d..ce472cd 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 @@ -1265,6 +1269,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 (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { @@ -1279,6 +1284,7 @@ void do_clear (struct command *command, int arg_num, struct arg args[], struct i free (config_directory); free (binlog_file_name); free (lua_file); + free (python_file); clear_history (); event_free (term_ev); struct event_base *ev_base = TLS->ev_base; @@ -2307,6 +2313,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 (); @@ -2336,6 +2345,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) { @@ -2401,7 +2413,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; @@ -2432,7 +2447,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; @@ -2463,7 +2481,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 888eece..daa7831 100644 --- a/main.c +++ b/main.c @@ -75,6 +75,10 @@ # include "lua-tg.h" #endif +#ifdef USE_PYTHON +# include "python-tg.h" +#endif + #include #define PROGNAME "telegram-cli" @@ -107,6 +111,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; @@ -381,6 +386,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); @@ -698,6 +707,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': @@ -942,6 +956,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 e0c739148b0ec1913b22f3e9e33cf851a2b955be Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 2 May 2015 04:58:48 -0700 Subject: [PATCH 35/97] Remove -Werror for dev --- Makefile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.in b/Makefile.in index 890216e..0423097 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 1b2fb1e1fe795aaa178362f70b62860fbb907d48 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 2 May 2015 05:03:13 -0700 Subject: [PATCH 36/97] 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 b658b61773ea7498c2e5242c056fa043061c6a06 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 2 May 2015 21:32:30 -0700 Subject: [PATCH 37/97] progress commit on python support --- main.c | 17 ++ python-tg.c | 698 ++++++++++++++++++++++++++++------------------------ test.py | 23 ++ 3 files changed, 412 insertions(+), 326 deletions(-) create mode 100644 test.py diff --git a/main.c b/main.c index daa7831..9f54013 100644 --- a/main.c +++ b/main.c @@ -493,6 +493,23 @@ void usage (void) { #ifdef USE_JSON printf (" --json prints answers and values in json format\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"); + printf (" -d daemon mode\n"); + printf (" -L log file name\n"); + printf (" -U change uid after start\n"); + printf (" -G change gid after start\n"); + printf (" -D disable output\n"); + printf (" -P port to listen for input commands\n"); + printf (" -S unix socket to create\n"); + printf (" -e make commands end exit\n"); + printf (" -I use user and chat IDs in updates instead of names\n"); + printf (" -6 use ipv6 (may be unstable)\n"); + exit (1); } 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 3a13f800c969c16bc584a1e16d726746ef8592eb Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 2 May 2015 23:29:50 -0700 Subject: [PATCH 38/97] 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 9f54013..caa7ad7 100644 --- a/main.c +++ b/main.c @@ -669,6 +669,9 @@ void args_parse (int argc, char **argv) { #endif #ifdef USE_LUA "s:" +#endif +#ifdef USE_PYTHON + "Z:" #endif , long_options, NULL )) != -1) { 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 5994d34eefb5d105f56384a0923d246a72676d0c Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sun, 3 May 2015 09:53:29 -0700 Subject: [PATCH 39/97] 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 30f0a3b1280a2a3f7017a442210d9d236cadc7fd Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sun, 3 May 2015 22:42:11 -0700 Subject: [PATCH 40/97] 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 1bbe620..a81ebd1 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 @@ -215,6 +216,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 ad904dbdc02ee5e8f60893961de44831bc7334a8 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Wed, 6 May 2015 23:54:31 -0700 Subject: [PATCH 41/97] 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 a81ebd1..feabf25 100644 --- a/loop.c +++ b/loop.c @@ -660,6 +660,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) { @@ -715,6 +719,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 9ccc3016cfde73fcb4d4122b1303a8d60c210be5 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Thu, 7 May 2015 00:04:15 -0700 Subject: [PATCH 42/97] 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 caa7ad7..d4aad84 100644 --- a/main.c +++ b/main.c @@ -727,13 +727,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 8b10fe78a600c2ace69386dd497f3540a879eafe Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Thu, 7 May 2015 00:20:13 -0700 Subject: [PATCH 43/97] 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 b674adbd20c60019f8b503a3f03a4bdf83f187e1 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Thu, 7 May 2015 00:24:45 -0700 Subject: [PATCH 44/97] 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 66aa288b3db18710b08cfb89eeaef59fd48634e2 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Thu, 7 May 2015 00:34:47 -0700 Subject: [PATCH 45/97] 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 faaea75eec40864e211b88d069d68afc9dfe0fbd Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Thu, 7 May 2015 00:44:39 -0700 Subject: [PATCH 46/97] 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 319bd1d6ffe4004ac5ae05c269a67c0fe9c6d0a9 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Thu, 7 May 2015 00:51:29 -0700 Subject: [PATCH 47/97] 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 a30333b4eaebc7e3163c39fe84ba9cf8e6ed56cf Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Thu, 7 May 2015 00:53:39 -0700 Subject: [PATCH 48/97] 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 a301e831298612479e2d93b8da3ba65597fa2bf9 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Thu, 7 May 2015 01:54:17 -0700 Subject: [PATCH 49/97] 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 8c00b44863e795caea79ee646754a58c2ca792a8 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 9 May 2015 02:10:24 -0700 Subject: [PATCH 50/97] 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 51ef044..cf26c1e 100755 --- a/configure +++ b/configure @@ -5948,7 +5948,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 9e70eb1a1313279b4b21ee63b4a5b546d4dc50fb Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 9 May 2015 02:16:29 -0700 Subject: [PATCH 51/97] 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 30518100f08d775993b886ab15e3bfde4eba42f1 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sun, 10 May 2015 04:09:39 -0700 Subject: [PATCH 52/97] 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 dadc452a2b5709fae553e737d99b5259a970bdf9 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Mon, 11 May 2015 22:02:18 -0700 Subject: [PATCH 53/97] 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 2460901ba55448d4e1d8f111dc17c5ef8c7ef270 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Tue, 12 May 2015 01:04:47 -0700 Subject: [PATCH 54/97] 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 3c32cba05e0ac2300d25cc312980f2e35c4b00e7 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Tue, 12 May 2015 01:51:59 -0700 Subject: [PATCH 55/97] 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 5131593da4e60947ff58786b4fc0149ce1c96faa Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Tue, 12 May 2015 02:05:30 -0700 Subject: [PATCH 56/97] 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 c9f38274f56014339075ad1831eb034766e15d0d Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Wed, 13 May 2015 00:55:08 -0700 Subject: [PATCH 57/97] Fix import error, still have const warnings. Implement mark_read --- python-tg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python-tg.c b/python-tg.c index c0e55e4..0784687 100644 --- a/python-tg.c +++ b/python-tg.c @@ -1317,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 287011c1167483c7109062df7882d6c4fc7deaaf Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Wed, 13 May 2015 21:10:15 -0700 Subject: [PATCH 58/97] 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); From e1d65dad8fb4ae9b26e5427f7a1a75b62be5ce17 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Fri, 15 May 2015 09:26:45 -0700 Subject: [PATCH 59/97] Fix merge of configure --- configure | 5 ----- 1 file changed, 5 deletions(-) diff --git a/configure b/configure index 90b847d..1408bc9 100755 --- a/configure +++ b/configure @@ -6379,8 +6379,6 @@ $as_echo "#define USE_PYTHON 1" >>confdefs.h fi -<<<<<<< HEAD - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libjansson" >&5 $as_echo_n "checking for libjansson... " >&6; } # Check whether --enable-json was given. @@ -6501,9 +6499,6 @@ $as_echo "#define USE_JSON 1" >>confdefs.h fi -======= ->>>>>>> 1b3cdff3fde9a12d9251fa388fc86a94a905db2a - #check for custom prog name { $as_echo "$as_me:${as_lineno-$LINENO}: checking progname" >&5 $as_echo_n "checking progname... " >&6; } From d89499bff20e1510be8273a929bac60c4b6d6a73 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Fri, 15 May 2015 10:41:58 -0700 Subject: [PATCH 60/97] Fix tg-2.0.1 related issues in python bindings --- python-tg.c | 88 +++++++++++++++++++++++++++-------------------------- tgl | 2 +- tgl-test.py | 2 +- 3 files changed, 47 insertions(+), 45 deletions(-) diff --git a/python-tg.c b/python-tg.c index 16cf89f..c2e0a3c 100644 --- a/python-tg.c +++ b/python-tg.c @@ -277,7 +277,7 @@ PyObject* get_peer (tgl_peer_id_t id, tgl_peer_t *P) { 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)) { + if (!P || !(P->flags & TGLPF_CREATED)) { PyObject *name; static char s[100]; @@ -332,19 +332,9 @@ PyObject* get_media (struct tgl_message_media *M) { switch (M->type) { case tgl_message_media_photo: - case tgl_message_media_photo_encr: py_add_string_field (media, "type", "photo"); + py_add_string_field (media, "caption", M->caption); 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"); @@ -364,6 +354,23 @@ PyObject* get_media (struct tgl_message_media *M) { py_add_string_field (media, "last_name", M->last_name); py_add_num_field (media, "user_id", M->user_id); break; + case tgl_message_media_webpage: + py_add_string_field (media, "type", "webpage"); + py_add_string_field (media, "type", "webpage"); + py_add_string_field (media, "url", M->webpage->url); + py_add_string_field (media, "title", M->webpage->title); + py_add_string_field (media, "description", M->webpage->description); + py_add_string_field (media, "author", M->webpage->author); + break; + case tgl_message_media_venue: + py_add_string_field (media, "type", "venue"); + py_add_num_field (media, "longitude", M->venue.geo.longitude); + py_add_num_field (media, "latitude", M->venue.geo.latitude); + py_add_string_field (media, "title", M->venue.title); + py_add_string_field (media, "address", M->venue.address); + py_add_string_field (media, "provider", M->venue.provider); + py_add_string_field (media, "venue_id", M->venue.venue_id); + break; default: py_add_string_field (media, "type", "unknown"); } @@ -382,7 +389,9 @@ PyObject* get_message (struct tgl_message *M) { static char s[30]; snprintf (s, 30, "%lld", M->id); py_add_string_field (msg, "id", s); - if (!(M->flags & FLAG_CREATED)) { return msg; } + if (!(M->flags & TGLMF_CREATED)) { + Py_RETURN_NONE; + } py_add_num_field (msg, "flags", M->flags); if (tgl_get_peer_type (M->fwd_from_id)) { @@ -390,24 +399,24 @@ PyObject* get_message (struct tgl_message *M) { 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); + py_add_num_field (msg, "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)); - PyDict_SetItemString(msg, "unread", (M->unread ? Py_True : Py_False)); - PyDict_SetItemString(msg, "service", (M->service ? Py_True : Py_False)); + PyDict_SetItemString(msg, "mention", ((M->flags & TGLMF_MENTION) ? Py_True : Py_False)); + PyDict_SetItemString(msg, "out", ((M->flags & TGLMF_OUT) ? Py_True : Py_False)); + PyDict_SetItemString(msg, "unread", ((M->flags & TGLMF_UNREAD) ? Py_True : Py_False)); + PyDict_SetItemString(msg, "service", ((M->flags & TGLMF_SERVICE) ? Py_True : Py_False)); PyDict_SetItemString(msg, "date", get_datetime(M->date)); - if (!M->service) { + if (!(M->flags & TGLMF_SERVICE)) { if (M->message_len && M->message) { PyDict_SetItemString(msg, "text", PyUnicode_FromStringAndSize(M->message, M->message_len)); } @@ -615,7 +624,6 @@ 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, @@ -708,7 +716,7 @@ void py_dialog_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int 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)) { + if (M && (M->flags & TGLMF_CREATED)) { PyDict_SetItemString(dialog, "message", get_message(M)); } PyDict_SetItemString(dialog, "unread", unread[i] ? Py_True : Py_False); @@ -738,7 +746,7 @@ void py_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_ PyObject *result = NULL; if(PyCallable_Check(callable)) { - if (success) { + if (success && M && (M->flags & TGLMF_CREATED)) { msg = get_message(M); } else { Py_INCREF(Py_None); @@ -787,7 +795,7 @@ void py_msg_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int nu Py_XDECREF(callable); } -void py_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, const char *file_name) { assert (TLSR == TLS); PyObject *callable = cb_extra; PyObject *arglist = NULL; @@ -899,7 +907,7 @@ void py_user_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl Py_XDECREF(callable); } -void py_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, const char *data) { assert (TLSR == TLS); PyObject *callable = cb_extra; PyObject *arglist = NULL; @@ -953,11 +961,11 @@ void py_do_all (void) { break; case pq_dialog_list: PyArg_ParseTuple(args, "|O", &cb_extra); - tgl_do_get_dialog_list (TLS, py_dialog_list_cb, cb_extra); + tgl_do_get_dialog_list (TLS, 100, 0, py_dialog_list_cb, cb_extra); break; case pq_msg: 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); + tgl_do_send_message (TLS, peer, str, len, 0, py_msg_cb, cb_extra); break; case pq_send_typing: PyArg_ParseTuple(args, "ii|O", &peer.type, &peer.id, &cb_extra); @@ -968,32 +976,32 @@ void py_do_all (void) { tgl_do_send_typing (TLS, peer, tgl_typing_cancel, py_empty_cb, cb_extra); break; case pq_rename_chat: - PyArg_ParseTuple(args, "iis|O", &peer.type, &peer.id, &str, &cb_extra); - tgl_do_rename_chat (TLS, peer, str, py_msg_cb, cb_extra); + PyArg_ParseTuple(args, "iis#|O", &peer.type, &peer.id, &str, &len, &cb_extra); + tgl_do_rename_chat (TLS, peer, str, len, py_msg_cb, cb_extra); break; case pq_send_photo: 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); + tgl_do_send_document (TLS, peer, str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_PHOTO, py_msg_cb, cb_extra); break; case pq_send_video: 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); + tgl_do_send_document (TLS, peer, str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_VIDEO, py_msg_cb, cb_extra); break; case pq_send_audio: 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); + tgl_do_send_document (TLS, peer, str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_AUDIO, py_msg_cb, cb_extra); break; case pq_send_document: 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); + tgl_do_send_document (TLS, peer, str, NULL, 0, 0, py_msg_cb, cb_extra); break; case pq_send_file: 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); + tgl_do_send_document (TLS, peer, str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_AUTO, py_msg_cb, cb_extra); break; case pq_send_text: PyArg_ParseTuple(args, "iis|O", &peer.type, &peer.id, &str, &cb_extra); - tgl_do_send_text (TLS, peer, str, py_msg_cb, cb_extra); + tgl_do_send_text (TLS, peer, str, 0, py_msg_cb, cb_extra); break; case pq_chat_set_photo: PyArg_ParseTuple(args, "iis|O", &peer.type, &peer.id, &str, &cb_extra); @@ -1040,11 +1048,7 @@ void py_do_all (void) { */ case pq_history: 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, "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); + tgl_do_get_history (TLS, peer, offset, limit, 0, py_msg_list_cb, cb_extra); break; case pq_chat_add_user: PyArg_ParseTuple(args, "iiii|O", &peer.type, &peer.id, &peer1.type, &peer1.id, &cb_extra); @@ -1114,7 +1118,7 @@ void py_do_all (void) { */ case pq_send_location: 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); + tgl_do_send_location (TLS, peer, PyFloat_AsDouble(pyObj1), PyFloat_AsDouble(pyObj2), 0, py_msg_cb, cb_extra); Py_XDECREF(pyObj1); Py_XDECREF(pyObj2); break; @@ -1183,7 +1187,6 @@ 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); } @@ -1240,7 +1243,6 @@ 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, ""}, diff --git a/tgl b/tgl index 76824c2..b3dcce3 160000 --- a/tgl +++ b/tgl @@ -1 +1 @@ -Subproject commit 76824c29a6dcb424e1109e691d31280a9cbaa954 +Subproject commit b3dcce35110f5c995366318c2886065287815d09 diff --git a/tgl-test.py b/tgl-test.py index 3c07062..d0620cc 100644 --- a/tgl-test.py +++ b/tgl-test.py @@ -29,7 +29,7 @@ def history_cb(msg_list, ptype, pid, success, 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)); + tgl.get_history(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: From a7f42ed42d08697c5ddff807dc44b3246b9c3121 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Fri, 15 May 2015 10:50:27 -0700 Subject: [PATCH 61/97] Add missing offset to tgl_do_get_history --- python-tg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python-tg.c b/python-tg.c index c2e0a3c..7fa0046 100644 --- a/python-tg.c +++ b/python-tg.c @@ -1047,7 +1047,7 @@ void py_do_all (void) { break; */ case pq_history: - PyArg_ParseTuple(args, "iii|O", &peer.type, &peer.id, &limit, &cb_extra); + PyArg_ParseTuple(args, "iiii|O", &peer.type, &peer.id, &offset, &limit, &cb_extra); tgl_do_get_history (TLS, peer, offset, limit, 0, py_msg_list_cb, cb_extra); break; case pq_chat_add_user: From 3af44a3bf80ead45916b298e65f7288bfee719dc Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sun, 17 May 2015 14:55:41 -0700 Subject: [PATCH 62/97] Better name for test bindings for py --- tgl-test.py => tg-test.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tgl-test.py => tg-test.py (100%) diff --git a/tgl-test.py b/tg-test.py similarity index 100% rename from tgl-test.py rename to tg-test.py From d001bcd2ca944803cf2e0dfd7b0179af5da6f3dc Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sun, 17 May 2015 15:03:56 -0700 Subject: [PATCH 63/97] Const fixes again, hoping this won't break anything --- python-tg.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/python-tg.c b/python-tg.c index 7fa0046..914e92f 100644 --- a/python-tg.c +++ b/python-tg.c @@ -977,7 +977,7 @@ void py_do_all (void) { break; case pq_rename_chat: PyArg_ParseTuple(args, "iis#|O", &peer.type, &peer.id, &str, &len, &cb_extra); - tgl_do_rename_chat (TLS, peer, str, len, py_msg_cb, cb_extra); + tgl_do_rename_chat (TLS, peer, str, len, py_empty_cb, cb_extra); break; case pq_send_photo: PyArg_ParseTuple(args, "iis|O", &peer.type, &peer.id, &str, &cb_extra); @@ -1005,7 +1005,7 @@ void py_do_all (void) { break; case pq_chat_set_photo: 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); + tgl_do_set_chat_photo (TLS, peer, str, py_empty_cb, cb_extra); break; /* case pq_load_photo: case pq_load_video: @@ -1052,11 +1052,11 @@ void py_do_all (void) { break; case pq_chat_add_user: 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); + tgl_do_add_user_to_chat (TLS, peer, peer1, 100, py_empty_cb, cb_extra); break; case pq_chat_del_user: 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); + tgl_do_del_user_from_chat (TLS, peer, peer1, py_empty_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]); @@ -1319,10 +1319,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 77081999c458104f6802d56e2ef58e9fb0b68fc1 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sun, 17 May 2015 15:58:32 -0700 Subject: [PATCH 64/97] Fixes to autotools for python detection --- Makefile.in | 3 +- autotools.sh | 1 - ax_python.m4 | 12 +- bootstrap | 6 + config.h.in | 6 +- configure | 422 ++++++++++++++++++++++----------------------------- configure.ac | 57 ++++--- 7 files changed, 240 insertions(+), 267 deletions(-) delete mode 100755 autotools.sh create mode 100755 bootstrap diff --git a/Makefile.in b/Makefile.in index 0423097..efbc79e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -4,8 +4,7 @@ CFLAGS=@CFLAGS@ LDFLAGS=@LDFLAGS@ @OPENSSL_LDFLAGS@ CPPFLAGS=@CPPFLAGS@ @OPENSSL_INCLUDES@ DEFS=@DEFS@ -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 +COMPILE_FLAGS=${CFLAGS} ${CPFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Werror -Wextra -Wno-deprecated-declarations -fno-strict-aliasing -fno-omit-frame-pointer -ggdb -Wno-unused-parameter -fPIC EXTRA_LIBS=@LIBS@ @EXTRA_LIBS@ @OPENSSL_LIBS@ LOCAL_LDFLAGS=-rdynamic -ggdb -levent ${EXTRA_LIBS} LINK_FLAGS=${LDFLAGS} ${LOCAL_LDFLAGS} diff --git a/autotools.sh b/autotools.sh deleted file mode 100755 index e180398..0000000 --- a/autotools.sh +++ /dev/null @@ -1 +0,0 @@ -aclocal ; autoheader; automake ; autoconf diff --git a/ax_python.m4 b/ax_python.m4 index 5739922..1695480 100644 --- a/ax_python.m4 +++ b/ax_python.m4 @@ -56,7 +56,8 @@ AC_DEFUN([AX_PYTHON], [AC_MSG_CHECKING(for python build information) AC_MSG_RESULT([]) -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 python in python3.4 python3.3 python3.2 python3.1 python2.7 python2.6 python3, python2, python; do + AC_CHECK_PROGS(PYTHON_BIN, [$python]) ax_python_bin=$PYTHON_BIN if test x$ax_python_bin != x; then @@ -87,12 +88,21 @@ AC_MSG_RESULT([ Binary: $ax_python_bin]) AC_MSG_RESULT([ Library: $ax_python_lib]) AC_MSG_RESULT([ Include Dir: $ax_python_header]) + +PYTHON_FOUND=yes if test x$ax_python_header != xno; then PYTHON_INCLUDE_DIR=$ax_python_header AC_SUBST(PYTHON_INCLUDE_DIR) +else + PYTHON_FOUND=no fi + if test x$ax_python_lib != xno; then PYTHON_LIB=$ax_python_lib AC_SUBST(PYTHON_LIB) +else + PYTHON_FOUND=no fi +AC_SUBST(PYTHON_FOUND) + ])dnl diff --git a/bootstrap b/bootstrap new file mode 100755 index 0000000..67cea4f --- /dev/null +++ b/bootstrap @@ -0,0 +1,6 @@ +#! /bin/sh + +aclocal +autoheader +automake --gnu --add-missing +autoconf diff --git a/config.h.in b/config.h.in index 72b5487..bb5f2d6 100644 --- a/config.h.in +++ b/config.h.in @@ -164,12 +164,12 @@ /* use lua */ #undef USE_LUA -/* fixed for correct valgrind work */ -#undef VALGRIND_FIXES - /* use python */ #undef USE_PYTHON +/* fixed for correct valgrind work */ +#undef VALGRIND_FIXES + /* Define to `int' if doesn't define. */ #undef gid_t diff --git a/configure b/configure index 1408bc9..3eae742 100755 --- a/configure +++ b/configure @@ -624,15 +624,7 @@ EXTRA_LIBS LIBOBJS PYTHON_CFLAGS PYTHON_LIBS -pkgpyexecdir -pyexecdir -pkgpythondir -pythondir -PYTHON_PLATFORM -PYTHON_EXEC_PREFIX -PYTHON_PREFIX -PYTHON_VERSION -PYTHON +PYTHON_FOUND PYTHON_LIB PYTHON_INCLUDE_DIR PYTHON_BIN @@ -708,8 +700,8 @@ with_zlib enable_libconfig enable_extf enable_liblua -enable_json enable_python +enable_json with_progname enable_valgrind ' @@ -724,8 +716,7 @@ CPPFLAGS CPP LUA LUA_INCLUDE -LUA_LIB -PYTHON' +LUA_LIB' # Initialize some variables set by options. @@ -1338,9 +1329,9 @@ Optional Features: --enable-libconfig/--disable-libconfig --enable-extf/--disable-extf --enable-liblua/--disable-liblua +--enable-python/--disable-python --enable-json/--disable-json --enable-valgrind/--disable-valgrind ---enable-python/--disable-python Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -1363,7 +1354,6 @@ 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. @@ -5940,14 +5930,25 @@ fi fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for python" >&5 +$as_echo_n "checking for python... " >&6; } # 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 + if test "x$enableval" = "xno" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 +$as_echo "disabled" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5 +$as_echo "enabled" >&6; } + + { $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.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 python in python3.4 python3.3 python3.2 python3.1 python2.7 python2.6 python3, python2, python; do + for ac_prog in $python do # Extract the first word of "$ac_prog", so it can be a program name with args. @@ -6097,102 +6098,69 @@ $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; } + +PYTHON_FOUND=yes if test x$ax_python_header != xno; then PYTHON_INCLUDE_DIR=$ax_python_header +else + PYTHON_FOUND=no 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 + PYTHON_FOUND=no 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=: + + + + if test $PYTHON_FOUND = no ; then + as_fn_error $? "No supported python lib version found. Try --disable-python" "$LINENO" 5 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 + + + EXTRA_LIBS="${EXTRA_LIBS} -l${PYTHON_LIB}" + CPPFLAGS="${CPPFLAGS} -I${PYTHON_INCLUDE_DIR}" + +$as_echo "#define USE_PYTHON 1" >>confdefs.h + + fi + fi + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5 +$as_echo "enabled" >&6; } + + { $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.4 python3.3 python3.2 python3.1 python2.7 python2.6 python3, python2, 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_path_PYTHON+:} false; then : +if ${ac_cv_prog_PYTHON_BIN+:} 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 + 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_path_PYTHON="$as_dir/$ac_word$ac_exec_ext" + 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 @@ -6200,185 +6168,164 @@ 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; } +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 - fi - am_display_PYTHON=$am_cv_pathless_PYTHON - fi + test -n "$PYTHON_BIN" && break +done - - 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 : +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 - am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[:3])"` + 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 -{ $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)"` +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 -{ $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 : + 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 - if test "x$prefix" = xNONE - then - am_py_prefix=$ac_default_prefix - else - am_py_prefix=$prefix + 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 - 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 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 +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; } +PYTHON_FOUND=yes +if test x$ax_python_header != xno; then + PYTHON_INCLUDE_DIR=$ax_python_header - 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 - + PYTHON_FOUND=no +fi + +if test x$ax_python_lib != xno; then + PYTHON_LIB=$ax_python_lib + +else + PYTHON_FOUND=no 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 + + if test $PYTHON_FOUND = no ; then + as_fn_error $? "No supported python lib version found. Try --disable-python" "$LINENO" 5 + else - - fi - - - PY_PREFIX=`$PYTHON -c 'import sys ; print sys.prefix'` - - - EXTRA_LIBS="${EXTRA_LIBS} -l${PYTHON_LIB}" - CPPFLAGS="${CPPFLAGS} -I${PYTHON_INCLUDE_DIR}" - + EXTRA_LIBS="${EXTRA_LIBS} -l${PYTHON_LIB}" + CPPFLAGS="${CPPFLAGS} -I${PYTHON_INCLUDE_DIR}" $as_echo "#define USE_PYTHON 1" >>confdefs.h + fi fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libjansson" >&5 $as_echo_n "checking for libjansson... " >&6; } # Check whether --enable-json was given. @@ -6499,6 +6446,7 @@ $as_echo "#define USE_JSON 1" >>confdefs.h fi + #check for custom prog name { $as_echo "$as_me:${as_lineno-$LINENO}: checking progname" >&5 $as_echo_n "checking progname... " >&6; } diff --git a/configure.ac b/configure.ac index 2379821..a2c09e5 100644 --- a/configure.ac +++ b/configure.ac @@ -94,20 +94,45 @@ AC_ARG_ENABLE(liblua,[--enable-liblua/--disable-liblua], AC_MSG_ERROR([No lua found. Try --disable-liblua]) ]) ]) + +AC_MSG_CHECKING([for python]) 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'` - AC_SUBST([PYTHON_LIBS]) - AC_SUBST([PYTHON_CFLAGS]) - EXTRA_LIBS="${EXTRA_LIBS} -l${PYTHON_LIB}" - CPPFLAGS="${CPPFLAGS} -I${PYTHON_INCLUDE_DIR}" + if test "x$enableval" = "xno" ; then + AC_MSG_RESULT([disabled]) + else + AC_MSG_RESULT([enabled]) - AC_DEFINE(USE_PYTHON,1,[use python]) + AX_PYTHON() + AC_SUBST([PYTHON_FOUND]) + if test $PYTHON_FOUND = no ; then + AC_MSG_ERROR([No supported python lib version found. Try --disable-python]) + else + 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]) + fi + fi + ],[ + AC_MSG_RESULT([enabled]) + + AX_PYTHON() + AC_SUBST([PYTHON_FOUND]) + if test $PYTHON_FOUND = no ; then + AC_MSG_ERROR([No supported python lib version found. Try --disable-python]) + else + 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]) + fi ]) + + AC_MSG_CHECKING([for libjansson]) AC_ARG_ENABLE(json,[--enable-json/--disable-json], [ @@ -124,20 +149,6 @@ AC_ARG_ENABLE(json,[--enable-json/--disable-json], AC_DEFINE(USE_JSON,1,[use json]) ]) -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'` - 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_MSG_CHECKING([progname]) AC_ARG_WITH(progname,[--with-progname=], From 1ca2fe694161d78809159fbfe8789776251216fd Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sun, 17 May 2015 16:48:17 -0700 Subject: [PATCH 65/97] Implement the rest of the methods. Remaining commented out methods require more advanced python c-api objects --- python-tg.c | 94 +++++++++++++++++++++++++++-------------------------- 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/python-tg.c b/python-tg.c index 914e92f..f8d0588 100644 --- a/python-tg.c +++ b/python-tg.c @@ -943,10 +943,10 @@ void py_do_all (void) { enum py_query_type f = (long)py_ptr[p ++]; PyObject *args = (PyObject *)py_ptr[p ++]; - - - const char *str; - int len, limit, offset; + const char *str, *str1, *str2, *str3; + int len, len1, len2, len3; + int limit, offset; + long msg_id; PyObject *pyObj1 = NULL; PyObject *pyObj2 = NULL; PyObject *cb_extra = NULL; @@ -1033,19 +1033,23 @@ void py_do_all (void) { 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]); + PyArg_ParseTuple(args, "iil|O", &peer.type, &peer.id, &msg_id, &cb_extra); + tgl_do_forward_message (TLS, peer, msg_id, 0, py_msg_cb, cb_extra); 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]); + PyArg_ParseTuple(args, "iil|O", &peer.type, &peer.id, &msg_id, &cb_extra); + tgl_do_forward_media (TLS, peer, msg_id, 0, py_msg_cb, cb_extra); 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]); + PyArg_ParseTuple(args, "ii|O", &peer.type, &peer.id, &cb_extra); + tgl_do_get_chat_info (TLS, peer, 0, py_chat_cb, cb_extra); 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]); + PyArg_ParseTuple(args, "ii|O", &peer.type, &peer.id, &cb_extra); + tgl_do_get_user_info (TLS, peer, 0, py_user_cb, cb_extra); break; -*/ case pq_history: PyArg_ParseTuple(args, "iiii|O", &peer.type, &peer.id, &offset, &limit, &cb_extra); tgl_do_get_history (TLS, peer, offset, limit, 0, py_msg_list_cb, cb_extra); @@ -1058,52 +1062,66 @@ void py_do_all (void) { 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_empty_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]); + case pq_add_contact: + PyArg_ParseTuple(args, "s#s#s#|O", &str1, &len1, &str2, &len2, &str3, &len3, &cb_extra); + tgl_do_add_contact (TLS, str1, len1, str2, len2, str3, len3, 0, py_contact_list_cb, cb_extra); break; case pq_del_contact: - tgl_do_del_contact (TLS, ((tgl_peer_t *)py_ptr[p + 1])->id, py_empty_cb, py_ptr[p]); + PyArg_ParseTuple(args, "ii|O", &peer.type, &peer.id, &cb_extra); + tgl_do_del_contact (TLS, peer, py_empty_cb, cb_extra); 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]); + PyArg_ParseTuple(args, "s#s#s#|O", &str1, &len1, &str2, &len2, &str3, &len3, &cb_extra); + tgl_do_add_contact (TLS, str1, len1, str2, len2, str3, len3, 1, py_contact_list_cb, cb_extra); 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]); + PyArg_ParseTuple(args, "iis#|O", &peer.type, &peer.id, &str, &len, &cb_extra); + tgl_do_msg_search (TLS, peer, 0, 0, 40, 0, str, len, py_msg_list_cb, cb_extra); 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]); + PyArg_ParseTuple(args, "s#|O", &str, &len, &cb_extra); + tgl_do_msg_search (TLS, tgl_set_peer_id (TGL_PEER_UNKNOWN, 0), 0, 0, 40, 0, str, len, py_msg_list_cb, cb_extra); break; -*/ case pq_mark_read: PyArg_ParseTuple(args, "ii|O", &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]); + PyArg_ParseTuple(args, "s|O", &str, &cb_extra); + tgl_do_set_profile_photo (TLS, str, py_empty_cb, cb_extra); break; case pq_set_profile_name: - tgl_do_set_profile_name (TLS, s1, s2, py_user_cb, py_ptr[p]); + PyArg_ParseTuple(args, "s#s#|O", &str1, &len1, &str2, len2, &cb_extra); + tgl_do_set_profile_name (TLS, str1, len1, str2, len2, py_user_cb, cb_extra); 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]); + PyArg_ParseTuple(args, "ii|O", &peer.type, &peer.id, &cb_extra); + tgl_do_create_secret_chat (TLS, peer, py_secret_chat_cb, cb_extra); 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]); + PyArg_ParseTuple(args, "Os|O", &pyObj1, str, &cb_extra); + if(PyList_Check(pyObj1) { + tgl_do_create_group_chat (TLS, peer, str, py_msg_cb, cb_extra); + } else { + logprintf("create_group_chat: Argument 1 must be a list of peers" + } 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]); + PyArg_ParseTuple(args, "l|O", msg_id, &cb_extra); + tgl_do_delete_msg (TLS, msg_id, py_empty_cb, cb_extra); 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_send_contact: + PyArg_ParseTuple(args, "iis#s#s#|O", &peer.type, &peer.id, &str1, &len1, &str2, &len2, &str3, &len3, &cb_extra); + tgl_do_send_contact (TLS, peer, str1, len1, str2, len2, str3, len3, 0, py_msg_cb, cb_extra); + break; case pq_status_online: PyArg_ParseTuple(args, "|O", &cb_extra); tgl_do_update_status (TLS, 1, py_empty_cb, cb_extra); @@ -1112,32 +1130,16 @@ void py_do_all (void) { 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]); + case pq_extf: + PyArg_ParseTuple(args, "s#|O", &str, &len, &cb_extra); + tgl_do_send_extf (TLS, str, len, py_str_cb, &cb_extra); break; -*/ case pq_send_location: 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), 0, py_msg_cb, cb_extra); Py_XDECREF(pyObj1); Py_XDECREF(pyObj2); 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); } From 36d5465d818e0f7a0e83c2a192c2dc5e5bd18468 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Mon, 18 May 2015 13:32:58 -0700 Subject: [PATCH 66/97] Fixed string mangling from dirname --- python-tg.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/python-tg.c b/python-tg.c index f8d0588..a0891f6 100644 --- a/python-tg.c +++ b/python-tg.c @@ -1320,6 +1320,9 @@ void py_init (const char *file) { PyObject* sysPath = PySys_GetObject((char*)"path"); PyList_Append(sysPath, PyUnicode_FromString(dirname(filename))); + // Recopy the string in, since dirname modified it. + strncpy(filename, file, 1024); + // remove .py extension from file, if any char* dot = strrchr(filename, '.'); if (dot && strcmp(dot, ".py") == 0) From da885d595a7b7865c98d5c72bcb51cd883925f2d Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Mon, 18 May 2015 14:31:59 -0700 Subject: [PATCH 67/97] Clean up msgs and newlines --- python-tg.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python-tg.c b/python-tg.c index a0891f6..081c9b3 100644 --- a/python-tg.c +++ b/python-tg.c @@ -483,7 +483,8 @@ void py_our_id (int id) { arglist = Py_BuildValue("(i)", id); result = PyEval_CallObject(_py_our_id, arglist); - Py_DECREF(arglist); if(result == NULL) + Py_DECREF(arglist); + if(result == NULL) PyErr_Print(); else if(PyUnicode_Check(result)) logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result))); @@ -1338,6 +1339,6 @@ void py_init (const char *file) { python_loaded = 1; PyDateTime_IMPORT; - logprintf("Python Initialized"); + logprintf("Python Initialized\n"); } From 50a654706bfb2a9077686c85d8f76c8e808a72bc Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Mon, 18 May 2015 17:13:51 -0700 Subject: [PATCH 68/97] Fix reply ID --- python-tg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python-tg.c b/python-tg.c index 081c9b3..e888a99 100644 --- a/python-tg.c +++ b/python-tg.c @@ -400,7 +400,8 @@ PyObject* get_message (struct tgl_message *M) { } if (M->reply_id) { - py_add_num_field (msg, "reply_to_id", M->reply_id); + snprintf (s, 30, "%lld", M->id); + py_add_string_field (msg, "reply_id", s); struct tgl_message *MR = tgl_message_get (TLS, M->reply_id); // Message details available only within session for now if (MR) { From 0a74621916858d95dafb8baaef3b1fe78fdd1331 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Mon, 18 May 2015 12:24:26 -0700 Subject: [PATCH 69/97] Adding new framework for more advanced python classes that wrap tgl structures. --- python-types.h | 271 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 python-types.h diff --git a/python-types.h b/python-types.h new file mode 100644 index 0000000..25dea90 --- /dev/null +++ b/python-types.h @@ -0,0 +1,271 @@ +#ifndef __PYTHON_TYPES_H__ +#define __PYTHON_TYPES_H__ + +#include +#include +#include +#include +#include "structmember.h" + +typedef struct { + PyObject_HEAD + tgl_peer_t peer; +} tgl_Peer; + +extern struct tgl_state *TLS; + +// modeled after tgls_free_peer +static void +tgl_Peer_dealloc(tgl_Peer* self) +{ + switch(self->peer.id.type) { + case TGL_PEER_USER: + if (self->peer.first_name) tfree_str(self->peer.first_name); + if (self->peer.last_name) tfree_str(self->peer.last_name); + if (self->peer.print_name) tfree_str(self->peer.print_name); + if (self->peer.phone) tfree_str(self->peer.phone); + if (self->peer.real_first_name) tfree_str(self->peer.real_first_name); + if (self->peer.real_last_name) tfree_str(self->peer.real_last_name); + if (self->peer.status.ev) { tgl_remove_status_expire (TLS, &self->peer); } + tgls_free_photo (TLS, self->peer.photo); + break; + case TGL_PEER_CHAT: + if (self->peer.title) tfree_str(self->peer.title); + if (self->peer.print_title) tfree_str(self->peer.print_title); + if (self->peer.user_list) tfree(self->peer.user_list, self->peer.user_list_size * sizeof(tgl_chat_user)); + tgls_free_photo (TLS, self->peer.photo); + break; + case TGL_PEER_ENCR_CHAT: + if (self->peer.print_name) tfree_str(self->peer.print_name); + if (self->peer.g_key) tfree (self->peer.g_key, 256); + break; + default: + } + + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static PyObject * +tgl_Peer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + tgl_Peer *self; + + self = (tgl_Peer *)type->tp_alloc(type, 0); + if (self != NULL) { + self->peer.id.type = 0; + self->peer.id.id = 0; + } + + return (PyObject *)self; +} + +static int +tgl_Peer_init(tgl_Peer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"type", "id", NULL}; + + if(!PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwlist, + &self->peer.id.type, + &self->peer.id.id)) + return -1; + + return 0; +} + +static PyObject * +tgl_Peer_get_name (tgl_Peer *self, void *closure) +{ + PyObject *ret; + if(self->peer.id.type == TGL_PEER_CHAT) + ret = PyUnicode_FromString(self->peer.print_title); + else + ret = PyUnicode_FromString(self->peer.print_name); + + Py_XINCREF(ret); + return ret; +} + + +static PyObject * +tgl_Peer_getuser_id (tgl_Peer *self, void *closure) +{ + PyObject *ret; + + if(self->peer.id.type == TGL_PEER_CHAT) + { + PyErr_SetString(PyExc_TypeError, + "peer.type == TGL_PEER_CHAT has no user_id"); + Py_RETURN_NONE; + } else { + ret = PyLong_FromLong(self->peer.user_id); + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Peer_getuser_list (tgl_Peer *self, void *closure) +{ + PyObject *ret, *peer; + tgl_chat_user *user_list; + + if(self->peer.id.type == TGL_PEER_CHAT) + { + ret = PyList_New(); + for(int i = 0; i < self->peer.user_list_size; i++) { + user_list = self->peer.userlist + i; + + } + } else { + PyErr_SetString(PyExc_TypeError, + "Only peer.type == TGL_PEER_CHAT has user_list"); + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Peer_get (tgl_Peer *self, void *closure) +{ + PyObject *ret; + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Peer_get (tgl_Peer *self, void *closure) +{ + PyObject *ret; + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Peer_get (tgl_Peer *self, void *closure) +{ + PyObject *ret; + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Peer_get (tgl_Peer *self, void *closure) +{ + PyObject *ret; + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Peer_get (tgl_Peer *self, void *closure) +{ + PyObject *ret; + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Peer_get (tgl_Peer *self, void *closure) +{ + PyObject *ret; + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Peer_get (tgl_Peer *self, void *closure) +{ + PyObject *ret; + + Py_XINCREF(ret); + return ret; +} + + + +static PyMemberDef tgl_Peer_members[] = { + {"type", T_INT, offsetof(tgl_Peer, peer.id.type), 0, "Peer Type"}, + {"id", T_INT, offsetof(tgl_Peer, peer.id.id), 0, "Peer ID" }, + {NULL} /* Sentinel */ +}; + +static PyObject * +tgl_Peer_type_name(tgl_Peer* self) +{ + PyObject *name; + switch(self->peer.id.type) { + case TGL_PEER_USER: + name = PyUnicode_FromString("user"); + break; + case TGL_PEER_CHAT: + name = PyUnicode_FromString("chat"); + break; + case TGL_PEER_ENCR_CHAT: + name = PyUnicode_FromString("secret_chat"); + break; + default: + name = PyUnicode_FromString("unknown"); + } + + return name; +} + +static PyMethodDef tgl_Peer_methods[] = { + {"type_name", (PyCFunction)tgl_Peer_type_name, METH_NOARGS, + "Return the string representation of the peer type." + }, + {NULL} /* Sentinel */ +}; + + +static PyTypeObject tgl_PeerType = { + PyVarObject_HEAD_INIT(NULL, 0) + "tgl.Peer", /* tp_name */ + sizeof(tgl_Peer), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)tgl_Peer_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + "tgl Peer", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + tgl_Peer_methods, /* tp_methods */ + tgl_Peer_members, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)tgl_Peer_init, /* tp_init */ + 0, /* tp_alloc */ + tgl_Peer_new, /* tp_new */ +}; + +#endif From d6407a028e7d038a9edb9e2b97a79a6c40916f8d Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Mon, 18 May 2015 12:25:45 -0700 Subject: [PATCH 70/97] More WIP work --- Makefile.in | 2 +- python-tg.c | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Makefile.in b/Makefile.in index efbc79e..c3116f3 100644 --- a/Makefile.in +++ b/Makefile.in @@ -4,7 +4,7 @@ CFLAGS=@CFLAGS@ LDFLAGS=@LDFLAGS@ @OPENSSL_LDFLAGS@ CPPFLAGS=@CPPFLAGS@ @OPENSSL_INCLUDES@ DEFS=@DEFS@ -COMPILE_FLAGS=${CFLAGS} ${CPFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Werror -Wextra -Wno-deprecated-declarations -fno-strict-aliasing -fno-omit-frame-pointer -ggdb -Wno-unused-parameter -fPIC +COMPILE_FLAGS=${CFLAGS} ${CPFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Werror -Wextra -Wno-missing-field-initializers -Wno-deprecated-declarations -fno-strict-aliasing -fno-omit-frame-pointer -ggdb -Wno-unused-parameter -fPIC EXTRA_LIBS=@LIBS@ @EXTRA_LIBS@ @OPENSSL_LIBS@ LOCAL_LDFLAGS=-rdynamic -ggdb -levent ${EXTRA_LIBS} LINK_FLAGS=${LDFLAGS} ${LOCAL_LDFLAGS} diff --git a/python-tg.c b/python-tg.c index e888a99..5a1a9ad 100644 --- a/python-tg.c +++ b/python-tg.c @@ -24,6 +24,7 @@ #ifdef USE_PYTHON #include "python-tg.h" +#include "python-types.h" #endif #include @@ -1286,6 +1287,12 @@ MOD_INIT(tgl) if (m == NULL) return MOD_ERROR_VAL; + if (PyType_Ready(&tgl_PeerType) < 0) + return MOD_ERROR_VAL; + + Py_INCREF(&tgl_PeerType); + PyModule_AddObject(m, "Peer", (PyObject *)&tgl_PeerType); + return MOD_SUCCESS_VAL(m); } From d6dec6f881107ea628923415eb5a1d9e6f57c25f Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Mon, 18 May 2015 12:26:57 -0700 Subject: [PATCH 71/97] Adding __pycache__ --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 90dcfa1..f9f3975 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ debian/files debian/telegram-cli/* debian/telegram-cli.debhelper.log debian/telegram-cli.substvars +__pycache__ From fa26c2b6968d49149296418803054aad514529b3 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Tue, 19 May 2015 01:40:57 -0700 Subject: [PATCH 72/97] Completed initial tgl_Peer type implementation --- python-tg.c | 10 +- python-types.h | 273 ++++++++++++++++++++++++++++++++++--------------- tg-test.py | 9 +- 3 files changed, 208 insertions(+), 84 deletions(-) diff --git a/python-tg.c b/python-tg.c index 5a1a9ad..b216390 100644 --- a/python-tg.c +++ b/python-tg.c @@ -24,7 +24,6 @@ #ifdef USE_PYTHON #include "python-tg.h" -#include "python-types.h" #endif #include @@ -74,6 +73,11 @@ // Python Imports #include "datetime.h" +// Custom Types +#include "python-types.h" + + + //#include "interface.h" //#include "auto/constants.h" #include @@ -269,7 +273,7 @@ PyObject* get_update_types (unsigned flags) { 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; @@ -320,7 +324,9 @@ PyObject* get_peer (tgl_peer_id_t id, tgl_peer_t *P) { } PyDict_SetItemString (peer, "peer", peer_obj); } +*/ + peer = tgl_Peer_FromTglPeer(P); return peer; } diff --git a/python-types.h b/python-types.h index 25dea90..8092416 100644 --- a/python-types.h +++ b/python-types.h @@ -3,6 +3,9 @@ #include #include +#include +#include +#include #include #include #include "structmember.h" @@ -20,26 +23,28 @@ tgl_Peer_dealloc(tgl_Peer* self) { switch(self->peer.id.type) { case TGL_PEER_USER: - if (self->peer.first_name) tfree_str(self->peer.first_name); - if (self->peer.last_name) tfree_str(self->peer.last_name); - if (self->peer.print_name) tfree_str(self->peer.print_name); - if (self->peer.phone) tfree_str(self->peer.phone); - if (self->peer.real_first_name) tfree_str(self->peer.real_first_name); - if (self->peer.real_last_name) tfree_str(self->peer.real_last_name); - if (self->peer.status.ev) { tgl_remove_status_expire (TLS, &self->peer); } - tgls_free_photo (TLS, self->peer.photo); + if (self->peer.user.first_name) tfree_str(self->peer.user.first_name); + if (self->peer.user.last_name) tfree_str(self->peer.user.last_name); + if (self->peer.user.print_name) tfree_str(self->peer.user.print_name); + if (self->peer.user.phone) tfree_str(self->peer.user.phone); + if (self->peer.user.real_first_name) tfree_str(self->peer.user.real_first_name); + if (self->peer.user.real_last_name) tfree_str(self->peer.user.real_last_name); + if (self->peer.user.status.ev) { tgl_remove_status_expire (TLS, &self->peer.user); } + tgls_free_photo (TLS, self->peer.user.photo); break; case TGL_PEER_CHAT: - if (self->peer.title) tfree_str(self->peer.title); - if (self->peer.print_title) tfree_str(self->peer.print_title); - if (self->peer.user_list) tfree(self->peer.user_list, self->peer.user_list_size * sizeof(tgl_chat_user)); - tgls_free_photo (TLS, self->peer.photo); + if (self->peer.chat.title) tfree_str(self->peer.chat.title); + if (self->peer.chat.print_title) tfree_str(self->peer.chat.print_title); + if (self->peer.chat.user_list) + tfree(self->peer.chat.user_list, self->peer.chat.user_list_size * sizeof(struct tgl_chat_user)); + tgls_free_photo (TLS, self->peer.chat.photo); break; case TGL_PEER_ENCR_CHAT: - if (self->peer.print_name) tfree_str(self->peer.print_name); - if (self->peer.g_key) tfree (self->peer.g_key, 256); + if (self->peer.encr_chat.print_name) tfree_str(self->peer.encr_chat.print_name); + if (self->peer.encr_chat.g_key) tfree (self->peer.encr_chat.g_key, 256); break; default: + PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); } Py_TYPE(self)->tp_free((PyObject*)self); @@ -59,6 +64,8 @@ tgl_Peer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return (PyObject *)self; } + + static int tgl_Peer_init(tgl_Peer *self, PyObject *args, PyObject *kwds) { @@ -73,13 +80,25 @@ tgl_Peer_init(tgl_Peer *self, PyObject *args, PyObject *kwds) } static PyObject * -tgl_Peer_get_name (tgl_Peer *self, void *closure) +tgl_Peer_getname (tgl_Peer *self, void *closure) { PyObject *ret; - if(self->peer.id.type == TGL_PEER_CHAT) - ret = PyUnicode_FromString(self->peer.print_title); - else - ret = PyUnicode_FromString(self->peer.print_name); + + switch(self->peer.id.type) { + case TGL_PEER_USER: + ret = PyUnicode_FromString(self->peer.user.print_name); + break; + case TGL_PEER_CHAT: + ret = PyUnicode_FromString(self->peer.chat.print_title); + break; + case TGL_PEER_ENCR_CHAT: + ret = PyUnicode_FromString(self->peer.encr_chat.print_name); + break; + default: + PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + Py_RETURN_NONE; + } + Py_XINCREF(ret); return ret; @@ -91,13 +110,21 @@ tgl_Peer_getuser_id (tgl_Peer *self, void *closure) { PyObject *ret; - if(self->peer.id.type == TGL_PEER_CHAT) - { - PyErr_SetString(PyExc_TypeError, - "peer.type == TGL_PEER_CHAT has no user_id"); - Py_RETURN_NONE; - } else { - ret = PyLong_FromLong(self->peer.user_id); + switch(self->peer.id.type) { + case TGL_PEER_USER: + ret = PyLong_FromLong(self->peer.id.id); + break; + case TGL_PEER_CHAT: + PyErr_SetString(PyExc_TypeError, "peer.type == TGL_PEER_CHAT has no user_id"); + Py_RETURN_NONE; + + break; + case TGL_PEER_ENCR_CHAT: + ret = PyLong_FromLong(self->peer.encr_chat.user_id); + break; + default: + PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + Py_RETURN_NONE; } Py_XINCREF(ret); @@ -108,19 +135,27 @@ static PyObject * tgl_Peer_getuser_list (tgl_Peer *self, void *closure) { PyObject *ret, *peer; - tgl_chat_user *user_list; + int i; + struct tgl_chat_user *user_list; + struct tgl_user *user; - if(self->peer.id.type == TGL_PEER_CHAT) - { - ret = PyList_New(); - for(int i = 0; i < self->peer.user_list_size; i++) { - user_list = self->peer.userlist + i; - - } - } else { - PyErr_SetString(PyExc_TypeError, - "Only peer.type == TGL_PEER_CHAT has user_list"); - Py_RETURN_NONE; + switch(self->peer.id.type) { + case TGL_PEER_CHAT: + ret = PyList_New(0); + for(i = 0; i < self->peer.chat.user_list_size; i++) { + // TODO: Sort tgl_user objects, maybe offline mode is enoug? + user_list = self->peer.chat.user_list + i; + PyList_Append(ret, PyLong_FromLong(user_list->user_id)); + } + break; + case TGL_PEER_ENCR_CHAT: + case TGL_PEER_USER: + PyErr_SetString(PyExc_TypeError, "Only peer.type == TGL_PEER_CHAT has user_list"); + Py_RETURN_NONE; + break; + default: + PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + Py_RETURN_NONE; } Py_XINCREF(ret); @@ -128,69 +163,87 @@ tgl_Peer_getuser_list (tgl_Peer *self, void *closure) } static PyObject * -tgl_Peer_get (tgl_Peer *self, void *closure) +tgl_Peer_getuser_status(tgl_Peer *self, void *closure) { PyObject *ret; + switch(self->peer.id.type) { + case TGL_PEER_USER: + ret = PyDict_New(); + PyDict_SetItemString(ret, "online", self->peer.user.status.online? Py_True : Py_False); + PyDict_SetItemString(ret, "when", PyDateTime_FromTimestamp(Py_BuildValue("(O)", + PyLong_FromLong(self->peer.user.status.when)))); + + break; + case TGL_PEER_CHAT: + case TGL_PEER_ENCR_CHAT: + PyErr_SetString(PyExc_TypeError, "Only peer.type == TGL_PEER_USER has user_status"); + Py_RETURN_NONE; + break; + default: + PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + Py_RETURN_NONE; + } + Py_XINCREF(ret); return ret; } static PyObject * -tgl_Peer_get (tgl_Peer *self, void *closure) +tgl_Peer_getphone (tgl_Peer *self, void *closure) { PyObject *ret; + switch(self->peer.id.type) { + case TGL_PEER_USER: + ret = PyUnicode_FromString(self->peer.user.phone); + break; + case TGL_PEER_CHAT: + case TGL_PEER_ENCR_CHAT: + PyErr_SetString(PyExc_TypeError, "Only peer.type == TGL_PEER_USER has phone"); + Py_RETURN_NONE; + break; + default: + PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + Py_RETURN_NONE; + } + Py_XINCREF(ret); return ret; } static PyObject * -tgl_Peer_get (tgl_Peer *self, void *closure) +tgl_Peer_getusername (tgl_Peer *self, void *closure) { PyObject *ret; + switch(self->peer.id.type) { + case TGL_PEER_USER: + ret = PyUnicode_FromString(self->peer.user.username); + break; + case TGL_PEER_CHAT: + case TGL_PEER_ENCR_CHAT: + PyErr_SetString(PyExc_TypeError, "Only peer.type == TGL_PEER_USER has username"); + Py_RETURN_NONE; + break; + default: + PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + Py_RETURN_NONE; + } + Py_XINCREF(ret); return ret; } -static PyObject * -tgl_Peer_get (tgl_Peer *self, void *closure) -{ - PyObject *ret; - - Py_XINCREF(ret); - return ret; -} - -static PyObject * -tgl_Peer_get (tgl_Peer *self, void *closure) -{ - PyObject *ret; - - Py_XINCREF(ret); - return ret; -} - -static PyObject * -tgl_Peer_get (tgl_Peer *self, void *closure) -{ - PyObject *ret; - - Py_XINCREF(ret); - return ret; -} - -static PyObject * -tgl_Peer_get (tgl_Peer *self, void *closure) -{ - PyObject *ret; - - Py_XINCREF(ret); - return ret; -} - - +static PyGetSetDef tgl_Peer_getseters[] = { + {"name", (getter)tgl_Peer_getname, NULL, "", NULL}, + {"user_id", (getter)tgl_Peer_getuser_id, NULL, "", NULL}, + {"user_list", (getter)tgl_Peer_getuser_list, NULL, "", NULL}, + {"user_status", (getter)tgl_Peer_getuser_status, NULL, "", NULL}, + {"phone", (getter)tgl_Peer_getphone, NULL, "", NULL}, + {"username", (getter)tgl_Peer_getusername, NULL, "", NULL}, + {NULL} /* Sentinel */ +}; static PyMemberDef tgl_Peer_members[] = { {"type", T_INT, offsetof(tgl_Peer, peer.id.type), 0, "Peer Type"}, @@ -202,6 +255,7 @@ static PyObject * tgl_Peer_type_name(tgl_Peer* self) { PyObject *name; + switch(self->peer.id.type) { case TGL_PEER_USER: name = PyUnicode_FromString("user"); @@ -210,12 +264,11 @@ tgl_Peer_type_name(tgl_Peer* self) name = PyUnicode_FromString("chat"); break; case TGL_PEER_ENCR_CHAT: - name = PyUnicode_FromString("secret_chat"); + name = PyUnicode_FromString("encr_chat"); break; default: name = PyUnicode_FromString("unknown"); } - return name; } @@ -257,7 +310,7 @@ static PyTypeObject tgl_PeerType = { 0, /* tp_iternext */ tgl_Peer_methods, /* tp_methods */ tgl_Peer_members, /* tp_members */ - 0, /* tp_getset */ + tgl_Peer_getseters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ @@ -268,4 +321,62 @@ static PyTypeObject tgl_PeerType = { tgl_Peer_new, /* tp_new */ }; + +static PyObject * +tgl_Peer_FromTglPeer(tgl_peer_t *peer) { + tgl_Peer *self = (tgl_Peer *) tgl_Peer_new((PyTypeObject *)&tgl_PeerType, Py_None, Py_None); + + memcpy(&self->peer, peer, sizeof(tgl_peer_t)); + + switch(self->peer.id.type) { + case TGL_PEER_USER: + // print_name + if(peer->user.print_name) { + self->peer.user.print_name = (char*)malloc(strlen(peer->user.print_name)); + memcpy(self->peer.user.print_name, peer->user.print_name, strlen(peer->user.print_name)); + } + // phone + if(peer->user.phone) { + self->peer.user.phone = (char*)malloc(strlen(peer->user.phone)); + memcpy(self->peer.user.phone, peer->user.phone, strlen(peer->user.phone)); + } + // username + if(peer->user.username) { + self->peer.user.username = (char*)malloc(strlen(peer->user.username)); + memcpy(self->peer.user.username, peer->user.username, strlen(peer->user.username)); + } + break; + case TGL_PEER_CHAT: + // print_title + if(peer->chat.print_title) { + self->peer.chat.print_title = (char*)malloc(strlen(peer->chat.print_title)); + memcpy(self->peer.chat.print_title, peer->chat.print_title, strlen(peer->chat.print_title)); + } + // user_list + if(peer->chat.user_list_size > 0) { + self->peer.chat.user_list = (struct tgl_chat_user*)malloc(self->peer.chat.user_list_size * + sizeof(struct tgl_chat_user)); + memcpy(self->peer.chat.user_list, peer->chat.user_list, + peer->chat.user_list_size * sizeof(struct tgl_chat_user)); + } + break; + case TGL_PEER_ENCR_CHAT: + // print_name + if(peer->encr_chat.print_name) { + self->peer.encr_chat.print_name = (char*)malloc(strlen(peer->encr_chat.print_name)); + memcpy(self->peer.encr_chat.print_name, peer->encr_chat.print_name, strlen(peer->encr_chat.print_name)); + } + // g_key + if(peer->encr_chat.g_key) { + self->peer.encr_chat.g_key = (unsigned char*)malloc(256); + memcpy(self->peer.encr_chat.g_key, peer->encr_chat.g_key, 256); + } + break; + default: + assert(0); + } + + return (PyObject *) self; +} + #endif diff --git a/tg-test.py b/tg-test.py index d0620cc..3b495a1 100644 --- a/tg-test.py +++ b/tg-test.py @@ -31,6 +31,13 @@ def history_cb(msg_list, ptype, pid, success, msgs): if len(msgs) == HISTORY_QUERY_SIZE: tgl.get_history(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; + + print(msg["to"].user_id) + +""" def on_msg_receive(msg): if msg["out"] and not binlog_done: return; @@ -53,7 +60,7 @@ def on_msg_receive(msg): 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" From 25ed20429c36d6a706aae31b79ecb59cd3084be4 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Tue, 19 May 2015 10:55:32 -0700 Subject: [PATCH 73/97] Split Python Types into their own c module like they should be. --- python-tg.c | 2 + python-types.c | 374 +++++++++++++++++++++++++++++++++++++++++++++++++ python-types.h | 370 +----------------------------------------------- 3 files changed, 377 insertions(+), 369 deletions(-) create mode 100644 python-types.c diff --git a/python-tg.c b/python-tg.c index b216390..8cfa821 100644 --- a/python-tg.c +++ b/python-tg.c @@ -77,6 +77,8 @@ #include "python-types.h" +extern PyTypeObject tgl_PeerType; + //#include "interface.h" //#include "auto/constants.h" diff --git a/python-types.c b/python-types.c new file mode 100644 index 0000000..d2ea8a7 --- /dev/null +++ b/python-types.c @@ -0,0 +1,374 @@ + +#include +#include +#include +#include +#include +#include +#include "structmember.h" + +// Python Imports +#include "datetime.h" + +#include "python-types.h" + +extern struct tgl_state *TLS; + +// modeled after tgls_free_peer +static void +tgl_Peer_dealloc(tgl_Peer* self) +{ + switch(self->peer.id.type) { + case TGL_PEER_USER: + if (self->peer.user.first_name) tfree_str(self->peer.user.first_name); + if (self->peer.user.last_name) tfree_str(self->peer.user.last_name); + if (self->peer.user.print_name) tfree_str(self->peer.user.print_name); + if (self->peer.user.phone) tfree_str(self->peer.user.phone); + if (self->peer.user.real_first_name) tfree_str(self->peer.user.real_first_name); + if (self->peer.user.real_last_name) tfree_str(self->peer.user.real_last_name); + if (self->peer.user.status.ev) { tgl_remove_status_expire (TLS, &self->peer.user); } + tgls_free_photo (TLS, self->peer.user.photo); + break; + case TGL_PEER_CHAT: + if (self->peer.chat.title) tfree_str(self->peer.chat.title); + if (self->peer.chat.print_title) tfree_str(self->peer.chat.print_title); + if (self->peer.chat.user_list) + tfree(self->peer.chat.user_list, self->peer.chat.user_list_size * sizeof(struct tgl_chat_user)); + tgls_free_photo (TLS, self->peer.chat.photo); + break; + case TGL_PEER_ENCR_CHAT: + if (self->peer.encr_chat.print_name) tfree_str(self->peer.encr_chat.print_name); + if (self->peer.encr_chat.g_key) tfree (self->peer.encr_chat.g_key, 256); + break; + default: + PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + } + + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static PyObject * +tgl_Peer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + tgl_Peer *self; + + self = (tgl_Peer *)type->tp_alloc(type, 0); + if (self != NULL) { + self->peer.id.type = 0; + self->peer.id.id = 0; + } + + return (PyObject *)self; +} + +static int +tgl_Peer_init(tgl_Peer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"type", "id", NULL}; + + if(!PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwlist, + &self->peer.id.type, + &self->peer.id.id)) + return -1; + + return 0; +} + +static PyObject * +tgl_Peer_getname (tgl_Peer *self, void *closure) +{ + PyObject *ret; + + switch(self->peer.id.type) { + case TGL_PEER_USER: + ret = PyUnicode_FromString(self->peer.user.print_name); + break; + case TGL_PEER_CHAT: + ret = PyUnicode_FromString(self->peer.chat.print_title); + break; + case TGL_PEER_ENCR_CHAT: + ret = PyUnicode_FromString(self->peer.encr_chat.print_name); + break; + default: + PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + + +static PyObject * +tgl_Peer_getuser_id (tgl_Peer *self, void *closure) +{ + PyObject *ret; + + switch(self->peer.id.type) { + case TGL_PEER_USER: + ret = PyLong_FromLong(self->peer.id.id); + break; + case TGL_PEER_CHAT: + PyErr_SetString(PyExc_TypeError, "peer.type == TGL_PEER_CHAT has no user_id"); + Py_RETURN_NONE; + + break; + case TGL_PEER_ENCR_CHAT: + ret = PyLong_FromLong(self->peer.encr_chat.user_id); + break; + default: + PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Peer_getuser_list (tgl_Peer *self, void *closure) +{ + PyObject *ret, *peer; + int i; + struct tgl_chat_user *user_list; + struct tgl_user *user; + + switch(self->peer.id.type) { + case TGL_PEER_CHAT: + ret = PyList_New(0); + for(i = 0; i < self->peer.chat.user_list_size; i++) { + // TODO: Sort tgl_user objects, maybe offline mode is enoug? + user_list = self->peer.chat.user_list + i; + PyList_Append(ret, PyLong_FromLong(user_list->user_id)); + } + break; + case TGL_PEER_ENCR_CHAT: + case TGL_PEER_USER: + PyErr_SetString(PyExc_TypeError, "Only peer.type == TGL_PEER_CHAT has user_list"); + Py_RETURN_NONE; + break; + default: + PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Peer_getuser_status(tgl_Peer *self, void *closure) +{ + PyObject *ret; + + switch(self->peer.id.type) { + case TGL_PEER_USER: + ret = PyDict_New(); + PyDict_SetItemString(ret, "online", self->peer.user.status.online? Py_True : Py_False); + PyDict_SetItemString(ret, "when", PyDateTime_FromTimestamp(Py_BuildValue("(O)", + PyLong_FromLong(self->peer.user.status.when)))); + + break; + case TGL_PEER_CHAT: + case TGL_PEER_ENCR_CHAT: + PyErr_SetString(PyExc_TypeError, "Only peer.type == TGL_PEER_USER has user_status"); + Py_RETURN_NONE; + break; + default: + PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Peer_getphone (tgl_Peer *self, void *closure) +{ + PyObject *ret; + + switch(self->peer.id.type) { + case TGL_PEER_USER: + ret = PyUnicode_FromString(self->peer.user.phone); + break; + case TGL_PEER_CHAT: + case TGL_PEER_ENCR_CHAT: + PyErr_SetString(PyExc_TypeError, "Only peer.type == TGL_PEER_USER has phone"); + Py_RETURN_NONE; + break; + default: + PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Peer_getusername (tgl_Peer *self, void *closure) +{ + PyObject *ret; + + switch(self->peer.id.type) { + case TGL_PEER_USER: + ret = PyUnicode_FromString(self->peer.user.username); + break; + case TGL_PEER_CHAT: + case TGL_PEER_ENCR_CHAT: + PyErr_SetString(PyExc_TypeError, "Only peer.type == TGL_PEER_USER has username"); + Py_RETURN_NONE; + break; + default: + PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyGetSetDef tgl_Peer_getseters[] = { + {"name", (getter)tgl_Peer_getname, NULL, "", NULL}, + {"user_id", (getter)tgl_Peer_getuser_id, NULL, "", NULL}, + {"user_list", (getter)tgl_Peer_getuser_list, NULL, "", NULL}, + {"user_status", (getter)tgl_Peer_getuser_status, NULL, "", NULL}, + {"phone", (getter)tgl_Peer_getphone, NULL, "", NULL}, + {"username", (getter)tgl_Peer_getusername, NULL, "", NULL}, + {NULL} /* Sentinel */ +}; + +static PyMemberDef tgl_Peer_members[] = { + {"type", T_INT, offsetof(tgl_Peer, peer.id.type), 0, "Peer Type"}, + {"id", T_INT, offsetof(tgl_Peer, peer.id.id), 0, "Peer ID" }, + {NULL} /* Sentinel */ +}; + +static PyObject * +tgl_Peer_type_name(tgl_Peer* self) +{ + PyObject *name; + + switch(self->peer.id.type) { + case TGL_PEER_USER: + name = PyUnicode_FromString("user"); + break; + case TGL_PEER_CHAT: + name = PyUnicode_FromString("chat"); + break; + case TGL_PEER_ENCR_CHAT: + name = PyUnicode_FromString("encr_chat"); + break; + default: + name = PyUnicode_FromString("unknown"); + } + return name; +} + +static PyMethodDef tgl_Peer_methods[] = { + {"type_name", (PyCFunction)tgl_Peer_type_name, METH_NOARGS, + "Return the string representation of the peer type." + }, + {NULL} /* Sentinel */ +}; + + +PyTypeObject tgl_PeerType = { + PyVarObject_HEAD_INIT(NULL, 0) + "tgl.Peer", /* tp_name */ + sizeof(tgl_Peer), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)tgl_Peer_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + "tgl Peer", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + tgl_Peer_methods, /* tp_methods */ + tgl_Peer_members, /* tp_members */ + tgl_Peer_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)tgl_Peer_init, /* tp_init */ + 0, /* tp_alloc */ + tgl_Peer_new, /* tp_new */ +}; + + +PyObject * +tgl_Peer_FromTglPeer(tgl_peer_t *peer) { + tgl_Peer *self = (tgl_Peer *) tgl_Peer_new((PyTypeObject *)&tgl_PeerType, Py_None, Py_None); + + memcpy(&self->peer, peer, sizeof(tgl_peer_t)); + + switch(self->peer.id.type) { + case TGL_PEER_USER: + // print_name + if(peer->user.print_name) { + self->peer.user.print_name = (char*)malloc(strlen(peer->user.print_name)); + memcpy(self->peer.user.print_name, peer->user.print_name, strlen(peer->user.print_name)); + } + // phone + if(peer->user.phone) { + self->peer.user.phone = (char*)malloc(strlen(peer->user.phone)); + memcpy(self->peer.user.phone, peer->user.phone, strlen(peer->user.phone)); + } + // username + if(peer->user.username) { + self->peer.user.username = (char*)malloc(strlen(peer->user.username)); + memcpy(self->peer.user.username, peer->user.username, strlen(peer->user.username)); + } + break; + case TGL_PEER_CHAT: + // print_title + if(peer->chat.print_title) { + self->peer.chat.print_title = (char*)malloc(strlen(peer->chat.print_title)); + memcpy(self->peer.chat.print_title, peer->chat.print_title, strlen(peer->chat.print_title)); + } + // user_list + if(peer->chat.user_list_size > 0) { + self->peer.chat.user_list = (struct tgl_chat_user*)malloc(self->peer.chat.user_list_size * + sizeof(struct tgl_chat_user)); + memcpy(self->peer.chat.user_list, peer->chat.user_list, + peer->chat.user_list_size * sizeof(struct tgl_chat_user)); + } + break; + case TGL_PEER_ENCR_CHAT: + // print_name + if(peer->encr_chat.print_name) { + self->peer.encr_chat.print_name = (char*)malloc(strlen(peer->encr_chat.print_name)); + memcpy(self->peer.encr_chat.print_name, peer->encr_chat.print_name, strlen(peer->encr_chat.print_name)); + } + // g_key + if(peer->encr_chat.g_key) { + self->peer.encr_chat.g_key = (unsigned char*)malloc(256); + memcpy(self->peer.encr_chat.g_key, peer->encr_chat.g_key, 256); + } + break; + default: + assert(0); + } + + return (PyObject *) self; +} diff --git a/python-types.h b/python-types.h index 8092416..211f1be 100644 --- a/python-types.h +++ b/python-types.h @@ -3,380 +3,12 @@ #include #include -#include -#include -#include -#include -#include -#include "structmember.h" typedef struct { PyObject_HEAD tgl_peer_t peer; } tgl_Peer; -extern struct tgl_state *TLS; - -// modeled after tgls_free_peer -static void -tgl_Peer_dealloc(tgl_Peer* self) -{ - switch(self->peer.id.type) { - case TGL_PEER_USER: - if (self->peer.user.first_name) tfree_str(self->peer.user.first_name); - if (self->peer.user.last_name) tfree_str(self->peer.user.last_name); - if (self->peer.user.print_name) tfree_str(self->peer.user.print_name); - if (self->peer.user.phone) tfree_str(self->peer.user.phone); - if (self->peer.user.real_first_name) tfree_str(self->peer.user.real_first_name); - if (self->peer.user.real_last_name) tfree_str(self->peer.user.real_last_name); - if (self->peer.user.status.ev) { tgl_remove_status_expire (TLS, &self->peer.user); } - tgls_free_photo (TLS, self->peer.user.photo); - break; - case TGL_PEER_CHAT: - if (self->peer.chat.title) tfree_str(self->peer.chat.title); - if (self->peer.chat.print_title) tfree_str(self->peer.chat.print_title); - if (self->peer.chat.user_list) - tfree(self->peer.chat.user_list, self->peer.chat.user_list_size * sizeof(struct tgl_chat_user)); - tgls_free_photo (TLS, self->peer.chat.photo); - break; - case TGL_PEER_ENCR_CHAT: - if (self->peer.encr_chat.print_name) tfree_str(self->peer.encr_chat.print_name); - if (self->peer.encr_chat.g_key) tfree (self->peer.encr_chat.g_key, 256); - break; - default: - PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); - } - - Py_TYPE(self)->tp_free((PyObject*)self); -} - -static PyObject * -tgl_Peer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - tgl_Peer *self; - - self = (tgl_Peer *)type->tp_alloc(type, 0); - if (self != NULL) { - self->peer.id.type = 0; - self->peer.id.id = 0; - } - - return (PyObject *)self; -} - - - -static int -tgl_Peer_init(tgl_Peer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"type", "id", NULL}; - - if(!PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwlist, - &self->peer.id.type, - &self->peer.id.id)) - return -1; - - return 0; -} - -static PyObject * -tgl_Peer_getname (tgl_Peer *self, void *closure) -{ - PyObject *ret; - - switch(self->peer.id.type) { - case TGL_PEER_USER: - ret = PyUnicode_FromString(self->peer.user.print_name); - break; - case TGL_PEER_CHAT: - ret = PyUnicode_FromString(self->peer.chat.print_title); - break; - case TGL_PEER_ENCR_CHAT: - ret = PyUnicode_FromString(self->peer.encr_chat.print_name); - break; - default: - PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); - Py_RETURN_NONE; - } - - - Py_XINCREF(ret); - return ret; -} - - -static PyObject * -tgl_Peer_getuser_id (tgl_Peer *self, void *closure) -{ - PyObject *ret; - - switch(self->peer.id.type) { - case TGL_PEER_USER: - ret = PyLong_FromLong(self->peer.id.id); - break; - case TGL_PEER_CHAT: - PyErr_SetString(PyExc_TypeError, "peer.type == TGL_PEER_CHAT has no user_id"); - Py_RETURN_NONE; - - break; - case TGL_PEER_ENCR_CHAT: - ret = PyLong_FromLong(self->peer.encr_chat.user_id); - break; - default: - PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); - Py_RETURN_NONE; - } - - Py_XINCREF(ret); - return ret; -} - -static PyObject * -tgl_Peer_getuser_list (tgl_Peer *self, void *closure) -{ - PyObject *ret, *peer; - int i; - struct tgl_chat_user *user_list; - struct tgl_user *user; - - switch(self->peer.id.type) { - case TGL_PEER_CHAT: - ret = PyList_New(0); - for(i = 0; i < self->peer.chat.user_list_size; i++) { - // TODO: Sort tgl_user objects, maybe offline mode is enoug? - user_list = self->peer.chat.user_list + i; - PyList_Append(ret, PyLong_FromLong(user_list->user_id)); - } - break; - case TGL_PEER_ENCR_CHAT: - case TGL_PEER_USER: - PyErr_SetString(PyExc_TypeError, "Only peer.type == TGL_PEER_CHAT has user_list"); - Py_RETURN_NONE; - break; - default: - PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); - Py_RETURN_NONE; - } - - Py_XINCREF(ret); - return ret; -} - -static PyObject * -tgl_Peer_getuser_status(tgl_Peer *self, void *closure) -{ - PyObject *ret; - - switch(self->peer.id.type) { - case TGL_PEER_USER: - ret = PyDict_New(); - PyDict_SetItemString(ret, "online", self->peer.user.status.online? Py_True : Py_False); - PyDict_SetItemString(ret, "when", PyDateTime_FromTimestamp(Py_BuildValue("(O)", - PyLong_FromLong(self->peer.user.status.when)))); - - break; - case TGL_PEER_CHAT: - case TGL_PEER_ENCR_CHAT: - PyErr_SetString(PyExc_TypeError, "Only peer.type == TGL_PEER_USER has user_status"); - Py_RETURN_NONE; - break; - default: - PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); - Py_RETURN_NONE; - } - - Py_XINCREF(ret); - return ret; -} - -static PyObject * -tgl_Peer_getphone (tgl_Peer *self, void *closure) -{ - PyObject *ret; - - switch(self->peer.id.type) { - case TGL_PEER_USER: - ret = PyUnicode_FromString(self->peer.user.phone); - break; - case TGL_PEER_CHAT: - case TGL_PEER_ENCR_CHAT: - PyErr_SetString(PyExc_TypeError, "Only peer.type == TGL_PEER_USER has phone"); - Py_RETURN_NONE; - break; - default: - PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); - Py_RETURN_NONE; - } - - Py_XINCREF(ret); - return ret; -} - -static PyObject * -tgl_Peer_getusername (tgl_Peer *self, void *closure) -{ - PyObject *ret; - - switch(self->peer.id.type) { - case TGL_PEER_USER: - ret = PyUnicode_FromString(self->peer.user.username); - break; - case TGL_PEER_CHAT: - case TGL_PEER_ENCR_CHAT: - PyErr_SetString(PyExc_TypeError, "Only peer.type == TGL_PEER_USER has username"); - Py_RETURN_NONE; - break; - default: - PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); - Py_RETURN_NONE; - } - - Py_XINCREF(ret); - return ret; -} - -static PyGetSetDef tgl_Peer_getseters[] = { - {"name", (getter)tgl_Peer_getname, NULL, "", NULL}, - {"user_id", (getter)tgl_Peer_getuser_id, NULL, "", NULL}, - {"user_list", (getter)tgl_Peer_getuser_list, NULL, "", NULL}, - {"user_status", (getter)tgl_Peer_getuser_status, NULL, "", NULL}, - {"phone", (getter)tgl_Peer_getphone, NULL, "", NULL}, - {"username", (getter)tgl_Peer_getusername, NULL, "", NULL}, - {NULL} /* Sentinel */ -}; - -static PyMemberDef tgl_Peer_members[] = { - {"type", T_INT, offsetof(tgl_Peer, peer.id.type), 0, "Peer Type"}, - {"id", T_INT, offsetof(tgl_Peer, peer.id.id), 0, "Peer ID" }, - {NULL} /* Sentinel */ -}; - -static PyObject * -tgl_Peer_type_name(tgl_Peer* self) -{ - PyObject *name; - - switch(self->peer.id.type) { - case TGL_PEER_USER: - name = PyUnicode_FromString("user"); - break; - case TGL_PEER_CHAT: - name = PyUnicode_FromString("chat"); - break; - case TGL_PEER_ENCR_CHAT: - name = PyUnicode_FromString("encr_chat"); - break; - default: - name = PyUnicode_FromString("unknown"); - } - return name; -} - -static PyMethodDef tgl_Peer_methods[] = { - {"type_name", (PyCFunction)tgl_Peer_type_name, METH_NOARGS, - "Return the string representation of the peer type." - }, - {NULL} /* Sentinel */ -}; - - -static PyTypeObject tgl_PeerType = { - PyVarObject_HEAD_INIT(NULL, 0) - "tgl.Peer", /* tp_name */ - sizeof(tgl_Peer), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)tgl_Peer_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - "tgl Peer", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - tgl_Peer_methods, /* tp_methods */ - tgl_Peer_members, /* tp_members */ - tgl_Peer_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)tgl_Peer_init, /* tp_init */ - 0, /* tp_alloc */ - tgl_Peer_new, /* tp_new */ -}; - - -static PyObject * -tgl_Peer_FromTglPeer(tgl_peer_t *peer) { - tgl_Peer *self = (tgl_Peer *) tgl_Peer_new((PyTypeObject *)&tgl_PeerType, Py_None, Py_None); - - memcpy(&self->peer, peer, sizeof(tgl_peer_t)); - - switch(self->peer.id.type) { - case TGL_PEER_USER: - // print_name - if(peer->user.print_name) { - self->peer.user.print_name = (char*)malloc(strlen(peer->user.print_name)); - memcpy(self->peer.user.print_name, peer->user.print_name, strlen(peer->user.print_name)); - } - // phone - if(peer->user.phone) { - self->peer.user.phone = (char*)malloc(strlen(peer->user.phone)); - memcpy(self->peer.user.phone, peer->user.phone, strlen(peer->user.phone)); - } - // username - if(peer->user.username) { - self->peer.user.username = (char*)malloc(strlen(peer->user.username)); - memcpy(self->peer.user.username, peer->user.username, strlen(peer->user.username)); - } - break; - case TGL_PEER_CHAT: - // print_title - if(peer->chat.print_title) { - self->peer.chat.print_title = (char*)malloc(strlen(peer->chat.print_title)); - memcpy(self->peer.chat.print_title, peer->chat.print_title, strlen(peer->chat.print_title)); - } - // user_list - if(peer->chat.user_list_size > 0) { - self->peer.chat.user_list = (struct tgl_chat_user*)malloc(self->peer.chat.user_list_size * - sizeof(struct tgl_chat_user)); - memcpy(self->peer.chat.user_list, peer->chat.user_list, - peer->chat.user_list_size * sizeof(struct tgl_chat_user)); - } - break; - case TGL_PEER_ENCR_CHAT: - // print_name - if(peer->encr_chat.print_name) { - self->peer.encr_chat.print_name = (char*)malloc(strlen(peer->encr_chat.print_name)); - memcpy(self->peer.encr_chat.print_name, peer->encr_chat.print_name, strlen(peer->encr_chat.print_name)); - } - // g_key - if(peer->encr_chat.g_key) { - self->peer.encr_chat.g_key = (unsigned char*)malloc(256); - memcpy(self->peer.encr_chat.g_key, peer->encr_chat.g_key, 256); - } - break; - default: - assert(0); - } - - return (PyObject *) self; -} +PyObject * tgl_Peer_FromTglPeer(tgl_peer_t *peer); #endif From 7c9129b0b49507bf4dd5d73bc8aeb5591f005059 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Tue, 19 May 2015 17:06:27 -0700 Subject: [PATCH 74/97] Add tgl_Msg class --- python-tg.h | 6 + python-types.c | 522 +++++++++++++++++++++++++++++++++++++++---------- python-types.h | 9 +- tg-test.py | 2 +- 4 files changed, 432 insertions(+), 107 deletions(-) diff --git a/python-tg.h b/python-tg.h index 2fb84ab..4145c7a 100644 --- a/python-tg.h +++ b/python-tg.h @@ -21,6 +21,7 @@ #define __PYTHON_TG_H__ #include +#include #include void py_init (const char *file); @@ -32,4 +33,9 @@ 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); + + +void py_add_string_field (PyObject* dict, char *name, const char *value); +void py_add_string_field_arr (PyObject* list, int num, const char *value); +void py_add_num_field (PyObject* dict, const char *name, double value); #endif diff --git a/python-types.c b/python-types.c index d2ea8a7..4488a9f 100644 --- a/python-types.c +++ b/python-types.c @@ -11,39 +11,16 @@ #include "datetime.h" #include "python-types.h" +#include "python-tg.h" extern struct tgl_state *TLS; -// modeled after tgls_free_peer +// +// tgl_peer_t wrapper +// static void tgl_Peer_dealloc(tgl_Peer* self) { - switch(self->peer.id.type) { - case TGL_PEER_USER: - if (self->peer.user.first_name) tfree_str(self->peer.user.first_name); - if (self->peer.user.last_name) tfree_str(self->peer.user.last_name); - if (self->peer.user.print_name) tfree_str(self->peer.user.print_name); - if (self->peer.user.phone) tfree_str(self->peer.user.phone); - if (self->peer.user.real_first_name) tfree_str(self->peer.user.real_first_name); - if (self->peer.user.real_last_name) tfree_str(self->peer.user.real_last_name); - if (self->peer.user.status.ev) { tgl_remove_status_expire (TLS, &self->peer.user); } - tgls_free_photo (TLS, self->peer.user.photo); - break; - case TGL_PEER_CHAT: - if (self->peer.chat.title) tfree_str(self->peer.chat.title); - if (self->peer.chat.print_title) tfree_str(self->peer.chat.print_title); - if (self->peer.chat.user_list) - tfree(self->peer.chat.user_list, self->peer.chat.user_list_size * sizeof(struct tgl_chat_user)); - tgls_free_photo (TLS, self->peer.chat.photo); - break; - case TGL_PEER_ENCR_CHAT: - if (self->peer.encr_chat.print_name) tfree_str(self->peer.encr_chat.print_name); - if (self->peer.encr_chat.g_key) tfree (self->peer.encr_chat.g_key, 256); - break; - default: - PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); - } - Py_TYPE(self)->tp_free((PyObject*)self); } @@ -53,11 +30,6 @@ tgl_Peer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) tgl_Peer *self; self = (tgl_Peer *)type->tp_alloc(type, 0); - if (self != NULL) { - self->peer.id.type = 0; - self->peer.id.id = 0; - } - return (PyObject *)self; } @@ -65,10 +37,14 @@ static int tgl_Peer_init(tgl_Peer *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"type", "id", NULL}; - + tgl_peer_id_t peer_id; if(!PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwlist, - &self->peer.id.type, - &self->peer.id.id)) + &peer_id.type, + &peer_id.id)) + return -1; + + self->peer = tgl_peer_get(TLS, peer_id); + if(self->peer == NULL) return -1; return 0; @@ -79,15 +55,15 @@ tgl_Peer_getname (tgl_Peer *self, void *closure) { PyObject *ret; - switch(self->peer.id.type) { + switch(self->peer->id.type) { case TGL_PEER_USER: - ret = PyUnicode_FromString(self->peer.user.print_name); + ret = PyUnicode_FromString(self->peer->user.print_name); break; case TGL_PEER_CHAT: - ret = PyUnicode_FromString(self->peer.chat.print_title); + ret = PyUnicode_FromString(self->peer->chat.print_title); break; case TGL_PEER_ENCR_CHAT: - ret = PyUnicode_FromString(self->peer.encr_chat.print_name); + ret = PyUnicode_FromString(self->peer->encr_chat.print_name); break; default: PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); @@ -104,9 +80,9 @@ tgl_Peer_getuser_id (tgl_Peer *self, void *closure) { PyObject *ret; - switch(self->peer.id.type) { + switch(self->peer->id.type) { case TGL_PEER_USER: - ret = PyLong_FromLong(self->peer.id.id); + ret = PyLong_FromLong(self->peer->id.id); break; case TGL_PEER_CHAT: PyErr_SetString(PyExc_TypeError, "peer.type == TGL_PEER_CHAT has no user_id"); @@ -114,7 +90,7 @@ tgl_Peer_getuser_id (tgl_Peer *self, void *closure) break; case TGL_PEER_ENCR_CHAT: - ret = PyLong_FromLong(self->peer.encr_chat.user_id); + ret = PyLong_FromLong(self->peer->encr_chat.user_id); break; default: PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); @@ -133,12 +109,12 @@ tgl_Peer_getuser_list (tgl_Peer *self, void *closure) struct tgl_chat_user *user_list; struct tgl_user *user; - switch(self->peer.id.type) { + switch(self->peer->id.type) { case TGL_PEER_CHAT: ret = PyList_New(0); - for(i = 0; i < self->peer.chat.user_list_size; i++) { + for(i = 0; i < self->peer->chat.user_list_size; i++) { // TODO: Sort tgl_user objects, maybe offline mode is enoug? - user_list = self->peer.chat.user_list + i; + user_list = self->peer->chat.user_list + i; PyList_Append(ret, PyLong_FromLong(user_list->user_id)); } break; @@ -161,12 +137,12 @@ tgl_Peer_getuser_status(tgl_Peer *self, void *closure) { PyObject *ret; - switch(self->peer.id.type) { + switch(self->peer->id.type) { case TGL_PEER_USER: ret = PyDict_New(); - PyDict_SetItemString(ret, "online", self->peer.user.status.online? Py_True : Py_False); + PyDict_SetItemString(ret, "online", self->peer->user.status.online? Py_True : Py_False); PyDict_SetItemString(ret, "when", PyDateTime_FromTimestamp(Py_BuildValue("(O)", - PyLong_FromLong(self->peer.user.status.when)))); + PyLong_FromLong(self->peer->user.status.when)))); break; case TGL_PEER_CHAT: @@ -188,9 +164,9 @@ tgl_Peer_getphone (tgl_Peer *self, void *closure) { PyObject *ret; - switch(self->peer.id.type) { + switch(self->peer->id.type) { case TGL_PEER_USER: - ret = PyUnicode_FromString(self->peer.user.phone); + ret = PyUnicode_FromString(self->peer->user.phone); break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: @@ -211,9 +187,9 @@ tgl_Peer_getusername (tgl_Peer *self, void *closure) { PyObject *ret; - switch(self->peer.id.type) { + switch(self->peer->id.type) { case TGL_PEER_USER: - ret = PyUnicode_FromString(self->peer.user.username); + ret = PyUnicode_FromString(self->peer->user.username); break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: @@ -229,7 +205,33 @@ tgl_Peer_getusername (tgl_Peer *self, void *closure) return ret; } + + +static PyObject * +tgl_Peer_getid (tgl_Peer *self, void *closure) +{ + PyObject *ret; + + ret = PyLong_FromLong(self->peer->id.id); + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Peer_gettype (tgl_Peer *self, void *closure) +{ + PyObject *ret; + + ret = PyLong_FromLong(self->peer->id.type); + + Py_XINCREF(ret); + return ret; +} + static PyGetSetDef tgl_Peer_getseters[] = { + {"id", (getter)tgl_Peer_getid, NULL, "", NULL}, + {"type", (getter)tgl_Peer_gettype, NULL, "", NULL}, {"name", (getter)tgl_Peer_getname, NULL, "", NULL}, {"user_id", (getter)tgl_Peer_getuser_id, NULL, "", NULL}, {"user_list", (getter)tgl_Peer_getuser_list, NULL, "", NULL}, @@ -240,8 +242,6 @@ static PyGetSetDef tgl_Peer_getseters[] = { }; static PyMemberDef tgl_Peer_members[] = { - {"type", T_INT, offsetof(tgl_Peer, peer.id.type), 0, "Peer Type"}, - {"id", T_INT, offsetof(tgl_Peer, peer.id.id), 0, "Peer ID" }, {NULL} /* Sentinel */ }; @@ -250,7 +250,7 @@ tgl_Peer_type_name(tgl_Peer* self) { PyObject *name; - switch(self->peer.id.type) { + switch(self->peer->id.type) { case TGL_PEER_USER: name = PyUnicode_FromString("user"); break; @@ -320,55 +320,367 @@ PyObject * tgl_Peer_FromTglPeer(tgl_peer_t *peer) { tgl_Peer *self = (tgl_Peer *) tgl_Peer_new((PyTypeObject *)&tgl_PeerType, Py_None, Py_None); - memcpy(&self->peer, peer, sizeof(tgl_peer_t)); - - switch(self->peer.id.type) { - case TGL_PEER_USER: - // print_name - if(peer->user.print_name) { - self->peer.user.print_name = (char*)malloc(strlen(peer->user.print_name)); - memcpy(self->peer.user.print_name, peer->user.print_name, strlen(peer->user.print_name)); - } - // phone - if(peer->user.phone) { - self->peer.user.phone = (char*)malloc(strlen(peer->user.phone)); - memcpy(self->peer.user.phone, peer->user.phone, strlen(peer->user.phone)); - } - // username - if(peer->user.username) { - self->peer.user.username = (char*)malloc(strlen(peer->user.username)); - memcpy(self->peer.user.username, peer->user.username, strlen(peer->user.username)); - } - break; - case TGL_PEER_CHAT: - // print_title - if(peer->chat.print_title) { - self->peer.chat.print_title = (char*)malloc(strlen(peer->chat.print_title)); - memcpy(self->peer.chat.print_title, peer->chat.print_title, strlen(peer->chat.print_title)); - } - // user_list - if(peer->chat.user_list_size > 0) { - self->peer.chat.user_list = (struct tgl_chat_user*)malloc(self->peer.chat.user_list_size * - sizeof(struct tgl_chat_user)); - memcpy(self->peer.chat.user_list, peer->chat.user_list, - peer->chat.user_list_size * sizeof(struct tgl_chat_user)); - } - break; - case TGL_PEER_ENCR_CHAT: - // print_name - if(peer->encr_chat.print_name) { - self->peer.encr_chat.print_name = (char*)malloc(strlen(peer->encr_chat.print_name)); - memcpy(self->peer.encr_chat.print_name, peer->encr_chat.print_name, strlen(peer->encr_chat.print_name)); - } - // g_key - if(peer->encr_chat.g_key) { - self->peer.encr_chat.g_key = (unsigned char*)malloc(256); - memcpy(self->peer.encr_chat.g_key, peer->encr_chat.g_key, 256); - } - break; - default: - assert(0); - } - + self->peer = peer; + return (PyObject *) self; +} + +// +// struct tgl_message wrapper +// + +static void +tgl_Msg_dealloc(tgl_Msg* self) +{ + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static PyObject * +tgl_Msg_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + tgl_Msg *self; + + self = (tgl_Msg *)type->tp_alloc(type, 0); + return (PyObject *)self; +} + +static int +tgl_Msg_init(tgl_Msg *self, PyObject *args, PyObject *kwds) +{ + return 0; +} + +static PyObject * +tgl_Msg_getid (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + ret = PyLong_FromLong(self->msg->id); + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getflags (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + ret = PyLong_FromLong(self->msg->flags); + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getmention (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + ret = ((self->msg->flags & TGLMF_MENTION) ? Py_True : Py_False); + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getout (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + ret = ((self->msg->flags & TGLMF_OUT) ? Py_True : Py_False); + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getunread (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + ret = ((self->msg->flags & TGLMF_UNREAD) ? Py_True : Py_False); + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getservice (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + ret = ((self->msg->flags & TGLMF_SERVICE) ? Py_True : Py_False); + + Py_XINCREF(ret); + return ret; +} + + +static PyObject * +tgl_Msg_getfrom (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + if(tgl_get_peer_type (self->msg->from_id)) { + ret = tgl_Peer_FromTglPeer(tgl_peer_get (TLS, self->msg->from_id)); + } else { + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getto (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + if(tgl_get_peer_type (self->msg->to_id)) { + ret = tgl_Peer_FromTglPeer(tgl_peer_get (TLS, self->msg->to_id)); + } else { + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_gettext (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + if(self->msg->message_len && self->msg->message && !(self->msg->flags & TGLMF_SERVICE)) { + ret = PyUnicode_FromStringAndSize(self->msg->message, self->msg->message_len); + } else { + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getmedia (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + // TODO probably want a custom class for media, but it's not too important right now. + if(self->msg->media.type && self->msg->media.type != tgl_message_media_none && !(self->msg->flags & TGLMF_SERVICE)) { + + ret = PyDict_New(); + switch (self->msg->media.type) { + case tgl_message_media_photo: + py_add_string_field (ret, "type", "photo"); + py_add_string_field (ret, "caption", self->msg->media.caption); + break; + case tgl_message_media_document: + case tgl_message_media_document_encr: + py_add_string_field (ret, "type", "document"); + break; + case tgl_message_media_unsupported: + py_add_string_field (ret, "type", "unsupported"); + break; + case tgl_message_media_geo: + py_add_string_field (ret, "type", "geo"); + py_add_num_field (ret, "longitude", self->msg->media.geo.longitude); + py_add_num_field (ret, "latitude", self->msg->media.geo.latitude); + break; + case tgl_message_media_contact: + py_add_string_field (ret, "type", "contact"); + py_add_string_field (ret, "phone", self->msg->media.phone); + py_add_string_field (ret, "first_name", self->msg->media.first_name); + py_add_string_field (ret, "last_name", self->msg->media.last_name); + py_add_num_field (ret, "user_id", self->msg->media.user_id); + break; + case tgl_message_media_webpage: + py_add_string_field (ret, "type", "webpage"); + py_add_string_field (ret, "type", "webpage"); + py_add_string_field (ret, "url", self->msg->media.webpage->url); + py_add_string_field (ret, "title", self->msg->media.webpage->title); + py_add_string_field (ret, "description", self->msg->media.webpage->description); + py_add_string_field (ret, "author", self->msg->media.webpage->author); + break; + case tgl_message_media_venue: + py_add_string_field (ret, "type", "venue"); + py_add_num_field (ret, "longitude", self->msg->media.venue.geo.longitude); + py_add_num_field (ret, "latitude", self->msg->media.venue.geo.latitude); + py_add_string_field (ret, "title", self->msg->media.venue.title); + py_add_string_field (ret, "address", self->msg->media.venue.address); + py_add_string_field (ret, "provider", self->msg->media.venue.provider); + py_add_string_field (ret, "venue_id", self->msg->media.venue.venue_id); + break; + default: + py_add_string_field (ret, "type", "unknown"); + } + } else { + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getdate (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + if(self->msg->date) { + ret = PyDateTime_FromTimestamp(Py_BuildValue("(O)", + PyLong_FromLong(self->msg->date))); + } else { + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getfwd_from (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + if(tgl_get_peer_type (self->msg->fwd_from_id)) { + ret = tgl_Peer_FromTglPeer(tgl_peer_get (TLS, self->msg->fwd_from_id)); + } else { + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getfwd_date (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + if(tgl_get_peer_type (self->msg->fwd_from_id)) { + ret = PyDateTime_FromTimestamp(Py_BuildValue("(O)", + PyLong_FromLong(self->msg->fwd_date))); + } else { + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getreply (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + if(self->msg->reply_id) { + struct tgl_message *MR = tgl_message_get (TLS, self->msg->reply_id); + if(MR) { + ret = tgl_Msg_FromTglMsg(MR); + } else { + Py_RETURN_NONE; + } + } else { + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getreply_id (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + if(self->msg->reply_id) { + ret = PyLong_FromLong(self->msg->reply_id); + } else { + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + + + + +static PyGetSetDef tgl_Msg_getseters[] = { + {"id", (getter)tgl_Msg_getid, NULL, "", NULL}, + {"flags", (getter)tgl_Msg_getflags, NULL, "", NULL}, + {"mention", (getter)tgl_Msg_getmention, NULL, "", NULL}, + {"out", (getter)tgl_Msg_getout, NULL, "", NULL}, + {"unread", (getter)tgl_Msg_getunread, NULL, "", NULL}, + {"service", (getter)tgl_Msg_getservice, NULL, "", NULL}, + {"from", (getter)tgl_Msg_getfrom, NULL, "", NULL}, + {"to", (getter)tgl_Msg_getto, NULL, "", NULL}, + {"text", (getter)tgl_Msg_gettext, NULL, "", NULL}, + {"media", (getter)tgl_Msg_getmedia, NULL, "", NULL}, + {"date", (getter)tgl_Msg_getdate, NULL, "", NULL}, + {"fwd_from", (getter)tgl_Msg_getfwd_from, NULL, "", NULL}, + {"fwd_date", (getter)tgl_Msg_getfwd_date, NULL, "", NULL}, + {"reply", (getter)tgl_Msg_getreply, NULL, "", NULL}, + {"reply_id", (getter)tgl_Msg_getreply_id, NULL, "", NULL}, + {NULL} /* Sentinel */ +}; + +static PyMemberDef tgl_Msg_members[] = { + {NULL} /* Sentinel */ +}; + +static PyMethodDef tgl_Msg_methods[] = { + {NULL} /* Sentinel */ +}; + + +PyTypeObject tgl_MsgType = { + PyVarObject_HEAD_INIT(NULL, 0) + "tgl.Peer", /* tp_name */ + sizeof(tgl_Msg), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)tgl_Msg_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + "tgl Peer", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + tgl_Msg_methods, /* tp_methods */ + tgl_Msg_members, /* tp_members */ + tgl_Msg_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)tgl_Msg_init, /* tp_init */ + 0, /* tp_alloc */ + tgl_Msg_new, /* tp_new */ +}; + + +PyObject * +tgl_Msg_FromTglMsg(struct tgl_message *msg) { + tgl_Msg *self = (tgl_Msg *) tgl_Msg_new((PyTypeObject *)&tgl_MsgType, Py_None, Py_None); + + self->msg = msg; return (PyObject *) self; } diff --git a/python-types.h b/python-types.h index 211f1be..448516a 100644 --- a/python-types.h +++ b/python-types.h @@ -6,9 +6,16 @@ typedef struct { PyObject_HEAD - tgl_peer_t peer; + tgl_peer_t *peer; } tgl_Peer; +typedef struct { + PyObject_HEAD + struct tgl_message *msg; +} tgl_Msg; + + PyObject * tgl_Peer_FromTglPeer(tgl_peer_t *peer); +PyObject * tgl_Msg_FromTglMsg(struct tgl_message *peer); #endif diff --git a/tg-test.py b/tg-test.py index 3b495a1..c90864d 100644 --- a/tg-test.py +++ b/tg-test.py @@ -35,7 +35,7 @@ def on_msg_receive(msg): if msg["out"] and not binlog_done: return; - print(msg["to"].user_id) + print(msg["to"].id) """ def on_msg_receive(msg): From fe030a69e2fec98d862c2bce36f6a73256186e99 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Tue, 19 May 2015 17:49:24 -0700 Subject: [PATCH 75/97] Initial python class implementation complete. --- python-tg.c | 223 ++----------------------------------------------- python-types.c | 39 +++++++-- tg-test.py | 4 +- 3 files changed, 42 insertions(+), 224 deletions(-) diff --git a/python-tg.c b/python-tg.c index 8cfa821..2c1b803 100644 --- a/python-tg.c +++ b/python-tg.c @@ -78,6 +78,7 @@ extern PyTypeObject tgl_PeerType; +extern PyTypeObject tgl_MsgType; //#include "interface.h" @@ -101,7 +102,6 @@ PyObject *_py_secret_chat_update; PyObject *_py_user_update; 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 @@ -155,67 +155,6 @@ PyObject* get_tgl_peer_type (int x) { 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); - } - if (P->user.username) { - py_add_string_field ( user, "username", P->user.username); - } - 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); @@ -275,166 +214,16 @@ PyObject* get_update_types (unsigned flags) { 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_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 & TGLPF_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", PyUnicode_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); - } -*/ peer = tgl_Peer_FromTglPeer(P); 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: - py_add_string_field (media, "type", "photo"); - py_add_string_field (media, "caption", M->caption); - 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; - case tgl_message_media_webpage: - py_add_string_field (media, "type", "webpage"); - py_add_string_field (media, "type", "webpage"); - py_add_string_field (media, "url", M->webpage->url); - py_add_string_field (media, "title", M->webpage->title); - py_add_string_field (media, "description", M->webpage->description); - py_add_string_field (media, "author", M->webpage->author); - break; - case tgl_message_media_venue: - py_add_string_field (media, "type", "venue"); - py_add_num_field (media, "longitude", M->venue.geo.longitude); - py_add_num_field (media, "latitude", M->venue.geo.latitude); - py_add_string_field (media, "title", M->venue.title); - py_add_string_field (media, "address", M->venue.address); - py_add_string_field (media, "provider", M->venue.provider); - py_add_string_field (media, "venue_id", M->venue.venue_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 & TGLMF_CREATED)) { - Py_RETURN_NONE; - } - 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))); - PyDict_SetItemString (msg, "fwd_date", get_datetime(M->fwd_date)); - } - - if (M->reply_id) { - snprintf (s, 30, "%lld", M->id); - py_add_string_field (msg, "reply_id", s); - 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, "mention", ((M->flags & TGLMF_MENTION) ? Py_True : Py_False)); - PyDict_SetItemString(msg, "out", ((M->flags & TGLMF_OUT) ? Py_True : Py_False)); - PyDict_SetItemString(msg, "unread", ((M->flags & TGLMF_UNREAD) ? Py_True : Py_False)); - PyDict_SetItemString(msg, "service", ((M->flags & TGLMF_SERVICE) ? Py_True : Py_False)); - PyDict_SetItemString(msg, "date", get_datetime(M->date)); - - if (!(M->flags & TGLMF_SERVICE)) { - if (M->message_len && M->message) { - 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)); - } - } - + + msg = tgl_Msg_FromTglMsg(M); return msg; } @@ -1301,6 +1090,12 @@ MOD_INIT(tgl) Py_INCREF(&tgl_PeerType); PyModule_AddObject(m, "Peer", (PyObject *)&tgl_PeerType); + if (PyType_Ready(&tgl_MsgType) < 0) + return MOD_ERROR_VAL; + + Py_INCREF(&tgl_MsgType); + PyModule_AddObject(m, "Msg", (PyObject *)&tgl_MsgType); + return MOD_SUCCESS_VAL(m); } diff --git a/python-types.c b/python-types.c index 4488a9f..352d8fd 100644 --- a/python-types.c +++ b/python-types.c @@ -206,6 +206,28 @@ tgl_Peer_getusername (tgl_Peer *self, void *closure) } +static PyObject * +tgl_Peer_getuser (tgl_Peer *self, void *closure) +{ + PyObject *ret; + + switch(self->peer->id.type) { + case TGL_PEER_ENCR_CHAT: + ret = tgl_Peer_FromTglPeer(tgl_peer_get(TLS, TGL_MK_USER (self->peer->encr_chat.user_id))); + break; + case TGL_PEER_USER: + case TGL_PEER_CHAT: + PyErr_SetString(PyExc_TypeError, "Only peer.type == TGL_PEER_ENCR_CHAT has user"); + Py_RETURN_NONE; + break; + default: + PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} static PyObject * tgl_Peer_getid (tgl_Peer *self, void *closure) @@ -234,6 +256,7 @@ static PyGetSetDef tgl_Peer_getseters[] = { {"type", (getter)tgl_Peer_gettype, NULL, "", NULL}, {"name", (getter)tgl_Peer_getname, NULL, "", NULL}, {"user_id", (getter)tgl_Peer_getuser_id, NULL, "", NULL}, + {"user", (getter)tgl_Peer_getuser, NULL, "", NULL}, {"user_list", (getter)tgl_Peer_getuser_list, NULL, "", NULL}, {"user_status", (getter)tgl_Peer_getuser_status, NULL, "", NULL}, {"phone", (getter)tgl_Peer_getphone, NULL, "", NULL}, @@ -417,7 +440,7 @@ tgl_Msg_getservice (tgl_Msg *self, void *closure) static PyObject * -tgl_Msg_getfrom (tgl_Msg *self, void *closure) +tgl_Msg_getsrc (tgl_Msg *self, void *closure) { PyObject *ret; @@ -432,7 +455,7 @@ tgl_Msg_getfrom (tgl_Msg *self, void *closure) } static PyObject * -tgl_Msg_getto (tgl_Msg *self, void *closure) +tgl_Msg_getdest (tgl_Msg *self, void *closure) { PyObject *ret; @@ -539,7 +562,7 @@ tgl_Msg_getdate (tgl_Msg *self, void *closure) } static PyObject * -tgl_Msg_getfwd_from (tgl_Msg *self, void *closure) +tgl_Msg_getfwd_src (tgl_Msg *self, void *closure) { PyObject *ret; @@ -614,12 +637,12 @@ static PyGetSetDef tgl_Msg_getseters[] = { {"out", (getter)tgl_Msg_getout, NULL, "", NULL}, {"unread", (getter)tgl_Msg_getunread, NULL, "", NULL}, {"service", (getter)tgl_Msg_getservice, NULL, "", NULL}, - {"from", (getter)tgl_Msg_getfrom, NULL, "", NULL}, - {"to", (getter)tgl_Msg_getto, NULL, "", NULL}, + {"src", (getter)tgl_Msg_getsrc, NULL, "", NULL}, + {"dest", (getter)tgl_Msg_getdest, NULL, "", NULL}, {"text", (getter)tgl_Msg_gettext, NULL, "", NULL}, {"media", (getter)tgl_Msg_getmedia, NULL, "", NULL}, {"date", (getter)tgl_Msg_getdate, NULL, "", NULL}, - {"fwd_from", (getter)tgl_Msg_getfwd_from, NULL, "", NULL}, + {"fwd_src", (getter)tgl_Msg_getfwd_src, NULL, "", NULL}, {"fwd_date", (getter)tgl_Msg_getfwd_date, NULL, "", NULL}, {"reply", (getter)tgl_Msg_getreply, NULL, "", NULL}, {"reply_id", (getter)tgl_Msg_getreply_id, NULL, "", NULL}, @@ -637,7 +660,7 @@ static PyMethodDef tgl_Msg_methods[] = { PyTypeObject tgl_MsgType = { PyVarObject_HEAD_INIT(NULL, 0) - "tgl.Peer", /* tp_name */ + "tgl.Msg", /* tp_name */ sizeof(tgl_Msg), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)tgl_Msg_dealloc, /* tp_dealloc */ @@ -656,7 +679,7 @@ PyTypeObject tgl_MsgType = { 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ - "tgl Peer", /* tp_doc */ + "tgl Message", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ diff --git a/tg-test.py b/tg-test.py index c90864d..a968c82 100644 --- a/tg-test.py +++ b/tg-test.py @@ -32,10 +32,10 @@ def history_cb(msg_list, ptype, pid, success, msgs): tgl.get_history(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: + if msg.out and not binlog_done: return; - print(msg["to"].id) + print("From: {0}, To: {1}".format(msg.src.id, msg.dest.user)) """ def on_msg_receive(msg): From 7f2fc476ebcc72ea056102ca25589c9c36c1ef72 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Tue, 19 May 2015 23:09:46 -0700 Subject: [PATCH 76/97] Migrate API to completely use new python objects. --- python-tg.c | 251 +++++++++++++++++++++++++++++++++---------------- python-tg.h | 48 ++++++++++ python-types.c | 147 ++++++++++++++++++++++------- tg-test.py | 6 +- 4 files changed, 334 insertions(+), 118 deletions(-) diff --git a/python-tg.c b/python-tg.c index 2c1b803..b73be1c 100644 --- a/python-tg.c +++ b/python-tg.c @@ -735,6 +735,8 @@ void py_str_cb (struct tgl_state *TLSR, void *cb_extra, int success, const char Py_XDECREF(callable); } +#define PY_PEER_ID(x) (tgl_peer_id_t)((tgl_Peer*)x)->peer->id + void py_do_all (void) { int p = 0; while (p < pos) { @@ -744,6 +746,10 @@ void py_do_all (void) { PyObject *args = (PyObject *)py_ptr[p ++]; const char *str, *str1, *str2, *str3; + + Py_ssize_t i; + tgl_user_id_t *ids; + int len, len1, len2, len3; int limit, offset; long msg_id; @@ -751,61 +757,87 @@ void py_do_all (void) { PyObject *pyObj2 = NULL; PyObject *cb_extra = NULL; - //struct tgl_message *M; - tgl_peer_id_t peer, peer1; + PyObject *peer = NULL; + PyObject *peer1 = NULL; switch (f) { case pq_contact_list: - PyArg_ParseTuple(args, "|O", &cb_extra); - tgl_do_update_contact_list (TLS, py_contact_list_cb, cb_extra); + if(PyArg_ParseTuple(args, "|O", &cb_extra)) + tgl_do_update_contact_list (TLS, py_contact_list_cb, cb_extra); + else + PyErr_Print(); break; case pq_dialog_list: - PyArg_ParseTuple(args, "|O", &cb_extra); - tgl_do_get_dialog_list (TLS, 100, 0, py_dialog_list_cb, cb_extra); + if(PyArg_ParseTuple(args, "|O", &cb_extra)) + tgl_do_get_dialog_list (TLS, 100, 0, py_dialog_list_cb, cb_extra); + else + PyErr_Print(); break; case pq_msg: - PyArg_ParseTuple(args, "iis#|O", &peer.type, &peer.id, &str, &len, &cb_extra); - tgl_do_send_message (TLS, peer, str, len, 0, py_msg_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!s#|O", &tgl_PeerType, &peer, &str, &len, &cb_extra)) + tgl_do_send_message (TLS, PY_PEER_ID(peer), str, len, 0, py_msg_cb, cb_extra); + else + PyErr_Print(); break; case pq_send_typing: - 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); + if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra)) + tgl_do_send_typing (TLS, PY_PEER_ID(peer), tgl_typing_typing, py_empty_cb, cb_extra); + else + PyErr_Print(); break; case pq_send_typing_abort: - 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); + if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra)) + tgl_do_send_typing (TLS, PY_PEER_ID(peer), tgl_typing_cancel, py_empty_cb, cb_extra); + else + PyErr_Print(); break; case pq_rename_chat: - PyArg_ParseTuple(args, "iis#|O", &peer.type, &peer.id, &str, &len, &cb_extra); - tgl_do_rename_chat (TLS, peer, str, len, py_empty_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!s#|O", &tgl_PeerType, &peer, &str, &len, &cb_extra)) + tgl_do_rename_chat (TLS, PY_PEER_ID(peer), str, len, py_empty_cb, cb_extra); + else + PyErr_Print(); break; case pq_send_photo: - PyArg_ParseTuple(args, "iis|O", &peer.type, &peer.id, &str, &cb_extra); - tgl_do_send_document (TLS, peer, str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_PHOTO, py_msg_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra)) + tgl_do_send_document (TLS, PY_PEER_ID(peer), str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_PHOTO, py_msg_cb, cb_extra); + else + PyErr_Print(); break; case pq_send_video: - PyArg_ParseTuple(args, "iis|O", &peer.type, &peer.id, &str, &cb_extra); - tgl_do_send_document (TLS, peer, str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_VIDEO, py_msg_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra)) + tgl_do_send_document (TLS, PY_PEER_ID(peer), str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_VIDEO, py_msg_cb, cb_extra); + else + PyErr_Print(); break; case pq_send_audio: - PyArg_ParseTuple(args, "iis|O", &peer.type, &peer.id, &str, &cb_extra); - tgl_do_send_document (TLS, peer, str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_AUDIO, py_msg_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra)) + tgl_do_send_document (TLS, PY_PEER_ID(peer), str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_AUDIO, py_msg_cb, cb_extra); + else + PyErr_Print(); break; case pq_send_document: - PyArg_ParseTuple(args, "iis|O", &peer.type, &peer.id, &str, &cb_extra); - tgl_do_send_document (TLS, peer, str, NULL, 0, 0, py_msg_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra)) + tgl_do_send_document (TLS, PY_PEER_ID(peer), str, NULL, 0, 0, py_msg_cb, cb_extra); + else + PyErr_Print(); break; case pq_send_file: - PyArg_ParseTuple(args, "iis|O", &peer.type, &peer.id, &str, &cb_extra); - tgl_do_send_document (TLS, peer, str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_AUTO, py_msg_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra)) + tgl_do_send_document (TLS, PY_PEER_ID(peer), str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_AUTO, py_msg_cb, cb_extra); + else + PyErr_Print(); break; case pq_send_text: - PyArg_ParseTuple(args, "iis|O", &peer.type, &peer.id, &str, &cb_extra); - tgl_do_send_text (TLS, peer, str, 0, py_msg_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra)) + tgl_do_send_text (TLS, PY_PEER_ID(peer), str, 0, py_msg_cb, cb_extra); + else + PyErr_Print(); break; case pq_chat_set_photo: - PyArg_ParseTuple(args, "iis|O", &peer.type, &peer.id, &str, &cb_extra); - tgl_do_set_chat_photo (TLS, peer, str, py_empty_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra)) + tgl_do_set_chat_photo (TLS, PY_PEER_ID(peer), str, py_empty_cb, cb_extra); + else + PyErr_Print(); break; /* case pq_load_photo: case pq_load_video: @@ -835,83 +867,124 @@ void py_do_all (void) { break; */ case pq_fwd: - PyArg_ParseTuple(args, "iil|O", &peer.type, &peer.id, &msg_id, &cb_extra); - tgl_do_forward_message (TLS, peer, msg_id, 0, py_msg_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!l|O", &tgl_PeerType, &peer, &msg_id, &cb_extra)) + tgl_do_forward_message (TLS, PY_PEER_ID(peer), msg_id, 0, py_msg_cb, cb_extra); + else + PyErr_Print(); break; case pq_fwd_media: - PyArg_ParseTuple(args, "iil|O", &peer.type, &peer.id, &msg_id, &cb_extra); - tgl_do_forward_media (TLS, peer, msg_id, 0, py_msg_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!l|O", &tgl_PeerType, &peer, &msg_id, &cb_extra)) + tgl_do_forward_media (TLS, PY_PEER_ID(peer), msg_id, 0, py_msg_cb, cb_extra); + else + PyErr_Print(); break; case pq_chat_info: - PyArg_ParseTuple(args, "ii|O", &peer.type, &peer.id, &cb_extra); - tgl_do_get_chat_info (TLS, peer, 0, py_chat_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra)) + tgl_do_get_chat_info (TLS, PY_PEER_ID(peer), 0, py_chat_cb, cb_extra); + else + PyErr_Print(); break; case pq_user_info: - PyArg_ParseTuple(args, "ii|O", &peer.type, &peer.id, &cb_extra); - tgl_do_get_user_info (TLS, peer, 0, py_user_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra)) + tgl_do_get_user_info (TLS, PY_PEER_ID(peer), 0, py_user_cb, cb_extra); + else + PyErr_Print(); break; case pq_history: - PyArg_ParseTuple(args, "iiii|O", &peer.type, &peer.id, &offset, &limit, &cb_extra); - tgl_do_get_history (TLS, peer, offset, limit, 0, py_msg_list_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!ii|O", &tgl_PeerType, &peer, &offset, &limit, &cb_extra)) + tgl_do_get_history (TLS, PY_PEER_ID(peer), offset, limit, 0, py_msg_list_cb, cb_extra); + else + PyErr_Print(); break; case pq_chat_add_user: - 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_empty_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!O!|O", &tgl_PeerType, &peer, &tgl_PeerType, &peer1, &cb_extra)) + tgl_do_add_user_to_chat (TLS, PY_PEER_ID(peer), PY_PEER_ID(peer1), 100, py_empty_cb, cb_extra); + else + PyErr_Print(); break; case pq_chat_del_user: - 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_empty_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!O!|O", &tgl_PeerType, &peer, &tgl_PeerType, &peer1, &cb_extra)) + tgl_do_del_user_from_chat (TLS, PY_PEER_ID(peer), PY_PEER_ID(peer1), py_empty_cb, cb_extra); + else + PyErr_Print(); break; case pq_add_contact: - PyArg_ParseTuple(args, "s#s#s#|O", &str1, &len1, &str2, &len2, &str3, &len3, &cb_extra); - tgl_do_add_contact (TLS, str1, len1, str2, len2, str3, len3, 0, py_contact_list_cb, cb_extra); + if(PyArg_ParseTuple(args, "s#s#s#|O", &str1, &len1, &str2, &len2, &str3, &len3, &cb_extra)) + tgl_do_add_contact (TLS, str1, len1, str2, len2, str3, len3, 0, py_contact_list_cb, cb_extra); + else + PyErr_Print(); break; case pq_del_contact: - PyArg_ParseTuple(args, "ii|O", &peer.type, &peer.id, &cb_extra); - tgl_do_del_contact (TLS, peer, py_empty_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra)) + tgl_do_del_contact (TLS, PY_PEER_ID(peer), py_empty_cb, cb_extra); + else + PyErr_Print(); break; case pq_rename_contact: - PyArg_ParseTuple(args, "s#s#s#|O", &str1, &len1, &str2, &len2, &str3, &len3, &cb_extra); - tgl_do_add_contact (TLS, str1, len1, str2, len2, str3, len3, 1, py_contact_list_cb, cb_extra); + if(PyArg_ParseTuple(args, "s#s#s#|O", &str1, &len1, &str2, &len2, &str3, &len3, &cb_extra)) + tgl_do_add_contact (TLS, str1, len1, str2, len2, str3, len3, 1, py_contact_list_cb, cb_extra); + else + PyErr_Print(); break; case pq_search: - PyArg_ParseTuple(args, "iis#|O", &peer.type, &peer.id, &str, &len, &cb_extra); - tgl_do_msg_search (TLS, peer, 0, 0, 40, 0, str, len, py_msg_list_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!s#|O", &tgl_PeerType, &peer, &str, &len, &cb_extra)) + tgl_do_msg_search (TLS, PY_PEER_ID(peer), 0, 0, 40, 0, str, len, py_msg_list_cb, cb_extra); + else + PyErr_Print(); break; case pq_global_search: - PyArg_ParseTuple(args, "s#|O", &str, &len, &cb_extra); - tgl_do_msg_search (TLS, tgl_set_peer_id (TGL_PEER_UNKNOWN, 0), 0, 0, 40, 0, str, len, py_msg_list_cb, cb_extra); + if(PyArg_ParseTuple(args, "s#|O", &str, &len, &cb_extra)) + tgl_do_msg_search (TLS, tgl_set_peer_id (TGL_PEER_UNKNOWN, 0), 0, 0, 40, 0, str, len, py_msg_list_cb, cb_extra); + else + PyErr_Print(); break; case pq_mark_read: - PyArg_ParseTuple(args, "ii|O", &peer.type, &peer.id, &cb_extra); - tgl_do_mark_read (TLS, peer, py_empty_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra)) + tgl_do_mark_read (TLS, PY_PEER_ID(peer), py_empty_cb, cb_extra); + else + PyErr_Print(); break; case pq_set_profile_photo: - PyArg_ParseTuple(args, "s|O", &str, &cb_extra); - tgl_do_set_profile_photo (TLS, str, py_empty_cb, cb_extra); + if(PyArg_ParseTuple(args, "s|O", &str, &cb_extra)) + tgl_do_set_profile_photo (TLS, str, py_empty_cb, cb_extra); + else + PyErr_Print(); break; case pq_set_profile_name: - PyArg_ParseTuple(args, "s#s#|O", &str1, &len1, &str2, len2, &cb_extra); - tgl_do_set_profile_name (TLS, str1, len1, str2, len2, py_user_cb, cb_extra); + if(PyArg_ParseTuple(args, "s#s#|O", &str1, &len1, &str2, len2, &cb_extra)) + tgl_do_set_profile_name (TLS, str1, len1, str2, len2, py_user_cb, cb_extra); + else + PyErr_Print(); break; case pq_create_secret_chat: - PyArg_ParseTuple(args, "ii|O", &peer.type, &peer.id, &cb_extra); - tgl_do_create_secret_chat (TLS, peer, py_secret_chat_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra)) + tgl_do_create_secret_chat (TLS, PY_PEER_ID(peer), py_secret_chat_cb, cb_extra); + else + PyErr_Print(); break; -/* case pq_create_group_chat: - PyArg_ParseTuple(args, "Os|O", &pyObj1, str, &cb_extra); - if(PyList_Check(pyObj1) { - tgl_do_create_group_chat (TLS, peer, str, py_msg_cb, cb_extra); - } else { - logprintf("create_group_chat: Argument 1 must be a list of peers" + if(PyArg_ParseTuple(args, "O!s#|O", &PyList_Type, &pyObj1, &str, &len, &cb_extra)) { + if(PyList_GET_SIZE(pyObj1) > 2) { + ids = (tgl_user_id_t *)malloc(PyList_GET_SIZE(pyObj1) * sizeof(tgl_user_id_t)); + for(i = 0; i < PyList_GET_SIZE(pyObj1); i++) { + peer = PyList_GetItem(pyObj1, i); + *(ids+i) = PY_PEER_ID(peer); + } + tgl_do_create_group_chat (TLS, PyList_GET_SIZE(pyObj1), ids, str, len, py_empty_cb, cb_extra); + + tfree(ids, PyList_GET_SIZE(pyObj1) * sizeof(tgl_user_id_t)); + } else { + logprintf("create_group_chat: Argument 1 must be a list of at least 3 peers"); + } } + Py_XDECREF(pyObj1); break; -*/ case pq_delete_msg: case pq_restore_msg: - PyArg_ParseTuple(args, "l|O", msg_id, &cb_extra); - tgl_do_delete_msg (TLS, msg_id, py_empty_cb, cb_extra); + if(PyArg_ParseTuple(args, "l|O", msg_id, &cb_extra)) + tgl_do_delete_msg (TLS, msg_id, py_empty_cb, cb_extra); + else + PyErr_Print(); break; /* case pq_accept_secret_chat: @@ -919,26 +992,38 @@ void py_do_all (void) { break; */ case pq_send_contact: - PyArg_ParseTuple(args, "iis#s#s#|O", &peer.type, &peer.id, &str1, &len1, &str2, &len2, &str3, &len3, &cb_extra); - tgl_do_send_contact (TLS, peer, str1, len1, str2, len2, str3, len3, 0, py_msg_cb, cb_extra); + if(PyArg_ParseTuple(args, "O!s#s#s#|O", &tgl_PeerType, &peer, &str1, &len1, &str2, &len2, + &str3, &len3, &cb_extra)) + tgl_do_send_contact (TLS, PY_PEER_ID(peer), str1, len1, str2, len2, str3, len3, 0, py_msg_cb, cb_extra); + else + PyErr_Print(); break; case pq_status_online: - PyArg_ParseTuple(args, "|O", &cb_extra); - tgl_do_update_status (TLS, 1, py_empty_cb, cb_extra); + if(PyArg_ParseTuple(args, "|O", &cb_extra)) + tgl_do_update_status (TLS, 1, py_empty_cb, cb_extra); + else + PyErr_Print(); break; case pq_status_offline: - PyArg_ParseTuple(args, "|O", &cb_extra); - tgl_do_update_status (TLS, 0, py_empty_cb, cb_extra); + if(PyArg_ParseTuple(args, "|O", &cb_extra)) + tgl_do_update_status (TLS, 0, py_empty_cb, cb_extra); + else + PyErr_Print(); break; case pq_extf: - PyArg_ParseTuple(args, "s#|O", &str, &len, &cb_extra); - tgl_do_send_extf (TLS, str, len, py_str_cb, &cb_extra); + if(PyArg_ParseTuple(args, "s#|O", &str, &len, &cb_extra)) + tgl_do_send_extf (TLS, str, len, py_str_cb, &cb_extra); + else + PyErr_Print(); break; case pq_send_location: - 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), 0, py_msg_cb, cb_extra); - Py_XDECREF(pyObj1); - Py_XDECREF(pyObj2); + if(PyArg_ParseTuple(args, "O!O!O!|O", &tgl_PeerType, &peer, &PyFloat_Type, &pyObj1, &PyFloat_Type, &pyObj2, &cb_extra)){ + tgl_do_send_location (TLS, PY_PEER_ID(peer), + PyFloat_AsDouble(pyObj1), PyFloat_AsDouble(pyObj2), 0, py_msg_cb, cb_extra); + Py_XDECREF(pyObj1); + Py_XDECREF(pyObj2); + } else + PyErr_Print(); break; default: assert (0); @@ -946,9 +1031,11 @@ void py_do_all (void) { // 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 + Py_XDECREF(peer); + Py_XDECREF(peer1); } pos = 0; diff --git a/python-tg.h b/python-tg.h index 4145c7a..bf3784e 100644 --- a/python-tg.h +++ b/python-tg.h @@ -24,6 +24,7 @@ #include #include +// Python functions void py_init (const char *file); void py_new_msg (struct tgl_message *M); void py_our_id (int id); @@ -34,7 +35,54 @@ void py_binlog_end (void); void py_diff_end (void); void py_do_all (void); +// Binding functions +PyObject* py_contact_list(PyObject *self, PyObject *args); +PyObject* py_dialog_list(PyObject *self, PyObject *args); +PyObject* py_rename_chat(PyObject *self, PyObject *args); +PyObject* py_send_msg(PyObject *self, PyObject *args); +PyObject* py_send_typing(PyObject *self, PyObject *args); +PyObject* py_send_typing_abort(PyObject *self, PyObject *args); +PyObject* py_send_photo(PyObject *self, PyObject *args); +PyObject* py_send_video(PyObject *self, PyObject *args); +PyObject* py_send_audio(PyObject *self, PyObject *args); +PyObject* py_send_document(PyObject *self, PyObject *args); +PyObject* py_send_file(PyObject *self, PyObject *args); +PyObject* py_send_text(PyObject *self, PyObject *args); +PyObject* py_chat_set_photo(PyObject *self, PyObject *args); +PyObject* py_load_photo(PyObject *self, PyObject *args); +PyObject* py_load_video(PyObject *self, PyObject *args); +PyObject* py_load_video_thumb(PyObject *self, PyObject *args); +PyObject* py_load_audio(PyObject *self, PyObject *args); +PyObject* py_load_document(PyObject *self, PyObject *args); +PyObject* py_load_document_thumb(PyObject *self, PyObject *args); +PyObject* py_fwd(PyObject *self, PyObject *args); +PyObject* py_fwd_media(PyObject *self, PyObject *args); +PyObject* py_chat_info(PyObject *self, PyObject *args); +PyObject* py_user_info(PyObject *self, PyObject *args); +PyObject* py_history(PyObject *self, PyObject *args); +PyObject* py_chat_add_user(PyObject *self, PyObject *args); +PyObject* py_chat_del_user(PyObject *self, PyObject *args); +PyObject* py_add_contact(PyObject *self, PyObject *args); +PyObject* py_del_contact(PyObject *self, PyObject *args); +PyObject* py_rename_contact(PyObject *self, PyObject *args); +PyObject* py_search(PyObject *self, PyObject *args); +PyObject* py_global_search(PyObject *self, PyObject *args); +PyObject* py_mark_read(PyObject *self, PyObject *args); +PyObject* py_set_profile_photo(PyObject *self, PyObject *args); +PyObject* py_set_profile_name(PyObject *self, PyObject *args); +PyObject* py_create_secret_chat(PyObject *self, PyObject *args); +PyObject* py_create_group_chat(PyObject *self, PyObject *args); +PyObject* py_delete_msg(PyObject *self, PyObject *args); +PyObject* py_restore_msg(PyObject *self, PyObject *args); +PyObject* py_accept_secret_chat(PyObject *self, PyObject *args); +PyObject* py_send_contact(PyObject *self, PyObject *args); +PyObject* py_status_online(PyObject *self, PyObject *args); +PyObject* py_status_offline(PyObject *self, PyObject *args); +PyObject* py_send_location(PyObject *self, PyObject *args); +PyObject* py_extf(PyObject *self, PyObject *args); + +// Util Functions void py_add_string_field (PyObject* dict, char *name, const char *value); void py_add_string_field_arr (PyObject* list, int num, const char *value); void py_add_num_field (PyObject* dict, const char *name, double value); diff --git a/python-types.c b/python-types.c index 352d8fd..93435f9 100644 --- a/python-types.c +++ b/python-types.c @@ -38,11 +38,13 @@ tgl_Peer_init(tgl_Peer *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"type", "id", NULL}; tgl_peer_id_t peer_id; - if(!PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwlist, + if(!PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwlist, &peer_id.type, &peer_id.id)) + { + PyErr_Format(PyErr_NewException("tgl.PeerInvalid", NULL, NULL), "Peer must specify type and id"); return -1; - + } self->peer = tgl_peer_get(TLS, peer_id); if(self->peer == NULL) return -1; @@ -66,7 +68,7 @@ tgl_Peer_getname (tgl_Peer *self, void *closure) ret = PyUnicode_FromString(self->peer->encr_chat.print_name); break; default: - PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + PyErr_SetString(PyExc_TypeError, "peer.type_name not supported!"); Py_RETURN_NONE; } @@ -85,7 +87,7 @@ tgl_Peer_getuser_id (tgl_Peer *self, void *closure) ret = PyLong_FromLong(self->peer->id.id); break; case TGL_PEER_CHAT: - PyErr_SetString(PyExc_TypeError, "peer.type == TGL_PEER_CHAT has no user_id"); + PyErr_SetString(PyExc_TypeError, "peer.type_name == 'chat' has no user_id"); Py_RETURN_NONE; break; @@ -93,7 +95,7 @@ tgl_Peer_getuser_id (tgl_Peer *self, void *closure) ret = PyLong_FromLong(self->peer->encr_chat.user_id); break; default: - PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + PyErr_SetString(PyExc_TypeError, "peer.type_name not supported!"); Py_RETURN_NONE; } @@ -120,11 +122,11 @@ tgl_Peer_getuser_list (tgl_Peer *self, void *closure) break; case TGL_PEER_ENCR_CHAT: case TGL_PEER_USER: - PyErr_SetString(PyExc_TypeError, "Only peer.type == TGL_PEER_CHAT has user_list"); + PyErr_SetString(PyExc_TypeError, "Only peer.type_name == 'chat' has user_list"); Py_RETURN_NONE; break; default: - PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + PyErr_SetString(PyExc_TypeError, "peer.type_name not supported!"); Py_RETURN_NONE; } @@ -147,11 +149,11 @@ tgl_Peer_getuser_status(tgl_Peer *self, void *closure) break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: - PyErr_SetString(PyExc_TypeError, "Only peer.type == TGL_PEER_USER has user_status"); + PyErr_SetString(PyExc_TypeError, "Only peer.type_name == 'user' has user_status"); Py_RETURN_NONE; break; default: - PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + PyErr_SetString(PyExc_TypeError, "peer.type_name not supported!"); Py_RETURN_NONE; } @@ -170,11 +172,11 @@ tgl_Peer_getphone (tgl_Peer *self, void *closure) break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: - PyErr_SetString(PyExc_TypeError, "Only peer.type == TGL_PEER_USER has phone"); + PyErr_SetString(PyExc_TypeError, "Only peer.type_name == 'user' has phone"); Py_RETURN_NONE; break; default: - PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + PyErr_SetString(PyExc_TypeError, "peer.type_name not supported!"); Py_RETURN_NONE; } @@ -193,11 +195,11 @@ tgl_Peer_getusername (tgl_Peer *self, void *closure) break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: - PyErr_SetString(PyExc_TypeError, "Only peer.type == TGL_PEER_USER has username"); + PyErr_SetString(PyExc_TypeError, "Only peer.type_name == 'user' has username"); Py_RETURN_NONE; break; default: - PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + PyErr_SetString(PyExc_TypeError, "peer.type_name not supported!"); Py_RETURN_NONE; } @@ -205,6 +207,51 @@ tgl_Peer_getusername (tgl_Peer *self, void *closure) return ret; } +static PyObject * +tgl_Peer_getfirst_name (tgl_Peer *self, void *closure) +{ + PyObject *ret; + + switch(self->peer->id.type) { + case TGL_PEER_USER: + ret = PyUnicode_FromString(self->peer->user.first_name); + break; + case TGL_PEER_CHAT: + case TGL_PEER_ENCR_CHAT: + PyErr_SetString(PyExc_TypeError, "Only peer.type_name == 'user' has first_name"); + Py_RETURN_NONE; + break; + default: + PyErr_SetString(PyExc_TypeError, "peer.type_name not supported!"); + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Peer_getlast_name (tgl_Peer *self, void *closure) +{ + PyObject *ret; + + switch(self->peer->id.type) { + case TGL_PEER_USER: + ret = PyUnicode_FromString(self->peer->user.username); + break; + case TGL_PEER_CHAT: + case TGL_PEER_ENCR_CHAT: + PyErr_SetString(PyExc_TypeError, "Only peer.type_name == 'user' has last_name"); + Py_RETURN_NONE; + break; + default: + PyErr_SetString(PyExc_TypeError, "peer.type_name not supported!"); + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} static PyObject * tgl_Peer_getuser (tgl_Peer *self, void *closure) @@ -216,12 +263,14 @@ tgl_Peer_getuser (tgl_Peer *self, void *closure) ret = tgl_Peer_FromTglPeer(tgl_peer_get(TLS, TGL_MK_USER (self->peer->encr_chat.user_id))); break; case TGL_PEER_USER: + ret = (PyObject*)self; + break; case TGL_PEER_CHAT: - PyErr_SetString(PyExc_TypeError, "Only peer.type == TGL_PEER_ENCR_CHAT has user"); + PyErr_SetString(PyExc_TypeError, "Only peer.type_name == 'chat' does not have user"); Py_RETURN_NONE; break; default: - PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); + PyErr_SetString(PyExc_TypeError, "peer.type_name not supported!"); Py_RETURN_NONE; } @@ -229,6 +278,27 @@ tgl_Peer_getuser (tgl_Peer *self, void *closure) return ret; } +static PyObject * +tgl_Peer_gettype_name(tgl_Peer* self) +{ + PyObject *name; + + switch(self->peer->id.type) { + case TGL_PEER_USER: + name = PyUnicode_FromString("user"); + break; + case TGL_PEER_CHAT: + name = PyUnicode_FromString("chat"); + break; + case TGL_PEER_ENCR_CHAT: + name = PyUnicode_FromString("secret_chat"); + break; + default: + name = PyUnicode_FromString("unknown"); + } + return name; +} + static PyObject * tgl_Peer_getid (tgl_Peer *self, void *closure) { @@ -254,6 +324,7 @@ tgl_Peer_gettype (tgl_Peer *self, void *closure) static PyGetSetDef tgl_Peer_getseters[] = { {"id", (getter)tgl_Peer_getid, NULL, "", NULL}, {"type", (getter)tgl_Peer_gettype, NULL, "", NULL}, + {"type_name", (getter)tgl_Peer_gettype_name, NULL, "", NULL}, {"name", (getter)tgl_Peer_getname, NULL, "", NULL}, {"user_id", (getter)tgl_Peer_getuser_id, NULL, "", NULL}, {"user", (getter)tgl_Peer_getuser, NULL, "", NULL}, @@ -261,6 +332,8 @@ static PyGetSetDef tgl_Peer_getseters[] = { {"user_status", (getter)tgl_Peer_getuser_status, NULL, "", NULL}, {"phone", (getter)tgl_Peer_getphone, NULL, "", NULL}, {"username", (getter)tgl_Peer_getusername, NULL, "", NULL}, + {"first_name", (getter)tgl_Peer_getfirst_name, NULL, "", NULL}, + {"last_name", (getter)tgl_Peer_getlast_name, NULL, "", NULL}, {NULL} /* Sentinel */ }; @@ -269,30 +342,36 @@ static PyMemberDef tgl_Peer_members[] = { }; static PyObject * -tgl_Peer_type_name(tgl_Peer* self) +tgl_Peer_send_msg (tgl_Peer *self, PyObject *args, PyObject *kwargs) { - PyObject *name; + static char *kwlist[] = {"message", "callback", NULL}; + + char *message; + PyObject *callback = NULL; + + if(PyArg_ParseTupleAndKeywords(args, kwargs, "s|O", kwlist, &message, &callback)) { + PyObject *api_call; + + if(callback) + api_call = Py_BuildValue("OsO", (PyObject*) self, message, callback); + else + api_call = Py_BuildValue("Os", (PyObject*) self, message); + + Py_XINCREF(Py_None); + Py_XINCREF(api_call); + + return py_send_msg(Py_None, api_call); + } else { + Py_XINCREF(Py_False); + return Py_False; + } - switch(self->peer->id.type) { - case TGL_PEER_USER: - name = PyUnicode_FromString("user"); - break; - case TGL_PEER_CHAT: - name = PyUnicode_FromString("chat"); - break; - case TGL_PEER_ENCR_CHAT: - name = PyUnicode_FromString("encr_chat"); - break; - default: - name = PyUnicode_FromString("unknown"); - } - return name; } + static PyMethodDef tgl_Peer_methods[] = { - {"type_name", (PyCFunction)tgl_Peer_type_name, METH_NOARGS, - "Return the string representation of the peer type." - }, + {"send_msg", (PyCFunction)tgl_Peer_send_msg, METH_VARARGS | METH_KEYWORDS, + "Send a message to peer object"}, {NULL} /* Sentinel */ }; diff --git a/tg-test.py b/tg-test.py index a968c82..a05454c 100644 --- a/tg-test.py +++ b/tg-test.py @@ -31,11 +31,13 @@ def history_cb(msg_list, ptype, pid, success, msgs): if len(msgs) == HISTORY_QUERY_SIZE: tgl.get_history(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; - - print("From: {0}, To: {1}".format(msg.src.id, msg.dest.user)) + tgl.send_msg(tgl.Peer(97704886), "Test") + print("Peers {0}".format(msg.src.id)) """ def on_msg_receive(msg): From b547ca7158fb8eead4ebb42d46cdbba7556fa1fd Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Tue, 19 May 2015 23:43:08 -0700 Subject: [PATCH 77/97] Add custom exceptions --- python-tg.c | 19 ++++++++++++++++++- python-types.c | 44 +++++++++++++++++++++++++------------------- tg-test.py | 34 +++++++++++----------------------- 3 files changed, 54 insertions(+), 43 deletions(-) diff --git a/python-tg.c b/python-tg.c index b73be1c..8e17d1e 100644 --- a/python-tg.c +++ b/python-tg.c @@ -80,7 +80,6 @@ extern PyTypeObject tgl_PeerType; extern PyTypeObject tgl_MsgType; - //#include "interface.h" //#include "auto/constants.h" #include @@ -93,6 +92,12 @@ extern struct tgl_state *TLS; static int python_loaded; +// TGL Python Exceptions +PyObject *TglError; +PyObject *PeerError; +PyObject *MsgError; + + // Python update function callables PyObject *_py_binlog_end; PyObject *_py_diff_end; @@ -1182,6 +1187,18 @@ MOD_INIT(tgl) Py_INCREF(&tgl_MsgType); PyModule_AddObject(m, "Msg", (PyObject *)&tgl_MsgType); + + TglError = PyErr_NewException("tgl.Error", NULL, NULL); + Py_INCREF(TglError); + PyModule_AddObject(m, "TglError", TglError); + + PeerError = PyErr_NewException("tgl.PeerError", NULL, NULL); + Py_INCREF(PeerError); + PyModule_AddObject(m, "PeerError", PeerError); + + MsgError = PyErr_NewException("tgl.MsgError", NULL, NULL); + Py_INCREF(MsgError); + PyModule_AddObject(m, "MsgError", MsgError); return MOD_SUCCESS_VAL(m); } diff --git a/python-types.c b/python-types.c index 93435f9..3e8f664 100644 --- a/python-types.c +++ b/python-types.c @@ -15,6 +15,11 @@ extern struct tgl_state *TLS; +// TGL Python Exceptions +extern PyObject *TglError; +extern PyObject *PeerError; +extern PyObject *MsgError; + // // tgl_peer_t wrapper // @@ -42,7 +47,7 @@ tgl_Peer_init(tgl_Peer *self, PyObject *args, PyObject *kwds) &peer_id.type, &peer_id.id)) { - PyErr_Format(PyErr_NewException("tgl.PeerInvalid", NULL, NULL), "Peer must specify type and id"); + PyErr_Format(PeerError, "Peer must specify type and id"); return -1; } self->peer = tgl_peer_get(TLS, peer_id); @@ -68,7 +73,7 @@ tgl_Peer_getname (tgl_Peer *self, void *closure) ret = PyUnicode_FromString(self->peer->encr_chat.print_name); break; default: - PyErr_SetString(PyExc_TypeError, "peer.type_name not supported!"); + PyErr_SetString(PeerError, "peer.type_name not supported!"); Py_RETURN_NONE; } @@ -87,7 +92,7 @@ tgl_Peer_getuser_id (tgl_Peer *self, void *closure) ret = PyLong_FromLong(self->peer->id.id); break; case TGL_PEER_CHAT: - PyErr_SetString(PyExc_TypeError, "peer.type_name == 'chat' has no user_id"); + PyErr_SetString(PeerError, "peer.type_name == 'chat' has no user_id"); Py_RETURN_NONE; break; @@ -95,7 +100,7 @@ tgl_Peer_getuser_id (tgl_Peer *self, void *closure) ret = PyLong_FromLong(self->peer->encr_chat.user_id); break; default: - PyErr_SetString(PyExc_TypeError, "peer.type_name not supported!"); + PyErr_SetString(PeerError, "peer.type_name not supported!"); Py_RETURN_NONE; } @@ -122,11 +127,11 @@ tgl_Peer_getuser_list (tgl_Peer *self, void *closure) break; case TGL_PEER_ENCR_CHAT: case TGL_PEER_USER: - PyErr_SetString(PyExc_TypeError, "Only peer.type_name == 'chat' has user_list"); + PyErr_SetString(PeerError, "Only peer.type_name == 'chat' has user_list"); Py_RETURN_NONE; break; default: - PyErr_SetString(PyExc_TypeError, "peer.type_name not supported!"); + PyErr_SetString(PeerError, "peer.type_name not supported!"); Py_RETURN_NONE; } @@ -149,11 +154,11 @@ tgl_Peer_getuser_status(tgl_Peer *self, void *closure) break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: - PyErr_SetString(PyExc_TypeError, "Only peer.type_name == 'user' has user_status"); + PyErr_SetString(PeerError, "Only peer.type_name == 'user' has user_status"); Py_RETURN_NONE; break; default: - PyErr_SetString(PyExc_TypeError, "peer.type_name not supported!"); + PyErr_SetString(PeerError, "peer.type_name not supported!"); Py_RETURN_NONE; } @@ -172,11 +177,11 @@ tgl_Peer_getphone (tgl_Peer *self, void *closure) break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: - PyErr_SetString(PyExc_TypeError, "Only peer.type_name == 'user' has phone"); + PyErr_SetString(PeerError, "Only peer.type_name == 'user' has phone"); Py_RETURN_NONE; break; default: - PyErr_SetString(PyExc_TypeError, "peer.type_name not supported!"); + PyErr_SetString(PeerError, "peer.type_name not supported!"); Py_RETURN_NONE; } @@ -195,11 +200,11 @@ tgl_Peer_getusername (tgl_Peer *self, void *closure) break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: - PyErr_SetString(PyExc_TypeError, "Only peer.type_name == 'user' has username"); + PyErr_SetString(PeerError, "Only peer.type_name == 'user' has username"); Py_RETURN_NONE; break; default: - PyErr_SetString(PyExc_TypeError, "peer.type_name not supported!"); + PyErr_SetString(PeerError, "peer.type_name not supported!"); Py_RETURN_NONE; } @@ -218,11 +223,11 @@ tgl_Peer_getfirst_name (tgl_Peer *self, void *closure) break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: - PyErr_SetString(PyExc_TypeError, "Only peer.type_name == 'user' has first_name"); + PyErr_SetString(PeerError, "Only peer.type_name == 'user' has first_name"); Py_RETURN_NONE; break; default: - PyErr_SetString(PyExc_TypeError, "peer.type_name not supported!"); + PyErr_SetString(PeerError, "peer.type_name not supported!"); Py_RETURN_NONE; } @@ -241,11 +246,11 @@ tgl_Peer_getlast_name (tgl_Peer *self, void *closure) break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: - PyErr_SetString(PyExc_TypeError, "Only peer.type_name == 'user' has last_name"); + PyErr_SetString(PeerError, "Only peer.type_name == 'user' has last_name"); Py_RETURN_NONE; break; default: - PyErr_SetString(PyExc_TypeError, "peer.type_name not supported!"); + PyErr_SetString(PeerError, "peer.type_name not supported!"); Py_RETURN_NONE; } @@ -266,11 +271,11 @@ tgl_Peer_getuser (tgl_Peer *self, void *closure) ret = (PyObject*)self; break; case TGL_PEER_CHAT: - PyErr_SetString(PyExc_TypeError, "Only peer.type_name == 'chat' does not have user"); + PyErr_SetString(PeerError, "Only peer.type_name == 'chat' does not have user"); Py_RETURN_NONE; break; default: - PyErr_SetString(PyExc_TypeError, "peer.type_name not supported!"); + PyErr_SetString(PeerError, "peer.type_name not supported!"); Py_RETURN_NONE; } @@ -448,7 +453,8 @@ tgl_Msg_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static int tgl_Msg_init(tgl_Msg *self, PyObject *args, PyObject *kwds) { - return 0; + PyErr_SetString(MsgError, "You cannot instantiate a tgl.Msg object, only the API can send them."); + return -1; } static PyObject * diff --git a/tg-test.py b/tg-test.py index a05454c..cb5fb10 100644 --- a/tg-test.py +++ b/tg-test.py @@ -24,45 +24,33 @@ def msg_cb(success, msg): HISTORY_QUERY_SIZE = 100 -def history_cb(msg_list, ptype, pid, success, msgs): +def history_cb(msg_list, peer, success, msgs): print(len(msgs)) msg_list.extend(msgs) print(len(msg_list)) if len(msgs) == HISTORY_QUERY_SIZE: - tgl.get_history(ptype, pid, len(msg_list), HISTORY_QUERY_SIZE, partial(history_cb, msg_list, ptype, pid)); + tgl.get_history(peer, len(msg_list), HISTORY_QUERY_SIZE, partial(history_cb, msg_list, peer)); def on_msg_receive(msg): if msg.out and not binlog_done: - return; - tgl.send_msg(tgl.Peer(97704886), "Test") - print("Peers {0}".format(msg.src.id)) - -""" -def on_msg_receive(msg): - if msg["out"] and not binlog_done: return; - if msg["to"]["id"] == our_id: # direct message - ptype = msg["from"]["type"] - pid = msg["from"]["id"] + if msg.dest.id == our_id: # direct message + peer = msg.src else: # chatroom - ptype = msg["to"]["type"] - pid = msg["to"]["id"] + peer = msg.dest - pp.pprint(msg) - - text = msg["text"] - - if text.startswith("!ping"): + if msg.text.startswith("!ping"): print("SENDING PONG") - tgl.send_msg(ptype, pid, "PONG!", msg_cb) + tgl.send_msg(peer, "PONG!", msg_cb) - if text.startswith("!loadhistory"): + if msg.text.startswith("!loadhistory"): msg_list = [] - tgl.get_history_ext(ptype, pid, 0, HISTORY_QUERY_SIZE, partial(history_cb, msg_list, ptype, pid)); -""" + tgl.get_history(peer, 0, HISTORY_QUERY_SIZE, partial(history_cb, msg_list, peer)); + + def on_secret_chat_update(peer, types): return "on_secret_chat_update" From 354aa64ae1797d8d7cc8df52358aad7406b0ce2a Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Wed, 20 May 2015 01:12:48 -0700 Subject: [PATCH 78/97] Implement reprs and fix dates --- python-tg.c | 6 --- python-types.c | 102 ++++++++++++++++++++++++++++++++++++++++++------- tg-test.py | 1 + 3 files changed, 90 insertions(+), 19 deletions(-) diff --git a/python-tg.c b/python-tg.c index 8e17d1e..7108609 100644 --- a/python-tg.c +++ b/python-tg.c @@ -109,12 +109,6 @@ PyObject *_py_chat_update; 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)); diff --git a/python-types.c b/python-types.c index 3e8f664..70caec4 100644 --- a/python-types.c +++ b/python-types.c @@ -20,6 +20,14 @@ extern PyObject *TglError; extern PyObject *PeerError; extern PyObject *MsgError; + +// Utility functions +PyObject* get_datetime(long datetime) +{ + return PyDateTime_FromTimestamp(Py_BuildValue("(O)", PyLong_FromLong(datetime))); +} + + // // tgl_peer_t wrapper // @@ -34,6 +42,7 @@ tgl_Peer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { tgl_Peer *self; + PyDateTime_IMPORT; self = (tgl_Peer *)type->tp_alloc(type, 0); return (PyObject *)self; } @@ -148,8 +157,7 @@ tgl_Peer_getuser_status(tgl_Peer *self, void *closure) case TGL_PEER_USER: ret = PyDict_New(); PyDict_SetItemString(ret, "online", self->peer->user.status.online? Py_True : Py_False); - PyDict_SetItemString(ret, "when", PyDateTime_FromTimestamp(Py_BuildValue("(O)", - PyLong_FromLong(self->peer->user.status.when)))); + PyDict_SetItemString(ret, "when", get_datetime(self->peer->user.status.when)); break; case TGL_PEER_CHAT: @@ -173,7 +181,10 @@ tgl_Peer_getphone (tgl_Peer *self, void *closure) switch(self->peer->id.type) { case TGL_PEER_USER: - ret = PyUnicode_FromString(self->peer->user.phone); + if(self->peer->user.phone) + ret = PyUnicode_FromString(self->peer->user.phone); + else + Py_RETURN_NONE; break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: @@ -196,7 +207,10 @@ tgl_Peer_getusername (tgl_Peer *self, void *closure) switch(self->peer->id.type) { case TGL_PEER_USER: - ret = PyUnicode_FromString(self->peer->user.username); + if(self->peer->user.username) + ret = PyUnicode_FromString(self->peer->user.username); + else + Py_RETURN_NONE; break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: @@ -219,7 +233,10 @@ tgl_Peer_getfirst_name (tgl_Peer *self, void *closure) switch(self->peer->id.type) { case TGL_PEER_USER: - ret = PyUnicode_FromString(self->peer->user.first_name); + if(self->peer->user.first_name) + ret = PyUnicode_FromString(self->peer->user.first_name); + else + Py_RETURN_NONE; break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: @@ -242,7 +259,10 @@ tgl_Peer_getlast_name (tgl_Peer *self, void *closure) switch(self->peer->id.type) { case TGL_PEER_USER: - ret = PyUnicode_FromString(self->peer->user.username); + if(self->peer->user.last_name) + ret = PyUnicode_FromString(self->peer->user.last_name); + else + Py_RETURN_NONE; break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: @@ -381,6 +401,39 @@ static PyMethodDef tgl_Peer_methods[] = { }; +static PyObject * +tgl_Peer_repr(tgl_Peer *self) +{ + PyObject *ret; + + switch(self->peer->id.type) { + case TGL_PEER_USER: + ret = PyUnicode_FromFormat("", + self->peer->id.id, + PyObject_GetAttrString((PyObject*)self, "username"), + PyObject_GetAttrString((PyObject*)self, "name"), + PyObject_GetAttrString((PyObject*)self, "first_name"), + PyObject_GetAttrString((PyObject*)self, "last_name"), + PyObject_GetAttrString((PyObject*)self, "phone") + ); + break; + case TGL_PEER_CHAT: + ret = PyUnicode_FromFormat("", + self->peer->id.id, self->peer->chat.print_title); + break; + case TGL_PEER_ENCR_CHAT: + ret = PyUnicode_FromFormat("", + self->peer->id.id, self->peer->encr_chat.print_name, + PyObject_GetAttrString((PyObject*)self, "user")); + break; + default: + ret = PyUnicode_FromFormat(""); + } + + return ret; +} + + PyTypeObject tgl_PeerType = { PyVarObject_HEAD_INIT(NULL, 0) "tgl.Peer", /* tp_name */ @@ -391,7 +444,7 @@ PyTypeObject tgl_PeerType = { 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ - 0, /* tp_repr */ + (reprfunc)tgl_Peer_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -446,6 +499,7 @@ tgl_Msg_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { tgl_Msg *self; + PyDateTime_IMPORT; self = (tgl_Msg *)type->tp_alloc(type, 0); return (PyObject *)self; } @@ -636,8 +690,7 @@ tgl_Msg_getdate (tgl_Msg *self, void *closure) PyObject *ret; if(self->msg->date) { - ret = PyDateTime_FromTimestamp(Py_BuildValue("(O)", - PyLong_FromLong(self->msg->date))); + ret = get_datetime(self->msg->date); } else { Py_RETURN_NONE; } @@ -667,8 +720,7 @@ tgl_Msg_getfwd_date (tgl_Msg *self, void *closure) PyObject *ret; if(tgl_get_peer_type (self->msg->fwd_from_id)) { - ret = PyDateTime_FromTimestamp(Py_BuildValue("(O)", - PyLong_FromLong(self->msg->fwd_date))); + ret = get_datetime(self->msg->fwd_date); } else { Py_RETURN_NONE; } @@ -712,7 +764,31 @@ tgl_Msg_getreply_id (tgl_Msg *self, void *closure) return ret; } +static PyObject * +tgl_Msg_repr(tgl_Msg *self) +{ + PyObject *ret; + ret = PyUnicode_FromFormat("", + self->msg->id, self->msg->flags, + PyObject_GetAttrString((PyObject*)self, "mention"), + PyObject_GetAttrString((PyObject*)self, "out"), + PyObject_GetAttrString((PyObject*)self, "unread"), + PyObject_GetAttrString((PyObject*)self, "service"), + PyObject_GetAttrString((PyObject*)self, "src"), + PyObject_GetAttrString((PyObject*)self, "dest"), + PyObject_GetAttrString((PyObject*)self, "text"), + PyObject_GetAttrString((PyObject*)self, "media"), + PyObject_GetAttrString((PyObject*)self, "date"), + PyObject_GetAttrString((PyObject*)self, "fwd_src"), + PyObject_GetAttrString((PyObject*)self, "fwd_date"), + PyObject_GetAttrString((PyObject*)self, "reply_id"), + PyObject_GetAttrString((PyObject*)self, "reply") + ); + + return ret; +} static PyGetSetDef tgl_Msg_getseters[] = { @@ -753,7 +829,7 @@ PyTypeObject tgl_MsgType = { 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ - 0, /* tp_repr */ + (reprfunc)tgl_Msg_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -764,7 +840,7 @@ PyTypeObject tgl_MsgType = { 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ - "tgl Message", /* tp_doc */ + "tgl Message", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ diff --git a/tg-test.py b/tg-test.py index cb5fb10..4750920 100644 --- a/tg-test.py +++ b/tg-test.py @@ -42,6 +42,7 @@ def on_msg_receive(msg): else: # chatroom peer = msg.dest + print(msg) if msg.text.startswith("!ping"): print("SENDING PONG") tgl.send_msg(peer, "PONG!", msg_cb) From f1eda8acff4de90fa3443478e66fff81e48a20ce Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Wed, 20 May 2015 01:28:23 -0700 Subject: [PATCH 79/97] Start test suite, WIP --- tg-test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tg-test.py b/tg-test.py index 4750920..e9ce991 100644 --- a/tg-test.py +++ b/tg-test.py @@ -42,7 +42,7 @@ def on_msg_receive(msg): else: # chatroom peer = msg.dest - print(msg) + pp.pprint(msg) if msg.text.startswith("!ping"): print("SENDING PONG") tgl.send_msg(peer, "PONG!", msg_cb) From 5576d7a094e5c95f4306edfaea09d242c27b8e26 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Wed, 20 May 2015 10:55:06 -0700 Subject: [PATCH 80/97] Python build fixes --- Makefile.in | 2 +- ax_python.m4 | 3 +-- configure | 6 ++---- loop.c | 4 ++++ python-tg.c | 2 +- python-types.c | 12 +++++++++--- 6 files changed, 18 insertions(+), 11 deletions(-) diff --git a/Makefile.in b/Makefile.in index c3116f3..eed8ae9 100644 --- a/Makefile.in +++ b/Makefile.in @@ -18,7 +18,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 ${OBJ}/json-tg.o ${OBJ}/python-tg.o +TG_OBJECTS=${OBJ}/main.o ${OBJ}/loop.o ${OBJ}/interface.o ${OBJ}/lua-tg.o ${OBJ}/json-tg.o ${OBJ}/python-tg.o ${OBJ}/python-types.o INCLUDE=-I. -I${srcdir} -I${srcdir}/tgl CC=@CC@ diff --git a/ax_python.m4 b/ax_python.m4 index 1695480..28c7bb1 100644 --- a/ax_python.m4 +++ b/ax_python.m4 @@ -56,8 +56,7 @@ AC_DEFUN([AX_PYTHON], [AC_MSG_CHECKING(for python build information) AC_MSG_RESULT([]) -for python in python3.4 python3.3 python3.2 python3.1 python2.7 python2.6 python3, python2, python; do - +for python in python3.4 python3.3 python3.2 python3.1 python3 python2.7 python2.6 python2 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 3eae742..d8778f0 100755 --- a/configure +++ b/configure @@ -5947,8 +5947,7 @@ $as_echo "enabled" >&6; } $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.4 python3.3 python3.2 python3.1 python2.7 python2.6 python3, python2, python; do - +for python in python3.4 python3.3 python3.2 python3.1 python3 python2.7 python2.6 python2 python; do for ac_prog in $python do # Extract the first word of "$ac_prog", so it can be a program name with args. @@ -6139,8 +6138,7 @@ $as_echo "enabled" >&6; } $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.4 python3.3 python3.2 python3.1 python2.7 python2.6 python3, python2, python; do - +for python in python3.4 python3.3 python3.2 python3.1 python3 python2.7 python2.6 python2 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/loop.c b/loop.c index feabf25..db1ae11 100644 --- a/loop.c +++ b/loop.c @@ -56,8 +56,12 @@ #include "interface.h" #include "telegram.h" #include "loop.h" +#if USE_LUA #include "lua-tg.h" +#endif +#if USE_PYTHON #include "python-tg.h" +#endif #include #include #include diff --git a/python-tg.c b/python-tg.c index 7108609..25d3b5a 100644 --- a/python-tg.c +++ b/python-tg.c @@ -24,7 +24,6 @@ #ifdef USE_PYTHON #include "python-tg.h" -#endif #include #include @@ -1251,3 +1250,4 @@ void py_init (const char *file) { logprintf("Python Initialized\n"); } +#endif diff --git a/python-types.c b/python-types.c index 70caec4..db2df62 100644 --- a/python-types.c +++ b/python-types.c @@ -1,4 +1,9 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef USE_PYTHON #include #include #include @@ -120,10 +125,9 @@ tgl_Peer_getuser_id (tgl_Peer *self, void *closure) static PyObject * tgl_Peer_getuser_list (tgl_Peer *self, void *closure) { - PyObject *ret, *peer; + PyObject *ret; int i; struct tgl_chat_user *user_list; - struct tgl_user *user; switch(self->peer->id.type) { case TGL_PEER_CHAT: @@ -382,7 +386,7 @@ tgl_Peer_send_msg (tgl_Peer *self, PyObject *args, PyObject *kwargs) else api_call = Py_BuildValue("Os", (PyObject*) self, message); - Py_XINCREF(Py_None); + Py_INCREF(Py_None); Py_XINCREF(api_call); return py_send_msg(Py_None, api_call); @@ -868,3 +872,5 @@ tgl_Msg_FromTglMsg(struct tgl_message *msg) { self->msg = msg; return (PyObject *) self; } + +#endif From faec9c9251d8b05d7e27cda89800a3879764f914 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Wed, 20 May 2015 12:41:55 -0700 Subject: [PATCH 81/97] Fix autoconf script for python detection. --- ax_python.m4 | 2 ++ configure | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/ax_python.m4 b/ax_python.m4 index 28c7bb1..9702193 100644 --- a/ax_python.m4 +++ b/ax_python.m4 @@ -71,6 +71,8 @@ if test x$ax_python_bin != x; then fi fi fi +unset ac_cv_prog_PYTHON_BIN +unset PYTHON_BIN done if test x$ax_python_bin = x; then ax_python_bin=no diff --git a/configure b/configure index d8778f0..93723f5 100755 --- a/configure +++ b/configure @@ -6077,6 +6077,8 @@ fi fi fi fi +unset ac_cv_prog_PYTHON_BIN +unset PYTHON_BIN done if test x$ax_python_bin = x; then ax_python_bin=no @@ -6268,6 +6270,8 @@ fi fi fi fi +unset ac_cv_prog_PYTHON_BIN +unset PYTHON_BIN done if test x$ax_python_bin = x; then ax_python_bin=no From 03bd7fbc50232177bd1dc1d39a202cf11931e5dd Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Wed, 20 May 2015 15:16:16 -0700 Subject: [PATCH 82/97] Added error handling to failed calls to get peer. --- python-types.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/python-types.c b/python-types.c index db2df62..2092e5f 100644 --- a/python-types.c +++ b/python-types.c @@ -588,7 +588,14 @@ tgl_Msg_getsrc (tgl_Msg *self, void *closure) PyObject *ret; if(tgl_get_peer_type (self->msg->from_id)) { - ret = tgl_Peer_FromTglPeer(tgl_peer_get (TLS, self->msg->from_id)); + tgl_peer_t *peer = tgl_peer_get (TLS, self->msg->from_id); + if(peer) + ret = tgl_Peer_FromTglPeer(peer); + else { + PyErr_SetString(PeerError, "Cannot Retrieve Peer. Internal tgl error"); + Py_RETURN_NONE; + } + } else { Py_RETURN_NONE; } @@ -603,7 +610,13 @@ tgl_Msg_getdest (tgl_Msg *self, void *closure) PyObject *ret; if(tgl_get_peer_type (self->msg->to_id)) { - ret = tgl_Peer_FromTglPeer(tgl_peer_get (TLS, self->msg->to_id)); + tgl_peer_t *peer = tgl_peer_get (TLS, self->msg->to_id); + if(peer) + ret = tgl_Peer_FromTglPeer(peer); + else { + PyErr_SetString(PeerError, "Cannot Retrieve Peer. Internal tgl error"); + Py_RETURN_NONE; + } } else { Py_RETURN_NONE; } @@ -709,7 +722,13 @@ tgl_Msg_getfwd_src (tgl_Msg *self, void *closure) PyObject *ret; if(tgl_get_peer_type (self->msg->fwd_from_id)) { - ret = tgl_Peer_FromTglPeer(tgl_peer_get (TLS, self->msg->fwd_from_id)); + tgl_peer_t *peer = tgl_peer_get (TLS, self->msg->fwd_from_id); + if(peer) + ret = tgl_Peer_FromTglPeer(peer); + else { + PyErr_SetString(PeerError, "Cannot Retrieve Peer. Internal tgl error"); + Py_RETURN_NONE; + } } else { Py_RETURN_NONE; } From 99bf18283d8c3a6d2d570b648a7f6a0f28d35149 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Thu, 21 May 2015 11:17:01 -0700 Subject: [PATCH 83/97] Add Python version to the tg startup banner. --- main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main.c b/main.c index 5b477ee..3f75831 100644 --- a/main.c +++ b/main.c @@ -960,6 +960,9 @@ int main (int argc, char **argv) { "This is free software, and you are welcome to redistribute it\n" "under certain conditions; type `show_license' for details.\n" "Telegram-cli uses libtgl version " TGL_VERSION "\n" +#ifdef USE_PYTHON + "Telegram-cli uses libpython version " PY_VERSION "\n" +#endif ); } running_for_first_time (); From ce4d9aff006143238cace79ac6c78d879c6a9931 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Thu, 21 May 2015 23:27:28 -0700 Subject: [PATCH 84/97] Add additional peer functions --- python-types.c | 326 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 313 insertions(+), 13 deletions(-) diff --git a/python-types.c b/python-types.c index 2092e5f..a3283bd 100644 --- a/python-types.c +++ b/python-types.c @@ -391,16 +391,316 @@ tgl_Peer_send_msg (tgl_Peer *self, PyObject *args, PyObject *kwargs) return py_send_msg(Py_None, api_call); } else { + PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } +static PyObject * +tgl_Peer_send_typing (tgl_Peer *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"callback", NULL}; + + PyObject *callback = NULL; + + if(PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &callback)) { + PyObject *api_call; + + if(callback) + api_call = Py_BuildValue("OO", (PyObject*) self, callback); + else + api_call = Py_BuildValue("O", (PyObject*) self); + + Py_INCREF(Py_None); + Py_XINCREF(api_call); + + return py_send_typing(Py_None, api_call); + } else { + PyErr_Print(); + Py_XINCREF(Py_False); + return Py_False; + } + +} + +static PyObject * +tgl_Peer_send_typing_abort (tgl_Peer *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"callback", NULL}; + + PyObject *callback = NULL; + + if(PyArg_ParseTupleAndKeywords(args, kwargs, "O!|O", kwlist, &callback)) { + PyObject *api_call; + + if(callback) + api_call = Py_BuildValue("OO", (PyObject*) self, callback); + else + api_call = Py_BuildValue("O", (PyObject*) self); + + Py_INCREF(Py_None); + Py_XINCREF(api_call); + + return py_send_typing_abort(Py_None, api_call); + } else { + PyErr_Print(); + Py_XINCREF(Py_False); + return Py_False; + } + +} + +static PyObject * +tgl_Peer_rename_chat (tgl_Peer *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"peer", "title", "callback", NULL}; + + char * title; + PyObject *callback = NULL; + + if(self->peer->id.type != TGL_PEER_CHAT) { + PyErr_SetString(PeerError, "Only a chat peer can be renamed"); + Py_XINCREF(Py_False); + return Py_False; + } + + if(PyArg_ParseTupleAndKeywords(args, kwargs, "s|O", kwlist, &title, &callback)) { + PyObject *api_call; + + if(callback) + api_call = Py_BuildValue("OsO", (PyObject*) self, title, callback); + else + api_call = Py_BuildValue("Os", (PyObject*) self, title); + + Py_INCREF(Py_None); + Py_XINCREF(api_call); + + return py_rename_chat(Py_None, api_call); + } else { + PyErr_Print(); + Py_XINCREF(Py_False); + return Py_False; + } + +} + +static PyObject * +tgl_Peer_send_photo (tgl_Peer *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"filename", "callback", NULL}; + + char *filename; + PyObject *callback = NULL; + + if(PyArg_ParseTupleAndKeywords(args, kwargs, "s|O", kwlist, &filename, &callback)) { + PyObject *api_call; + + if(callback) + api_call = Py_BuildValue("OsO", (PyObject*) self, filename, callback); + else + api_call = Py_BuildValue("Os", (PyObject*) self, filename); + + Py_INCREF(Py_None); + Py_XINCREF(api_call); + + return py_send_photo(Py_None, api_call); + } else { + PyErr_Print(); + Py_XINCREF(Py_False); + return Py_False; + } + +} + +static PyObject * +tgl_Peer_send_video (tgl_Peer *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"filename", "callback", NULL}; + + char *filename; + PyObject *callback = NULL; + + if(PyArg_ParseTupleAndKeywords(args, kwargs, "s|O", kwlist, &filename, &callback)) { + PyObject *api_call; + + if(callback) + api_call = Py_BuildValue("OsO", (PyObject*) self, filename, callback); + else + api_call = Py_BuildValue("Os", (PyObject*) self, filename); + + Py_INCREF(Py_None); + Py_XINCREF(api_call); + + return py_send_video(Py_None, api_call); + } else { + PyErr_Print(); + Py_XINCREF(Py_False); + return Py_False; + } + +} + +static PyObject * +tgl_Peer_send_audio (tgl_Peer *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"filename", "callback", NULL}; + + char *filename; + PyObject *callback = NULL; + + if(PyArg_ParseTupleAndKeywords(args, kwargs, "s|O", kwlist, &filename, &callback)) { + PyObject *api_call; + + if(callback) + api_call = Py_BuildValue("OsO", (PyObject*) self, filename, callback); + else + api_call = Py_BuildValue("Os", (PyObject*) self, filename); + + Py_INCREF(Py_None); + Py_XINCREF(api_call); + + return py_send_audio(Py_None, api_call); + } else { + PyErr_Print(); + Py_XINCREF(Py_False); + return Py_False; + } + +} + +static PyObject * +tgl_Peer_send_document (tgl_Peer *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"filename", "callback", NULL}; + + char *filename; + PyObject *callback = NULL; + + if(PyArg_ParseTupleAndKeywords(args, kwargs, "s|O", kwlist, &filename, &callback)) { + PyObject *api_call; + + if(callback) + api_call = Py_BuildValue("OsO", (PyObject*) self, filename, callback); + else + api_call = Py_BuildValue("Os", (PyObject*) self, filename); + + Py_INCREF(Py_None); + Py_XINCREF(api_call); + + return py_send_document(Py_None, api_call); + } else { + PyErr_Print(); + Py_XINCREF(Py_False); + return Py_False; + } + +} + +static PyObject * +tgl_Peer_send_file (tgl_Peer *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"filename", "callback", NULL}; + + char *filename; + PyObject *callback = NULL; + + if(PyArg_ParseTupleAndKeywords(args, kwargs, "s|O", kwlist, &filename, &callback)) { + PyObject *api_call; + + if(callback) + api_call = Py_BuildValue("OsO", (PyObject*) self, filename, callback); + else + api_call = Py_BuildValue("Os", (PyObject*) self, filename); + + Py_INCREF(Py_None); + Py_XINCREF(api_call); + + return py_send_file(Py_None, api_call); + } else { + PyErr_Print(); + Py_XINCREF(Py_False); + return Py_False; + } + +} + +static PyObject * +tgl_Peer_send_text (tgl_Peer *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"filename", "callback", NULL}; + + char *filename; + PyObject *callback = NULL; + + if(PyArg_ParseTupleAndKeywords(args, kwargs, "s|O", kwlist, &filename, &callback)) { + PyObject *api_call; + + if(callback) + api_call = Py_BuildValue("OsO", (PyObject*) self, filename, callback); + else + api_call = Py_BuildValue("Os", (PyObject*) self, filename); + + Py_INCREF(Py_None); + Py_XINCREF(api_call); + + return py_send_text(Py_None, api_call); + } else { + PyErr_Print(); + Py_XINCREF(Py_False); + return Py_False; + } + +} + +static PyObject * +tgl_Peer_chat_set_photo (tgl_Peer *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"peer", "filename", "callback", NULL}; + + char * filename; + PyObject *callback = NULL; + + if(self->peer->id.type != TGL_PEER_CHAT) { + PyErr_SetString(PeerError, "Only a chat peer can have a chat photo set."); + Py_XINCREF(Py_False); + return Py_False; + } + + if(PyArg_ParseTupleAndKeywords(args, kwargs, "s|O", kwlist, &filename, &callback)) { + PyObject *api_call; + + if(callback) + api_call = Py_BuildValue("OsO", (PyObject*) self, filename, callback); + else + api_call = Py_BuildValue("Os", (PyObject*) self, filename); + + Py_INCREF(Py_None); + Py_XINCREF(api_call); + + return py_chat_set_photo(Py_None, api_call); + } else { + PyErr_Print(); + Py_XINCREF(Py_False); + return Py_False; + } + +} static PyMethodDef tgl_Peer_methods[] = { - {"send_msg", (PyCFunction)tgl_Peer_send_msg, METH_VARARGS | METH_KEYWORDS, - "Send a message to peer object"}, + {"send_msg", (PyCFunction)tgl_Peer_send_msg, METH_VARARGS | METH_KEYWORDS, + "Send a message to peer object"}, + {"send_typing", (PyCFunction)tgl_Peer_send_typing, METH_VARARGS | METH_KEYWORDS, ""}, + {"send_typing_abort", (PyCFunction)tgl_Peer_send_typing_abort, METH_VARARGS | METH_KEYWORDS, ""}, + {"rename_chat", (PyCFunction)tgl_Peer_rename_chat, METH_VARARGS | METH_KEYWORDS, ""}, + {"send_photo", (PyCFunction)tgl_Peer_send_photo, METH_VARARGS | METH_KEYWORDS, ""}, + {"send_video", (PyCFunction)tgl_Peer_send_video, METH_VARARGS | METH_KEYWORDS, ""}, + {"send_audio", (PyCFunction)tgl_Peer_send_audio, METH_VARARGS | METH_KEYWORDS, ""}, + {"send_file", (PyCFunction)tgl_Peer_send_file, METH_VARARGS | METH_KEYWORDS, ""}, + {"send_document", (PyCFunction)tgl_Peer_send_document, METH_VARARGS | METH_KEYWORDS, ""}, + {"send_text", (PyCFunction)tgl_Peer_send_text, METH_VARARGS | METH_KEYWORDS, ""}, + {"chat_set_photo", (PyCFunction)tgl_Peer_chat_set_photo, METH_VARARGS | METH_KEYWORDS, ""}, {NULL} /* Sentinel */ }; @@ -409,26 +709,26 @@ static PyObject * tgl_Peer_repr(tgl_Peer *self) { PyObject *ret; - + switch(self->peer->id.type) { case TGL_PEER_USER: ret = PyUnicode_FromFormat("", - self->peer->id.id, - PyObject_GetAttrString((PyObject*)self, "username"), - PyObject_GetAttrString((PyObject*)self, "name"), - PyObject_GetAttrString((PyObject*)self, "first_name"), - PyObject_GetAttrString((PyObject*)self, "last_name"), - PyObject_GetAttrString((PyObject*)self, "phone") - ); + self->peer->id.id, + PyObject_GetAttrString((PyObject*)self, "username"), + PyObject_GetAttrString((PyObject*)self, "name"), + PyObject_GetAttrString((PyObject*)self, "first_name"), + PyObject_GetAttrString((PyObject*)self, "last_name"), + PyObject_GetAttrString((PyObject*)self, "phone") + ); break; case TGL_PEER_CHAT: ret = PyUnicode_FromFormat("", - self->peer->id.id, self->peer->chat.print_title); + self->peer->id.id, self->peer->chat.print_title); break; case TGL_PEER_ENCR_CHAT: ret = PyUnicode_FromFormat("", - self->peer->id.id, self->peer->encr_chat.print_name, - PyObject_GetAttrString((PyObject*)self, "user")); + self->peer->id.id, self->peer->encr_chat.print_name, + PyObject_GetAttrString((PyObject*)self, "user")); break; default: ret = PyUnicode_FromFormat(""); From ce34da49f4e76d8a2b21fc55d31ce510111491e2 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 23 May 2015 17:09:08 -0700 Subject: [PATCH 85/97] Comeplete tgl.Peer methods. --- python-types.c | 233 ++++++++++++++++++++++++++++++++++++++++++++++++- tg-test.py | 13 ++- 2 files changed, 236 insertions(+), 10 deletions(-) diff --git a/python-types.c b/python-types.c index a3283bd..c073cdb 100644 --- a/python-types.c +++ b/python-types.c @@ -25,6 +25,8 @@ extern PyObject *TglError; extern PyObject *PeerError; extern PyObject *MsgError; +// Forward type declarations +PyTypeObject tgl_PeerType; // Utility functions PyObject* get_datetime(long datetime) @@ -432,7 +434,7 @@ tgl_Peer_send_typing_abort (tgl_Peer *self, PyObject *args, PyObject *kwargs) PyObject *callback = NULL; - if(PyArg_ParseTupleAndKeywords(args, kwargs, "O!|O", kwlist, &callback)) { + if(PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &callback)) { PyObject *api_call; if(callback) @@ -455,7 +457,7 @@ tgl_Peer_send_typing_abort (tgl_Peer *self, PyObject *args, PyObject *kwargs) static PyObject * tgl_Peer_rename_chat (tgl_Peer *self, PyObject *args, PyObject *kwargs) { - static char *kwlist[] = {"peer", "title", "callback", NULL}; + static char *kwlist[] = {"title", "callback", NULL}; char * title; PyObject *callback = NULL; @@ -657,7 +659,7 @@ tgl_Peer_send_text (tgl_Peer *self, PyObject *args, PyObject *kwargs) static PyObject * tgl_Peer_chat_set_photo (tgl_Peer *self, PyObject *args, PyObject *kwargs) { - static char *kwlist[] = {"peer", "filename", "callback", NULL}; + static char *kwlist[] = {"filename", "callback", NULL}; char * filename; PyObject *callback = NULL; @@ -688,6 +690,222 @@ tgl_Peer_chat_set_photo (tgl_Peer *self, PyObject *args, PyObject *kwargs) } +static PyObject * +tgl_Peer_chat_add_user (tgl_Peer *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"peer", "callback", NULL}; + + PyObject *peer; + PyObject *callback = NULL; + + if(self->peer->id.type != TGL_PEER_CHAT) { + PyErr_SetString(PeerError, "Only a chat peer can have a user added."); + Py_XINCREF(Py_False); + return Py_False; + } + + if(PyArg_ParseTupleAndKeywords(args, kwargs, "O!|O", kwlist, &tgl_PeerType, &peer, &callback)) { + PyObject *api_call; + + if(callback) + api_call = Py_BuildValue("OOO", (PyObject*) self, peer, callback); + else + api_call = Py_BuildValue("OO", (PyObject*) self, peer); + + Py_INCREF(Py_None); + Py_XINCREF(api_call); + + return py_chat_add_user(Py_None, api_call); + } else { + PyErr_Print(); + Py_XINCREF(Py_False); + return Py_False; + } + +} + +static PyObject * +tgl_Peer_chat_del_user (tgl_Peer *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"peer", "callback", NULL}; + + PyObject *peer; + PyObject *callback = NULL; + + if(self->peer->id.type != TGL_PEER_CHAT) { + PyErr_SetString(PeerError, "Only a chat peer can have a user deleted."); + Py_XINCREF(Py_False); + return Py_False; + } + + if(PyArg_ParseTupleAndKeywords(args, kwargs, "O!|O", kwlist, &tgl_PeerType, &peer, &callback)) { + PyObject *api_call; + + if(callback) + api_call = Py_BuildValue("OOO", (PyObject*) self, peer, callback); + else + api_call = Py_BuildValue("OO", (PyObject*) self, peer); + + Py_INCREF(Py_None); + Py_XINCREF(api_call); + + return py_chat_del_user(Py_None, api_call); + } else { + PyErr_Print(); + Py_XINCREF(Py_False); + return Py_False; + } + +} + +static PyObject * +tgl_Peer_history (tgl_Peer *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"offset", "limit", "callback", NULL}; + + int offset, limit; + PyObject *callback = NULL; + + if(PyArg_ParseTupleAndKeywords(args, kwargs, "ii|O", kwlist, &offset, &limit, &callback)) { + PyObject *api_call; + + if(callback) + api_call = Py_BuildValue("OiiO", (PyObject*) self, offset, limit, callback); + else + api_call = Py_BuildValue("Oii", (PyObject*) self, offset, limit); + + Py_INCREF(Py_None); + Py_XINCREF(api_call); + + return py_history(Py_None, api_call); + } else { + PyErr_Print(); + Py_XINCREF(Py_False); + return Py_False; + } + +} + +static PyObject * +tgl_Peer_info (tgl_Peer *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"callback", NULL}; + + PyObject *callback = NULL; + + if(self->peer->id.type == TGL_PEER_ENCR_CHAT) { + PyErr_SetString(PeerError, "Secret chats currently have no info."); + Py_XINCREF(Py_False); + return Py_False; + } + + if(PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &callback)) { + PyObject *api_call; + + if(callback) + api_call = Py_BuildValue("OO", (PyObject*) self, callback); + else + api_call = Py_None; + + Py_INCREF(Py_None); + Py_XINCREF(api_call); + if(self->peer->id.type == TGL_PEER_USER) + return py_user_info(Py_None, api_call); + else + return py_chat_info(Py_None, api_call); + } else { + PyErr_Print(); + Py_XINCREF(Py_False); + return Py_False; + } + +} + +static PyObject * +tgl_Peer_send_contact (tgl_Peer *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"phone", "first_name", "last_name", "callback", NULL}; + + char *phone, *first_name, *last_name; + PyObject *callback = NULL; + + if(PyArg_ParseTupleAndKeywords(args, kwargs, "sss|O", kwlist, &phone, &first_name, &last_name, &callback)) { + PyObject *api_call; + + if(callback) + api_call = Py_BuildValue("Osss", (PyObject*) self, phone, first_name, last_name, callback); + else + api_call = Py_BuildValue("Os", (PyObject*) self, phone, first_name, last_name); + + Py_INCREF(Py_None); + Py_XINCREF(api_call); + + return py_send_contact(Py_None, api_call); + } else { + PyErr_Print(); + Py_XINCREF(Py_False); + return Py_False; + } + +} + + +static PyObject * +tgl_Peer_send_location (tgl_Peer *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"latitude", "longitude", "callback", NULL}; + + PyObject *latitude, *longitude; + PyObject *callback = NULL; + + if(PyArg_ParseTupleAndKeywords(args, kwargs, "O!O!|O", kwlist, &PyFloat_Type, + &latitude, &PyFloat_Type, &longitude, &callback)) { + PyObject *api_call; + + if(callback) + api_call = Py_BuildValue("OOOO", (PyObject*) self, latitude, longitude, callback); + else + api_call = Py_BuildValue("OOO", (PyObject*) self, latitude, longitude); + + Py_INCREF(Py_None); + Py_XINCREF(api_call); + + return py_send_location(Py_None, api_call); + } else { + PyErr_Print(); + Py_XINCREF(Py_False); + return Py_False; + } + +} + +static PyObject * +tgl_Peer_mark_read (tgl_Peer *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"callback", NULL}; + + PyObject *callback = NULL; + + if(PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &callback)) { + PyObject *api_call; + + if(callback) + api_call = Py_BuildValue("OO", (PyObject*) self, callback); + else + api_call = Py_BuildValue("O", (PyObject*) self); + + Py_INCREF(Py_None); + Py_XINCREF(api_call); + + return py_mark_read(Py_None, api_call); + } else { + PyErr_Print(); + Py_XINCREF(Py_False); + return Py_False; + } + +} + static PyMethodDef tgl_Peer_methods[] = { {"send_msg", (PyCFunction)tgl_Peer_send_msg, METH_VARARGS | METH_KEYWORDS, "Send a message to peer object"}, @@ -701,6 +919,13 @@ static PyMethodDef tgl_Peer_methods[] = { {"send_document", (PyCFunction)tgl_Peer_send_document, METH_VARARGS | METH_KEYWORDS, ""}, {"send_text", (PyCFunction)tgl_Peer_send_text, METH_VARARGS | METH_KEYWORDS, ""}, {"chat_set_photo", (PyCFunction)tgl_Peer_chat_set_photo, METH_VARARGS | METH_KEYWORDS, ""}, + {"info", (PyCFunction)tgl_Peer_info, METH_VARARGS | METH_KEYWORDS, ""}, + {"history", (PyCFunction)tgl_Peer_history, METH_VARARGS | METH_KEYWORDS, ""}, + {"chat_add_user", (PyCFunction)tgl_Peer_chat_add_user, METH_VARARGS | METH_KEYWORDS, ""}, + {"chat_del_user", (PyCFunction)tgl_Peer_chat_del_user, METH_VARARGS | METH_KEYWORDS, ""}, + {"send_contact", (PyCFunction)tgl_Peer_send_contact, METH_VARARGS | METH_KEYWORDS, ""}, + {"send_location", (PyCFunction)tgl_Peer_send_location, METH_VARARGS | METH_KEYWORDS, ""}, + {"mark_read", (PyCFunction)tgl_Peer_mark_read, METH_VARARGS | METH_KEYWORDS, ""}, {NULL} /* Sentinel */ }; @@ -1137,6 +1362,8 @@ static PyMemberDef tgl_Msg_members[] = { {NULL} /* Sentinel */ }; + + static PyMethodDef tgl_Msg_methods[] = { {NULL} /* Sentinel */ }; diff --git a/tg-test.py b/tg-test.py index e9ce991..fddd387 100644 --- a/tg-test.py +++ b/tg-test.py @@ -16,7 +16,7 @@ def on_get_difference_end(): def on_our_id(id): our_id = id - return "Set ID: " + str(our_id) + return "Set ID: " + str(our_id) def msg_cb(success, msg): pp.pprint(success) @@ -31,7 +31,9 @@ def history_cb(msg_list, peer, success, msgs): if len(msgs) == HISTORY_QUERY_SIZE: tgl.get_history(peer, len(msg_list), HISTORY_QUERY_SIZE, partial(history_cb, msg_list, peer)); - + +def cb(success): + print(success) def on_msg_receive(msg): if msg.out and not binlog_done: @@ -45,11 +47,8 @@ def on_msg_receive(msg): pp.pprint(msg) if msg.text.startswith("!ping"): print("SENDING PONG") - tgl.send_msg(peer, "PONG!", msg_cb) - - if msg.text.startswith("!loadhistory"): - msg_list = [] - tgl.get_history(peer, 0, HISTORY_QUERY_SIZE, partial(history_cb, msg_list, peer)); + peer.send_msg("PONG!", msg_cb) + peer.send_contact(msg.src.phone, msg.src.first_name, msg.src.last_name , cb) def on_secret_chat_update(peer, types): From dbdf81cfbeb70e8a2b0a0e987f2c0603f09c2582 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 23 May 2015 17:25:36 -0700 Subject: [PATCH 86/97] Add documentation. --- README-PY | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 README-PY diff --git a/README-PY b/README-PY new file mode 100644 index 0000000..ae4467b --- /dev/null +++ b/README-PY @@ -0,0 +1,95 @@ +To use python with client you should write python script. You can specify it from config ("python_script" option) or from command_line [-Z]. + +You should set the following callbacks in your script: + tgl.on_binlog_replay_end() - it is called when replay of old events end. Any updates prior this call were already received by this client + some time ago. + + tgl.on_get_difference_end() - it is called after first get_difference call. So we received all updates after last client execute. + + tgl.on_our_id(our_id) - Informs about id of currently logged in user. + + tgl.on_msg_receive(msg) - it is called when we receive new msg (!! may be called before on_binlog_replay_end, than it is old msg). + + tgl.on_user_update(peer, what_changed) - updated info about user. what_changed is array of strings. + tgl.on_chat_update(peer, what_changed) - updated info about user. what_changed is array of strings. + tgl.on_secret_chat_update(peer, what_changed) - updated info about user. what_changed is array of strings. + + + +Also, you can call several functions. Each this function last two arguments, are callback, which is a python function implementing the callback from the function. +These functions may return false immidiately if something is bad with args, or return true and call cb_function in future. +The callback function should have one arguments: first success (True or False), and the rest depends on the call. +Functions that require a peer type other than what is passed will raise tgl.PeerError. + + +Function_list (arguments are listed aside from callback, import tgl for access) : + tgl.get_contact_list () + tgl.get_dialog_list () + + tgl.rename_chat (peer, new_name) + tgl.chat_set_photo (peer, file) + + tgl.send_typing (peer) + tgl.send_typing_abort (peer) + + tgl.send_msg (peer, text) + tgl.fwd_msg (peer, msg) + + tgl.send_photo (peer, file) + tgl.send_video (peer, file) + tgl.send_audio (peer, file) + tgl.send_document (peer, file) + tgl.send_text (peer, file) + + tgl.load_photo(msg) + tgl.load_video(msg) + tgl.load_video_thumb(msg) + tgl.load_audio(msg) + tgl.load_document(msg) + tgl.load_document_thumb(msg) + + tgl.info (peer) + + tgl.get_history (peer, limit) + + tgl.chat_add_user (peer, user) + tgl.chat_del_user (peer, user) + + tgl.add_contact (phone, first_name, last_name) + tgl.rename_contact (phone, first_name, last_name) + + tgl.msg_search (peer, text) + tgl.msg_global_search (text) + + tgl.mark_read (peer) + + tgl.set_profile_photo (file) + + tgl.create_secret_chat (user) + tgl.create_group_chat (peer, name) + + tgl.delete_msg (msg) + tgl.restore_msg (msg_id) + + tgl.status_online () + tgl.status_offline () + + tgl.send_location (peer, latitude, longitude) + +Additionally, the tgl.Peer object has the following direct methods: + peer.rename_chat(new_name) + peer.chat_set_photo(file) + peer.send_typing() + peer.send_typing_abort() + peer.send_msg(text) + peer.send_photo(file) + peer.send_video(file) + peer.send_document(file) + peer.send_text(file) + peer.info() + peer.history(limit, offset) + peer.add_user(peer) + peer.del_user(peer) + peer.search(text) + peer.mark_read() + peer.send_location(latitude, longitude) From 16a12a73988b82d45104bf5b2ef4a1cb50429abd Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 23 May 2015 17:29:17 -0700 Subject: [PATCH 87/97] Adding python to travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index a299f36..809110d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,7 @@ install: - sudo apt-get install libreadline6-dev - sudo apt-get install libssl-dev - sudo apt-get install liblua5.2-dev lua5.2 + - sudo apt-get install libpython3-dev python3 - sudo apt-get install libevent-dev - sudo apt-get install libjansson-dev From 9d9f89a1f936fa2743605b245662bd9ea66109fb Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 23 May 2015 17:37:29 -0700 Subject: [PATCH 88/97] Adding python to README.md --- README.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index cb36c98..0853582 100644 --- a/README.md +++ b/README.md @@ -24,30 +24,34 @@ Clone GitHub Repository git clone --recursive https://github.com/vysheng/tg.git && cd tg +### Python Suppoer + +Python support is currently limited to Python 2.7 or Python 3.1+. Other versions may work but are not tested. + #### Linux and BSDs -Install libs: readline, openssl and (if you want to use config) libconfig, liblua and libjansson. -If you do not want to use them pass options --disable-libconfig, --disable-liblua and --disable-json respectively. +Install libs: readline, openssl and (if you want to use config) libconfig, liblua, python and libjansson. +If you do not want to use them pass options --disable-libconfig, --disable-liblua, --disable-python and --disable-json respectively. On Ubuntu/Debian use: - sudo apt-get install libreadline-dev libconfig-dev libssl-dev lua5.2 liblua5.2-dev libevent-dev libjansson-dev make + sudo apt-get install libreadline-dev libconfig-dev libssl-dev lua5.2 liblua5.2-dev libevent-dev libjansson-dev libpython-dev make On gentoo: - sudo emerge -av sys-libs/readline dev-libs/libconfig dev-libs/openssl dev-lang/lua dev-libs/libevent dev-libs/jansson + sudo emerge -av sys-libs/readline dev-libs/libconfig dev-libs/openssl dev-lang/lua dev-libs/libevent dev-libs/jansson dev-lang/python On Fedora: - sudo yum install lua-devel openssl-devel libconfig-devel readline-devel libevent-devel + sudo yum install lua-devel openssl-devel libconfig-devel readline-devel libevent-devel python-devel On FreeBSD: - pkg install libconfig libexecinfo lua52 + pkg install libconfig libexecinfo lua52 python On OpenBSD: - pkg_add libconfig libexecinfo lua + pkg_add libconfig libexecinfo lua python Then, @@ -69,6 +73,7 @@ If using [Homebrew](http://brew.sh/): brew install libconfig brew install readline brew install lua + brew install python brew install libevent export CFLAGS="-I/usr/local/include -I/usr/local/Cellar/readline/6.3.8/include" export LDFLAGS="-L/usr/local/lib -L/usr/local/Cellar/readline/6.3.8/lib" @@ -81,6 +86,7 @@ If using [MacPorts](https://www.macports.org): sudo port install libconfig-hr sudo port install readline sudo port install lua51 + sudo port install python34 sudo port install libevent export CFLAGS="-I/usr/local/include -I/opt/local/include -I/opt/local/include/lua-5.1" export LDFLAGS="-L/usr/local/lib -L/opt/local/lib -L/opt/local/lib/lua-5.1" From 964b210f5054d81dfa5cbbfc5e52f7144b67f2a1 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 23 May 2015 17:38:15 -0700 Subject: [PATCH 89/97] typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0853582..20de295 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Clone GitHub Repository git clone --recursive https://github.com/vysheng/tg.git && cd tg -### Python Suppoer +### Python Support Python support is currently limited to Python 2.7 or Python 3.1+. Other versions may work but are not tested. From 8b5a1f98d7a93024e9ada840a7aa67dd2ca465b3 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 23 May 2015 17:43:33 -0700 Subject: [PATCH 90/97] Gentoo ebuild, untested changes --- gentoo/net-im/telegram-cli/telegram-cli-9999.ebuild | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gentoo/net-im/telegram-cli/telegram-cli-9999.ebuild b/gentoo/net-im/telegram-cli/telegram-cli-9999.ebuild index c6ec5b3..de50269 100644 --- a/gentoo/net-im/telegram-cli/telegram-cli-9999.ebuild +++ b/gentoo/net-im/telegram-cli/telegram-cli-9999.ebuild @@ -20,7 +20,9 @@ DEPEND="sys-libs/zlib dev-libs/libconfig dev-libs/openssl dev-libs/libevent - lua? ( dev-lang/lua )" + lua? ( dev-lang/lua ) + json? ( dev-lib/jansson ) + python? ( dev-lang/python )" src_unpack() { git-2_src_unpack @@ -30,6 +32,8 @@ src_unpack() { src_configure() { econf $(use_enable lua liblua ) + econf $(use_enable python python ) + econf $(use_enable json json ) } src_install() { From 622303ce91bc6388dbd2090e3526bd7eebe7bc80 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 23 May 2015 17:53:24 -0700 Subject: [PATCH 91/97] Change to libpython-dev and python for travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 809110d..c6dead1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ install: - sudo apt-get install libreadline6-dev - sudo apt-get install libssl-dev - sudo apt-get install liblua5.2-dev lua5.2 - - sudo apt-get install libpython3-dev python3 + - sudo apt-get install libpython-dev python - sudo apt-get install libevent-dev - sudo apt-get install libjansson-dev From 0cf690a8aaa03de05201ba8b16072923e7ceb8e5 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 23 May 2015 17:57:35 -0700 Subject: [PATCH 92/97] Still trying to appease the travis gods. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c6dead1..51df285 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ install: - sudo apt-get install libreadline6-dev - sudo apt-get install libssl-dev - sudo apt-get install liblua5.2-dev lua5.2 - - sudo apt-get install libpython-dev python + - sudo apt-get install python-dev python - sudo apt-get install libevent-dev - sudo apt-get install libjansson-dev From 6aa4dabf5f853a9e41e155a9c4391f3b83336dbf Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 23 May 2015 18:26:58 -0700 Subject: [PATCH 93/97] fix include orders because python defines _GNU_SOURCE unconditionally and it can collide with other libs --- loop.c | 10 +++++++--- main.c | 7 ++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/loop.c b/loop.c index db1ae11..050537b 100644 --- a/loop.c +++ b/loop.c @@ -21,7 +21,13 @@ #include "config.h" #endif +#if USE_PYTHON +#include "python-tg.h" +#endif + +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif #define READLINE_CALLBACKS #include @@ -59,9 +65,7 @@ #if USE_LUA #include "lua-tg.h" #endif -#if USE_PYTHON -#include "python-tg.h" -#endif + #include #include #include diff --git a/main.c b/main.c index 3f75831..9452d27 100644 --- a/main.c +++ b/main.c @@ -21,6 +21,10 @@ #include "config.h" #endif +#ifdef USE_PYTHON +# include "python-tg.h" +#endif + #include #include #include @@ -75,9 +79,6 @@ # include "lua-tg.h" #endif -#ifdef USE_PYTHON -# include "python-tg.h" -#endif #include From 8c3adff675641a76d00368291168e1d3276a7648 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 23 May 2015 18:28:38 -0700 Subject: [PATCH 94/97] Missed a _GNU_SOURCE define --- interface.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/interface.c b/interface.c index ce472cd..d6a83bf 100644 --- a/interface.c +++ b/interface.c @@ -21,7 +21,13 @@ #include "config.h" #endif -#define _GNU_SOURCE +#ifdef USE_PYTHON +# include "python-tg.h" +#endif + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif #include #include @@ -59,9 +65,6 @@ # include "lua-tg.h" #endif -#ifdef USE_PYTHON -# include "python-tg.h" -#endif //#include "mtproto-common.h" From f1a18dabfe401ead5e603c70f9760cf7eb3d96e0 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 23 May 2015 18:39:20 -0700 Subject: [PATCH 95/97] Adding explicit libraries for CentOS builds. --- Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.in b/Makefile.in index eed8ae9..c032397 100644 --- a/Makefile.in +++ b/Makefile.in @@ -6,7 +6,7 @@ CPPFLAGS=@CPPFLAGS@ @OPENSSL_INCLUDES@ DEFS=@DEFS@ COMPILE_FLAGS=${CFLAGS} ${CPFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Werror -Wextra -Wno-missing-field-initializers -Wno-deprecated-declarations -fno-strict-aliasing -fno-omit-frame-pointer -ggdb -Wno-unused-parameter -fPIC EXTRA_LIBS=@LIBS@ @EXTRA_LIBS@ @OPENSSL_LIBS@ -LOCAL_LDFLAGS=-rdynamic -ggdb -levent ${EXTRA_LIBS} +LOCAL_LDFLAGS=-rdynamic -ggdb -levent ${EXTRA_LIBS} -ldl -lpthread -lutil LINK_FLAGS=${LDFLAGS} ${LOCAL_LDFLAGS} DEP=dep From 825cfcd96f8504a14a89c904accb7a0ae4731ce0 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 23 May 2015 18:40:56 -0700 Subject: [PATCH 96/97] More include order issues due to python's broken define logic. --- python-tg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python-tg.h b/python-tg.h index bf3784e..bc724ea 100644 --- a/python-tg.h +++ b/python-tg.h @@ -20,8 +20,8 @@ #ifndef __PYTHON_TG_H__ #define __PYTHON_TG_H__ -#include #include +#include #include // Python functions From d594d718f2ef8c95ce7907dc19c030ad839ab9c9 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Sat, 23 May 2015 18:47:39 -0700 Subject: [PATCH 97/97] clang identified some bugs that gcc nor I did! --- python-tg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python-tg.c b/python-tg.c index 25d3b5a..a045bda 100644 --- a/python-tg.c +++ b/python-tg.c @@ -750,7 +750,7 @@ void py_do_all (void) { int len, len1, len2, len3; int limit, offset; - long msg_id; + long msg_id = 0; PyObject *pyObj1 = NULL; PyObject *pyObj2 = NULL; PyObject *cb_extra = NULL; @@ -949,7 +949,7 @@ void py_do_all (void) { PyErr_Print(); break; case pq_set_profile_name: - if(PyArg_ParseTuple(args, "s#s#|O", &str1, &len1, &str2, len2, &cb_extra)) + if(PyArg_ParseTuple(args, "s#s#|O", &str1, &len1, &str2, &len2, &cb_extra)) tgl_do_set_profile_name (TLS, str1, len1, str2, len2, py_user_cb, cb_extra); else PyErr_Print(); @@ -979,7 +979,7 @@ void py_do_all (void) { break; case pq_delete_msg: case pq_restore_msg: - if(PyArg_ParseTuple(args, "l|O", msg_id, &cb_extra)) + if(PyArg_ParseTuple(args, "l|O", &msg_id, &cb_extra)) tgl_do_delete_msg (TLS, msg_id, py_empty_cb, cb_extra); else PyErr_Print();