2013-10-23 10:26:17 -04:00
/*
This file is part of telegram - client .
Telegram - client is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 2 of the License , or
( at your option ) any later version .
Telegram - client is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this telegram - client . If not , see < http : //www.gnu.org/licenses/>.
Copyright Vitaly Valtman 2013
*/
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"
2013-10-11 16:52:20 -04:00
# include "queries.h"
2013-10-13 06:18:08 -04:00
# include "interface.h"
# include "telegram.h"
# include "structures.h"
2013-10-18 12:00:47 -04:00
# include "mtproto-common.h"
2013-11-25 12:16:34 -05:00
2014-01-24 10:05:41 -05:00
# define ALLOW_MULT 1
2013-10-24 11:44:54 -04:00
char * default_prompt = " > " ;
int unread_messages ;
2013-10-25 15:50:10 -04:00
int msg_num_mode ;
2014-02-27 03:48:05 -05:00
int alert_sound ;
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-28 18:33:13 -04:00
long long cur_uploading_bytes ;
long long cur_uploaded_bytes ;
long long cur_downloading_bytes ;
long long cur_downloaded_bytes ;
2013-10-29 20:08:30 -04:00
char * line_ptr ;
2013-10-31 19:18:34 -04:00
extern peer_t * Peers [ ] ;
2013-11-04 12:34:27 -05:00
extern int peer_num ;
2013-10-29 20:08:30 -04:00
2013-12-06 12:14:41 -05:00
int in_chat_mode ;
peer_id_t chat_mode_id ;
2013-11-09 17:47:19 -05:00
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 ) ;
}
char * next_token ( int * l ) {
while ( * line_ptr = = ' ' ) { line_ptr + + ; }
if ( ! * line_ptr ) {
* l = 0 ;
return 0 ;
}
int neg = 0 ;
char * s = line_ptr ;
2013-11-06 17:16:46 -05:00
int in_str = 0 ;
while ( * line_ptr & & ( * line_ptr ! = ' ' | | neg | | in_str ) ) {
2014-01-24 10:05:41 -05:00
/* if (*line_ptr == '\\') {
2013-10-29 20:08:30 -04:00
neg = 1 - neg ;
} else {
2013-11-06 17:16:46 -05:00
if ( * line_ptr = = ' " ' & & ! neg ) {
in_str = ! in_str ;
}
2013-10-29 20:08:30 -04:00
neg = 0 ;
2014-01-24 10:05:41 -05:00
} */
2013-10-29 20:08:30 -04:00
line_ptr + + ;
}
* l = line_ptr - s ;
return s ;
}
# define NOT_FOUND (int)0x80000000
2013-10-31 19:18:34 -04:00
peer_id_t PEER_NOT_FOUND = { . id = NOT_FOUND } ;
2013-11-04 18:15:24 -05:00
long long next_token_int ( void ) {
2013-10-29 20:08:30 -04:00
int l ;
char * s = next_token ( & l ) ;
if ( ! s ) { return NOT_FOUND ; }
char * r ;
2013-11-04 18:15:24 -05:00
long long x = strtoll ( s , & r , 10 ) ;
2013-10-29 20:08:30 -04:00
if ( r = = s + l ) {
return x ;
} else {
return NOT_FOUND ;
}
}
2013-10-31 19:18:34 -04:00
peer_id_t next_token_user ( void ) {
2013-10-29 20:08:30 -04:00
int l ;
char * s = next_token ( & l ) ;
2013-10-31 19:18:34 -04:00
if ( ! s ) { return PEER_NOT_FOUND ; }
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 ) ;
if ( r > = 0 ) { return set_peer_id ( PEER_USER , r ) ; }
else { return PEER_NOT_FOUND ; }
2013-10-29 20:08:30 -04:00
}
2013-10-31 19:18:34 -04:00
2013-10-29 20:08:30 -04:00
int index = 0 ;
2013-11-04 12:34:27 -05:00
while ( index < peer_num & & ( ! is_same_word ( s , l , Peers [ index ] - > print_name ) | | get_peer_type ( Peers [ index ] - > id ) ! = PEER_USER ) ) {
2013-10-29 20:08:30 -04:00
index + + ;
}
2013-11-04 12:34:27 -05:00
if ( index < peer_num ) {
2013-10-29 20:08:30 -04:00
return Peers [ index ] - > id ;
} else {
2013-10-31 19:18:34 -04:00
return PEER_NOT_FOUND ;
2013-10-29 20:08:30 -04:00
}
}
2013-10-31 19:18:34 -04:00
peer_id_t next_token_chat ( void ) {
2013-10-29 20:08:30 -04:00
int l ;
char * s = next_token ( & l ) ;
2013-10-31 19:18:34 -04:00
if ( ! s ) { return PEER_NOT_FOUND ; }
if ( l > = 6 & & ! memcmp ( s , " chat# " , 5 ) ) {
s + = 5 ;
l - = 5 ;
int r = atoi ( s ) ;
if ( r > = 0 ) { return set_peer_id ( PEER_CHAT , r ) ; }
else { return PEER_NOT_FOUND ; }
2013-10-29 20:08:30 -04:00
}
2013-10-31 19:18:34 -04:00
2013-10-29 20:08:30 -04:00
int index = 0 ;
2013-11-04 12:34:27 -05:00
while ( index < peer_num & & ( ! is_same_word ( s , l , Peers [ index ] - > print_name ) | | get_peer_type ( Peers [ index ] - > id ) ! = PEER_CHAT ) ) {
2013-10-29 20:08:30 -04:00
index + + ;
}
2013-11-04 12:34:27 -05:00
if ( index < peer_num ) {
2013-10-29 20:08:30 -04:00
return Peers [ index ] - > id ;
} else {
2013-10-31 19:18:34 -04:00
return PEER_NOT_FOUND ;
2013-10-29 20:08:30 -04:00
}
}
2013-11-04 18:15:24 -05:00
peer_id_t next_token_encr_chat ( void ) {
int l ;
char * s = next_token ( & l ) ;
if ( ! s ) { return PEER_NOT_FOUND ; }
int index = 0 ;
while ( index < peer_num & & ( ! is_same_word ( s , l , Peers [ index ] - > print_name ) | | get_peer_type ( Peers [ index ] - > id ) ! = PEER_ENCR_CHAT ) ) {
index + + ;
}
if ( index < peer_num ) {
return Peers [ index ] - > id ;
} else {
return PEER_NOT_FOUND ;
}
}
2013-10-31 19:18:34 -04:00
peer_id_t next_token_peer ( void ) {
2013-10-29 20:08:30 -04:00
int l ;
char * s = next_token ( & l ) ;
2013-10-31 19:18:34 -04:00
if ( ! s ) { return PEER_NOT_FOUND ; }
if ( l > = 6 & & ! memcmp ( s , " user# " , 5 ) ) {
s + = 5 ;
l - = 5 ;
int r = atoi ( s ) ;
if ( r > = 0 ) { return set_peer_id ( PEER_USER , r ) ; }
else { return PEER_NOT_FOUND ; }
}
if ( l > = 6 & & ! memcmp ( s , " chat# " , 5 ) ) {
s + = 5 ;
l - = 5 ;
int r = atoi ( s ) ;
if ( r > = 0 ) { return set_peer_id ( PEER_CHAT , r ) ; }
else { return PEER_NOT_FOUND ; }
2013-10-29 20:08:30 -04:00
}
2013-10-31 19:18:34 -04:00
2013-10-29 20:08:30 -04:00
int index = 0 ;
2013-11-04 12:34:27 -05:00
while ( index < peer_num & & ( ! is_same_word ( s , l , Peers [ index ] - > print_name ) ) ) {
2013-10-29 20:08:30 -04:00
index + + ;
}
2013-11-04 12:34:27 -05:00
if ( index < peer_num ) {
2013-10-29 20:08:30 -04:00
return Peers [ index ] - > id ;
} else {
2013-10-31 19:18:34 -04:00
return PEER_NOT_FOUND ;
2013-10-29 20:08:30 -04:00
}
}
2013-10-28 18:33:13 -04:00
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 ) {
peer_t * U = user_chat_get ( chat_mode_id ) ;
assert ( U & & U - > print_name ) ;
2014-01-10 09:37:56 -05:00
l + = tsnprintf ( buf + l , 999 - l , COLOR_RED " %.*s " COLOR_NORMAL , 100 , U - > print_name ) ;
2013-12-06 12:14:41 -05:00
}
2013-10-28 18:33:13 -04:00
if ( unread_messages | | cur_uploading_bytes | | cur_downloading_bytes ) {
2014-01-10 09:37:56 -05:00
l + = tsnprintf ( buf + l , 999 - l , COLOR_RED " [ " ) ;
2013-10-28 18:33:13 -04:00
int ok = 0 ;
if ( unread_messages ) {
2014-01-10 09:37:56 -05:00
l + = tsnprintf ( buf + l , 999 - l , " %d unread " , unread_messages ) ;
2013-10-28 18:33:13 -04:00
ok = 1 ;
}
if ( cur_uploading_bytes ) {
if ( ok ) { * ( buf + l ) = ' ' ; l + + ; }
ok = 1 ;
2014-01-10 09:37:56 -05:00
l + = tsnprintf ( buf + l , 999 - l , " %lld%%Up " , 100 * cur_uploaded_bytes / cur_uploading_bytes ) ;
2013-10-28 18:33:13 -04:00
}
if ( cur_downloading_bytes ) {
if ( ok ) { * ( buf + l ) = ' ' ; l + + ; }
ok = 1 ;
2014-01-10 09:37:56 -05:00
l + = tsnprintf ( buf + l , 999 - l , " %lld%%Down " , 100 * cur_downloaded_bytes / cur_downloading_bytes ) ;
2013-10-28 18:33:13 -04:00
}
2014-01-10 09:37:56 -05:00
l + = tsnprintf ( buf + l , 999 - l , " ] " COLOR_NORMAL ) ;
2013-10-24 11:44:54 -04:00
return buf ;
2013-12-06 12:14:41 -05:00
}
2014-01-10 09:37:56 -05:00
l + = tsnprintf ( 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 ) {
rl_set_prompt ( s ) ;
}
2013-10-28 18:33:13 -04:00
void update_prompt ( void ) {
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
} ;
2013-10-03 08:38:25 -04:00
char * commands [ ] = {
" help " ,
" msg " ,
2013-10-11 16:52:20 -04:00
" contact_list " ,
2013-10-13 06:18:08 -04:00
" stats " ,
2013-10-18 12:00:47 -04:00
" history " ,
" dialog_list " ,
2013-10-21 14:24:31 -04:00
" send_photo " ,
" send_video " ,
2013-10-22 04:36:07 -04:00
" send_text " ,
2013-10-23 06:24:59 -04:00
" chat_info " ,
2013-10-25 13:29:02 -04:00
" user_info " ,
2013-10-25 15:50:10 -04:00
" fwd " ,
2013-10-25 18:33:17 -04:00
" rename_chat " ,
2013-10-27 15:35:02 -04:00
" load_photo " ,
" view_photo " ,
" load_video_thumb " ,
" view_video_thumb " ,
" load_video " ,
" view_video " ,
2013-10-30 06:10:16 -04:00
" add_contact " ,
" rename_contact " ,
2013-10-25 05:28:29 -04:00
" show_license " ,
2013-11-01 11:02:28 -04:00
" search " ,
2013-11-04 12:34:27 -05:00
" mark_read " ,
2013-11-04 18:15:24 -05:00
" visualize_key " ,
2013-11-05 17:24:26 -05:00
" create_secret_chat " ,
2013-11-06 17:46:17 -05:00
" suggested_contacts " ,
2013-11-06 18:12:40 -05:00
" global_search " ,
2013-11-06 19:08:16 -05:00
" chat_add_user " ,
" chat_del_user " ,
2013-11-09 04:51:07 -05:00
" status_online " ,
" status_offline " ,
" contacts_search " ,
2013-11-09 13:23:11 -05:00
" quit " ,
2013-12-21 06:53:32 -05:00
" safe_quit " ,
2013-11-15 05:37:14 -05:00
" send_audio " ,
" load_audio " ,
" view_audio " ,
" send_document " ,
" load_document_thumb " ,
" view_document_thumb " ,
" load_document " ,
" view_document " ,
2013-11-15 11:14:25 -05:00
" set " ,
2013-12-06 12:14:41 -05:00
" chat_with_peer " ,
2014-01-24 10:05:41 -05:00
" delete_msg " ,
" restore_msg " ,
2014-02-25 15:09:59 -05:00
" create_group_chat " ,
2013-10-03 08:38:25 -04:00
0 } ;
int commands_flags [ ] = {
070 ,
072 ,
2013-10-13 06:18:08 -04:00
07 ,
07 ,
2013-10-18 12:00:47 -04:00
072 ,
07 ,
2013-10-21 14:24:31 -04:00
0732 ,
0732 ,
2013-10-22 04:36:07 -04:00
0732 ,
2013-10-23 06:24:59 -04:00
074 ,
2013-10-25 15:50:10 -04:00
071 ,
2013-10-25 13:29:02 -04:00
072 ,
2013-10-25 18:33:17 -04:00
074 ,
2013-10-25 05:28:29 -04:00
07 ,
2013-10-27 15:35:02 -04:00
07 ,
07 ,
07 ,
07 ,
07 ,
07 ,
2013-10-30 06:10:16 -04:00
071 ,
07 ,
2013-11-01 11:02:28 -04:00
072 ,
2013-11-04 12:34:27 -05:00
072 ,
2013-11-04 18:15:24 -05:00
075 ,
2013-11-05 17:24:26 -05:00
071 ,
2013-11-06 17:46:17 -05:00
07 ,
2013-11-06 18:12:40 -05:00
07 ,
2013-11-06 19:08:16 -05:00
0724 ,
0724 ,
2013-11-09 04:51:07 -05:00
07 ,
07 ,
07 ,
2013-11-09 13:23:11 -05:00
07 ,
2013-12-24 06:58:31 -05:00
07 ,
2013-11-15 05:37:14 -05:00
0732 ,
07 ,
07 ,
0732 ,
2013-11-19 12:01:18 -05:00
07 ,
07 ,
07 ,
07 ,
2013-11-15 11:14:25 -05:00
07 ,
2013-12-06 12:14:41 -05:00
072 ,
2014-01-24 10:05:41 -05:00
07 ,
2014-02-25 15:09:59 -05:00
072 ,
2014-01-24 10:05:41 -05:00
07
2013-10-03 08:38:25 -04:00
} ;
2013-10-03 12:09:06 -04:00
2013-11-30 13:52:13 -05:00
2013-10-03 08:38:25 -04:00
int get_complete_mode ( void ) {
2013-10-29 20:08:30 -04:00
line_ptr = rl_line_buffer ;
2013-10-03 08:38:25 -04:00
int l = 0 ;
2013-10-29 20:08:30 -04:00
char * r = next_token ( & l ) ;
if ( ! r ) { return 0 ; }
while ( r & & r [ 0 ] = = ' [ ' & & r [ l - 1 ] = = ' ] ' ) {
r = next_token ( & l ) ;
if ( ! r ) { return 0 ; }
}
2013-11-30 13:52:13 -05:00
if ( * r = = ' [ ' & & ! r [ l ] ) {
return 6 ;
}
2013-10-29 20:08:30 -04:00
if ( ! * line_ptr ) { return 0 ; }
2013-10-03 08:38:25 -04:00
char * * command = commands ;
int n = 0 ;
int flags = - 1 ;
while ( * command ) {
2013-10-29 20:08:30 -04:00
if ( is_same_word ( r , l , * command ) ) {
2013-10-03 08:38:25 -04:00
flags = commands_flags [ n ] ;
break ;
}
n + + ;
command + + ;
}
if ( flags = = - 1 ) {
2013-10-29 20:08:30 -04:00
return 7 ;
2013-10-03 08:38:25 -04:00
}
int s = 0 ;
while ( 1 ) {
2013-10-29 20:08:30 -04:00
if ( ! next_token ( & l ) | | ! * line_ptr ) {
return flags ? flags & 7 : 7 ;
}
2013-10-03 08:38:25 -04:00
s + + ;
if ( s < = 4 ) { flags > > = 3 ; }
}
}
2013-10-13 06:18:08 -04:00
int complete_user_list ( int index , const char * text , int len , char * * R ) {
index + + ;
2013-11-04 12:34:27 -05:00
while ( index < peer_num & & ( ! Peers [ index ] - > print_name | | strncmp ( Peers [ index ] - > print_name , text , len ) | | get_peer_type ( Peers [ index ] - > id ) ! = PEER_USER ) ) {
2013-10-13 06:18:08 -04:00
index + + ;
}
2013-11-04 12:34:27 -05:00
if ( index < peer_num ) {
2014-01-10 09:37:56 -05:00
* R = strdup ( Peers [ index ] - > print_name ) ;
2013-10-14 13:26:25 -04:00
return index ;
} else {
return - 1 ;
}
}
2013-10-23 06:24:59 -04:00
int complete_chat_list ( int index , const char * text , int len , char * * R ) {
index + + ;
2013-11-04 12:34:27 -05:00
while ( index < peer_num & & ( ! Peers [ index ] - > print_name | | strncmp ( Peers [ index ] - > print_name , text , len ) | | get_peer_type ( Peers [ index ] - > id ) ! = PEER_CHAT ) ) {
2013-10-23 06:24:59 -04:00
index + + ;
}
2013-11-04 12:34:27 -05:00
if ( index < peer_num ) {
2014-01-10 09:37:56 -05:00
* R = strdup ( Peers [ index ] - > print_name ) ;
2013-10-23 06:24:59 -04:00
return index ;
} else {
return - 1 ;
}
}
2013-11-04 18:15:24 -05:00
int complete_encr_chat_list ( int index , const char * text , int len , char * * R ) {
index + + ;
while ( index < peer_num & & ( ! Peers [ index ] - > print_name | | strncmp ( Peers [ index ] - > print_name , text , len ) | | get_peer_type ( Peers [ index ] - > id ) ! = PEER_ENCR_CHAT ) ) {
index + + ;
}
if ( index < peer_num ) {
2014-01-10 09:37:56 -05:00
* R = strdup ( Peers [ index ] - > print_name ) ;
2013-11-04 18:15:24 -05:00
return index ;
} else {
return - 1 ;
}
}
2013-10-14 13:26:25 -04:00
int complete_user_chat_list ( int index , const char * text , int len , char * * R ) {
index + + ;
2013-11-04 12:34:27 -05:00
while ( index < peer_num & & ( ! Peers [ index ] - > print_name | | strncmp ( Peers [ index ] - > print_name , text , len ) ) ) {
2013-10-14 13:26:25 -04:00
index + + ;
}
2013-11-04 12:34:27 -05:00
if ( index < peer_num ) {
2014-01-10 09:37:56 -05:00
* R = strdup ( Peers [ index ] - > print_name ) ;
2013-10-13 06:18:08 -04:00
return index ;
} else {
return - 1 ;
}
}
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 ] ) ;
2013-10-03 08:38:25 -04:00
return index ;
} else {
* R = 0 ;
return - 1 ;
}
}
char * command_generator ( const char * text , int state ) {
static int len , index , mode ;
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 ;
2013-10-03 08:38:25 -04:00
if ( ! state ) {
len = strlen ( text ) ;
index = - 1 ;
2013-10-28 17:56:17 -04:00
c = rl_line_buffer [ rl_point ] ;
rl_line_buffer [ rl_point ] = 0 ;
2013-10-03 08:38:25 -04:00
mode = get_complete_mode ( ) ;
} else {
if ( index = = - 1 ) { return 0 ; }
}
2013-10-28 17:57:22 -04:00
if ( mode = = - 1 ) {
if ( c ) { rl_line_buffer [ rl_point ] = c ; }
return 0 ;
}
2013-10-03 08:38:25 -04:00
char * R = 0 ;
switch ( mode & 7 ) {
case 0 :
index = complete_string_list ( commands , index , text , 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 ;
case 1 :
2014-01-10 09:37:56 -05:00
index = complete_user_list ( index , text , 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 ;
case 2 :
2013-10-14 13:26:25 -04:00
index = complete_user_chat_list ( index , text , 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 ;
case 3 :
2013-10-28 17:56:17 -04:00
R = rl_filename_completion_function ( text , state ) ;
if ( c ) { rl_line_buffer [ rl_point ] = c ; }
return R ;
2013-10-23 06:24:59 -04:00
case 4 :
index = complete_chat_list ( index , text , 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 ;
2013-11-04 18:15:24 -05:00
case 5 :
index = complete_encr_chat_list ( index , text , len , & R ) ;
if ( c ) { rl_line_buffer [ rl_point ] = c ; }
return R ;
2013-11-30 13:52:13 -05:00
case 6 :
index = complete_string_list ( modifiers , index , text , len , & R ) ;
if ( c ) { rl_line_buffer [ rl_point ] = c ; }
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 offline_mode ;
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
}
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 ; }
do_get_history ( chat_mode_id , limit ) ;
return ;
}
if ( ! strncmp ( line , " /read " , 5 ) ) {
do_mark_read ( chat_mode_id ) ;
return ;
}
2014-02-12 18:52:25 -05:00
if ( strlen ( line ) > 0 ) {
do_send_message ( chat_mode_id , line , strlen ( line ) ) ;
}
2013-12-06 12:14:41 -05:00
}
2013-10-03 08:38:25 -04:00
void interpreter ( char * line UU ) {
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 ) ;
}
2013-10-29 20:08:30 -04:00
int l ;
char * command ;
while ( 1 ) {
command = next_token ( & l ) ;
2013-11-01 07:27:08 -04:00
if ( ! command ) { in_readline = 0 ; return ; }
2013-10-29 20:08:30 -04:00
if ( * command = = ' [ ' & & command [ l - 1 ] = = ' ] ' ) {
2013-11-25 12:16:34 -05:00
work_modifier ( command , l ) ;
2013-10-29 20:08:30 -04:00
} else {
break ;
}
}
2013-11-25 12:16:34 -05:00
int _ ;
char * save = line_ptr ;
int ll = l ;
char * cs = command ;
for ( _ = 0 ; _ < count ; _ + + ) {
line_ptr = save ;
l = ll ;
command = cs ;
2013-10-29 20:08:30 -04:00
# define IS_WORD(s) is_same_word (command, l, (s))
# define RET in_readline = 0; return;
2013-10-31 19:18:34 -04:00
peer_id_t id ;
# define GET_PEER \
id = next_token_peer ( ) ; \
if ( ! cmp_peer_id ( id , PEER_NOT_FOUND ) ) { \
2013-12-06 11:40:52 -05:00
printf ( " Bad user/chat id \n " ) ; \
2013-10-31 19:18:34 -04:00
RET ; \
}
# define GET_PEER_USER \
id = next_token_user ( ) ; \
if ( ! cmp_peer_id ( id , PEER_NOT_FOUND ) ) { \
printf ( " Bad user id \n " ) ; \
RET ; \
}
# define GET_PEER_CHAT \
id = next_token_chat ( ) ; \
if ( ! cmp_peer_id ( id , PEER_NOT_FOUND ) ) { \
2013-11-04 18:15:24 -05:00
printf ( " Bad chat id \n " ) ; \
RET ; \
}
# define GET_PEER_ENCR_CHAT \
id = next_token_encr_chat ( ) ; \
if ( ! cmp_peer_id ( id , PEER_NOT_FOUND ) ) { \
printf ( " Bad encr_chat id \n " ) ; \
2013-10-31 19:18:34 -04:00
RET ; \
}
2013-10-29 20:08:30 -04:00
if ( IS_WORD ( " contact_list " ) ) {
2013-10-11 16:52:20 -04:00
do_update_contact_list ( ) ;
2013-10-29 20:08:30 -04:00
} else if ( IS_WORD ( " dialog_list " ) ) {
2013-10-18 12:00:47 -04:00
do_get_dialog_list ( ) ;
2013-10-29 20:08:30 -04:00
} else if ( IS_WORD ( " stats " ) ) {
2013-10-13 06:18:08 -04:00
static char stat_buf [ 1 < < 15 ] ;
print_stat ( stat_buf , ( 1 < < 15 ) - 1 ) ;
printf ( " %s \n " , stat_buf ) ;
2013-10-29 20:08:30 -04:00
} else if ( IS_WORD ( " msg " ) ) {
2013-10-31 19:18:34 -04:00
GET_PEER ;
2013-10-29 20:08:30 -04:00
int t ;
char * s = next_token ( & t ) ;
if ( ! s ) {
printf ( " Empty message \n " ) ;
RET ;
}
do_send_message ( id , s , strlen ( s ) ) ;
} else if ( IS_WORD ( " rename_chat " ) ) {
2013-10-31 19:18:34 -04:00
GET_PEER_CHAT ;
2013-10-29 20:08:30 -04:00
int t ;
char * s = next_token ( & t ) ;
if ( ! s ) {
printf ( " Empty new name \n " ) ;
RET ;
}
do_rename_chat ( id , s ) ;
} else if ( IS_WORD ( " send_photo " ) ) {
2013-10-31 19:18:34 -04:00
GET_PEER ;
2013-10-29 20:08:30 -04:00
int t ;
char * s = next_token ( & t ) ;
if ( ! s ) {
printf ( " Empty file name \n " ) ;
RET ;
}
2014-01-13 07:26:48 -05:00
do_send_photo ( CODE_input_media_uploaded_photo , id , tstrndup ( s , t ) ) ;
2013-10-29 20:08:30 -04:00
} else if ( IS_WORD ( " send_video " ) ) {
2013-10-31 19:18:34 -04:00
GET_PEER ;
2013-10-29 20:08:30 -04:00
int t ;
char * s = next_token ( & t ) ;
if ( ! s ) {
printf ( " Empty file name \n " ) ;
RET ;
}
2014-01-13 07:26:48 -05:00
do_send_photo ( CODE_input_media_uploaded_video , id , tstrndup ( s , t ) ) ;
2013-10-29 20:08:30 -04:00
} else if ( IS_WORD ( " send_text " ) ) {
2013-10-31 19:18:34 -04:00
GET_PEER ;
2013-10-29 20:08:30 -04:00
int t ;
char * s = next_token ( & t ) ;
if ( ! s ) {
printf ( " Empty file name \n " ) ;
RET ;
}
2014-01-13 07:26:48 -05:00
do_send_text ( id , tstrndup ( s , t ) ) ;
2013-10-29 20:08:30 -04:00
} else if ( IS_WORD ( " fwd " ) ) {
2013-10-31 19:18:34 -04:00
GET_PEER ;
2013-10-29 20:08:30 -04:00
int num = next_token_int ( ) ;
if ( num = = NOT_FOUND | | num < = 0 ) {
printf ( " Bad msg id \n " ) ;
RET ;
}
do_forward_message ( id , num ) ;
} else if ( IS_WORD ( " load_photo " ) ) {
2013-11-04 18:15:24 -05:00
long long num = next_token_int ( ) ;
if ( num = = NOT_FOUND ) {
2013-10-29 20:08:30 -04:00
printf ( " Bad msg id \n " ) ;
RET ;
}
struct message * M = message_get ( num ) ;
2014-03-06 16:07:04 -05:00
if ( M & & ! M - > service & & M - > media . type = = CODE_message_media_photo ) {
2013-10-29 20:08:30 -04:00
do_load_photo ( & M - > media . photo , 1 ) ;
2014-03-06 16:07:04 -05:00
} else if ( M & & ! M - > service & & M - > media . type = = CODE_decrypted_message_media_photo ) {
2013-11-04 18:15:24 -05:00
do_load_encr_video ( & M - > media . encr_video , 1 ) ; // this is not a bug.
2013-10-29 20:08:30 -04:00
} else {
printf ( " Bad msg id \n " ) ;
RET ;
}
} else if ( IS_WORD ( " view_photo " ) ) {
2013-11-04 18:15:24 -05:00
long long num = next_token_int ( ) ;
if ( num = = NOT_FOUND ) {
2013-10-29 20:08:30 -04:00
printf ( " Bad msg id \n " ) ;
RET ;
}
struct message * M = message_get ( num ) ;
2014-03-06 16:07:04 -05:00
if ( M & & ! M - > service & & M - > media . type = = CODE_message_media_photo ) {
2013-10-29 20:08:30 -04:00
do_load_photo ( & M - > media . photo , 2 ) ;
2014-03-06 16:07:04 -05:00
} else if ( M & & ! M - > service & & M - > media . type = = CODE_decrypted_message_media_photo ) {
2013-11-04 18:15:24 -05:00
do_load_encr_video ( & M - > media . encr_video , 2 ) ; // this is not a bug.
2013-10-29 20:08:30 -04:00
} else {
printf ( " Bad msg id \n " ) ;
RET ;
}
} else if ( IS_WORD ( " load_video_thumb " ) ) {
2013-11-04 18:15:24 -05:00
long long num = next_token_int ( ) ;
if ( num = = NOT_FOUND ) {
2013-10-29 20:08:30 -04:00
printf ( " Bad msg id \n " ) ;
RET ;
}
struct message * M = message_get ( num ) ;
2014-03-06 16:07:04 -05:00
if ( M & & ! M - > service & & M - > media . type = = CODE_message_media_video ) {
2013-10-29 20:08:30 -04:00
do_load_video_thumb ( & M - > media . video , 1 ) ;
} else {
printf ( " Bad msg id \n " ) ;
RET ;
}
} else if ( IS_WORD ( " view_video_thumb " ) ) {
2013-11-04 18:15:24 -05:00
long long num = next_token_int ( ) ;
if ( num = = NOT_FOUND ) {
2013-10-29 20:08:30 -04:00
printf ( " Bad msg id \n " ) ;
RET ;
}
struct message * M = message_get ( num ) ;
2014-03-06 16:07:04 -05:00
if ( M & & ! M - > service & & M - > media . type = = CODE_message_media_video ) {
2013-10-29 20:08:30 -04:00
do_load_video_thumb ( & M - > media . video , 2 ) ;
} else {
printf ( " Bad msg id \n " ) ;
RET ;
}
} else if ( IS_WORD ( " load_video " ) ) {
2013-11-04 18:15:24 -05:00
long long num = next_token_int ( ) ;
if ( num = = NOT_FOUND ) {
2013-10-29 20:08:30 -04:00
printf ( " Bad msg id \n " ) ;
RET ;
}
struct message * M = message_get ( num ) ;
2014-03-06 16:07:04 -05:00
if ( M & & ! M - > service & & M - > media . type = = CODE_message_media_video ) {
2013-10-29 20:08:30 -04:00
do_load_video ( & M - > media . video , 1 ) ;
2014-03-06 16:07:04 -05:00
} else if ( M & & ! M - > service & & M - > media . type = = CODE_decrypted_message_media_video ) {
2013-11-04 18:15:24 -05:00
do_load_encr_video ( & M - > media . encr_video , 1 ) ;
2013-10-29 20:08:30 -04:00
} else {
printf ( " Bad msg id \n " ) ;
RET ;
}
} else if ( IS_WORD ( " view_video " ) ) {
2013-11-04 18:15:24 -05:00
long long num = next_token_int ( ) ;
if ( num = = NOT_FOUND ) {
2013-10-29 20:08:30 -04:00
printf ( " Bad msg id \n " ) ;
RET ;
}
struct message * M = message_get ( num ) ;
2014-03-06 16:07:04 -05:00
if ( M & & ! M - > service & & M - > media . type = = CODE_message_media_video ) {
2013-10-29 20:08:30 -04:00
do_load_video ( & M - > media . video , 2 ) ;
2014-03-06 16:07:04 -05:00
} else if ( M & & ! M - > service & & M - > media . type = = CODE_decrypted_message_media_video ) {
2013-11-04 18:15:24 -05:00
do_load_encr_video ( & M - > media . encr_video , 2 ) ;
2013-10-29 20:08:30 -04:00
} else {
printf ( " Bad msg id \n " ) ;
RET ;
}
} else if ( IS_WORD ( " chat_info " ) ) {
2013-10-31 19:18:34 -04:00
GET_PEER_CHAT ;
2013-10-29 20:08:30 -04:00
do_get_chat_info ( id ) ;
} else if ( IS_WORD ( " user_info " ) ) {
2013-10-31 19:18:34 -04:00
GET_PEER_USER ;
2013-10-29 20:08:30 -04:00
do_get_user_info ( id ) ;
} else if ( IS_WORD ( " history " ) ) {
2013-10-31 19:18:34 -04:00
GET_PEER ;
2013-10-29 20:08:30 -04:00
int limit = next_token_int ( ) ;
do_get_history ( id , limit > 0 ? limit : 40 ) ;
2013-11-06 19:08:16 -05:00
} else if ( IS_WORD ( " chat_add_user " ) ) {
GET_PEER_CHAT ;
peer_id_t chat_id = id ;
GET_PEER_USER ;
do_add_user_to_chat ( chat_id , id , 100 ) ;
} else if ( IS_WORD ( " chat_del_user " ) ) {
GET_PEER_CHAT ;
peer_id_t chat_id = id ;
GET_PEER_USER ;
do_del_user_from_chat ( chat_id , id ) ;
2013-10-30 06:10:16 -04:00
} else if ( IS_WORD ( " add_contact " ) ) {
int phone_len , first_name_len , last_name_len ;
char * phone , * first_name , * last_name ;
phone = next_token ( & phone_len ) ;
if ( ! phone ) {
printf ( " No phone number found \n " ) ;
RET ;
}
first_name = next_token ( & first_name_len ) ;
if ( ! first_name_len ) {
printf ( " No first name found \n " ) ;
RET ;
}
last_name = next_token ( & last_name_len ) ;
if ( ! last_name_len ) {
printf ( " No last name found \n " ) ;
RET ;
}
do_add_contact ( phone , phone_len , first_name , first_name_len , last_name , last_name_len , 0 ) ;
} else if ( IS_WORD ( " rename_contact " ) ) {
2013-10-31 19:18:34 -04:00
GET_PEER_USER ;
peer_t * U = user_chat_get ( id ) ;
2013-10-30 06:10:16 -04:00
if ( ! U ) {
printf ( " No such user \n " ) ;
RET ;
}
if ( ! U - > user . phone | | ! strlen ( U - > user . phone ) ) {
printf ( " User has no phone. Can not rename \n " ) ;
RET ;
}
int phone_len , first_name_len , last_name_len ;
char * phone , * first_name , * last_name ;
phone_len = strlen ( U - > user . phone ) ;
phone = U - > user . phone ;
first_name = next_token ( & first_name_len ) ;
if ( ! first_name_len ) {
printf ( " No first name found \n " ) ;
RET ;
}
last_name = next_token ( & last_name_len ) ;
if ( ! last_name_len ) {
printf ( " No last name found \n " ) ;
RET ;
}
do_add_contact ( phone , phone_len , first_name , first_name_len , last_name , last_name_len , 1 ) ;
2013-10-29 20:08:30 -04:00
} else if ( IS_WORD ( " help " ) ) {
2013-10-28 15:14:34 -04:00
//print_start ();
2013-10-24 14:22:11 -04:00
push_color ( COLOR_YELLOW ) ;
printf (
" help - prints this help \n "
" msg <peer> Text - sends message to this peer \n "
" contact_list - prints info about users in your contact list \n "
" stats - just for debugging \n "
2014-01-30 11:46:09 -05:00
" history <peer> [limit] - prints history (and marks it as read). Default limit = 40 \n "
2013-10-24 14:22:11 -04:00
" dialog_list - prints info about your dialogs \n "
" send_photo <peer> <photo-file-name> - sends photo to peer \n "
" send_video <peer> <video-file-name> - sends video to peer \n "
" send_text <peer> <text-file-name> - sends text file as plain messages \n "
" chat_info <chat> - prints info about chat \n "
2013-10-25 13:29:02 -04:00
" user_info <user> - prints info about user \n "
2013-10-28 15:14:34 -04:00
" fwd <user> <msg-seqno> - forward message to user. You can see message numbers starting client with -N \n "
2014-02-21 06:23:37 -05:00
" rename_chat <chat> <new-name> \n "
2014-02-08 11:44:10 -05:00
" load_photo/load_video/load_video_thumb <msg-seqno> - loads photo/video to download dir. You can see message numbers starting client with -N \n "
" view_photo/view_video/view_video_thumb <msg-seqno> - loads photo/video to download dir and starts system default viewer. You can see message numbers starting client with -N \n "
2013-10-28 15:14:34 -04:00
" show_license - prints contents of GPLv2 \n "
2013-11-04 12:34:27 -05:00
" search <peer> pattern - searches pattern in messages with peer \n "
2013-11-06 18:18:35 -05:00
" global_search pattern - searches pattern in all messages \n "
2013-11-04 12:34:27 -05:00
" mark_read <peer> - mark read all received messages with peer \n "
2013-11-06 18:18:35 -05:00
" add_contact <phone-number> <first-name> <last-name> - tries to add contact to contact-list by phone \n "
" create_secret_chat <user> - creates secret chat with this user \n "
2014-02-25 15:09:59 -05:00
" create_group_chat <user> <chat-topic> - creates group chat with this user, add more users with chat_add_user <user> \n "
2013-11-06 18:18:35 -05:00
" rename_contact <user> <first-name> <last-name> - tries to rename contact. If you have another device it will be a fight \n "
" suggested_contacts - print info about contacts, you have max common friends \n "
" visualize_key <secret_chat> - prints visualization of encryption key. You should compare it to your partner's one \n "
2013-11-15 11:14:25 -05:00
" set <param> <param-value>. Possible <param> values are: \n "
" \t debug_verbosity - just as it sounds. Debug verbosity \n "
" \t log_level - level of logging of new events. Lower is less verbose: \n "
" \t \t Level 1: prints info about read messages \n "
" \t \t Level 2: prints line, when somebody is typing in chat \n "
" \t \t Level 3: prints line, when somebody changes online status \n "
" \t msg_num - enables/disables numeration of messages \n "
2014-02-27 03:48:05 -05:00
" \t alert - enables/disables alert sound notifications \n "
2013-12-06 12:16:17 -05:00
" chat_with_peer <peer> - starts chat with this peer. Every command after is message to this peer. Type /exit or /quit to end this mode \n "
2013-10-24 14:22:11 -04:00
) ;
pop_color ( ) ;
2013-10-29 20:08:30 -04:00
} else if ( IS_WORD ( " show_license " ) ) {
2013-10-25 05:28:29 -04:00
char * b =
# include "LICENSE.h"
;
printf ( " %s " , b ) ;
2013-11-01 11:02:28 -04:00
} else if ( IS_WORD ( " search " ) ) {
GET_PEER ;
int from = 0 ;
int to = 0 ;
int limit = 40 ;
int t ;
char * s = next_token ( & t ) ;
if ( ! s ) {
printf ( " Empty message \n " ) ;
RET ;
}
do_msg_search ( id , from , to , limit , s ) ;
2013-11-06 18:12:40 -05:00
} else if ( IS_WORD ( " global_search " ) ) {
int from = 0 ;
int to = 0 ;
int limit = 40 ;
int t ;
char * s = next_token ( & t ) ;
if ( ! s ) {
printf ( " Empty message \n " ) ;
RET ;
}
do_msg_search ( PEER_NOT_FOUND , from , to , limit , s ) ;
2013-11-04 12:34:27 -05:00
} else if ( IS_WORD ( " mark_read " ) ) {
GET_PEER ;
do_mark_read ( id ) ;
2013-11-04 18:15:24 -05:00
} else if ( IS_WORD ( " visualize_key " ) ) {
GET_PEER_ENCR_CHAT ;
do_visualize_key ( id ) ;
2013-11-05 17:24:26 -05:00
} else if ( IS_WORD ( " create_secret_chat " ) ) {
GET_PEER ;
do_create_secret_chat ( id ) ;
2014-02-25 15:09:59 -05:00
} else if ( IS_WORD ( " create_group_chat " ) ) {
GET_PEER ;
int t ;
char * s = next_token ( & t ) ;
if ( ! s ) {
printf ( " Empty chat topic \n " ) ;
RET ;
}
do_create_group_chat ( id , s ) ;
2013-11-06 17:46:17 -05:00
} else if ( IS_WORD ( " suggested_contacts " ) ) {
do_get_suggested ( ) ;
2013-11-09 04:51:07 -05:00
} else if ( IS_WORD ( " status_online " ) ) {
do_update_status ( 1 ) ;
} else if ( IS_WORD ( " status_offline " ) ) {
do_update_status ( 0 ) ;
} else if ( IS_WORD ( " contacts_search " ) ) {
int t ;
char * s = next_token ( & t ) ;
if ( ! s ) {
printf ( " Empty search query \n " ) ;
RET ;
}
do_contacts_search ( 100 , s ) ;
2013-11-15 05:37:14 -05:00
} else if ( IS_WORD ( " send_audio " ) ) {
GET_PEER ;
int t ;
char * s = next_token ( & t ) ;
if ( ! s ) {
printf ( " Empty file name \n " ) ;
RET ;
}
2014-01-13 07:26:48 -05:00
do_send_photo ( CODE_input_media_uploaded_audio , id , tstrndup ( s , t ) ) ;
2013-11-15 05:37:14 -05:00
} else if ( IS_WORD ( " send_document " ) ) {
GET_PEER ;
int t ;
char * s = next_token ( & t ) ;
if ( ! s ) {
printf ( " Empty file name \n " ) ;
RET ;
}
2014-01-13 07:26:48 -05:00
do_send_photo ( CODE_input_media_uploaded_document , id , tstrndup ( s , t ) ) ;
2013-11-15 05:37:14 -05:00
} else if ( IS_WORD ( " load_audio " ) ) {
long long num = next_token_int ( ) ;
if ( num = = NOT_FOUND ) {
printf ( " Bad msg id \n " ) ;
RET ;
}
struct message * M = message_get ( num ) ;
2014-03-06 16:07:04 -05:00
if ( M & & ! M - > service & & M - > media . type = = CODE_message_media_audio ) {
2014-01-17 09:16:35 -05:00
do_load_audio ( & M - > media . video , 1 ) ;
2014-03-06 16:07:04 -05:00
} else if ( M & & ! M - > service & & M - > media . type = = CODE_decrypted_message_media_audio ) {
2013-11-15 05:37:14 -05:00
do_load_encr_video ( & M - > media . encr_video , 1 ) ;
} else {
printf ( " Bad msg id \n " ) ;
RET ;
}
} else if ( IS_WORD ( " view_audio " ) ) {
long long num = next_token_int ( ) ;
if ( num = = NOT_FOUND ) {
printf ( " Bad msg id \n " ) ;
RET ;
}
struct message * M = message_get ( num ) ;
2014-03-06 16:07:04 -05:00
if ( M & & ! M - > service & & M - > media . type = = CODE_message_media_audio ) {
2014-01-17 09:16:35 -05:00
do_load_audio ( & M - > media . video , 2 ) ;
2014-03-06 16:07:04 -05:00
} else if ( M & & ! M - > service & & M - > media . type = = CODE_decrypted_message_media_audio ) {
2013-11-15 05:37:14 -05:00
do_load_encr_video ( & M - > media . encr_video , 2 ) ;
} else {
printf ( " Bad msg id \n " ) ;
RET ;
}
} else if ( IS_WORD ( " load_document_thumb " ) ) {
long long num = next_token_int ( ) ;
if ( num = = NOT_FOUND ) {
printf ( " Bad msg id \n " ) ;
RET ;
}
struct message * M = message_get ( num ) ;
if ( M & & ! M - > service & & M - > media . type = = ( int ) CODE_message_media_document ) {
2013-12-20 10:45:59 -05:00
do_load_document_thumb ( & M - > media . document , 1 ) ;
2013-11-15 05:37:14 -05:00
} else {
printf ( " Bad msg id \n " ) ;
RET ;
}
} else if ( IS_WORD ( " view_document_thumb " ) ) {
long long num = next_token_int ( ) ;
if ( num = = NOT_FOUND ) {
printf ( " Bad msg id \n " ) ;
RET ;
}
struct message * M = message_get ( num ) ;
if ( M & & ! M - > service & & M - > media . type = = ( int ) CODE_message_media_document ) {
2013-12-20 10:45:59 -05:00
do_load_document_thumb ( & M - > media . document , 2 ) ;
2013-11-15 05:37:14 -05:00
} else {
printf ( " Bad msg id \n " ) ;
RET ;
}
} else if ( IS_WORD ( " load_document " ) ) {
long long num = next_token_int ( ) ;
if ( num = = NOT_FOUND ) {
printf ( " Bad msg id \n " ) ;
RET ;
}
struct message * M = message_get ( num ) ;
2014-03-06 16:07:04 -05:00
if ( M & & ! M - > service & & M - > media . type = = CODE_message_media_document ) {
2013-12-20 10:45:59 -05:00
do_load_document ( & M - > media . document , 1 ) ;
2014-03-06 16:07:04 -05:00
} else if ( M & & ! M - > service & & M - > media . type = = CODE_decrypted_message_media_document ) {
2013-11-15 05:37:14 -05:00
do_load_encr_video ( & M - > media . encr_video , 1 ) ;
} else {
printf ( " Bad msg id \n " ) ;
RET ;
}
} else if ( IS_WORD ( " view_document " ) ) {
long long num = next_token_int ( ) ;
if ( num = = NOT_FOUND ) {
printf ( " Bad msg id \n " ) ;
RET ;
}
struct message * M = message_get ( num ) ;
2014-03-06 16:07:04 -05:00
if ( M & & ! M - > service & & M - > media . type = = CODE_message_media_document ) {
2013-12-20 10:45:59 -05:00
do_load_document ( & M - > media . document , 2 ) ;
2014-03-06 16:07:04 -05:00
} else if ( M & & ! M - > service & & M - > media . type = = CODE_decrypted_message_media_document ) {
2013-11-15 05:37:14 -05:00
do_load_encr_video ( & M - > media . encr_video , 2 ) ;
} else {
printf ( " Bad msg id \n " ) ;
RET ;
}
2013-11-15 11:14:25 -05:00
} else if ( IS_WORD ( " set " ) ) {
command = next_token ( & l ) ;
long long num = next_token_int ( ) ;
if ( num = = NOT_FOUND ) {
printf ( " Bad msg id \n " ) ;
RET ;
}
if ( IS_WORD ( " debug_verbosity " ) ) {
verbosity = num ;
} else if ( IS_WORD ( " log_level " ) ) {
log_level = num ;
} else if ( IS_WORD ( " msg_num " ) ) {
msg_num_mode = num ;
2014-02-27 03:48:05 -05:00
} else if ( IS_WORD ( " alert " ) ) {
alert_sound = num ;
2013-11-15 11:14:25 -05:00
}
2013-12-06 12:14:41 -05:00
} else if ( IS_WORD ( " chat_with_peer " ) ) {
GET_PEER ;
in_chat_mode = 1 ;
chat_mode_id = id ;
2014-01-24 10:05:41 -05:00
} else if ( IS_WORD ( " delete_msg " ) ) {
long long num = next_token_int ( ) ;
if ( num = = NOT_FOUND ) {
printf ( " Bad msg id \n " ) ;
RET ;
}
do_delete_msg ( num ) ;
} else if ( IS_WORD ( " restore_msg " ) ) {
long long num = next_token_int ( ) ;
if ( num = = NOT_FOUND ) {
printf ( " Bad msg id \n " ) ;
RET ;
}
do_restore_msg ( num ) ;
} else if ( IS_WORD ( " delete_restore_msg " ) ) {
long long num = next_token_int ( ) ;
if ( num = = NOT_FOUND ) {
printf ( " Bad msg id \n " ) ;
RET ;
}
do_delete_msg ( num ) ;
do_restore_msg ( num ) ;
2013-11-09 13:23:11 -05:00
} else if ( IS_WORD ( " quit " ) ) {
exit ( 0 ) ;
2013-12-21 06:53:32 -05:00
} else if ( IS_WORD ( " safe_quit " ) ) {
safe_quit = 1 ;
2013-10-11 16:52:20 -04:00
}
2013-11-25 12:16:34 -05:00
}
2013-10-29 20:08:30 -04:00
# undef IS_WORD
# undef RET
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 ; }
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-01-10 09:37:56 -05:00
saved_line = talloc ( rl_end + 1 ) ;
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-01-10 06:32:57 -05:00
saved_line = talloc ( rl_end + 1 ) ;
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 ; }
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-01-10 09:37:56 -05:00
tfree_str ( saved_line ) ;
2013-10-18 15:30:24 -04:00
}
prompt_was = 0 ;
}
2013-10-13 06:18:08 -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 ( ) ;
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 ( ) ;
}
2013-10-13 06:18:08 -04:00
printf ( COLOR_GREY " *** " ) ;
2013-10-11 16:52:20 -04:00
va_list ap ;
va_start ( ap , format ) ;
vfprintf ( stdout , format , ap ) ;
va_end ( ap ) ;
2013-10-13 06:18:08 -04:00
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 ) {
assert ( color_stack_pos < 10 ) ;
color_stack [ color_stack_pos + + ] = color ;
printf ( " %s " , color ) ;
}
void pop_color ( void ) {
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 ) ;
}
}
void print_media ( struct message_media * M ) {
2013-12-19 17:50:31 -05:00
assert ( M ) ;
2013-10-18 15:30:24 -04:00
switch ( M - > type ) {
case CODE_message_media_empty :
2013-11-29 16:43:56 -05:00
case CODE_decrypted_message_media_empty :
2013-10-18 15:30:24 -04:00
return ;
case CODE_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 ;
case CODE_message_media_video :
printf ( " [video] " ) ;
return ;
2013-11-15 05:37:14 -05:00
case CODE_message_media_audio :
printf ( " [audio] " ) ;
return ;
case CODE_message_media_document :
if ( M - > document . mime_type & & M - > document . caption ) {
printf ( " [document %s: type %s] " , M - > document . caption , M - > document . mime_type ) ;
} else {
printf ( " [document] " ) ;
}
return ;
2013-11-04 12:34:27 -05:00
case CODE_decrypted_message_media_photo :
printf ( " [photo] " ) ;
return ;
case CODE_decrypted_message_media_video :
printf ( " [video] " ) ;
return ;
2013-11-15 05:37:14 -05:00
case CODE_decrypted_message_media_audio :
printf ( " [audio] " ) ;
return ;
case CODE_decrypted_message_media_document :
printf ( " [document] " ) ;
return ;
2013-10-18 15:30:24 -04:00
case CODE_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 ;
case CODE_message_media_contact :
printf ( " [contact] " ) ;
push_color ( COLOR_RED ) ;
printf ( " %s %s " , M - > first_name , M - > last_name ) ;
pop_color ( ) ;
printf ( " %s " , M - > phone ) ;
return ;
case CODE_message_media_unsupported :
printf ( " [unsupported] " ) ;
return ;
default :
assert ( 0 ) ;
}
}
2013-10-23 06:24:59 -04:00
int unknown_user_list_pos ;
int unknown_user_list [ 1000 ] ;
2013-10-31 19:18:34 -04:00
void print_user_name ( peer_id_t id , peer_t * U ) {
assert ( get_peer_type ( id ) = = PEER_USER ) ;
2013-10-18 15:30:24 -04:00
push_color ( COLOR_RED ) ;
if ( ! U ) {
2013-10-31 19:18:34 -04:00
printf ( " user#%d " , 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 + + ) {
2013-10-31 19:18:34 -04:00
if ( unknown_user_list [ i ] = = get_peer_id ( id ) ) {
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 ) ;
2013-10-31 19:18:34 -04:00
unknown_user_list [ unknown_user_list_pos + + ] = 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 ) ) {
2013-11-06 18:12:40 -05:00
printf ( " deleted user#%d " , get_peer_id ( id ) ) ;
2013-11-21 14:35:49 -05:00
} else if ( ! ( U - > flags & FLAG_CREATED ) ) {
printf ( " empty user#%d " , 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 ( ) ;
}
2013-10-31 19:18:34 -04:00
void print_chat_name ( peer_id_t id , peer_t * C ) {
2013-12-19 17:50:31 -05:00
assert ( get_peer_type ( id ) = = PEER_CHAT ) ;
2013-10-18 15:30:24 -04:00
push_color ( COLOR_MAGENTA ) ;
if ( ! C ) {
2013-10-31 19:18:34 -04:00
printf ( " chat#%d " , get_peer_id ( id ) ) ;
2013-10-18 15:30:24 -04:00
} else {
printf ( " %s " , C - > chat . title ) ;
}
pop_color ( ) ;
}
2013-11-02 13:01:22 -04:00
void print_encr_chat_name ( peer_id_t id , peer_t * C ) {
2013-12-19 17:50:31 -05:00
assert ( get_peer_type ( id ) = = PEER_ENCR_CHAT ) ;
2013-11-02 13:01:22 -04:00
push_color ( COLOR_MAGENTA ) ;
if ( ! C ) {
printf ( " encr_chat#%d " , get_peer_id ( id ) ) ;
} else {
printf ( " %s " , C - > print_name ) ;
}
pop_color ( ) ;
}
void print_encr_chat_name_full ( peer_id_t id , peer_t * C ) {
2013-12-19 17:50:31 -05:00
assert ( get_peer_type ( id ) = = PEER_ENCR_CHAT ) ;
2013-11-02 13:01:22 -04:00
push_color ( COLOR_MAGENTA ) ;
if ( ! C ) {
printf ( " encr_chat#%d " , get_peer_id ( id ) ) ;
} 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 ) ;
}
2013-10-18 15:30:24 -04:00
int our_id ;
2013-10-21 15:27:29 -04:00
void print_service_message ( struct message * M ) {
2013-12-19 17:50:31 -05:00
assert ( M ) ;
2013-10-21 15:27:29 -04:00
print_start ( ) ;
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 ( " " ) ;
2013-11-15 05:37:14 -05:00
if ( get_peer_type ( M - > to_id ) = = PEER_CHAT ) {
print_chat_name ( M - > to_id , user_chat_get ( M - > to_id ) ) ;
} else {
2013-12-19 17:50:31 -05:00
assert ( get_peer_type ( M - > to_id ) = = PEER_ENCR_CHAT ) ;
2013-11-15 05:37:14 -05:00
print_encr_chat_name ( M - > to_id , user_chat_get ( M - > to_id ) ) ;
}
2013-10-21 15:27:29 -04:00
printf ( " " ) ;
print_user_name ( M - > from_id , user_chat_get ( M - > from_id ) ) ;
switch ( M - > action . type ) {
case CODE_message_action_empty :
printf ( " \n " ) ;
break ;
2013-11-22 18:26:35 -05:00
case CODE_message_action_geo_chat_create :
printf ( " Created geo chat \n " ) ;
break ;
case CODE_message_action_geo_chat_checkin :
printf ( " Checkin in geochat \n " ) ;
break ;
2013-10-21 15:27:29 -04:00
case CODE_message_action_chat_create :
printf ( " created chat %s. %d users \n " , M - > action . title , M - > action . user_num ) ;
break ;
case CODE_message_action_chat_edit_title :
printf ( " changed title to %s \n " ,
M - > action . new_title ) ;
break ;
case CODE_message_action_chat_edit_photo :
printf ( " changed photo \n " ) ;
break ;
case CODE_message_action_chat_delete_photo :
printf ( " deleted photo \n " ) ;
break ;
case CODE_message_action_chat_add_user :
printf ( " added user " ) ;
2013-10-31 19:18:34 -04:00
print_user_name ( set_peer_id ( PEER_USER , M - > action . user ) , user_chat_get ( set_peer_id ( PEER_USER , M - > action . user ) ) ) ;
2013-10-21 15:27:29 -04:00
printf ( " \n " ) ;
break ;
case CODE_message_action_chat_delete_user :
printf ( " deleted user " ) ;
2013-10-31 19:18:34 -04:00
print_user_name ( set_peer_id ( PEER_USER , M - > action . user ) , user_chat_get ( set_peer_id ( PEER_USER , M - > action . user ) ) ) ;
2013-10-21 15:27:29 -04:00
printf ( " \n " ) ;
break ;
2013-11-15 05:37:14 -05:00
case CODE_decrypted_message_action_set_message_t_t_l :
printf ( " set ttl to %d seconds. Unsupported yet \n " , M - > action . ttl ) ;
break ;
2013-10-21 15:27:29 -04:00
default :
assert ( 0 ) ;
}
pop_color ( ) ;
print_end ( ) ;
}
2013-10-31 19:18:34 -04:00
peer_id_t last_from_id ;
peer_id_t last_to_id ;
2013-10-16 15:19:39 -04:00
void print_message ( struct 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 ;
}
2013-12-18 10:21:49 -05:00
if ( ! get_peer_type ( M - > to_id ) ) {
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
print_start ( ) ;
2013-10-31 19:18:34 -04:00
if ( get_peer_type ( M - > to_id ) = = 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 ( " " ) ;
print_user_name ( M - > to_id , user_chat_get ( M - > to_id ) ) ;
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 ( " " ) ;
print_user_name ( M - > from_id , user_chat_get ( M - > from_id ) ) ;
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
}
2013-11-04 12:34:27 -05:00
} else if ( get_peer_type ( M - > to_id ) = = PEER_ENCR_CHAT ) {
peer_t * P = user_chat_get ( M - > to_id ) ;
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 {
2013-11-04 12:34:27 -05:00
assert ( get_peer_type ( M - > to_id ) = = 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 ( " " ) ;
print_chat_name ( M - > to_id , user_chat_get ( M - > to_id ) ) ;
printf ( " " ) ;
print_user_name ( M - > from_id , user_chat_get ( M - > from_id ) ) ;
2013-10-31 19:18:34 -04:00
if ( ( get_peer_type ( M - > from_id ) = = PEER_USER ) & & ( get_peer_id ( M - > from_id ) = = 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
}
2013-10-31 19:18:34 -04:00
if ( get_peer_type ( M - > fwd_from_id ) = = PEER_USER ) {
2013-10-24 18:21:52 -04:00
printf ( " [fwd from " ) ;
print_user_name ( M - > fwd_from_id , user_chat_get ( M - > fwd_from_id ) ) ;
printf ( " ] " ) ;
}
2013-10-18 15:30:24 -04:00
if ( M - > message & & strlen ( M - > message ) ) {
printf ( " %s " , M - > message ) ;
}
if ( M - > media . type ! = CODE_message_media_empty ) {
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 " ) ;
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 ) {
readline_active = 1 ;
rl_callback_handler_install ( get_default_prompt ( ) , interpreter ) ;
2014-03-05 08:18:53 -05:00
rl_attempted_completion_function = ( void * ) complete_text ;
2013-11-09 17:47:19 -05:00
rl_completion_entry_function = ( void * ) complete_none ;
}