parse READY event to get information for session

This commit is contained in:
Florian Stinglmayr 2019-07-10 19:04:41 +02:00
parent d10f0b1f32
commit b6cffac1d9
10 changed files with 225 additions and 23 deletions

View File

@ -46,7 +46,9 @@ dc_account_t dc_account_new2(char const *email, char const *pass);
dc_account_t dc_account_from_fullname(char const *fullid);
dc_account_t dc_account_from_json(json_t *j);
dc_account_t dc_account_from_relationship(json_t *j);
json_t *dc_account_to_json(dc_account_t a);
bool dc_account_load(dc_account_t a, json_t *j);
void dc_account_set_email(dc_account_t a, char const *email);
char const *dc_account_email(dc_account_t a);
@ -76,6 +78,7 @@ bool dc_account_equal(dc_account_t a, dc_account_t b);
/* relationships
*/
void dc_account_set_friends(dc_account_t a, dc_account_t *ptr, size_t len);
void dc_account_add_friend(dc_account_t a, dc_account_t friend);
dc_account_t dc_account_nthfriend(dc_account_t a, size_t i);
size_t dc_account_friends_size(dc_account_t a);
dc_account_t dc_account_findfriend(dc_account_t a, char const *fullname);

View File

@ -56,6 +56,7 @@ dc_channel_type_t dc_channel_type(dc_channel_t c);
void dc_channel_set_type(dc_channel_t c, dc_channel_type_t t);
size_t dc_channel_recipients(dc_channel_t c);
void dc_channel_addrecipient(dc_channel_t c, dc_account_t a);
dc_account_t dc_channel_nthrecipient(dc_channel_t c, size_t i);
size_t dc_channel_messages(dc_channel_t c);

View File

@ -7,6 +7,13 @@
struct dc_event_;
typedef struct dc_event_ *dc_event_t;
typedef enum {
DC_EVENT_TYPE_UNKNOWN = 0,
DC_EVENT_TYPE_READY,
DC_EVENT_TYPE_LAST,
} dc_event_type_t;
dc_event_t dc_event_new(char const *type, json_t *payload);
/**
@ -22,4 +29,9 @@ char const *dc_event_type(dc_event_t e);
*/
json_t *dc_event_payload(dc_event_t e);
/**
* Returns an integer code representing the given type string.
*/
dc_event_type_t dc_event_type_code(dc_event_t e);
#endif

View File

@ -52,6 +52,19 @@ bool dc_session_has_token(dc_session_t s);
*/
dc_account_t dc_session_me(dc_session_t s);
/**
* access to the internal account cache
*/
void dc_session_add_account(dc_session_t s, dc_account_t u);
/**
* access to the internal channel cache
*/
void dc_session_add_channel(dc_session_t s, dc_channel_t u);
/**
* comparision functions for sorting, and finding
*/
bool dc_session_equal_me(dc_session_t s, dc_account_t a);
bool dc_session_equal_me_fullname(dc_session_t s, char const *a);

View File

