Sometimes updates work
This commit is contained in:
parent
baa56b709c
commit
a8a18a8076
23
interface.c
23
interface.c
@ -198,6 +198,18 @@ void interpreter (char *line UU) {
|
||||
static char stat_buf[1 << 15];
|
||||
print_stat (stat_buf, (1 << 15) - 1);
|
||||
printf ("%s\n", stat_buf);
|
||||
} else if (!memcmp (line, "msg ", 4)) {
|
||||
char *q = line + 4;
|
||||
int len;
|
||||
char *text = get_token (&q, &len);
|
||||
int index = 0;
|
||||
while (index < user_num + chat_num && (!Peers[index]->print_name || strncmp (Peers[index]->print_name, text, len) || Peers[index]->id < 0)) {
|
||||
index ++;
|
||||
}
|
||||
while (*q && (*q == ' ' || *q == '\t')) { q ++; }
|
||||
if (*q && index < user_num + chat_num) {
|
||||
do_send_message (Peers[index], q);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,3 +288,14 @@ void logprintf (const char *format, ...) {
|
||||
free(saved_line);
|
||||
}
|
||||
}
|
||||
|
||||
void print_message (struct message *M) {
|
||||
union user_chat *U = user_chat_get (M->from_id);
|
||||
if (!M->service) {
|
||||
if (U && U->id > 0) {
|
||||
rprintf (COLOR_RED "%s %s " COLOR_GREEN " >>> " COLOR_NORMAL " %s\n", U->user.first_name, U->user.last_name, M->message);
|
||||
} else {
|
||||
rprintf (COLOR_RED "User #%d " COLOR_GREEN " >>> " COLOR_NORMAL " %s\n", M->from_id, M->message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#define COLOR_NORMAL "\033[0m"
|
||||
#define COLOR_GREEN "\033[32;1m"
|
||||
#define COLOR_GREY "\033[37;1m"
|
||||
#define COLOR_YELLOW "\033[33;1m"
|
||||
|
||||
|
||||
char *get_default_prompt (void);
|
||||
@ -16,4 +17,7 @@ void rprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
void iprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
void logprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
void hexdump (int *in_ptr, int *in_end);
|
||||
|
||||
struct message;
|
||||
void print_message (struct message *M);
|
||||
#endif
|
||||
|
191
mtproto-client.c
191
mtproto-client.c
@ -23,6 +23,7 @@
|
||||
#include "queries.h"
|
||||
#include "loop.h"
|
||||
#include "interface.h"
|
||||
#include "structures.h"
|
||||
|
||||
#define sha1 SHA1
|
||||
|
||||
@ -611,6 +612,181 @@ int auth_work_start (struct connection *c UU) {
|
||||
}
|
||||
|
||||
void rpc_execute_answer (struct connection *c, long long msg_id UU);
|
||||
|
||||
void work_update (struct connection *c UU, long long msg_id UU) {
|
||||
unsigned op = fetch_int ();
|
||||
switch (op) {
|
||||
case CODE_update_new_message:
|
||||
{
|
||||
struct message *M = fetch_alloc_message ();
|
||||
print_message (M);
|
||||
break;
|
||||
};
|
||||
case CODE_update_message_i_d:
|
||||
{
|
||||
int id = fetch_int (); // id
|
||||
int new = fetch_long (); // random_id
|
||||
struct message *M = message_get (new);
|
||||
update_message_id (M, id);
|
||||
}
|
||||
break;
|
||||
case CODE_update_read_messages:
|
||||
{
|
||||
assert (fetch_int () == (int)CODE_vector);
|
||||
int n = fetch_int ();
|
||||
int i;
|
||||
for (i = 0; i < n; i++) {
|
||||
int id = fetch_int ();
|
||||
struct message *M = message_get (id);
|
||||
if (M) {
|
||||
M->unread = 0;
|
||||
}
|
||||
}
|
||||
fetch_int (); //pts
|
||||
}
|
||||
break;
|
||||
case CODE_update_user_typing:
|
||||
{
|
||||
int id = fetch_int ();
|
||||
union user_chat *U = user_chat_get (id);
|
||||
if (U) {
|
||||
rprintf (COLOR_YELLOW "User " COLOR_RED "%s %s" COLOR_YELLOW " is typing....\n" COLOR_NORMAL, U->user.first_name, U->user.last_name);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CODE_update_chat_user_typing:
|
||||
{
|
||||
int chat_id = fetch_int ();
|
||||
int id = fetch_int ();
|
||||
union user_chat *C = user_chat_get (-chat_id);
|
||||
union user_chat *U = user_chat_get (id);
|
||||
if (U && C) {
|
||||
rprintf (COLOR_YELLOW "User " COLOR_RED "%s %s" COLOR_YELLOW " is typing in chat %s....\n" COLOR_NORMAL, U->user.first_name, U->user.last_name, C->chat.title);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CODE_update_user_status:
|
||||
{
|
||||
int user_id = fetch_int ();
|
||||
union user_chat *U = user_chat_get (user_id);
|
||||
if (U) {
|
||||
fetch_user_status (&U->user.status);
|
||||
rprintf (COLOR_YELLOW "User " COLOR_RED "%s %s" COLOR_YELLOW " is now %s\n" COLOR_NORMAL, U->user.first_name, U->user.last_name, (U->user.status.online > 0) ? "online" : "offline");
|
||||
} else {
|
||||
struct user_status t;
|
||||
fetch_user_status (&t);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CODE_update_user_name:
|
||||
{
|
||||
int user_id = fetch_int ();
|
||||
union user_chat *UC = user_chat_get (user_id);
|
||||
if (UC) {
|
||||
struct user *U = &UC->user;
|
||||
if (U->first_name) { free (U->first_name); }
|
||||
if (U->last_name) { free (U->first_name); }
|
||||
if (U->print_name) { free (U->first_name); }
|
||||
U->first_name = fetch_str_dup ();
|
||||
U->last_name = fetch_str_dup ();
|
||||
if (!strlen (U->first_name)) {
|
||||
if (!strlen (U->last_name)) {
|
||||
U->print_name = strdup ("none");
|
||||
} else {
|
||||
U->print_name = strdup (U->last_name);
|
||||
}
|
||||
} else {
|
||||
if (!strlen (U->last_name)) {
|
||||
U->print_name = strdup (U->first_name);
|
||||
} else {
|
||||
U->print_name = malloc (strlen (U->first_name) + strlen (U->last_name) + 2);
|
||||
sprintf (U->print_name, "%s_%s", U->first_name, U->last_name);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int l;
|
||||
l = prefetch_strlen ();
|
||||
fetch_str (l);
|
||||
l = prefetch_strlen ();
|
||||
fetch_str (l);
|
||||
l = prefetch_strlen ();
|
||||
fetch_str (l);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CODE_update_user_photo:
|
||||
{
|
||||
int user_id = fetch_int ();
|
||||
union user_chat *UC = user_chat_get (user_id);
|
||||
if (UC) {
|
||||
struct user *U = &UC->user;
|
||||
unsigned y = fetch_int ();
|
||||
if (y == CODE_user_profile_photo_empty) {
|
||||
U->photo_big.dc = -2;
|
||||
U->photo_small.dc = -2;
|
||||
} else {
|
||||
assert (y == CODE_user_profile_photo);
|
||||
fetch_file_location (&U->photo_small);
|
||||
fetch_file_location (&U->photo_big);
|
||||
}
|
||||
} else {
|
||||
struct file_location t;
|
||||
unsigned y = fetch_int ();
|
||||
if (y == CODE_user_profile_photo_empty) {
|
||||
} else {
|
||||
assert (y == CODE_user_profile_photo);
|
||||
fetch_file_location (&t);
|
||||
fetch_file_location (&t);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
logprintf ("Unknown update type %08x\n", op);
|
||||
}
|
||||
}
|
||||
|
||||
void work_update_short (struct connection *c, long long msg_id) {
|
||||
assert (fetch_int () == CODE_update_short);
|
||||
work_update (c, msg_id);
|
||||
fetch_int (); // date
|
||||
}
|
||||
|
||||
void work_updates (struct connection *c, long long msg_id) {
|
||||
assert (fetch_int () == CODE_updates);
|
||||
assert (fetch_int () == CODE_vector);
|
||||
int n = fetch_int ();
|
||||
int i;
|
||||
for (i = 0; i < n; i++) {
|
||||
work_update (c, msg_id);
|
||||
}
|
||||
assert (fetch_int () == CODE_vector);
|
||||
n = fetch_int ();
|
||||
for (i = 0; i < n; i++) {
|
||||
fetch_alloc_user ();
|
||||
}
|
||||
assert (fetch_int () == CODE_vector);
|
||||
n = fetch_int ();
|
||||
for (i = 0; i < n; i++) {
|
||||
fetch_alloc_chat ();
|
||||
}
|
||||
fetch_int (); // date
|
||||
fetch_int (); // seq
|
||||
|
||||
}
|
||||
|
||||
void work_update_short_message (struct connection *c UU, long long msg_id UU) {
|
||||
assert (fetch_int () == (int)CODE_update_short_message);
|
||||
struct message *M = fetch_alloc_message_short ();
|
||||
print_message (M);
|
||||
}
|
||||
|
||||
void work_update_short_chat_message (struct connection *c UU, long long msg_id UU) {
|
||||
assert (fetch_int () == CODE_update_short_chat_message);
|
||||
struct message *M = fetch_alloc_message_short_chat ();
|
||||
print_message (M);
|
||||
}
|
||||
|
||||
void work_container (struct connection *c, long long msg_id UU) {
|
||||
if (verbosity) {
|
||||
logprintf ( "work_container: msg_id = %lld\n", msg_id);
|
||||
@ -671,6 +847,9 @@ void work_rpc_result (struct connection *c UU, long long msg_id UU) {
|
||||
}
|
||||
|
||||
void rpc_execute_answer (struct connection *c, long long msg_id UU) {
|
||||
if (verbosity >= 5) {
|
||||
hexdump_in ();
|
||||
}
|
||||
int op = prefetch_int ();
|
||||
switch (op) {
|
||||
case CODE_msg_container:
|
||||
@ -685,6 +864,18 @@ void rpc_execute_answer (struct connection *c, long long msg_id UU) {
|
||||
case CODE_rpc_result:
|
||||
work_rpc_result (c, msg_id);
|
||||
return;
|
||||
case CODE_update_short:
|
||||
work_update_short (c, msg_id);
|
||||
return;
|
||||
case CODE_updates:
|
||||
work_updates (c, msg_id);
|
||||
return;
|
||||
case CODE_update_short_message:
|
||||
work_update_short_message (c, msg_id);
|
||||
return;
|
||||
case CODE_update_short_chat_message:
|
||||
work_update_short_chat_message (c, msg_id);
|
||||
return;
|
||||
}
|
||||
logprintf ( "Unknown message: \n");
|
||||
hexdump_in ();
|
||||
|
@ -255,8 +255,12 @@ static inline int prefetch_strlen (void) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern int verbosity;
|
||||
static inline char *fetch_str (int len) {
|
||||
assert (len >= 0);
|
||||
if (verbosity > 6) {
|
||||
logprintf ("fetch_string: len = %d\n", len);
|
||||
}
|
||||
if (len < 254) {
|
||||
char *str = (char *) in_ptr + 1;
|
||||
in_ptr += 1 + (len >> 2);
|
||||
@ -289,6 +293,9 @@ static inline long have_prefetch_ints (void) {
|
||||
int fetch_bignum (BIGNUM *x);
|
||||
|
||||
static inline int fetch_int (void) {
|
||||
if (verbosity > 6) {
|
||||
logprintf ("fetch_int: 0x%08x (%d)\n", *in_ptr, *in_ptr);
|
||||
}
|
||||
return *(in_ptr ++);
|
||||
}
|
||||
|
||||
|
1
net.c
1
net.c
@ -391,6 +391,7 @@ void connections_poll_result (struct pollfd *fds, int max) {
|
||||
|
||||
int send_all_acks (struct session *S) {
|
||||
clear_packet ();
|
||||
out_int (CODE_msgs_ack);
|
||||
out_int (tree_count_int (S->ack_tree));
|
||||
while (S->ack_tree) {
|
||||
int x = tree_get_min_int (S->ack_tree);
|
||||
|
63
queries.c
63
queries.c
@ -46,6 +46,7 @@ struct query *send_query (struct dc *DC, int ints, void *data, struct query_meth
|
||||
logprintf ( "Sending query of size %d to DC (%s:%d)\n", 4 * ints, DC->ip, DC->port);
|
||||
}
|
||||
struct query *q = malloc (sizeof (*q));
|
||||
memset (q, 0, sizeof (*q));
|
||||
q->data_len = ints;
|
||||
q->data = malloc (4 * ints);
|
||||
memcpy (q->data, data, 4 * ints);
|
||||
@ -68,7 +69,10 @@ struct query *send_query (struct dc *DC, int ints, void *data, struct query_meth
|
||||
|
||||
void query_ack (long long id) {
|
||||
struct query *q = query_get (id);
|
||||
if (q) { q->flags |= QUERY_ACK_RECEIVED; }
|
||||
if (q) {
|
||||
remove_event_timer (&q->ev);
|
||||
q->flags |= QUERY_ACK_RECEIVED;
|
||||
}
|
||||
}
|
||||
|
||||
void query_error (long long id) {
|
||||
@ -85,7 +89,9 @@ void query_error (long long id) {
|
||||
logprintf ( "No such query\n");
|
||||
}
|
||||
} else {
|
||||
remove_event_timer (&q->ev);
|
||||
if (!(q->flags & QUERY_ACK_RECEIVED)) {
|
||||
remove_event_timer (&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);
|
||||
@ -143,7 +149,9 @@ void query_result (long long id UU) {
|
||||
logprintf ( "No such query\n");
|
||||
}
|
||||
} else {
|
||||
remove_event_timer (&q->ev);
|
||||
if (!(q->flags & QUERY_ACK_RECEIVED)) {
|
||||
remove_event_timer (&q->ev);
|
||||
}
|
||||
queries_tree = tree_delete_query (queries_tree, q);
|
||||
if (q->methods && q->methods->on_answer) {
|
||||
q->methods->on_answer (q);
|
||||
@ -191,6 +199,10 @@ void work_timers (void) {
|
||||
assert (ev);
|
||||
if (ev->timeout > t) { break; }
|
||||
remove_event_timer (ev);
|
||||
assert (ev->alarm);
|
||||
if (verbosity) {
|
||||
logprintf ("Alarm\n");
|
||||
}
|
||||
ev->alarm (ev->self);
|
||||
}
|
||||
}
|
||||
@ -405,3 +417,48 @@ void do_update_contact_list (void) {
|
||||
out_string ("");
|
||||
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_contacts_methods);
|
||||
}
|
||||
|
||||
|
||||
int msg_send_on_answer (struct query *q UU) {
|
||||
assert (fetch_int () == (int)CODE_messages_sent_message);
|
||||
int uid = fetch_int (); // uid
|
||||
int date = fetch_int (); // date
|
||||
int ptr = fetch_int (); // ptr
|
||||
int seq = fetch_int (); // seq
|
||||
logprintf ("Sent: uid = %d, date = %d, ptr = %d, seq = %d\n", uid, date, ptr, seq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct query_methods msg_send_methods = {
|
||||
.on_answer = msg_send_on_answer
|
||||
};
|
||||
|
||||
int out_message_num;
|
||||
void do_send_message (union user_chat *U, const char *msg) {
|
||||
if (!out_message_num) {
|
||||
out_message_num = lrand48 ();
|
||||
}
|
||||
clear_packet ();
|
||||
out_int (CODE_messages_send_message);
|
||||
if (U->id < 0) {
|
||||
out_int (CODE_input_peer_chat);
|
||||
out_int (-U->id);
|
||||
} else {
|
||||
if (U->user.access_hash) {
|
||||
out_int (CODE_input_peer_foreign);
|
||||
out_int (U->id);
|
||||
out_long (U->user.access_hash);
|
||||
} else {
|
||||
out_int (CODE_input_peer_contact);
|
||||
out_int (U->id);
|
||||
}
|
||||
}
|
||||
out_string (msg);
|
||||
out_long (out_message_num ++);
|
||||
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_methods);
|
||||
if (U->id < 0) {
|
||||
rprintf (COLOR_RED "%s" COLOR_GREEN " <<< " COLOR_NORMAL "%s\n", U->chat.title, msg);
|
||||
} else {
|
||||
rprintf (COLOR_RED "%s %s" COLOR_GREEN " <<< " COLOR_NORMAL "%s\n", U->user.first_name, U->user.last_name, msg);
|
||||
}
|
||||
}
|
||||
|
@ -44,4 +44,6 @@ int do_send_code_result (const char *code);
|
||||
double get_double_time (void);
|
||||
|
||||
void do_update_contact_list (void);
|
||||
union user_chat;
|
||||
void do_send_message (union user_chat *U, const char *msg);
|
||||
#endif
|
||||
|
85
structures.c
85
structures.c
@ -4,6 +4,8 @@
|
||||
#include "telegram.h"
|
||||
#include "tree.h"
|
||||
|
||||
int verbosity;
|
||||
|
||||
void fetch_file_location (struct file_location *loc) {
|
||||
int x = fetch_int ();
|
||||
if (x == CODE_file_location_unavailable) {
|
||||
@ -234,6 +236,28 @@ void fetch_message_action (struct message_action *M) {
|
||||
}
|
||||
}
|
||||
|
||||
void fetch_message_short (struct message *M) {
|
||||
memset (M, 0, sizeof (*M));
|
||||
M->id = fetch_int ();
|
||||
M->from_id = fetch_int ();
|
||||
M->message = fetch_str_dup ();
|
||||
fetch_int (); // pts
|
||||
M->date = fetch_int ();
|
||||
fetch_int (); // seq
|
||||
}
|
||||
|
||||
void fetch_message_short_chat (struct message *M) {
|
||||
memset (M, 0, sizeof (*M));
|
||||
M->id = fetch_int ();
|
||||
M->from_id = fetch_int ();
|
||||
M->to_id = fetch_int ();
|
||||
M->message = fetch_str_dup ();
|
||||
fetch_int (); // pts
|
||||
M->date = fetch_int ();
|
||||
fetch_int (); // seq
|
||||
}
|
||||
|
||||
|
||||
void fetch_message_media (struct message_media *M) {
|
||||
memset (M, 0, sizeof (*M));
|
||||
M->type = fetch_int ();
|
||||
@ -442,6 +466,49 @@ struct message *fetch_alloc_message (void) {
|
||||
}
|
||||
}
|
||||
|
||||
struct message *fetch_alloc_message_short (void) {
|
||||
struct message *M = malloc (sizeof (*M));
|
||||
fetch_message_short (M);
|
||||
struct message *M1 = tree_lookup_message (message_tree, M);
|
||||
messages_allocated ++;
|
||||
if (M1) {
|
||||
message_del_use (M1);
|
||||
free_message (M1);
|
||||
memcpy (M1, M, sizeof (*M));
|
||||
free (M);
|
||||
message_add_use (M1);
|
||||
messages_allocated --;
|
||||
return M1;
|
||||
} else {
|
||||
message_add_use (M);
|
||||
message_tree = tree_insert_message (message_tree, M, lrand48 ());
|
||||
return M;
|
||||
}
|
||||
}
|
||||
|
||||
struct message *fetch_alloc_message_short_chat (void) {
|
||||
struct message *M = malloc (sizeof (*M));
|
||||
fetch_message_short_chat (M);
|
||||
if (verbosity >= 2) {
|
||||
logprintf ("Read message with id %d\n", M->id);
|
||||
}
|
||||
struct message *M1 = tree_lookup_message (message_tree, M);
|
||||
messages_allocated ++;
|
||||
if (M1) {
|
||||
message_del_use (M1);
|
||||
free_message (M1);
|
||||
memcpy (M1, M, sizeof (*M));
|
||||
free (M);
|
||||
message_add_use (M1);
|
||||
messages_allocated --;
|
||||
return M1;
|
||||
} else {
|
||||
message_add_use (M);
|
||||
message_tree = tree_insert_message (message_tree, M, lrand48 ());
|
||||
return M;
|
||||
}
|
||||
}
|
||||
|
||||
struct chat *fetch_alloc_chat (void) {
|
||||
union user_chat *U = malloc (sizeof (*U));
|
||||
fetch_chat (&U->chat);
|
||||
@ -475,3 +542,21 @@ int print_stat (char *s, int len) {
|
||||
messages_allocated
|
||||
);
|
||||
}
|
||||
|
||||
union user_chat *user_chat_get (int id) {
|
||||
union user_chat U;
|
||||
U.id = id;
|
||||
return tree_lookup_peer (peer_tree, &U);
|
||||
}
|
||||
|
||||
struct message *message_get (int id) {
|
||||
struct message M;
|
||||
M.id = id;
|
||||
return tree_lookup_message (message_tree, &M);
|
||||
}
|
||||
|
||||
void update_message_id (struct message *M, int id) {
|
||||
message_tree = tree_delete_message (message_tree, M);
|
||||
M->id = id;
|
||||
message_tree = tree_insert_message (message_tree, M, lrand48 ());
|
||||
}
|
||||
|
@ -142,12 +142,19 @@ struct message {
|
||||
};
|
||||
|
||||
void fetch_file_location (struct file_location *loc);
|
||||
void fetch_user_status (struct user_status *S);
|
||||
void fetch_user (struct user *U);
|
||||
struct user *fetch_alloc_user (void);
|
||||
struct chat *fetch_alloc_chat (void);
|
||||
struct message *fetch_alloc_message (void);
|
||||
struct message *fetch_alloc_message_short (void);
|
||||
struct message *fetch_alloc_message_short_chat (void);
|
||||
|
||||
void free_user (struct user *U);
|
||||
void free_chat (struct chat *U);
|
||||
|
||||
int print_stat (char *s, int len);
|
||||
union user_chat *user_chat_get (int id);
|
||||
struct message *message_get (int id);
|
||||
void update_message_id (struct message *M, int id);
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user