Many bug fixes. Added dialog_list query

This commit is contained in:
Vysheng 2013-10-18 20:00:47 +04:00
parent a8a18a8076
commit e40ae9590d
8 changed files with 282 additions and 21 deletions

View File

@ -13,6 +13,8 @@
#include "interface.h"
#include "telegram.h"
#include "structures.h"
#include "mtproto-common.h"
char *default_prompt = ">";
char *get_default_prompt (void) {
@ -28,6 +30,8 @@ char *commands[] = {
"msg",
"contact_list",
"stats",
"history",
"dialog_list",
0 };
int commands_flags[] = {
@ -35,6 +39,8 @@ int commands_flags[] = {
072,
07,
07,
072,
07,
};
char *a = 0;
@ -194,6 +200,8 @@ void interpreter (char *line UU) {
}
if (!memcmp (line, "contact_list", 12)) {
do_update_contact_list ();
} else if (!memcmp (line, "dialog_list", 11)) {
do_get_dialog_list ();
} else if (!memcmp (line, "stats", 5)) {
static char stat_buf[1 << 15];
print_stat (stat_buf, (1 << 15) - 1);
@ -203,13 +211,32 @@ void interpreter (char *line UU) {
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)) {
while (index < user_num + chat_num && (!Peers[index]->print_name || strncmp (Peers[index]->print_name, text, len))) {
index ++;
}
while (*q && (*q == ' ' || *q == '\t')) { q ++; }
if (*q && index < user_num + chat_num) {
do_send_message (Peers[index], q);
}
} else if (!memcmp (line, "history", 7)) {
char *q = line + 7;
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 ++;
}
if (index < user_num + chat_num) {
char *text = get_token (&q, &len);
int limit = 40;
if (text) {
limit = atoi (text);
if (limit <= 0 || limit >= 1000000) {
limit = 40;
}
}
do_get_history (Peers[index], limit);
}
}
}
@ -289,13 +316,58 @@ void logprintf (const char *format, ...) {
}
}
const char *message_media_type_str (struct message_media *M) {
static char buf[1000];
switch (M->type) {
case CODE_message_media_empty:
return "";
case CODE_message_media_photo:
return "[photo]";
case CODE_message_media_video:
return "[video]";
case CODE_message_media_geo:
sprintf (buf, "[geo] %.6lf:%.6lf", M->geo.latitude, M->geo.longitude);
return buf;
case CODE_message_media_contact:
snprintf (buf, 999, "[contact] " COLOR_RED "%s %s" COLOR_NORMAL " %s", M->first_name, M->last_name, M->phone);
return buf;
case CODE_message_media_unsupported:
return "[unsupported]";
default:
assert (0);
return "";
}
}
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);
if (M->service) {
rprintf ("Service message\n");
return;
}
if (M->to_id >= 0) {
if (M->out) {
union user_chat *U = user_chat_get (M->to_id);
assert (M->from_id >= 0);
if (U) {
rprintf (COLOR_RED "%s %s" COLOR_GREEN " <<< %s %s" COLOR_NORMAL "\n", U->user.first_name, U->user.last_name, M->message, message_media_type_str (&M->media));
} else {
rprintf (COLOR_RED "User #%d" COLOR_GREEN " <<< %s %s" COLOR_NORMAL "\n", M->from_id, M->message, message_media_type_str (&M->media));
}
} else {
rprintf (COLOR_RED "User #%d " COLOR_GREEN " >>> " COLOR_NORMAL " %s\n", M->from_id, M->message);
union user_chat *U = user_chat_get (M->from_id);
assert (M->from_id >= 0);
if (U) {
rprintf (COLOR_RED "%s %s" COLOR_BLUE " >>> %s %s" COLOR_NORMAL "\n", U->user.first_name, U->user.last_name, M->message, message_media_type_str (&M->media));
} else {
rprintf (COLOR_RED "User #%d" COLOR_BLUE " >>> %s %s" COLOR_NORMAL "\n", M->from_id, M->message, message_media_type_str (&M->media));
}
}
} else {
rprintf ("Message to chat %d\n", -M->to_id);
union user_chat *C = user_chat_get (M->to_id);
if (C) {
rprintf ("Chat %s\n", C->chat.title);
}
}
}

View File

@ -6,6 +6,7 @@
#define COLOR_GREEN "\033[32;1m"
#define COLOR_GREY "\033[37;1m"
#define COLOR_YELLOW "\033[33;1m"
#define COLOR_BLUE "\033[34;1m"
char *get_default_prompt (void);

View File

