2013-10-23 10:26:17 -04:00
/*
2014-08-21 18:02:43 -04:00
This file is part of telegram - cli .
2013-10-23 10:26:17 -04:00
2014-08-21 18:02:43 -04:00
Telegram - cli is free software : you can redistribute it and / or modify
2013-10-23 10:26:17 -04:00
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 .
2014-08-21 18:02:43 -04:00
Telegram - cli is distributed in the hope that it will be useful ,
2013-10-23 10:26:17 -04:00
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
2014-08-21 18:02:43 -04:00
along with this telegram - cli . If not , see < http : //www.gnu.org/licenses/>.
2013-10-23 10:26:17 -04:00
2014-08-21 18:02:43 -04:00
Copyright Vitaly Valtman 2013 - 2014
2013-10-23 10:26:17 -04:00
*/
2014-01-13 08:05:25 -05:00
# ifdef HAVE_CONFIG_H
2013-11-09 17:47:19 -05:00
# include "config.h"
2014-01-13 08:05:25 -05:00
# endif
2013-10-03 08:38:25 -04:00
# define _GNU_SOURCE
2013-11-09 17:47:19 -05:00
2013-10-03 08:38:25 -04:00
# include <assert.h>
# include <stdio.h>
2013-10-11 16:52:20 -04:00
# include <stdarg.h>
2013-10-03 08:38:25 -04:00
# include <stdlib.h>
# include <string.h>
2013-10-18 14:00:19 -04:00
2013-11-09 17:47:19 -05:00
# ifdef READLINE_GNU
2013-10-18 14:00:19 -04:00
# include <readline/readline.h>
# include <readline/history.h>
2013-11-09 17:47:19 -05:00
# else
2013-11-11 06:34:45 -05:00
# include <readline/readline.h>
# include <readline/history.h>
2013-11-09 17:47:19 -05:00
# endif
2013-10-18 14:00:19 -04:00
2013-10-03 08:38:25 -04:00
# include "include.h"
2014-08-13 11:55:16 -04:00
//#include "queries.h"
2013-10-13 06:18:08 -04:00
# include "interface.h"
# include "telegram.h"
2014-09-07 15:12:39 -04:00
# ifdef EVENT_V2
2014-08-21 16:35:27 -04:00
# include <event2/event.h>
2014-09-07 15:12:39 -04:00
# else
# include <event.h>
# include "event-old.h"
# endif
2014-08-18 12:39:04 -04:00
//#include "auto/constants.h"
2014-08-14 18:16:01 -04:00
//#include "tools.h"
2014-08-13 11:55:16 -04:00
//#include "structures.h"
2013-10-18 12:00:47 -04:00
2014-08-21 11:38:51 -04:00
# ifdef USE_LUA
# include "lua-tg.h"
# endif
2014-08-13 11:55:16 -04:00
//#include "mtproto-common.h"
2013-11-25 12:16:34 -05:00
2014-08-13 08:56:55 -04:00
# include "tgl.h"
2014-08-31 10:18:19 -04:00
# include "loop.h"
2014-08-13 08:56:55 -04:00
2014-08-14 18:16:01 -04:00
# ifndef PATH_MAX
# define PATH_MAX 4096
# endif
# ifdef __APPLE__
# define OPEN_BIN "open %s"
# else
# define OPEN_BIN "xdg-open %s"
# endif
2014-01-24 10:05:41 -05:00
# define ALLOW_MULT 1
2013-10-24 11:44:54 -04:00
char * default_prompt = " > " ;
2014-08-26 12:06:30 -04:00
int disable_auto_accept ;
2013-10-25 15:50:10 -04:00
int msg_num_mode ;
2014-08-24 20:11:41 -04:00
int disable_colors ;
2014-02-27 03:48:05 -05:00
int alert_sound ;
2014-08-21 11:38:51 -04:00
extern int binlog_read ;
2013-10-03 08:38:25 -04:00
2013-12-21 06:53:32 -05:00
int safe_quit ;
2013-10-29 20:08:30 -04:00
int in_readline ;
2013-11-11 06:34:45 -05:00
int readline_active ;
2013-10-29 20:08:30 -04:00
2013-11-15 11:14:25 -05:00
int log_level ;
2013-10-29 20:08:30 -04:00
char * line_ptr ;
2013-12-06 12:14:41 -05:00
int in_chat_mode ;
2014-08-13 11:55:16 -04:00
tgl_peer_id_t chat_mode_id ;
2014-08-26 14:26:00 -04:00
extern int readline_disabled ;
2013-11-09 17:47:19 -05:00
2014-09-09 13:05:36 -04:00
extern int disable_output ;
2013-10-29 20:08:30 -04:00
int is_same_word ( const char * s , size_t l , const char * word ) {
return s & & word & & strlen ( word ) = = l & & ! memcmp ( s , word , l ) ;
}
2014-09-17 17:03:20 -04:00
static void skip_wspc ( void ) {
while ( * line_ptr & & ( ( unsigned char ) * line_ptr ) < = ' ' ) {
line_ptr + + ;
2014-08-12 21:22:15 -04:00
}
}
2014-08-13 11:55:16 -04:00
2014-09-17 17:03:20 -04:00
static char * cur_token ;
static int cur_token_len ;
static int cur_token_end_str ;
static int cur_token_quoted ;
static void unescape_token ( char * start , char * end ) {
static char cur_token_buff [ ( 1 < < 20 ) + 1 ] ;
cur_token_len = 0 ;
cur_token = cur_token_buff ;
while ( start < end ) {
assert ( cur_token_len < ( 1 < < 20 ) ) ;
switch ( * start ) {
case ' \\ ' :
start + + ;
switch ( * start ) {
case ' n ' :
cur_token [ cur_token_len + + ] = ' \n ' ;
break ;
case ' r ' :
cur_token [ cur_token_len + + ] = ' \r ' ;
break ;
case ' t ' :
cur_token [ cur_token_len + + ] = ' \t ' ;
break ;
case ' b ' :
cur_token [ cur_token_len + + ] = ' \b ' ;
break ;
case ' a ' :
cur_token [ cur_token_len + + ] = ' \a ' ;
break ;
default :
cur_token [ cur_token_len + + ] = * start ;
break ;
}
break ;
default :
cur_token [ cur_token_len + + ] = * start ; ;
break ;
}
start + + ;
}
cur_token [ cur_token_len ] = 0 ;
}
int force_end_mode ;
static void next_token ( void ) {
skip_wspc ( ) ;
cur_token_end_str = 0 ;
cur_token_quoted = 0 ;
if ( ! * line_ptr ) {
cur_token_len = 0 ;
cur_token_end_str = 1 ;
return ;
}
char c = * line_ptr ;
char * start = line_ptr ;
if ( c = = ' " ' | | c = = ' \' ' ) {
cur_token_quoted = 1 ;
line_ptr + + ;
int esc = 0 ;
while ( * line_ptr & & ( esc | | * line_ptr ! = c ) ) {
if ( * line_ptr = = ' \\ ' ) {
esc = 1 - esc ;
} else {
esc = 0 ;
}
line_ptr + + ;
}
if ( ! * line_ptr ) {
cur_token_len = - 2 ;
} else {
unescape_token ( start + 1 , line_ptr ) ;
line_ptr + + ;
}
} else {
while ( * line_ptr & & ( ( unsigned char ) * line_ptr ) > ' ' ) {
line_ptr + + ;
}
cur_token = start ;
cur_token_len = line_ptr - start ;
cur_token_end_str = ( ! force_end_mode ) & & ( * line_ptr = = 0 ) ;
2013-10-29 20:08:30 -04:00
}
2014-09-17 17:03:20 -04:00
}
void next_token_end ( void ) {
skip_wspc ( ) ;
if ( * line_ptr & & * line_ptr ! = ' " ' & & * line_ptr ! = ' \' ' ) {
cur_token_quoted = 0 ;
cur_token = line_ptr ;
while ( * line_ptr ) { line_ptr + + ; }
cur_token_len = line_ptr - cur_token ;
while ( ( ( unsigned char ) cur_token [ cur_token_len - 1 ] ) < = ' ' & & cur_token_len > = 0 ) {
cur_token_len - - ;
}
assert ( cur_token_len > 0 ) ;
cur_token_end_str = ! force_end_mode ;
return ;
} else {
if ( * line_ptr ) {
next_token ( ) ;
skip_wspc ( ) ;
if ( * line_ptr ) {
cur_token_len = - 1 ;
}
} else {
next_token ( ) ;
}
2013-10-29 20:08:30 -04:00
}
}
# define NOT_FOUND (int)0x80000000
2014-08-13 11:55:16 -04:00
tgl_peer_id_t TGL_PEER_NOT_FOUND = { . id = NOT_FOUND } ;
2013-10-31 19:18:34 -04:00
2014-09-17 17:03:20 -04:00
long long cur_token_int ( void ) {
if ( cur_token_len < = 0 ) {
2013-10-29 20:08:30 -04:00
return NOT_FOUND ;
2014-09-17 17:03:20 -04:00
} else {
char c = cur_token [ cur_token_len ] ;
cur_token [ cur_token_len ] = 0 ;
char * end = 0 ;
long long x = strtoll ( cur_token , & end , 0 ) ;
cur_token [ cur_token_len ] = c ;
if ( end ! = cur_token + cur_token_len ) {
return NOT_FOUND ;
} else {
return x ;
}
2013-10-29 20:08:30 -04:00
}
}
2014-09-17 17:03:20 -04:00
tgl_peer_id_t cur_token_user ( void ) {
if ( cur_token_len < = 0 ) { return TGL_PEER_NOT_FOUND ; }
int l = cur_token_len ;
char * s = cur_token ;
char c = cur_token [ cur_token_len ] ;
cur_token [ cur_token_len ] = 0 ;
2013-10-29 20:08:30 -04:00
2013-10-31 19:18:34 -04:00
if ( l > = 6 & & ! memcmp ( s , " user# " , 5 ) ) {
s + = 5 ;
l - = 5 ;
int r = atoi ( s ) ;
2014-09-17 17:03:20 -04:00
cur_token [ cur_token_len ] = c ;
2014-08-13 11:55:16 -04:00
if ( r > = 0 ) { return tgl_set_peer_id ( TGL_PEER_USER , r ) ; }
else { return TGL_PEER_NOT_FOUND ; }
2013-10-29 20:08:30 -04:00
}
2014-09-03 11:54:50 -04:00
if ( l > = 8 & & ! memcmp ( s , " user#id " , 7 ) ) {
s + = 7 ;
l - = 7 ;
int r = atoi ( s ) ;
2014-09-17 17:03:20 -04:00
cur_token [ cur_token_len ] = c ;
2014-09-03 11:54:50 -04:00
if ( r > = 0 ) { return tgl_set_peer_id ( TGL_PEER_USER , r ) ; }
else { return TGL_PEER_NOT_FOUND ; }
}
2013-10-31 19:18:34 -04:00
2014-08-13 11:55:16 -04:00
tgl_peer_t * P = tgl_peer_get_by_name ( s ) ;
2014-09-17 17:03:20 -04:00
cur_token [ cur_token_len ] = c ;
2014-08-13 08:56:55 -04:00
2014-08-13 11:55:16 -04:00
if ( P & & tgl_get_peer_type ( P - > id ) = = TGL_PEER_USER ) {
2014-08-13 08:56:55 -04:00
return P - > id ;
2013-10-29 20:08:30 -04:00
} else {
2014-08-13 11:55:16 -04:00
return TGL_PEER_NOT_FOUND ;
2013-10-29 20:08:30 -04:00
}
}
2014-09-17 17:03:20 -04:00
tgl_peer_id_t cur_token_chat ( void ) {
if ( cur_token_len < = 0 ) { return TGL_PEER_NOT_FOUND ; }
int l = cur_token_len ;
char * s = cur_token ;
char c = cur_token [ cur_token_len ] ;
cur_token [ cur_token_len ] = 0 ;
2013-10-31 19:18:34 -04:00
if ( l > = 6 & & ! memcmp ( s , " chat# " , 5 ) ) {
s + = 5 ;
l - = 5 ;
int r = atoi ( s ) ;
2014-09-17 17:03:20 -04:00
cur_token [ cur_token_len ] = c ;
2014-08-13 11:55:16 -04:00
if ( r > = 0 ) { return tgl_set_peer_id ( TGL_PEER_CHAT , r ) ; }
else { return TGL_PEER_NOT_FOUND ; }
2013-10-29 20:08:30 -04:00
}
2014-09-03 11:54:50 -04:00
if ( l > = 8 & & ! memcmp ( s , " chat#id " , 7 ) ) {
s + = 7 ;
l - = 7 ;
int r = atoi ( s ) ;
2014-09-17 17:03:20 -04:00
cur_token [ cur_token_len ] = c ;
2014-09-03 11:54:50 -04:00
if ( r > = 0 ) { return tgl_set_peer_id ( TGL_PEER_CHAT , r ) ; }
else { return TGL_PEER_NOT_FOUND ; }
}
2013-10-31 19:18:34 -04:00
2014-08-13 11:55:16 -04:00
tgl_peer_t * P = tgl_peer_get_by_name ( s ) ;
2014-09-17 17:03:20 -04:00
cur_token [ cur_token_len ] = c ;
2014-08-13 08:56:55 -04:00
2014-08-13 11:55:16 -04:00
if ( P & & tgl_get_peer_type ( P - > id ) = = TGL_PEER_CHAT ) {
2014-08-13 08:56:55 -04:00
return P - > id ;
2013-10-29 20:08:30 -04:00
} else {
2014-08-13 11:55:16 -04:00
return TGL_PEER_NOT_FOUND ;
2013-10-29 20:08:30 -04:00
}
}
2014-09-17 17:03:20 -04:00
tgl_peer_id_t cur_token_encr_chat ( void ) {
if ( cur_token_len < = 0 ) { return TGL_PEER_NOT_FOUND ; }
char * s = cur_token ;
char c = cur_token [ cur_token_len ] ;
cur_token [ cur_token_len ] = 0 ;
2013-11-04 18:15:24 -05:00
2014-08-13 11:55:16 -04:00
tgl_peer_t * P = tgl_peer_get_by_name ( s ) ;
2014-09-17 17:03:20 -04:00
cur_token [ cur_token_len ] = c ;
2014-08-13 08:56:55 -04:00
2014-08-13 11:55:16 -04:00
if ( P & & tgl_get_peer_type ( P - > id ) = = TGL_PEER_ENCR_CHAT ) {
2014-08-13 08:56:55 -04:00
return P - > id ;
2013-11-04 18:15:24 -05:00
} else {
2014-08-13 11:55:16 -04:00
return TGL_PEER_NOT_FOUND ;
2013-11-04 18:15:24 -05:00
}
}
2014-09-17 17:03:20 -04:00
tgl_peer_id_t cur_token_peer ( void ) {
if ( cur_token_len < = 0 ) { return TGL_PEER_NOT_FOUND ; }
int l = cur_token_len ;
char * s = cur_token ;
char c = cur_token [ cur_token_len ] ;
cur_token [ cur_token_len ] = 0 ;
2013-10-31 19:18:34 -04:00
if ( l > = 6 & & ! memcmp ( s , " user# " , 5 ) ) {
s + = 5 ;
l - = 5 ;
int r = atoi ( s ) ;
2014-09-17 17:03:20 -04:00
cur_token [ cur_token_len ] = c ;
2014-08-13 11:55:16 -04:00
if ( r > = 0 ) { return tgl_set_peer_id ( TGL_PEER_USER , r ) ; }
else { return TGL_PEER_NOT_FOUND ; }
2013-10-31 19:18:34 -04:00
}
if ( l > = 6 & & ! memcmp ( s , " chat# " , 5 ) ) {
s + = 5 ;
l - = 5 ;
int r = atoi ( s ) ;
2014-09-17 17:03:20 -04:00
cur_token [ cur_token_len ] = c ;
if ( r > = 0 ) { return tgl_set_peer_id ( TGL_PEER_CHAT , r ) ; }
else { return TGL_PEER_NOT_FOUND ; }
}
if ( l > = 8 & & ! memcmp ( s , " user#id " , 7 ) ) {
s + = 7 ;
l - = 7 ;
int r = atoi ( s ) ;
cur_token [ cur_token_len ] = c ;
if ( r > = 0 ) { return tgl_set_peer_id ( TGL_PEER_USER , r ) ; }
else { return TGL_PEER_NOT_FOUND ; }
}
if ( l > = 8 & & ! memcmp ( s , " chat#id " , 7 ) ) {
s + = 7 ;
l - = 7 ;
int r = atoi ( s ) ;
cur_token [ cur_token_len ] = c ;
2014-08-13 11:55:16 -04:00
if ( r > = 0 ) { return tgl_set_peer_id ( TGL_PEER_CHAT , r ) ; }
else { return TGL_PEER_NOT_FOUND ; }
2013-10-29 20:08:30 -04:00
}
2014-08-13 08:56:55 -04:00
2014-08-13 11:55:16 -04:00
tgl_peer_t * P = tgl_peer_get_by_name ( s ) ;
2014-09-17 17:03:20 -04:00
cur_token [ cur_token_len ] = c ;
2014-08-13 08:56:55 -04:00
if ( P ) {
return P - > id ;
2013-10-29 20:08:30 -04:00
} else {
2014-08-13 11:55:16 -04:00
return TGL_PEER_NOT_FOUND ;
2013-10-29 20:08:30 -04:00
}
}
2013-10-28 18:33:13 -04:00
2014-09-17 17:03:20 -04:00
static tgl_peer_t * mk_peer ( tgl_peer_id_t id ) {
if ( tgl_get_peer_type ( id ) = = NOT_FOUND ) { return 0 ; }
tgl_peer_t * P = tgl_peer_get ( id ) ;
return P ;
}
2013-10-03 08:38:25 -04:00
char * get_default_prompt ( void ) {
2013-12-06 12:14:41 -05:00
static char buf [ 1000 ] ;
int l = 0 ;
if ( in_chat_mode ) {
2014-08-13 11:55:16 -04:00
tgl_peer_t * U = tgl_peer_get ( chat_mode_id ) ;
2013-12-06 12:14:41 -05:00
assert ( U & & U - > print_name ) ;
2014-08-14 18:16:01 -04:00
l + = snprintf ( buf + l , 999 - l , COLOR_RED " %.*s " COLOR_NORMAL , 100 , U - > print_name ) ;
2013-12-06 12:14:41 -05:00
}
2014-08-13 11:55:16 -04:00
if ( tgl_state . unread_messages | | tgl_state . cur_uploading_bytes | | tgl_state . cur_downloading_bytes ) {
2014-08-14 18:16:01 -04:00
l + = snprintf ( buf + l , 999 - l , COLOR_RED " [ " ) ;
2013-10-28 18:33:13 -04:00
int ok = 0 ;
2014-08-13 11:55:16 -04:00
if ( tgl_state . unread_messages ) {
2014-08-14 18:16:01 -04:00
l + = snprintf ( buf + l , 999 - l , " %d unread " , tgl_state . unread_messages ) ;
2013-10-28 18:33:13 -04:00
ok = 1 ;
}
2014-08-13 11:55:16 -04:00
if ( tgl_state . cur_uploading_bytes ) {
2013-10-28 18:33:13 -04:00
if ( ok ) { * ( buf + l ) = ' ' ; l + + ; }
ok = 1 ;
2014-08-14 18:16:01 -04:00
l + = snprintf ( buf + l , 999 - l , " %lld%%Up " , 100 * tgl_state . cur_uploaded_bytes / tgl_state . cur_uploading_bytes ) ;
2013-10-28 18:33:13 -04:00
}
2014-08-13 11:55:16 -04:00
if ( tgl_state . cur_downloading_bytes ) {
2013-10-28 18:33:13 -04:00
if ( ok ) { * ( buf + l ) = ' ' ; l + + ; }
ok = 1 ;
2014-08-14 18:16:01 -04:00
l + = snprintf ( buf + l , 999 - l , " %lld%%Down " , 100 * tgl_state . cur_downloaded_bytes / tgl_state . cur_downloading_bytes ) ;
2013-10-28 18:33:13 -04:00
}
2014-08-14 18:16:01 -04:00
l + = snprintf ( buf + l , 999 - l , " ] " COLOR_NORMAL ) ;
2014-08-21 16:35:27 -04:00
l + = snprintf ( buf + l , 999 - l , " %s " , default_prompt ) ;
2013-10-24 11:44:54 -04:00
return buf ;
2013-12-06 12:14:41 -05:00
}
2014-08-14 18:16:01 -04:00
l + = snprintf ( buf + l , 999 - l , " %s " , default_prompt ) ;
2013-12-06 12:14:41 -05:00
return buf ;
2013-10-03 08:38:25 -04:00
}
char * complete_none ( const char * text UU , int state UU ) {
return 0 ;
}
2013-11-09 17:47:19 -05:00
void set_prompt ( const char * s ) {
2014-08-26 14:26:00 -04:00
if ( readline_disabled ) { return ; }
2013-11-09 17:47:19 -05:00
rl_set_prompt ( s ) ;
}
2013-10-28 18:33:13 -04:00
void update_prompt ( void ) {
2014-08-26 14:26:00 -04:00
if ( readline_disabled ) { return ; }
2013-10-28 18:33:13 -04:00
print_start ( ) ;
2013-11-09 17:47:19 -05:00
set_prompt ( get_default_prompt ( ) ) ;
2013-11-11 06:34:45 -05:00
if ( readline_active ) {
rl_redisplay ( ) ;
}
2013-10-28 18:33:13 -04:00
print_end ( ) ;
}
2013-11-30 13:52:13 -05:00
char * modifiers [ ] = {
" [offline] " ,
0
} ;
2013-12-06 12:14:41 -05:00
char * in_chat_commands [ ] = {
" /exit " ,
" /quit " ,
2013-12-19 17:50:31 -05:00
" /history " ,
" /read " ,
2013-12-06 12:14:41 -05:00
0
} ;
2014-08-25 12:17:17 -04:00
enum command_argument {
ca_none ,
ca_user ,
ca_chat ,
ca_secret_chat ,
ca_peer ,
ca_file_name ,
ca_file_name_end ,
ca_period ,
ca_number ,
ca_string_end ,
ca_string ,
ca_modifier ,
2014-09-10 07:52:42 -04:00
ca_command ,
2014-09-17 17:03:20 -04:00
ca_extf ,
ca_optional = 256
} ;
struct arg {
int flags ;
struct {
tgl_peer_t * P ;
struct tgl_message * M ;
char * str ;
long long num ;
} ;
2013-10-03 08:38:25 -04:00
} ;
2013-10-03 12:09:06 -04:00
2014-08-25 12:17:17 -04:00
struct command {
char * name ;
enum command_argument args [ 10 ] ;
2014-09-17 17:03:20 -04:00
void ( * fun ) ( int arg_num , struct arg args [ ] ) ;
2014-09-18 09:10:42 -04:00
char * desc ;
2014-08-25 12:17:17 -04:00
} ;
2014-09-17 17:03:20 -04:00
int offline_mode ;
void print_user_list_gw ( void * extra , int success , int num , struct tgl_user * UL [ ] ) ;
void print_msg_list_gw ( void * extra , int success , int num , struct tgl_message * ML [ ] ) ;
void print_dialog_list_gw ( void * extra , int success , int size , tgl_peer_id_t peers [ ] , int last_msg_id [ ] , int unread_count [ ] ) ;
void print_chat_info_gw ( void * extra , int success , struct tgl_chat * C ) ;
void print_user_info_gw ( void * extra , int success , struct tgl_user * C ) ;
void print_filename_gw ( void * extra , int success , char * name ) ;
void open_filename_gw ( void * extra , int success , char * name ) ;
void print_secret_chat_gw ( void * extra , int success , struct tgl_secret_chat * E ) ;
void print_card_gw ( void * extra , int success , int size , int * card ) ;
void print_user_gw ( void * extra , int success , struct tgl_user * U ) ;
void print_msg_gw ( void * extra , int success , struct tgl_message * M ) ;
2014-09-18 09:10:42 -04:00
struct command commands [ ] ;
2014-09-17 17:03:20 -04:00
void do_help ( int arg_num , struct arg args [ ] ) {
assert ( ! arg_num ) ;
push_color ( COLOR_YELLOW ) ;
2014-09-18 09:10:42 -04:00
struct command * cmd = commands ;
while ( cmd - > name ) {
printf ( " %s \n " , cmd - > desc ) ;
cmd + + ;
}
2014-09-17 17:03:20 -04:00
pop_color ( ) ;
fflush ( stdout ) ;
}
void do_contact_list ( int arg_num , struct arg args [ ] ) {
assert ( ! arg_num ) ;
tgl_do_update_contact_list ( print_user_list_gw , 0 ) ;
}
void do_stats ( int arg_num , struct arg args [ ] ) {
assert ( ! arg_num ) ;
static char stat_buf [ 1 < < 15 ] ;
tgl_print_stat ( stat_buf , ( 1 < < 15 ) - 1 ) ;
printf ( " %s \n " , stat_buf ) ;
fflush ( stdout ) ;
}
void do_history ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 3 ) ;
tgl_do_get_history_ext ( args [ 0 ] . P - > id , args [ 2 ] . num ! = NOT_FOUND ? args [ 2 ] . num : 0 , args [ 1 ] . num ! = NOT_FOUND ? args [ 1 ] . num : 40 , offline_mode , print_msg_list_gw , 0 ) ;
}
void do_dialog_list ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 0 ) ;
tgl_do_get_dialog_list ( print_dialog_list_gw , 0 ) ;
}
void do_send_photo ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 2 ) ;
tgl_do_send_photo ( tgl_message_media_photo , args [ 0 ] . P - > id , args [ 1 ] . str , 0 , 0 ) ;
}
void do_send_audio ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 2 ) ;
tgl_do_send_photo ( tgl_message_media_audio , args [ 0 ] . P - > id , args [ 1 ] . str , 0 , 0 ) ;
}
void do_send_video ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 2 ) ;
tgl_do_send_photo ( tgl_message_media_video , args [ 0 ] . P - > id , args [ 1 ] . str , 0 , 0 ) ;
}
void do_send_document ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 2 ) ;
tgl_do_send_photo ( tgl_message_media_document , args [ 0 ] . P - > id , args [ 1 ] . str , 0 , 0 ) ;
}
void do_send_text ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 2 ) ;
tgl_do_send_text ( args [ 0 ] . P - > id , args [ 1 ] . str , 0 , 0 ) ;
}
void do_chat_info ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 1 ) ;
tgl_do_get_chat_info ( args [ 0 ] . P - > id , offline_mode , print_chat_info_gw , 0 ) ;
}
void do_user_info ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 1 ) ;
tgl_do_get_user_info ( args [ 0 ] . P - > id , offline_mode , print_user_info_gw , 0 ) ;
}
void do_fwd ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 2 ) ;
tgl_do_forward_message ( args [ 0 ] . P - > id , args [ 1 ] . num , 0 , 0 ) ;
}
void do_fwd_media ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 2 ) ;
tgl_do_forward_message ( args [ 0 ] . P - > id , args [ 1 ] . num , 0 , 0 ) ;
}
void do_msg ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 2 ) ;
tgl_do_send_message ( args [ 0 ] . P - > id , args [ 1 ] . str , strlen ( args [ 1 ] . str ) , 0 , 0 ) ;
}
void do_rename_chat ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 2 ) ;
tgl_do_rename_chat ( args [ 0 ] . P - > id , args [ 1 ] . str , 0 , 0 ) ;
}
# define DO_LOAD_PHOTO(tp,act,actf) \
void do_ # # act # # _ # # tp ( int arg_num , struct arg args [ ] ) { \
assert ( arg_num = = 1 ) ; \
struct tgl_message * M = tgl_message_get ( args [ 0 ] . num ) ; \
if ( M & & ! M - > service & & M - > media . type = = tgl_message_media_ # # tp ) { \
tgl_do_load_ # # tp ( & M - > media . tp , actf , 0 ) ; \
} else if ( M & & ! M - > service & & M - > media . type = = tgl_message_media_ # # tp # # _encr ) { \
tgl_do_load_encr_video ( & M - > media . encr_video , actf , 0 ) ; \
} \
}
# define DO_LOAD_PHOTO_THUMB(tp,act,actf) \
void do_ # # act # # _ # # tp # # _thumb ( int arg_num , struct arg args [ ] ) { \
assert ( arg_num = = 1 ) ; \
struct tgl_message * M = tgl_message_get ( args [ 0 ] . num ) ; \
if ( M & & ! M - > service & & M - > media . type = = tgl_message_media_ # # tp ) { \
tgl_do_load_ # # tp # # _thumb ( & M - > media . tp , actf , 0 ) ; \
} \
}
DO_LOAD_PHOTO ( photo , load , print_filename_gw )
DO_LOAD_PHOTO ( video , load , print_filename_gw )
DO_LOAD_PHOTO ( audio , load , print_filename_gw )
DO_LOAD_PHOTO ( document , load , print_filename_gw )
DO_LOAD_PHOTO_THUMB ( video , load , print_filename_gw )
DO_LOAD_PHOTO_THUMB ( document , load , print_filename_gw )
DO_LOAD_PHOTO ( photo , open , open_filename_gw )
DO_LOAD_PHOTO ( video , open , open_filename_gw )
DO_LOAD_PHOTO ( audio , open , open_filename_gw )
DO_LOAD_PHOTO ( document , open , open_filename_gw )
DO_LOAD_PHOTO_THUMB ( video , open , open_filename_gw )
DO_LOAD_PHOTO_THUMB ( document , open , open_filename_gw )
void do_add_contact ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 3 ) ;
tgl_do_add_contact ( args [ 0 ] . str , strlen ( args [ 0 ] . str ) , args [ 1 ] . str , strlen ( args [ 1 ] . str ) , args [ 2 ] . str , strlen ( args [ 2 ] . str ) , 0 , print_user_list_gw , 0 ) ;
}
void do_del_contact ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 1 ) ;
tgl_do_del_contact ( args [ 0 ] . P - > id , 0 , 0 ) ;
}
void do_rename_contact ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 3 ) ;
if ( args [ 0 ] . P - > user . phone ) {
tgl_do_add_contact ( args [ 0 ] . P - > user . phone , strlen ( args [ 0 ] . P - > user . phone ) , args [ 1 ] . str , strlen ( args [ 1 ] . str ) , args [ 2 ] . str , strlen ( args [ 2 ] . str ) , 0 , print_user_list_gw , 0 ) ;
}
}
void do_show_license ( int arg_num , struct arg args [ ] ) {
assert ( ! arg_num ) ;
char * b =
# include "LICENSE.h"
;
printf ( " %s " , b ) ;
}
void do_search ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 5 ) ;
tgl_peer_id_t id ;
if ( args [ 0 ] . P ) {
id = args [ 0 ] . P - > id ;
} else {
id = TGL_PEER_NOT_FOUND ;
}
int limit ;
if ( args [ 1 ] . num ! = NOT_FOUND ) {
limit = args [ 1 ] . num ;
} else {
limit = 40 ;
}
int from ;
if ( args [ 2 ] . num ! = NOT_FOUND ) {
from = args [ 2 ] . num ;
} else {
from = 0 ;
}
int to ;
if ( args [ 3 ] . num ! = NOT_FOUND ) {
to = args [ 3 ] . num ;
} else {
to = 0 ;
}
tgl_do_msg_search ( id , from , to , limit , args [ 4 ] . str , print_msg_list_gw , 0 ) ;
}
void do_mark_read ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 1 ) ;
tgl_do_mark_read ( args [ 0 ] . P - > id , 0 , 0 ) ;
}
void do_visualize_key ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 1 ) ;
static char * colors [ 4 ] = { COLOR_GREY , COLOR_CYAN , COLOR_BLUE , COLOR_GREEN } ;
static unsigned char buf [ 16 ] ;
memset ( buf , 0 , sizeof ( buf ) ) ;
tgl_peer_id_t id = args [ 0 ] . P - > id ;
tgl_do_visualize_key ( id , buf ) ;
print_start ( ) ;
int i ;
for ( i = 0 ; i < 16 ; i + + ) {
int x = buf [ i ] ;
int j ;
for ( j = 0 ; j < 4 ; j + + ) {
push_color ( colors [ x & 3 ] ) ;
push_color ( COLOR_INVERSE ) ;
if ( ! disable_colors ) {
printf ( " " ) ;
} else {
switch ( x & 3 ) {
case 0 :
printf ( " " ) ;
break ;
case 1 :
printf ( " -- " ) ;
break ;
case 2 :
printf ( " == " ) ;
break ;
case 3 :
printf ( " || " ) ;
break ;
}
}
pop_color ( ) ;
pop_color ( ) ;
x = x > > 2 ;
}
if ( i & 1 ) { printf ( " \n " ) ; }
}
print_end ( ) ;
}
void do_create_secret_chat ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 1 ) ;
tgl_do_create_secret_chat ( args [ 0 ] . P - > id , print_secret_chat_gw , 0 ) ;
}
void do_chat_add_user ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 3 ) ;
tgl_do_add_user_to_chat ( args [ 0 ] . P - > id , args [ 1 ] . P - > id , args [ 2 ] . num ! = NOT_FOUND ? args [ 2 ] . num : 100 , 0 , 0 ) ;
}
void do_chat_del_user ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 2 ) ;
tgl_do_del_user_from_chat ( args [ 0 ] . P - > id , args [ 1 ] . P - > id , 0 , 0 ) ;
}
void do_status_online ( int arg_num , struct arg args [ ] ) {
assert ( ! arg_num ) ;
tgl_do_update_status ( 1 , 0 , 0 ) ;
}
void do_status_offline ( int arg_num , struct arg args [ ] ) {
assert ( ! arg_num ) ;
tgl_do_update_status ( 0 , 0 , 0 ) ;
}
void do_quit ( int arg_num , struct arg args [ ] ) {
exit ( 0 ) ;
}
void do_safe_quit ( int arg_num , struct arg args [ ] ) {
safe_quit = 1 ;
}
void do_set ( int arg_num , struct arg args [ ] ) {
int num = args [ 1 ] . num ;
if ( ! strcmp ( args [ 0 ] . str , " debug_verbosity " ) ) {
tgl_set_verbosity ( num ) ;
} else if ( ! strcmp ( args [ 0 ] . str , " log_level " ) ) {
log_level = num ;
} else if ( ! strcmp ( args [ 0 ] . str , " msg_num " ) ) {
msg_num_mode = num ;
} else if ( ! strcmp ( args [ 0 ] . str , " alert " ) ) {
alert_sound = num ;
}
}
void do_chat_with_peer ( int arg_num , struct arg args [ ] ) {
in_chat_mode = 1 ;
chat_mode_id = args [ 0 ] . P - > id ;
}
void do_delete_msg ( int arg_num , struct arg args [ ] ) {
tgl_do_delete_msg ( args [ 0 ] . num , 0 , 0 ) ;
}
void do_restore_msg ( int arg_num , struct arg args [ ] ) {
tgl_do_restore_msg ( args [ 0 ] . num , 0 , 0 ) ;
}
void do_create_group_chat ( int arg_num , struct arg args [ ] ) {
assert ( arg_num > = 1 & & arg_num < = 1000 ) ;
static tgl_peer_id_t ids [ 1000 ] ;
int i ;
for ( i = 0 ; i < arg_num - 1 ; i + + ) {
ids [ i ] = args [ i + 1 ] . P - > id ;
}
tgl_do_create_group_chat_ex ( arg_num - 1 , ids , args [ 0 ] . str , 0 , 0 ) ;
}
void do_chat_set_photo ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 2 ) ;
tgl_do_set_chat_photo ( args [ 0 ] . P - > id , args [ 1 ] . str , 0 , 0 ) ;
}
void do_set_profile_photo ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 1 ) ;
tgl_do_set_profile_photo ( args [ 0 ] . str , 0 , 0 ) ;
}
void do_accept_secret_chat ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 1 ) ;
tgl_do_accept_encr_chat_request ( & args [ 0 ] . P - > encr_chat , 0 , 0 ) ;
}
void do_set_ttl ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 2 ) ;
if ( args [ 0 ] . P - > encr_chat . state = = sc_ok ) {
tgl_do_set_encr_chat_ttl ( & args [ 0 ] . P - > encr_chat , args [ 1 ] . num , 0 , 0 ) ;
}
}
void do_export_card ( int arg_num , struct arg args [ ] ) {
assert ( ! arg_num ) ;
tgl_do_export_card ( print_card_gw , 0 ) ;
}
void do_import_card ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 1 ) ;
char * s = args [ 0 ] . str ;
int l = strlen ( s ) ;
if ( l > 0 ) {
int i ;
static int p [ 10 ] ;
int pp = 0 ;
int cur = 0 ;
int ok = 1 ;
for ( i = 0 ; i < l ; i + + ) {
if ( s [ i ] > = ' 0 ' & & s [ i ] < = ' 9 ' ) {
cur = cur * 16 + s [ i ] - ' 0 ' ;
} else if ( s [ i ] > = ' a ' & & s [ i ] < = ' f ' ) {
cur = cur * 16 + s [ i ] - ' a ' + 10 ;
} else if ( s [ i ] = = ' : ' ) {
if ( pp > = 9 ) {
ok = 0 ;
break ;
}
p [ pp + + ] = cur ;
cur = 0 ;
}
}
if ( ok ) {
p [ pp + + ] = cur ;
tgl_do_import_card ( pp , p , print_user_gw , 0 ) ;
}
}
}
void do_send_contact ( int arg_num , struct arg args [ ] ) {
assert ( arg_num = = 4 ) ;
tgl_do_send_contact ( args [ 0 ] . P - > id , args [ 1 ] . str , strlen ( args [ 1 ] . str ) , args [ 2 ] . str , strlen ( args [ 2 ] . str ) , args [ 3 ] . str , strlen ( args [ 3 ] . str ) , print_msg_gw , 0 ) ;
}
2014-08-25 12:17:17 -04:00
struct command commands [ ] = {
2014-09-18 09:10:42 -04:00
{ " help " , { ca_none } , do_help , " help \t Prints this help " } ,
{ " contact_list " , { ca_none } , do_contact_list , " contact_list \t Prints contact list " } ,
{ " stats " , { ca_none } , do_stats , " stats \t For debug purpose " } ,
{ " history " , { ca_peer , ca_number | ca_optional , ca_number | ca_optional , ca_none } , do_history , " history <peer> [limit] [offset] \t Prints messages with this peer (most recent message lower). Also marks messages as read " } ,
{ " dialog_list " , { ca_none } , do_dialog_list , " dialog_list \t List of last conversations " } ,
{ " send_photo " , { ca_peer , ca_file_name_end , ca_none } , do_send_photo , " send_photo <peer> <file> \t Sends photo to peer " } ,
{ " send_video " , { ca_peer , ca_file_name_end , ca_none } , do_send_video , " send_video <peer> <file> \t Sends video to peer " } ,
{ " send_audio " , { ca_peer , ca_file_name_end , ca_none } , do_send_audio , " send_audio <peer> <file> \t Sends audio to peer " } ,
{ " send_document " , { ca_peer , ca_file_name_end , ca_none } , do_send_document , " send_document <peer> <file> \t Sends document to peer " } ,
{ " send_text " , { ca_peer , ca_file_name_end , ca_none } , do_send_text , " send_text <peer> <file> \t Sends contents of text file as plain text message " } ,
{ " chat_info " , { ca_chat , ca_none } , do_chat_info , " chat_info <chat> \t Prints info about chat (id, members, admin, etc.) " } ,
{ " user_info " , { ca_user , ca_none } , do_user_info , " user_info <user> \t Prints info about user (id, last online, phone) " } ,
{ " fwd " , { ca_peer , ca_number , ca_none } , do_fwd , " fwd <peer> <msg-id> \t Forwards message to peer. Forward to secret chats is forbidden " } ,
{ " fwd_media " , { ca_peer , ca_number , ca_none } , do_fwd_media , " fwd <peer> <msg-id> \t Forwards message media to peer. Forward to secret chats is forbidden. Result slightly differs from fwd " } ,
{ " msg " , { ca_peer , ca_string_end , ca_none } , do_msg , " msg <peer> <text> \t Sends text message to peer " } ,
{ " rename_chat " , { ca_peer , ca_string_end , ca_none } , do_rename_chat , " rename_chat <chat> <new name> \t Renames chat " } ,
{ " load_photo " , { ca_number , ca_none } , do_load_photo , " load_photo <msg-id> \t Downloads file to downloads dirs. Prints file name after download end " } ,
{ " load_video " , { ca_number , ca_none } , do_load_video , " load_video <msg-id> \t Downloads file to downloads dirs. Prints file name after download end " } ,
{ " load_audio " , { ca_number , ca_none } , do_load_audio , " load_audio <msg-id> \t Downloads file to downloads dirs. Prints file name after download end " } ,
{ " load_document " , { ca_number , ca_none } , do_load_document , " load_document <msg-id> \t Downloads file to downloads dirs. Prints file name after download end " } ,
{ " load_video_thumb " , { ca_number , ca_none } , do_load_video_thumb , " load_video_thumb <msg-id> \t Downloads file to downloads dirs. Prints file name after download end " } ,
{ " load_document_thumb " , { ca_number , ca_none } , do_load_document_thumb , " load_document_thumb <msg-id> \t Downloads file to downloads dirs. Prints file name after download end " } ,
{ " view_photo " , { ca_number , ca_none } , do_open_photo , " view_photo <msg-id> \t Downloads file to downloads dirs. Then tries to open it with system default action " } ,
{ " view_video " , { ca_number , ca_none } , do_open_video , " view_video <msg-id> \t Downloads file to downloads dirs. Then tries to open it with system default action " } ,
{ " view_audio " , { ca_number , ca_none } , do_open_audio , " view_audio <msg-id> \t Downloads file to downloads dirs. Then tries to open it with system default action " } ,
{ " view_document " , { ca_number , ca_none } , do_open_document , " view_document <msg-id> \t Downloads file to downloads dirs. Then tries to open it with system default action " } ,
{ " view_video_thumb " , { ca_number , ca_none } , do_open_video_thumb , " view_video_thumb <msg-id> \t Downloads file to downloads dirs. Then tries to open it with system default action " } ,
{ " view_document_thumb " , { ca_number , ca_none } , do_open_document_thumb , " view_document_thumb <msg-id> \t Downloads file to downloads dirs. Then tries to open it with system default action " } ,
{ " add_contact " , { ca_string , ca_string , ca_string , ca_none } , do_add_contact , " add_contact <phone> <first name> <last name> \t Tries to add user to contact list " } ,
{ " del_contact " , { ca_user , ca_none } , do_del_contact , " del_contact <user> \t Deletes contact from contact list " } ,
{ " rename_contact " , { ca_user , ca_string , ca_string , ca_none } , do_rename_contact , " rename_contact <user> <first name> <last name> \t Renames contact " } ,
{ " show_license " , { ca_none } , do_show_license , " show_license \t Prints contents of GPL license " } ,
{ " search " , { ca_peer | ca_optional , ca_number | ca_optional , ca_number | ca_optional , ca_number | ca_optional , ca_string_end } , do_search , " search [peer] [from] [to] pattern \t Search for pattern in messages from date from to date to (unixtime) in messages with peer (if peer not present, in all messages) " } ,
{ " mark_read " , { ca_peer , ca_none } , do_mark_read , " mark_read <peer> \t Marks messages with peer as read " } ,
{ " visualize_key " , { ca_secret_chat , ca_none } , do_visualize_key , " visualize_key <secret chat> \t Prints visualization of encryption key (first 16 bytes sha1 of it in fact} " } ,
{ " create_secret_chat " , { ca_user , ca_none } , do_create_secret_chat , " create_secret_chat <user> \t Starts creation of secret chat " } ,
{ " chat_add_user " , { ca_chat , ca_user , ca_number | ca_optional , ca_none } , do_chat_add_user , " chat_add_user <chat> <user> [msgs-to-forward] \t Adds user to chat. Sends him last msgs-to-forward message from this chat. Default 100 " } ,
{ " chat_del_user " , { ca_chat , ca_user , ca_none } , do_chat_del_user , " chat_del_user <chat> <user> \t Deletes user from chat " } ,
{ " status_online " , { ca_none } , do_status_online , " status_online \t Sets status as online " } ,
{ " status_offline " , { ca_none } , do_status_offline , " status_offline \t Sets status as offline " } ,
{ " quit " , { ca_none } , do_quit , " quit \t Quits immideatly " } ,
{ " safe_quit " , { ca_none } , do_safe_quit , " safe_quit \t Waits for all queries to end, then quits " } ,
{ " set " , { ca_string , ca_number , ca_none } , do_set , " set <param> <value> \t Sets value of param. Currently available: log_level, debug_verbosity, alarm, msg_num " } ,
{ " chat_with_peer " , { ca_peer , ca_none } , do_chat_with_peer , " chat_with_peer <peer> \t Interface option. All input will be treated as messages to this peer. Type /quit to end this mode " } ,
{ " delete_msg " , { ca_number , ca_none } , do_delete_msg , " delete_msg <msg-id> \t Deletes message " } ,
{ " restore_msg " , { ca_number , ca_none } , do_restore_msg , " restore_msg <msg-id> \t Restores message. Only available shortly (one hour?) after deletion " } ,
{ " create_group_chat " , { ca_string , ca_user , ca_period , ca_none } , do_create_group_chat , " create_group_chat <name> <user>+ \t Creates group chat with users " } ,
{ " chat_set_photo " , { ca_chat , ca_file_name_end , ca_none } , do_chat_set_photo , " chat_set_photo <chat> <filename> \t Sets chat photo. Photo will be cropped to square " } ,
{ " set_profile_photo " , { ca_file_name_end , ca_none } , do_set_profile_photo , " set_profile_photo <filename> \t Sets profile photo. Photo will be cropped to square " } ,
{ " accept_secret_chat " , { ca_secret_chat , ca_none } , do_accept_secret_chat , " accept_secret_chat <secret chat> \t Accepts secret chat. Only useful with -E option " } ,
{ " set_ttl " , { ca_secret_chat , ca_number , ca_none } , do_set_ttl , " set_ttl <secret chat> \t Sets secret chat ttl. Client itself ignores ttl " } ,
{ " export_card " , { ca_none } , do_export_card , " export_card \t Prints card that can be imported by another user with import_card method " } ,
{ " import_card " , { ca_string , ca_none } , do_import_card , " import_card <card> \t Gets user by card and prints it name. You can then send messages to him as usual " } ,
{ " send_contact " , { ca_peer , ca_string , ca_string , ca_string } , do_send_contact , " send_contact <peer> <phone> <first-name> <last-name> \t Sends contact (not necessary telegram user) " } ,
{ 0 , { ca_none } , 0 , " " }
2014-08-25 12:17:17 -04:00
} ;
2013-11-30 13:52:13 -05:00
2014-08-25 12:17:17 -04:00
enum command_argument get_complete_mode ( void ) {
2014-09-17 17:03:20 -04:00
force_end_mode = 0 ;
2013-10-29 20:08:30 -04:00
line_ptr = rl_line_buffer ;
2014-09-17 17:03:20 -04:00
while ( 1 ) {
next_token ( ) ;
if ( cur_token_quoted ) { return ca_none ; }
if ( cur_token_len < = 0 ) { return ca_command ; }
if ( * cur_token = = ' [ ' ) {
if ( cur_token_end_str ) {
return ca_modifier ;
}
if ( cur_token [ cur_token_len - 1 ] ! = ' ] ' ) {
return ca_none ;
}
continue ;
}
break ;
2013-11-30 13:52:13 -05:00
}
2014-09-17 17:03:20 -04:00
if ( cur_token_quoted ) { return ca_none ; }
if ( cur_token_end_str ) { return ca_command ; }
if ( * cur_token = = ' ( ' ) { return ca_extf ; }
2014-08-25 12:17:17 -04:00
struct command * command = commands ;
2013-10-03 08:38:25 -04:00
int n = 0 ;
2014-08-25 12:17:17 -04:00
struct tgl_command ;
while ( command - > name ) {
2014-09-17 17:03:20 -04:00
if ( is_same_word ( cur_token , cur_token_len , command - > name ) ) {
2013-10-03 08:38:25 -04:00
break ;
}
n + + ;
command + + ;
}
2014-09-17 17:03:20 -04:00
if ( ! command - > name ) {
return ca_none ;
}
2014-08-25 12:17:17 -04:00
enum command_argument * flags = command - > args ;
2013-10-03 08:38:25 -04:00
while ( 1 ) {
2014-09-17 17:03:20 -04:00
if ( * flags = = ca_period ) {
flags - - ;
2014-08-25 12:17:17 -04:00
}
2014-09-17 17:03:20 -04:00
enum command_argument op = ( * flags ) & 255 ;
int opt = ( * flags ) & ca_optional ;
if ( op = = ca_none ) { return ca_none ; }
if ( op = = ca_string_end | | op = = ca_file_name_end ) {
next_token_end ( ) ;
if ( cur_token_len < 0 | | ! cur_token_end_str ) {
return ca_none ;
} else {
return op ;
}
2014-08-25 12:17:17 -04:00
}
2014-09-17 17:03:20 -04:00
char * save = line_ptr ;
next_token ( ) ;
if ( op = = ca_user | | op = = ca_chat | | op = = ca_secret_chat | | op = = ca_peer | | op = = ca_number ) {
if ( cur_token_quoted ) {
if ( opt ) {
line_ptr = save ;
flags + + ;
continue ;
} else {
return ca_none ;
}
} else {
if ( cur_token_end_str ) { return op ; }
int ok = 1 ;
switch ( op ) {
case ca_user :
ok = ( tgl_get_peer_type ( cur_token_user ( ) ) ! = NOT_FOUND ) ;
break ;
case ca_chat :
ok = ( tgl_get_peer_type ( cur_token_chat ( ) ) ! = NOT_FOUND ) ;
break ;
case ca_secret_chat :
ok = ( tgl_get_peer_type ( cur_token_encr_chat ( ) ) ! = NOT_FOUND ) ;
break ;
case ca_peer :
ok = ( tgl_get_peer_type ( cur_token_user ( ) ) ! = NOT_FOUND ) ;
break ;
case ca_number :
ok = ( cur_token_int ( ) ! = NOT_FOUND ) ;
break ;
default :
assert ( 0 ) ;
}
if ( opt & & ! ok ) {
line_ptr = save ;
flags + + ;
continue ;
}
if ( ! ok ) {
return ca_none ;
}
flags + + ;
continue ;
}
2014-08-25 12:17:17 -04:00
}
2014-09-17 17:03:20 -04:00
if ( op = = ca_string | | op = = ca_file_name ) {
if ( cur_token_end_str ) {
return op ;
} else {
flags + + ;
continue ;
}
2013-10-29 20:08:30 -04:00
}
2014-09-17 17:03:20 -04:00
assert ( 0 ) ;
2013-10-03 08:38:25 -04:00
}
}
int complete_string_list ( char * * list , int index , const char * text , int len , char * * R ) {
index + + ;
2013-10-03 12:09:06 -04:00
while ( list [ index ] & & strncmp ( list [ index ] , text , len ) ) {
2013-10-03 08:38:25 -04:00
index + + ;
}
2013-10-03 12:09:06 -04:00
if ( list [ index ] ) {
2014-01-10 09:37:56 -05:00
* R = strdup ( list [ index ] ) ;
2014-09-11 05:24:06 -04:00
assert ( * R ) ;
2013-10-03 08:38:25 -04:00
return index ;
} else {
* R = 0 ;
return - 1 ;
}
}
2014-08-25 12:17:17 -04:00
int complete_command_list ( int index , const char * text , int len , char * * R ) {
index + + ;
while ( commands [ index ] . name & & strncmp ( commands [ index ] . name , text , len ) ) {
index + + ;
}
if ( commands [ index ] . name ) {
* R = strdup ( commands [ index ] . name ) ;
2014-09-11 05:24:06 -04:00
assert ( * R ) ;
2014-08-25 12:17:17 -04:00
return index ;
} else {
* R = 0 ;
return - 1 ;
}
}
2013-10-03 08:38:25 -04:00
char * command_generator ( const char * text , int state ) {
2014-08-25 12:17:17 -04:00
static int len , index ;
static enum command_argument mode ;
2014-09-17 17:03:20 -04:00
static char * command_pos ;
static int command_len ;
2013-12-06 12:14:41 -05:00
if ( in_chat_mode ) {
char * R = 0 ;
index = complete_string_list ( in_chat_commands , index , text , rl_point , & R ) ;
return R ;
}
2013-10-03 12:09:06 -04:00
2013-10-28 17:56:17 -04:00
char c = 0 ;
2014-09-17 17:03:20 -04:00
c = rl_line_buffer [ rl_point ] ;
rl_line_buffer [ rl_point ] = 0 ;
2013-10-03 08:38:25 -04:00
if ( ! state ) {
len = strlen ( text ) ;
index = - 1 ;
2013-10-28 17:56:17 -04:00
2013-10-03 08:38:25 -04:00
mode = get_complete_mode ( ) ;
2014-09-17 17:03:20 -04:00
command_pos = cur_token ;
command_len = cur_token_len ;
2013-10-03 08:38:25 -04:00
} else {
if ( index = = - 1 ) { return 0 ; }
}
2014-08-25 12:17:17 -04:00
if ( mode = = ca_none | | mode = = ca_string | | mode = = ca_string_end | | mode = = ca_number ) {
2013-10-28 17:57:22 -04:00
if ( c ) { rl_line_buffer [ rl_point ] = c ; }
return 0 ;
}
2014-09-17 17:03:20 -04:00
assert ( command_len > = 0 ) ;
2013-10-03 08:38:25 -04:00
char * R = 0 ;
2014-09-17 17:03:20 -04:00
switch ( mode & 255 ) {
2014-08-25 12:17:17 -04:00
case ca_command :
2014-09-17 17:03:20 -04:00
index = complete_command_list ( index , command_pos , command_len , & R ) ;
2013-10-28 17:56:17 -04:00
if ( c ) { rl_line_buffer [ rl_point ] = c ; }
2013-10-03 08:38:25 -04:00
return R ;
2014-08-25 12:17:17 -04:00
case ca_user :
2014-09-17 17:03:20 -04:00
index = tgl_complete_user_list ( index , command_pos , command_len , & R ) ;
2013-10-28 17:56:17 -04:00
if ( c ) { rl_line_buffer [ rl_point ] = c ; }
2013-10-03 08:38:25 -04:00
return R ;
2014-08-25 12:17:17 -04:00
case ca_peer :
2014-09-17 17:03:20 -04:00
index = tgl_complete_peer_list ( index , command_pos , command_len , & R ) ;
2013-10-28 17:56:17 -04:00
if ( c ) { rl_line_buffer [ rl_point ] = c ; }
2013-10-03 08:38:25 -04:00
return R ;
2014-08-25 12:17:17 -04:00
case ca_file_name :
case ca_file_name_end :
2014-09-17 17:03:20 -04:00
R = rl_filename_completion_function ( command_pos , state ) ;
2013-10-28 17:56:17 -04:00
if ( c ) { rl_line_buffer [ rl_point ] = c ; }
return R ;
2014-08-25 12:17:17 -04:00
case ca_chat :
2014-09-17 17:03:20 -04:00
index = tgl_complete_chat_list ( index , command_pos , command_len , & R ) ;
2013-10-28 17:56:17 -04:00
if ( c ) { rl_line_buffer [ rl_point ] = c ; }
2013-10-23 06:24:59 -04:00
return R ;
2014-08-25 12:17:17 -04:00
case ca_secret_chat :
2014-09-17 17:03:20 -04:00
index = tgl_complete_encr_chat_list ( index , command_pos , command_len , & R ) ;
2013-11-04 18:15:24 -05:00
if ( c ) { rl_line_buffer [ rl_point ] = c ; }
return R ;
2014-08-25 12:17:17 -04:00
case ca_modifier :
2014-09-17 17:03:20 -04:00
index = complete_string_list ( modifiers , index , command_pos , command_len , & R ) ;
2013-11-30 13:52:13 -05:00
if ( c ) { rl_line_buffer [ rl_point ] = c ; }
return R ;
2014-09-10 07:52:42 -04:00
case ca_extf :
index = tglf_extf_autocomplete ( text , len , index , & R , rl_line_buffer , rl_point ) ;
2014-09-17 17:03:20 -04:00
if ( c ) { rl_line_buffer [ rl_point ] = c ; }
2014-09-10 07:52:42 -04:00
return R ;
2013-10-03 08:38:25 -04:00
default :
2013-10-28 17:56:17 -04:00
if ( c ) { rl_line_buffer [ rl_point ] = c ; }
2013-10-03 08:38:25 -04:00
return 0 ;
}
}
char * * complete_text ( char * text , int start UU , int end UU ) {
return ( char * * ) rl_completion_matches ( text , command_generator ) ;
}
2013-11-25 12:16:34 -05:00
int count = 1 ;
void work_modifier ( const char * s , int l ) {
if ( is_same_word ( s , l , " [offline] " ) ) {
offline_mode = 1 ;
}
# ifdef ALLOW_MULT
if ( sscanf ( s , " [x%d] " , & count ) > = 1 ) {
}
# endif
2013-10-29 20:08:30 -04:00
}
2014-08-14 18:16:01 -04:00
void print_msg_list_gw ( void * extra , int success , int num , struct tgl_message * ML [ ] ) {
if ( ! success ) { return ; }
print_start ( ) ;
int i ;
for ( i = num - 1 ; i > = 0 ; i - - ) {
print_message ( ML [ i ] ) ;
}
print_end ( ) ;
}
void print_msg_gw ( void * extra , int success , struct tgl_message * M ) {
if ( ! success ) { return ; }
print_start ( ) ;
print_message ( M ) ;
print_end ( ) ;
}
void print_user_list_gw ( void * extra , int success , int num , struct tgl_user * UL [ ] ) {
if ( ! success ) { return ; }
print_start ( ) ;
int i ;
for ( i = num - 1 ; i > = 0 ; i - - ) {
print_user_name ( UL [ i ] - > id , ( void * ) UL [ i ] ) ;
2014-08-18 12:39:04 -04:00
printf ( " \n " ) ;
2014-08-14 18:16:01 -04:00
}
print_end ( ) ;
}
2014-08-29 11:46:04 -04:00
void print_user_gw ( void * extra , int success , struct tgl_user * U ) {
if ( ! success ) { return ; }
print_start ( ) ;
print_user_name ( U - > id , ( void * ) U ) ;
printf ( " \n " ) ;
print_end ( ) ;
}
2014-08-14 18:16:01 -04:00
void print_filename_gw ( void * extra , int success , char * name ) {
if ( ! success ) { return ; }
print_start ( ) ;
printf ( " Saved to %s \n " , name ) ;
print_end ( ) ;
}
void open_filename_gw ( void * extra , int success , char * name ) {
if ( ! success ) { return ; }
static char buf [ PATH_MAX ] ;
if ( snprintf ( buf , sizeof ( buf ) , OPEN_BIN , name ) > = ( int ) sizeof ( buf ) ) {
logprintf ( " Open image command buffer overflow \n " ) ;
} else {
int x = system ( buf ) ;
if ( x < 0 ) {
logprintf ( " Can not open image viewer: %m \n " ) ;
logprintf ( " Image is at %s \n " , name ) ;
}
}
}
void print_chat_info_gw ( void * extra , int success , struct tgl_chat * C ) {
2014-08-18 12:39:04 -04:00
if ( ! success ) {
vlogprintf ( E_NOTICE , " Failed to get chat info \n " ) ;
return ;
}
2014-08-14 18:16:01 -04:00
print_start ( ) ;
tgl_peer_t * U = ( void * ) C ;
push_color ( COLOR_YELLOW ) ;
printf ( " Chat " ) ;
print_chat_name ( U - > id , U ) ;
2014-09-03 12:32:56 -04:00
printf ( " (id %d) members: \n " , tgl_get_peer_id ( U - > id ) ) ;
2014-08-14 18:16:01 -04:00
int i ;
for ( i = 0 ; i < C - > user_list_size ; i + + ) {
printf ( " \t \t " ) ;
print_user_name ( TGL_MK_USER ( C - > user_list [ i ] . user_id ) , tgl_peer_get ( TGL_MK_USER ( C - > user_list [ i ] . user_id ) ) ) ;
printf ( " invited by " ) ;
print_user_name ( TGL_MK_USER ( C - > user_list [ i ] . inviter_id ) , tgl_peer_get ( TGL_MK_USER ( C - > user_list [ i ] . inviter_id ) ) ) ;
printf ( " at " ) ;
print_date_full ( C - > user_list [ i ] . date ) ;
if ( C - > user_list [ i ] . user_id = = C - > admin_id ) {
printf ( " admin " ) ;
}
printf ( " \n " ) ;
}
pop_color ( ) ;
print_end ( ) ;
}
void print_user_info_gw ( void * extra , int success , struct tgl_user * U ) {
if ( ! success ) { return ; }
tgl_peer_t * C = ( void * ) U ;
print_start ( ) ;
push_color ( COLOR_YELLOW ) ;
printf ( " User " ) ;
print_user_name ( U - > id , C ) ;
2014-08-24 12:49:06 -04:00
printf ( " (#%d): \n " , tgl_get_peer_id ( U - > id ) ) ;
2014-08-14 18:16:01 -04:00
printf ( " \t real name: %s %s \n " , U - > real_first_name , U - > real_last_name ) ;
printf ( " \t phone: %s \n " , U - > phone ) ;
if ( U - > status . online > 0 ) {
printf ( " \t online \n " ) ;
} else {
printf ( " \t offline (was online " ) ;
print_date_full ( U - > status . when ) ;
printf ( " ) \n " ) ;
}
pop_color ( ) ;
print_end ( ) ;
}
void print_secret_chat_gw ( void * extra , int success , struct tgl_secret_chat * E ) {
if ( ! success ) { return ; }
print_start ( ) ;
push_color ( COLOR_YELLOW ) ;
printf ( " Encrypted chat " ) ;
print_encr_chat_name ( E - > id , ( void * ) E ) ;
printf ( " is now in wait state \n " ) ;
pop_color ( ) ;
print_end ( ) ;
}
2013-12-06 12:14:41 -05:00
2014-08-14 18:16:01 -04:00
void print_dialog_list_gw ( void * extra , int success , int size , tgl_peer_id_t peers [ ] , int last_msg_id [ ] , int unread_count [ ] ) {
if ( ! success ) { return ; }
print_start ( ) ;
push_color ( 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 ( peers [ i ] ) ;
printf ( " User " ) ;
print_user_name ( peers [ i ] , UC ) ;
printf ( " : %d unread \n " , unread_count [ i ] ) ;
break ;
case TGL_PEER_CHAT :
UC = tgl_peer_get ( peers [ i ] ) ;
printf ( " Chat " ) ;
print_chat_name ( peers [ i ] , UC ) ;
printf ( " : %d unread \n " , unread_count [ i ] ) ;
break ;
}
}
pop_color ( ) ;
print_end ( ) ;
}
2013-12-06 12:14:41 -05:00
void interpreter_chat_mode ( char * line ) {
2014-02-22 20:06:57 -05:00
if ( line = = NULL | | /* EOF received */
! strncmp ( line , " /exit " , 5 ) | | ! strncmp ( line , " /quit " , 5 ) ) {
2013-12-06 12:14:41 -05:00
in_chat_mode = 0 ;
update_prompt ( ) ;
return ;
}
2013-12-19 17:50:31 -05:00
if ( ! strncmp ( line , " /history " , 8 ) ) {
int limit = 40 ;
2014-01-10 07:37:07 -05:00
sscanf ( line , " /history %99d " , & limit ) ;
2013-12-19 17:50:31 -05:00
if ( limit < 0 | | limit > 1000 ) { limit = 40 ; }
2014-08-14 18:16:01 -04:00
tgl_do_get_history ( chat_mode_id , limit , offline_mode , print_msg_list_gw , 0 ) ;
2013-12-19 17:50:31 -05:00
return ;
}
if ( ! strncmp ( line , " /read " , 5 ) ) {
2014-08-14 18:16:01 -04:00
tgl_do_mark_read ( chat_mode_id , 0 , 0 ) ;
2013-12-19 17:50:31 -05:00
return ;
}
2014-08-20 12:41:56 -04:00
if ( strlen ( line ) > 0 ) {
2014-08-20 12:36:45 -04:00
tgl_do_send_message ( chat_mode_id , line , strlen ( line ) , 0 , 0 ) ;
2014-02-12 18:52:25 -05:00
}
2013-12-06 12:14:41 -05:00
}
2014-08-21 16:35:27 -04:00
# define MAX_UNREAD_MESSAGE_COUNT 10000
struct tgl_message * unread_message_list [ MAX_UNREAD_MESSAGE_COUNT ] ;
int unread_message_count ;
struct event * unread_message_event ;
void print_read_list ( int num , struct tgl_message * list [ ] ) {
int i ;
print_start ( ) ;
for ( i = 0 ; i < num ; i + + ) if ( list [ i ] ) {
tgl_peer_id_t to_id ;
if ( tgl_get_peer_type ( list [ i ] - > to_id ) = = TGL_PEER_USER & & tgl_get_peer_id ( list [ i ] - > to_id ) = = tgl_state . our_id ) {
to_id = list [ i ] - > from_id ;
} else {
to_id = list [ i ] - > to_id ;
}
int j ;
int c1 = 0 ;
int c2 = 0 ;
for ( j = i ; j < num ; j + + ) if ( list [ j ] ) {
tgl_peer_id_t end_id ;
if ( tgl_get_peer_type ( list [ j ] - > to_id ) = = TGL_PEER_USER & & tgl_get_peer_id ( list [ j ] - > to_id ) = = tgl_state . our_id ) {
end_id = list [ j ] - > from_id ;
} else {
end_id = list [ j ] - > to_id ;
}
if ( ! tgl_cmp_peer_id ( to_id , end_id ) ) {
if ( list [ j ] - > out ) {
c1 + + ;
} else {
c2 + + ;
}
list [ j ] = 0 ;
}
}
assert ( c1 + c2 > 0 ) ;
push_color ( COLOR_YELLOW ) ;
switch ( tgl_get_peer_type ( to_id ) ) {
case TGL_PEER_USER :
printf ( " User " ) ;
print_user_name ( to_id , tgl_peer_get ( to_id ) ) ;
break ;
case TGL_PEER_CHAT :
printf ( " Chat " ) ;
print_chat_name ( to_id , tgl_peer_get ( to_id ) ) ;
break ;
case TGL_PEER_ENCR_CHAT :
printf ( " Secret chat " ) ;
2014-08-27 12:59:42 -04:00
print_encr_chat_name ( to_id , tgl_peer_get ( to_id ) ) ;
2014-08-21 16:35:27 -04:00
break ;
default :
assert ( 0 ) ;
}
printf ( " marked read %d outbox and %d inbox messages \n " , c1 , c2 ) ;
pop_color ( ) ;
}
print_end ( ) ;
}
void unread_message_alarm ( evutil_socket_t fd , short what , void * arg ) {
print_read_list ( unread_message_count , unread_message_list ) ;
unread_message_count = 0 ;
event_free ( unread_message_event ) ;
unread_message_event = 0 ;
}
2014-08-14 18:16:01 -04:00
void mark_read_upd ( int num , struct tgl_message * list [ ] ) {
2014-08-21 11:38:51 -04:00
if ( ! binlog_read ) { return ; }
2014-08-14 18:16:01 -04:00
if ( log_level < 1 ) { return ; }
2014-08-21 11:38:51 -04:00
2014-08-21 16:35:27 -04:00
if ( unread_message_count + num < = MAX_UNREAD_MESSAGE_COUNT ) {
memcpy ( unread_message_list + unread_message_count , list , num * sizeof ( void * ) ) ;
unread_message_count + = num ;
if ( ! unread_message_event ) {
unread_message_event = evtimer_new ( tgl_state . ev_base , unread_message_alarm , 0 ) ;
static struct timeval ptimeout = { 1 , 0 } ;
event_add ( unread_message_event , & ptimeout ) ;
}
} else {
print_read_list ( unread_message_count , unread_message_list ) ;
print_read_list ( num , list ) ;
unread_message_count = 0 ;
if ( unread_message_event ) {
event_free ( unread_message_event ) ;
unread_message_event = 0 ;
}
}
/*
tgl_peer_id_t to_id = list [ 0 ] - > to_id ;
2014-08-21 11:38:51 -04:00
int ok = 1 ;
int i ;
for ( i = 1 ; i < num ; i + + ) {
if ( tgl_cmp_peer_id ( to_id , list [ i ] - > to_id ) ) {
ok = 0 ;
}
}
2014-08-14 18:16:01 -04:00
print_start ( ) ;
push_color ( COLOR_YELLOW ) ;
2014-08-21 11:38:51 -04:00
if ( ! ok ) {
printf ( " %d messages mark read \n " , num ) ;
} else {
printf ( " %d messages mark read in " , num ) ;
switch ( tgl_get_peer_type ( to_id ) ) {
case TGL_PEER_USER :
printf ( " user " ) ;
print_user_name ( to_id , tgl_peer_get ( to_id ) ) ;
break ;
case TGL_PEER_CHAT :
printf ( " chat " ) ;
print_chat_name ( to_id , tgl_peer_get ( to_id ) ) ;
break ;
case TGL_PEER_ENCR_CHAT :
printf ( " secret chat " ) ;
print_chat_name ( to_id , tgl_peer_get ( to_id ) ) ;
break ;
}
printf ( " \n " ) ;
}
2014-08-14 18:16:01 -04:00
pop_color ( ) ;
2014-08-21 16:35:27 -04:00
print_end ( ) ; */
2014-08-14 18:16:01 -04:00
}
void type_notification_upd ( struct tgl_user * U ) {
2014-09-09 13:05:36 -04:00
if ( log_level < 2 | | disable_output ) { return ; }
2014-08-14 18:16:01 -04:00
print_start ( ) ;
push_color ( COLOR_YELLOW ) ;
printf ( " User " ) ;
print_user_name ( U - > id , ( void * ) U ) ;
printf ( " is typing \n " ) ;
pop_color ( ) ;
print_end ( ) ;
}
void type_in_chat_notification_upd ( struct tgl_user * U , struct tgl_chat * C ) {
2014-09-09 13:05:36 -04:00
if ( log_level < 2 | | disable_output ) { return ; }
2014-08-14 18:16:01 -04:00
print_start ( ) ;
push_color ( COLOR_YELLOW ) ;
printf ( " User " ) ;
print_user_name ( U - > id , ( void * ) U ) ;
printf ( " is typing in chat " ) ;
print_chat_name ( C - > id , ( void * ) C ) ;
printf ( " \n " ) ;
pop_color ( ) ;
print_end ( ) ;
}
2014-08-18 12:39:04 -04:00
void print_message_gw ( struct tgl_message * M ) {
2014-08-21 11:38:51 -04:00
# ifdef USE_LUA
lua_new_msg ( M ) ;
# endif
2014-09-09 13:05:36 -04:00
if ( disable_output ) { return ; }
2014-08-21 11:38:51 -04:00
if ( ! binlog_read ) { return ; }
2014-08-18 12:39:04 -04:00
print_start ( ) ;
print_message ( M ) ;
print_end ( ) ;
}
2014-08-21 11:38:51 -04:00
void our_id_gw ( int id ) {
# ifdef USE_LUA
lua_our_id ( id ) ;
# endif
}
void print_peer_updates ( int flags ) {
if ( flags & TGL_UPDATE_PHONE ) {
printf ( " phone " ) ;
}
if ( flags & TGL_UPDATE_CONTACT ) {
printf ( " contact " ) ;
}
if ( flags & TGL_UPDATE_PHOTO ) {
printf ( " photo " ) ;
}
if ( flags & TGL_UPDATE_BLOCKED ) {
printf ( " blocked " ) ;
}
if ( flags & TGL_UPDATE_REAL_NAME ) {
printf ( " name " ) ;
}
if ( flags & TGL_UPDATE_NAME ) {
printf ( " contact_name " ) ;
}
if ( flags & TGL_UPDATE_REQUESTED ) {
printf ( " status " ) ;
}
if ( flags & TGL_UPDATE_WORKING ) {
printf ( " status " ) ;
}
if ( flags & TGL_UPDATE_FLAGS ) {
printf ( " flags " ) ;
}
if ( flags & TGL_UPDATE_TITLE ) {
printf ( " title " ) ;
}
if ( flags & TGL_UPDATE_ADMIN ) {
printf ( " admin " ) ;
}
if ( flags & TGL_UPDATE_MEMBERS ) {
printf ( " members " ) ;
}
if ( flags & TGL_UPDATE_ACCESS_HASH ) {
printf ( " access_hash " ) ;
}
}
void user_update_gw ( struct tgl_user * U , unsigned flags ) {
# ifdef USE_LUA
lua_user_update ( U , flags ) ;
# endif
2014-09-09 13:05:36 -04:00
if ( disable_output ) { return ; }
2014-08-21 11:38:51 -04:00
if ( ! binlog_read ) { return ; }
if ( ! ( flags & TGL_UPDATE_CREATED ) ) {
print_start ( ) ;
push_color ( COLOR_YELLOW ) ;
printf ( " User " ) ;
print_user_name ( U - > id , ( void * ) U ) ;
if ( ! ( flags & TGL_UPDATE_DELETED ) ) {
printf ( " updated " ) ;
print_peer_updates ( flags ) ;
} else {
printf ( " deleted " ) ;
}
printf ( " \n " ) ;
pop_color ( ) ;
print_end ( ) ;
}
}
void chat_update_gw ( struct tgl_chat * U , unsigned flags ) {
# ifdef USE_LUA
lua_chat_update ( U , flags ) ;
# endif
2014-09-09 13:05:36 -04:00
if ( disable_output ) { return ; }
2014-08-21 11:38:51 -04:00
if ( ! binlog_read ) { return ; }
if ( ! ( flags & TGL_UPDATE_CREATED ) ) {
print_start ( ) ;
push_color ( COLOR_YELLOW ) ;
printf ( " Chat " ) ;
print_chat_name ( U - > id , ( void * ) U ) ;
if ( ! ( flags & TGL_UPDATE_DELETED ) ) {
printf ( " updated " ) ;
print_peer_updates ( flags ) ;
} else {
printf ( " deleted " ) ;
}
printf ( " \n " ) ;
pop_color ( ) ;
print_end ( ) ;
}
}
void secret_chat_update_gw ( struct tgl_secret_chat * U , unsigned flags ) {
# ifdef USE_LUA
lua_secret_chat_update ( U , flags ) ;
# endif
2014-09-09 13:05:36 -04:00
if ( disable_output ) { return ; }
2014-08-21 11:38:51 -04:00
if ( ! binlog_read ) { return ; }
2014-08-31 10:18:19 -04:00
if ( ( flags & TGL_UPDATE_WORKING ) | | ( flags & TGL_UPDATE_DELETED ) ) {
write_secret_chat_file ( ) ;
}
2014-08-26 12:06:30 -04:00
if ( ( flags & TGL_UPDATE_REQUESTED ) & & ! disable_auto_accept ) {
tgl_do_accept_encr_chat_request ( U , 0 , 0 ) ;
}
2014-08-21 11:38:51 -04:00
if ( ! ( flags & TGL_UPDATE_CREATED ) ) {
print_start ( ) ;
push_color ( COLOR_YELLOW ) ;
printf ( " Secret chat " ) ;
print_encr_chat_name ( U - > id , ( void * ) U ) ;
if ( ! ( flags & TGL_UPDATE_DELETED ) ) {
printf ( " updated " ) ;
print_peer_updates ( flags ) ;
} else {
printf ( " deleted " ) ;
}
printf ( " \n " ) ;
pop_color ( ) ;
print_end ( ) ;
}
}
2014-08-29 11:46:04 -04:00
void print_card_gw ( void * extra , int success , int size , int * card ) {
assert ( success ) ;
print_start ( ) ;
printf ( " Card: " ) ;
int i ;
for ( i = 0 ; i < size ; i + + ) {
printf ( " %08x%c " , card [ i ] , i = = size - 1 ? ' \n ' : ' : ' ) ;
}
print_end ( ) ;
}
2014-09-10 07:52:42 -04:00
void callback_extf ( void * extra , int success , char * buf ) {
print_start ( ) ;
printf ( " %s \n " , buf ) ;
print_end ( ) ;
}
2014-08-14 18:16:01 -04:00
struct tgl_update_callback upd_cb = {
2014-08-18 12:39:04 -04:00
. new_msg = print_message_gw ,
2014-08-14 18:16:01 -04:00
. marked_read = mark_read_upd ,
. logprintf = logprintf ,
. type_notification = type_notification_upd ,
. type_in_chat_notification = type_in_chat_notification_upd ,
. type_in_secret_chat_notification = 0 ,
. status_notification = 0 ,
. user_registered = 0 ,
. user_activated = 0 ,
. new_authorization = 0 ,
2014-08-21 11:38:51 -04:00
. user_update = user_update_gw ,
. chat_update = chat_update_gw ,
. secret_chat_update = secret_chat_update_gw ,
. msg_receive = print_message_gw ,
. our_id = our_id_gw
2014-08-14 18:16:01 -04:00
} ;
2013-10-03 08:38:25 -04:00
void interpreter ( char * line UU ) {
2014-09-17 17:03:20 -04:00
force_end_mode = 1 ;
2013-10-29 20:08:30 -04:00
assert ( ! in_readline ) ;
in_readline = 1 ;
2013-12-06 12:14:41 -05:00
if ( in_chat_mode ) {
interpreter_chat_mode ( line ) ;
in_readline = 0 ;
return ;
}
line_ptr = line ;
2013-11-25 12:16:34 -05:00
offline_mode = 0 ;
count = 1 ;
2013-10-29 20:08:30 -04:00
if ( ! line ) {
in_readline = 0 ;
return ;
}
2013-10-13 06:18:08 -04:00
if ( line & & * line ) {
add_history ( line ) ;
}
2014-09-17 17:03:20 -04:00
if ( * line = = ' ( ' ) {
tgl_do_send_extf ( line , strlen ( line ) , callback_extf , 0 ) ;
in_readline = 0 ;
return ;
}
2013-10-29 20:08:30 -04:00
while ( 1 ) {
2014-09-17 17:03:20 -04:00
next_token ( ) ;
if ( cur_token_quoted ) {
in_readline = 0 ;
return ;
2013-10-29 20:08:30 -04:00
}
2013-10-31 19:18:34 -04:00
2014-09-17 17:03:20 -04:00
if ( cur_token_len < = 0 ) {
in_readline = 0 ;
return ;
2013-10-29 20:08:30 -04:00
}
2014-09-17 17:03:20 -04:00
if ( * cur_token = = ' [ ' ) {
if ( cur_token_end_str ) {
in_readline = 0 ;
return ;
}
if ( cur_token [ cur_token_len - 1 ] ! = ' ] ' ) {
in_readline = 0 ;
return ;
}
work_modifier ( cur_token , cur_token_len ) ;
continue ;
2013-10-30 06:10:16 -04:00
}
2014-09-17 17:03:20 -04:00
break ;
}
if ( cur_token_quoted | | cur_token_end_str ) {
in_readline = 0 ;
return ;
}
struct command * command = commands ;
int n = 0 ;
struct tgl_command ;
while ( command - > name ) {
if ( is_same_word ( cur_token , cur_token_len , command - > name ) ) {
break ;
2013-10-30 06:10:16 -04:00
}
2014-09-17 17:03:20 -04:00
n + + ;
command + + ;
}
if ( ! command - > name ) {
in_readline = 0 ;
return ;
}
enum command_argument * flags = command - > args ;
void ( * fun ) ( int , struct arg [ ] ) = command - > fun ;
int args_num = 0 ;
static struct arg args [ 1000 ] ;
while ( 1 ) {
assert ( args_num < 1000 ) ;
args [ args_num ] . flags = 0 ;
int period = 0 ;
if ( * flags = = ca_period ) {
period = 1 ;
flags - - ;
2013-10-30 06:10:16 -04:00
}
2014-09-17 17:03:20 -04:00
enum command_argument op = ( * flags ) & 255 ;
int opt = ( * flags ) & ca_optional ;
if ( op = = ca_none ) {
next_token ( ) ;
if ( cur_token_end_str ) {
fun ( args_num , args ) ;
}
break ;
2013-10-30 06:10:16 -04:00
}
2014-09-17 17:03:20 -04:00
if ( op = = ca_string_end | | op = = ca_file_name_end ) {
next_token_end ( ) ;
if ( cur_token_len < 0 ) {
break ;
} else {
args [ args_num ] . flags = 1 ;
args [ args_num + + ] . str = strndup ( cur_token , cur_token_len ) ;
fun ( args_num , args ) ;
break ;
}
2013-11-01 11:02:28 -04:00
}
2014-09-17 17:03:20 -04:00
char * save = line_ptr ;
next_token ( ) ;
if ( period & & cur_token_end_str ) {
fun ( args_num , args ) ;
break ;
2013-11-06 18:12:40 -05:00
}
2014-09-17 17:03:20 -04:00
if ( op = = ca_user | | op = = ca_chat | | op = = ca_secret_chat | | op = = ca_peer | | op = = ca_number ) {
if ( cur_token_quoted ) {
if ( opt ) {
if ( op ! = ca_number ) {
args [ args_num + + ] . P = 0 ;
} else {
args [ args_num + + ] . num = NOT_FOUND ;
}
line_ptr = save ;
flags + + ;
continue ;
2014-08-26 17:03:50 -04:00
} else {
2014-09-17 17:03:20 -04:00
break ;
}
} else {
if ( cur_token_end_str ) {
if ( opt ) {
if ( op ! = ca_number ) {
args [ args_num + + ] . P = 0 ;
} else {
args [ args_num + + ] . num = NOT_FOUND ;
}
line_ptr = save ;
flags + + ;
continue ;
} else {
2014-08-26 17:03:50 -04:00
break ;
}
}
2014-09-17 17:03:20 -04:00
int ok = 1 ;
switch ( op ) {
case ca_user :
args [ args_num + + ] . P = mk_peer ( cur_token_user ( ) ) ;
ok = args [ args_num - 1 ] . P ! = NULL ;
break ;
case ca_chat :
args [ args_num + + ] . P = mk_peer ( cur_token_chat ( ) ) ;
ok = args [ args_num - 1 ] . P ! = NULL ;
break ;
case ca_secret_chat :
args [ args_num + + ] . P = mk_peer ( cur_token_encr_chat ( ) ) ;
ok = args [ args_num - 1 ] . P ! = NULL ;
break ;
case ca_peer :
args [ args_num + + ] . P = mk_peer ( cur_token_peer ( ) ) ;
ok = args [ args_num - 1 ] . P ! = NULL ;
break ;
case ca_number :
args [ args_num + + ] . num = cur_token_int ( ) ;
ok = ( args [ args_num - 1 ] . num ! = NOT_FOUND ) ;
break ;
default :
assert ( 0 ) ;
}
if ( opt & & ! ok ) {
if ( op ! = ca_number ) {
args [ args_num + + ] . P = 0 ;
} else {
args [ args_num + + ] . num = NOT_FOUND ;
2014-08-29 11:46:04 -04:00
}
2014-09-17 17:03:20 -04:00
line_ptr = save ;
flags + + ;
continue ;
2014-08-29 11:46:04 -04:00
}
2014-09-17 17:03:20 -04:00
if ( ! ok ) {
break ;
}
flags + + ;
continue ;
2014-08-29 11:46:04 -04:00
}
}
2014-09-17 17:03:20 -04:00
if ( op = = ca_string | | op = = ca_file_name ) {
if ( cur_token_end_str | | cur_token_len < 0 ) {
break ;
} else {
args [ args_num ] . flags = 1 ;
args [ args_num + + ] . str = strndup ( cur_token , cur_token_len ) ;
flags + + ;
continue ;
}
2014-09-11 07:04:04 -04:00
}
2014-09-17 17:03:20 -04:00
assert ( 0 ) ;
2013-10-11 16:52:20 -04:00
}
2014-09-17 17:03:20 -04:00
int i ;
for ( i = 0 ; i < args_num ; i + + ) {
if ( args [ i ] . flags & 1 ) {
free ( args [ i ] . str ) ;
}
2013-11-25 12:16:34 -05:00
}
2014-09-17 17:03:20 -04:00
2013-11-15 07:59:06 -05:00
update_prompt ( ) ;
2013-10-29 20:08:30 -04:00
in_readline = 0 ;
2013-10-11 16:52:20 -04:00
}
2013-10-13 06:18:08 -04:00
int readline_active ;
2013-10-11 16:52:20 -04:00
void rprintf ( const char * format , . . . ) {
2013-11-06 17:16:46 -05:00
print_start ( ) ;
2013-10-13 06:18:08 -04:00
va_list ap ;
va_start ( ap , format ) ;
vfprintf ( stdout , format , ap ) ;
va_end ( ap ) ;
2013-11-06 17:16:46 -05:00
print_end ( ) ;
2013-10-13 06:18:08 -04:00
}
2013-10-18 15:30:24 -04:00
int saved_point ;
char * saved_line ;
int prompt_was ;
void print_start ( void ) {
2013-10-29 20:08:30 -04:00
if ( in_readline ) { return ; }
2014-08-26 14:26:00 -04:00
if ( readline_disabled ) { return ; }
2013-10-18 15:30:24 -04:00
assert ( ! prompt_was ) ;
if ( readline_active ) {
saved_point = rl_point ;
2013-11-09 17:47:19 -05:00
# ifdef READLINE_GNU
2014-08-14 18:16:01 -04:00
saved_line = malloc ( rl_end + 1 ) ;
2014-09-11 05:24:06 -04:00
assert ( saved_line ) ;
2014-01-10 09:37:56 -05:00
saved_line [ rl_end ] = 0 ;
memcpy ( saved_line , rl_line_buffer , rl_end ) ;
2013-10-18 15:30:24 -04:00
rl_save_prompt ( ) ;
rl_replace_line ( " " , 0 ) ;
2013-11-09 17:47:19 -05:00
# else
assert ( rl_end > = 0 ) ;
2014-08-14 18:16:01 -04:00
saved_line = malloc ( rl_end + 1 ) ;
2014-09-11 05:24:06 -04:00
assert ( saved_line ) ;
2013-11-09 17:47:19 -05:00
memcpy ( saved_line , rl_line_buffer , rl_end + 1 ) ;
rl_line_buffer [ 0 ] = 0 ;
set_prompt ( " " ) ;
# endif
2013-10-18 15:30:24 -04:00
rl_redisplay ( ) ;
}
prompt_was = 1 ;
}
2013-11-09 17:47:19 -05:00
2013-10-18 15:30:24 -04:00
void print_end ( void ) {
2013-10-29 20:08:30 -04:00
if ( in_readline ) { return ; }
2014-08-26 14:26:00 -04:00
if ( readline_disabled ) {
fflush ( stdout ) ;
return ;
}
2013-10-18 15:30:24 -04:00
assert ( prompt_was ) ;
if ( readline_active ) {
2013-11-09 17:47:19 -05:00
set_prompt ( get_default_prompt ( ) ) ;
# if READLINE_GNU
2013-10-18 15:30:24 -04:00
rl_replace_line ( saved_line , 0 ) ;
2013-11-09 17:47:19 -05:00
# else
memcpy ( rl_line_buffer , saved_line , rl_end + 1 ) ; // not safe, but I hope this would work.
# endif
2013-10-18 15:30:24 -04:00
rl_point = saved_point ;
rl_redisplay ( ) ;
2014-08-14 18:16:01 -04:00
free ( saved_line ) ;
2013-10-18 15:30:24 -04:00
}
prompt_was = 0 ;
}
2014-08-20 21:56:53 -04:00
/*void hexdump (int *in_ptr, int *in_end) {
2013-11-09 17:47:19 -05:00
print_start ( ) ;
2013-10-13 06:18:08 -04:00
int * ptr = in_ptr ;
2013-11-09 17:47:19 -05:00
while ( ptr < in_end ) { printf ( " %08x " , * ( ptr + + ) ) ; }
printf ( " \n " ) ;
print_end ( ) ;
2014-08-20 21:56:53 -04:00
} */
2013-10-13 06:18:08 -04:00
void logprintf ( const char * format , . . . ) {
2013-11-21 14:35:49 -05:00
int x = 0 ;
if ( ! prompt_was ) {
x = 1 ;
print_start ( ) ;
}
2014-08-26 14:26:00 -04:00
if ( ! disable_colors ) {
printf ( COLOR_GREY ) ;
}
printf ( " *** " ) ;
2013-10-11 16:52:20 -04:00
va_list ap ;
va_start ( ap , format ) ;
vfprintf ( stdout , format , ap ) ;
va_end ( ap ) ;
2014-08-26 14:26:00 -04:00
if ( ! disable_colors ) {
printf ( COLOR_NORMAL ) ;
}
2013-11-21 14:35:49 -05:00
if ( x ) {
print_end ( ) ;
}
2013-10-03 08:38:25 -04:00
}
2013-10-16 15:19:39 -04:00
2013-10-18 15:30:24 -04:00
int color_stack_pos ;
const char * color_stack [ 10 ] ;
void push_color ( const char * color ) {
2014-08-24 20:11:41 -04:00
if ( disable_colors ) { return ; }
2013-10-18 15:30:24 -04:00
assert ( color_stack_pos < 10 ) ;
color_stack [ color_stack_pos + + ] = color ;
printf ( " %s " , color ) ;
}
void pop_color ( void ) {
2014-08-24 20:11:41 -04:00
if ( disable_colors ) { return ; }
2013-10-18 15:30:24 -04:00
assert ( color_stack_pos > 0 ) ;
color_stack_pos - - ;
if ( color_stack_pos > = 1 ) {
2013-10-21 14:24:31 -04:00
printf ( " %s " , color_stack [ color_stack_pos - 1 ] ) ;
2013-10-18 15:30:24 -04:00
} else {
printf ( " %s " , COLOR_NORMAL ) ;
}
}
2014-08-13 11:55:16 -04:00
void print_media ( struct tgl_message_media * M ) {
2013-12-19 17:50:31 -05:00
assert ( M ) ;
2013-10-18 15:30:24 -04:00
switch ( M - > type ) {
2014-08-18 12:39:04 -04:00
case tgl_message_media_none :
2013-10-18 15:30:24 -04:00
return ;
2014-08-18 12:39:04 -04:00
case tgl_message_media_photo :
2013-10-21 14:24:31 -04:00
if ( M - > photo . caption & & strlen ( M - > photo . caption ) ) {
printf ( " [photo %s] " , M - > photo . caption ) ;
} else {
printf ( " [photo] " ) ;
}
2013-10-18 15:30:24 -04:00
return ;
2014-08-18 12:39:04 -04:00
case tgl_message_media_video :
2014-08-12 21:22:15 -04:00
if ( M - > video . mime_type ) {
printf ( " [video: type %s] " , M - > video . mime_type ) ;
} else {
printf ( " [video] " ) ;
}
2013-10-18 15:30:24 -04:00
return ;
2014-08-18 12:39:04 -04:00
case tgl_message_media_audio :
2014-08-12 21:22:15 -04:00
if ( M - > audio . mime_type ) {
printf ( " [audio: type %s] " , M - > audio . mime_type ) ;
} else {
printf ( " [audio] " ) ;
}
2013-11-15 05:37:14 -05:00
return ;
2014-08-18 12:39:04 -04:00
case tgl_message_media_document :
2013-11-15 05:37:14 -05:00
if ( M - > document . mime_type & & M - > document . caption ) {
printf ( " [document %s: type %s] " , M - > document . caption , M - > document . mime_type ) ;
} else {
printf ( " [document] " ) ;
}
return ;
2014-08-18 12:39:04 -04:00
case tgl_message_media_photo_encr :
printf ( " [photo] " ) ;
2013-11-04 12:34:27 -05:00
return ;
2014-08-18 12:39:04 -04:00
case tgl_message_media_video_encr :
if ( M - > encr_video . mime_type ) {
printf ( " [video: type %s] " , M - > encr_video . mime_type ) ;
} else {
printf ( " [video] " ) ;
}
2013-11-04 12:34:27 -05:00
return ;
2014-08-18 12:39:04 -04:00
case tgl_message_media_audio_encr :
if ( M - > encr_audio . mime_type ) {
printf ( " [audio: type %s] " , M - > encr_audio . mime_type ) ;
} else {
printf ( " [audio] " ) ;
}
2013-11-15 05:37:14 -05:00
return ;
2014-08-18 12:39:04 -04:00
case tgl_message_media_document_encr :
if ( M - > encr_document . mime_type & & M - > encr_document . file_name ) {
printf ( " [document %s: type %s] " , M - > encr_document . file_name , M - > encr_document . mime_type ) ;
} else {
printf ( " [document] " ) ;
}
2013-11-15 05:37:14 -05:00
return ;
2014-08-18 12:39:04 -04:00
case tgl_message_media_geo :
2013-10-23 14:23:33 -04:00
printf ( " [geo] https://maps.google.com/?q=%.6lf,%.6lf " , M - > geo . latitude , M - > geo . longitude ) ;
2013-10-18 15:30:24 -04:00
return ;
2014-08-18 12:39:04 -04:00
case tgl_message_media_contact :
2013-10-18 15:30:24 -04:00
printf ( " [contact] " ) ;
push_color ( COLOR_RED ) ;
printf ( " %s %s " , M - > first_name , M - > last_name ) ;
pop_color ( ) ;
printf ( " %s " , M - > phone ) ;
return ;
2014-08-18 12:39:04 -04:00
case tgl_message_media_unsupported :
2013-10-18 15:30:24 -04:00
printf ( " [unsupported] " ) ;
return ;
default :
2014-08-18 12:39:04 -04:00
printf ( " x = %d \n " , M - > type ) ;
2013-10-18 15:30:24 -04:00
assert ( 0 ) ;
}
}
2013-10-23 06:24:59 -04:00
int unknown_user_list_pos ;
int unknown_user_list [ 1000 ] ;
2014-08-13 11:55:16 -04:00
void print_user_name ( tgl_peer_id_t id , tgl_peer_t * U ) {
assert ( tgl_get_peer_type ( id ) = = TGL_PEER_USER ) ;
2013-10-18 15:30:24 -04:00
push_color ( COLOR_RED ) ;
if ( ! U ) {
2014-08-13 11:55:16 -04:00
printf ( " user#%d " , tgl_get_peer_id ( id ) ) ;
2013-10-23 06:24:59 -04:00
int i ;
2013-10-31 19:18:34 -04:00
int ok = 1 ;
2013-10-23 06:24:59 -04:00
for ( i = 0 ; i < unknown_user_list_pos ; i + + ) {
2014-08-13 11:55:16 -04:00
if ( unknown_user_list [ i ] = = tgl_get_peer_id ( id ) ) {
2013-10-31 19:18:34 -04:00
ok = 0 ;
2013-10-23 06:24:59 -04:00
break ;
}
}
2013-10-31 19:18:34 -04:00
if ( ok ) {
2013-10-23 06:24:59 -04:00
assert ( unknown_user_list_pos < 1000 ) ;
2014-08-13 11:55:16 -04:00
unknown_user_list [ unknown_user_list_pos + + ] = tgl_get_peer_id ( id ) ;
2013-10-23 06:24:59 -04:00
}
2013-10-18 15:30:24 -04:00
} else {
2013-10-24 03:38:32 -04:00
if ( U - > flags & ( FLAG_USER_SELF | FLAG_USER_CONTACT ) ) {
2013-10-23 06:24:59 -04:00
push_color ( COLOR_REDB ) ;
}
2013-11-21 14:35:49 -05:00
if ( ( U - > flags & FLAG_DELETED ) ) {
2014-08-13 11:55:16 -04:00
printf ( " deleted user#%d " , tgl_get_peer_id ( id ) ) ;
2013-11-21 14:35:49 -05:00
} else if ( ! ( U - > flags & FLAG_CREATED ) ) {
2014-08-13 11:55:16 -04:00
printf ( " empty user#%d " , tgl_get_peer_id ( id ) ) ;
2013-11-06 18:12:40 -05:00
} else if ( ! U - > user . first_name | | ! strlen ( U - > user . first_name ) ) {
2013-10-23 06:24:59 -04:00
printf ( " %s " , U - > user . last_name ) ;
2013-11-06 18:12:40 -05:00
} else if ( ! U - > user . last_name | | ! strlen ( U - > user . last_name ) ) {
2013-10-23 06:24:59 -04:00
printf ( " %s " , U - > user . first_name ) ;
} else {
printf ( " %s %s " , U - > user . first_name , U - > user . last_name ) ;
}
2013-10-24 03:38:32 -04:00
if ( U - > flags & ( FLAG_USER_SELF | FLAG_USER_CONTACT ) ) {
2013-10-23 06:24:59 -04:00
pop_color ( ) ;
}
2013-10-18 15:30:24 -04:00
}
pop_color ( ) ;
}
2014-08-13 11:55:16 -04:00
void print_chat_name ( tgl_peer_id_t id , tgl_peer_t * C ) {
assert ( tgl_get_peer_type ( id ) = = TGL_PEER_CHAT ) ;
2013-10-18 15:30:24 -04:00
push_color ( COLOR_MAGENTA ) ;
if ( ! C ) {
2014-08-13 11:55:16 -04:00
printf ( " chat#%d " , tgl_get_peer_id ( id ) ) ;
2013-10-18 15:30:24 -04:00
} else {
printf ( " %s " , C - > chat . title ) ;
}
pop_color ( ) ;
}
2014-08-13 11:55:16 -04:00
void print_encr_chat_name ( tgl_peer_id_t id , tgl_peer_t * C ) {
assert ( tgl_get_peer_type ( id ) = = TGL_PEER_ENCR_CHAT ) ;
2013-11-02 13:01:22 -04:00
push_color ( COLOR_MAGENTA ) ;
if ( ! C ) {
2014-08-13 11:55:16 -04:00
printf ( " encr_chat#%d " , tgl_get_peer_id ( id ) ) ;
2013-11-02 13:01:22 -04:00
} else {
printf ( " %s " , C - > print_name ) ;
}
pop_color ( ) ;
}
2014-08-13 11:55:16 -04:00
void print_encr_chat_name_full ( tgl_peer_id_t id , tgl_peer_t * C ) {
assert ( tgl_get_peer_type ( id ) = = TGL_PEER_ENCR_CHAT ) ;
2013-11-02 13:01:22 -04:00
push_color ( COLOR_MAGENTA ) ;
if ( ! C ) {
2014-08-13 11:55:16 -04:00
printf ( " encr_chat#%d " , tgl_get_peer_id ( id ) ) ;
2013-11-02 13:01:22 -04:00
} else {
printf ( " %s " , C - > print_name ) ;
}
pop_color ( ) ;
}
2013-10-18 15:30:24 -04:00
static char * monthes [ ] = { " Jan " , " Feb " , " Mar " , " Apr " , " May " , " Jun " , " Jul " , " Aug " , " Sep " , " Oct " , " Nov " , " Dec " } ;
void print_date ( long t ) {
2014-02-18 13:06:00 -05:00
struct tm * tm = localtime ( ( void * ) & t ) ;
2013-10-18 15:30:24 -04:00
if ( time ( 0 ) - t < 12 * 60 * 60 ) {
printf ( " [%02d:%02d] " , tm - > tm_hour , tm - > tm_min ) ;
} else {
printf ( " [%02d %s] " , tm - > tm_mday , monthes [ tm - > tm_mon ] ) ;
}
}
2013-10-24 03:38:32 -04:00
void print_date_full ( long t ) {
2014-02-18 13:06:00 -05:00
struct tm * tm = localtime ( ( void * ) & t ) ;
2013-10-24 03:38:32 -04:00
printf ( " [%04d/%02d/%02d %02d:%02d:%02d] " , tm - > tm_year + 1900 , tm - > tm_mon + 1 , tm - > tm_mday , tm - > tm_hour , tm - > tm_min , tm - > tm_sec ) ;
}
2014-08-13 11:55:16 -04:00
void print_service_message ( struct tgl_message * M ) {
2013-12-19 17:50:31 -05:00
assert ( M ) ;
2014-08-18 12:39:04 -04:00
//print_start ();
2013-10-21 15:27:29 -04:00
push_color ( COLOR_GREY ) ;
2013-10-24 18:21:52 -04:00
push_color ( COLOR_MAGENTA ) ;
2013-10-27 19:24:03 -04:00
if ( msg_num_mode ) {
2013-11-02 06:14:30 -04:00
printf ( " %lld " , M - > id ) ;
2013-10-27 19:24:03 -04:00
}
2013-10-21 15:27:29 -04:00
print_date ( M - > date ) ;
2013-10-24 18:21:52 -04:00
pop_color ( ) ;
2013-10-21 15:27:29 -04:00
printf ( " " ) ;
2014-08-13 11:55:16 -04:00
if ( tgl_get_peer_type ( M - > to_id ) = = TGL_PEER_CHAT ) {
print_chat_name ( M - > to_id , tgl_peer_get ( M - > to_id ) ) ;
2013-11-15 05:37:14 -05:00
} else {
2014-08-13 11:55:16 -04:00
assert ( tgl_get_peer_type ( M - > to_id ) = = TGL_PEER_ENCR_CHAT ) ;
print_encr_chat_name ( M - > to_id , tgl_peer_get ( M - > to_id ) ) ;
2013-11-15 05:37:14 -05:00
}
2013-10-21 15:27:29 -04:00
printf ( " " ) ;
2014-08-13 11:55:16 -04:00
print_user_name ( M - > from_id , tgl_peer_get ( M - > from_id ) ) ;
2013-10-21 15:27:29 -04:00
switch ( M - > action . type ) {
2014-08-18 12:39:04 -04:00
case tgl_message_action_none :
2013-10-21 15:27:29 -04:00
printf ( " \n " ) ;
break ;
2014-08-18 12:39:04 -04:00
case tgl_message_action_geo_chat_create :
2013-11-22 18:26:35 -05:00
printf ( " Created geo chat \n " ) ;
break ;
2014-08-18 12:39:04 -04:00
case tgl_message_action_geo_chat_checkin :
2013-11-22 18:26:35 -05:00
printf ( " Checkin in geochat \n " ) ;
break ;
2014-08-18 12:39:04 -04:00
case tgl_message_action_chat_create :
2013-10-21 15:27:29 -04:00
printf ( " created chat %s. %d users \n " , M - > action . title , M - > action . user_num ) ;
break ;
2014-08-18 12:39:04 -04:00
case tgl_message_action_chat_edit_title :
2013-10-21 15:27:29 -04:00
printf ( " changed title to %s \n " ,
M - > action . new_title ) ;
break ;
2014-08-18 12:39:04 -04:00
case tgl_message_action_chat_edit_photo :
2013-10-21 15:27:29 -04:00
printf ( " changed photo \n " ) ;
break ;
2014-08-18 12:39:04 -04:00
case tgl_message_action_chat_delete_photo :
2013-10-21 15:27:29 -04:00
printf ( " deleted photo \n " ) ;
break ;
2014-08-18 12:39:04 -04:00
case tgl_message_action_chat_add_user :
2013-10-21 15:27:29 -04:00
printf ( " added user " ) ;
2014-08-13 11:55:16 -04:00
print_user_name ( tgl_set_peer_id ( TGL_PEER_USER , M - > action . user ) , tgl_peer_get ( tgl_set_peer_id ( TGL_PEER_USER , M - > action . user ) ) ) ;
2013-10-21 15:27:29 -04:00
printf ( " \n " ) ;
break ;
2014-08-18 12:39:04 -04:00
case tgl_message_action_chat_delete_user :
2013-10-21 15:27:29 -04:00
printf ( " deleted user " ) ;
2014-08-13 11:55:16 -04:00
print_user_name ( tgl_set_peer_id ( TGL_PEER_USER , M - > action . user ) , tgl_peer_get ( tgl_set_peer_id ( TGL_PEER_USER , M - > action . user ) ) ) ;
2013-10-21 15:27:29 -04:00
printf ( " \n " ) ;
break ;
2014-08-18 12:39:04 -04:00
case tgl_message_action_set_message_ttl :
2013-11-15 05:37:14 -05:00
printf ( " set ttl to %d seconds. Unsupported yet \n " , M - > action . ttl ) ;
break ;
2014-08-18 12:39:04 -04:00
case tgl_message_action_read_messages :
2014-08-12 21:22:15 -04:00
printf ( " %d messages marked read \n " , M - > action . read_cnt ) ;
break ;
2014-08-18 12:39:04 -04:00
case tgl_message_action_delete_messages :
2014-08-12 21:22:15 -04:00
printf ( " %d messages deleted \n " , M - > action . delete_cnt ) ;
break ;
2014-08-18 12:39:04 -04:00
case tgl_message_action_screenshot_messages :
2014-08-12 21:22:15 -04:00
printf ( " %d messages screenshoted \n " , M - > action . screenshot_cnt ) ;
break ;
2014-08-18 12:39:04 -04:00
case tgl_message_action_flush_history :
2014-08-12 21:22:15 -04:00
printf ( " cleared history \n " ) ;
break ;
2014-08-18 12:39:04 -04:00
case tgl_message_action_notify_layer :
2014-08-12 21:22:15 -04:00
printf ( " updated layer to %d \n " , M - > action . layer ) ;
break ;
2013-10-21 15:27:29 -04:00
default :
assert ( 0 ) ;
}
pop_color ( ) ;
2014-08-18 12:39:04 -04:00
//print_end ();
2013-10-21 15:27:29 -04:00
}
2014-08-13 11:55:16 -04:00
tgl_peer_id_t last_from_id ;
tgl_peer_id_t last_to_id ;
2013-10-31 19:18:34 -04:00
2014-08-13 11:55:16 -04:00
void print_message ( struct tgl_message * M ) {
2013-12-19 17:50:31 -05:00
assert ( M ) ;
2013-11-21 14:35:49 -05:00
if ( M - > flags & ( FLAG_MESSAGE_EMPTY | FLAG_DELETED ) ) {
2013-11-04 12:34:27 -05:00
return ;
}
2013-12-19 17:50:31 -05:00
if ( ! ( M - > flags & FLAG_CREATED ) ) { return ; }
2013-10-18 12:00:47 -04:00
if ( M - > service ) {
2013-10-21 15:27:29 -04:00
print_service_message ( M ) ;
2013-10-18 12:00:47 -04:00
return ;
}
2014-08-13 11:55:16 -04:00
if ( ! tgl_get_peer_type ( M - > to_id ) ) {
2013-12-18 10:21:49 -05:00
logprintf ( " Bad msg \n " ) ;
return ;
}
2013-10-18 15:30:24 -04:00
2013-10-31 19:18:34 -04:00
last_from_id = M - > from_id ;
last_to_id = M - > to_id ;
2013-10-18 15:30:24 -04:00
2014-08-18 12:39:04 -04:00
//print_start ();
2014-08-13 11:55:16 -04:00
if ( tgl_get_peer_type ( M - > to_id ) = = TGL_PEER_USER ) {
2013-10-18 12:00:47 -04:00
if ( M - > out ) {
2013-10-18 15:30:24 -04:00
push_color ( COLOR_GREEN ) ;
2013-10-25 15:50:10 -04:00
if ( msg_num_mode ) {
2013-11-02 06:14:30 -04:00
printf ( " %lld " , M - > id ) ;
2013-10-25 15:50:10 -04:00
}
2013-10-18 15:30:24 -04:00
print_date ( M - > date ) ;
pop_color ( ) ;
printf ( " " ) ;
2014-08-13 11:55:16 -04:00
print_user_name ( M - > to_id , tgl_peer_get ( M - > to_id ) ) ;
2013-10-18 15:30:24 -04:00
push_color ( COLOR_GREEN ) ;
2013-10-21 14:24:31 -04:00
if ( M - > unread ) {
printf ( " <<< " ) ;
} else {
printf ( " ««« " ) ;
}
2013-10-16 15:19:39 -04:00
} else {
2013-10-18 15:30:24 -04:00
push_color ( COLOR_BLUE ) ;
2013-10-25 15:50:10 -04:00
if ( msg_num_mode ) {
2013-11-02 06:14:30 -04:00
printf ( " %lld " , M - > id ) ;
2013-10-25 15:50:10 -04:00
}
2013-10-18 15:30:24 -04:00
print_date ( M - > date ) ;
pop_color ( ) ;
printf ( " " ) ;
2014-08-13 11:55:16 -04:00
print_user_name ( M - > from_id , tgl_peer_get ( M - > from_id ) ) ;
2013-10-18 15:30:24 -04:00
push_color ( COLOR_BLUE ) ;
2013-10-21 14:24:31 -04:00
if ( M - > unread ) {
printf ( " >>> " ) ;
} else {
printf ( " »»» " ) ;
}
2014-02-27 03:48:05 -05:00
if ( alert_sound ) {
play_sound ( ) ;
}
2013-10-18 12:00:47 -04:00
}
2014-08-13 11:55:16 -04:00
} else if ( tgl_get_peer_type ( M - > to_id ) = = TGL_PEER_ENCR_CHAT ) {
tgl_peer_t * P = tgl_peer_get ( M - > to_id ) ;
2013-11-04 12:34:27 -05:00
assert ( P ) ;
if ( M - > out ) {
push_color ( COLOR_GREEN ) ;
if ( msg_num_mode ) {
printf ( " %lld " , M - > id ) ;
}
print_date ( M - > date ) ;
printf ( " " ) ;
push_color ( COLOR_CYAN ) ;
printf ( " %s " , P - > print_name ) ;
pop_color ( ) ;
if ( M - > unread ) {
printf ( " <<< " ) ;
} else {
printf ( " ««« " ) ;
}
} else {
push_color ( COLOR_BLUE ) ;
if ( msg_num_mode ) {
printf ( " %lld " , M - > id ) ;
}
print_date ( M - > date ) ;
push_color ( COLOR_CYAN ) ;
printf ( " %s " , P - > print_name ) ;
pop_color ( ) ;
if ( M - > unread ) {
printf ( " >>> " ) ;
} else {
printf ( " »»» " ) ;
}
2014-02-27 03:48:05 -05:00
if ( alert_sound ) {
play_sound ( ) ;
}
2013-11-04 12:34:27 -05:00
}
2013-10-18 12:00:47 -04:00
} else {
2014-08-13 11:55:16 -04:00
assert ( tgl_get_peer_type ( M - > to_id ) = = TGL_PEER_CHAT ) ;
2013-10-18 15:30:24 -04:00
push_color ( COLOR_MAGENTA ) ;
2013-10-25 15:50:10 -04:00
if ( msg_num_mode ) {
2013-11-02 06:14:30 -04:00
printf ( " %lld " , M - > id ) ;
2013-10-25 15:50:10 -04:00
}
2013-10-18 15:30:24 -04:00
print_date ( M - > date ) ;
pop_color ( ) ;
printf ( " " ) ;
2014-08-13 11:55:16 -04:00
print_chat_name ( M - > to_id , tgl_peer_get ( M - > to_id ) ) ;
2013-10-18 15:30:24 -04:00
printf ( " " ) ;
2014-08-13 11:55:16 -04:00
print_user_name ( M - > from_id , tgl_peer_get ( M - > from_id ) ) ;
if ( ( tgl_get_peer_type ( M - > from_id ) = = TGL_PEER_USER ) & & ( tgl_get_peer_id ( M - > from_id ) = = tgl_state . our_id ) ) {
2013-10-18 15:30:24 -04:00
push_color ( COLOR_GREEN ) ;
} else {
push_color ( COLOR_BLUE ) ;
2013-10-16 15:19:39 -04:00
}
2013-10-21 14:24:31 -04:00
if ( M - > unread ) {
printf ( " >>> " ) ;
} else {
printf ( " »»» " ) ;
}
2013-10-18 15:30:24 -04:00
}
2014-08-13 11:55:16 -04:00
if ( tgl_get_peer_type ( M - > fwd_from_id ) = = TGL_PEER_USER ) {
2013-10-24 18:21:52 -04:00
printf ( " [fwd from " ) ;
2014-08-13 11:55:16 -04:00
print_user_name ( M - > fwd_from_id , tgl_peer_get ( M - > fwd_from_id ) ) ;
2013-10-24 18:21:52 -04:00
printf ( " ] " ) ;
}
2013-10-18 15:30:24 -04:00
if ( M - > message & & strlen ( M - > message ) ) {
printf ( " %s " , M - > message ) ;
}
2014-08-18 12:39:04 -04:00
if ( M - > media . type ! = tgl_message_media_none ) {
2013-10-18 15:30:24 -04:00
print_media ( & M - > media ) ;
2013-10-16 15:19:39 -04:00
}
2013-10-18 15:30:24 -04:00
pop_color ( ) ;
assert ( ! color_stack_pos ) ;
printf ( " \n " ) ;
2014-08-18 12:39:04 -04:00
//print_end();
2013-10-16 15:19:39 -04:00
}
2013-11-09 17:47:19 -05:00
2014-02-27 03:48:05 -05:00
void play_sound ( void ) {
printf ( " \a " ) ;
}
2013-11-09 17:47:19 -05:00
void set_interface_callbacks ( void ) {
2014-08-26 14:26:00 -04:00
if ( readline_disabled ) { return ; }
2013-11-09 17:47:19 -05:00
readline_active = 1 ;
rl_callback_handler_install ( get_default_prompt ( ) , interpreter ) ;
2014-08-25 12:17:17 -04:00
//rl_attempted_completion_function = (void *) complete_text;
rl_completion_entry_function = command_generator ;
2013-11-09 17:47:19 -05:00
}