build channel object for chat channels

This commit is contained in:
Florian Stinglmayr 2019-07-04 20:58:08 +02:00
parent 7f5ceff688
commit be4e5cedc3
8 changed files with 341 additions and 64 deletions

View File

@ -11,6 +11,7 @@ SET(SOURCES
"include/dc/account.h"
"include/dc/api.h"
"include/dc/apisync.h"
"include/dc/channel.h"
"include/dc/guild.h"
"include/dc/loop.h"
"include/dc/refable.h"
@ -18,8 +19,8 @@ SET(SOURCES
"src/account.c"
"src/api.c"
"src/api-friends.c"
"src/api-util.c"
"src/apisync.c"
"src/channel.c"
"src/guild.c"
"src/loop.c"
"src/refable.c"

View File

@ -5,6 +5,8 @@
#include <stdbool.h>
#include <stdlib.h>
#include <jansson.h>
struct dc_account_;
typedef struct dc_account_ *dc_account_t;
@ -43,6 +45,9 @@ dc_account_t dc_account_new(void);
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);
json_t *dc_account_to_json(dc_account_t a);
void dc_account_set_email(dc_account_t a, char const *email);
char const *dc_account_email(dc_account_t a);

View File

@ -0,0 +1,53 @@
#ifndef DC_CHANNEL_H
#define DC_CHANNEL_H
#include <stdint.h>
#include <jansson.h>
/**
* A discord channel. Exactly what it says on the tin. A place where one
* or more guardsmen can exchange Slaaneshi heresy without their commissars
* finding out about it. What's important here is that there are channel
* types, and that each channel has various recipients.
*/
typedef enum {
/* standard text channel in a guild
*/
CHANNEL_TYPE_GUILD_TEXT = 0,
/* A direct message channel for 1:1 communication
*/
CHANNEL_TYPE_DM_TEXT,
/* A guild voice channel
*/
CHANNEL_TYPE_GUILD_VOICE,
/* Group direct message channel 1:N communication
*/
CHANNEL_TYPE_GROUP_DM,
/* Category within a GUILD
*/
CHANNEL_TYPE_GUILD_CATEGORY,
/* News channel
*/
CHANNEL_TYPE_GUILD_NEWS,
/* Guild store, no idea what this is
*/
CHANNEL_TYPE_GUILD_STORE,
} dc_channel_type_t;
struct dc_channel_;
typedef struct dc_channel_ *dc_channel_t;
dc_channel_t dc_channel_new(void);
dc_channel_t dc_channel_from_json(json_t *j);
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);
#endif

View File

@ -116,6 +116,56 @@ dc_account_t dc_account_from_fullname(char const *fullid)
return acc;
}
dc_account_t dc_account_from_json(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, "username");
goto_if_true(val == NULL || !json_is_string(val), error);
dc_account_set_username(user, json_string_value(val));
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));
return user;
error:
dc_unref(user);
return NULL;
}
json_t *dc_account_to_json(dc_account_t a)
{
json_t *j = NULL;
return_if_true(a == NULL, NULL);
return_if_true(dc_account_username(a) == NULL ||
dc_account_discriminator(a) == NULL,
NULL
);
j = json_object();
return_if_true(j == NULL, NULL);
if (a->id != NULL) {
json_object_set_new(j, "id", json_string(a->id));
}
json_object_set_new(j, "username", json_string(a->username));
json_object_set_new(j, "discriminator", json_string(a->discriminator));
return j;
}
void dc_account_set_email(dc_account_t a, char const *email)
{
return_if_true(a == NULL,);

View File

@ -27,7 +27,7 @@ bool dc_api_get_friends(dc_api_t api, dc_account_t login)
continue;
}
dc_account_t a = dc_api_account_from_json(val);
dc_account_t a = dc_account_from_json(val);
if (a == NULL) {
continue;
}
@ -72,7 +72,7 @@ bool dc_api_remove_friend(dc_api_t api, dc_account_t login, dc_account_t friend)
asprintf(&url, "users/@me/relationships/%s", dc_account_id(friend));
post = dc_api_account_to_json(friend);
post = dc_account_to_json(friend);
return_if_true(post == NULL, false);
reply = dc_api_call_sync(api, "DELETE", dc_account_token(login), url, post);
@ -103,7 +103,7 @@ bool dc_api_accept_friend(dc_api_t api, dc_account_t login, dc_account_t friend)
asprintf(&url, "users/@me/relationships/%s", dc_account_id(friend));
post = dc_api_account_to_json(friend);
post = dc_account_to_json(friend);
return_if_true(post == NULL, false);
reply = dc_api_call_sync(api, "PUT", dc_account_token(login), url, post);
@ -131,7 +131,7 @@ bool dc_api_add_friend(dc_api_t api, dc_account_t login, dc_account_t friend)
return_if_true(api == NULL, false);
return_if_true(login == NULL, false);
post = dc_api_account_to_json(friend);
post = dc_account_to_json(friend);
return_if_true(post == NULL, false);
reply = dc_api_call_sync(api, "POST", dc_account_token(login), url, post);

View File

@ -1,53 +0,0 @@
#include <dc/api.h>
#include "internal.h"
dc_account_t dc_api_account_from_json(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, "username");
goto_if_true(val == NULL || !json_is_string(val), error);
dc_account_set_username(user, json_string_value(val));
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));
return user;
error:
dc_unref(user);
return NULL;
}
json_t *dc_api_account_to_json(dc_account_t a)
{
json_t *j = NULL;
return_if_true(a == NULL, NULL);
return_if_true(dc_account_username(a) == NULL ||
dc_account_discriminator(a) == NULL,
NULL
);
j = json_object();
return_if_true(j == NULL, NULL);
json_object_set_new(j, "username",
json_string(dc_account_username(a))
);
json_object_set_new(j, "discriminator",
json_string(dc_account_discriminator(a))
);
return j;
}