@ -17,6 +17,7 @@
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <poll.h>
#include <zlib.h>
#include "net.h"
#include "include.h"
@ -619,6 +620,7 @@ void work_update (struct connection *c UU, long long msg_id UU) {
case CODE_update_new_message:
{
struct message *M = fetch_alloc_message ();
fetch_int (); //pts
print_message (M);
break;
};
@ -846,6 +848,45 @@ void work_rpc_result (struct connection *c UU, long long msg_id UU) {
}
}
#define MAX_PACKED_SIZE (1 << 20)
void work_packed (struct connection *c, long long msg_id) {
assert (fetch_int () == CODE_gzip_packed);
static int in_gzip;
static int buf[MAX_PACKED_SIZE >> 2];
assert (!in_gzip);
in_gzip = 1;
int l = prefetch_strlen ();
char *s = fetch_str (l);
size_t dl = MAX_PACKED_SIZE;
z_stream strm = {0};
assert (inflateInit2 (&strm, 16 + MAX_WBITS) == Z_OK);
strm.avail_in = l;
strm.next_in = (void *)s;
strm.avail_out = MAX_PACKED_SIZE;
strm.next_out = (void *)buf;
int err = inflate (&strm, Z_FINISH);
if (verbosity) {
logprintf ( "inflate error = %d\n", err);
logprintf ( "inflated %d bytes\n", (int)strm.total_out);
}
int *end = in_ptr;
int *eend = in_end;
assert (dl % 4 == 0);
in_ptr = buf;
in_end = in_ptr + strm.total_out / 4;
if (verbosity >= 4) {
logprintf ( "Unzipped data: ");
hexdump_in ();
}
rpc_execute_answer (c, msg_id);
in_ptr = end;
in_end = eend;
in_gzip = 0;
}
void rpc_execute_answer (struct connection *c, long long msg_id UU) {
if (verbosity >= 5) {
hexdump_in ();
@ -876,6 +917,9 @@ void rpc_execute_answer (struct connection *c, long long msg_id UU) {
case CODE_update_short_chat_message:
work_update_short_chat_message (c, msg_id);
return;
case CODE_gzip_packed:
work_packed (c, msg_id);
return;
}
logprintf ( "Unknown message: \n");
hexdump_in ();

View File

@ -299,6 +299,14 @@ static inline int fetch_int (void) {
return *(in_ptr ++);
}
static inline int fetch_bool (void) {
if (verbosity > 6) {
logprintf ("fetch_bool: 0x%08x (%d)\n", *in_ptr, *in_ptr);
}
assert (*(in_ptr) == (int)CODE_bool_true || *(in_ptr) == (int)CODE_bool_false);
return *(in_ptr ++) == (int)CODE_bool_true;
}
static inline int prefetch_int (void) {
return *(in_ptr);
}

109
queries.c
View File

@ -33,6 +33,8 @@ struct query *query_get (long long id) {
int alarm_query (struct query *q) {
assert (q);
q->ev.timeout = get_double_time () + QUERY_TIMEOUT;
insert_event_timer (&q->ev);
return 0;
}
@ -69,7 +71,7 @@ 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) {
if (q && !(q->flags & QUERY_ACK_RECEIVED)) {
remove_event_timer (&q->ev);
q->flags |= QUERY_ACK_RECEIVED;
}
@ -462,3 +464,108 @@ void do_send_message (union user_chat *U, const char *msg) {
rprintf (COLOR_RED "%s %s" COLOR_GREEN " <<< " COLOR_NORMAL "%s\n", U->user.first_name, U->user.last_name, msg);
}
}
int get_history_on_answer (struct query *q UU) {
static struct message *ML[10000];
int i;
int x = fetch_int ();
if (x == (int)CODE_messages_messages_slice) {
fetch_int ();
rprintf ("...\n");
} else {
assert (x == (int)CODE_messages_messages);
}
assert (fetch_int () == CODE_vector);
int n = fetch_int ();
for (i = 0; i < n; i++) {
struct message *M = fetch_alloc_message ();
if (i <= 9999) {
ML[i] = M;
}
}
if (n > 10000) { n = 10000; }
for (i = n - 1; i >= 0; i--) {
print_message (ML[i]);
}
assert (fetch_int () == CODE_vector);
n = fetch_int ();
for (i = 0; i < n; i++) {
fetch_alloc_chat ();
}
assert (fetch_int () == CODE_vector);
n = fetch_int ();
for (i = 0; i < n; i++) {
fetch_alloc_user ();
}
return 0;
}
struct query_methods get_history_methods = {
.on_answer = get_history_on_answer,
};
void do_get_history (union user_chat *U, int limit) {
clear_packet ();
out_int (CODE_messages_get_history);
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_int (0);
out_int (0);
out_int (limit);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_history_methods);
}
int get_dialogs_on_answer (struct query *q UU) {
assert (fetch_int () == CODE_messages_dialogs);
assert (fetch_int () == CODE_vector);
int n, i;
n = fetch_int ();
for (i = 0; i < n; i++) {
assert (fetch_int () == CODE_dialog);
fetch_peer_id ();
fetch_int ();
fetch_int ();
}
assert (fetch_int () == CODE_vector);
n = fetch_int ();
for (i = 0; i < n; i++) {
fetch_alloc_message ();
}
assert (fetch_int () == CODE_vector);
n = fetch_int ();
for (i = 0; i < n; i++) {
fetch_alloc_chat ();
}
assert (fetch_int () == CODE_vector);
n = fetch_int ();
for (i = 0; i < n; i++) {
fetch_alloc_user ();
}
return 0;
}
struct query_methods get_dialogs_methods = {
.on_answer = get_dialogs_on_answer,
};
void do_get_dialog_list (void) {
clear_packet ();
out_int (CODE_messages_get_dialogs);
out_int (0);
out_int (0);
out_int (1000);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dialogs_methods);
}

