Add timestamp support

Discord sends message times which are useful in case of pinned/backlog messages, relay those to bitlbee so that it can timestamp messages like this.

Fixes: #152
This commit is contained in:
Alcaro 2018-05-26 08:54:30 +02:00 committed by Artem Savkov
parent ae2177abd5
commit 19e0c63101
5 changed files with 44 additions and 18 deletions

View File

@ -537,7 +537,7 @@ static void discord_handle_server(struct im_connection *ic, json_value *sinfo,
}
static gboolean discord_post_message(channel_info *cinfo, const gchar *author,
gchar *msg, gboolean is_self)
gchar *msg, gboolean is_self, time_t tstamp)
{
int flags = 0;
@ -550,13 +550,13 @@ static gboolean discord_post_message(channel_info *cinfo, const gchar *author,
}
if (cinfo->type == CHANNEL_PRIVATE) {
imcb_buddy_msg(cinfo->to.handle.ic, author, msg, flags, 0);
imcb_buddy_msg(cinfo->to.handle.ic, author, msg, flags, tstamp);
return TRUE;
} else if (cinfo->type == CHANNEL_GROUP_PRIVATE && cinfo->to.group.gc != NULL) {
imcb_chat_msg(cinfo->to.group.gc, author, msg, flags, 0);
imcb_chat_msg(cinfo->to.group.gc, author, msg, flags, tstamp);
return TRUE;
} else if (cinfo->type == CHANNEL_TEXT && cinfo->to.channel.gc != NULL) {
imcb_chat_msg(cinfo->to.channel.gc, author, msg, flags, 0);
imcb_chat_msg(cinfo->to.channel.gc, author, msg, flags, tstamp);
return TRUE;
}
return FALSE;
@ -590,7 +590,7 @@ static gboolean discord_replace_channel(const GMatchInfo *match,
static gboolean discord_prepare_message(struct im_connection *ic,
json_value *minfo,
channel_info *cinfo, gboolean is_edit)
channel_info *cinfo, gboolean is_edit, gboolean use_tstamp)
{
discord_data *dd = ic->proto_data;
gboolean posted = FALSE;
@ -603,6 +603,8 @@ static gboolean discord_prepare_message(struct im_connection *ic,
"author"), "username"));
const char *nonce = json_o_str(minfo, "nonce");
gboolean is_self = discord_is_self(ic, author);
time_t tstamp = use_tstamp ? parse_iso_8601(json_o_str(minfo, "timestamp")) : 0;
// Don't echo self messages that we sent in this session
if (is_self && nonce != NULL && g_strcmp0(nonce, dd->nonce) == 0) {
@ -651,7 +653,7 @@ static gboolean discord_prepare_message(struct im_connection *ic,
}
if (cinfo->type == CHANNEL_PRIVATE) {
posted = discord_post_message(cinfo, cinfo->to.handle.name, msg, is_self);
posted = discord_post_message(cinfo, cinfo->to.handle.name, msg, is_self, tstamp);
} else if (cinfo->type == CHANNEL_TEXT || cinfo->type == CHANNEL_GROUP_PRIVATE) {
json_value *mentions = json_o_get(minfo, "mentions");
if (mentions != NULL && mentions->type == json_array) {
@ -693,7 +695,7 @@ static gboolean discord_prepare_message(struct im_connection *ic,
ic->proto_data, NULL);
g_regex_unref(cregex);
posted = discord_post_message(cinfo, author, fmsg, is_self);
posted = discord_post_message(cinfo, author, fmsg, is_self, tstamp);
g_free(fmsg);
}
@ -701,7 +703,7 @@ static gboolean discord_prepare_message(struct im_connection *ic,
if (attachments != NULL && attachments->type == json_array) {
for (int aidx = 0; aidx < attachments->u.array.length; aidx++) {
const char *url = json_o_str(attachments->u.array.values[aidx], "url");
posted = discord_post_message(cinfo, author, (char *)url, is_self);
posted = discord_post_message(cinfo, author, (char *)url, is_self, tstamp);
}
}
g_free(author);
@ -710,7 +712,7 @@ static gboolean discord_prepare_message(struct im_connection *ic,
}
void discord_handle_message(struct im_connection *ic, json_value *minfo,
handler_action action)
handler_action action, gboolean use_tstamp)
{
discord_data *dd = ic->proto_data;
@ -723,6 +725,8 @@ void discord_handle_message(struct im_connection *ic, json_value *minfo,
if (cinfo == NULL) {
return;
}
time_t tstamp = use_tstamp ? parse_iso_8601(json_o_str(minfo, "timestamp")) : 0;
if (action == ACTION_CREATE) {
guint64 msgid = g_ascii_strtoull(json_o_str(minfo, "id"), NULL, 10);
@ -733,7 +737,7 @@ void discord_handle_message(struct im_connection *ic, json_value *minfo,
if ((msgid > cinfo->last_read) || (pinned &&
!g_slist_find_custom(cinfo->pinned, json_o_str(minfo, "id"),
(GCompareFunc)g_strcmp0))) {
gboolean posted = discord_prepare_message(ic, minfo, cinfo, FALSE);
gboolean posted = discord_prepare_message(ic, minfo, cinfo, FALSE, use_tstamp);
if (posted) {
if (msgid > cinfo->last_read) {
cinfo->last_read = msgid;
@ -748,7 +752,7 @@ void discord_handle_message(struct im_connection *ic, json_value *minfo,
}
} else if (action == ACTION_UPDATE) {
if (json_o_str(json_o_get(minfo, "author"), "username") != NULL) {
discord_prepare_message(ic, minfo, cinfo, TRUE);
discord_prepare_message(ic, minfo, cinfo, TRUE, use_tstamp);
} else {
json_value *embeds = json_o_get(minfo, "embeds");
if (embeds != NULL && embeds->type == json_array) {
@ -765,7 +769,7 @@ void discord_handle_message(struct im_connection *ic, json_value *minfo,
const char *title = json_o_str(embeds->u.array.values[eidx], "title");
if (title != NULL) {
msg = g_strconcat("title: ", title, NULL);
discord_post_message(cinfo, author, msg, FALSE);
discord_post_message(cinfo, author, msg, FALSE, tstamp);
g_free(msg);
}
@ -773,7 +777,7 @@ void discord_handle_message(struct im_connection *ic, json_value *minfo,
"description");
if (description != NULL) {
msg = g_strconcat("description: ", description, NULL);
discord_post_message(cinfo, author, msg, FALSE);
discord_post_message(cinfo, author, msg, FALSE, tstamp);
g_free(msg);
}
}
@ -966,10 +970,10 @@ gboolean discord_parse_message(struct im_connection *ic, gchar *buf, guint64 siz
discord_handle_server(ic, sinfo, ACTION_DELETE);
} else if (g_strcmp0(event, "MESSAGE_CREATE") == 0) {
json_value *minfo = json_o_get(js, "d");
discord_handle_message(ic, minfo, ACTION_CREATE);
discord_handle_message(ic, minfo, ACTION_CREATE, FALSE);
} else if (g_strcmp0(event, "MESSAGE_UPDATE") == 0) {
json_value *minfo = json_o_get(js, "d");
discord_handle_message(ic, minfo, ACTION_UPDATE);
discord_handle_message(ic, minfo, ACTION_UPDATE, TRUE);
} else if (g_strcmp0(event, "RELATIONSHIP_ADD") == 0) {
json_value *rinfo = json_o_get(js, "d");
discord_handle_relationship(ic, rinfo, ACTION_CREATE);

View File

@ -24,7 +24,7 @@ typedef enum {
} handler_action;
void discord_handle_message(struct im_connection *ic, json_value *minfo,
handler_action action);
handler_action action, gboolean use_tstamp);
void discord_handle_channel(struct im_connection *ic, json_value *cinfo,
const char *server_id, handler_action action);
/* Returns TRUE if it called iwc_logout() */

View File

@ -344,7 +344,7 @@ static void discord_http_backlog_cb(struct http_request *req)
for (int midx = messages->u.array.length - 1; midx >= 0; midx--) {
json_value *minfo = messages->u.array.values[midx];
discord_handle_message(ic, minfo, ACTION_CREATE);
discord_handle_message(ic, minfo, ACTION_CREATE, TRUE);
}
json_value_free(messages);
@ -388,7 +388,7 @@ static void discord_http_pinned_cb(struct http_request *req)
for (int midx = messages->u.array.length - 1; midx >= 0; midx--) {
json_value *minfo = messages->u.array.values[midx];
discord_handle_message(ic, minfo, ACTION_CREATE);
discord_handle_message(ic, minfo, ACTION_CREATE, TRUE);
}
json_value_free(messages);

View File

@ -382,3 +382,20 @@ char *discord_utf8_strndup(const char *str, size_t n)
return g_strndup(str, g_utf8_offset_to_pointer(str, n) - str);
}
time_t parse_iso_8601(const char *timestamp)
{
#if GLIB_CHECK_VERSION(2,56,0)
if (!timestamp) return 0;
GDateTime *dt = g_date_time_new_from_iso8601(timestamp, NULL);
if (!dt) return 0;
gint64 unix = g_date_time_to_unix(dt);
g_date_time_unref(dt);
return unix;
#else
GTimeVal gt;
if (!timestamp) return 0;
if (!g_time_val_from_iso8601(timestamp, &gt)) return 0;
return gt.tv_sec;
#endif
}

View File

@ -17,6 +17,7 @@
#include "discord.h"
#include <stdlib.h>
#include <glib.h>
#include <time.h>
typedef enum {
SEARCH_UNKNOWN,
@ -43,3 +44,7 @@ char *discord_canonize_name(const char *name);
char *discord_escape_string(const char *msg);
void discord_debug(char *format, ...);
char *discord_utf8_strndup(const char *str, size_t n);
/* input: 2018-05-24T19:06:42.190000+00:00 */
/* output: 1527188802 (the .19 and timezone are discarded) */
time_t parse_iso_8601(const char *timestamp);