fetch messages for channels and display them

This commit is contained in:
2019-07-08 18:38:24 +02:00
parent 8718ef85a0
commit c3f4f5a180
13 changed files with 397 additions and 8 deletions

View File

@@ -2,6 +2,47 @@
#include "internal.h"
bool dc_api_get_messages(dc_api_t api, dc_account_t login, dc_channel_t c)
{
bool ret = false;
char *url = NULL;
json_t *reply = NULL, *i = NULL;
GPtrArray *msgs = NULL;
size_t idx = 0;
return_if_true(api == NULL || login == NULL || c == NULL, false);
msgs = g_ptr_array_new_with_free_func((GDestroyNotify)dc_unref);
goto_if_true(msgs == NULL, cleanup);
asprintf(&url, "channels/%s/messages", dc_channel_id(c));
goto_if_true(url == NULL, cleanup);
reply = dc_api_call_sync(api, "GET", TOKEN(login), url, NULL);
goto_if_true(reply == NULL, cleanup);
goto_if_true(!json_is_array(reply), cleanup);
json_array_foreach(reply, idx, i) {
dc_message_t m = dc_message_from_json(i);
g_ptr_array_add(msgs, m);
}
dc_channel_addmessages(c, (dc_message_t*)msgs->pdata, msgs->len);
ret = true;
cleanup:
if (msgs != NULL) {
g_ptr_array_unref(msgs);
msgs = NULL;
}
json_decref(reply);
free(url);
return ret;
}
bool dc_api_create_channel(dc_api_t api, dc_account_t login,
dc_account_t *recipients, size_t nrecp,
dc_channel_t *channel)

View File

@@ -43,6 +43,8 @@ struct dc_channel_
/* application ID of the group DM creator if it is bot-created
*/
char *application_id;
GPtrArray *messages;
};
static void dc_channel_free(dc_channel_t c)
@@ -62,6 +64,11 @@ static void dc_channel_free(dc_channel_t c)
c->recipients = NULL;
}
if (c->messages != NULL) {
g_ptr_array_unref(c->messages);
c->messages = NULL;
}
free(c);
}
@@ -76,6 +83,10 @@ dc_channel_t dc_channel_new(void)
(GDestroyNotify)dc_unref
);
c->messages = g_ptr_array_new_with_free_func(
(GDestroyNotify)dc_unref
);
return dc_ref(c);
}
@@ -214,6 +225,12 @@ json_t *dc_channel_to_json(dc_channel_t c)
return j;
}
char const *dc_channel_id(dc_channel_t c)
{
return_if_true(c == NULL, NULL);
return c->id;
}
dc_channel_type_t dc_channel_type(dc_channel_t c)
{
return_if_true(c == NULL, -1);
@@ -238,3 +255,30 @@ dc_account_t dc_channel_nthrecipient(dc_channel_t c, size_t i)
return_if_true(i >= c->recipients->len, NULL);
return g_ptr_array_index(c->recipients, i);
}
size_t dc_channel_messages(dc_channel_t c)
{
return_if_true(c == NULL || c->messages == NULL, 0);
return c->messages->len;
}
dc_message_t dc_channel_nthmessage(dc_channel_t c, size_t i)
{
return_if_true(c == NULL || c->messages == NULL, NULL);
return_if_true(i >= c->messages->len, NULL);
return g_ptr_array_index(c->messages, i);
}
void dc_channel_addmessages(dc_channel_t c, dc_message_t *m, size_t s)
{
return_if_true(c == NULL || c->messages == NULL,);
return_if_true(m == NULL || s == 0,);
size_t i = 0;
for (i = 0; i < s; i++) {
g_ptr_array_add(c->messages, dc_ref(m[i]));
}
g_ptr_array_sort(c->messages, (GCompareFunc)dc_message_compare);
}

View File

