From ba4e76ed96ab249f3bb919fd17adcffb0a7b4d5c Mon Sep 17 00:00:00 2001 From: vvaltman Date: Tue, 11 Nov 2014 21:10:03 +0300 Subject: [PATCH] Added user status support --- interface.c | 22 ++++++++++++++++++++- queries.c | 3 +-- structures.c | 31 +++++++++++++++++++++++++----- tgl-fetch.h | 2 +- tgl-layout.h | 1 + tgl.h | 5 +++++ updates.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++--- updates.h | 4 ++++ 8 files changed, 110 insertions(+), 12 deletions(-) diff --git a/interface.c b/interface.c index 6492bae..5351622 100644 --- a/interface.c +++ b/interface.c @@ -2006,6 +2006,25 @@ void callback_extf (struct tgl_state *TLS, void *extra, int success, char *buf) mprint_end (ev); } +void user_status_upd (struct tgl_state *TLS, struct tgl_user *U) { + if (disable_output && !notify_ev) { return; } + if (!binlog_read) { return; } + if (log_level < 2) { 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); + if (U->status.online > 0) { + mprintf (ev, " online"); + } else { + mprintf (ev, " offline"); + } + mprintf (ev, "\n"); + mpop_color (ev); + mprint_end (ev); +} + struct tgl_update_callback upd_cb = { .new_msg = print_message_gw, .marked_read = mark_read_upd, @@ -2021,7 +2040,8 @@ struct tgl_update_callback upd_cb = { .chat_update = chat_update_gw, .secret_chat_update = secret_chat_update_gw, .msg_receive = print_message_gw, - .our_id = our_id_gw + .our_id = our_id_gw, + .user_status_update = user_status_upd }; diff --git a/queries.c b/queries.c index e71fa5d..a80c104 100644 --- a/queries.c +++ b/queries.c @@ -1106,8 +1106,7 @@ void tgl_do_mark_read (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback) if (P->last) { tgl_do_messages_mark_read_encr (TLS, id, P->encr_chat.access_hash, P->last->date, callback, callback_extra); } else { - tgl_do_messages_mark_read_encr (TLS, id, P->encr_chat.access_hash, time (0) - 10, callback, callback_extra); - + tgl_do_messages_mark_read_encr (TLS, id, P->encr_chat.access_hash, 0, callback, callback_extra); } } /* }}} */ diff --git a/structures.c b/structures.c index ce3473a..632625b 100644 --- a/structures.c +++ b/structures.c @@ -135,19 +135,40 @@ int tglf_fetch_file_location (struct tgl_state *TLS, struct tgl_file_location *l return 0; } -int tglf_fetch_user_status (struct tgl_state *TLS, struct tgl_user_status *S) { +int tglf_fetch_user_status (struct tgl_state *TLS, struct tgl_user_status *S, struct tgl_user *U) { unsigned x = fetch_int (); assert (x == CODE_user_status_empty || x == CODE_user_status_online || x == CODE_user_status_offline); switch (x) { case CODE_user_status_empty: + if (S->online) { + tgl_insert_status_update (TLS, U); + tgl_remove_status_expire (TLS, U); + } S->online = 0; S->when = 0; break; case CODE_user_status_online: - S->online = 1; - S->when = fetch_int (); + { + int when = fetch_int (); + if (S->online != 1) { + tgl_insert_status_update (TLS, U); + tgl_insert_status_expire (TLS, U); + S->online = 1; + } else { + if (when != S->when) { + tgl_remove_status_expire (TLS, U); + tgl_insert_status_expire (TLS, U); + } + } + } break; case CODE_user_status_offline: + if (S->online != -1) { + tgl_insert_status_update (TLS, U); + if (S->online == 1) { + tgl_remove_status_expire (TLS, U); + } + } S->online = -1; S->when = fetch_int (); break; @@ -221,7 +242,7 @@ int tglf_fetch_user (struct tgl_state *TLS, struct tgl_user *U) { bl_do_user_add (TLS, tgl_get_peer_id (U->id), s1, l1, s2, l2, access_hash, phone, phone_len, x == CODE_user_contact); bl_do_user_set_username (TLS, U, s3, l3); assert (tglf_fetch_user_photo (TLS, U) >= 0); - assert (tglf_fetch_user_status (TLS, &U->status) >= 0); + assert (tglf_fetch_user_status (TLS, &U->status, U) >= 0); if (x == CODE_user_self) { fetch_bool (); @@ -253,7 +274,7 @@ int tglf_fetch_user (struct tgl_state *TLS, struct tgl_user *U) { } assert (tglf_fetch_user_photo (TLS, U) >= 0); - tglf_fetch_user_status (TLS, &U->status); + tglf_fetch_user_status (TLS, &U->status, U); if (x == CODE_user_self) { fetch_bool (); } diff --git a/tgl-fetch.h b/tgl-fetch.h index c83170a..428f32e 100644 --- a/tgl-fetch.h +++ b/tgl-fetch.h @@ -22,7 +22,7 @@ #include "tgl.h" int tglf_fetch_file_location (struct tgl_state *TLS, struct tgl_file_location *loc); -int tglf_fetch_user_status (struct tgl_state *TLS, struct tgl_user_status *S); +int tglf_fetch_user_status (struct tgl_state *TLS, struct tgl_user_status *S, struct tgl_user *U); int tglf_fetch_user (struct tgl_state *TLS, struct tgl_user *U); struct tgl_user *tglf_fetch_alloc_user (struct tgl_state *TLS); struct tgl_user *tglf_fetch_alloc_user_full (struct tgl_state *TLS); diff --git a/tgl-layout.h b/tgl-layout.h index 8f1c4db..50177ef 100644 --- a/tgl-layout.h +++ b/tgl-layout.h @@ -234,6 +234,7 @@ struct tgl_encr_file { struct tgl_user_status { int online; int when; + struct tgl_timer *ev; }; struct tgl_user { diff --git a/tgl.h b/tgl.h index dd1fa20..33e19b5 100644 --- a/tgl.h +++ b/tgl.h @@ -93,6 +93,7 @@ struct tgl_update_callback { void (*msg_receive)(struct tgl_state *TLS, struct tgl_message *M); void (*our_id)(struct tgl_state *TLS, int id); void (*notification)(struct tgl_state *TLS, char *type, char *message); + void (*user_status_update)(struct tgl_state *TLS, struct tgl_user *U); char *(*create_print_name) (struct tgl_state *TLS, tgl_peer_id_t id, const char *a1, const char *a2, const char *a3, const char *a4); }; @@ -204,6 +205,10 @@ struct tgl_state { struct tree_query *queries_tree; char *base_path; + + struct tree_user *online_updates; + + struct tgl_timer *online_updates_timer; }; #pragma pack(pop) //extern struct tgl_state tgl_state; diff --git a/updates.c b/updates.c index c7f2f9f..d01bfdc 100644 --- a/updates.c +++ b/updates.c @@ -23,6 +23,7 @@ #include "binlog.h" #include "auto.h" #include "structures.h" +#include "tree.h" #include @@ -130,14 +131,13 @@ void tglu_work_update (struct tgl_state *TLS, struct connection *c, long long ms tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ()); tgl_peer_t *U = tgl_peer_get (TLS, user_id); if (U) { - tglf_fetch_user_status (TLS, &U->user.status); + tglf_fetch_user_status (TLS, &U->user.status, &U->user); if (TLS->callback.status_notification) { TLS->callback.status_notification (TLS, (void *)U); } } else { - struct tgl_user_status t; - tglf_fetch_user_status (TLS, &t); + assert (skip_type_any (TYPE_TO_PARAM (user_status)) >= 0); } } break; @@ -544,3 +544,51 @@ void tglu_work_updates_to_long (struct tgl_state *TLS, struct connection *c, lon vlogprintf (E_NOTICE, "updates too long... Getting difference\n"); tgl_do_get_difference (TLS, 0, 0, 0); } + +#define user_cmp(a,b) (tgl_get_peer_id ((a)->id) - tgl_get_peer_id ((b)->id)) +DEFINE_TREE(user, struct tgl_user *,user_cmp,0) + +static void notify_status (struct tgl_user *U, void *ex) { + struct tgl_state *TLS = ex; + if (TLS->callback.user_status_update) { + TLS->callback.user_status_update (TLS, U); + } +} + +static void status_notify (struct tgl_state *TLS, void *arg) { + tree_act_ex_user (TLS->online_updates, notify_status, TLS); + tree_clear_user (TLS->online_updates); + TLS->online_updates = NULL; + TLS->timer_methods->free (TLS->online_updates_timer); + TLS->online_updates_timer = NULL; +} + +void tgl_insert_status_update (struct tgl_state *TLS, struct tgl_user *U) { + if (!tree_lookup_user (TLS->online_updates, U)) { + TLS->online_updates = tree_insert_user (TLS->online_updates, U, lrand48 ()); + } + if (!TLS->online_updates_timer) { + TLS->online_updates_timer = TLS->timer_methods->alloc (TLS, status_notify, 0); + TLS->timer_methods->insert (TLS->online_updates_timer, 0); + } +} + +static void user_expire (struct tgl_state *TLS, void *arg) { + struct tgl_user *U = arg; + TLS->timer_methods->free (U->status.ev); + U->status.ev = 0; + U->status.online = -1; + U->status.when = tglt_get_double_time (); + tgl_insert_status_update (TLS, U); +} + +void tgl_insert_status_expire (struct tgl_state *TLS, struct tgl_user *U) { + assert (!U->status.ev); + U->status.ev = TLS->timer_methods->alloc (TLS, user_expire, U); + TLS->timer_methods->insert (U->status.ev, U->status.when - tglt_get_double_time ()); +} + +void tgl_remove_status_expire (struct tgl_state *TLS, struct tgl_user *U) { + TLS->timer_methods->free (U->status.ev); + U->status.ev = 0; +} diff --git a/updates.h b/updates.h index 0716131..c586888 100644 --- a/updates.h +++ b/updates.h @@ -32,4 +32,8 @@ void tglu_fetch_pts (struct tgl_state *TLS); void tglu_fetch_qts (struct tgl_state *TLS); void tglu_fetch_seq (struct tgl_state *TLS); void tglu_fetch_date (struct tgl_state *TLS); + +void tgl_insert_status_update (struct tgl_state *TLS, struct tgl_user *U); +void tgl_insert_status_expire (struct tgl_state *TLS, struct tgl_user *U); +void tgl_remove_status_expire (struct tgl_state *TLS, struct tgl_user *U); #endif