added json support

This commit is contained in:
vvaltman 2015-05-11 14:20:34 +03:00
parent 76aec0bf15
commit 402375ec43
8 changed files with 855 additions and 105 deletions

View File

@ -19,7 +19,7 @@ DIR_LIST=${DEP} ${AUTO} ${EXE} ${OBJ} ${LIB} ${DEP}/auto ${OBJ}/auto
EXE_LIST=${EXE}/telegram-cli
TG_OBJECTS=${OBJ}/main.o ${OBJ}/loop.o ${OBJ}/interface.o ${OBJ}/lua-tg.o
TG_OBJECTS=${OBJ}/main.o ${OBJ}/loop.o ${OBJ}/interface.o ${OBJ}/lua-tg.o ${OBJ}/json-tg.o
INCLUDE=-I. -I${srcdir} -I${srcdir}/tgl
CC=@CC@

View File

@ -36,6 +36,9 @@
/* Define to 1 if you have the `event' library (-levent). */
#undef HAVE_LIBEVENT
/* Define to 1 if you have the `jansson' library (-ljansson). */
#undef HAVE_LIBJANSSON
/* Define to 1 if you have the `m' library (-lm). */
#undef HAVE_LIBM
@ -155,6 +158,9 @@
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* use json */
#undef USE_JSON
/* use lua */
#undef USE_LUA

125
configure vendored
View File

@ -694,6 +694,7 @@ with_zlib
enable_libconfig
enable_extf
enable_liblua
enable_json
with_progname
enable_valgrind
'
@ -1321,6 +1322,7 @@ Optional Features:
--enable-libconfig/--disable-libconfig
--enable-extf/--disable-extf
--enable-liblua/--disable-liblua
--enable-json/--disable-json
--enable-valgrind/--disable-valgrind
Optional Packages:
@ -5865,7 +5867,130 @@ 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.
if test "${enable_json+set}" = set; then :
enableval=$enable_json;
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 json_array_set_new in -ljansson" >&5
$as_echo_n "checking for json_array_set_new in -ljansson... " >&6; }
if ${ac_cv_lib_jansson_json_array_set_new+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-ljansson $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char json_array_set_new ();
int
main ()
{
return json_array_set_new ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_jansson_json_array_set_new=yes
else
ac_cv_lib_jansson_json_array_set_new=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jansson_json_array_set_new" >&5
$as_echo "$ac_cv_lib_jansson_json_array_set_new" >&6; }
if test "x$ac_cv_lib_jansson_json_array_set_new" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBJANSSON 1
_ACEOF
LIBS="-ljansson $LIBS"
else
as_fn_error $? "No libjansson found. Try --disable-json" "$LINENO" 5
fi
$as_echo "#define USE_JSON 1" >>confdefs.h
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 json_array_set_new in -ljansson" >&5
$as_echo_n "checking for json_array_set_new in -ljansson... " >&6; }
if ${ac_cv_lib_jansson_json_array_set_new+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-ljansson $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char json_array_set_new ();
int
main ()
{
return json_array_set_new ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_jansson_json_array_set_new=yes
else
ac_cv_lib_jansson_json_array_set_new=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jansson_json_array_set_new" >&5
$as_echo "$ac_cv_lib_jansson_json_array_set_new" >&6; }
if test "x$ac_cv_lib_jansson_json_array_set_new" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBJANSSON 1
_ACEOF
LIBS="-ljansson $LIBS"
else
as_fn_error $? "No libjansson found. Try --disable-json" "$LINENO" 5
fi
$as_echo "#define USE_JSON 1" >>confdefs.h
fi
#check for custom prog name
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking progname" >&5
$as_echo_n "checking progname... " >&6; }
# Check whether --with-progname was given.
if test "${with_progname+set}" = set; then :

View File