@ -116,24 +116,43 @@ dc_account_t dc_account_from_fullname(char const *fullid)
return acc;
}
dc_account_t dc_account_from_json(json_t *j)
bool dc_account_load(dc_account_t user, json_t *j)
{
json_t *val = NULL;
return_if_true(!json_is_object(j), false);
val = json_object_get(j, "id");
return_if_true(val == NULL || !json_is_string(val), false);
dc_account_set_id(user, json_string_value(val));
val = json_object_get(j, "username");
return_if_true(val == NULL || !json_is_string(val), false);
dc_account_set_username(user, json_string_value(val));
val = json_object_get(j, "discriminator");
return_if_true(val == NULL || !json_is_string(val), false);
dc_account_set_discriminator(user, json_string_value(val));
return true;
}
dc_account_t dc_account_from_relationship(json_t *j)
{
dc_account_t user = dc_account_new();
json_t *val = NULL;
goto_if_true(!json_is_object(j), error);
val = json_object_get(j, "user");
goto_if_true(val == NULL || !json_is_object(val), error);
val = json_object_get(j, "username");
goto_if_true(val == NULL || !json_is_string(val), error);
dc_account_set_username(user, json_string_value(val));
if (!dc_account_load(user, val)) {
goto error;
}
val = json_object_get(j, "discriminator");
goto_if_true(val == NULL || !json_is_string(val), error);
dc_account_set_discriminator(user, json_string_value(val));
val = json_object_get(j, "id");
goto_if_true(val == NULL || !json_is_string(val), error);
dc_account_set_id(user, json_string_value(val));
val = json_object_get(j, "type");
if (val != NULL && json_is_integer(val)) {
dc_account_set_friend_state(user, json_integer_value(val));
}
return user;
@ -143,6 +162,18 @@ error:
return NULL;
}
dc_account_t dc_account_from_json(json_t *j)
{
dc_account_t user = dc_account_new();
if (!dc_account_load(user, j)) {
dc_unref(user);
return NULL;
}
return user;
}
json_t *dc_account_to_json(dc_account_t a)
{
json_t *j = NULL;
@ -315,6 +346,12 @@ dc_account_t dc_account_findfriend(dc_account_t a, char const *fullname)
return NULL;
}
void dc_account_add_friend(dc_account_t a, dc_account_t friend)
{
return_if_true(a == NULL || friend == NULL,);
g_ptr_array_add(a->friends, dc_ref(friend));
}
dc_account_t dc_account_nthfriend(dc_account_t a, size_t i)
{
return_if_true(a == NULL || a->friends == NULL, NULL);

View File

@ -256,6 +256,12 @@ dc_account_t dc_channel_nthrecipient(dc_channel_t c, size_t i)
return g_ptr_array_index(c->recipients, i);
}
void dc_channel_addrecipient(dc_channel_t c, dc_account_t a)
{
return_if_true(c == NULL || a == NULL,);
g_ptr_array_add(c->recipients, dc_ref(a));
}
size_t dc_channel_messages(dc_channel_t c)
{
return_if_true(c == NULL || c->messages == NULL, 0);

View File

@ -57,3 +57,22 @@ json_t *dc_event_payload(dc_event_t e)
return_if_true(e == NULL, NULL);
return e->payload;
}
dc_event_type_t dc_event_type_code(dc_event_t e)
{
static char const *types[] = {
"UNKNOWN",
"READY",
NULL
};
int i = 0;
for (i = 0; types[i] != NULL; i++) {
if (strcmp(types[i], e->type) == 0) {
return (dc_event_type_t)i;
}
}
return DC_EVENT_TYPE_UNKNOWN;
}

View File

@ -309,10 +309,6 @@ static void dc_gateway_process_read(dc_gateway_t gw)
do {
ret = curl_easy_recv(gw->easy, buf, sizeof(buf), &outlen);
if (ret == CURLE_OK && outlen > 0) {
FILE *f = fopen("output.txt", "a+");
fwrite(buf, outlen, sizeof(char), f);
fputc('\n', f);
fclose(f);
g_byte_array_append(gw->buffer, (uint8_t const*)buf, outlen);
}
} while (ret == CURLE_OK && outlen > 0);

View File

