full friends list support, add remove, and accept
This commit is contained in:
parent
efce6a6543
commit
7f5ceff688
@ -17,6 +17,8 @@ SET(SOURCES
|
|||||||
"include/dc/util.h"
|
"include/dc/util.h"
|
||||||
"src/account.c"
|
"src/account.c"
|
||||||
"src/api.c"
|
"src/api.c"
|
||||||
|
"src/api-friends.c"
|
||||||
|
"src/api-util.c"
|
||||||
"src/apisync.c"
|
"src/apisync.c"
|
||||||
"src/guild.c"
|
"src/guild.c"
|
||||||
"src/loop.c"
|
"src/loop.c"
|
||||||
|
@ -13,14 +13,35 @@ typedef enum {
|
|||||||
/* accountt is a mutual friend
|
/* accountt is a mutual friend
|
||||||
*/
|
*/
|
||||||
FRIEND_STATE_FRIEND = 1,
|
FRIEND_STATE_FRIEND = 1,
|
||||||
/* pending account, the other side hasn't accepted yet
|
/* pending friend request, the other side hasn't accepted yet
|
||||||
*/
|
*/
|
||||||
FRIEND_STATE_PENDING = 4,
|
FRIEND_STATE_PENDING = 3,
|
||||||
} dc_account_friend_states;
|
} dc_account_friend_states;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a given account within the discord system. To start your work,
|
||||||
|
* you will have to create an account object, give it email and password, and
|
||||||
|
* call the dc_api_authenticate() with it. This gives you a login token that
|
||||||
|
* you can use to call other API methods (such as dc_api_get_friends()) for
|
||||||
|
* that account.
|
||||||
|
*
|
||||||
|
* Accounts have a few important attributes that we store:
|
||||||
|
* * ID (or snowflake), a 64 bit ID of the user, that we store as a string.
|
||||||
|
* * username, a string that represents the accounts user name
|
||||||
|
* * discriminator, a number that differentiates users with the same name
|
||||||
|
* * email, for login accounts only
|
||||||
|
* * password, for login accounts only
|
||||||
|
* * friend_state, if the account is someone login account's friend, we store
|
||||||
|
* the relationship in this flag. See the dc_account_friend_state enum for
|
||||||
|
* details.
|
||||||
|
* And one compound attribute:
|
||||||
|
* * fullname, a combination of username and discriminator separated by the
|
||||||
|
* pound sign, e.g. nola#2457
|
||||||
|
*/
|
||||||
|
|
||||||
dc_account_t dc_account_new(void);
|
dc_account_t dc_account_new(void);
|
||||||
dc_account_t dc_account_new2(char const *email, char const *pass);
|
dc_account_t dc_account_new2(char const *email, char const *pass);
|
||||||
dc_account_t dc_account_from_fullid(char const *fullid);
|
dc_account_t dc_account_from_fullname(char const *fullid);
|
||||||
|
|
||||||
void dc_account_set_email(dc_account_t a, char const *email);
|
void dc_account_set_email(dc_account_t a, char const *email);
|
||||||
char const *dc_account_email(dc_account_t a);
|
char const *dc_account_email(dc_account_t a);
|
||||||
@ -37,7 +58,7 @@ char const *dc_account_username(dc_account_t a);
|
|||||||
void dc_account_set_discriminator(dc_account_t a, char const *id);
|
void dc_account_set_discriminator(dc_account_t a, char const *id);
|
||||||
char const *dc_account_discriminator(dc_account_t a);
|
char const *dc_account_discriminator(dc_account_t a);
|
||||||
|
|
||||||
char const *dc_account_full_username(dc_account_t a);
|
char const *dc_account_fullname(dc_account_t a);
|
||||||
|
|
||||||
void dc_account_set_token(dc_account_t a, char const *token);
|
void dc_account_set_token(dc_account_t a, char const *token);
|
||||||
char const *dc_account_token(dc_account_t a);
|
char const *dc_account_token(dc_account_t a);
|
||||||
@ -48,6 +69,7 @@ bool dc_account_has_token(dc_account_t a);
|
|||||||
void dc_account_set_friends(dc_account_t a, dc_account_t *ptr, size_t len);
|
void dc_account_set_friends(dc_account_t a, dc_account_t *ptr, size_t len);
|
||||||
dc_account_t dc_account_nthfriend(dc_account_t a, size_t i);
|
dc_account_t dc_account_nthfriend(dc_account_t a, size_t i);
|
||||||
size_t dc_account_friends_size(dc_account_t a);
|
size_t dc_account_friends_size(dc_account_t a);
|
||||||
|
|
||||||
int dc_account_friend_state(dc_account_t a);
|
int dc_account_friend_state(dc_account_t a);
|
||||||
void dc_account_set_friend_state(dc_account_t a, int state);
|
void dc_account_set_friend_state(dc_account_t a, int state);
|
||||||
|
|
||||||
|
@ -70,4 +70,21 @@ bool dc_api_get_friends(dc_api_t api, dc_account_t login);
|
|||||||
*/
|
*/
|
||||||
bool dc_api_add_friend(dc_api_t api, dc_account_t login, dc_account_t friend);
|
bool dc_api_add_friend(dc_api_t api, dc_account_t login, dc_account_t friend);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a given account as a friend to the friends list. Warning: The
|
||||||
|
* account ID (aka account snowflake) is required to perform this operation,
|
||||||
|
* so you cannot just do dc_account_from_fullname(). Suggestion: use an object
|
||||||
|
* from the actual friends list of the account login.
|
||||||
|
*/
|
||||||
|
bool dc_api_remove_friend(dc_api_t api, dc_account_t login,
|
||||||
|
dc_account_t friend);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accepts someone who has sent a friend request to you, as a friend. Warning:
|
||||||
|
* The object "friend" requires an account ID (aka snowflake) for this method
|
||||||
|
* to work. You should take this object perhaps from the "login"'s friend list.
|
||||||
|
*/
|
||||||
|
bool dc_api_accept_friend(dc_api_t api, dc_account_t login,
|
||||||
|
dc_account_t friend);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -84,7 +84,7 @@ dc_account_t dc_account_new2(char const *email, char const *pass)
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
dc_account_t dc_account_from_fullid(char const *fullid)
|
dc_account_t dc_account_from_fullname(char const *fullid)
|
||||||
{
|
{
|
||||||
return_if_true(fullid == NULL, NULL);
|
return_if_true(fullid == NULL, NULL);
|
||||||
|
|
||||||
@ -226,7 +226,7 @@ char const *dc_account_discriminator(dc_account_t a)
|
|||||||
return a->discriminator;
|
return a->discriminator;
|
||||||
}
|
}
|
||||||
|
|
||||||
char const *dc_account_full_username(dc_account_t a)
|
char const *dc_account_fullname(dc_account_t a)
|
||||||
{
|
{
|
||||||
return_if_true(a == NULL, NULL);
|
return_if_true(a == NULL, NULL);
|
||||||
return a->full;
|
return a->full;
|
||||||
|
150
libdc/src/api-friends.c
Normal file
150
libdc/src/api-friends.c
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
#include <dc/api.h>
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
bool dc_api_get_friends(dc_api_t api, dc_account_t login)
|
||||||
|
{
|
||||||
|
char const *url = "users/@me/relationships";
|
||||||
|
json_t *reply = NULL, *c = NULL, *val = NULL;
|
||||||
|
bool ret = false;
|
||||||
|
size_t i = 0;
|
||||||
|
GPtrArray *f = g_ptr_array_new_with_free_func((GDestroyNotify)dc_unref);
|
||||||
|
|
||||||
|
return_if_true(api == NULL, false);
|
||||||
|
return_if_true(login == NULL, false);
|
||||||
|
|
||||||
|
reply = dc_api_call_sync(api, "GET", dc_account_token(login), url, NULL);
|
||||||
|
goto_if_true(reply == NULL, cleanup);
|
||||||
|
|
||||||
|
goto_if_true(!json_is_array(reply), cleanup);
|
||||||
|
|
||||||
|
json_array_foreach(reply, i, c) {
|
||||||
|
/* the return is an array of objects, with a "user" member
|
||||||
|
* type 1 is probably a friend
|
||||||
|
*/
|
||||||
|
val = json_object_get(c, "user");
|
||||||
|
if (val == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
dc_account_t a = dc_api_account_from_json(val);
|
||||||
|
if (a == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read the type also known as "typ"
|
||||||
|
*/
|
||||||
|
val = json_object_get(c, "type");
|
||||||
|
if (val != NULL && json_is_integer(val)) {
|
||||||
|
int state = json_integer_value(val);
|
||||||
|
dc_account_set_friend_state(a, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ptr_array_add(f, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f->len == 0) {
|
||||||
|
/* me_irl :-(
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
dc_account_set_friends(login, (dc_account_t*)f->pdata, f->len);
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
g_ptr_array_free(f, FALSE);
|
||||||
|
json_decref(reply);
|
||||||
|
reply = NULL;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dc_api_remove_friend(dc_api_t api, dc_account_t login, dc_account_t friend)
|
||||||
|
{
|
||||||
|
char *url = NULL;
|
||||||
|
json_t *reply = NULL, *post = NULL;
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
return_if_true(api == NULL, false);
|
||||||
|
return_if_true(login == NULL || friend == NULL, false);
|
||||||
|
return_if_true(dc_account_id(friend) == NULL, false);
|
||||||
|
|
||||||
|
asprintf(&url, "users/@me/relationships/%s", dc_account_id(friend));
|
||||||
|
|
||||||
|
post = dc_api_account_to_json(friend);
|
||||||
|
return_if_true(post == NULL, false);
|
||||||
|
|
||||||
|
reply = dc_api_call_sync(api, "DELETE", dc_account_token(login), url, post);
|
||||||
|
/* if no data comes back, then the whole thing was a success
|
||||||
|
*/
|
||||||
|
goto_if_true(reply != NULL, cleanup);
|
||||||
|
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
free(url);
|
||||||
|
json_decref(post);
|
||||||
|
json_decref(reply);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dc_api_accept_friend(dc_api_t api, dc_account_t login, dc_account_t friend)
|
||||||
|
{
|
||||||
|
char *url = NULL;
|
||||||
|
json_t *reply = NULL, *post = NULL;
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
return_if_true(api == NULL, false);
|
||||||
|
return_if_true(login == NULL || friend == NULL, false);
|
||||||
|
return_if_true(dc_account_id(friend) == NULL, false);
|
||||||
|
|
||||||
|
asprintf(&url, "users/@me/relationships/%s", dc_account_id(friend));
|
||||||
|
|
||||||
|
post = dc_api_account_to_json(friend);
|
||||||
|
return_if_true(post == NULL, false);
|
||||||
|
|
||||||
|
reply = dc_api_call_sync(api, "PUT", dc_account_token(login), url, post);
|
||||||
|
/* no data = successful
|
||||||
|
*/
|
||||||
|
goto_if_true(reply != NULL, cleanup);
|
||||||
|
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
free(url);
|
||||||
|
json_decref(post);
|
||||||
|
json_decref(reply);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dc_api_add_friend(dc_api_t api, dc_account_t login, dc_account_t friend)
|
||||||
|
{
|
||||||
|
char const *url = "users/@me/relationships";
|
||||||
|
json_t *reply = NULL, *post = NULL;
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
return_if_true(api == NULL, false);
|
||||||
|
return_if_true(login == NULL, false);
|
||||||
|
|
||||||
|
post = dc_api_account_to_json(friend);
|
||||||
|
return_if_true(post == NULL, false);
|
||||||
|
|
||||||
|
reply = dc_api_call_sync(api, "POST", dc_account_token(login), url, post);
|
||||||
|
/* apparently if no data comes back, then the whole thing was a success
|
||||||
|
*/
|
||||||
|
goto_if_true(reply != NULL, cleanup);
|
||||||
|
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
json_decref(post);
|
||||||
|
json_decref(reply);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
53
libdc/src/api-util.c
Normal file
53
libdc/src/api-util.c
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#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;
|
||||||
|
}
|
138
libdc/src/api.c
138
libdc/src/api.c
@ -322,56 +322,6 @@ cleanup:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static json_t *dc_api_user_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool dc_api_get_userinfo(dc_api_t api, dc_account_t login,
|
bool dc_api_get_userinfo(dc_api_t api, dc_account_t login,
|
||||||
dc_account_t user)
|
dc_account_t user)
|
||||||
{
|
{
|
||||||
@ -414,94 +364,6 @@ cleanup:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dc_api_get_friends(dc_api_t api, dc_account_t login)
|
|
||||||
{
|
|
||||||
char const *url = "users/@me/relationships";
|
|
||||||
json_t *reply = NULL, *c = NULL, *val = NULL;
|
|
||||||
bool ret = false;
|
|
||||||
size_t i = 0;
|
|
||||||
GPtrArray *f = g_ptr_array_new_with_free_func((GDestroyNotify)dc_unref);
|
|
||||||
|
|
||||||
return_if_true(api == NULL, false);
|
|
||||||
return_if_true(login == NULL, false);
|
|
||||||
|
|
||||||
reply = dc_api_call_sync(api, "GET", dc_account_token(login), url, NULL);
|
|
||||||
goto_if_true(reply == NULL, cleanup);
|
|
||||||
|
|
||||||
goto_if_true(!json_is_array(reply), cleanup);
|
|
||||||
|
|
||||||
json_array_foreach(reply, i, c) {
|
|
||||||
/* the return is an array of objects, with a "user" member
|
|
||||||
* type 1 is probably a friend
|
|
||||||
*/
|
|
||||||
val = json_object_get(c, "user");
|
|
||||||
if (val == NULL) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
dc_account_t a = dc_api_account_from_json(val);
|
|
||||||
if (a == NULL) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* read the type also known as "typ"
|
|
||||||
*/
|
|
||||||
val = json_object_get(c, "type");
|
|
||||||
if (val != NULL && json_is_integer(val)) {
|
|
||||||
int state = json_integer_value(val);
|
|
||||||
dc_account_set_friend_state(a, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_ptr_array_add(f, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f->len == 0) {
|
|
||||||
/* me_irl :-(
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
dc_account_set_friends(login, (dc_account_t*)f->pdata, f->len);
|
|
||||||
ret = true;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
|
|
||||||
g_ptr_array_free(f, FALSE);
|
|
||||||
json_decref(reply);
|
|
||||||
reply = NULL;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a given account as a friend to the friends list
|
|
||||||
*/
|
|
||||||
bool dc_api_add_friend(dc_api_t api, dc_account_t login, dc_account_t friend)
|
|
||||||
{
|
|
||||||
char const *url = "users/@me/relationships";
|
|
||||||
json_t *reply = NULL, *post = NULL;
|
|
||||||
bool ret = false;
|
|
||||||
|
|
||||||
return_if_true(api == NULL, false);
|
|
||||||
return_if_true(login == NULL, false);
|
|
||||||
|
|
||||||
post = dc_api_user_to_json(friend);
|
|
||||||
return_if_true(post == NULL, false);
|
|
||||||
|
|
||||||
reply = dc_api_call_sync(api, "POST", dc_account_token(login), url, post);
|
|
||||||
/* apparently if no data comes back, then the whole thing was a success
|
|
||||||
*/
|
|
||||||
goto_if_true(reply != NULL, cleanup);
|
|
||||||
|
|
||||||
ret = true;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
|
|
||||||
json_decref(post);
|
|
||||||
json_decref(reply);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool dc_api_get_userguilds(dc_api_t api, dc_account_t login, GPtrArray **out)
|
bool dc_api_get_userguilds(dc_api_t api, dc_account_t login, GPtrArray **out)
|
||||||
{
|
{
|
||||||
char const *url = "users/@me/guilds";
|
char const *url = "users/@me/guilds";
|
||||||
|
@ -22,10 +22,18 @@
|
|||||||
#include <event2/thread.h>
|
#include <event2/thread.h>
|
||||||
|
|
||||||
#include <dc/util.h>
|
#include <dc/util.h>
|
||||||
|
#include <dc/refable.h>
|
||||||
|
#include <dc/account.h>
|
||||||
|
|
||||||
//#define DEBUG
|
//#define DEBUG
|
||||||
|
|
||||||
#define return_if_true(v,r) do { if (v) return r; } while(0)
|
#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 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
|
#endif
|
||||||
|
@ -19,6 +19,11 @@ bool ncdc_dispatch_deinit(void);
|
|||||||
|
|
||||||
bool ncdc_dispatch(ncdc_mainwindow_t n, wchar_t const *s);
|
bool ncdc_dispatch(ncdc_mainwindow_t n, wchar_t const *s);
|
||||||
|
|
||||||
|
/* find a given command in a list of commands, helpful if your command has
|
||||||
|
* sub commands. for example usage see the friends command
|
||||||
|
*/
|
||||||
|
ncdc_commands_t *ncdc_find_cmd(ncdc_commands_t *cmds, wchar_t const *name);
|
||||||
|
|
||||||
bool ncdc_cmd_friends(ncdc_mainwindow_t n, size_t ac, wchar_t **av);
|
bool ncdc_cmd_friends(ncdc_mainwindow_t n, size_t ac, wchar_t **av);
|
||||||
bool ncdc_cmd_login(ncdc_mainwindow_t n, size_t ac, wchar_t **av);
|
bool ncdc_cmd_login(ncdc_mainwindow_t n, size_t ac, wchar_t **av);
|
||||||
bool ncdc_cmd_quit(ncdc_mainwindow_t n, size_t ac, wchar_t **av);
|
bool ncdc_cmd_quit(ncdc_mainwindow_t n, size_t ac, wchar_t **av);
|
||||||
|
@ -89,26 +89,29 @@ bool ncdc_dispatch_deinit(void)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ncdc_commands_t *ncdc_find_cmd(ncdc_commands_t *cmds, wchar_t const *name)
|
||||||
|
{
|
||||||
|
ncdc_commands_t *it = NULL;
|
||||||
|
|
||||||
|
for (it = cmds; it->name != NULL; it++) {
|
||||||
|
if (wcscmp(it->name, name) == 0) {
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
bool ncdc_dispatch(ncdc_mainwindow_t n, wchar_t const *s)
|
bool ncdc_dispatch(ncdc_mainwindow_t n, wchar_t const *s)
|
||||||
{
|
{
|
||||||
wchar_t **tokens = NULL;
|
wchar_t **tokens = NULL;
|
||||||
size_t i = 0, tokenlen = 0;
|
|
||||||
ncdc_commands_t *it = NULL;
|
ncdc_commands_t *it = NULL;
|
||||||
queue_item *item = NULL;
|
queue_item *item = NULL;
|
||||||
|
|
||||||
tokens = w_tokenise(s);
|
tokens = w_tokenise(s);
|
||||||
return_if_true(tokens == NULL, false);
|
return_if_true(tokens == NULL, false);
|
||||||
|
|
||||||
tokenlen = wcslen(tokens[0]);
|
if ((it = ncdc_find_cmd(cmds, tokens[0])) == NULL) {
|
||||||
|
|
||||||
for (i = 0; cmds[i].name != NULL; i++) {
|
|
||||||
if (wcsncmp(cmds[i].name, tokens[0], tokenlen) == 0) {
|
|
||||||
it = cmds+i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (it == NULL) {
|
|
||||||
/* no such command
|
/* no such command
|
||||||
*/
|
*/
|
||||||
LOG(n, L"error: no such command \"%ls\"", tokens[0]);
|
LOG(n, L"error: no such command \"%ls\"", tokens[0]);
|
||||||
|
@ -6,7 +6,7 @@ ncdc_cmd_friends_list(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
|
|||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
wchar_t c = ' ';
|
char c = ' ';
|
||||||
|
|
||||||
ret = dc_api_get_friends(api, current_account);
|
ret = dc_api_get_friends(api, current_account);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
@ -21,7 +21,7 @@ ncdc_cmd_friends_list(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
|
|||||||
case FRIEND_STATE_PENDING: c = 'P'; break;
|
case FRIEND_STATE_PENDING: c = 'P'; break;
|
||||||
default: c = ' '; break;
|
default: c = ' '; break;
|
||||||
}
|
}
|
||||||
LOG(n, L"%lc %s", c, dc_account_full_username(acc));
|
LOG(n, L" %c %s", c, dc_account_fullname(acc));
|
||||||
}
|
}
|
||||||
LOG(n, L"End of /FRIENDS list");
|
LOG(n, L"End of /FRIENDS list");
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ ncdc_cmd_friends_add(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
|
|||||||
name = w_convert(av[1]);
|
name = w_convert(av[1]);
|
||||||
return_if_true(name == NULL, false);
|
return_if_true(name == NULL, false);
|
||||||
|
|
||||||
friend = dc_account_from_fullid(name);
|
friend = dc_account_from_fullname(name);
|
||||||
if (friend == NULL) {
|
if (friend == NULL) {
|
||||||
LOG(n, L"friends: add: invalid username given, use the full ID");
|
LOG(n, L"friends: add: invalid username given, use the full ID");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -53,7 +53,7 @@ ncdc_cmd_friends_add(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(n, L"friends: add: request for friendship sent");
|
LOG(n, L"friends: add: request for friendship sent to %s", name);
|
||||||
ret = true;
|
ret = true;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
@ -64,9 +64,105 @@ cleanup:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
ncdc_cmd_friends_remove(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
|
||||||
|
{
|
||||||
|
char *name = NULL;
|
||||||
|
dc_account_t friend = NULL;
|
||||||
|
bool ret = false;
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
if (ac <= 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = w_convert(av[1]);
|
||||||
|
return_if_true(name == NULL, false);
|
||||||
|
|
||||||
|
for (i = 0; i < dc_account_friends_size(current_account); i++) {
|
||||||
|
dc_account_t cur = dc_account_nthfriend(current_account, i);
|
||||||
|
if (strcmp(dc_account_fullname(cur), name) == 0) {
|
||||||
|
friend = cur;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (friend == NULL) {
|
||||||
|
LOG(n, L"friends: remove: no such friend in friend's list");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dc_api_remove_friend(api, current_account, friend)) {
|
||||||
|
LOG(n, L"friends: remove: failed to remove friend");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(n, L"friends: remove: friend %s removed", name);
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
free(name);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
ncdc_cmd_friends_accept(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
|
||||||
|
{
|
||||||
|
char *name = NULL;
|
||||||
|
dc_account_t friend = NULL;
|
||||||
|
bool ret = false;
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
if (ac <= 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = w_convert(av[1]);
|
||||||
|
return_if_true(name == NULL, false);
|
||||||
|
|
||||||
|
for (i = 0; i < dc_account_friends_size(current_account); i++) {
|
||||||
|
dc_account_t cur = dc_account_nthfriend(current_account, i);
|
||||||
|
if (strcmp(dc_account_fullname(cur), name) == 0 &&
|
||||||
|
dc_account_friend_state(cur) == FRIEND_STATE_PENDING) {
|
||||||
|
friend = cur;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (friend == NULL) {
|
||||||
|
LOG(n, L"friends: accept: no such pending friend on the list");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dc_api_accept_friend(api, current_account, friend)) {
|
||||||
|
LOG(n, L"friends: accept: failed to accept friend");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(n, L"friends: accept: friend %s accepted", name);
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
free(name);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ncdc_commands_t subcmds[] = {
|
||||||
|
{ L"accept", ncdc_cmd_friends_accept },
|
||||||
|
{ L"add", ncdc_cmd_friends_add },
|
||||||
|
{ L"list", ncdc_cmd_friends_list },
|
||||||
|
{ L"remove", ncdc_cmd_friends_remove },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
bool ncdc_cmd_friends(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
|
bool ncdc_cmd_friends(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
|
||||||
{
|
{
|
||||||
wchar_t *subcmd = NULL;
|
wchar_t *subcmd = NULL;
|
||||||
|
ncdc_commands_t *it = NULL;
|
||||||
|
|
||||||
if (current_account == NULL ||
|
if (current_account == NULL ||
|
||||||
!dc_account_has_token(current_account)) {
|
!dc_account_has_token(current_account)) {
|
||||||
@ -83,13 +179,10 @@ bool ncdc_cmd_friends(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
|
|||||||
--ac;
|
--ac;
|
||||||
++av;
|
++av;
|
||||||
|
|
||||||
if (wcscmp(subcmd, L"list") == 0) {
|
if ((it = ncdc_find_cmd(subcmds, subcmd)) == NULL) {
|
||||||
return ncdc_cmd_friends_list(n, ac, av);
|
LOG(n, L"friends: no such subcommand \"%ls\"", subcmd);
|
||||||
} else if (wcscmp(subcmd, L"add") == 0) {
|
|
||||||
return ncdc_cmd_friends_add(n, ac, av);
|
|
||||||
} else {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return it->handler(n, ac, av);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user