227
libdc/src/channel.c Normal file
View File

@ -0,0 +1,227 @@
#include <dc/channel.h>
#include "internal.h"
struct dc_channel_
{
dc_refable_t ref;
dc_channel_type_t type;
/* snowflake of the channel
*/
char *id;
/* Guild ID this channel belongs to, may be NULL
*/
char *guild_id;
/* Name of the channel
*/
char *name;
/* Slaneeshi filth?
*/
bool nsfw;
/* ID of last message in the channel
*/
char *last_message_id;
/* list of recipients, array of dc_account_t
*/
GPtrArray *recipients;
/* Snowflake of the owner
*/
char *owner_id;
/* ID of the parent channel or bot
*/
char *parent_id;
/* application ID of the group DM creator if it is bot-created
*/
char *application_id;
};
static void dc_channel_free(dc_channel_t c)
{
return_if_true(c == NULL,);
free(c->id);
free(c->guild_id);
free(c->name);
free(c->last_message_id);
free(c->owner_id);
free(c->parent_id);
free(c->application_id);
if (c->recipients != NULL) {
g_ptr_array_unref(c->recipients);
c->recipients = NULL;
}
free(c);
}
dc_channel_t dc_channel_new(void)
{
dc_channel_t c = calloc(1, sizeof(struct dc_channel_));
return_if_true(c == NULL, NULL);
c->ref.cleanup = (dc_cleanup_t)dc_channel_free;
c->recipients = g_ptr_array_new_with_free_func(
(GDestroyNotify)dc_unref
);
return dc_ref(c);
}
dc_channel_t dc_channel_from_json(json_t *j)
{
json_t *v = NULL;
dc_channel_t c = dc_channel_new();
goto_if_true(!json_is_object(j), error);
v = json_object_get(j, "id");
goto_if_true(v == NULL || !json_is_string(v), error);
c->id = strdup(json_string_value(v));
v = json_object_get(j, "type");
goto_if_true(v == NULL || !json_is_integer(v), error);
c->type = json_integer_value(v);
v = json_object_get(j, "guild_id");
if (v != NULL && json_is_string(v)) {
c->guild_id = strdup(json_string_value(v));
}
v = json_object_get(j, "name");
if (v == NULL && json_is_string(v)) {
c->name = strdup(json_string_value(v));
}
v = json_object_get(j, "nsfw");
if (v != NULL && json_is_boolean(v)) {
c->nsfw = json_boolean_value(v);
}
v = json_object_get(j, "last_message_id");
if (v != NULL && json_is_string(v)) {
c->last_message_id = strdup(json_string_value(v));
}
v = json_object_get(j, "owner_id");
if (v != NULL && json_is_string(v)) {
c->owner_id = strdup(json_string_value(v));
}
v = json_object_get(j, "parent_id");
if (v != NULL && json_is_string(v)) {
c->parent_id = strdup(json_string_value(v));
}
v = json_object_get(j, "application_id");
if (v != NULL && json_is_string(v)) {
c->application_id = strdup(json_string_value(v));
}
v = json_object_get(j, "recipients");
if (v != NULL && json_is_array(v)) {
json_t *i = NULL;
size_t idx = 0;
json_array_foreach(v, idx, i) {
dc_account_t a = dc_account_from_json(i);
if (a != NULL) {
g_ptr_array_add(c->recipients, a);
}
}
}
return c;
error:
dc_unref(c);
return NULL;
}
json_t *dc_channel_to_json(dc_channel_t c)
{
json_t *j = NULL;
return_if_true(c->id == NULL, NULL);
j = json_object();
return_if_true(j == NULL, NULL);
/* I was so close in making a J_SET() macro for my lazy ass.
*/
json_object_set_new(j, "id", json_string(c->id));
json_object_set_new(j, "type", json_integer(c->type));
/* TODO: tribool to see if it was actually set, or assume "false"
* is a sane default and continue on.
*/
json_object_set_new(j, "nsfw", json_boolean(c->nsfw));
if (c->guild_id != NULL) {
json_object_set_new(j, "guild_id", json_string(c->guild_id));
}
if (c->name != NULL) {
json_object_set_new(j, "name", json_string(c->name));
}
if (c->last_message_id != NULL) {
json_object_set_new(j, "last_message_id",
json_string(c->last_message_id));
}
if (c->owner_id != NULL) {
json_object_set_new(j, "owner_id", json_string(c->owner_id));
}
if (c->parent_id != NULL) {
json_object_set_new(j, "parent_id", json_string(c->parent_id));
}
if (c->application_id != NULL) {
json_object_set_new(j, "application_id",
json_string(c->application_id));
}
if (c->recipients != NULL && c->recipients->len > 0) {
size_t i = 0;
json_t *arr = json_array();
for (i = 0; i < c->recipients->len; i++) {
dc_account_t acc = g_ptr_array_index(c->recipients, i);
json_t *a = dc_account_to_json(acc);
if (a != NULL) {
json_array_append_new(arr, a);
}
}
json_object_set_new(j, "recipients", arr);
}
return j;
}
dc_channel_type_t dc_channel_type(dc_channel_t c)
{
return_if_true(c == NULL, -1);
return c->type;
}
void dc_channel_set_type(dc_channel_t c, dc_channel_type_t t)
{
return_if_true(c == NULL,);
c->type = t;
}

View File

@ -30,10 +30,4 @@
#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)
/* These are internal helper methods, their ABI, and API stability
* is not garuanteed. So please beware
*/
json_t *dc_api_account_to_json(dc_account_t a);
dc_account_t dc_api_account_from_json(json_t *j);
#endif