@ -94,7 +94,24 @@ AC_ARG_ENABLE(liblua,[--enable-liblua/--disable-liblua],
])
])
AC_MSG_CHECKING([for libjansson])
AC_ARG_ENABLE(json,[--enable-json/--disable-json],
[
if test "x$enableval" = "xno" ; then
AC_MSG_RESULT([disabled])
else
AC_MSG_RESULT([enabled])
AC_CHECK_LIB([jansson],[json_array_set_new],[],AC_MSG_ERROR([No libjansson found. Try --disable-json]))
AC_DEFINE(USE_JSON,1,[use json])
fi
],[
AC_MSG_RESULT([enabled])
AC_CHECK_LIB([jansson],[json_array_set_new],[],AC_MSG_ERROR([No libjansson found. Try --disable-json]))
AC_DEFINE(USE_JSON,1,[use json])
])
#check for custom prog name
AC_MSG_CHECKING([progname])
AC_ARG_WITH(progname,[--with-progname=<name>],
[
if test "x$with_progname" = "xno" ; then

View File

@ -74,6 +74,11 @@
#define OPEN_BIN "xdg-open %s"
#endif
#ifdef USE_JSON
# include "jansson.h"
# include "json-tg.h"
#endif
#define ALLOW_MULT 1
char *default_prompt = "> ";
@ -82,7 +87,7 @@ extern char one_string[];
extern int one_string_len;
extern char *one_string_prompt;
extern int one_string_flags;
extern int enable_json;
int disable_auto_accept;
int msg_num_mode;
int disable_colors;
@ -1599,17 +1604,40 @@ void work_modifier (const char *s, int l) {
void print_fail (struct in_ev *ev) {
mprint_start (ev);
mprintf (ev, "FAIL\n");
if (!enable_json) {
mprintf (ev, "FAIL\n");
} else {
#ifdef USE_JSON
json_t *res = json_object ();
assert (json_object_set (res, "result", json_string ("FAIL")) >= 0);
char *s = json_dumps (res, 0);
mprintf (ev, "%s\n", s);
json_decref (res);
free (s);
#endif
}
mprint_end (ev);
}
void print_success (struct in_ev *ev) {
if (ev) {
if (ev || enable_json) {
mprint_start (ev);
mprintf (ev, "SUCCESS\n");
if (!enable_json) {
mprintf (ev, "SUCCESS\n");
} else {
#ifdef USE_JSON
json_t *res = json_object ();
assert (json_object_set (res, "result", json_string ("SUCCESS")) >= 0);
char *s = json_dumps (res, 0);
mprintf (ev, "%s\n", s);
json_decref (res);
free (s);
#endif
}
mprint_end (ev);
}
}
void print_success_gw (struct tgl_state *TLSR, void *extra, int success) {
assert (TLS == TLSR);
struct in_ev *ev = extra;
@ -1644,10 +1672,26 @@ void print_msg_list_gw (struct tgl_state *TLSR, void *extra, int success, int nu
return;
}
if (!success) { print_fail (ev); return; }
mprint_start (ev);
int i;
for (i = num - 1; i >= 0; i--) {
print_message (ev, ML[i]);
if (!enable_json) {
int i;
for (i = num - 1; i >= 0; i--) {
print_message (ev, ML[i]);
}
} else {
#ifdef USE_JSON
json_t *res = json_array ();
int i;
for (i = num - 1; i >= 0; i--) {
json_t *a = json_pack_message (ML[i]);
assert (json_array_append (res, a) >= 0);
}
char *s = json_dumps (res, 0);
mprintf (ev, "%s\n", s);
json_decref (res);
free (s);
#endif
}
mprint_end (ev);
}
@ -1661,7 +1705,17 @@ void print_msg_gw (struct tgl_state *TLSR, void *extra, int success, struct tgl_
}
if (!success) { print_fail (ev); return; }
mprint_start (ev);
print_message (ev, M);
if (!enable_json) {
print_message (ev, M);
} else {
#ifdef USE_JSON
json_t *res = json_pack_message (M);
char *s = json_dumps (res, 0);
mprintf (ev, "%s\n", s);
json_decref (res);
free (s);
#endif
}
mprint_end (ev);
}
@ -1674,10 +1728,25 @@ void print_user_list_gw (struct tgl_state *TLSR, void *extra, int success, int n
}
if (!success) { print_fail (ev); return; }
mprint_start (ev);
int i;
for (i = num - 1; i >= 0; i--) {
print_user_name (ev, UL[i]->id, (void *)UL[i]);
mprintf (ev, "\n");
if (!enable_json) {
int i;
for (i = num - 1; i >= 0; i--) {
print_user_name (ev, UL[i]->id, (void *)UL[i]);
mprintf (ev, "\n");
}
} else {
#ifdef USE_JSON
json_t *res = json_array ();
int i;
for (i = num - 1; i >= 0; i--) {
json_t *a = json_pack_peer (UL[i]->id, (void *)UL[i]);
assert (json_array_append (res, a) >= 0);
}
char *s = json_dumps (res, 0);
mprintf (ev, "%s\n", s);
json_decref (res);
free (s);
#endif
}
mprint_end (ev);
}
@ -1691,8 +1760,18 @@ void print_user_gw (struct tgl_state *TLSR, void *extra, int success, struct tgl
}
if (!success) { print_fail (ev); return; }
mprint_start (ev);
print_user_name (ev, U->id, (void *)U);
mprintf (ev, "\n");
if (!enable_json) {
print_user_name (ev, U->id, (void *)U);
mprintf (ev, "\n");
} else {
#ifdef USE_JSON
json_t *res = json_pack_peer (U->id, (void *)U);
char *s = json_dumps (res, 0);
mprintf (ev, "%s\n", s);
json_decref (res);
free (s);
#endif
}
mprint_end (ev);
}
@ -1705,7 +1784,18 @@ void print_filename_gw (struct tgl_state *TLSR, void *extra, int success, char *
}
if (!success) { print_fail (ev); return; }
mprint_start (ev);
mprintf (ev, "Saved to %s\n", name);
if (!enable_json) {
mprintf (ev, "Saved to %s\n", name);
} else {
#ifdef USE_JSON
json_t *res = json_object ();
assert (json_object_set (res, "result", json_string (name)) >= 0);
char *s = json_dumps (res, 0);
mprintf (ev, "%s\n", s);
json_decref (res);
free (s);
#endif
}
mprint_end (ev);
}
@ -1718,7 +1808,19 @@ void print_string_gw (struct tgl_state *TLSR, void *extra, int success, const ch
}
if (!success) { print_fail (ev); return; }
mprint_start (ev);
mprintf (ev, "%s\n", name);
mprint_start (ev);
if (!enable_json) {
mprintf (ev, "%s\n", name);
} else {
#ifdef USE_JSON
json_t *res = json_object ();
assert (json_object_set (res, "result", json_string (name)) >= 0);
char *s = json_dumps (res, 0);
mprintf (ev, "%s\n", s);
json_decref (res);
free (s);
#endif
}
mprint_end (ev);
}
@ -1752,30 +1854,42 @@ void print_chat_info_gw (struct tgl_state *TLSR, void *extra, int success, struc
}
if (!success) { print_fail (ev); return; }
mprint_start (ev);
tgl_peer_t *U = (void *)C;
mpush_color (ev, COLOR_YELLOW);
mprintf (ev, "Chat ");
print_chat_name (ev, U->id, U);
mprintf (ev, " (id %d) members:\n", tgl_get_peer_id (U->id));
int i;
for (i = 0; i < C->user_list_size; i++) {
mprintf (ev, "\t\t");
print_user_name (ev, TGL_MK_USER (C->user_list[i].user_id), tgl_peer_get (TLS, TGL_MK_USER (C->user_list[i].user_id)));
mprintf (ev, " invited by ");
print_user_name (ev, TGL_MK_USER (C->user_list[i].inviter_id), tgl_peer_get (TLS, TGL_MK_USER (C->user_list[i].inviter_id)));
mprintf (ev, " at ");
print_date_full (ev, C->user_list[i].date);
if (C->user_list[i].user_id == C->admin_id) {
mprintf (ev, " admin");
if (!enable_json) {
tgl_peer_t *U = (void *)C;
mpush_color (ev, COLOR_YELLOW);
mprintf (ev, "Chat ");
print_chat_name (ev, U->id, U);
mprintf (ev, " (id %d) members:\n", tgl_get_peer_id (U->id));
int i;
for (i = 0; i < C->user_list_size; i++) {
mprintf (ev, "\t\t");
print_user_name (ev, TGL_MK_USER (C->user_list[i].user_id), tgl_peer_get (TLS, TGL_MK_USER (C->user_list[i].user_id)));
mprintf (ev, " invited by ");
print_user_name (ev, TGL_MK_USER (C->user_list[i].inviter_id), tgl_peer_get (TLS, TGL_MK_USER (C->user_list[i].inviter_id)));
mprintf (ev, " at ");
print_date_full (ev, C->user_list[i].date);
if (C->user_list[i].user_id == C->admin_id) {
mprintf (ev, " admin");
}
mprintf (ev, "\n");
}
mprintf (ev, "\n");
mpop_color (ev);
} else {
#ifdef USE_JSON
json_t *res = json_pack_peer (C->id, (void *)C);
char *s = json_dumps (res, 0);
mprintf (ev, "%s\n", s);
json_decref (res);
free (s);
#endif
}
mpop_color (ev);
mprint_end (ev);
}
void print_user_status (struct tgl_user_status *S, struct in_ev *ev) {
if (enable_json) { return; }
if (S->online > 0) {
mprintf (ev, "online (was online ");
print_date_full (ev, S->when);
@ -1805,21 +1919,31 @@ void print_user_info_gw (struct tgl_state *TLSR, void *extra, int success, struc
return;
}
if (!success) { print_fail (ev); return; }
tgl_peer_t *C = (void *)U;
mprint_start (ev);
mpush_color (ev, COLOR_YELLOW);
mprintf (ev, "User ");
print_user_name (ev, U->id, C);
if (U->username) {
mprintf (ev, " @%s", U->username);
tgl_peer_t *C = (void *)U;
if (!enable_json) {
mpush_color (ev, COLOR_YELLOW);
mprintf (ev, "User ");
print_user_name (ev, U->id, C);
if (U->username) {
mprintf (ev, " @%s", U->username);
}
mprintf (ev, " (#%d):\n", tgl_get_peer_id (U->id));
mprintf (ev, "\treal name: %s %s\n", U->real_first_name, U->real_last_name);
mprintf (ev, "\tphone: %s\n", U->phone);
mprintf (ev, "\t");
print_user_status (&U->status, ev);
mprintf (ev, "\n");
mpop_color (ev);
} else {
#ifdef USE_JSON
json_t *res = json_pack_peer (U->id, (void *)U);
char *s = json_dumps (res, 0);
mprintf (ev, "%s\n", s);
json_decref (res);
free (s);
#endif
}
mprintf (ev, " (#%d):\n", tgl_get_peer_id (U->id));
mprintf (ev, "\treal name: %s %s\n", U->real_first_name, U->real_last_name);
mprintf (ev, "\tphone: %s\n", U->phone);
mprintf (ev, "\t");
print_user_status (&U->status, ev);
mprintf (ev, "\n");
mpop_color (ev);
mprint_end (ev);
}
@ -1832,11 +1956,21 @@ void print_secret_chat_gw (struct tgl_state *TLSR, void *extra, int success, str
}
if (!success) { print_fail (ev); return; }
mprint_start (ev);
mpush_color (ev, COLOR_YELLOW);
mprintf (ev, " Encrypted chat ");
print_encr_chat_name (ev, E->id, (void *)E);
mprintf (ev, " is now in wait state\n");
mpop_color (ev);
if (!enable_json) {
mpush_color (ev, COLOR_YELLOW);
mprintf (ev, " Encrypted chat ");
print_encr_chat_name (ev, E->id, (void *)E);
mprintf (ev, " is now in wait state\n");
mpop_color (ev);
} else {
#ifdef USE_JSON
json_t *res = json_pack_peer (E->id, (void *)E);
char *s = json_dumps (res, 0);
mprintf (ev, "%s\n", s);
json_decref (res);
free (s);
#endif
}
mprint_end (ev);
}
@ -1849,26 +1983,41 @@ void print_dialog_list_gw (struct tgl_state *TLSR, void *extra, int success, int
}
if (!success) { print_fail (ev); return; }
mprint_start (ev);
mpush_color (ev, COLOR_YELLOW);
int i;
for (i = size - 1; i >= 0; i--) {
tgl_peer_t *UC;
switch (tgl_get_peer_type (peers[i])) {
case TGL_PEER_USER:
UC = tgl_peer_get (TLS, peers[i]);
mprintf (ev, "User ");
print_user_name (ev, peers[i], UC);
mprintf (ev, ": %d unread\n", unread_count[i]);
break;
case TGL_PEER_CHAT:
UC = tgl_peer_get (TLS, peers[i]);
mprintf (ev, "Chat ");
print_chat_name (ev, peers[i], UC);
mprintf (ev, ": %d unread\n", unread_count[i]);
break;
if (!enable_json) {
mpush_color (ev, COLOR_YELLOW);
int i;
for (i = size - 1; i >= 0; i--) {
tgl_peer_t *UC;
switch (tgl_get_peer_type (peers[i])) {
case TGL_PEER_USER:
UC = tgl_peer_get (TLS, peers[i]);
mprintf (ev, "User ");
print_user_name (ev, peers[i], UC);
mprintf (ev, ": %d unread\n", unread_count[i]);
break;
case TGL_PEER_CHAT:
UC = tgl_peer_get (TLS, peers[i]);
mprintf (ev, "Chat ");
print_chat_name (ev, peers[i], UC);
mprintf (ev, ": %d unread\n", unread_count[i]);
break;
}
}
mpop_color (ev);
} else {
#ifdef USE_JSON
json_t *res = json_array ();
int i;
for (i = size - 1; i >= 0; i--) {
json_t *a = json_pack_peer (peers[i], tgl_peer_get (TLS, peers[i]));
assert (json_array_append (res, a) >= 0);
}
char *s = json_dumps (res, 0);
mprintf (ev, "%s\n", s);
json_decref (res);
free (s);
#endif
}
mpop_color (ev);
mprint_end (ev);
}
@ -2029,6 +2178,7 @@ void print_typing (struct in_ev *ev, enum tgl_typing_status status) {
void type_notification_upd (struct tgl_state *TLSR, struct tgl_user *U, enum tgl_typing_status status) {
assert (TLSR == TLS);
if (log_level < 2 || (disable_output && !notify_ev)) { return; }
if (enable_json) { return; }
struct in_ev *ev = notify_ev;
mprint_start (ev);
mpush_color (ev, COLOR_YELLOW);
@ -2044,6 +2194,7 @@ void type_notification_upd (struct tgl_state *TLSR, struct tgl_user *U, enum tgl
void type_in_chat_notification_upd (struct tgl_state *TLSR, struct tgl_user *U, struct tgl_chat *C, enum tgl_typing_status status) {
assert (TLSR == TLS);
if (log_level < 2 || (disable_output && !notify_ev)) { return; }
if (enable_json) { return; }
struct in_ev *ev = notify_ev;
mprint_start (ev);
mpush_color (ev, COLOR_YELLOW);
@ -2074,7 +2225,17 @@ void print_message_gw (struct tgl_state *TLSR, struct tgl_message *M) {
if (disable_output && !notify_ev) { return; }
struct in_ev *ev = notify_ev;
mprint_start (ev);
print_message (ev, M);
if (!enable_json) {
print_message (ev, M);
} else {
#ifdef USE_JSON
json_t *res = json_pack_message (M);
char *s = json_dumps (res, 0);
mprintf (ev, "%s\n", s);
json_decref (res);
free (s);
#endif
}
mprint_end (ev);
}
@ -2130,6 +2291,18 @@ void print_peer_updates (struct in_ev *ev, int flags) {
}
}
void json_peer_update (struct in_ev *ev, tgl_peer_t *P, unsigned flags) {
#ifdef USE_JSON
json_t *res = json_object ();
assert (json_object_set (res, "peer", json_pack_peer (P->id, P)) >= 0);
assert (json_object_set (res, "updates", json_pack_updates (flags)) >= 0);
char *s = json_dumps (res, 0);
mprintf (ev, "%s\n", s);
json_decref (res);
free (s);
#endif
}
void user_update_gw (struct tgl_state *TLSR, struct tgl_user *U, unsigned flags) {
assert (TLSR == TLS);
#ifdef USE_LUA
@ -2142,17 +2315,21 @@ void user_update_gw (struct tgl_state *TLSR, struct tgl_user *U, unsigned flags)
if (!(flags & TGL_UPDATE_CREATED)) {
mprint_start (ev);
mpush_color (ev, COLOR_YELLOW);
mprintf (ev, "User ");
print_user_name (ev, U->id, (void *)U);
if (!(flags & TGL_UPDATE_DELETED)) {
mprintf (ev, " updated");
print_peer_updates (ev, flags);
if (!enable_json) {
mpush_color (ev, COLOR_YELLOW);
mprintf (ev, "User ");
print_user_name (ev, U->id, (void *)U);
if (!(flags & TGL_UPDATE_DELETED)) {
mprintf (ev, " updated");
print_peer_updates (ev, flags);
} else {
mprintf (ev, " deleted");
}
mprintf (ev, "\n");
mpop_color (ev);
} else {
mprintf (ev, " deleted");
json_peer_update (ev, (void *)U, flags);
}
mprintf (ev, "\n");
mpop_color (ev);
mprint_end (ev);
}
}
@ -2169,17 +2346,21 @@ void chat_update_gw (struct tgl_state *TLSR, struct tgl_chat *U, unsigned flags)
if (!(flags & TGL_UPDATE_CREATED)) {
mprint_start (ev);
mpush_color (ev, COLOR_YELLOW);
mprintf (ev, "Chat ");
print_chat_name (ev, U->id, (void *)U);
if (!(flags & TGL_UPDATE_DELETED)) {
mprintf (ev, " updated");
print_peer_updates (ev, flags);
if (!enable_json) {
mpush_color (ev, COLOR_YELLOW);
mprintf (ev, "Chat ");
print_chat_name (ev, U->id, (void *)U);
if (!(flags & TGL_UPDATE_DELETED)) {
mprintf (ev, " updated");
print_peer_updates (ev, flags);
} else {
mprintf (ev, " deleted");
}
mprintf (ev, "\n");
mpop_color (ev);
} else {
mprintf (ev, " deleted");
json_peer_update (ev, (void *)U, flags);
}
mprintf (ev, "\n");
mpop_color (ev);
mprint_end (ev);
}
}
@ -2207,17 +2388,21 @@ void secret_chat_update_gw (struct tgl_state *TLSR, struct tgl_secret_chat *U, u
if (!(flags & TGL_UPDATE_CREATED)) {
mprint_start (ev);
mpush_color (ev, COLOR_YELLOW);
mprintf (ev, "Secret chat ");
print_encr_chat_name (ev, U->id, (void *)U);
if (!(flags & TGL_UPDATE_DELETED)) {
mprintf (ev, " updated");
print_peer_updates (ev, flags);
if (!enable_json) {
mpush_color (ev, COLOR_YELLOW);
mprintf (ev, "Secret chat ");
print_encr_chat_name (ev, U->id, (void *)U);
if (!(flags & TGL_UPDATE_DELETED)) {
mprintf (ev, " updated");
print_peer_updates (ev, flags);
} else {
mprintf (ev, " deleted");
}
mprintf (ev, "\n");
mpop_color (ev);
} else {
mprintf (ev, " deleted");
json_peer_update (ev, (void *)U, flags);
}
mprintf (ev, "\n");
mpop_color (ev);
mprint_end (ev);
}
}
@ -2231,10 +2416,27 @@ void print_card_gw (struct tgl_state *TLSR, void *extra, int success, int size,
}
if (!success) { print_fail (ev); return; }
mprint_start (ev);
mprintf (ev, "Card: ");
int i;
for (i = 0; i < size; i++) {
mprintf (ev, "%08x%c", card[i], i == size - 1 ? '\n' : ':');
if (!enable_json) {
mprintf (ev, "Card: ");
int i;
for (i = 0; i < size; i++) {
mprintf (ev, "%08x%c", card[i], i == size - 1 ? '\n' : ':');
}
} else {
#ifdef USE_JSON
static char q[1000];
int pos = 0;
int i;
for (i = 0; i < size; i++) {
pos += sprintf (q + pos, "%08x%s", card[i], i == size - 1 ? "" : ":");
}
json_t *res = json_object ();
assert (json_object_set (res, "result", json_string (q)) >= 0);
char *s = json_dumps (res, 0);
mprintf (ev, "%s\n", s);
json_decref (res);
free (s);
#endif
}
mprint_end (ev);
}
@ -2247,7 +2449,18 @@ void callback_extf (struct tgl_state *TLS, void *extra, int success, char *buf)
}
if (!success) { print_fail (ev); return; }
mprint_start (ev);
mprintf (ev, "%s\n", buf);
if (!enable_json) {
mprintf (ev, "%s\n", buf);
} else {
#ifdef USE_JSON
json_t *res = json_object ();
assert (json_object_set (res, "result", json_string (buf)) >= 0);
char *s = json_dumps (res, 0);
mprintf (ev, "%s\n", s);
json_decref (res);
free (s);
#endif
}
mprint_end (ev);
}
@ -2255,6 +2468,7 @@ void user_status_upd (struct tgl_state *TLS, struct tgl_user *U) {
if (disable_output && !notify_ev) { return; }
if (!binlog_read) { return; }
if (log_level < 3) { return; }
if (enable_json) { return; }
struct in_ev *ev = notify_ev;
mprint_start (ev);
mpush_color (ev, COLOR_YELLOW);

369
json-tg.c Normal file
View File

@ -0,0 +1,369 @@
#include "config.h"
#ifdef USE_JSON
#include <jansson.h>
#include "json-tg.h"
#include <tgl.h>
#include <tgl-layout.h>
#include <assert.h>
extern struct tgl_state *TLS;
void json_pack_peer_type (json_t *res, tgl_peer_id_t id) {
int x = tgl_get_peer_type (id);
switch (x) {
case TGL_PEER_USER:
assert (json_object_set (res, "type", json_string ("user")) >= 0);
break;
case TGL_PEER_CHAT:
assert (json_object_set (res, "type", json_string ("chat")) >= 0);
break;
case TGL_PEER_ENCR_CHAT:
assert (json_object_set (res, "type", json_string ("encr_chat")) >= 0);
break;
default:
assert (0);
}
}
void json_pack_user (json_t *res, tgl_peer_t *P) {
if (P->user.first_name) {
assert (json_object_set (res, "first_name", json_string (P->user.first_name)) >= 0);
}
if (P->user.last_name) {
assert (json_object_set (res, "last_name", json_string (P->user.last_name)) >= 0);
}
if (P->user.real_first_name) {
assert (json_object_set (res, "real_first_name", json_string (P->user.real_first_name)) >= 0);
}
if (P->user.real_last_name) {
assert (json_object_set (res, "real_last_name", json_string (P->user.real_last_name)) >= 0);
}
if (P->user.phone) {
assert (json_object_set (res, "phone", json_string (P->user.phone)) >= 0);
}
if (P->user.username) {
assert (json_object_set (res, "username", json_string (P->user.username)) >= 0);
}
}
void json_pack_chat (json_t *res, tgl_peer_t *P) {
assert (P->chat.title);
assert (json_object_set (res, "title", json_string (P->chat.title)) >= 0);
assert (json_object_set (res, "members_num", json_integer (P->chat.users_num)) >= 0);
if (P->chat.user_list) {
json_t *m = json_array ();
assert (m);
int i;
for (i = 0; i < P->chat.users_num; i++) {
tgl_peer_id_t id = TGL_MK_USER (P->chat.user_list[i].user_id);
assert (json_array_append (m, json_pack_peer (id, tgl_peer_get (TLS, id))) >= 0);
}
assert (json_object_set (res, "members", m) >= 0);
}
}
void json_pack_encr_chat (json_t *res, tgl_peer_t *P) {
assert (json_object_set (res, "user", json_pack_peer (TGL_MK_USER (P->encr_chat.user_id), tgl_peer_get (TLS, TGL_MK_USER (P->encr_chat.user_id)))) >= 0);
}
json_t *json_pack_peer (tgl_peer_id_t id, tgl_peer_t *P) {
json_t *res = json_object ();
assert (json_object_set (res, "id", json_integer (tgl_get_peer_id (id))) >= 0);
json_pack_peer_type (res, id);
assert (res);
if (!P || !(P->flags & TGLPF_CREATED)) {
static char s[100];
switch (tgl_get_peer_type (id)) {
case TGL_PEER_USER:
sprintf (s, "user#%d", tgl_get_peer_id (id));
break;
case TGL_PEER_CHAT:
sprintf (s, "chat#%d", tgl_get_peer_id (id));
break;
case TGL_PEER_ENCR_CHAT:
sprintf (s, "encr_chat#%d", tgl_get_peer_id (id));
break;
default:
assert (0);
}
assert (json_object_set (res, "print_name", json_string (s)) >= 0);
return res;
}
assert (json_object_set (res, "print_name", json_string (P->print_name)) >= 0);
assert (json_object_set (res, "flags", json_integer (P->flags)) >= 0);
switch (tgl_get_peer_type (id)) {
case TGL_PEER_USER:
json_pack_user (res, P);
break;
case TGL_PEER_CHAT:
json_pack_chat (res, P);
break;
case TGL_PEER_ENCR_CHAT:
json_pack_encr_chat (res, P);
break;
default:
assert (0);
}
return res;
}
json_t *json_pack_updates (unsigned flags) {
json_t *a = json_array ();
if (flags & TGL_UPDATE_CREATED) {
assert (json_array_append (a, json_string ("created")) >= 0);
}
if (flags & TGL_UPDATE_DELETED) {
assert (json_array_append (a, json_string ("deleted")) >= 0);
}
if (flags & TGL_UPDATE_PHONE) {
assert (json_array_append (a, json_string ("phone")) >= 0);
}
if (flags & TGL_UPDATE_CONTACT) {
assert (json_array_append (a, json_string ("contact")) >= 0);
}
if (flags & TGL_UPDATE_PHOTO) {
assert (json_array_append (a, json_string ("photo")) >= 0);
}
if (flags & TGL_UPDATE_BLOCKED) {
assert (json_array_append (a, json_string ("blocked")) >= 0);
}
if (flags & TGL_UPDATE_REAL_NAME) {
assert (json_array_append (a, json_string ("real_name")) >= 0);
}
if (flags & TGL_UPDATE_NAME) {
assert (json_array_append (a, json_string ("name")) >= 0);
}
if (flags & TGL_UPDATE_REQUESTED) {
assert (json_array_append (a, json_string ("requested")) >= 0);
}
if (flags & TGL_UPDATE_WORKING) {
assert (json_array_append (a, json_string ("working")) >= 0);
}
if (flags & TGL_UPDATE_FLAGS) {
assert (json_array_append (a, json_string ("flags")) >= 0);
}
if (flags & TGL_UPDATE_TITLE) {
assert (json_array_append (a, json_string ("title")) >= 0);
}
if (flags & TGL_UPDATE_ADMIN) {
assert (json_array_append (a, json_string ("admin")) >= 0);
}
if (flags & TGL_UPDATE_MEMBERS) {
assert (json_array_append (a, json_string ("members")) >= 0);
}
if (flags & TGL_UPDATE_USERNAME) {
assert (json_array_append (a, json_string ("username")) >= 0);
}
return a;
}
json_t *json_pack_media (struct tgl_message_media *M) {
json_t *res = json_object ();
switch (M->type) {
case tgl_message_media_photo:
assert (json_object_set (res, "type", json_string ("photo")) >= 0);
if (M->caption) {
assert (json_object_set (res, "caption", json_string (M->caption)) >= 0);
}
break;
case tgl_message_media_document:
case tgl_message_media_document_encr:
assert (json_object_set (res, "type", json_string ("document")) >= 0);
break;
case tgl_message_media_unsupported:
assert (json_object_set (res, "type", json_string ("unsupported")) >= 0);
break;
case tgl_message_media_geo:
assert (json_object_set (res, "type", json_string ("geo")) >= 0);
assert (json_object_set (res, "longitude", json_real (M->geo.longitude)) >= 0);
assert (json_object_set (res, "latitude", json_real (M->geo.latitude)) >= 0);
break;
case tgl_message_media_contact:
assert (json_object_set (res, "type", json_string ("contact")) >= 0);
assert (json_object_set (res, "phone", json_string (M->phone)) >= 0);
assert (json_object_set (res, "first_name", json_string (M->first_name)) >= 0);
assert (json_object_set (res, "last_name", json_string (M->last_name)) >= 0);
assert (json_object_set (res, "user_id", json_integer (M->user_id)) >= 0);
break;
case tgl_message_media_webpage:
assert (json_object_set (res, "type", json_string ("webpage")) >= 0);
if (M->webpage->url) {
assert (json_object_set (res, "url", json_string (M->webpage->url)) >= 0);
}
if (M->webpage->title) {
assert (json_object_set (res, "title", json_string (M->webpage->title)) >= 0);
}
if (M->webpage->description) {
assert (json_object_set (res, "description", json_string (M->webpage->description)) >= 0);
}
if (M->webpage->author) {
assert (json_object_set (res, "author", json_string (M->webpage->author)) >= 0);
}
break;
case tgl_message_media_venue:
assert (json_object_set (res, "type", json_string ("venue")) >= 0);
assert (json_object_set (res, "longitude", json_real (M->venue.geo.longitude)) >= 0);
assert (json_object_set (res, "latitude", json_real (M->venue.geo.latitude)) >= 0);
if (M->venue.title) {
assert (json_object_set (res, "type", json_string (M->venue.title)) >= 0);
}
if (M->venue.address) {
assert (json_object_set (res, "address", json_string (M->venue.address)) >= 0);
}
if (M->venue.provider) {
assert (json_object_set (res, "provider", json_string (M->venue.provider)) >= 0);
}
if (M->venue.venue_id) {
assert (json_object_set (res, "venue_id", json_string (M->venue.venue_id)) >= 0);
}
break;
default:
assert (json_object_set (res, "type", json_string ("???")) >= 0);
}
return res;
}
json_t *json_pack_service (struct tgl_message *M) {
json_t *res = json_object ();
switch (M->action.type) {
case tgl_message_action_geo_chat_create:
assert (json_object_set (res, "type", json_string ("geo_created")) >= 0);
break;
case tgl_message_action_geo_chat_checkin:
assert (json_object_set (res, "type", json_string ("geo_checkin")) >= 0);
break;
case tgl_message_action_chat_create:
assert (json_object_set (res, "type", json_string ("chat_created")) >= 0);
assert (json_object_set (res, "title", json_string (M->action.title)) >= 0);
break;
case tgl_message_action_chat_edit_title:
assert (json_object_set (res, "type", json_string ("chat_rename")) >= 0);
assert (json_object_set (res, "title", json_string (M->action.title)) >= 0);
break;
case tgl_message_action_chat_edit_photo:
assert (json_object_set (res, "type", json_string ("chat_change_photo")) >= 0);
break;
case tgl_message_action_chat_delete_photo:
assert (json_object_set (res, "type", json_string ("chat_delete_photo")) >= 0);
break;
case tgl_message_action_chat_add_user:
assert (json_object_set (res, "type", json_string ("chat_add_user")) >= 0);
assert (json_object_set (res, "user", json_pack_peer (tgl_set_peer_id (TGL_PEER_USER, M->action.user), tgl_peer_get (TLS, tgl_set_peer_id (TGL_PEER_USER, M->action.user)))) >= 0);
break;
case tgl_message_action_chat_add_user_by_link:
assert (json_object_set (res, "type", json_string ("chat_add_user_link")) >= 0);
assert (json_object_set (res, "user", json_pack_peer (tgl_set_peer_id (TGL_PEER_USER, M->action.user), tgl_peer_get (TLS, tgl_set_peer_id (TGL_PEER_USER, M->action.user)))) >= 0);
break;
case tgl_message_action_chat_delete_user:
assert (json_object_set (res, "type", json_string ("chat_del_user")) >= 0);
assert (json_object_set (res, "user", json_pack_peer (tgl_set_peer_id (TGL_PEER_USER, M->action.user), tgl_peer_get (TLS, tgl_set_peer_id (TGL_PEER_USER, M->action.user)))) >= 0);
break;
case tgl_message_action_set_message_ttl:
assert (json_object_set (res, "type", json_string ("set_ttl")) >= 0);
assert (json_object_set (res, "ttl", json_integer (M->action.ttl)) >= 0);
break;
case tgl_message_action_read_messages:
assert (json_object_set (res, "type", json_string ("read")) >= 0);
assert (json_object_set (res, "count", json_integer (M->action.read_cnt)) >= 0);
break;
case tgl_message_action_delete_messages:
assert (json_object_set (res, "type", json_string ("delete")) >= 0);
assert (json_object_set (res, "count", json_integer (M->action.delete_cnt)) >= 0);
break;
case tgl_message_action_screenshot_messages:
assert (json_object_set (res, "type", json_string ("screenshot")) >= 0);
assert (json_object_set (res, "count", json_integer (M->action.screenshot_cnt)) >= 0);
break;
case tgl_message_action_flush_history:
assert (json_object_set (res, "type", json_string ("flush")) >= 0);
break;
case tgl_message_action_resend:
assert (json_object_set (res, "type", json_string ("resend")) >= 0);
break;
case tgl_message_action_notify_layer:
assert (json_object_set (res, "type", json_string ("notify_layer")) >= 0);
assert (json_object_set (res, "layer", json_integer (M->action.layer)) >= 0);
break;
case tgl_message_action_typing:
assert (json_object_set (res, "type", json_string ("typing")) >= 0);
break;
case tgl_message_action_noop:
assert (json_object_set (res, "type", json_string ("noop")) >= 0);
break;
case tgl_message_action_request_key:
assert (json_object_set (res, "type", json_string ("request_key")) >= 0);
break;
case tgl_message_action_accept_key:
assert (json_object_set (res, "type", json_string ("accept_key")) >= 0);
break;
case tgl_message_action_commit_key:
assert (json_object_set (res, "type", json_string ("commit_key")) >= 0);
break;
case tgl_message_action_abort_key:
assert (json_object_set (res, "type", json_string ("abort_key")) >= 0);
break;
default:
assert (json_object_set (res, "type", json_string ("???")) >= 0);
break;
}
return res;
}
json_t *json_pack_message (struct tgl_message *M) {
json_t *res = json_object ();
assert (json_object_set (res, "id", json_integer (M->id)) >= 0);
if (!(M->flags & TGLMF_CREATED)) { return res; }
assert (json_object_set (res, "id", json_integer (M->flags)) >= 0);
if (tgl_get_peer_type (M->fwd_from_id)) {
assert (json_object_set (res, "fwd_from", json_pack_peer (M->fwd_from_id, tgl_peer_get (TLS, M->fwd_from_id))) >= 0);
assert (json_object_set (res, "fwd_date", json_integer (M->fwd_date)) >= 0);
}
if (M->reply_id) {
assert (json_object_set (res, "reply_id", json_integer (M->reply_id)) >= 0);
}
if (M->flags & TGLMF_MENTION) {
assert (json_object_set (res, "mention", json_true ()) >= 0);
}
assert (json_object_set (res, "from", json_pack_peer (M->from_id, tgl_peer_get (TLS, M->from_id))) >= 0);
assert (json_object_set (res, "to", json_pack_peer (M->to_id, tgl_peer_get (TLS, M->to_id))) >= 0);
assert (json_object_set (res, "out", json_boolean (M->flags & TGLMF_OUT)) >= 0);
assert (json_object_set (res, "unread", json_boolean (M->flags & TGLMF_UNREAD)) >= 0);
assert (json_object_set (res, "service", json_boolean (M->flags & TGLMF_SERVICE)) >= 0);
assert (json_object_set (res, "date", json_integer (M->date)) >= 0);
if (!(M->flags & TGLMF_SERVICE)) {
if (M->message_len && M->message) {
assert (json_object_set (res, "text", json_string (M->message)) >= 0);
}
if (M->media.type && M->media.type != tgl_message_media_none) {
assert (json_object_set (res, "media", json_pack_media (&M->media)) >= 0);
}
} else {
assert (json_object_set (res, "action", json_pack_service (M)) >= 0);
}
return res;
}
#endif

12
json-tg.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef __JSON_TG_H__
#define __JSON_TG_H__
#include "config.h"
#ifdef USE_JSON
#include <jansson.h>
#include <tgl.h>
#include <tgl-layout.h>
json_t *json_pack_message (struct tgl_message *M);
json_t *json_pack_updates (unsigned flags);
json_t *json_pack_peer (tgl_peer_id_t id, tgl_peer_t *P);
#endif
#endif

9
main.c
View File

@ -120,6 +120,7 @@ int use_ids;
int ipv6_enabled;
char *start_command;
int disable_link_preview;
int enable_json;
struct tgl_state *TLS;
@ -480,7 +481,9 @@ void usage (void) {
printf (" --help/-h prints this help\n");
printf (" --accept-any-tcp accepts tcp connections from any src (only loopback by default)\n");
printf (" --disable-link-preview disables server-side previews to links\n");
#ifdef USE_JSON
printf (" --json prints answers and values in json format\n");
#endif
exit (1);
}
@ -625,6 +628,7 @@ void args_parse (int argc, char **argv) {
{"help", no_argument, 0, 'h'},
{"accept-any-tcp", no_argument, 0, 1001},
{"disable-link-preview", no_argument, 0, 1002},
{"json", no_argument, 0, 1003},
{0, 0, 0, 0 }
};
@ -738,6 +742,9 @@ void args_parse (int argc, char **argv) {
case 1002:
disable_link_preview = 2;
break;
case 1003:
enable_json = 1;
break;
case 'h':
default:
usage ();