@ -9,12 +9,35 @@ struct dc_session_
dc_api_t api;
dc_account_t login;
dc_gateway_t gateway;
GHashTable *accounts;
GHashTable *channels;
};
/* event handlers
*/
typedef void (*dc_session_handler_t)(dc_session_t s, dc_event_t e);
static void dc_session_handle_ready(dc_session_t s, dc_event_t e);
static dc_session_handler_t handlers[DC_EVENT_TYPE_LAST] = {
[DC_EVENT_TYPE_UNKNOWN] = NULL,
[DC_EVENT_TYPE_READY] = dc_session_handle_ready,
};
static void dc_session_free(dc_session_t s)
{
return_if_true(s == NULL,);
if (s->accounts != NULL) {
g_hash_table_unref(s->accounts);
s->accounts = NULL;
}
if (s->channels != NULL) {
g_hash_table_unref(s->channels);
s->channels = NULL;
}
dc_session_logout(s);
dc_unref(s->api);
@ -23,14 +46,68 @@ static void dc_session_free(dc_session_t s)
free(s);
}
static void dc_session_handle_ready(dc_session_t s, dc_event_t e)
{
json_t *r = dc_event_payload(e);
json_t *user = NULL;
json_t *relationships = NULL;
size_t idx = 0;
json_t *c = NULL;
json_t *channels = NULL;
/* retrieve user information about ourselves, including snowflake,
* discriminator, and other things
*/
user = json_object_get(r, "user");
if (user != NULL && json_is_object(user)) {
dc_account_load(s->login, user);
dc_session_add_account(s, s->login);
}
/* load relationships, aka friends
*/
relationships = json_object_get(r, "relationships");
if (relationships != NULL && json_is_array(relationships)) {
json_array_foreach(relationships, idx, c) {
dc_account_t u = dc_account_from_relationship(user);
if (u == NULL) {
continue;
}
dc_account_add_friend(s->login, u);
dc_session_add_account(s, u);
}
}
/* load channels
*/
channels = json_object_get(r, "private_channels");
if (channels != NULL && json_is_array(channels)) {
json_array_foreach(channels, idx, c) {
dc_channel_t chan = dc_channel_from_json(c);
if (chan == NULL) {
continue;
}
dc_session_add_channel(s, chan);
}
}
}
static void dc_session_handler(dc_gateway_t gw, dc_event_t e, void *p)
{
dc_session_t s = (dc_session_t)p;
dc_session_handler_t h = handlers[dc_event_type_code(e)];
if (h != NULL) {
h(s, e);
}
char *str = NULL;
str = json_dumps(dc_event_payload(e), 0);
FILE *f = fopen("events.txt", "a+");
fprintf(f, "%p: %s: %s\n", s, dc_event_type(e), str);
fprintf(f, "%s: %s\n", dc_event_type(e), str);
free(str);
fclose(f);
}
@ -44,17 +121,29 @@ dc_session_t dc_session_new(dc_loop_t loop)
s->ref.cleanup = (dc_cleanup_t)dc_session_free;
s->accounts = g_hash_table_new_full(g_str_hash, g_str_equal,
free, dc_unref
);
goto_if_true(s->accounts == NULL, error);
s->channels = g_hash_table_new_full(g_str_hash, g_str_equal,
free, dc_unref
);
goto_if_true(s->channels == NULL, error);
s->loop = dc_ref(loop);
s->api = dc_api_new();
if (s->api == NULL) {
dc_session_free(s);
return NULL;
}
goto_if_true(s->api == NULL, error);
dc_loop_add_api(s->loop, s->api);
return dc_ref(s);
error:
dc_session_free(s);
return NULL;
}
bool dc_session_logout(dc_session_t s)
@ -133,3 +222,29 @@ bool dc_session_equal_me_fullname(dc_session_t s, char const *a)
return_if_true(s == NULL || s->login == NULL || a == NULL, false);
return (strcmp(dc_account_fullname(s->login), a) == 0);
}
void dc_session_add_account(dc_session_t s, dc_account_t u)
{
return_if_true(s == NULL || u == NULL,);
return_if_true(dc_account_id(u) == NULL,);
char const *id = dc_account_id(u);
if (!g_hash_table_contains(s->accounts, id)) {
g_hash_table_insert(s->accounts, strdup(id), dc_ref(u));
}
}
void dc_session_add_channel(dc_session_t s, dc_channel_t u)
{
return_if_true(s == NULL || u == NULL,);
return_if_true(dc_channel_id(u) == NULL,);
char const *id = dc_channel_id(u);
if (!g_hash_table_contains(s->channels, id)) {
g_hash_table_insert(s->channels, strdup(id), dc_ref(u));
/* TODO: dedup for saving storage
*/
}
}

View File

@ -102,7 +102,7 @@ dc_gateway_parseframe(uint8_t const *data, size_t datalen,
goto_if_true(datalen <= idx, cleanup);
memcpy(&len, data+idx, sizeof(len));
data_len = len;
data_len = GUINT16_TO_BE(len);
idx += sizeof(len);
} else if (l == 127) {
/* read an uint16_t from the data
@ -113,7 +113,7 @@ dc_gateway_parseframe(uint8_t const *data, size_t datalen,
goto_if_true(datalen <= idx, cleanup);
memcpy(&len, data+idx, sizeof(len));
data_len = len;
data_len = GUINT64_TO_BE(len);
idx += sizeof(len);
}