95
95
96
96
#include <errno.h>
97
97
98
+ #include "tgl/tree.h"
99
+
100
+ struct username_peer_pair {
101
+ const char * username ;
102
+ tgl_peer_t * peer ;
103
+ };
104
+
105
+ #define username_peer_pair_cmp (a ,b ) strcmp (a->username, b->username)
106
+ DEFINE_TREE (username_peer_pair , struct username_peer_pair * , username_peer_pair_cmp , NULL )
107
+ struct tree_username_peer_pair * username_peer_pair ;
108
+
109
+ struct username_peer_pair * current_map ;
110
+
98
111
#define ALLOW_MULT 1
99
112
char * default_prompt = "> " ;
100
113
@@ -478,6 +491,19 @@ tgl_peer_id_t parse_input_peer_id (const char *s, int l, int mask) {
478
491
return res ;
479
492
}
480
493
494
+ if (* s == '@' ) {
495
+ s ++ ;
496
+ l -- ;
497
+ char * tmp = strndup (s , l );
498
+ struct username_peer_pair * p = tree_lookup_username_peer_pair (username_peer_pair , (void * )& tmp );
499
+ free (tmp );
500
+ if (p && (!mask || tgl_get_peer_type (p -> peer -> id ) == mask )) {
501
+ return p -> peer -> id ;
502
+ } else {
503
+ return TGL_PEER_NOT_FOUND ;
504
+ }
505
+ }
506
+
481
507
const char * ss [] = {"user#id" , "user#" , "chat#id" , "chat#" , "secret_chat#id" , "secret_chat#" , "channel#id" , "channel#" };
482
508
int tt [] = {TGL_PEER_USER , TGL_PEER_USER , TGL_PEER_CHAT , TGL_PEER_CHAT , TGL_PEER_ENCR_CHAT , TGL_PEER_ENCR_CHAT , TGL_PEER_CHANNEL , TGL_PEER_CHANNEL };
483
509
@@ -2050,6 +2076,44 @@ int complete_chat_command (tgl_peer_t *P, int index, const char *text, int len,
2050
2076
}
2051
2077
}
2052
2078
2079
+ int complete_username (int mode , int index , const char * text , int len , char * * R ) {
2080
+ * R = NULL ;
2081
+ if (len > 0 && * text == '@' ) {
2082
+ text ++ ;
2083
+ len -- ;
2084
+ }
2085
+ index ++ ;
2086
+ while (index < TLS -> peer_num ) {
2087
+ tgl_peer_t * P = TLS -> Peers [index ];
2088
+ if (mode && tgl_get_peer_type (P -> id ) != mode ) {
2089
+ index ++ ;
2090
+ continue ;
2091
+ }
2092
+ char * u = NULL ;
2093
+ if (tgl_get_peer_type (P -> id ) == TGL_PEER_USER ) {
2094
+ u = P -> user .username ;
2095
+ } else if (tgl_get_peer_type (P -> id ) == TGL_PEER_CHANNEL ) {
2096
+ u = P -> channel .username ;
2097
+ }
2098
+ if (!u ) {
2099
+ index ++ ;
2100
+ continue ;
2101
+ }
2102
+ if ((int )strlen (u ) < len || memcmp (u , text , len )) {
2103
+ index ++ ;
2104
+ continue ;
2105
+ }
2106
+ * R = malloc (strlen (u ) + 2 );
2107
+ * R [0 ] = '@' ;
2108
+ memcpy (* R + 1 , u , strlen (u ) + 1 );
2109
+ break ;
2110
+ }
2111
+ if (index == TLS -> peer_num ) {
2112
+ return -1 ;
2113
+ }
2114
+ return index ;
2115
+ }
2116
+
2053
2117
char * command_generator (const char * text , int state ) {
2054
2118
#ifndef DISABLE_EXTF
2055
2119
static int len ;
@@ -2094,11 +2158,19 @@ char *command_generator (const char *text, int state) {
2094
2158
if (c ) { rl_line_buffer [rl_point ] = c ; }
2095
2159
return R ;
2096
2160
case ca_user :
2097
- index = tgl_complete_user_list (TLS , index , command_pos , command_len , & R );
2161
+ if (command_len && command_pos [0 ] == '@' ) {
2162
+ index = complete_username (TGL_PEER_USER , index , command_pos , command_len , & R );
2163
+ } else {
2164
+ index = tgl_complete_user_list (TLS , index , command_pos , command_len , & R );
2165
+ }
2098
2166
if (c ) { rl_line_buffer [rl_point ] = c ; }
2099
2167
return R ;
2100
2168
case ca_peer :
2101
- index = tgl_complete_peer_list (TLS , index , command_pos , command_len , & R );
2169
+ if (command_len && command_pos [0 ] == '@' ) {
2170
+ index = complete_username (0 , index , command_pos , command_len , & R );
2171
+ } else {
2172
+ index = tgl_complete_peer_list (TLS , index , command_pos , command_len , & R );
2173
+ }
2102
2174
if (c ) { rl_line_buffer [rl_point ] = c ; }
2103
2175
return R ;
2104
2176
case ca_file_name :
@@ -2115,7 +2187,11 @@ char *command_generator (const char *text, int state) {
2115
2187
if (c ) { rl_line_buffer [rl_point ] = c ; }
2116
2188
return R ;
2117
2189
case ca_channel :
2118
- index = tgl_complete_channel_list (TLS , index , command_pos , command_len , & R );
2190
+ if (command_len && command_pos [0 ] == '@' ) {
2191
+ index = complete_username (TGL_PEER_CHANNEL , index , command_pos , command_len , & R );
2192
+ } else {
2193
+ index = tgl_complete_channel_list (TLS , index , command_pos , command_len , & R );
2194
+ }
2119
2195
if (c ) { rl_line_buffer [rl_point ] = c ; }
2120
2196
return R ;
2121
2197
case ca_modifier :
@@ -3073,6 +3149,39 @@ void json_peer_update (struct in_ev *ev, tgl_peer_t *P, unsigned flags) {
3073
3149
#endif
3074
3150
}
3075
3151
3152
+ void peer_update_username (tgl_peer_t * P , const char * username ) {
3153
+ if (!username ) {
3154
+ if (P -> extra ) {
3155
+ struct username_peer_pair * p = tree_lookup_username_peer_pair (username_peer_pair , (void * )& P -> extra );
3156
+ assert (p );
3157
+ username_peer_pair = tree_delete_username_peer_pair (username_peer_pair , p );
3158
+ tfree_str (P -> extra );
3159
+ tfree (p , sizeof (* p ));
3160
+ P -> extra = NULL ;
3161
+ }
3162
+ return ;
3163
+ }
3164
+ assert (username );
3165
+ if (P -> extra && !strcmp (P -> extra , username )) {
3166
+ return ;
3167
+ }
3168
+ if (P -> extra ) {
3169
+ struct username_peer_pair * p = tree_lookup_username_peer_pair (username_peer_pair , (void * )& P -> extra );
3170
+ assert (p );
3171
+ username_peer_pair = tree_delete_username_peer_pair (username_peer_pair , p );
3172
+ tfree_str (P -> extra );
3173
+ tfree (p , sizeof (* p ));
3174
+ P -> extra = NULL ;
3175
+ }
3176
+
3177
+ P -> extra = tstrdup (username );
3178
+ struct username_peer_pair * p = talloc (sizeof (* p ));
3179
+ p -> peer = P ;
3180
+ p -> username = P -> extra ;
3181
+
3182
+ username_peer_pair = tree_insert_username_peer_pair (username_peer_pair , p , rand ());
3183
+ }
3184
+
3076
3185
void user_update_gw (struct tgl_state * TLSR , struct tgl_user * U , unsigned flags ) {
3077
3186
assert (TLSR == TLS );
3078
3187
#ifdef USE_LUA
@@ -3081,6 +3190,8 @@ void user_update_gw (struct tgl_state *TLSR, struct tgl_user *U, unsigned flags)
3081
3190
#ifdef USE_PYTHON
3082
3191
py_user_update (U , flags );
3083
3192
#endif
3193
+
3194
+ peer_update_username ((void * )U , U -> username );
3084
3195
3085
3196
if (disable_output && !notify_ev ) { return ; }
3086
3197
if (!binlog_read ) { return ; }
@@ -3149,8 +3260,6 @@ void secret_chat_update_gw (struct tgl_state *TLSR, struct tgl_secret_chat *U, u
3149
3260
#ifdef USE_PYTHON
3150
3261
py_secret_chat_update (U , flags );
3151
3262
#endif
3152
-
3153
-
3154
3263
3155
3264
if ((flags & TGL_UPDATE_WORKING ) || (flags & TGL_UPDATE_DELETED )) {
3156
3265
write_secret_chat_file ();
@@ -3188,6 +3297,15 @@ void secret_chat_update_gw (struct tgl_state *TLSR, struct tgl_secret_chat *U, u
3188
3297
}
3189
3298
}
3190
3299
3300
+ void channel_update_gw (struct tgl_state * TLSR , struct tgl_channel * U , unsigned flags ) {
3301
+ assert (TLSR == TLS );
3302
+
3303
+ peer_update_username ((void * )U , U -> username );
3304
+
3305
+ if (disable_output && !notify_ev ) { return ; }
3306
+ if (!binlog_read ) { return ; }
3307
+ }
3308
+
3191
3309
void print_card_gw (struct tgl_state * TLSR , void * extra , int success , int size , int * card ) {
3192
3310
assert (TLSR == TLS );
3193
3311
struct in_ev * ev = extra ;
@@ -3295,6 +3413,7 @@ struct tgl_update_callback upd_cb = {
3295
3413
.user_update = user_update_gw ,
3296
3414
.chat_update = chat_update_gw ,
3297
3415
.secret_chat_update = secret_chat_update_gw ,
3416
+ .channel_update = channel_update_gw ,
3298
3417
.msg_receive = print_message_gw ,
3299
3418
.our_id = our_id_gw ,
3300
3419
.user_status_update = user_status_upd ,
0 commit comments