Merge branch 'master' of https://github.com/vysheng/tg
This commit is contained in:
commit
2867d3733b
@ -23,10 +23,11 @@ LIB_LIST=${LIB}/libtgl.a
|
||||
TG_OBJECTS=${OBJ}/main.o ${OBJ}/loop.o ${OBJ}/interface.o ${OBJ}/lua-tg.o
|
||||
TGL_OBJECTS=${OBJ}/net.o ${OBJ}/mtproto-common.o ${OBJ}/mtproto-client.o ${OBJ}/queries.o ${OBJ}/structures.o ${OBJ}/binlog.o ${OBJ}/auto/auto.o ${OBJ}/tgl.o ${OBJ}/updates.o
|
||||
TLC_OBJECTS=${OBJ}/tlc.o ${OBJ}/tl-parser.o ${OBJ}/crc32.o
|
||||
TLD_OBJECTS=${OBJ}/dump-tl-file.o
|
||||
GENERATE_OBJECTS=${OBJ}/generate.o
|
||||
COMMON_OBJECTS=${OBJ}/tools.o
|
||||
OBJ_LIST=${TG_OBJECTS} ${TLC_OBJECTS} ${GENERATE_OBJECTS} ${COMMON_OBJECTS} ${TGL_OBJECTS}
|
||||
OBJ_C=${TLC_OBJECTS} ${GENERATE_OBJECTS} ${COMMON_OBJECTS} ${TGL_OBJECTS}
|
||||
OBJ_LIST=${TG_OBJECTS} ${TLC_OBJECTS} ${GENERATE_OBJECTS} ${COMMON_OBJECTS} ${TGL_OBJECTS} ${TLD_OBJECTS}
|
||||
OBJ_C=${TLC_OBJECTS} ${GENERATE_OBJECTS} ${COMMON_OBJECTS} ${TGL_OBJECTS} ${TLD_OBJECTS}
|
||||
|
||||
DEPENDENCE=$(subst ${OBJ}/,${DEP}/,$(patsubst %.o,%.d,${OBJ_LIST}))
|
||||
DEPENDENCE_LIST=${DEPENDENCE}
|
||||
@ -41,6 +42,7 @@ CC=@CC@
|
||||
all: ${EXE_LIST} ${DIR_LIST} ${LIB_LIST}
|
||||
create_dirs_and_headers: ${DIR_LIST} ${AUTO}/auto.c ${AUTO}/auto-header.h ${AUTO}/constants.h
|
||||
create_dirs: ${DIR_LIST}
|
||||
dump-tl: ${EXE}/dump-tl-file
|
||||
|
||||
${DIR_LIST}:
|
||||
@test -d $@ || mkdir -p $@
|
||||
@ -85,6 +87,9 @@ ${AUTO}/auto-header.h: ${AUTO}/scheme.tlo ${EXE}/generate
|
||||
${AUTO}/constants.h: ${AUTO}/scheme2.tl ${srcdir}/gen_constants_h.awk
|
||||
awk -f ${srcdir}/gen_constants_h.awk < $< > $@
|
||||
|
||||
${EXE}/dump-tl-file: ${OBJ}/auto/auto.o ${TLD_OBJECTS}
|
||||
${CC} ${OBJ}/auto/auto.o ${TLD_OBJECTS} ${LINK_FLAGS} -o $@
|
||||
|
||||
clean:
|
||||
rm -rf ${DIR_LIST} config.log config.status > /dev/null || echo "all clean"
|
||||
|
||||
|
@ -74,5 +74,7 @@ Function_list (arguments are listed aside from cb_function and cb_extra, :
|
||||
status_online ()
|
||||
status_offline ()
|
||||
|
||||
send_location (peer, latitude, longitude)
|
||||
|
||||
Also, you have function
|
||||
postpone (cb_function, cb_extra, timeout). It will call your cb_function in specified number of seconds (number of seconds may be double).
|
||||
|
461
auto-static-print.c
Normal file
461
auto-static-print.c
Normal file
@ -0,0 +1,461 @@
|
||||
/*
|
||||
This file is part of tgl-library
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Copyright Vitaly Valtman 2014
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int cur_token_len;
|
||||
static char *cur_token;
|
||||
static int cur_token_real_len;
|
||||
static int cur_token_quoted;
|
||||
static int multiline_output = 1;
|
||||
static int multiline_offset;
|
||||
static int multiline_offset_size = 2;
|
||||
|
||||
static int *in_ptr, *in_end;
|
||||
|
||||
static inline int fetch_int (void) {
|
||||
return *(in_ptr ++);
|
||||
}
|
||||
|
||||
static inline int fetch_long (void) {
|
||||
long long r = *(long long *)in_ptr;
|
||||
in_ptr += 2;
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline int fetch_long (void) {
|
||||
long long r = *(long long *)in_ptr;
|
||||
in_ptr += 2;
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void out_int (int a) {}
|
||||
static inline void out_double (double a) {}
|
||||
static inline void out_string (char *s, int l) {}
|
||||
static inline void out_long (long long a) {}
|
||||
|
||||
static int disable_field_names;
|
||||
|
||||
#define expect_token(token,len) \
|
||||
if (len != cur_token_len || memcmp (cur_token, token, cur_token_len)) { return -1; } \
|
||||
local_next_token ();
|
||||
|
||||
#define expect_token_ptr(token,len) \
|
||||
if (len != cur_token_len || memcmp (cur_token, token, cur_token_len)) { return 0; } \
|
||||
local_next_token ();
|
||||
|
||||
#define expect_token_autocomplete(token,len) \
|
||||
if (cur_token_len == -3 && len >= cur_token_real_len && !memcmp (cur_token, token, cur_token_real_len)) { set_autocomplete_string (token); return -1; }\
|
||||
if (len != cur_token_len || memcmp (cur_token, token, cur_token_len)) { return -1; } \
|
||||
local_next_token ();
|
||||
|
||||
#define expect_token_ptr_autocomplete(token,len) \
|
||||
if (cur_token_len == -3 && len >= cur_token_real_len && !memcmp (cur_token, token, cur_token_real_len)) { set_autocomplete_string (token); return 0; }\
|
||||
if (len != cur_token_len || memcmp (cur_token, token, cur_token_len)) { return 0; } \
|
||||
local_next_token ();
|
||||
|
||||
|
||||
static int autocomplete_mode;
|
||||
static char *autocomplete_string;
|
||||
static int (*autocomplete_fun)(const char *, int, int, char **);
|
||||
|
||||
static void set_autocomplete_string (const char *s) {
|
||||
if (autocomplete_string) { free (autocomplete_string); }
|
||||
autocomplete_string = strdup (s);
|
||||
assert (autocomplete_string);
|
||||
autocomplete_mode = 1;
|
||||
}
|
||||
|
||||
static void set_autocomplete_type (int (*f)(const char *, int, int, char **)) {
|
||||
autocomplete_fun = f;
|
||||
autocomplete_mode = 2;
|
||||
}
|
||||
|
||||
static int is_int (void) {
|
||||
if (cur_token_len <= 0) { return 0; }
|
||||
char c = cur_token[cur_token_len];
|
||||
cur_token[cur_token_len] = 0;
|
||||
char *p = 0;
|
||||
|
||||
if (strtoll (cur_token, &p, 10)) {}
|
||||
cur_token[cur_token_len] = c;
|
||||
|
||||
return p == cur_token + cur_token_len;
|
||||
}
|
||||
|
||||
static long long get_int (void) {
|
||||
if (cur_token_len <= 0) { return 0; }
|
||||
char c = cur_token[cur_token_len];
|
||||
cur_token[cur_token_len] = 0;
|
||||
char *p = 0;
|
||||
|
||||
long long val = strtoll (cur_token, &p, 0);
|
||||
cur_token[cur_token_len] = c;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int is_double (void) {
|
||||
if (cur_token_len <= 0) { return 0; }
|
||||
char c = cur_token[cur_token_len];
|
||||
cur_token[cur_token_len] = 0;
|
||||
char *p = 0;
|
||||
|
||||
if (strtod (cur_token, &p)) {}
|
||||
cur_token[cur_token_len] = c;
|
||||
|
||||
return p == cur_token + cur_token_len;
|
||||
}
|
||||
|
||||
static double get_double (void) {
|
||||
if (cur_token_len <= 0) { return 0; }
|
||||
char c = cur_token[cur_token_len];
|
||||
cur_token[cur_token_len] = 0;
|
||||
char *p = 0;
|
||||
|
||||
double val = strtod (cur_token, &p);
|
||||
cur_token[cur_token_len] = c;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static struct paramed_type *paramed_type_dup (struct paramed_type *P) {
|
||||
if (ODDP (P)) { return P; }
|
||||
struct paramed_type *R = malloc (sizeof (*R));
|
||||
assert (R);
|
||||
R->type = malloc (sizeof (*R->type));
|
||||
assert (R->type);
|
||||
memcpy (R->type, P->type, sizeof (*P->type));
|
||||
R->type->id = strdup (P->type->id);
|
||||
assert (R->type->id);
|
||||
|
||||
if (P->type->params_num) {
|
||||
R->params = malloc (sizeof (void *) * P->type->params_num);
|
||||
assert (R->params);
|
||||
int i;
|
||||
for (i = 0; i < P->type->params_num; i++) {
|
||||
R->params[i] = paramed_type_dup (P->params[i]);
|
||||
}
|
||||
}
|
||||
return R;
|
||||
}
|
||||
|
||||
void tgl_paramed_type_free (struct paramed_type *P) {
|
||||
if (ODDP (P)) { return; }
|
||||
if (P->type->params_num) {
|
||||
int i;
|
||||
for (i = 0; i < P->type->params_num; i++) {
|
||||
tgl_paramed_type_free (P->params[i]);
|
||||
}
|
||||
free (P->params);
|
||||
}
|
||||
free (P->type->id);
|
||||
free (P->type);
|
||||
free (P);
|
||||
}
|
||||
|
||||
static char *buffer_pos, *buffer_end;
|
||||
|
||||
static int is_wspc (char c) {
|
||||
return c <= 32 && c > 0;
|
||||
}
|
||||
|
||||
static void skip_wspc (void) {
|
||||
while (buffer_pos < buffer_end && is_wspc (*buffer_pos)) {
|
||||
buffer_pos ++;
|
||||
}
|
||||
}
|
||||
|
||||
static int is_letter (char c) {
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '.' || c == '_' || c == '-';
|
||||
}
|
||||
|
||||
|
||||
static char exp_buffer[1 << 25];;
|
||||
static int exp_buffer_pos;
|
||||
|
||||
static inline int is_hex (char c) {
|
||||
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
|
||||
}
|
||||
|
||||
static inline int hex2dec (char c) {
|
||||
if (c >= '0' && c <= '9') { return c - '0'; }
|
||||
else { return c - 'a' + 10; }
|
||||
}
|
||||
|
||||
static void expand_backslashed (char *s, int len) {
|
||||
int backslashed = 0;
|
||||
exp_buffer_pos = 0;
|
||||
int i = 0;
|
||||
while (i < len) {
|
||||
assert (i + 3 <= (1 << 25));
|
||||
if (backslashed) {
|
||||
backslashed = 0;
|
||||
switch (s[i ++]) {
|
||||
case 'n':
|
||||
exp_buffer[exp_buffer_pos ++] = '\n';
|
||||
break;
|
||||
case 'r':
|
||||
exp_buffer[exp_buffer_pos ++] = '\r';
|
||||
break;
|
||||
case 't':
|
||||
exp_buffer[exp_buffer_pos ++] = '\t';
|
||||
break;
|
||||
case 'b':
|
||||
exp_buffer[exp_buffer_pos ++] = '\b';
|
||||
break;
|
||||
case 'a':
|
||||
exp_buffer[exp_buffer_pos ++] = '\a';
|
||||
break;
|
||||
case '\\':
|
||||
exp_buffer[exp_buffer_pos ++] = '\\';
|
||||
break;
|
||||
case 'x':
|
||||
if (i + 2 > len || !is_hex (s[i]) || !is_hex (s[i + 1])) {
|
||||
exp_buffer_pos = -1;
|
||||
return;
|
||||
}
|
||||
exp_buffer[exp_buffer_pos ++] = hex2dec (s[i]) * 16 + hex2dec (s[i + 1]);
|
||||
i += 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (s[i] == '\\') {
|
||||
backslashed = 1;
|
||||
i ++;
|
||||
} else {
|
||||
exp_buffer[exp_buffer_pos ++] = s[i ++];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void local_next_token (void) {
|
||||
skip_wspc ();
|
||||
cur_token_quoted = 0;
|
||||
if (buffer_pos >= buffer_end) {
|
||||
cur_token_len = -3;
|
||||
cur_token_real_len = 0;
|
||||
return;
|
||||
}
|
||||
char c = *buffer_pos;
|
||||
if (is_letter (c)) {
|
||||
cur_token = buffer_pos;
|
||||
while (buffer_pos < buffer_end && is_letter (*buffer_pos)) {
|
||||
buffer_pos ++;
|
||||
}
|
||||
if (buffer_pos < buffer_end) {
|
||||
cur_token_len = buffer_pos - cur_token;
|
||||
} else {
|
||||
cur_token_real_len = buffer_pos - cur_token;
|
||||
cur_token_len = -3;
|
||||
}
|
||||
return;
|
||||
} else if (c == '"') {
|
||||
cur_token_quoted = 1;
|
||||
cur_token = buffer_pos ++;
|
||||
int backslashed = 0;
|
||||
while (buffer_pos < buffer_end && (*buffer_pos != '"' || backslashed)) {
|
||||
if (*buffer_pos == '\\') {
|
||||
backslashed ^= 1;
|
||||
} else {
|
||||
backslashed = 0;
|
||||
}
|
||||
buffer_pos ++;
|
||||
}
|
||||
if (*buffer_pos == '"') {
|
||||
buffer_pos ++;
|
||||
expand_backslashed (cur_token + 1, buffer_pos - cur_token - 2);
|
||||
if (exp_buffer_pos < 0) {
|
||||
cur_token_len = -2;
|
||||
} else {
|
||||
cur_token_len = exp_buffer_pos;
|
||||
cur_token = exp_buffer;
|
||||
}
|
||||
} else {
|
||||
cur_token_len = -2;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
if (c) {
|
||||
cur_token = buffer_pos ++;
|
||||
cur_token_len = 1;
|
||||
} else {
|
||||
cur_token_len = -3;
|
||||
cur_token_real_len = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX_FVARS 100
|
||||
static struct paramed_type *fvars[MAX_FVARS];
|
||||
static int fvars_pos;
|
||||
|
||||
static void add_var_to_be_freed (struct paramed_type *P) {
|
||||
assert (fvars_pos < MAX_FVARS);
|
||||
fvars[fvars_pos ++] = P;
|
||||
}
|
||||
|
||||
static void free_vars_to_be_freed (void) {
|
||||
int i;
|
||||
for (i = 0; i < fvars_pos; i++) {
|
||||
tgl_paramed_type_free (fvars[i]);
|
||||
}
|
||||
fvars_pos = 0;
|
||||
}
|
||||
|
||||
int tglf_extf_autocomplete (const char *text, int text_len, int index, char **R, char *data, int data_len) {
|
||||
if (index == -1) {
|
||||
buffer_pos = data;
|
||||
buffer_end = data + data_len;
|
||||
autocomplete_mode = 0;
|
||||
local_next_token ();
|
||||
struct paramed_type *P = autocomplete_function_any ();
|
||||
free_vars_to_be_freed ();
|
||||
if (P) { tgl_paramed_type_free (P); }
|
||||
}
|
||||
if (autocomplete_mode == 0) { return -1; }
|
||||
int len = strlen (text);
|
||||
if (autocomplete_mode == 1) {
|
||||
if (index >= 0) { return -1; }
|
||||
index = 0;
|
||||
if (!strncmp (text, autocomplete_string, len)) {
|
||||
*R = strdup (autocomplete_string);
|
||||
assert (*R);
|
||||
return index;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return autocomplete_fun (text, len, index, R);
|
||||
}
|
||||
}
|
||||
|
||||
struct paramed_type *tglf_extf_store (const char *data, int data_len) {
|
||||
buffer_pos = (char *)data;
|
||||
buffer_end = (char *)(data + data_len);
|
||||
local_next_token ();
|
||||
return store_function_any ();
|
||||
}
|
||||
|
||||
#define OUT_BUF_SIZE (1 << 25)
|
||||
static char out_buf[OUT_BUF_SIZE];
|
||||
static int out_buf_pos;
|
||||
|
||||
#define eprintf(...) \
|
||||
do { \
|
||||
out_buf_pos += snprintf (out_buf + out_buf_pos, OUT_BUF_SIZE - out_buf_pos, __VA_ARGS__);\
|
||||
assert (out_buf_pos < OUT_BUF_SIZE);\
|
||||
} while (0)\
|
||||
|
||||
static int valid_utf8_char (const char *str) {
|
||||
unsigned char c = (unsigned char) *str;
|
||||
int n = 0;
|
||||
|
||||
if ((c & 0x80) == 0x00) {
|
||||
n = 0;
|
||||
} else if ((c & 0xe0) == 0xc0) {
|
||||
n = 1;
|
||||
} else if ((c & 0xf0) == 0xe0) {
|
||||
n = 2;
|
||||
} else if ((c & 0xf8) == 0xf0) {
|
||||
n = 3;
|
||||
} else if ((c & 0xfc) == 0xf8) {
|
||||
n = 4;
|
||||
} else if ((c & 0xfe) == 0xfc) {
|
||||
n = 5;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < n; i ++) {
|
||||
if ((((unsigned char)(str[i + 1])) & 0xc0) != 0x80) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return n + 1;
|
||||
}
|
||||
|
||||
static void print_escaped_string (const char *str, int len) {
|
||||
eprintf ("\"");
|
||||
const char *end = str + len;
|
||||
while (str < end) {
|
||||
int n = valid_utf8_char (str);
|
||||
if (n < 0) {
|
||||
eprintf ("\\x%02x", (int)(unsigned char)*str);
|
||||
str ++;
|
||||
} else if (n >= 2) {
|
||||
int i;
|
||||
for (i = 0; i < n; i++) {
|
||||
eprintf ("%c", *(str ++));
|
||||
}
|
||||
} else if (((unsigned char)*str) >= ' ' && *str != '"' && *str != '\\') {
|
||||
eprintf ("%c", *str);
|
||||
str ++;
|
||||
} else {
|
||||
switch (*str) {
|
||||
case '\n':
|
||||
eprintf("\\n");
|
||||
break;
|
||||
case '\r':
|
||||
eprintf("\\r");
|
||||
break;
|
||||
case '\t':
|
||||
eprintf("\\t");
|
||||
break;
|
||||
case '\b':
|
||||
eprintf("\\b");
|
||||
break;
|
||||
case '\a':
|
||||
eprintf("\\a");
|
||||
break;
|
||||
case '\\':
|
||||
eprintf ("\\\\");
|
||||
break;
|
||||
case '"':
|
||||
eprintf ("\\\"");
|
||||
break;
|
||||
default:
|
||||
eprintf ("\\x%02x", (int)(unsigned char)*str);
|
||||
break;
|
||||
}
|
||||
str ++;
|
||||
}
|
||||
}
|
||||
eprintf ("\"");
|
||||
}
|
||||
|
||||
static void print_offset (void) {
|
||||
int i;
|
||||
for (i = 0; i < multiline_offset; i++) {
|
||||
eprintf (" ");
|
||||
}
|
||||
}
|
||||
|
||||
char *tglf_extf_fetch (struct paramed_type *T) {
|
||||
out_buf_pos = 0;
|
||||
fetch_type_any (T);
|
||||
return out_buf;
|
||||
}
|
@ -432,6 +432,6 @@ static void print_offset (void) {
|
||||
|
||||
char *tglf_extf_fetch (struct paramed_type *T) {
|
||||
out_buf_pos = 0;
|
||||
fetch_type_any (T);
|
||||
if (fetch_type_any (T) < 0) { return 0; }
|
||||
return out_buf;
|
||||
}
|
||||
|
70
binlog.c
70
binlog.c
@ -782,6 +782,12 @@ static int fetch_comb_binlog_send_message_text (void *extra) {
|
||||
}
|
||||
|
||||
M->to_id = tgl_set_peer_id (t, fetch_int ());
|
||||
if (t == TGL_PEER_ENCR_CHAT) {
|
||||
tgl_peer_t *P = tgl_peer_get (M->to_id);
|
||||
if (P) {
|
||||
P->encr_chat.out_seq_no ++;
|
||||
}
|
||||
}
|
||||
M->date = fetch_int ();
|
||||
|
||||
int l = prefetch_strlen ();
|
||||
@ -825,6 +831,11 @@ static int fetch_comb_binlog_send_message_action_encr (void *extra) {
|
||||
M->media.type = tgl_message_media_none;
|
||||
tglf_fetch_message_action_encrypted (&M->action);
|
||||
|
||||
tgl_peer_t *P = tgl_peer_get (M->to_id);
|
||||
if (P) {
|
||||
P->encr_chat.out_seq_no ++;
|
||||
}
|
||||
|
||||
M->unread = 1;
|
||||
M->out = tgl_get_peer_id (M->from_id) == tgl_state.our_id;
|
||||
M->service = 1;
|
||||
@ -953,6 +964,11 @@ static int fetch_comb_binlog_create_message_media_encr_pending (void *extra) {
|
||||
M->to_id = tgl_set_peer_id (t, fetch_int ());
|
||||
M->date = fetch_int ();
|
||||
|
||||
tgl_peer_t *P = tgl_peer_get (M->to_id);
|
||||
if (P) {
|
||||
P->encr_chat.out_seq_no ++;
|
||||
}
|
||||
|
||||
int l = prefetch_strlen ();
|
||||
M->message = talloc (l + 1);
|
||||
memcpy (M->message, fetch_str (l), l);
|
||||
@ -1316,13 +1332,53 @@ static void create_new_binlog (void) {
|
||||
static int s[1000];
|
||||
packet_ptr = s;
|
||||
out_int (CODE_binlog_start);
|
||||
if (tgl_state.test_mode) {
|
||||
out_int (CODE_binlog_dc_option);
|
||||
out_int (tgl_state.test_mode ? TG_SERVER_TEST_DC : TG_SERVER_DC);
|
||||
out_int (1);
|
||||
out_string ("");
|
||||
out_string (tgl_state.test_mode ? TG_SERVER_TEST : TG_SERVER);
|
||||
out_string (TG_SERVER_TEST_1);
|
||||
out_int (443);
|
||||
out_int (CODE_binlog_dc_option);
|
||||
out_int (2);
|
||||
out_string ("");
|
||||
out_string (TG_SERVER_TEST_2);
|
||||
out_int (443);
|
||||
out_int (CODE_binlog_dc_option);
|
||||
out_int (3);
|
||||
out_string ("");
|
||||
out_string (TG_SERVER_TEST_3);
|
||||
out_int (443);
|
||||
out_int (CODE_binlog_default_dc);
|
||||
out_int (tgl_state.test_mode ? TG_SERVER_TEST_DC : TG_SERVER_DC);
|
||||
out_int (2);
|
||||
} else {
|
||||
out_int (CODE_binlog_dc_option);
|
||||
out_int (1);
|
||||
out_string ("");
|
||||
out_string (TG_SERVER_1);
|
||||
out_int (443);
|
||||
out_int (CODE_binlog_dc_option);
|
||||
out_int (2);
|
||||
out_string ("");
|
||||
out_string (TG_SERVER_2);
|
||||
out_int (443);
|
||||
out_int (CODE_binlog_dc_option);
|
||||
out_int (3);
|
||||
out_string ("");
|
||||
out_string (TG_SERVER_3);
|
||||
out_int (443);
|
||||
out_int (CODE_binlog_dc_option);
|
||||
out_int (4);
|
||||
out_string ("");
|
||||
out_string (TG_SERVER_4);
|
||||
out_int (443);
|
||||
out_int (CODE_binlog_dc_option);
|
||||
out_int (5);
|
||||
out_string ("");
|
||||
out_string (TG_SERVER_5);
|
||||
out_int (443);
|
||||
out_int (CODE_binlog_default_dc);
|
||||
out_int (2);
|
||||
}
|
||||
|
||||
int fd = open (get_binlog_file_name (), O_WRONLY | O_EXCL | O_CREAT, 0600);
|
||||
if (fd < 0) {
|
||||
@ -1542,7 +1598,7 @@ void bl_do_user_set_friend (struct tgl_user *U, int friend) {
|
||||
|
||||
void bl_do_dc_option (int id, int l1, const char *name, int l2, const char *ip, int port) {
|
||||
struct tgl_dc *DC = tgl_state.DC_list[id];
|
||||
if (DC) { return; }
|
||||
if (DC && !strncmp (ip, DC->ip, l2)) { return; }
|
||||
|
||||
clear_packet ();
|
||||
out_int (CODE_binlog_dc_option);
|
||||
@ -1717,7 +1773,7 @@ void bl_do_encr_chat_init (int id, int user_id, unsigned char random[], unsigned
|
||||
|
||||
void bl_do_set_pts (int pts) {
|
||||
if (tgl_state.locks & TGL_LOCK_DIFF) { return; }
|
||||
if (pts == tgl_state.pts) { return; }
|
||||
if (pts <= tgl_state.pts) { return; }
|
||||
int *ev = alloc_log_event (8);
|
||||
ev[0] = CODE_binlog_set_pts;
|
||||
ev[1] = pts;
|
||||
@ -1726,7 +1782,7 @@ void bl_do_set_pts (int pts) {
|
||||
|
||||
void bl_do_set_qts (int qts) {
|
||||
if (tgl_state.locks & TGL_LOCK_DIFF) { return; }
|
||||
if (qts == tgl_state.qts) { return; }
|
||||
if (qts <= tgl_state.qts) { return; }
|
||||
int *ev = alloc_log_event (8);
|
||||
ev[0] = CODE_binlog_set_qts;
|
||||
ev[1] = qts;
|
||||
@ -1735,7 +1791,7 @@ void bl_do_set_qts (int qts) {
|
||||
|
||||
void bl_do_set_date (int date) {
|
||||
if (tgl_state.locks & TGL_LOCK_DIFF) { return; }
|
||||
if (date == tgl_state.date) { return; }
|
||||
if (date <= tgl_state.date) { return; }
|
||||
int *ev = alloc_log_event (8);
|
||||
ev[0] = CODE_binlog_set_date;
|
||||
ev[1] = date;
|
||||
|
6
debian/changelog
vendored
6
debian/changelog
vendored
@ -1,5 +1,5 @@
|
||||
telegram-cli (0.1-1) unstable; urgency=low
|
||||
telegram-cli (1.0.5.1-1) unstable; urgency=low
|
||||
|
||||
* Initial release (Closes #737563)
|
||||
* Initial release
|
||||
|
||||
-- Cleto Martín <cleto@debian.org> Mon, 03 Feb 2014 20:00:03 +0000
|
||||
-- Steve Illichevsky <still.ru@gmail.com> Wed, 01 Oct 2014 21:06:28 +0400
|
||||
|
2
debian/compat
vendored
2
debian/compat
vendored
@ -1 +1 @@
|
||||
9
|
||||
8
|
||||
|
10
debian/control
vendored
10
debian/control
vendored
@ -1,16 +1,16 @@
|
||||
Source: telegram-cli
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Cleto Martín <cleto@debian.org>
|
||||
Priority: extra
|
||||
Maintainer: Steve Illichevsky <still.ru@gmail.com>
|
||||
Build-Depends: debhelper (>= 8.0.0),
|
||||
autotools-dev,
|
||||
autoconf-archive,
|
||||
libreadline-dev,
|
||||
libconfig-dev,
|
||||
libssl-dev,
|
||||
lua5.2,
|
||||
liblua5.2-dev
|
||||
Standards-Version: 3.9.4
|
||||
lua5.1,
|
||||
liblua5.1-dev
|
||||
Standards-Version: 3.9.2
|
||||
Homepage: https://github.com/vysheng/tg
|
||||
Vcs-Git: git://github.com/vysheng/tg.git
|
||||
Vcs-Browser: https://github.com/vysheng/tg
|
||||
|
23
debian/copyright
vendored
23
debian/copyright
vendored
@ -1,19 +1,19 @@
|
||||
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Format: http://dep.debian.net/deps/dep5
|
||||
Upstream-Name: telegram-cli
|
||||
Source: https://github.com/vysheng/tg
|
||||
|
||||
Files: *
|
||||
Copyright: 2013 Vitaly Valtman
|
||||
License: GPL-2.0+
|
||||
Copyright: 2013-2014 Vitaly Valtman <https://github.com/vysheng>
|
||||
License: GPL-3.0+
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2014 Cleto Martín <cleto@debian.org>
|
||||
License: GPL-2.0+
|
||||
Copyright: 2014 Steve Illichevsky <still.ru@gmail.com>
|
||||
License: GPL-3.0+
|
||||
|
||||
License: GPL-2.0+
|
||||
This package is free software; you can redistribute it and/or modify
|
||||
License: GPL-3.0+
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
.
|
||||
This package is distributed in the hope that it will be useful,
|
||||
@ -22,7 +22,10 @@ License: GPL-2.0+
|
||||
GNU General Public License for more details.
|
||||
.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
.
|
||||
On Debian systems, the complete text of the GNU General
|
||||
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
|
||||
Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
|
||||
|
||||
# Please also look if there are files or directories which have a
|
||||
# different copyright/license attached and list them here.
|
||||
|
3
debian/docs
vendored
3
debian/docs
vendored
@ -1 +1,4 @@
|
||||
README.es
|
||||
README-LUA
|
||||
README.md
|
||||
#telegram-cli.8
|
||||
|
1
debian/files
vendored
Normal file
1
debian/files
vendored
Normal file
@ -0,0 +1 @@
|
||||
telegram-cli_1.0.5.1-1_i386.deb net extra
|
4
debian/install
vendored
4
debian/install
vendored
@ -1 +1,3 @@
|
||||
telegram usr/bin
|
||||
bin/telegram-cli usr/bin
|
||||
bin/tlc usr/bin
|
||||
server.pub etc/telegram-cli
|
||||
|
10
debian/rules
vendored
10
debian/rules
vendored
@ -1,12 +1,18 @@
|
||||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
# Sample debian/rules that uses debhelper.
|
||||
# This file was originally written by Joey Hess and Craig Small.
|
||||
# As a special exception, when this file is copied by dh-make into a
|
||||
# dh-make output file, you may use that output file without restriction.
|
||||
# This special exception was added by Craig Small in version 0.37 of dh-make.
|
||||
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
VERSION=$(shell dpkg-parsechangelog | sed -n 's/^Version: //p' | cut -f1 -d'-')
|
||||
PACKAGE_NAME=$(shell dpkg-parsechangelog | sed -n 's/^Source: //p')
|
||||
|
||||
%:
|
||||
dh $@ --with autotools-dev
|
||||
|
||||
build-orig:
|
||||
mkdir -p $(PACKAGE_NAME)-$(VERSION)
|
||||
tar --exclude=ax_lua.m4 --exclude=debian --exclude=\.pc \
|
||||
|
48
debian/telegram-cli.8
vendored
Normal file
48
debian/telegram-cli.8
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
.TH man 8 "02 October 2014" "1.0.5.1" "telegram-cli man page"
|
||||
.SH NAME
|
||||
telegram-cli \- Command-line interface for Telegram messenger
|
||||
.SH SYNOPSIS
|
||||
telegram-cli -k [keyfile]
|
||||
.SH DESCRIPTION
|
||||
Telegram messenger is a cloud-based instant messaging designed for
|
||||
smart phones and similar to Whatsapp but more flexible, and
|
||||
powerful. You can send messages, photos, videos and documents to
|
||||
people who are in your phone contacts (and have Telegram). Telegram
|
||||
also supports secret chats whose provide a private (encrypted) way of
|
||||
communication.
|
||||
.
|
||||
This package contains a command-line based client for Telegram with
|
||||
the following features:
|
||||
* Colored terminal messages.
|
||||
* Message management: history, stats, etc.
|
||||
* Group chat: create and manage groups.
|
||||
* Secret chat: secured and encrypted conversations.
|
||||
* Contact management: add/edit/remove contacts.
|
||||
* Multimedia support: send/load photos and videos.
|
||||
.SH OPTIONS
|
||||
Telegram-cli Usage
|
||||
-u specify username (would not be asked during authorization)
|
||||
-k specify location of public key (possible multiple entries)
|
||||
-v increase verbosity (0-ERROR 1-WARNIN 2-NOTICE 3+-DEBUG-levels)
|
||||
-N message num mode
|
||||
-c config file name
|
||||
-p use specified profile
|
||||
-l log level
|
||||
-f during authorization fetch all messages since registration
|
||||
-E diable auto accept of encrypted chats
|
||||
-s lua script file
|
||||
-W send dialog_list query and wait for answer before reading input
|
||||
-C disable color output
|
||||
-R disable readline
|
||||
-d daemon mode
|
||||
-L <log-name> log file name
|
||||
-U <user-name> change uid after start
|
||||
-G <group-name> change gid after start
|
||||
-D disable output
|
||||
-P <port> port to listen for input commands
|
||||
-S <socket-name> unix socket to create
|
||||
.SH SEE ALSO
|
||||
.SH BUGS
|
||||
No known bugs.
|
||||
.SH AUTHOR
|
||||
Vitaliy Vatman (-@-)
|
1
debian/telegram-cli.manpages
vendored
Normal file
1
debian/telegram-cli.manpages
vendored
Normal file
@ -0,0 +1 @@
|
||||
debian/telegram-cli.8
|
73
dump-tl-file.c
Normal file
73
dump-tl-file.c
Normal file
@ -0,0 +1,73 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "auto.h"
|
||||
|
||||
int *tgl_in_ptr, *tgl_in_end;
|
||||
|
||||
int tgl_packet_buffer[0];
|
||||
int *tgl_packet_ptr;
|
||||
|
||||
char *tgl_strdup (char *s) {
|
||||
return strdup (s);
|
||||
}
|
||||
|
||||
void tgl_out_cstring (const char *str, long len) {}
|
||||
char *tglf_extf_fetch (struct paramed_type *T);
|
||||
|
||||
#define LEN (1 << 28)
|
||||
static int x[LEN / 4];
|
||||
int main (int argc, char **argv) {
|
||||
int i;
|
||||
int dump_binlog = 0;
|
||||
while ((i = getopt (argc, argv, "b")) != -1) {
|
||||
switch (i) {
|
||||
case 'b':
|
||||
dump_binlog = 1;
|
||||
break;
|
||||
default:
|
||||
printf ("unknown option '%c'\n", (char)i);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
if (!dump_binlog) {
|
||||
exit (1);
|
||||
}
|
||||
if (optind + 1 != argc) {
|
||||
exit (1);
|
||||
}
|
||||
int fd = open (argv[optind], O_RDONLY);
|
||||
if (fd < 0) {
|
||||
perror ("open");
|
||||
exit (1);
|
||||
}
|
||||
int r = read (fd, x, LEN);
|
||||
if (r <= 0) {
|
||||
perror ("read");
|
||||
exit (1);
|
||||
}
|
||||
if (r == LEN) {
|
||||
printf ("Too long file\n");
|
||||
exit (1);
|
||||
}
|
||||
assert (!(r & 3));
|
||||
tgl_in_ptr = x;
|
||||
tgl_in_end = x + (r / 4);
|
||||
while (tgl_in_ptr < tgl_in_end) {
|
||||
if (dump_binlog) {
|
||||
char *R = tglf_extf_fetch (TYPE_TO_PARAM(binlog_update));
|
||||
if (!R) {
|
||||
printf ("Can not fetch\n");
|
||||
exit (1);
|
||||
}
|
||||
printf ("%s\n", R);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1 +1 @@
|
||||
encrypted_scheme16.tl
|
||||
encrypted_scheme17.tl
|
30
encrypted_scheme17.tl
Normal file
30
encrypted_scheme17.tl
Normal file
@ -0,0 +1,30 @@
|
||||
---types---
|
||||
decryptedMessageLayer#99a438cf layer:int message:DecryptedMessage = DecryptedMessageLayer;
|
||||
decryptedMessage_l16#1f814f1f random_id:long random_bytes:bytes message:string media:DecryptedMessageMedia = DecryptedMessage;
|
||||
decryptedMessageService_l16#aa48327d random_id:long random_bytes:bytes action:DecryptedMessageAction = DecryptedMessage;
|
||||
|
||||
decryptedMessage#20a6d4e2 in_seq_no:int out_seq_no:int ttl:int random_id:long random_bytes:bytes message:string media:DecryptedMessageMedia = DecryptedMessage;
|
||||
decryptedMessageService#9bb84a4e in_seq_no:int out_seq_no:int random_id:long random_bytes:bytes action:DecryptedMessageAction = DecryptedMessage;
|
||||
|
||||
decryptedMessageMediaEmpty#89f5c4a = DecryptedMessageMedia;
|
||||
decryptedMessageMediaPhoto#32798a8c thumb:bytes thumb_w:int thumb_h:int w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
|
||||
//decryptedMessageMediaVideo#4cee6ef3 thumb:bytes thumb_w:int thumb_h:int duration:int w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
|
||||
decryptedMessageMediaGeoPoint#35480a59 lat:double long:double = DecryptedMessageMedia;
|
||||
decryptedMessageMediaContact#588a0a97 phone_number:string first_name:string last_name:string user_id:int = DecryptedMessageMedia;
|
||||
decryptedMessageActionSetMessageTTL#a1733aec ttl_seconds:int = DecryptedMessageAction;
|
||||
|
||||
decryptedMessageMediaDocument#b095434b thumb:bytes thumb_w:int thumb_h:int file_name:string mime_type:string size:int key:bytes iv:bytes = DecryptedMessageMedia;
|
||||
//decryptedMessageMediaAudio#6080758f duration:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
|
||||
|
||||
decryptedMessageMediaVideo#524a415d thumb:bytes thumb_w:int thumb_h:int duration:int mime_type:string w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
|
||||
decryptedMessageMediaAudio#57e0a9cb duration:int mime_type:string size:int key:bytes iv:bytes = DecryptedMessageMedia;
|
||||
decryptedMessageActionReadMessages#c4f40be random_ids:Vector<long> = DecryptedMessageAction;
|
||||
decryptedMessageActionDeleteMessages#65614304 random_ids:Vector<long> = DecryptedMessageAction;
|
||||
decryptedMessageActionScreenshotMessages#8ac1f475 random_ids:Vector<long> = DecryptedMessageAction;
|
||||
decryptedMessageActionFlushHistory#6719e45c = DecryptedMessageAction;
|
||||
decryptedMessageActionNotifyLayer#f3048883 layer:int = DecryptedMessageAction;
|
||||
|
||||
|
||||
decryptedMessageActionTyping#ccb27641 action:SendMessageAction = DecryptedMessageAction;
|
||||
|
||||
---functions---
|
181
interface.c
181
interface.c
@ -292,6 +292,23 @@ long long cur_token_int (void) {
|
||||
}
|
||||
}
|
||||
|
||||
double cur_token_double (void) {
|
||||
if (cur_token_len <= 0) {
|
||||
return NOT_FOUND;
|
||||
} else {
|
||||
char c = cur_token[cur_token_len];
|
||||
cur_token[cur_token_len] = 0;
|
||||
char *end = 0;
|
||||
double x = strtod (cur_token, &end);
|
||||
cur_token[cur_token_len] = c;
|
||||
if (end != cur_token + cur_token_len) {
|
||||
return NOT_FOUND;
|
||||
} else {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tgl_peer_id_t cur_token_user (void) {
|
||||
if (cur_token_len <= 0) { return TGL_PEER_NOT_FOUND; }
|
||||
int l = cur_token_len;
|
||||
@ -300,17 +317,17 @@ tgl_peer_id_t cur_token_user (void) {
|
||||
char c = cur_token[cur_token_len];
|
||||
cur_token[cur_token_len] = 0;
|
||||
|
||||
if (l >= 6 && !memcmp (s, "user#", 5)) {
|
||||
s += 5;
|
||||
l -= 5;
|
||||
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, "user#id", 7)) {
|
||||
s += 7;
|
||||
l -= 7;
|
||||
if (l >= 6 && !memcmp (s, "user#", 5)) {
|
||||
s += 5;
|
||||
l -= 5;
|
||||
int r = atoi (s);
|
||||
cur_token[cur_token_len] = c;
|
||||
if (r >= 0) { return tgl_set_peer_id (TGL_PEER_USER, r); }
|
||||
@ -335,18 +352,17 @@ tgl_peer_id_t cur_token_chat (void) {
|
||||
char c = cur_token[cur_token_len];
|
||||
cur_token[cur_token_len] = 0;
|
||||
|
||||
if (l >= 6 && !memcmp (s, "chat#", 5)) {
|
||||
s += 5;
|
||||
l -= 5;
|
||||
if (l >= 8 && !memcmp (s, "chat#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_CHAT, r); }
|
||||
else { return TGL_PEER_NOT_FOUND; }
|
||||
}
|
||||
|
||||
if (l >= 8 && !memcmp (s, "chat#id", 7)) {
|
||||
s += 7;
|
||||
l -= 7;
|
||||
if (l >= 6 && !memcmp (s, "chat#", 5)) {
|
||||
s += 5;
|
||||
l -= 5;
|
||||
int r = atoi (s);
|
||||
cur_token[cur_token_len] = c;
|
||||
if (r >= 0) { return tgl_set_peer_id (TGL_PEER_CHAT, r); }
|
||||
@ -386,22 +402,6 @@ tgl_peer_id_t cur_token_peer (void) {
|
||||
char c = cur_token[cur_token_len];
|
||||
cur_token[cur_token_len] = 0;
|
||||
|
||||
if (l >= 6 && !memcmp (s, "user#", 5)) {
|
||||
s += 5;
|
||||
l -= 5;
|
||||
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 >= 6 && !memcmp (s, "chat#", 5)) {
|
||||
s += 5;
|
||||
l -= 5;
|
||||
int r = atoi (s);
|
||||
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;
|
||||
@ -418,6 +418,22 @@ tgl_peer_id_t cur_token_peer (void) {
|
||||
if (r >= 0) { return tgl_set_peer_id (TGL_PEER_CHAT, r); }
|
||||
else { return TGL_PEER_NOT_FOUND; }
|
||||
}
|
||||
if (l >= 6 && !memcmp (s, "user#", 5)) {
|
||||
s += 5;
|
||||
l -= 5;
|
||||
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 >= 6 && !memcmp (s, "chat#", 5)) {
|
||||
s += 5;
|
||||
l -= 5;
|
||||
int r = atoi (s);
|
||||
cur_token[cur_token_len] = c;
|
||||
if (r >= 0) { return tgl_set_peer_id (TGL_PEER_CHAT, r); }
|
||||
else { return TGL_PEER_NOT_FOUND; }
|
||||
}
|
||||
|
||||
tgl_peer_t *P = tgl_peer_get_by_name (s);
|
||||
cur_token[cur_token_len] = c;
|
||||
@ -432,6 +448,15 @@ tgl_peer_id_t cur_token_peer (void) {
|
||||
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);
|
||||
if (!P) {
|
||||
if (tgl_get_peer_type (id) == TGL_PEER_USER) {
|
||||
tgl_insert_empty_user (tgl_get_peer_id (id));
|
||||
}
|
||||
if (tgl_get_peer_type (id) == TGL_PEER_CHAT) {
|
||||
tgl_insert_empty_chat (tgl_get_peer_id (id));
|
||||
}
|
||||
P = tgl_peer_get (id);
|
||||
}
|
||||
return P;
|
||||
}
|
||||
|
||||
@ -511,6 +536,7 @@ enum command_argument {
|
||||
ca_file_name_end,
|
||||
ca_period,
|
||||
ca_number,
|
||||
ca_double,
|
||||
ca_string_end,
|
||||
ca_string,
|
||||
ca_modifier,
|
||||
@ -528,6 +554,7 @@ struct arg {
|
||||
struct tgl_message *M;
|
||||
char *str;
|
||||
long long num;
|
||||
double dval;
|
||||
};
|
||||
};
|
||||
|
||||
@ -988,6 +1015,11 @@ void do_clear (int arg_num, struct arg args[], struct in_ev *ev) {
|
||||
do_halt (0);
|
||||
}
|
||||
|
||||
void do_send_location (int arg_num, struct arg args[], struct in_ev *ev) {
|
||||
assert (arg_num == 3);
|
||||
tgl_do_send_location (args[0].P->id, args[1].dval, args[2].dval, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
struct command commands[] = {
|
||||
{"help", {ca_none}, do_help, "help\tPrints this help"},
|
||||
@ -1030,7 +1062,7 @@ struct command commands[] = {
|
||||
{"chat_del_user", {ca_chat, ca_user, ca_none}, do_chat_del_user, "chat_del_user <chat> <user>\tDeletes user from chat"},
|
||||
{"status_online", {ca_none}, do_status_online, "status_online\tSets status as online"},
|
||||
{"status_offline", {ca_none}, do_status_offline, "status_offline\tSets status as offline"},
|
||||
{"quit", {ca_none}, do_quit, "quit\tQuits immideatly"},
|
||||
{"quit", {ca_none}, do_quit, "quit\tQuits immediately"},
|
||||
{"safe_quit", {ca_none}, do_safe_quit, "safe_quit\tWaits for all queries to end, then quits"},
|
||||
{"set", {ca_string, ca_number, ca_none}, do_set, "set <param> <value>\tSets 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>\tInterface option. All input will be treated as messages to this peer. Type /quit to end this mode"},
|
||||
@ -1046,6 +1078,7 @@ struct command commands[] = {
|
||||
{"send_contact", {ca_peer, ca_string, ca_string, ca_string, ca_none}, do_send_contact, "send_contact <peer> <phone> <first-name> <last-name>\tSends contact (not necessary telegram user)"},
|
||||
{"main_session", {ca_none}, do_main_session, "main_session\tSends updates to this connection (or terminal). Useful only with listening socket"},
|
||||
{"clear", {ca_none}, do_clear, "clear\tClears all data and exits. For debug."},
|
||||
{"send_location", {ca_peer, ca_double, ca_double, ca_none}, do_send_location, "send_location <peer> <latitude> <longitude>\tSends geo location"},
|
||||
{0, {ca_none}, 0, ""}
|
||||
};
|
||||
|
||||
@ -1108,7 +1141,7 @@ enum command_argument get_complete_mode (void) {
|
||||
|
||||
char *save = line_ptr;
|
||||
next_token ();
|
||||
if (op == ca_user || op == ca_chat || op == ca_secret_chat || op == ca_peer || op == ca_number) {
|
||||
if (op == ca_user || op == ca_chat || op == ca_secret_chat || op == ca_peer || op == ca_number || op == ca_double) {
|
||||
if (cur_token_quoted) {
|
||||
if (opt) {
|
||||
line_ptr = save;
|
||||
@ -1137,6 +1170,9 @@ enum command_argument get_complete_mode (void) {
|
||||
case ca_number:
|
||||
ok = (cur_token_int () != NOT_FOUND);
|
||||
break;
|
||||
case ca_double:
|
||||
ok = (cur_token_double () != NOT_FOUND);
|
||||
break;
|
||||
default:
|
||||
assert (0);
|
||||
}
|
||||
@ -1222,7 +1258,7 @@ char *command_generator (const char *text, int state) {
|
||||
if (index == -1) { return 0; }
|
||||
}
|
||||
|
||||
if (mode == ca_none || mode == ca_string || mode == ca_string_end || mode == ca_number) {
|
||||
if (mode == ca_none || mode == ca_string || mode == ca_string_end || mode == ca_number || mode == ca_double) {
|
||||
if (c) { rl_line_buffer[rl_point] = c; }
|
||||
return 0;
|
||||
}
|
||||
@ -1594,26 +1630,68 @@ void mark_read_upd (int num, struct tgl_message *list[]) {
|
||||
}
|
||||
}
|
||||
|
||||
void type_notification_upd (struct tgl_user *U) {
|
||||
void print_typing (struct in_ev *ev, enum tgl_typing_status status) {
|
||||
switch (status) {
|
||||
case tgl_typing_none:
|
||||
mprintf (ev, "doing nothing");
|
||||
break;
|
||||
case tgl_typing_typing:
|
||||
mprintf (ev, "typing");
|
||||
break;
|
||||
case tgl_typing_cancel:
|
||||
mprintf (ev, "deleting typed message");
|
||||
break;
|
||||
case tgl_typing_record_video:
|
||||
mprintf (ev, "recording video");
|
||||
break;
|
||||
case tgl_typing_upload_video:
|
||||
mprintf (ev, "uploading video");
|
||||
break;
|
||||
case tgl_typing_record_audio:
|
||||
mprintf (ev, "recording audio");
|
||||
break;
|
||||
case tgl_typing_upload_audio:
|
||||
mprintf (ev, "uploading audio");
|
||||
break;
|
||||
case tgl_typing_upload_photo:
|
||||
mprintf (ev, "uploading photo");
|
||||
break;
|
||||
case tgl_typing_upload_document:
|
||||
mprintf (ev, "uploading document");
|
||||
break;
|
||||
case tgl_typing_geo:
|
||||
mprintf (ev, "choosing location");
|
||||
break;
|
||||
case tgl_typing_choose_contact:
|
||||
mprintf (ev, "choosing contact");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void type_notification_upd (struct tgl_user *U, enum tgl_typing_status status) {
|
||||
if (log_level < 2 || (disable_output && !notify_ev)) { return; }
|
||||
struct in_ev *ev = notify_ev;
|
||||
mprint_start (ev);
|
||||
mpush_color (ev, COLOR_YELLOW);
|
||||
mprintf (ev, "User ");
|
||||
print_user_name (ev, U->id, (void *)U);
|
||||
mprintf (ev, " is typing\n");
|
||||
mprintf (ev, " is ");
|
||||
print_typing (ev, status);
|
||||
mprintf (ev, "\n");
|
||||
mpop_color (ev);
|
||||
mprint_end (ev);
|
||||
}
|
||||
|
||||
void type_in_chat_notification_upd (struct tgl_user *U, struct tgl_chat *C) {
|
||||
void type_in_chat_notification_upd (struct tgl_user *U, struct tgl_chat *C, enum tgl_typing_status status) {
|
||||
if (log_level < 2 || (disable_output && !notify_ev)) { return; }
|
||||
struct in_ev *ev = notify_ev;
|
||||
mprint_start (ev);
|
||||
mpush_color (ev, COLOR_YELLOW);
|
||||
mprintf (ev, "User ");
|
||||
print_user_name (ev, U->id, (void *)U);
|
||||
mprintf (ev, " is typing in chat ");
|
||||
mprintf (ev, " is ");
|
||||
print_typing (ev, status);
|
||||
mprintf (ev, " in chat ");
|
||||
print_chat_name (ev, C->id, (void *)C);
|
||||
mprintf (ev, "\n");
|
||||
mpop_color (ev);
|
||||
@ -1916,8 +1994,11 @@ void interpreter_ex (char *line UU, void *ex) {
|
||||
if (op == ca_none) {
|
||||
next_token ();
|
||||
if (cur_token_end_str) {
|
||||
int z;
|
||||
for (z = 0; z < count; z ++) {
|
||||
fun (args_num, args, ex);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1928,7 +2009,10 @@ void interpreter_ex (char *line UU, void *ex) {
|
||||
} else {
|
||||
args[args_num].flags = 1;
|
||||
args[args_num ++].str = strndup (cur_token, cur_token_len);
|
||||
int z;
|
||||
for (z = 0; z < count; z ++) {
|
||||
fun (args_num, args, ex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1937,17 +2021,24 @@ void interpreter_ex (char *line UU, void *ex) {
|
||||
next_token ();
|
||||
|
||||
if (period && cur_token_end_str) {
|
||||
int z;
|
||||
for (z = 0; z < count; z ++) {
|
||||
fun (args_num, args, ex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (op == ca_user || op == ca_chat || op == ca_secret_chat || op == ca_peer || op == ca_number) {
|
||||
if (op == ca_user || op == ca_chat || op == ca_secret_chat || op == ca_peer || op == ca_number || op == ca_double) {
|
||||
if (cur_token_quoted) {
|
||||
if (opt) {
|
||||
if (op != ca_number) {
|
||||
if (op != ca_number && op != ca_double) {
|
||||
args[args_num ++].P = 0;
|
||||
} else {
|
||||
if (op == ca_number) {
|
||||
args[args_num ++].num = NOT_FOUND;
|
||||
} else {
|
||||
args[args_num ++].dval = NOT_FOUND;
|
||||
}
|
||||
}
|
||||
line_ptr = save;
|
||||
flags ++;
|
||||
@ -1958,10 +2049,14 @@ void interpreter_ex (char *line UU, void *ex) {
|
||||
} else {
|
||||
if (cur_token_end_str) {
|
||||
if (opt) {
|
||||
if (op != ca_number) {
|
||||
if (op != ca_number && op != ca_double) {
|
||||
args[args_num ++].P = 0;
|
||||
} else {
|
||||
if (op == ca_number) {
|
||||
args[args_num ++].num = NOT_FOUND;
|
||||
} else {
|
||||
args[args_num ++].dval = NOT_FOUND;
|
||||
}
|
||||
}
|
||||
line_ptr = save;
|
||||
flags ++;
|
||||
@ -1992,6 +2087,10 @@ void interpreter_ex (char *line UU, void *ex) {
|
||||
args[args_num ++].num = cur_token_int ();
|
||||
ok = (args[args_num - 1].num != NOT_FOUND);
|
||||
break;
|
||||
case ca_double:
|
||||
args[args_num ++].dval = cur_token_double ();
|
||||
ok = (args[args_num - 1].dval != NOT_FOUND);
|
||||
break;
|
||||
default:
|
||||
assert (0);
|
||||
}
|
||||
@ -2386,6 +2485,10 @@ void print_service_message (struct in_ev *ev, struct tgl_message *M) {
|
||||
case tgl_message_action_notify_layer:
|
||||
mprintf (ev, " updated layer to %d\n", M->action.layer);
|
||||
break;
|
||||
case tgl_message_action_typing:
|
||||
mprintf (ev, " is ");
|
||||
print_typing (ev, M->action.typing);
|
||||
break;
|
||||
default:
|
||||
assert (0);
|
||||
}
|
||||
|
32
loop.c
32
loop.c
@ -91,6 +91,8 @@ static int delete_stdin_event;
|
||||
|
||||
extern volatile int sigterm_cnt;
|
||||
|
||||
extern char *start_command;
|
||||
|
||||
static void stdin_read_callback_all (int arg, short what, struct event *self) {
|
||||
if (!readline_disabled) {
|
||||
if (((long)arg) & 1) {
|
||||
@ -500,9 +502,19 @@ void read_dc (int auth_file_fd, int id, unsigned ver) {
|
||||
}
|
||||
|
||||
void empty_auth_file (void) {
|
||||
char *ip = tgl_state.test_mode ? TG_SERVER_TEST : TG_SERVER;
|
||||
bl_do_dc_option (tgl_state.test_mode ? TG_SERVER_TEST_DC : TG_SERVER_DC, 0, "", strlen (ip), ip, 443);
|
||||
bl_do_set_working_dc (tgl_state.test_mode ? TG_SERVER_TEST_DC : TG_SERVER_DC);
|
||||
if (tgl_state.test_mode) {
|
||||
bl_do_dc_option (1, 0, "", strlen (TG_SERVER_TEST_1), TG_SERVER_TEST_1, 443);
|
||||
bl_do_dc_option (2, 0, "", strlen (TG_SERVER_TEST_2), TG_SERVER_TEST_2, 443);
|
||||
bl_do_dc_option (3, 0, "", strlen (TG_SERVER_TEST_3), TG_SERVER_TEST_3, 443);
|
||||
bl_do_set_working_dc (2);
|
||||
} else {
|
||||
bl_do_dc_option (1, 0, "", strlen (TG_SERVER_1), TG_SERVER_1, 443);
|
||||
bl_do_dc_option (2, 0, "", strlen (TG_SERVER_2), TG_SERVER_2, 443);
|
||||
bl_do_dc_option (3, 0, "", strlen (TG_SERVER_3), TG_SERVER_3, 443);
|
||||
bl_do_dc_option (4, 0, "", strlen (TG_SERVER_4), TG_SERVER_4, 443);
|
||||
bl_do_dc_option (5, 0, "", strlen (TG_SERVER_5), TG_SERVER_5, 443);
|
||||
bl_do_set_working_dc (2);
|
||||
}
|
||||
}
|
||||
|
||||
int need_dc_list_update;
|
||||
@ -842,6 +854,20 @@ int loop (void) {
|
||||
lua_diff_end ();
|
||||
#endif
|
||||
|
||||
if (start_command) {
|
||||
safe_quit = 1;
|
||||
while (*start_command) {
|
||||
char *start = start_command;
|
||||
while (*start_command && *start_command != '\n') {
|
||||
start_command ++;
|
||||
}
|
||||
if (*start_command) {
|
||||
*start_command = 0;
|
||||
start_command ++;
|
||||
}
|
||||
interpreter_ex (start, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*tgl_do_get_dialog_list (get_dialogs_callback, 0);
|
||||
if (wait_dialog_list) {
|
||||
|
25
lua-tg.c
25
lua-tg.c
@ -495,6 +495,7 @@ enum lua_query_type {
|
||||
lq_send_contact,
|
||||
lq_status_online,
|
||||
lq_status_offline,
|
||||
lq_send_location,
|
||||
lq_extf
|
||||
};
|
||||
|
||||
@ -1086,6 +1087,14 @@ void lua_do_all (void) {
|
||||
free (s);
|
||||
p += 2;
|
||||
break;
|
||||
case lq_send_location:
|
||||
if (sizeof (void *) == 4) {
|
||||
tgl_do_send_location (((tgl_peer_t *)lua_ptr[p + 1])->id , *(float *)(lua_ptr + p + 2), *(float *)(lua_ptr + p + 3), lua_msg_cb, lua_ptr[p]);
|
||||
} else {
|
||||
tgl_do_send_location (((tgl_peer_t *)lua_ptr[p + 1])->id , *(double *)(lua_ptr + p + 2), *(double *)(lua_ptr + p + 3), lua_msg_cb, lua_ptr[p]);
|
||||
}
|
||||
p += 4;
|
||||
break;
|
||||
/*
|
||||
lq_delete_msg,
|
||||
lq_restore_msg,
|
||||
@ -1120,7 +1129,8 @@ enum lua_function_param {
|
||||
lfp_number,
|
||||
lfp_positive_number,
|
||||
lfp_nonnegative_number,
|
||||
lfp_msg
|
||||
lfp_msg,
|
||||
lfp_double
|
||||
};
|
||||
|
||||
struct lua_function {
|
||||
@ -1168,6 +1178,7 @@ struct lua_function functions[] = {
|
||||
{"send_contact", lq_send_contact, { lfp_peer, lfp_string, lfp_string, lfp_string, lfp_none }},
|
||||
{"status_online", lq_status_online, { lfp_none }},
|
||||
{"status_offline", lq_status_offline, { lfp_none }},
|
||||
{"send_location", lq_send_location, { lfp_peer, lfp_double, lfp_double, lfp_none }},
|
||||
{"ext_function", lq_extf, { lfp_string, lfp_none }},
|
||||
{ 0, 0, { lfp_none}}
|
||||
};
|
||||
@ -1203,6 +1214,7 @@ static int parse_lua_function (lua_State *L, struct lua_function *F) {
|
||||
const char *s;
|
||||
tgl_peer_t *P;
|
||||
long long num;
|
||||
double dval;
|
||||
struct tgl_message *M;
|
||||
switch (F->params[p]) {
|
||||
case lfp_none:
|
||||
@ -1256,6 +1268,17 @@ static int parse_lua_function (lua_State *L, struct lua_function *F) {
|
||||
lua_ptr[pos + p] = (void *)(long)num;
|
||||
break;
|
||||
|
||||
case lfp_double:
|
||||
dval = lua_tonumber (L, -cc);
|
||||
|
||||
if (sizeof (void *) == 4) {
|
||||
*(float *)(lua_ptr + pos + p) = dval;
|
||||
} else {
|
||||
assert (sizeof (void *) >= 8);
|
||||
*(double *)(lua_ptr + pos + p) = dval;
|
||||
}
|
||||
break;
|
||||
|
||||
case lfp_positive_number:
|
||||
num = lua_tonumber (L, -cc);
|
||||
if (num <= 0) {
|
||||
|
17
main.c
17
main.c
@ -59,6 +59,7 @@
|
||||
|
||||
#include <grp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "telegram.h"
|
||||
#include "loop.h"
|
||||
@ -110,6 +111,7 @@ int readline_disabled;
|
||||
int disable_output;
|
||||
int reset_authorization;
|
||||
int port;
|
||||
char *start_command;
|
||||
|
||||
void set_default_username (const char *s) {
|
||||
if (default_username) {
|
||||
@ -283,7 +285,7 @@ void parse_config_val (config_t *conf, char **s, char *param_name, const char *d
|
||||
strcpy (buf + l, param_name);
|
||||
config_lookup_string (conf, buf, &r);
|
||||
if (r) {
|
||||
if (path) {
|
||||
if (path && *r != '/') {
|
||||
tasprintf (s, "%s/%s", path, r);
|
||||
} else {
|
||||
*s = tstrdup (r);
|
||||
@ -399,6 +401,11 @@ void parse_config (void) {
|
||||
tasprintf (&secret_chat_file_name, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, SECRET_CHAT_FILE);
|
||||
}
|
||||
tgl_set_download_directory (downloads_directory);
|
||||
if (!mkdir (downloads_directory, CONFIG_DIRECTORY_MODE)) {
|
||||
if (!disable_output) {
|
||||
printf ("[%s] created\n", downloads_directory);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -421,7 +428,7 @@ void usage (void) {
|
||||
#endif
|
||||
printf (" -l log level\n");
|
||||
printf (" -f during authorization fetch all messages since registration\n");
|
||||
printf (" -E diable auto accept of encrypted chats\n");
|
||||
printf (" -E disable auto accept of encrypted chats\n");
|
||||
#ifdef USE_LUA
|
||||
printf (" -s lua script file\n");
|
||||
#endif
|
||||
@ -435,6 +442,7 @@ void usage (void) {
|
||||
printf (" -D disable output\n");
|
||||
printf (" -P <port> port to listen for input commands\n");
|
||||
printf (" -S <socket-name> unix socket to create\n");
|
||||
printf (" -e <commands> make commands end exit\n");
|
||||
|
||||
exit (1);
|
||||
}
|
||||
@ -537,7 +545,7 @@ char *unix_socket;
|
||||
|
||||
void args_parse (int argc, char **argv) {
|
||||
int opt = 0;
|
||||
while ((opt = getopt (argc, argv, "u:hk:vNl:fEwWCRdL:DU:G:qP:S:"
|
||||
while ((opt = getopt (argc, argv, "u:hk:vNl:fEwWCRdL:DU:G:qP:S:e:"
|
||||
#ifdef HAVE_LIBCONFIG
|
||||
"c:p:"
|
||||
#else
|
||||
@ -626,6 +634,9 @@ void args_parse (int argc, char **argv) {
|
||||
case 'S':
|
||||
unix_socket = optarg;
|
||||
break;
|
||||
case 'e':
|
||||
start_command = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
usage ();
|
||||
|
@ -80,7 +80,7 @@
|
||||
#define MAX_NET_RES (1L << 16)
|
||||
//extern int log_level;
|
||||
|
||||
#ifndef HAVE___BUILTIN_BSWAP32
|
||||
#if !defined(HAVE___BUILTIN_BSWAP32) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
|
||||
static inline unsigned __builtin_bswap32(unsigned x) {
|
||||
return ((x << 24) & 0xff000000 ) |
|
||||
((x << 8) & 0x00ff0000 ) |
|
||||
@ -284,6 +284,13 @@ static int process_respq_answer (struct connection *c, char *packet, int len, in
|
||||
unsigned long long what;
|
||||
unsigned p1, p2;
|
||||
int i;
|
||||
|
||||
long long packet_auth_key_id = *(long long *)packet;
|
||||
if (packet_auth_key_id) {
|
||||
assert (temp_key);
|
||||
vlogprintf (E_WARNING, "received packet during creation of temp auth key. Probably answer on old query. Drop\n");
|
||||
return 0;
|
||||
}
|
||||
vlogprintf (E_DEBUG, "process_respq_answer(), len=%d, op=0x%08x\n", len, *(int *)(packet + 20));
|
||||
assert (len >= 76);
|
||||
assert (!*(long long *) packet);
|
||||
@ -552,6 +559,12 @@ static int process_dh_answer (struct connection *c, char *packet, int len, int t
|
||||
//if (len < 116) {
|
||||
// vlogprintf (E_ERROR, "%u * %u = %llu", p1, p2, what);
|
||||
//}
|
||||
long long packet_auth_key_id = *(long long *)packet;
|
||||
if (packet_auth_key_id) {
|
||||
assert (temp_key);
|
||||
vlogprintf (E_WARNING, "received packet during creation of temp auth key. Probably answer on old query. Drop\n");
|
||||
return 0;
|
||||
}
|
||||
assert (len >= 116);
|
||||
assert (!*(long long *) packet);
|
||||
assert (*(int *) (packet + 16) == len - 20);
|
||||
@ -660,6 +673,13 @@ static void mpc_on_get_config (void *extra, int success);
|
||||
static int process_auth_complete (struct connection *c UU, char *packet, int len, int temp_key) {
|
||||
struct tgl_dc *D = tgl_state.net_methods->get_dc (c);
|
||||
vlogprintf (E_DEBUG - 1, "process_dh_answer(), len=%d\n", len);
|
||||
|
||||
long long packet_auth_key_id = *(long long *)packet;
|
||||
if (packet_auth_key_id) {
|
||||
assert (temp_key);
|
||||
vlogprintf (E_WARNING, "received packet during creation of temp auth key. Probably answer on old query. Drop\n");
|
||||
return 0;
|
||||
}
|
||||
assert (len == 72);
|
||||
assert (!*(long long *) packet);
|
||||
assert (*(int *) (packet + 16) == len - 20);
|
||||
@ -1058,8 +1078,9 @@ static int process_rpc_message (struct connection *c UU, struct encrypted_messag
|
||||
assert (len >= MINSZ && (len & 15) == (UNENCSZ & 15));
|
||||
struct tgl_dc *DC = tgl_state.net_methods->get_dc (c);
|
||||
if (enc->auth_key_id != DC->temp_auth_key_id && enc->auth_key_id != DC->auth_key_id) {
|
||||
vlogprintf (E_ERROR, "received msg from dc %d with auth_key_id %lld (perm_auth_key_id %lld temp_auth_key_id %lld)\n",
|
||||
vlogprintf (E_WARNING, "received msg from dc %d with auth_key_id %lld (perm_auth_key_id %lld temp_auth_key_id %lld). Dropping\n",
|
||||
DC->id, enc->auth_key_id, DC->auth_key_id, DC->temp_auth_key_id);
|
||||
return 0;
|
||||
}
|
||||
if (enc->auth_key_id == DC->temp_auth_key_id) {
|
||||
assert (enc->auth_key_id == DC->temp_auth_key_id);
|
||||
@ -1280,7 +1301,7 @@ void tglmp_on_start (void) {
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
vlogprintf (E_ERROR, "No pubic keys found\n");
|
||||
vlogprintf (E_ERROR, "No public keys found\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
@ -1341,7 +1362,8 @@ static void regen_temp_key_gw (evutil_socket_t fd, short what, void *arg) {
|
||||
}
|
||||
|
||||
struct tgl_dc *tglmp_alloc_dc (int id, char *ip, int port UU) {
|
||||
assert (!tgl_state.DC_list[id]);
|
||||
//assert (!tgl_state.DC_list[id]);
|
||||
if (!tgl_state.DC_list[id]) {
|
||||
struct tgl_dc *DC = talloc0 (sizeof (*DC));
|
||||
DC->id = id;
|
||||
DC->ip = ip;
|
||||
@ -1354,6 +1376,12 @@ struct tgl_dc *tglmp_alloc_dc (int id, char *ip, int port UU) {
|
||||
static struct timeval p;
|
||||
event_add (DC->ev, &p);
|
||||
return DC;
|
||||
} else {
|
||||
struct tgl_dc *DC = tgl_state.DC_list[id];
|
||||
tfree_str (DC->ip);
|
||||
DC->ip = tstrdup (ip);
|
||||
return DC;
|
||||
}
|
||||
}
|
||||
|
||||
static struct mtproto_methods mtproto_methods = {
|
||||
|
@ -201,7 +201,6 @@ static inline int prefetch_strlen (void) {
|
||||
|
||||
static inline char *fetch_str (int len) {
|
||||
assert (len >= 0);
|
||||
vlogprintf (E_DEBUG + 3, "fetch_string: len = %d\n", len);
|
||||
if (len < 254) {
|
||||
char *str = (char *) in_ptr + 1;
|
||||
in_ptr += 1 + (len >> 2);
|
||||
@ -294,12 +293,10 @@ int tgl_fetch_bignum (BIGNUM *x);
|
||||
|
||||
static inline int fetch_int (void) {
|
||||
assert (in_ptr + 1 <= in_end);
|
||||
vlogprintf (E_DEBUG + 3, "fetch_int: 0x%08x (%d)\n", *in_ptr, *in_ptr);
|
||||
return *(in_ptr ++);
|
||||
}
|
||||
|
||||
static inline int fetch_bool (void) {
|
||||
vlogprintf (E_DEBUG + 3, "fetch_bool: 0x%08x (%d)\n", *in_ptr, *in_ptr);
|
||||
assert (in_ptr + 1 <= in_end);
|
||||
assert (*(in_ptr) == (int)CODE_bool_true || *(in_ptr) == (int)CODE_bool_false);
|
||||
return *(in_ptr ++) == (int)CODE_bool_true;
|
||||
|
6
net.c
6
net.c
@ -26,11 +26,11 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
@ -345,6 +345,10 @@ static void restart_connection (struct connection *c) {
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons (c->port);
|
||||
if (strcmp (c->ip, c->dc->ip)) {
|
||||
tfree_str (c->ip);
|
||||
c->ip = tstrdup (c->dc->ip);
|
||||
}
|
||||
addr.sin_addr.s_addr = inet_addr (c->ip);
|
||||
|
||||
|
||||
|
139
queries.c
139
queries.c
@ -94,7 +94,7 @@ struct query *tglq_query_get (long long id) {
|
||||
|
||||
static int alarm_query (struct query *q) {
|
||||
assert (q);
|
||||
vlogprintf (E_DEBUG, "Alarm query %lld\n", q->msg_id);
|
||||
vlogprintf (E_DEBUG - 1, "Alarm query %lld\n", q->msg_id);
|
||||
//q->ev.timeout = get_double_time () + QUERY_TIMEOUT;
|
||||
//insert_event_timer (&q->ev);
|
||||
|
||||
@ -118,7 +118,9 @@ static int alarm_query (struct query *q) {
|
||||
tglmp_encrypt_send_message (q->session->c, packet_buffer, packet_ptr - packet_buffer, q->flags & QUERY_FORCE_SEND);
|
||||
} else {
|
||||
q->flags &= ~QUERY_ACK_RECEIVED;
|
||||
if (tree_lookup_query (queries_tree, q)) {
|
||||
queries_tree = tree_delete_query (queries_tree, q);
|
||||
}
|
||||
q->msg_id = tglmp_encrypt_send_message (q->session->c, q->data, q->data_len, (q->flags & QUERY_FORCE_SEND) | 1);
|
||||
queries_tree = tree_insert_query (queries_tree, q, lrand48 ());
|
||||
q->session_id = q->session->session_id;
|
||||
@ -219,15 +221,36 @@ void tglq_query_error (long long id) {
|
||||
event_del (q->ev);
|
||||
}
|
||||
queries_tree = tree_delete_query (queries_tree, q);
|
||||
if (q->methods && q->methods->on_error) {
|
||||
q->methods->on_error (q, error_code, error_len, error);
|
||||
int res = 0;
|
||||
if (q->methods && q->methods->on_error && error_code != 500) {
|
||||
res = q->methods->on_error (q, error_code, error_len, error);
|
||||
} else {
|
||||
vlogprintf ( E_WARNING, "error for query #%lld: #%d :%.*s\n", id, error_code, error_len, error);
|
||||
if (error_code == 420 || error_code == 500) {
|
||||
int wait;
|
||||
if (error_code == 420) {
|
||||
if (strncmp (error, "FLOOD_WAIT_", 11)) {
|
||||
vlogprintf (E_ERROR, "error = '%s'\n", error);
|
||||
wait = 10;
|
||||
} else {
|
||||
wait = atoll (error + 11);
|
||||
}
|
||||
} else {
|
||||
wait = 10;
|
||||
}
|
||||
q->flags &= ~QUERY_ACK_RECEIVED;
|
||||
static struct timeval ptimeout;
|
||||
ptimeout.tv_sec = wait;
|
||||
event_add (q->ev, &ptimeout);
|
||||
q->session_id = 0;
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
if (res <= 0) {
|
||||
tfree (q->data, q->data_len * 4);
|
||||
event_free (q->ev);
|
||||
tfree (q, sizeof (*q));
|
||||
}
|
||||
}
|
||||
tgl_state.active_queries --;
|
||||
}
|
||||
|
||||
@ -314,7 +337,7 @@ static void out_random (int n) {
|
||||
|
||||
int allow_send_linux_version;
|
||||
void tgl_do_insert_header (void) {
|
||||
out_int (CODE_invoke_with_layer16);
|
||||
out_int (CODE_invoke_with_layer17);
|
||||
out_int (CODE_init_connection);
|
||||
out_int (TG_APP_ID);
|
||||
if (allow_send_linux_version) {
|
||||
@ -914,7 +937,17 @@ static int msg_send_on_answer (struct query *q UU) {
|
||||
}
|
||||
|
||||
static int msg_send_on_error (struct query *q, int error_code, int error_len, char *error) {
|
||||
vlogprintf (E_WARNING, "error for query #%lld: #%d :%.*s\n", q->msg_id, error_code, error_len, error);
|
||||
//vlogprintf (E_WARNING, "error for query #%lld: #%d :%.*s\n", q->msg_id, error_code, error_len, error);
|
||||
if (error_code == 420) {
|
||||
assert (!strncmp (error, "FLOOD_WAIT_", 11));
|
||||
int wait = atoll (error + 11);
|
||||
q->flags &= ~QUERY_ACK_RECEIVED;
|
||||
static struct timeval ptimeout;
|
||||
ptimeout.tv_sec = wait;
|
||||
event_add (q->ev, &ptimeout);
|
||||
q->session_id = 0;
|
||||
return 1;
|
||||
}
|
||||
long long x = *(long long *)q->extra;
|
||||
tfree (q->extra, 8);
|
||||
struct tgl_message *M = tgl_message_get (x);
|
||||
@ -957,7 +990,13 @@ void tgl_do_send_encr_msg_action (struct tgl_message *M, void (*callback)(void *
|
||||
out_long (P->encr_chat.access_hash);
|
||||
out_long (M->id);
|
||||
encr_start ();
|
||||
if (P->encr_chat.layer <= 16) {
|
||||
out_int (CODE_decrypted_message_service_l16);
|
||||
} else {
|
||||
out_int (CODE_decrypted_message_service);
|
||||
out_int (2 * P->encr_chat.in_seq_no + (P->encr_chat.admin_id != tgl_state.our_id));
|
||||
out_int (2 * P->encr_chat.out_seq_no + (P->encr_chat.admin_id == tgl_state.our_id));
|
||||
}
|
||||
out_long (M->id);
|
||||
static int buf[4];
|
||||
tglt_secure_random (buf, 16);
|
||||
@ -1001,7 +1040,14 @@ void tgl_do_send_encr_msg (struct tgl_message *M, void (*callback)(void *callbac
|
||||
out_long (P->encr_chat.access_hash);
|
||||
out_long (M->id);
|
||||
encr_start ();
|
||||
if (P->encr_chat.layer <= 16) {
|
||||
out_int (CODE_decrypted_message_l16);
|
||||
} else {
|
||||
out_int (CODE_decrypted_message);
|
||||
out_int (2 * P->encr_chat.in_seq_no + (P->encr_chat.admin_id != tgl_state.our_id));
|
||||
out_int (2 * P->encr_chat.out_seq_no + (P->encr_chat.admin_id == tgl_state.our_id));
|
||||
out_int (0);
|
||||
}
|
||||
out_long (M->id);
|
||||
static int buf[4];
|
||||
tglt_secure_random (buf, 16);
|
||||
@ -1141,6 +1187,7 @@ void tgl_do_messages_mark_read (tgl_peer_id_t id, int max_id, int offset, void (
|
||||
out_peer_id (id);
|
||||
out_int (max_id);
|
||||
out_int (offset);
|
||||
out_int (CODE_bool_true);
|
||||
int *t = talloc (12);
|
||||
t[0] = tgl_get_peer_type (id);
|
||||
t[1] = tgl_get_peer_id (id);
|
||||
@ -1738,7 +1785,14 @@ static void send_part (struct send_file *f, void *callback, void *callback_extra
|
||||
tglt_secure_random (&r, 8);
|
||||
out_long (r);
|
||||
encr_start ();
|
||||
if (P->encr_chat.layer <= 16) {
|
||||
out_int (CODE_decrypted_message_l16);
|
||||
} else {
|
||||
out_int (CODE_decrypted_message);
|
||||
out_int (2 * P->encr_chat.in_seq_no + (P->encr_chat.admin_id != tgl_state.our_id));
|
||||
out_int (2 * P->encr_chat.out_seq_no + (P->encr_chat.admin_id == tgl_state.our_id) + 2);
|
||||
out_int (0);
|
||||
}
|
||||
out_long (r);
|
||||
out_random (15 + 4 * (lrand48 () % 3));
|
||||
out_string ("");
|
||||
@ -1783,9 +1837,7 @@ static void send_part (struct send_file *f, void *callback, void *callback_extra
|
||||
out_cstring ((void *)f->key, 32);
|
||||
out_cstring ((void *)f->init_iv, 32);
|
||||
|
||||
long long msg_id;
|
||||
tglt_secure_random (&msg_id, 8);
|
||||
bl_do_create_message_media_encr_pending (msg_id, tgl_state.our_id, tgl_get_peer_type (f->to_id), tgl_get_peer_id (f->to_id), time (0), 0, 0, save_ptr, packet_ptr - save_ptr);
|
||||
bl_do_create_message_media_encr_pending (r, tgl_state.our_id, tgl_get_peer_type (f->to_id), tgl_get_peer_id (f->to_id), time (0), 0, 0, save_ptr, packet_ptr - save_ptr);
|
||||
|
||||
encr_finish (&P->encr_chat);
|
||||
if (f->size < (16 << 20)) {
|
||||
@ -1807,7 +1859,7 @@ static void send_part (struct send_file *f, void *callback, void *callback_extra
|
||||
out_int ((*(int *)md5) ^ (*(int *)(md5 + 4)));
|
||||
|
||||
tfree_secure (f->iv, 32);
|
||||
struct tgl_message *M = tgl_message_get (msg_id);
|
||||
struct tgl_message *M = tgl_message_get (r);
|
||||
assert (M);
|
||||
|
||||
//M->media.encr_photo.key = f->key;
|
||||
@ -1943,6 +1995,7 @@ void tgl_do_set_profile_photo (char *file_name, void (*callback)(void *callback_
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ Forward */
|
||||
static int fwd_msg_on_answer (struct query *q UU) {
|
||||
assert (fetch_int () == (int)CODE_messages_stated_message);
|
||||
@ -2093,6 +2146,65 @@ void tgl_do_forward_media (tgl_peer_id_t id, int n, void (*callback)(void *callb
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Send location */
|
||||
|
||||
void tgl_do_send_location(tgl_peer_id_t id, double latitude, double longitude, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
|
||||
if (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT) {
|
||||
clear_packet ();
|
||||
out_int (CODE_messages_send_encrypted);
|
||||
out_int (CODE_input_encrypted_chat);
|
||||
out_int (tgl_get_peer_id (id));
|
||||
tgl_peer_t *P = tgl_peer_get (id);
|
||||
assert (P);
|
||||
out_long (P->encr_chat.access_hash);
|
||||
|
||||
long long r;
|
||||
tglt_secure_random (&r, 8);
|
||||
out_long (r);
|
||||
encr_start ();
|
||||
if (P->encr_chat.layer <= 16) {
|
||||
out_int (CODE_decrypted_message_l16);
|
||||
} else {
|
||||
out_int (CODE_decrypted_message);
|
||||
out_int (2 * P->encr_chat.in_seq_no + (P->encr_chat.admin_id != tgl_state.our_id));
|
||||
out_int (2 * P->encr_chat.out_seq_no + (P->encr_chat.admin_id == tgl_state.our_id) + 2);
|
||||
out_int (0);
|
||||
}
|
||||
out_long (r);
|
||||
out_random (15 + 4 * (lrand48 () % 3));
|
||||
out_string ("");
|
||||
int *save_ptr = packet_ptr;
|
||||
out_int (CODE_decrypted_message_media_geo_point);
|
||||
out_double (latitude);
|
||||
out_double (longitude);
|
||||
|
||||
bl_do_create_message_media_encr_pending (r, tgl_state.our_id, tgl_get_peer_type (id), tgl_get_peer_id (id), time (0), 0, 0, save_ptr, packet_ptr - save_ptr);
|
||||
|
||||
encr_finish (&P->encr_chat);
|
||||
|
||||
struct tgl_message *M = tgl_message_get (r);
|
||||
assert (M);
|
||||
|
||||
tglq_send_query (tgl_state.DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_encr_methods, M, callback, callback_extra);
|
||||
} else {
|
||||
long long t;
|
||||
tglt_secure_random (&t, 8);
|
||||
vlogprintf (E_DEBUG, "t = %lld\n", t);
|
||||
|
||||
clear_packet ();
|
||||
out_int (CODE_messages_send_media);
|
||||
out_peer_id (id);
|
||||
out_int (CODE_input_media_geo_point);
|
||||
out_int (CODE_input_geo_point);
|
||||
out_double (latitude);
|
||||
out_double (longitude);
|
||||
out_long (t);
|
||||
|
||||
tglq_send_query (tgl_state.DC_working, packet_ptr - packet_buffer, packet_buffer, &fwd_msg_methods, 0, callback, callback_extra);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Rename chat */
|
||||
static int rename_chat_on_answer (struct query *q UU) {
|
||||
assert (fetch_int () == (int)CODE_messages_stated_message);
|
||||
@ -2361,6 +2473,10 @@ static int download_on_answer (struct query *q) {
|
||||
struct download *D = q->extra;
|
||||
if (D->fd == -1) {
|
||||
D->fd = open (D->name, O_CREAT | O_WRONLY, 0640);
|
||||
if (D->fd < 0) {
|
||||
vlogprintf (E_ERROR, "Can not open for writing: %m\n");
|
||||
assert (D->fd >= 0);
|
||||
}
|
||||
}
|
||||
fetch_int (); // mtime
|
||||
int len = prefetch_strlen ();
|
||||
@ -2906,6 +3022,9 @@ static int send_encr_accept_on_answer (struct query *q UU) {
|
||||
print_end ();
|
||||
}*/
|
||||
|
||||
if (E->state == sc_ok) {
|
||||
tgl_do_send_encr_chat_layer (E);
|
||||
}
|
||||
if (q->callback) {
|
||||
((void (*)(void *, int, struct tgl_secret_chat *))q->callback) (q->callback_extra, E->state == sc_ok, E);
|
||||
}
|
||||
|
528
scheme17.tl
Normal file
528
scheme17.tl
Normal file
@ -0,0 +1,528 @@
|
||||
int ?= Int;
|
||||
long ?= Long;
|
||||
double ?= Double;
|
||||
string ?= String;
|
||||
|
||||
bytes string = Bytes;
|
||||
|
||||
boolFalse#bc799737 = Bool;
|
||||
boolTrue#997275b5 = Bool;
|
||||
|
||||
vector#1cb5c415 {t:Type} # [ t ] = Vector t;
|
||||
|
||||
error#c4b9f9bb code:int text:string = Error;
|
||||
|
||||
null#56730bcc = Null;
|
||||
|
||||
inputPeerEmpty#7f3b18ea = InputPeer;
|
||||
inputPeerSelf#7da07ec9 = InputPeer;
|
||||
inputPeerContact#1023dbe8 user_id:int = InputPeer;
|
||||
inputPeerForeign#9b447325 user_id:int access_hash:long = InputPeer;
|
||||
inputPeerChat#179be863 chat_id:int = InputPeer;
|
||||
|
||||
inputUserEmpty#b98886cf = InputUser;
|
||||
inputUserSelf#f7c1b13f = InputUser;
|
||||
inputUserContact#86e94f65 user_id:int = InputUser;
|
||||
inputUserForeign#655e74ff user_id:int access_hash:long = InputUser;
|
||||
|
||||
inputPhoneContact#f392b7f4 client_id:long phone:string first_name:string last_name:string = InputContact;
|
||||
|
||||
inputFile#f52ff27f id:long parts:int name:string md5_checksum:string = InputFile;
|
||||
|
||||
inputMediaEmpty#9664f57f = InputMedia;
|
||||
inputMediaUploadedPhoto#2dc53a7d file:InputFile = InputMedia;
|
||||
inputMediaPhoto#8f2ab2ec id:InputPhoto = InputMedia;
|
||||
inputMediaGeoPoint#f9c44144 geo_point:InputGeoPoint = InputMedia;
|
||||
inputMediaContact#a6e45987 phone_number:string first_name:string last_name:string = InputMedia;
|
||||
inputMediaUploadedVideo#133ad6f6 file:InputFile duration:int w:int h:int mime_type:string = InputMedia;
|
||||
inputMediaUploadedThumbVideo#9912dabf file:InputFile thumb:InputFile duration:int w:int h:int mime_type:string = InputMedia;
|
||||
inputMediaVideo#7f023ae6 id:InputVideo = InputMedia;
|
||||
|
||||
inputChatPhotoEmpty#1ca48f57 = InputChatPhoto;
|
||||
inputChatUploadedPhoto#94254732 file:InputFile crop:InputPhotoCrop = InputChatPhoto;
|
||||
inputChatPhoto#b2e1bf08 id:InputPhoto crop:InputPhotoCrop = InputChatPhoto;
|
||||
|
||||
inputGeoPointEmpty#e4c123d6 = InputGeoPoint;
|
||||
inputGeoPoint#f3b7acc9 lat:double long:double = InputGeoPoint;
|
||||
|
||||
inputPhotoEmpty#1cd7bf0d = InputPhoto;
|
||||
inputPhoto#fb95c6c4 id:long access_hash:long = InputPhoto;
|
||||
|
||||
inputVideoEmpty#5508ec75 = InputVideo;
|
||||
inputVideo#ee579652 id:long access_hash:long = InputVideo;
|
||||
|
||||
inputFileLocation#14637196 volume_id:long local_id:int secret:long = InputFileLocation;
|
||||
inputVideoFileLocation#3d0364ec id:long access_hash:long = InputFileLocation;
|
||||
|
||||
inputPhotoCropAuto#ade6b004 = InputPhotoCrop;
|
||||
inputPhotoCrop#d9915325 crop_left:double crop_top:double crop_width:double = InputPhotoCrop;
|
||||
|
||||
inputAppEvent#770656a8 time:double type:string peer:long data:string = InputAppEvent;
|
||||
|
||||
peerUser#9db1bc6d user_id:int = Peer;
|
||||
peerChat#bad0e5bb chat_id:int = Peer;
|
||||
|
||||
storage.fileUnknown#aa963b05 = storage.FileType;
|
||||
storage.fileJpeg#7efe0e = storage.FileType;
|
||||
storage.fileGif#cae1aadf = storage.FileType;
|
||||
storage.filePng#a4f63c0 = storage.FileType;
|
||||
storage.filePdf#ae1e508d = storage.FileType;
|
||||
storage.fileMp3#528a0677 = storage.FileType;
|
||||
storage.fileMov#4b09ebbc = storage.FileType;
|
||||
storage.filePartial#40bc6f52 = storage.FileType;
|
||||
storage.fileMp4#b3cea0e4 = storage.FileType;
|
||||
storage.fileWebp#1081464c = storage.FileType;
|
||||
|
||||
fileLocationUnavailable#7c596b46 volume_id:long local_id:int secret:long = FileLocation;
|
||||
fileLocation#53d69076 dc_id:int volume_id:long local_id:int secret:long = FileLocation;
|
||||
|
||||
userEmpty#200250ba id:int = User;
|
||||
userSelf#720535ec id:int first_name:string last_name:string phone:string photo:UserProfilePhoto status:UserStatus inactive:Bool = User;
|
||||
userContact#f2fb8319 id:int first_name:string last_name:string access_hash:long phone:string photo:UserProfilePhoto status:UserStatus = User;
|
||||
userRequest#22e8ceb0 id:int first_name:string last_name:string access_hash:long phone:string photo:UserProfilePhoto status:UserStatus = User;
|
||||
userForeign#5214c89d id:int first_name:string last_name:string access_hash:long photo:UserProfilePhoto status:UserStatus = User;
|
||||
userDeleted#b29ad7cc id:int first_name:string last_name:string = User;
|
||||
|
||||
userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
|
||||
userProfilePhoto#d559d8c8 photo_id:long photo_small:FileLocation photo_big:FileLocation = UserProfilePhoto;
|
||||
|
||||
userStatusEmpty#9d05049 = UserStatus;
|
||||
userStatusOnline#edb93949 expires:int = UserStatus;
|
||||
userStatusOffline#8c703f was_online:int = UserStatus;
|
||||
|
||||
chatEmpty#9ba2d800 id:int = Chat;
|
||||
chat#6e9c9bc7 id:int title:string photo:ChatPhoto participants_count:int date:int left:Bool version:int = Chat;
|
||||
chatForbidden#fb0ccc41 id:int title:string date:int = Chat;
|
||||
|
||||
chatFull#630e61be id:int participants:ChatParticipants chat_photo:Photo notify_settings:PeerNotifySettings = ChatFull;
|
||||
|
||||
chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
|
||||
|
||||
chatParticipantsForbidden#fd2bb8a chat_id:int = ChatParticipants;
|
||||
chatParticipants#7841b415 chat_id:int admin_id:int participants:Vector<ChatParticipant> version:int = ChatParticipants;
|
||||
|
||||
chatPhotoEmpty#37c1011c = ChatPhoto;
|
||||
chatPhoto#6153276a photo_small:FileLocation photo_big:FileLocation = ChatPhoto;
|
||||
|
||||
messageEmpty#83e5de54 id:int = Message;
|
||||
//message#22eb6aba id:int from_id:int to_id:Peer out:Bool unread:Bool date:int message:string media:MessageMedia = Message;
|
||||
//messageForwarded#5f46804 id:int fwd_from_id:int fwd_date:int from_id:int to_id:Peer out:Bool unread:Bool date:int message:string media:MessageMedia = Message;
|
||||
//messageService#9f8d60bb id:int from_id:int to_id:Peer out:Bool unread:Bool date:int action:MessageAction = Message;
|
||||
|
||||
messageMediaEmpty#3ded6320 = MessageMedia;
|
||||
messageMediaPhoto#c8c45a2a photo:Photo = MessageMedia;
|
||||
messageMediaVideo#a2d24290 video:Video = MessageMedia;
|
||||
messageMediaGeo#56e0d474 geo:GeoPoint = MessageMedia;
|
||||
messageMediaContact#5e7d2f39 phone_number:string first_name:string last_name:string user_id:int = MessageMedia;
|
||||
messageMediaUnsupported#29632a36 bytes:bytes = MessageMedia;
|
||||
|
||||
messageActionEmpty#b6aef7b0 = MessageAction;
|
||||
messageActionChatCreate#a6638b9a title:string users:Vector<int> = MessageAction;
|
||||
messageActionChatEditTitle#b5a1ce5a title:string = MessageAction;
|
||||
messageActionChatEditPhoto#7fcb13a8 photo:Photo = MessageAction;
|
||||
messageActionChatDeletePhoto#95e3fbef = MessageAction;
|
||||
messageActionChatAddUser#5e3cfc4b user_id:int = MessageAction;
|
||||
messageActionChatDeleteUser#b2ae9b0c user_id:int = MessageAction;
|
||||
|
||||
dialog#ab3a99ac peer:Peer top_message:int unread_count:int notify_settings:PeerNotifySettings = Dialog;
|
||||
|
||||
photoEmpty#2331b22d id:long = Photo;
|
||||
photo#22b56751 id:long access_hash:long user_id:int date:int caption:string geo:GeoPoint sizes:Vector<PhotoSize> = Photo;
|
||||
|
||||
photoSizeEmpty#e17e23c type:string = PhotoSize;
|
||||
photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize;
|
||||
photoCachedSize#e9a734fa type:string location:FileLocation w:int h:int bytes:bytes = PhotoSize;
|
||||
|
||||
videoEmpty#c10658a8 id:long = Video;
|
||||
video#388fa391 id:long access_hash:long user_id:int date:int caption:string duration:int mime_type:string size:int thumb:PhotoSize dc_id:int w:int h:int = Video;
|
||||
|
||||
geoPointEmpty#1117dd5f = GeoPoint;
|
||||
geoPoint#2049d70c long:double lat:double = GeoPoint;
|
||||
|
||||
auth.checkedPhone#e300cc3b phone_registered:Bool phone_invited:Bool = auth.CheckedPhone;
|
||||
|
||||
auth.sentCode#efed51d9 phone_registered:Bool phone_code_hash:string send_call_timeout:int is_password:Bool = auth.SentCode;
|
||||
|
||||
auth.authorization#f6b673a4 expires:int user:User = auth.Authorization;
|
||||
|
||||
auth.exportedAuthorization#df969c2d id:int bytes:bytes = auth.ExportedAuthorization;
|
||||
|
||||
inputNotifyPeer#b8bc5b0c peer:InputPeer = InputNotifyPeer;
|
||||
inputNotifyUsers#193b4417 = InputNotifyPeer;
|
||||
inputNotifyChats#4a95e84e = InputNotifyPeer;
|
||||
inputNotifyAll#a429b886 = InputNotifyPeer;
|
||||
|
||||
inputPeerNotifyEventsEmpty#f03064d8 = InputPeerNotifyEvents;
|
||||
inputPeerNotifyEventsAll#e86a2c74 = InputPeerNotifyEvents;
|
||||
|
||||
inputPeerNotifySettings#46a2ce98 mute_until:int sound:string show_previews:Bool events_mask:int = InputPeerNotifySettings;
|
||||
|
||||
peerNotifyEventsEmpty#add53cb3 = PeerNotifyEvents;
|
||||
peerNotifyEventsAll#6d1ded88 = PeerNotifyEvents;
|
||||
|
||||
peerNotifySettingsEmpty#70a68512 = PeerNotifySettings;
|
||||
peerNotifySettings#8d5e11ee mute_until:int sound:string show_previews:Bool events_mask:int = PeerNotifySettings;
|
||||
|
||||
wallPaper#ccb03657 id:int title:string sizes:Vector<PhotoSize> color:int = WallPaper;
|
||||
|
||||
userFull#771095da user:User link:contacts.Link profile_photo:Photo notify_settings:PeerNotifySettings blocked:Bool real_first_name:string real_last_name:string = UserFull;
|
||||
|
||||
contact#f911c994 user_id:int mutual:Bool = Contact;
|
||||
|
||||
importedContact#d0028438 user_id:int client_id:long = ImportedContact;
|
||||
|
||||
contactBlocked#561bc879 user_id:int date:int = ContactBlocked;
|
||||
|
||||
contactFound#ea879f95 user_id:int = ContactFound;
|
||||
|
||||
contactSuggested#3de191a1 user_id:int mutual_contacts:int = ContactSuggested;
|
||||
|
||||
contactStatus#aa77b873 user_id:int expires:int = ContactStatus;
|
||||
|
||||
chatLocated#3631cf4c chat_id:int distance:int = ChatLocated;
|
||||
|
||||
contacts.foreignLinkUnknown#133421f8 = contacts.ForeignLink;
|
||||
contacts.foreignLinkRequested#a7801f47 has_phone:Bool = contacts.ForeignLink;
|
||||
contacts.foreignLinkMutual#1bea8ce1 = contacts.ForeignLink;
|
||||
|
||||
contacts.myLinkEmpty#d22a1c60 = contacts.MyLink;
|
||||
contacts.myLinkRequested#6c69efee contact:Bool = contacts.MyLink;
|
||||
contacts.myLinkContact#c240ebd9 = contacts.MyLink;
|
||||
|
||||
contacts.link#eccea3f5 my_link:contacts.MyLink foreign_link:contacts.ForeignLink user:User = contacts.Link;
|
||||
|
||||
contacts.contacts#6f8b8cb2 contacts:Vector<Contact> users:Vector<User> = contacts.Contacts;
|
||||
contacts.contactsNotModified#b74ba9d2 = contacts.Contacts;
|
||||
|
||||
contacts.importedContacts#ad524315 imported:Vector<ImportedContact> retry_contacts:Vector<long> users:Vector<User> = contacts.ImportedContacts;
|
||||
|
||||
contacts.blocked#1c138d15 blocked:Vector<ContactBlocked> users:Vector<User> = contacts.Blocked;
|
||||
contacts.blockedSlice#900802a1 count:int blocked:Vector<ContactBlocked> users:Vector<User> = contacts.Blocked;
|
||||
|
||||
contacts.found#566000e results:Vector<ContactFound> users:Vector<User> = contacts.Found;
|
||||
|
||||
contacts.suggested#5649dcc5 results:Vector<ContactSuggested> users:Vector<User> = contacts.Suggested;
|
||||
|
||||
messages.dialogs#15ba6c40 dialogs:Vector<Dialog> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Dialogs;
|
||||
messages.dialogsSlice#71e094f3 count:int dialogs:Vector<Dialog> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Dialogs;
|
||||
|
||||
messages.messages#8c718e87 messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||
messages.messagesSlice#b446ae3 count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||
|
||||
messages.messageEmpty#3f4e0648 = messages.Message;
|
||||
messages.message#ff90c417 message:Message chats:Vector<Chat> users:Vector<User> = messages.Message;
|
||||
|
||||
messages.statedMessages#969478bb messages:Vector<Message> chats:Vector<Chat> users:Vector<User> pts:int seq:int = messages.StatedMessages;
|
||||
|
||||
messages.statedMessage#d07ae726 message:Message chats:Vector<Chat> users:Vector<User> pts:int seq:int = messages.StatedMessage;
|
||||
|
||||
messages.sentMessage#d1f4d35c id:int date:int pts:int seq:int = messages.SentMessage;
|
||||
|
||||
messages.chat#40e9002a chat:Chat users:Vector<User> = messages.Chat;
|
||||
|
||||
messages.chats#8150cbd8 chats:Vector<Chat> users:Vector<User> = messages.Chats;
|
||||
|
||||
messages.chatFull#e5d7d19c full_chat:ChatFull chats:Vector<Chat> users:Vector<User> = messages.ChatFull;
|
||||
|
||||
messages.affectedHistory#b7de36f2 pts:int seq:int offset:int = messages.AffectedHistory;
|
||||
|
||||
inputMessagesFilterEmpty#57e2f66c = MessagesFilter;
|
||||
inputMessagesFilterPhotos#9609a51c = MessagesFilter;
|
||||
inputMessagesFilterVideo#9fc00e65 = MessagesFilter;
|
||||
inputMessagesFilterPhotoVideo#56e9f0e4 = MessagesFilter;
|
||||
inputMessagesFilterDocument#9eddf188 = MessagesFilter;
|
||||
inputMessagesFilterAudio#cfc87522 = MessagesFilter;
|
||||
|
||||
updateNewMessage#13abdb3 message:Message pts:int = Update;
|
||||
updateMessageID#4e90bfd6 id:int random_id:long = Update;
|
||||
updateReadMessages#c6649e31 messages:Vector<int> pts:int = Update;
|
||||
updateDeleteMessages#a92bfe26 messages:Vector<int> pts:int = Update;
|
||||
updateRestoreMessages#d15de04d messages:Vector<int> pts:int = Update;
|
||||
//updateUserTyping#6baa8508 user_id:int = Update;
|
||||
//updateChatUserTyping#3c46cfe6 chat_id:int user_id:int = Update;
|
||||
updateChatParticipants#7761198 participants:ChatParticipants = Update;
|
||||
updateUserStatus#1bfbd823 user_id:int status:UserStatus = Update;
|
||||
updateUserName#da22d9ad user_id:int first_name:string last_name:string = Update;
|
||||
updateUserPhoto#95313b0c user_id:int date:int photo:UserProfilePhoto previous:Bool = Update;
|
||||
updateContactRegistered#2575bbb9 user_id:int date:int = Update;
|
||||
updateContactLink#51a48a9a user_id:int my_link:contacts.MyLink foreign_link:contacts.ForeignLink = Update;
|
||||
updateActivation#6f690963 user_id:int = Update;
|
||||
updateNewAuthorization#8f06529a auth_key_id:long date:int device:string location:string = Update;
|
||||
|
||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||
|
||||
updates.differenceEmpty#5d75a138 date:int seq:int = updates.Difference;
|
||||
updates.difference#f49ca0 new_messages:Vector<Message> new_encrypted_messages:Vector<EncryptedMessage> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> state:updates.State = updates.Difference;
|
||||
updates.differenceSlice#a8fb1981 new_messages:Vector<Message> new_encrypted_messages:Vector<EncryptedMessage> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> intermediate_state:updates.State = updates.Difference;
|
||||
|
||||
updatesTooLong#e317af7e = Updates;
|
||||
updateShortMessage#d3f45784 id:int from_id:int message:string pts:int date:int seq:int = Updates;
|
||||
updateShortChatMessage#2b2fbd4e id:int from_id:int chat_id:int message:string pts:int date:int seq:int = Updates;
|
||||
updateShort#78d4dec1 update:Update date:int = Updates;
|
||||
updatesCombined#725b04c3 updates:Vector<Update> users:Vector<User> chats:Vector<Chat> date:int seq_start:int seq:int = Updates;
|
||||
updates#74ae4240 updates:Vector<Update> users:Vector<User> chats:Vector<Chat> date:int seq:int = Updates;
|
||||
|
||||
photos.photos#8dca6aa5 photos:Vector<Photo> users:Vector<User> = photos.Photos;
|
||||
photos.photosSlice#15051f54 count:int photos:Vector<Photo> users:Vector<User> = photos.Photos;
|
||||
|
||||
photos.photo#20212ca8 photo:Photo users:Vector<User> = photos.Photo;
|
||||
|
||||
upload.file#96a18d5 type:storage.FileType mtime:int bytes:bytes = upload.File;
|
||||
|
||||
dcOption#2ec2a43c id:int hostname:string ip_address:string port:int = DcOption;
|
||||
|
||||
config#2e54dd74 date:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> chat_size_max:int broadcast_size_max:int = Config;
|
||||
|
||||
nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc;
|
||||
|
||||
help.appUpdate#8987f311 id:int critical:Bool url:string text:string = help.AppUpdate;
|
||||
help.noAppUpdate#c45a6536 = help.AppUpdate;
|
||||
|
||||
help.inviteText#18cb9f78 message:string = help.InviteText;
|
||||
|
||||
messages.statedMessagesLinks#3e74f5c6 messages:Vector<Message> chats:Vector<Chat> users:Vector<User> links:Vector<contacts.Link> pts:int seq:int = messages.StatedMessages;
|
||||
|
||||
messages.statedMessageLink#a9af2881 message:Message chats:Vector<Chat> users:Vector<User> links:Vector<contacts.Link> pts:int seq:int = messages.StatedMessage;
|
||||
|
||||
messages.sentMessageLink#e9db4a3f id:int date:int pts:int seq:int links:Vector<contacts.Link> = messages.SentMessage;
|
||||
|
||||
inputGeoChat#74d456fa chat_id:int access_hash:long = InputGeoChat;
|
||||
|
||||
inputNotifyGeoChatPeer#4d8ddec8 peer:InputGeoChat = InputNotifyPeer;
|
||||
|
||||
geoChat#75eaea5a id:int access_hash:long title:string address:string venue:string geo:GeoPoint photo:ChatPhoto participants_count:int date:int checked_in:Bool version:int = Chat;
|
||||
|
||||
geoChatMessageEmpty#60311a9b chat_id:int id:int = GeoChatMessage;
|
||||
geoChatMessage#4505f8e1 chat_id:int id:int from_id:int date:int message:string media:MessageMedia = GeoChatMessage;
|
||||
geoChatMessageService#d34fa24e chat_id:int id:int from_id:int date:int action:MessageAction = GeoChatMessage;
|
||||
|
||||
geochats.statedMessage#17b1578b message:GeoChatMessage chats:Vector<Chat> users:Vector<User> seq:int = geochats.StatedMessage;
|
||||
|
||||
geochats.located#48feb267 results:Vector<ChatLocated> messages:Vector<GeoChatMessage> chats:Vector<Chat> users:Vector<User> = geochats.Located;
|
||||
|
||||
geochats.messages#d1526db1 messages:Vector<GeoChatMessage> chats:Vector<Chat> users:Vector<User> = geochats.Messages;
|
||||
geochats.messagesSlice#bc5863e8 count:int messages:Vector<GeoChatMessage> chats:Vector<Chat> users:Vector<User> = geochats.Messages;
|
||||
|
||||
messageActionGeoChatCreate#6f038ebc title:string address:string = MessageAction;
|
||||
messageActionGeoChatCheckin#c7d53de = MessageAction;
|
||||
|
||||
updateNewGeoChatMessage#5a68e3f7 message:GeoChatMessage = Update;
|
||||
|
||||
wallPaperSolid#63117f24 id:int title:string bg_color:int color:int = WallPaper;
|
||||
|
||||
updateNewEncryptedMessage#12bcbd9a message:EncryptedMessage qts:int = Update;
|
||||
updateEncryptedChatTyping#1710f156 chat_id:int = Update;
|
||||
updateEncryption#b4a2e88d chat:EncryptedChat date:int = Update;
|
||||
updateEncryptedMessagesRead#38fe25b7 chat_id:int max_date:int date:int = Update;
|
||||
|
||||
encryptedChatEmpty#ab7ec0a0 id:int = EncryptedChat;
|
||||
encryptedChatWaiting#3bf703dc id:int access_hash:long date:int admin_id:int participant_id:int = EncryptedChat;
|
||||
encryptedChatRequested#c878527e id:int access_hash:long date:int admin_id:int participant_id:int g_a:bytes = EncryptedChat;
|
||||
encryptedChat#fa56ce36 id:int access_hash:long date:int admin_id:int participant_id:int g_a_or_b:bytes key_fingerprint:long = EncryptedChat;
|
||||
encryptedChatDiscarded#13d6dd27 id:int = EncryptedChat;
|
||||
|
||||
inputEncryptedChat#f141b5e1 chat_id:int access_hash:long = InputEncryptedChat;
|
||||
|
||||
encryptedFileEmpty#c21f497e = EncryptedFile;
|
||||
encryptedFile#4a70994c id:long access_hash:long size:int dc_id:int key_fingerprint:int = EncryptedFile;
|
||||
|
||||
inputEncryptedFileEmpty#1837c364 = InputEncryptedFile;
|
||||
inputEncryptedFileUploaded#64bd0306 id:long parts:int md5_checksum:string key_fingerprint:int = InputEncryptedFile;
|
||||
inputEncryptedFile#5a17b5e5 id:long access_hash:long = InputEncryptedFile;
|
||||
|
||||
inputEncryptedFileLocation#f5235d55 id:long access_hash:long = InputFileLocation;
|
||||
|
||||
encryptedMessage#ed18c118 random_id:long chat_id:int date:int bytes:bytes file:EncryptedFile = EncryptedMessage;
|
||||
encryptedMessageService#23734b06 random_id:long chat_id:int date:int bytes:bytes = EncryptedMessage;
|
||||
|
||||
messages.dhConfigNotModified#c0e24635 random:bytes = messages.DhConfig;
|
||||
messages.dhConfig#2c221edd g:int p:bytes version:int random:bytes = messages.DhConfig;
|
||||
|
||||
messages.sentEncryptedMessage#560f8935 date:int = messages.SentEncryptedMessage;
|
||||
messages.sentEncryptedFile#9493ff32 date:int file:EncryptedFile = messages.SentEncryptedMessage;
|
||||
|
||||
inputFileBig#fa4f0bb5 id:long parts:int name:string = InputFile;
|
||||
|
||||
inputEncryptedFileBigUploaded#2dc173c8 id:long parts:int key_fingerprint:int = InputEncryptedFile;
|
||||
|
||||
updateChatParticipantAdd#3a0eeb22 chat_id:int user_id:int inviter_id:int version:int = Update;
|
||||
updateChatParticipantDelete#6e5f8c22 chat_id:int user_id:int version:int = Update;
|
||||
updateDcOptions#8e5e9873 dc_options:Vector<DcOption> = Update;
|
||||
|
||||
inputMediaUploadedAudio#4e498cab file:InputFile duration:int mime_type:string = InputMedia;
|
||||
inputMediaAudio#89938781 id:InputAudio = InputMedia;
|
||||
inputMediaUploadedDocument#34e794bd file:InputFile file_name:string mime_type:string = InputMedia;
|
||||
inputMediaUploadedThumbDocument#3e46de5d file:InputFile thumb:InputFile file_name:string mime_type:string = InputMedia;
|
||||
inputMediaDocument#d184e841 id:InputDocument = InputMedia;
|
||||
|
||||
messageMediaDocument#2fda2204 document:Document = MessageMedia;
|
||||
messageMediaAudio#c6b68300 audio:Audio = MessageMedia;
|
||||
|
||||
inputAudioEmpty#d95adc84 = InputAudio;
|
||||
inputAudio#77d440ff id:long access_hash:long = InputAudio;
|
||||
|
||||
inputDocumentEmpty#72f0eaae = InputDocument;
|
||||
inputDocument#18798952 id:long access_hash:long = InputDocument;
|
||||
|
||||
inputAudioFileLocation#74dc404d id:long access_hash:long = InputFileLocation;
|
||||
inputDocumentFileLocation#4e45abe9 id:long access_hash:long = InputFileLocation;
|
||||
|
||||
audioEmpty#586988d8 id:long = Audio;
|
||||
audio#c7ac6496 id:long access_hash:long user_id:int date:int duration:int mime_type:string size:int dc_id:int = Audio;
|
||||
|
||||
documentEmpty#36f8c871 id:long = Document;
|
||||
document#9efc6326 id:long access_hash:long user_id:int date:int file_name:string mime_type:string size:int thumb:PhotoSize dc_id:int = Document;
|
||||
|
||||
help.support#17c6b5f6 phone_number:string user:User = help.Support;
|
||||
|
||||
notifyPeer#9fd40bd8 peer:Peer = NotifyPeer;
|
||||
notifyUsers#b4c83b4c = NotifyPeer;
|
||||
notifyChats#c007cec3 = NotifyPeer;
|
||||
notifyAll#74d07c60 = NotifyPeer;
|
||||
|
||||
updateUserBlocked#80ece81a user_id:int blocked:Bool = Update;
|
||||
updateNotifySettings#bec268ef peer:NotifyPeer notify_settings:PeerNotifySettings = Update;
|
||||
|
||||
auth.sentAppCode#e325edcf phone_registered:Bool phone_code_hash:string send_call_timeout:int is_password:Bool = auth.SentCode;
|
||||
|
||||
updateUserTyping#5c486927 user_id:int action:SendMessageAction = Update;
|
||||
updateChatUserTyping#9a65ea1f chat_id:int user_id:int action:SendMessageAction = Update;
|
||||
|
||||
|
||||
message#567699b3 flags:int id:int from_id:int to_id:Peer date:int message:string media:MessageMedia = Message;
|
||||
messageForwarded#a367e716 flags:int id:int fwd_from_id:int fwd_date:int from_id:int to_id:Peer date:int message:string media:MessageMedia = Message;
|
||||
messageService#1d86f70e flags:int id:int from_id:int to_id:Peer date:int action:MessageAction = Message;
|
||||
|
||||
|
||||
sendMessageTypingAction#16bf744e = SendMessageAction;
|
||||
sendMessageCancelAction#fd5ec8f5 = SendMessageAction;
|
||||
sendMessageRecordVideoAction#a187d66f = SendMessageAction;
|
||||
sendMessageUploadVideoAction#92042ff7 = SendMessageAction;
|
||||
sendMessageRecordAudioAction#d52f73f7 = SendMessageAction;
|
||||
sendMessageUploadAudioAction#e6ac8a6f = SendMessageAction;
|
||||
sendMessageUploadPhotoAction#990a3c1a = SendMessageAction;
|
||||
sendMessageUploadDocumentAction#8faee98e = SendMessageAction;
|
||||
sendMessageGeoLocationAction#176f8ba1 = SendMessageAction;
|
||||
sendMessageChooseContactAction#628cbc6f = SendMessageAction;
|
||||
|
||||
---functions---
|
||||
|
||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||
|
||||
invokeAfterMsgs#3dc4b4f0 {X:Type} msg_ids:Vector<long> query:!X = X;
|
||||
|
||||
auth.checkPhone#6fe51dfb phone_number:string = auth.CheckedPhone;
|
||||
auth.sendCode#768d5f4d phone_number:string sms_type:int api_id:int api_hash:string lang_code:string = auth.SentCode;
|
||||
auth.sendCall#3c51564 phone_number:string phone_code_hash:string = Bool;
|
||||
auth.signUp#1b067634 phone_number:string phone_code_hash:string phone_code:string first_name:string last_name:string = auth.Authorization;
|
||||
auth.signIn#bcd51581 phone_number:string phone_code_hash:string phone_code:string = auth.Authorization;
|
||||
auth.logOut#5717da40 = Bool;
|
||||
auth.resetAuthorizations#9fab0d1a = Bool;
|
||||
auth.sendInvites#771c1d97 phone_numbers:Vector<string> message:string = Bool;
|
||||
auth.exportAuthorization#e5bfffcd dc_id:int = auth.ExportedAuthorization;
|
||||
auth.importAuthorization#e3ef9613 id:int bytes:bytes = auth.Authorization;
|
||||
auth.bindTempAuthKey#cdd42a05 perm_auth_key_id:long nonce:long expires_at:int encrypted_message:bytes = Bool;
|
||||
|
||||
account.registerDevice#446c712c token_type:int token:string device_model:string system_version:string app_version:string app_sandbox:Bool lang_code:string = Bool;
|
||||
account.unregisterDevice#65c55b40 token_type:int token:string = Bool;
|
||||
account.updateNotifySettings#84be5b93 peer:InputNotifyPeer settings:InputPeerNotifySettings = Bool;
|
||||
account.getNotifySettings#12b3ad31 peer:InputNotifyPeer = PeerNotifySettings;
|
||||
account.resetNotifySettings#db7e1747 = Bool;
|
||||
account.updateProfile#f0888d68 first_name:string last_name:string = User;
|
||||
account.updateStatus#6628562c offline:Bool = Bool;
|
||||
account.getWallPapers#c04cfac2 = Vector<WallPaper>;
|
||||
|
||||
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
|
||||
users.getFullUser#ca30a5b1 id:InputUser = UserFull;
|
||||
|
||||
contacts.getStatuses#c4a353ee = Vector<ContactStatus>;
|
||||
contacts.getContacts#22c6aa08 hash:string = contacts.Contacts;
|
||||
contacts.importContacts#da30b32d contacts:Vector<InputContact> replace:Bool = contacts.ImportedContacts;
|
||||
contacts.search#11f812d8 q:string limit:int = contacts.Found;
|
||||
contacts.getSuggested#cd773428 limit:int = contacts.Suggested;
|
||||
contacts.deleteContact#8e953744 id:InputUser = contacts.Link;
|
||||
contacts.deleteContacts#59ab389e id:Vector<InputUser> = Bool;
|
||||
contacts.block#332b49fc id:InputUser = Bool;
|
||||
contacts.unblock#e54100bd id:InputUser = Bool;
|
||||
contacts.getBlocked#f57c350f offset:int limit:int = contacts.Blocked;
|
||||
contacts.exportCard#84e53737 = Vector<int>;
|
||||
contacts.importCard#4fe196fe export_card:Vector<int> = User;
|
||||
|
||||
messages.getMessages#4222fa74 id:Vector<int> = messages.Messages;
|
||||
messages.getDialogs#eccf1df6 offset:int max_id:int limit:int = messages.Dialogs;
|
||||
messages.getHistory#92a1df2f peer:InputPeer offset:int max_id:int limit:int = messages.Messages;
|
||||
messages.search#7e9f2ab peer:InputPeer q:string filter:MessagesFilter min_date:int max_date:int offset:int max_id:int limit:int = messages.Messages;
|
||||
messages.readHistory#eed884c6 peer:InputPeer max_id:int offset:int read_contents:Bool = messages.AffectedHistory;
|
||||
messages.deleteHistory#f4f8fb61 peer:InputPeer offset:int = messages.AffectedHistory;
|
||||
messages.deleteMessages#14f2dd0a id:Vector<int> = Vector<int>;
|
||||
messages.restoreMessages#395f9d7e id:Vector<int> = Vector<int>;
|
||||
messages.receivedMessages#28abcb68 max_id:int = Vector<int>;
|
||||
messages.setTyping#a3825e50 peer:InputPeer action:SendMessageAction = Bool;
|
||||
messages.sendMessage#4cde0aab peer:InputPeer message:string random_id:long = messages.SentMessage;
|
||||
messages.sendMedia#a3c85d76 peer:InputPeer media:InputMedia random_id:long = messages.StatedMessage;
|
||||
messages.forwardMessages#514cd10f peer:InputPeer id:Vector<int> = messages.StatedMessages;
|
||||
messages.getChats#3c6aa187 id:Vector<int> = messages.Chats;
|
||||
messages.getFullChat#3b831c66 chat_id:int = messages.ChatFull;
|
||||
messages.editChatTitle#b4bc68b5 chat_id:int title:string = messages.StatedMessage;
|
||||
messages.editChatPhoto#d881821d chat_id:int photo:InputChatPhoto = messages.StatedMessage;
|
||||
messages.addChatUser#2ee9ee9e chat_id:int user_id:InputUser fwd_limit:int = messages.StatedMessage;
|
||||
messages.deleteChatUser#c3c5cd23 chat_id:int user_id:InputUser = messages.StatedMessage;
|
||||
messages.createChat#419d9aee users:Vector<InputUser> title:string = messages.StatedMessage;
|
||||
|
||||
updates.getState#edd4882a = updates.State;
|
||||
updates.getDifference#a041495 pts:int date:int qts:int = updates.Difference;
|
||||
|
||||
photos.updateProfilePhoto#eef579a0 id:InputPhoto crop:InputPhotoCrop = UserProfilePhoto;
|
||||
photos.uploadProfilePhoto#d50f9c88 file:InputFile caption:string geo_point:InputGeoPoint crop:InputPhotoCrop = photos.Photo;
|
||||
|
||||
upload.saveFilePart#b304a621 file_id:long file_part:int bytes:bytes = Bool;
|
||||
upload.getFile#e3a6cfb5 location:InputFileLocation offset:int limit:int = upload.File;
|
||||
|
||||
help.getConfig#c4f9186b = Config;
|
||||
help.getNearestDc#1fb33026 = NearestDc;
|
||||
help.getAppUpdate#c812ac7e device_model:string system_version:string app_version:string lang_code:string = help.AppUpdate;
|
||||
help.saveAppLog#6f02f748 events:Vector<InputAppEvent> = Bool;
|
||||
help.getInviteText#a4a95186 lang_code:string = help.InviteText;
|
||||
|
||||
photos.getUserPhotos#b7ee553c user_id:InputUser offset:int max_id:int limit:int = photos.Photos;
|
||||
|
||||
messages.forwardMessage#3f3f4f2 peer:InputPeer id:int random_id:long = messages.StatedMessage;
|
||||
messages.sendBroadcast#41bb0972 contacts:Vector<InputUser> message:string media:InputMedia = messages.StatedMessages;
|
||||
|
||||
geochats.getLocated#7f192d8f geo_point:InputGeoPoint radius:int limit:int = geochats.Located;
|
||||
geochats.getRecents#e1427e6f offset:int limit:int = geochats.Messages;
|
||||
geochats.checkin#55b3e8fb peer:InputGeoChat = geochats.StatedMessage;
|
||||
geochats.getFullChat#6722dd6f peer:InputGeoChat = messages.ChatFull;
|
||||
geochats.editChatTitle#4c8e2273 peer:InputGeoChat title:string address:string = geochats.StatedMessage;
|
||||
geochats.editChatPhoto#35d81a95 peer:InputGeoChat photo:InputChatPhoto = geochats.StatedMessage;
|
||||
geochats.search#cfcdc44d peer:InputGeoChat q:string filter:MessagesFilter min_date:int max_date:int offset:int max_id:int limit:int = geochats.Messages;
|
||||
geochats.getHistory#b53f7a68 peer:InputGeoChat offset:int max_id:int limit:int = geochats.Messages;
|
||||
geochats.setTyping#8b8a729 peer:InputGeoChat typing:Bool = Bool;
|
||||
geochats.sendMessage#61b0044 peer:InputGeoChat message:string random_id:long = geochats.StatedMessage;
|
||||
geochats.sendMedia#b8f0deff peer:InputGeoChat media:InputMedia random_id:long = geochats.StatedMessage;
|
||||
geochats.createGeoChat#e092e16 title:string geo_point:InputGeoPoint address:string venue:string = geochats.StatedMessage;
|
||||
|
||||
messages.getDhConfig#26cf8950 version:int random_length:int = messages.DhConfig;
|
||||
messages.requestEncryption#f64daf43 user_id:InputUser random_id:int g_a:bytes = EncryptedChat;
|
||||
messages.acceptEncryption#3dbc0415 peer:InputEncryptedChat g_b:bytes key_fingerprint:long = EncryptedChat;
|
||||
messages.discardEncryption#edd923c5 chat_id:int = Bool;
|
||||
messages.setEncryptedTyping#791451ed peer:InputEncryptedChat typing:Bool = Bool;
|
||||
messages.readEncryptedHistory#7f4b690a peer:InputEncryptedChat max_date:int = Bool;
|
||||
messages.sendEncrypted#a9776773 peer:InputEncryptedChat random_id:long data:bytes = messages.SentEncryptedMessage;
|
||||
messages.sendEncryptedFile#9a901b66 peer:InputEncryptedChat random_id:long data:bytes file:InputEncryptedFile = messages.SentEncryptedMessage;
|
||||
messages.sendEncryptedService#32d439a4 peer:InputEncryptedChat random_id:long data:bytes = messages.SentEncryptedMessage;
|
||||
messages.receivedQueue#55a5bb66 max_qts:int = Vector<long>;
|
||||
|
||||
upload.saveBigFilePart#de7b673d file_id:long file_part:int file_total_parts:int bytes:bytes = Bool;
|
||||
|
||||
initConnection#69796de9 {X:Type} api_id:int device_model:string system_version:string app_version:string lang_code:string query:!X = X;
|
||||
|
||||
help.getSupport#9cdf08cd = help.Support;
|
||||
|
||||
auth.sendSms#da9f3e8 phone_number:string phone_code_hash:string = Bool;
|
||||
|
||||
messages.readMessageContents id:Vector<int> = Vector<int>;
|
||||
|
||||
|
||||
invokeWithLayer17#50858a19 {X:Type} query:!X = X;
|
||||
|
8
server.pub
Normal file
8
server.pub
Normal file
@ -0,0 +1,8 @@
|
||||
-----BEGIN RSA PUBLIC KEY-----
|
||||
MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6
|
||||
lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS
|
||||
an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw
|
||||
Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+
|
||||
8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n
|
||||
Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
||||
-----END RSA PUBLIC KEY-----
|
81
structures.c
81
structures.c
@ -108,6 +108,34 @@ char *tgls_default_create_print_name (tgl_peer_id_t id, const char *a1, const ch
|
||||
return tstrdup (s);
|
||||
}
|
||||
|
||||
enum tgl_typing_status tglf_fetch_typing (void) {
|
||||
switch (fetch_int ()) {
|
||||
case CODE_send_message_typing_action:
|
||||
return tgl_typing_typing;
|
||||
case CODE_send_message_cancel_action:
|
||||
return tgl_typing_cancel;
|
||||
case CODE_send_message_record_video_action:
|
||||
return tgl_typing_record_video;
|
||||
case CODE_send_message_upload_video_action:
|
||||
return tgl_typing_upload_video;
|
||||
case CODE_send_message_record_audio_action:
|
||||
return tgl_typing_record_audio;
|
||||
case CODE_send_message_upload_audio_action:
|
||||
return tgl_typing_upload_audio;
|
||||
case CODE_send_message_upload_photo_action:
|
||||
return tgl_typing_upload_photo;
|
||||
case CODE_send_message_upload_document_action:
|
||||
return tgl_typing_upload_document;
|
||||
case CODE_send_message_geo_location_action:
|
||||
return tgl_typing_geo;
|
||||
case CODE_send_message_choose_contact_action:
|
||||
return tgl_typing_choose_contact;
|
||||
default:
|
||||
assert (0);
|
||||
return tgl_typing_none;
|
||||
}
|
||||
}
|
||||
|
||||
/* {{{ Fetch */
|
||||
|
||||
int tglf_fetch_file_location (struct tgl_file_location *loc) {
|
||||
@ -512,8 +540,8 @@ void tglf_fetch_photo_size (struct tgl_photo_size *S) {
|
||||
void tglf_fetch_geo (struct tgl_geo *G) {
|
||||
unsigned x = fetch_int ();
|
||||
if (x == CODE_geo_point) {
|
||||
G->longitude = fetch_double ();
|
||||
G->latitude = fetch_double ();
|
||||
G->longitude = fetch_double ();
|
||||
} else {
|
||||
assert (x == CODE_geo_point_empty);
|
||||
G->longitude = 0;
|
||||
@ -923,8 +951,8 @@ void tglf_fetch_message_media_encrypted (struct tgl_message_media *M) {
|
||||
*/
|
||||
case CODE_decrypted_message_media_geo_point:
|
||||
M->type = tgl_message_media_geo;
|
||||
M->geo.longitude = fetch_double ();
|
||||
M->geo.latitude = fetch_double ();
|
||||
M->geo.longitude = fetch_double ();
|
||||
break;
|
||||
case CODE_decrypted_message_media_contact:
|
||||
M->type = tgl_message_media_contact;
|
||||
@ -990,6 +1018,10 @@ void tglf_fetch_message_action_encrypted (struct tgl_message_action *M) {
|
||||
case CODE_decrypted_message_action_flush_history:
|
||||
M->type = tgl_message_action_flush_history;
|
||||
break;
|
||||
case CODE_decrypted_message_action_typing:
|
||||
M->type = tgl_message_action_typing;
|
||||
M->typing = tglf_fetch_typing ();
|
||||
break;
|
||||
default:
|
||||
vlogprintf (E_ERROR, "x = 0x%08x\n", x);
|
||||
assert (0);
|
||||
@ -1009,6 +1041,10 @@ tgl_peer_id_t tglf_fetch_peer_id (void) {
|
||||
void tglf_fetch_message (struct tgl_message *M) {
|
||||
unsigned x = fetch_int ();
|
||||
assert (x == CODE_message_empty || x == CODE_message || x == CODE_message_forwarded || x == CODE_message_service);
|
||||
int flags = 0;
|
||||
if (x != CODE_message_empty) {
|
||||
flags = fetch_int ();
|
||||
}
|
||||
int id = fetch_int ();
|
||||
assert (M->id == id);
|
||||
if (x == CODE_message_empty) {
|
||||
@ -1024,11 +1060,12 @@ void tglf_fetch_message (struct tgl_message *M) {
|
||||
int from_id = fetch_int ();
|
||||
tgl_peer_id_t to_id = tglf_fetch_peer_id ();
|
||||
|
||||
fetch_bool (); // out.
|
||||
//fetch_bool (); // out.
|
||||
|
||||
int unread = fetch_bool ();
|
||||
//int unread = fetch_bool ();
|
||||
int date = fetch_int ();
|
||||
|
||||
int unread = (flags & 1) != 0;
|
||||
int new = !(M->flags & FLAG_CREATED);
|
||||
|
||||
if (x == CODE_message_service) {
|
||||
@ -1190,12 +1227,30 @@ void tglf_fetch_encrypted_message (struct tgl_message *M) {
|
||||
assert (layer >= 0);
|
||||
x = fetch_int ();
|
||||
}
|
||||
assert (x == CODE_decrypted_message || x == CODE_decrypted_message_service);
|
||||
assert (x == CODE_decrypted_message || x == CODE_decrypted_message_service || x == CODE_decrypted_message_l16 || x == CODE_decrypted_message_service_l16);
|
||||
//assert (id == fetch_long ());
|
||||
if (x == CODE_decrypted_message || x == CODE_decrypted_message_service) {
|
||||
int out_seq_no = fetch_int ();
|
||||
int in_seq_no = fetch_int ();
|
||||
if (in_seq_no / 2 <= P->encr_chat.in_seq_no) {
|
||||
vlogprintf (E_WARNING, "Hole in seq in secret chat. in_seq_no = %d, expect_seq_no = %d\n", in_seq_no / 2, P->encr_chat.in_seq_no + 1);
|
||||
}
|
||||
if (in_seq_no / 2 > P->encr_chat.in_seq_no + 1) {
|
||||
vlogprintf (E_WARNING, "Hole in seq in secret chat. in_seq_no = %d, expect_seq_no = %d\n", in_seq_no / 2, P->encr_chat.in_seq_no + 1);
|
||||
}
|
||||
//vlogprintf (E_WARNING, "in = %d, out = %d\n", in_seq_no, out_seq_no);
|
||||
assert (out_seq_no / 2 <= P->encr_chat.out_seq_no);
|
||||
P->encr_chat.in_seq_no = in_seq_no / 2;
|
||||
if (x == CODE_decrypted_message) {
|
||||
fetch_int (); // ttl
|
||||
}
|
||||
} else {
|
||||
P->encr_chat.in_seq_no ++;
|
||||
}
|
||||
fetch_long ();
|
||||
ll = prefetch_strlen ();
|
||||
fetch_str (ll); // random_bytes
|
||||
if (x == CODE_decrypted_message) {
|
||||
if (x == CODE_decrypted_message || x == CODE_decrypted_message_l16) {
|
||||
l = prefetch_strlen ();
|
||||
s = fetch_str (l);
|
||||
start = in_ptr;
|
||||
@ -1216,9 +1271,9 @@ void tglf_fetch_encrypted_message (struct tgl_message *M) {
|
||||
if (ok) {
|
||||
int *start_file = in_ptr;
|
||||
assert (skip_type_any (TYPE_TO_PARAM (encrypted_file)) >= 0);
|
||||
if (x == CODE_decrypted_message) {
|
||||
if (x == CODE_decrypted_message || x == CODE_decrypted_message_l16) {
|
||||
bl_do_create_message_media_encr (id, P->encr_chat.user_id, TGL_PEER_ENCR_CHAT, to_id, date, l, s, start, end - start, start_file, in_ptr - start_file);
|
||||
} else if (x == CODE_decrypted_message_service) {
|
||||
} else if (x == CODE_decrypted_message_service || x == CODE_decrypted_message_service_l16) {
|
||||
bl_do_create_message_service_encr (id, P->encr_chat.user_id, TGL_PEER_ENCR_CHAT, to_id, date, start, end - start);
|
||||
}
|
||||
} else {
|
||||
@ -1226,7 +1281,7 @@ void tglf_fetch_encrypted_message (struct tgl_message *M) {
|
||||
M->media.type = CODE_message_media_empty;
|
||||
}
|
||||
} else {
|
||||
if (ok && x == CODE_decrypted_message_service) {
|
||||
if (ok && (x == CODE_decrypted_message_service || x == CODE_decrypted_message_service_l16)) {
|
||||
bl_do_create_message_service_encr (id, P->encr_chat.user_id, TGL_PEER_ENCR_CHAT, to_id, date, start, end - start);
|
||||
}
|
||||
}
|
||||
@ -1310,12 +1365,12 @@ struct tgl_user *tglf_fetch_alloc_user_full (void) {
|
||||
}
|
||||
|
||||
struct tgl_message *tglf_fetch_alloc_message (void) {
|
||||
int data[2];
|
||||
prefetch_data (data, 8);
|
||||
struct tgl_message *M = tgl_message_get (data[1]);
|
||||
int data[3];
|
||||
prefetch_data (data, 12);
|
||||
struct tgl_message *M = tgl_message_get (data[0] != (int)CODE_message_empty ? data[2] : data[1]);
|
||||
|
||||
if (!M) {
|
||||
M = tglm_message_alloc (data[1]);
|
||||
M = tglm_message_alloc (data[0] != (int)CODE_message_empty ? data[2] : data[1]);
|
||||
}
|
||||
tglf_fetch_message (M);
|
||||
return M;
|
||||
|
@ -51,5 +51,6 @@ void tglp_peer_delete_name (tgl_peer_t *P);
|
||||
void tglp_insert_encrypted_chat (tgl_peer_t *P);
|
||||
void tglp_insert_user (tgl_peer_t *P);
|
||||
void tglp_insert_chat (tgl_peer_t *P);
|
||||
enum tgl_typing_status tglf_fetch_typing (void);
|
||||
|
||||
#endif
|
||||
|
20
tgl-layout.h
20
tgl-layout.h
@ -120,7 +120,22 @@ enum tgl_message_action_type {
|
||||
tgl_message_action_delete_messages,
|
||||
tgl_message_action_screenshot_messages,
|
||||
tgl_message_action_flush_history,
|
||||
tgl_message_action_notify_layer
|
||||
tgl_message_action_notify_layer,
|
||||
tgl_message_action_typing
|
||||
};
|
||||
|
||||
enum tgl_typing_status {
|
||||
tgl_typing_none,
|
||||
tgl_typing_typing,
|
||||
tgl_typing_cancel,
|
||||
tgl_typing_record_video,
|
||||
tgl_typing_upload_video,
|
||||
tgl_typing_record_audio,
|
||||
tgl_typing_upload_audio,
|
||||
tgl_typing_upload_photo,
|
||||
tgl_typing_upload_document,
|
||||
tgl_typing_geo,
|
||||
tgl_typing_choose_contact
|
||||
};
|
||||
|
||||
struct tgl_file_location {
|
||||
@ -288,6 +303,8 @@ struct tgl_secret_chat {
|
||||
int date;
|
||||
int ttl;
|
||||
int layer;
|
||||
int in_seq_no;
|
||||
int out_seq_no;
|
||||
long long access_hash;
|
||||
unsigned char *g_key;
|
||||
unsigned char *nonce;
|
||||
@ -367,6 +384,7 @@ struct tgl_message_action {
|
||||
int read_cnt;
|
||||
int delete_cnt;
|
||||
int screenshot_cnt;
|
||||
enum tgl_typing_status typing;
|
||||
};
|
||||
};
|
||||
|
||||
|
25
tgl.h
25
tgl.h
@ -24,16 +24,22 @@
|
||||
#include <string.h>
|
||||
|
||||
#define TGL_MAX_DC_NUM 100
|
||||
#define TG_SERVER "149.154.167.50"
|
||||
#define TG_SERVER_TEST "149.154.167.40"
|
||||
#define TG_SERVER_DC 2
|
||||
#define TG_SERVER_TEST_DC 2
|
||||
#define TG_SERVER_1 "173.240.5.1"
|
||||
#define TG_SERVER_2 "149.154.167.51"
|
||||
#define TG_SERVER_3 "174.140.142.6"
|
||||
#define TG_SERVER_4 "149.154.167.91"
|
||||
#define TG_SERVER_5 "149.154.171.5"
|
||||
|
||||
|
||||
#define TG_SERVER_TEST_1 "173.240.5.253"
|
||||
#define TG_SERVER_TEST_2 "149.154.167.40"
|
||||
#define TG_SERVER_TEST_3 "174.140.142.5"
|
||||
|
||||
// JUST RANDOM STRING
|
||||
#define TGL_BUILD "2014"
|
||||
#define TGL_VERSION "1.0.5"
|
||||
#define TGL_BUILD "2234"
|
||||
#define TGL_VERSION "1.0.6"
|
||||
|
||||
#define TGL_ENCRYPTED_LAYER 16
|
||||
#define TGL_ENCRYPTED_LAYER 17
|
||||
|
||||
struct connection;
|
||||
struct mtproto_methods;
|
||||
@ -70,8 +76,8 @@ struct tgl_update_callback {
|
||||
void (*new_msg)(struct tgl_message *M);
|
||||
void (*marked_read)(int num, struct tgl_message *list[]);
|
||||
void (*logprintf)(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
void (*type_notification)(struct tgl_user *U);
|
||||
void (*type_in_chat_notification)(struct tgl_user *U, struct tgl_chat *C);
|
||||
void (*type_notification)(struct tgl_user *U, enum tgl_typing_status status);
|
||||
void (*type_in_chat_notification)(struct tgl_user *U, struct tgl_chat *C, enum tgl_typing_status status);
|
||||
void (*type_in_secret_chat_notification)(struct tgl_secret_chat *E);
|
||||
void (*status_notification)(struct tgl_user *U);
|
||||
void (*user_registered)(struct tgl_user *U);
|
||||
@ -289,6 +295,7 @@ void tgl_do_send_contact (tgl_peer_id_t id, const char *phone, int phone_len, co
|
||||
void tgl_do_forward_media (tgl_peer_id_t id, int n, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra);
|
||||
void tgl_do_del_contact (tgl_peer_id_t id, void (*callback)(void *callback_extra, int success), void *callback_extra);
|
||||
void tgl_do_set_encr_chat_ttl (struct tgl_secret_chat *E, int ttl, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra);
|
||||
void tgl_do_send_location(tgl_peer_id_t id, double latitude, double longitude, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra);
|
||||
|
||||
|
||||
void tgl_do_visualize_key (tgl_peer_id_t id, unsigned char buf[16]);
|
||||
|
@ -99,24 +99,28 @@ void tglu_work_update (struct connection *c, long long msg_id) {
|
||||
break;
|
||||
case CODE_update_user_typing:
|
||||
{
|
||||
//vlogprintf (E_ERROR, "user typing\n");
|
||||
tgl_peer_id_t id = TGL_MK_USER (fetch_int ());
|
||||
tgl_peer_t *U = tgl_peer_get (id);
|
||||
enum tgl_typing_status status = tglf_fetch_typing ();
|
||||
|
||||
if (tgl_state.callback.type_notification && U) {
|
||||
tgl_state.callback.type_notification ((void *)U);
|
||||
tgl_state.callback.type_notification ((void *)U, status);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CODE_update_chat_user_typing:
|
||||
{
|
||||
//vlogprintf (E_ERROR, "chat typing\n");
|
||||
tgl_peer_id_t chat_id = TGL_MK_CHAT (fetch_int ());
|
||||
tgl_peer_id_t id = TGL_MK_USER (fetch_int ());
|
||||
tgl_peer_t *C = tgl_peer_get (chat_id);
|
||||
tgl_peer_t *U = tgl_peer_get (id);
|
||||
enum tgl_typing_status status = tglf_fetch_typing ();
|
||||
|
||||
if (U && C) {
|
||||
if (tgl_state.callback.type_in_chat_notification) {
|
||||
tgl_state.callback.type_in_chat_notification ((void *)U, (void *)C);
|
||||
tgl_state.callback.type_in_chat_notification ((void *)U, (void *)C, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user