View File

@ -46,4 +46,6 @@ 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);
void do_get_history (union user_chat *U, int limit);
void do_get_dialog_list (void);
#endif

View File

@ -148,6 +148,7 @@ void fetch_chat (struct chat *C) {
}
void fetch_photo_size (struct photo_size *S) {
memset (S, 0, sizeof (*S));
unsigned x = fetch_int ();
assert (x == CODE_photo_size || x == CODE_photo_cached_size);
S->type = fetch_str_dup ();
@ -162,9 +163,15 @@ void fetch_photo_size (struct photo_size *S) {
}
void fetch_geo (struct geo *G) {
assert (fetch_int () == CODE_geo_point);
G->longitude = fetch_double ();
G->latitude = fetch_double ();
unsigned x = fetch_int ();
if (x == CODE_geo_point) {
G->longitude = fetch_double ();
G->latitude = fetch_double ();
} else {
assert (x == CODE_geo_point_empty);
G->longitude = 0;
G->latitude = 0;
}
}
void fetch_photo (struct photo *P) {
@ -244,17 +251,19 @@ void fetch_message_short (struct message *M) {
fetch_int (); // pts
M->date = fetch_int ();
fetch_int (); // seq
M->media.type = CODE_message_media_empty;
}
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->to_id = -fetch_int ();
M->message = fetch_str_dup ();
fetch_int (); // pts
M->date = fetch_int ();
fetch_int (); // seq
M->media.type = CODE_message_media_empty;
}
@ -283,10 +292,21 @@ void fetch_message_media (struct message_media *M) {
M->data = fetch_str_dup ();
break;
default:
logprintf ("type = 0x%08x\n", M->type);
assert (0);
}
}
int fetch_peer_id (void) {
unsigned x =fetch_int ();
if (x == CODE_peer_user) {
return fetch_int ();
} else {
assert (CODE_peer_chat);
return -fetch_int ();
}
}
void fetch_message (struct message *M) {
memset (M, 0, sizeof (*M));
unsigned x = fetch_int ();
@ -301,9 +321,9 @@ void fetch_message (struct message *M) {
M->fwd_date = fetch_int ();
}
M->from_id = fetch_int ();
M->to_id = fetch_int ();
M->out = (fetch_int () == (int)CODE_bool_true);
M->unread = (fetch_int () == (int)CODE_bool_true);
M->to_id = fetch_peer_id ();
M->out = fetch_bool ();
M->unread = fetch_bool ();
M->date = fetch_int ();
if (x == CODE_message_service) {
M->service = 1;
@ -360,21 +380,27 @@ void free_user (struct user *U) {
void free_photo_size (struct photo_size *S) {
free (S->type);
free (S->data);
if (S->data) {
free (S->data);
}
}
void free_photo (struct photo *P) {
free (P->caption);
int i;
for (i = 0; i < P->sizes_num; i++) {
free_photo_size (&P->sizes[i]);
if (!P->access_hash) { return; }
if (P->caption) { free (P->caption); }
if (P->sizes) {
int i;
for (i = 0; i < P->sizes_num; i++) {
free_photo_size (&P->sizes[i]);
}
free (P->sizes);
}
free (P->sizes);
}
void free_video (struct video *V) {
if (!V->access_hash) { return; }
free (V->caption);
free (&V->thumb);
free_photo_size (&V->thumb);
}
void free_message_media (struct message_media *M) {

View File

@ -149,6 +149,7 @@ 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);
int fetch_peer_id (void);
void free_user (struct user *U);
void free_chat (struct chat *U);