1
0
mirror of https://github.com/profanity-im/profanity.git synced 2024-12-04 14:46:46 -05:00

Handle late delivery

This commit is contained in:
MarcoPolo-PasTonMolo 2022-08-20 22:48:02 +03:00
parent 4b9ff6d4dc
commit a704838152
5 changed files with 108 additions and 26 deletions

View File

@ -640,8 +640,8 @@ sv_ev_incoming_message(ProfMessage* message)
new_win = TRUE; new_win = TRUE;
if (prefs_get_boolean(PREF_MAM)) { if (prefs_get_boolean(PREF_MAM)) {
iq_mam_request(chatwin);
win_print_loading_history(window); win_print_loading_history(window);
iq_mam_request(chatwin, g_date_time_add_seconds(message->timestamp, 0)); // copy timestamp
} }
#ifdef HAVE_OMEMO #ifdef HAVE_OMEMO

View File

@ -98,7 +98,7 @@ chatwin_new(const char* const barejid)
#endif // HAVE_OMEMO #endif // HAVE_OMEMO
if (prefs_get_boolean(PREF_MAM)) { if (prefs_get_boolean(PREF_MAM)) {
iq_mam_request(chatwin); iq_mam_request(chatwin, NULL);
win_print_loading_history(window); win_print_loading_history(window);
} }
@ -320,10 +320,7 @@ chatwin_incoming_msg(ProfChatWin* chatwin, ProfMessage* message, gboolean win_cr
} }
win_insert_last_read_position_marker((ProfWin*)chatwin, chatwin->barejid); win_insert_last_read_position_marker((ProfWin*)chatwin, chatwin->barejid);
win_print_incoming(window, display_name, message);
if (!win_created || !prefs_get_boolean(PREF_MAM)) {
win_print_incoming(window, display_name, message);
}
} }
wins_add_urls_ac(window, message); wins_add_urls_ac(window, message);
@ -542,7 +539,8 @@ _chatwin_history(ProfChatWin* chatwin, const char* const contact_barejid)
} }
// Print history starting from start_time to end_time if end_time is null the // Print history starting from start_time to end_time if end_time is null the
// first entrie's timestamp in the buffer is used. Flip true to prepend to buffer. // first entry's timestamp in the buffer is used. Flip true to prepend to buffer.
// Timestamps should be in iso8601
gboolean gboolean
chatwin_db_history(ProfChatWin* chatwin, char* start_time, char* end_time, gboolean flip) chatwin_db_history(ProfChatWin* chatwin, char* start_time, char* end_time, gboolean flip)
{ {

View File

@ -1869,6 +1869,7 @@ win_print_loading_history(ProfWin* window)
{ {
GDateTime* timestamp = buffer_size(window->layout->buffer) != 0 ? buffer_get_entry(window->layout->buffer, 0)->time : g_date_time_new_now_local(); GDateTime* timestamp = buffer_size(window->layout->buffer) != 0 ? buffer_get_entry(window->layout->buffer, 0)->time : g_date_time_new_now_local();
buffer_prepend(window->layout->buffer, "-", 0, timestamp, NO_DATE, THEME_ROOMINFO, NULL, NULL, LOADING_MESSAGE, NULL, NULL); buffer_prepend(window->layout->buffer, "-", 0, timestamp, NO_DATE, THEME_ROOMINFO, NULL, NULL, LOADING_MESSAGE, NULL, NULL);
g_date_time_unref(timestamp);
win_redraw(window); win_redraw(window);
} }

View File

@ -109,9 +109,17 @@ typedef struct mam_rsm_userdata
char* barejid; char* barejid;
char* start_datestr; char* start_datestr;
char* end_datestr; char* end_datestr;
gboolean fetch_next;
ProfChatWin* win; ProfChatWin* win;
} MamRsmUserdata; } MamRsmUserdata;
typedef struct late_delivery_userdata
{
ProfChatWin* win;
GDateTime* enddate;
GDateTime* startdate;
} LateDeliveryUserdata;
static int _iq_handler(xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* const userdata); static int _iq_handler(xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* const userdata);
static void _error_handler(xmpp_stanza_t* const stanza); static void _error_handler(xmpp_stanza_t* const stanza);
@ -149,6 +157,7 @@ static int _command_exec_response_handler(xmpp_stanza_t* const stanza, void* con
static int _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata); static int _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata);
static int _register_change_password_result_id_handler(xmpp_stanza_t* const stanza, void* const userdata); static int _register_change_password_result_id_handler(xmpp_stanza_t* const stanza, void* const userdata);
static void _iq_mam_request(ProfChatWin* win, GDateTime* startdate, GDateTime* enddate);
static void _iq_free_room_data(ProfRoomInfoData* roominfo); static void _iq_free_room_data(ProfRoomInfoData* roominfo);
static void _iq_free_affiliation_set(ProfPrivilegeSet* affiliation_set); static void _iq_free_affiliation_set(ProfPrivilegeSet* affiliation_set);
static void _iq_free_affiliation_list(ProfAffiliationList* affiliation_list); static void _iq_free_affiliation_list(ProfAffiliationList* affiliation_list);
@ -164,6 +173,8 @@ static gboolean autoping_wait = FALSE;
static GTimer* autoping_time = NULL; static GTimer* autoping_time = NULL;
static GHashTable* id_handlers; static GHashTable* id_handlers;
static GHashTable* rooms_cache = NULL; static GHashTable* rooms_cache = NULL;
static GSList* late_delivery_windows = NULL;
static gboolean received_disco_items = FALSE;
static int static int
_iq_handler(xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* const userdata) _iq_handler(xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* const userdata)
@ -258,6 +269,8 @@ iq_handlers_init(void)
id_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)_iq_id_handler_free); id_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)_iq_id_handler_free);
rooms_cache = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)xmpp_stanza_release); rooms_cache = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)xmpp_stanza_release);
late_delivery_windows = malloc(sizeof(GSList *));
late_delivery_windows->data = NULL;
} }
void void
@ -2525,7 +2538,16 @@ _disco_items_result_handler(xmpp_stanza_t* const stanza)
if (g_strcmp0(id, "discoitemsreq") == 0) { if (g_strcmp0(id, "discoitemsreq") == 0) {
cons_show_disco_items(items, from); cons_show_disco_items(items, from);
} else if (g_strcmp0(id, "discoitemsreq_onconnect") == 0) { } else if (g_strcmp0(id, "discoitemsreq_onconnect") == 0) {
received_disco_items = TRUE;
connection_set_disco_items(items); connection_set_disco_items(items);
while (late_delivery_windows->data) {
LateDeliveryUserdata* del_data = late_delivery_windows->data;
_iq_mam_request(del_data->win, del_data->startdate, del_data->enddate);
late_delivery_windows = g_slist_next(late_delivery_windows);
free(del_data);
}
} }
g_slist_free_full(items, (GDestroyNotify)_item_destroy); g_slist_free_full(items, (GDestroyNotify)_item_destroy);
@ -2622,7 +2644,7 @@ iq_mam_request_older(ProfChatWin* win)
} }
void void
iq_mam_request(ProfChatWin* win) _iq_mam_request(ProfChatWin* win, GDateTime* startdate, GDateTime* enddate)
{ {
if (connection_supports(XMPP_FEATURE_MAM2) == FALSE) { if (connection_supports(XMPP_FEATURE_MAM2) == FALSE) {
log_warning("Server doesn't advertise %s feature.", XMPP_FEATURE_MAM2); log_warning("Server doesn't advertise %s feature.", XMPP_FEATURE_MAM2);
@ -2630,43 +2652,72 @@ iq_mam_request(ProfChatWin* win)
return; return;
} }
ProfMessage* last_msg = log_database_get_limits_info(win->barejid, TRUE);
// To get last page and have flipped paging set firstid to empty string
char* firstid = ""; char* firstid = "";
char* startdate = NULL; char* startdate_str = NULL;
char* enddate = NULL; char* enddate_str = NULL;
gboolean fetch_next = FALSE;
// If last message found if (startdate) {
if (last_msg->timestamp) { startdate_str = g_date_time_format(startdate, "%FT%T.%f%:z");
startdate = g_date_time_format(last_msg->timestamp, "%FT%T.%f%:z"); fetch_next = TRUE;
} else { g_date_time_unref(startdate);
} else if (!enddate) {
GDateTime* now = g_date_time_new_now_utc(); GDateTime* now = g_date_time_new_now_utc();
enddate = g_date_time_format(now, "%FT%T.%f%:z"); enddate_str = g_date_time_format(now, "%FT%T.%f%:z");
g_date_time_unref(now); g_date_time_unref(now);
} }
if (enddate) {
enddate_str = g_date_time_format(enddate, "%FT%T.%f%:z");
g_date_time_unref(enddate);
}
xmpp_ctx_t* const ctx = connection_get_ctx(); xmpp_ctx_t* const ctx = connection_get_ctx();
xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, win->barejid, startdate, enddate, firstid, NULL); xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, win->barejid, startdate_str, enddate_str, firstid, NULL);
MamRsmUserdata* data = malloc(sizeof(MamRsmUserdata)); MamRsmUserdata* data = malloc(sizeof(MamRsmUserdata));
if (data) { if (data) {
data->start_datestr = startdate; data->start_datestr = startdate_str;
data->end_datestr = enddate; data->end_datestr = enddate_str;
data->barejid = strdup(win->barejid); data->barejid = strdup(win->barejid);
data->fetch_next = fetch_next;
data->win = win; data->win = win;
iq_id_handler_add(xmpp_stanza_get_id(iq), _mam_rsm_id_handler, NULL, data); iq_id_handler_add(xmpp_stanza_get_id(iq), _mam_rsm_id_handler, NULL, data);
} }
message_free(last_msg);
iq_send_stanza(iq); iq_send_stanza(iq);
xmpp_stanza_release(iq); xmpp_stanza_release(iq);
return; return;
} }
void
iq_mam_request(ProfChatWin* win, GDateTime* enddate)
{
ProfMessage* last_msg = log_database_get_limits_info(win->barejid, TRUE);
GDateTime* startdate = last_msg->timestamp ? g_date_time_add_seconds(last_msg->timestamp, 0) : NULL; // copy timestamp
message_free(last_msg);
// Save request for later if disco items haven't been received yet
if (!received_disco_items) {
if (late_delivery_windows->data == NULL) {
LateDeliveryUserdata* cur_del_data = malloc(sizeof(LateDeliveryUserdata));
cur_del_data->win = win;
cur_del_data->enddate = enddate;
cur_del_data->startdate = startdate;
late_delivery_windows->data = cur_del_data;
}
late_delivery_windows = g_slist_append(late_delivery_windows, NULL);
}
_iq_mam_request(win, startdate, enddate);
return;
}
static int static int
_mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata) _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata)
{ {
@ -2684,11 +2735,39 @@ _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata)
ProfWin* window = (ProfWin*)data->win; ProfWin* window = (ProfWin*)data->win;
buffer_remove_entry(window->layout->buffer, 0); buffer_remove_entry(window->layout->buffer, 0);
if (is_complete || data->end_datestr) {
chatwin_db_history(data->win, is_complete ? NULL : data->start_datestr, NULL, TRUE); char *start_str = NULL;
if (data->start_datestr) {
start_str = strdup(data->start_datestr);
// Convert to iso8601
start_str[strlen(start_str) - 3] = '\0';
}
char *end_str = NULL;
if (data->end_datestr) {
end_str = strdup(data->end_datestr);
// Convert to iso8601
end_str[strlen(end_str) - 3] = '\0';
}
if (is_complete || !data->fetch_next) {
chatwin_db_history(data->win, is_complete ? NULL : start_str, end_str, TRUE);
// TODO free memory
if (start_str) {
free(start_str);
free(data->start_datestr);
}
if (end_str) {
free(data->end_datestr);
}
free(data->barejid);
free(data);
return 0; return 0;
} }
chatwin_db_history(data->win, data->start_datestr, NULL, TRUE);
chatwin_db_history(data->win, start_str, end_str, TRUE);
if (start_str) free(start_str);
xmpp_stanza_t* set = xmpp_stanza_get_child_by_name_and_ns(fin, STANZA_TYPE_SET, STANZA_NS_RSM); xmpp_stanza_t* set = xmpp_stanza_get_child_by_name_and_ns(fin, STANZA_TYPE_SET, STANZA_NS_RSM);
if (set) { if (set) {
@ -2701,6 +2780,10 @@ _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata)
// 4.3.2. send same stanza with set,max stanza // 4.3.2. send same stanza with set,max stanza
xmpp_ctx_t* const ctx = connection_get_ctx(); xmpp_ctx_t* const ctx = connection_get_ctx();
if (end_str) {
free(data->end_datestr);
}
data->end_datestr = NULL;
xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, data->barejid, data->start_datestr, data->end_datestr, firstid, NULL); xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, data->barejid, data->start_datestr, data->end_datestr, firstid, NULL);
free(firstid); free(firstid);

View File

@ -261,7 +261,7 @@ void iq_autoping_check(void);
void iq_http_upload_request(HTTPUpload* upload); void iq_http_upload_request(HTTPUpload* upload);
void iq_command_list(const char* const target); void iq_command_list(const char* const target);
void iq_command_exec(const char* const target, const char* const command); void iq_command_exec(const char* const target, const char* const command);
void iq_mam_request(ProfChatWin* win); void iq_mam_request(ProfChatWin* win, GDateTime* enddate);
void iq_mam_request_older(ProfChatWin* win); void iq_mam_request_older(ProfChatWin* win);
void iq_register_change_password(const char* const user, const char* const password); void iq_register_change_password(const char* const user, const char* const password);
void iq_muc_register_nick(const char* const roomjid); void iq_muc_register_nick(const char* const roomjid);