@@ -30,4 +30,6 @@
#define return_if_true(v,r) do { if (v) return r; } while(0)
#define goto_if_true(v,l) do { if (v) goto l; } while(0)
#define TOKEN(l) (dc_account_token(l))
#endif

155
libdc/src/message.c Normal file
View File

@@ -0,0 +1,155 @@
#include <dc/message.h>
#include "internal.h"
struct dc_message_
{
dc_refable_t ref;
char *id;
char *timestamp;
char *content;
char *channel_id;
time_t ts;
dc_account_t author;
};
static void dc_message_parse_timestamp(dc_message_t m);
static void dc_message_free(dc_message_t m)
{
return_if_true(m == NULL,);
free(m->id);
free(m->timestamp);
free(m->content);
free(m->channel_id);
dc_unref(m->author);
free(m);
}
dc_message_t dc_message_new(void)
{
dc_message_t m = calloc(1, sizeof(struct dc_message_));
return_if_true(m == NULL, NULL);
m->ref.cleanup = (dc_cleanup_t)dc_message_free;
return dc_ref(m);
}
dc_message_t dc_message_from_json(json_t *j)
{
dc_message_t m = NULL;
json_t *val = NULL;
return_if_true(j == NULL || !json_is_object(j), NULL);
m = dc_message_new();
return_if_true(m == NULL, NULL);
val = json_object_get(j, "id");
goto_if_true(val == NULL || !json_is_string(val), error);
m->id = strdup(json_string_value(val));
val = json_object_get(j, "timestamp");
goto_if_true(val == NULL || !json_is_string(val), error);
m->timestamp = strdup(json_string_value(val));
dc_message_parse_timestamp(m);
val = json_object_get(j, "content");
goto_if_true(val == NULL || !json_is_string(val), error);
m->content = strdup(json_string_value(val));
val = json_object_get(j, "channel_id");
goto_if_true(val == NULL || !json_is_string(val), error);
m->channel_id = strdup(json_string_value(val));
val = json_object_get(j, "author");
goto_if_true(val == NULL || !json_is_object(val), error);
m->author = dc_account_from_json(val);
return m;
error:
dc_unref(m);
return NULL;
}
json_t *dc_message_to_json(dc_message_t m)
{
return_if_true(m == NULL, NULL);
json_t *j = json_object();
return_if_true(j == NULL, NULL);
if (m->id != NULL) {
json_object_set_new(j, "id", json_string(m->id));
}
if (m->timestamp != NULL) {
json_object_set_new(j, "timestamp", json_string(m->timestamp));
}
if (m->channel_id != NULL) {
json_object_set_new(j, "channel_id", json_string(m->channel_id));
}
if (m->author != NULL) {
json_t *a = dc_account_to_json(m->author);
json_object_set_new(j, "author", a);
}
json_object_set_new(j, "content", json_string(m->content));
return j;
}
static void dc_message_parse_timestamp(dc_message_t m)
{
return_if_true(m == NULL || m->timestamp == NULL,);
struct tm t = {0};
strptime(m->timestamp, "%Y-%m-%dT%H:%M:%S", &t);
m->ts = timegm(&t);
}
int dc_message_compare(dc_message_t *a, dc_message_t *b)
{
return_if_true(a == NULL || *a == NULL ||
b == NULL || *b == NULL, 0);
return (*a)->ts - (*b)->ts;
}
char const *dc_message_id(dc_message_t m)
{
return_if_true(m == NULL, NULL);
return m->id;
}
char const *dc_message_channel_id(dc_message_t m)
{
return_if_true(m == NULL, NULL);
return m->channel_id;
}
char const *dc_message_timestamp(dc_message_t m)
{
return_if_true(m == NULL, NULL);
return m->timestamp;
}
char const *dc_message_content(dc_message_t m)
{
return_if_true(m == NULL, NULL);
return m->content;
}
dc_account_t dc_message_author(dc_message_t m)
{
return_if_true(m == NULL, NULL);
return m->author;
}