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:
parent
ae2177abd5
commit
19e0c63101
|
@ -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);
|
||||
|
|
|
@ -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() */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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, >)) return 0;
|
||||
return gt.tv_sec;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue