Commit 452c30fc authored by vvaltman's avatar vvaltman

Merge branch 'master' of https://github.com/datamachine/tg into datamachine-master

parents 8ba66a86 d594d718
telegram
*.o
Makefile
aclocal.m4
autom4te.cache
config.h
config.log
......@@ -17,3 +18,4 @@ debian/files
debian/telegram-cli/*
debian/telegram-cli.debhelper.log
debian/telegram-cli.substvars
__pycache__
......@@ -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 python-dev python
- sudo apt-get install libevent-dev
- sudo apt-get install libjansson-dev
......
......@@ -4,10 +4,9 @@ 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 -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
......@@ -19,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
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@
......
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)
......@@ -24,30 +24,35 @@ Clone GitHub Repository
git clone --recursive https://github.com/vysheng/tg.git && cd tg
### Python Support
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 libjansson-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 +74,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 +87,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"
......
# ===========================================================================
# 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 <http://www.gnu.org/licenses/>.
#
# 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.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
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
unset ac_cv_prog_PYTHON_BIN
unset PYTHON_BIN
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])
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
#! /bin/sh
aclocal
autoheader
automake --gnu --add-missing
autoconf
......@@ -164,6 +164,9 @@
/* use lua */
#undef USE_LUA
/* use python */
#undef USE_PYTHON
/* fixed for correct valgrind work */
#undef VALGRIND_FIXES
......
......@@ -622,6 +622,12 @@ ac_includes_default="\
ac_subst_vars='LTLIBOBJS
EXTRA_LIBS
LIBOBJS
PYTHON_CFLAGS
PYTHON_LIBS
PYTHON_FOUND
PYTHON_LIB
PYTHON_INCLUDE_DIR
PYTHON_BIN
LUA_LIB
LUA_INCLUDE
pkgluaexecdir
......@@ -694,6 +700,7 @@ with_zlib
enable_libconfig
enable_extf
enable_liblua
enable_python
enable_json
with_progname
enable_valgrind
......@@ -1322,6 +1329,7 @@ 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
......@@ -2393,6 +2401,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 <http://www.gnu.org/licenses/>.
#
# 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
# ===========================================================================
......@@ -5867,6 +5931,403 @@ 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;
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 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.
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
unset ac_cv_prog_PYTHON_BIN
unset PYTHON_BIN
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
else
PYTHON_FOUND=no
fi
if test x$ax_python_lib != xno; then
PYTHON_LIB=$ax_python_lib
else
PYTHON_FOUND=no
fi
if test $PYTHON_FOUND = no ; then
as_fn_error $? "No supported python lib version found. Try --disable-python" "$LINENO" 5
else
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 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.
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
unset ac_cv_prog_PYTHON_BIN
unset PYTHON_BIN
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
else
PYTHON_FOUND=no
fi
if test x$ax_python_lib != xno; then
PYTHON_LIB=$ax_python_lib
else
PYTHON_FOUND=no
fi
if test $PYTHON_FOUND = no ; then
as_fn_error $? "No supported python lib version found. Try --disable-python" "$LINENO" 5
else
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.
......
......@@ -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,44 @@ AC_ARG_ENABLE(liblua,[--enable-liblua/--disable-liblua],
])
])
AC_MSG_CHECKING([for python])
AC_ARG_ENABLE(python,[--enable-python/--disable-python],
[
if test "x$enableval" = "xno" ; then
AC_MSG_RESULT([disabled])
else
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
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],
[
......
......@@ -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() {
......
......@@ -21,7 +21,13 @@
#include "config.h"
#endif
#ifdef USE_PYTHON
# include "python-tg.h"
#endif
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <assert.h>
#include <stdio.h>
......@@ -59,6 +65,7 @@
# include "lua-tg.h"
#endif
//#include "mtproto-common.h"
#include <tgl/tgl.h>
......@@ -1288,6 +1295,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) {
......@@ -1302,6 +1310,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;
......@@ -2332,6 +2341,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 ();
......@@ -2361,6 +2373,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) {
......@@ -2426,6 +2441,9 @@ 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; }
......@@ -2457,6 +2475,9 @@ 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; }
......@@ -2488,6 +2509,11 @@ 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 ();
......
......@@ -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 <assert.h>
......@@ -56,7 +62,10 @@
#include "interface.h"
#include "telegram.h"
#include "loop.h"
#if USE_LUA
#include "lua-tg.h"
#endif
#include <tgl/tgl.h>
#include <tgl/tgl-binlog.h>
#include <tgl/tgl-net.h>
......@@ -215,6 +224,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);
......@@ -655,6 +668,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) {
......@@ -710,6 +727,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);
......
......@@ -21,6 +21,10 @@
#include "config.h"
#endif
#ifdef USE_PYTHON
# include "python-tg.h"
#endif
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
......@@ -75,6 +79,7 @@
# include "lua-tg.h"
#endif
#include <tgl/tgl.h>
#define PROGNAME "telegram-cli"
......@@ -107,6 +112,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 +387,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);
......@@ -484,6 +494,26 @@ 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
#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-name> log file name\n");
printf (" -U <user-name> change uid after start\n");
printf (" -G <group-name> change gid after start\n");
printf (" -D disable output\n");
printf (" -P <port> port to listen for input commands\n");
printf (" -S <socket-name> unix socket to create\n");
printf (" -e <commands> 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);
}
......@@ -643,8 +673,12 @@ void args_parse (int argc, char **argv) {
#endif
#ifdef USE_LUA
"s:"
#endif
#ifdef USE_PYTHON
"Z:"
#endif
, long_options, NULL
)) != -1) {
switch (opt) {
case 1000:
......@@ -700,6 +734,11 @@ void args_parse (int argc, char **argv) {
case 'W':
wait_dialog_list = 1;
break;
#ifdef USE_PYTHON
case 'Z':
python_file = strdup (optarg);
break;
#endif
case 'C':
disable_colors ++;
break;
......@@ -922,6 +961,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 ();
......@@ -942,6 +984,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 ();
......
/*
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 <http://www.gnu.org/licenses/>.
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 <string.h>
#include <stdlib.h>
#include <libgen.h>
#include <Python.h>
#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
#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"
// Custom Types
#include "python-types.h"
extern PyTypeObject tgl_PeerType;
extern PyTypeObject tgl_MsgType;
//#include "interface.h"
//#include "auto/constants.h"
#include <tgl/tgl.h>
#include "interface.h"
#include <assert.h>
extern int verbosity;
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;
PyObject *_py_our_id;
PyObject *_py_new_msg;
PyObject *_py_secret_chat_update;
PyObject *_py_user_update;
PyObject *_py_chat_update;
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; }
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) {
assert(PyList_Check(list));
if (!value || !strlen (value)) { return; }
if(num >= 0)
PyList_SetItem (list, num, PyUnicode_FromString (value));
else // Append
PyList_Append (list, PyUnicode_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 = PyUnicode_FromString("user");
break;
case TGL_PEER_CHAT:
type = PyUnicode_FromString("chat");
break;
case TGL_PEER_ENCR_CHAT:
type = PyUnicode_FromString("encr_chat");
break;
default:
assert (0);
}
return type;
}
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 = tgl_Peer_FromTglPeer(P);
return peer;
}
PyObject* get_message (struct tgl_message *M) {
assert (M);
PyObject *msg;
msg = tgl_Msg_FromTglMsg(M);
return msg;
}
void py_binlog_end (void) {
if (!python_loaded) { return; }
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)
PyErr_Print();
else if(PyUnicode_Check(result))
logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result)));
Py_XDECREF(result);
}
void py_diff_end (void) {
if (!python_loaded) { return; }
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)
PyErr_Print();
else if(PyUnicode_Check(result))
logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result)));
Py_XDECREF(result);
}
void py_our_id (int id) {
if (!python_loaded) { return; }
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(PyUnicode_Check(result))
logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result)));
Py_XDECREF(result);
}
void py_new_msg (struct tgl_message *M) {
if (!python_loaded) { return; }
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);
result = PyEval_CallObject(_py_new_msg, arglist);
Py_DECREF(arglist);
if(result == NULL)
PyErr_Print();
else if(PyUnicode_Check(result))
logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result)));
Py_XDECREF(result);
}
void py_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) {
if (!python_loaded) { return; }
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);
arglist = Py_BuildValue("(OO)", peer, types);
result = PyEval_CallObject(_py_secret_chat_update, arglist);
Py_DECREF(arglist);
if(result == NULL)
PyErr_Print();
else if(PyUnicode_Check(result))
logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result)));
Py_XDECREF(result);
}
void py_user_update (struct tgl_user *U, unsigned flags) {
if (!python_loaded) { return; }
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);
arglist = Py_BuildValue("(OO)", peer, types);
result = PyEval_CallObject(_py_user_update, arglist);
Py_DECREF(arglist);
if(result == NULL)
PyErr_Print();
else if(PyUnicode_Check(result))
logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result)));
Py_XDECREF(result);
}
void py_chat_update (struct tgl_chat *C, unsigned flags) {
if (!python_loaded) { return; }
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);
arglist = Py_BuildValue("(OO)", peer, types);
result = PyEval_CallObject(_py_chat_update, arglist);
Py_DECREF(arglist);
if(result == NULL)
PyErr_Print();
else if(PyUnicode_Check(result))
logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result)));
Py_XDECREF(result);
}
////extern tgl_peer_t *Peers[];
////extern int peer_num;
//
#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 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
};
void py_empty_cb (struct tgl_state *TLSR, void *cb_extra, int success) {
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);
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);
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 & TGLMF_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);
PyObject *callable = cb_extra;
PyObject *arglist = NULL;
PyObject *msg = NULL;
PyObject *result = NULL;
if(PyCallable_Check(callable)) {
if (success && M && (M->flags & TGLMF_CREATED)) {
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);
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, const char *file_name) {
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);
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);
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);
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, const char *data) {
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);
}
#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) {
assert (p + 2 <= pos);
enum py_query_type f = (long)py_ptr[p ++];
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 = 0;
PyObject *pyObj1 = NULL;
PyObject *pyObj2 = NULL;
PyObject *cb_extra = NULL;
PyObject *peer = NULL;
PyObject *peer1 = NULL;
switch (f) {
case pq_contact_list:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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 {
, 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]);
} 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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
tgl_do_accept_encr_chat_request (TLS, py_ptr[p + 1], py_secret_chat_cb, py_ptr[p]);
break;
*/
case pq_send_contact:
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:
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:
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:
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:
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);
}
// 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;
}
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); }
// 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);
static PyMethodDef py_tgl_methods[] = {
{"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", 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, ""},
{"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;
if (PyType_Ready(&tgl_PeerType) < 0)
return MOD_ERROR_VAL;
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);
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);
}
/*
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; }
python_loaded = 0;
PyObject *pModule;
// 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);
Py_Initialize();
#else
Py_Initialize();
inittgl();
#endif
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)
*dot = 0;
pModule = PyImport_Import(PyUnicode_FromString(basename(filename)));
if(pModule == NULL || PyErr_Occurred()) { // Error loading script
logprintf("Failed to load python script\n");
PyErr_Print();
exit(1);
}
python_loaded = 1;
PyDateTime_IMPORT;
logprintf("Python Initialized\n");
}
#endif
/*
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 <http://www.gnu.org/licenses/>.
Copyright Vitaly Valtman 2013-2015
Copyright Vincent Castellano 2015
*/
#ifndef __PYTHON_TG_H__
#define __PYTHON_TG_H__
#include <Python.h>
#include <string.h>
#include <tgl/tgl.h>
// Python functions
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);
// 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);
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef USE_PYTHON
#include <Python.h>
#include <tgl/tgl.h>
#include <tgl/tools.h>
#include <tgl/updates.h>
#include <tgl/tgl-structures.h>
#include <stdlib.h>
#include "structmember.h"
// Python Imports
#include "datetime.h"
#include "python-types.h"
#include "python-tg.h"
extern struct tgl_state *TLS;
// TGL Python Exceptions
extern PyObject *TglError;
extern PyObject *PeerError;
extern PyObject *MsgError;
// Forward type declarations
PyTypeObject tgl_PeerType;
// Utility functions
PyObject* get_datetime(long datetime)
{
return PyDateTime_FromTimestamp(Py_BuildValue("(O)", PyLong_FromLong(datetime)));
}
//
// tgl_peer_t wrapper
//
static void
tgl_Peer_dealloc(tgl_Peer* self)
{
Py_TYPE(self)->tp_free((PyObject*)self);
}
static PyObject *
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;
}
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,
&peer_id.type,
&peer_id.id))
{
PyErr_Format(PeerError, "Peer must specify type and id");
return -1;
}
self->peer = tgl_peer_get(TLS, peer_id);
if(self->peer == NULL)
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(PeerError, "peer.type_name 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(PeerError, "peer.type_name == '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(PeerError, "peer.type_name not supported!");
Py_RETURN_NONE;
}
Py_XINCREF(ret);
return ret;
}
static PyObject *
tgl_Peer_getuser_list (tgl_Peer *self, void *closure)
{
PyObject *ret;
int i;
struct tgl_chat_user *user_list;
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(PeerError, "Only peer.type_name == 'chat' has user_list");
Py_RETURN_NONE;
break;
default:
PyErr_SetString(PeerError, "peer.type_name 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", get_datetime(self->peer->user.status.when));
break;
case TGL_PEER_CHAT:
case TGL_PEER_ENCR_CHAT:
PyErr_SetString(PeerError, "Only peer.type_name == 'user' has user_status");
Py_RETURN_NONE;
break;
default:
PyErr_SetString(PeerError, "peer.type_name 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:
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:
PyErr_SetString(PeerError, "Only peer.type_name == 'user' has phone");
Py_RETURN_NONE;
break;
default:
PyErr_SetString(PeerError, "peer.type_name 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:
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:
PyErr_SetString(PeerError, "Only peer.type_name == 'user' has username");
Py_RETURN_NONE;
break;
default:
PyErr_SetString(PeerError, "peer.type_name not supported!");
Py_RETURN_NONE;
}
Py_XINCREF(ret);
return ret;
}
static PyObject *
tgl_Peer_getfirst_name (tgl_Peer *self, void *closure)
{
PyObject *ret;
switch(self->peer->id.type) {
case TGL_PEER_USER:
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:
PyErr_SetString(PeerError, "Only peer.type_name == 'user' has first_name");
Py_RETURN_NONE;
break;
default:
PyErr_SetString(PeerError, "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:
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:
PyErr_SetString(PeerError, "Only peer.type_name == 'user' has last_name");
Py_RETURN_NONE;
break;
default:
PyErr_SetString(PeerError, "peer.type_name not supported!");
Py_RETURN_NONE;
}
Py_XINCREF(ret);
return ret;
}
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:
ret = (PyObject*)self;
break;
case TGL_PEER_CHAT:
PyErr_SetString(PeerError, "Only peer.type_name == 'chat' does not have user");
Py_RETURN_NONE;
break;
default:
PyErr_SetString(PeerError, "peer.type_name not supported!");
Py_RETURN_NONE;
}
Py_XINCREF(ret);
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)
{
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},
{"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},
{"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},
{"first_name", (getter)tgl_Peer_getfirst_name, NULL, "", NULL},
{"last_name", (getter)tgl_Peer_getlast_name, NULL, "", NULL},
{NULL} /* Sentinel */
};
static PyMemberDef tgl_Peer_members[] = {
{NULL} /* Sentinel */
};
static PyObject *
tgl_Peer_send_msg (tgl_Peer *self, PyObject *args, PyObject *kwargs)
{
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_INCREF(Py_None);
Py_XINCREF(api_call);
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", 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[] = {"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[] = {"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 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"},
{"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, ""},
{"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 */
};
static PyObject *
tgl_Peer_repr(tgl_Peer *self)
{
PyObject *ret;
switch(self->peer->id.type) {
case TGL_PEER_USER:
ret = PyUnicode_FromFormat("<tgl.Peer: type=user, id=%ld, username=%R, name=%R, first_name=%R, last_name=%R, phone=%R>",
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("<tgl.Peer: type=chat, id=%ld, name=%s>",
self->peer->id.id, self->peer->chat.print_title);
break;
case TGL_PEER_ENCR_CHAT:
ret = PyUnicode_FromFormat("<tgl.Peer: type=secret_chat, id=%ld, name=%s, user=%R>",
self->peer->id.id, self->peer->encr_chat.print_name,
PyObject_GetAttrString((PyObject*)self, "user"));
break;
default:
ret = PyUnicode_FromFormat("<tgl.Peer: Type Unknown>");
}
return ret;
}
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 */
(reprfunc)tgl_Peer_repr, /* 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);
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;
PyDateTime_IMPORT;
self = (tgl_Msg *)type->tp_alloc(type, 0);
return (PyObject *)self;
}
static int
tgl_Msg_init(tgl_Msg *self, PyObject *args, PyObject *kwds)
{
PyErr_SetString(MsgError, "You cannot instantiate a tgl.Msg object, only the API can send them.");
return -1;
}
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_getsrc (tgl_Msg *self, void *closure)
{
PyObject *ret;
if(tgl_get_peer_type (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;
}
Py_XINCREF(ret);
return ret;
}
static PyObject *
tgl_Msg_getdest (tgl_Msg *self, void *closure)
{
PyObject *ret;
if(tgl_get_peer_type (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;
}
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 = get_datetime(self->msg->date);
} else {
Py_RETURN_NONE;
}
Py_XINCREF(ret);
return ret;
}
static PyObject *
tgl_Msg_getfwd_src (tgl_Msg *self, void *closure)
{
PyObject *ret;
if(tgl_get_peer_type (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;
}
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 = get_datetime(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 PyObject *
tgl_Msg_repr(tgl_Msg *self)
{
PyObject *ret;
ret = PyUnicode_FromFormat("<tgl.Msg id=%ld, flags=%d, mention=%R, out=%R, unread=%R, service=%R, src=%R, "
"dest=%R, text=%R, media=%R, date=%R, fwd_src=%R, fwd_date=%R, reply_id=%R, reply=%R>",
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[] = {
{"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},
{"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_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},
{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.Msg", /* 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 */
(reprfunc)tgl_Msg_repr, /* 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 Message", /* 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;
}
#endif
#ifndef __PYTHON_TYPES_H__
#define __PYTHON_TYPES_H__
#include <Python.h>
#include <tgl/tgl.h>
typedef struct {
PyObject_HEAD
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
......@@ -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
......
import tgl
import pprint
from functools import partial
our_id = 0
pp = pprint.PrettyPrinter(indent=4)
binlog_done = False;
def on_binlog_replay_end():
binlog_done = True;
def on_get_difference_end():
pass
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)
HISTORY_QUERY_SIZE = 100
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(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:
return;
if msg.dest.id == our_id: # direct message
peer = msg.src
else: # chatroom
peer = msg.dest
pp.pprint(msg)
if msg.text.startswith("!ping"):
print("SENDING PONG")
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):
return "on_secret_chat_update"
def on_user_update():
pass
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)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment