began work on a msg command

This commit is contained in:
Florian Stinglmayr 2019-07-05 16:40:16 +02:00
parent e2bdd05775
commit a164afe170
16 changed files with 231 additions and 4 deletions

View File

@ -69,11 +69,16 @@ void dc_account_set_token(dc_account_t a, char const *token);
char const *dc_account_token(dc_account_t a);
bool dc_account_has_token(dc_account_t a);
/* compare
*/
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);
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);
int dc_account_friend_state(dc_account_t a);
void dc_account_set_friend_state(dc_account_t a, int state);

View File

@ -4,6 +4,8 @@
#include <stdint.h>
#include <jansson.h>
#include <dc/account.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
@ -50,4 +52,7 @@ 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);
size_t dc_channel_recipients(dc_channel_t c);
dc_account_t dc_channel_nthrecipient(dc_channel_t c, size_t i);
#endif

View File

@ -282,6 +282,13 @@ char const *dc_account_fullname(dc_account_t a)
return a->full;
}
bool dc_account_equal(dc_account_t a, dc_account_t b)
{
return_if_true(a == NULL && b == NULL, true);
return_if_true(a == NULL || b == NULL, false);
return (strcmp(a->full, b->full) == 0);
}
void dc_account_set_friends(dc_account_t a, dc_account_t *friends, size_t len)
{
size_t i = 0;
@ -293,6 +300,21 @@ void dc_account_set_friends(dc_account_t a, dc_account_t *friends, size_t len)
}
}
dc_account_t dc_account_findfriend(dc_account_t a, char const *fullname)
{
size_t i = 0;
return_if_true(a == NULL || fullname == NULL, NULL);
for (i = 0; i < a->friends->len; i++) {
dc_account_t f = g_ptr_array_index(a->friends, i);
if (strcmp(f->full, fullname) == 0) {
return f;
}
}
return NULL;
}
dc_account_t dc_account_nthfriend(dc_account_t a, size_t i)
{
return_if_true(a == NULL || a->friends == NULL, NULL);

View File

@ -18,7 +18,7 @@ bool dc_api_create_channel(dc_api_t api, dc_account_t login,
goto_if_true(url == NULL, cleanup);
/* build a JSON object that contains one array called "recipients":
* {"recipients": ["snowflake#1", "snowflake#N"]}
* {"recipients": ["snowflake#1", ..., "snowflake#N"]}
*/
data = json_object();
array = json_array();
@ -42,6 +42,7 @@ bool dc_api_create_channel(dc_api_t api, dc_account_t login,
goto_if_true(c == NULL, cleanup);
*channel = c;
ret = true;
cleanup:

View File

@ -225,3 +225,16 @@ void dc_channel_set_type(dc_channel_t c, dc_channel_type_t t)
return_if_true(c == NULL,);
c->type = t;
}
size_t dc_channel_recipients(dc_channel_t c)
{
return_if_true(c == NULL || c->recipients == NULL, 0);
return c->recipients->len;
}
dc_account_t dc_channel_nthrecipient(dc_channel_t c, size_t i)
{
return_if_true(c == NULL || c->recipients == NULL, NULL);
return_if_true(i >= c->recipients->len, NULL);
return g_ptr_array_index(c->recipients, i);
}

View File

@ -20,6 +20,7 @@ SET(SOURCES
"src/input.c"
"src/login.c"
"src/mainwindow.c"
"src/msg.c"
"src/ncdc.c"
"src/textview.c"
"src/util.c"

View File

@ -27,5 +27,6 @@ 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_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_msg(ncdc_mainwindow_t n, size_t ac, wchar_t **av);
#endif

View File

@ -14,6 +14,9 @@ ncdc_mainwindow_t ncdc_mainwindow_new(void);
#define LOG(n, ...) ncdc_mainwindow_log(n, __VA_ARGS__)
void ncdc_mainwindow_log(ncdc_mainwindow_t w, wchar_t const *fmt, ...);
GPtrArray *ncdc_mainwindow_views(ncdc_mainwindow_t n);
void ncdc_mainwindow_switchview(ncdc_mainwindow_t n, int idx);
void ncdc_mainwindow_refresh(ncdc_mainwindow_t n);
void ncdc_mainwindow_input_ready(ncdc_mainwindow_t n);

View File

@ -62,6 +62,7 @@ char *w_convert(wchar_t const *w);
wchar_t* wcsndup(const wchar_t* string, size_t maxlen);
size_t w_strlenv(wchar_t **s);
void w_strfreev(wchar_t **s);
wchar_t *w_joinv(wchar_t const **v, size_t len);
wchar_t **w_tokenise(wchar_t const *w);
wchar_t *w_next_tok(wchar_t const *w);
wchar_t const *w_next_word(wchar_t const *w, ssize_t len);

View File

@ -8,6 +8,12 @@ typedef struct ncdc_textview_ *ncdc_textview_t;
ncdc_textview_t ncdc_textview_new(void);
dc_account_t ncdc_textview_account(ncdc_textview_t v);
void ncdc_textview_set_account(ncdc_textview_t v, dc_account_t a);
dc_channel_t ncdc_textview_channel(ncdc_textview_t v);
void ncdc_textview_set_channel(ncdc_textview_t v, dc_channel_t a);
void ncdc_textview_append(ncdc_textview_t v, wchar_t const *w);
wchar_t const *ncdc_textview_nthline(ncdc_textview_t v, size_t i);
void ncdc_textview_render(ncdc_textview_t v, WINDOW *win, int lines, int cols);

View File

@ -4,6 +4,7 @@ ncdc_commands_t cmds[] = {
{ L"/friend", ncdc_cmd_friends },
{ L"/friends", ncdc_cmd_friends },
{ L"/login", ncdc_cmd_login },
{ L"/msg", ncdc_cmd_msg },
{ L"/quit", ncdc_cmd_quit },
{ NULL, NULL }
};

View File

@ -34,6 +34,11 @@ bool ncdc_cmd_login(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
goto cleanup;
}
if (!dc_api_get_userinfo(api, acc, acc)) {
LOG(n, L"login: %ls: failed to get basic user information", av[1]);
goto cleanup;
}
current_account = acc;
LOG(n, L"login: %ls: authentication successful", av[1]);
ret = true;

View File

@ -37,6 +37,9 @@ struct ncdc_mainwindow_
WINDOW *sep2;
ncdc_input_t in;
GPtrArray *views;
int curview;
ncdc_textview_t log;
int focus;
@ -59,7 +62,11 @@ static void ncdc_mainwindow_free(ncdc_mainwindow_t n)
delwin(n->sep2);
dc_unref(n->in);
dc_unref(n->log);
if (n->views != NULL) {
g_ptr_array_unref(n->views);
n->views = NULL;
}
free(n);
}
@ -74,7 +81,11 @@ ncdc_mainwindow_t ncdc_mainwindow_new(void)
ptr->in = ncdc_input_new();
ncdc_input_set_callback(ptr->in, ncdc_mainwindow_callback, ptr);
ptr->views = g_ptr_array_new_with_free_func(
(GDestroyNotify)dc_unref
);
ptr->log = ncdc_textview_new();
g_ptr_array_add(ptr->views, ptr->log);
ptr->guilds = newwin(5, 5, 1, 1);
ptr->chat = newwin(5, 5, 4, 4);
@ -192,11 +203,28 @@ void ncdc_mainwindow_input_ready(ncdc_mainwindow_t n)
}
}
GPtrArray *ncdc_mainwindow_views(ncdc_mainwindow_t n)
{
return n->views;
}
void ncdc_mainwindow_switchview(ncdc_mainwindow_t n, int idx)
{
return_if_true(n == NULL || n->views == NULL,);
return_if_true(idx >= n->views->len,);
n->curview = idx;
}
void ncdc_mainwindow_refresh(ncdc_mainwindow_t n)
{
ncdc_textview_t v = 0;
wnoutrefresh(n->guilds);
ncdc_textview_render(n->log, n->chat, n->chat_h, n->chat_w);
/* render active text view
*/
v = g_ptr_array_index(n->views, n->curview);
ncdc_textview_render(v, n->chat, n->chat_h, n->chat_w);
wnoutrefresh(n->chat);
ncdc_input_draw(n->in, n->input);

79
ncdc/src/msg.c Normal file
View File

@ -0,0 +1,79 @@
#include <ncdc/cmds.h>
#include <ncdc/ncdc.h>
#include <ncdc/textview.h>
bool ncdc_cmd_msg(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
{
return_if_true(ac <= 1, false);
char * target = NULL;
wchar_t *full_message = NULL;
char * message = NULL;
bool ret = false;
dc_channel_t c = NULL;
ncdc_textview_t v = NULL;
size_t i = 0;
if (current_account == NULL || !dc_account_has_token(current_account)) {
LOG(n, L"msg: not logged in");
return false;
}
target = w_convert(av[1]);
goto_if_true(target == NULL, cleanup);
/* find out if the target is a friend we can contact
*/
dc_account_t f = dc_account_findfriend(current_account, target);
if (f == NULL) {
LOG(n, L"msg: no such friend found: \"%s\"", target);
goto cleanup;
}
/* see if we have a channel already, that services that user
*/
for (i = 0; i < ncdc_mainwindow_views(n)->len; i++) {
v = g_ptr_array_index(ncdc_mainwindow_views(n), i);
dc_channel_t chan = ncdc_textview_channel(v);
if (chan != NULL &&
dc_channel_type(chan) == CHANNEL_TYPE_DM_TEXT &&
dc_account_equal(dc_channel_nthrecipient(chan, 1), f)) {
c = dc_ref(chan);
ncdc_mainwindow_switchview(n, i);
break;
}
}
if (c == NULL) {
/* no? create a new window and switch to it
*/
if (!dc_api_create_channel(api, current_account, &f, 1, &c)) {
LOG(n, L"msg: failed to create channel");
goto cleanup;
}
v = ncdc_textview_new();
goto_if_true(v == NULL, cleanup);
ncdc_textview_set_account(v, dc_ref(current_account));
ncdc_textview_set_channel(v, dc_ref(c));
g_ptr_array_add(ncdc_mainwindow_views(n), dc_ref(v));
ncdc_mainwindow_switchview(n, ncdc_mainwindow_views(n)->len-1);
}
ret = true;
cleanup:
dc_unref(c);
dc_unref(v);
free(target);
free(full_message);
free(message);
return ret;
}

View File

@ -4,14 +4,24 @@
struct ncdc_textview_
{
dc_refable_t ref;
GPtrArray *par;
dc_account_t account;
dc_channel_t channel;
};
static void ncdc_textview_free(ncdc_textview_t v)
{
return_if_true(v == NULL,);
dc_unref(v->account);
dc_unref(v->channel);
if (v->par != NULL) {
g_ptr_array_unref(v->par);
}
free(v);
}
@ -31,6 +41,32 @@ ncdc_textview_t ncdc_textview_new(void)
return p;
}
dc_account_t ncdc_textview_account(ncdc_textview_t v)
{
return_if_true(v == NULL, NULL);
return v->account;
}
void ncdc_textview_set_account(ncdc_textview_t v, dc_account_t a)
{
return_if_true(v == NULL || a == NULL,);
dc_unref(v->account);
v->account = dc_ref(a);
}
dc_channel_t ncdc_textview_channel(ncdc_textview_t v)
{
return_if_true(v == NULL, NULL);
return v->channel;
}
void ncdc_textview_set_channel(ncdc_textview_t v, dc_channel_t a)
{
return_if_true(v == NULL || a == NULL,);
dc_unref(v->channel);
v->channel = dc_ref(a);
}
void ncdc_textview_append(ncdc_textview_t v, wchar_t const *w)
{
return_if_true(v == NULL || w == NULL,);

View File

@ -118,6 +118,26 @@ wchar_t **w_tokenise(wchar_t const *str)
return (wchar_t**)g_ptr_array_free(array, FALSE);
}
wchar_t *w_joinv(wchar_t const **v, size_t len)
{
wchar_t *buf = NULL;
size_t buflen = 0;
FILE *f = open_wmemstream(&buf, &buflen);
size_t i = 0;
return_if_true(f == NULL, NULL);
for (i = 0; i < len; i++) {
fwprintf(f, L"%ls", v[i]);
if (i < (len-1)) {
fputwc(' ', f);
}
}
fclose(f);
return buf;
}
char *w_convert(wchar_t const *w)
{
size_t sz = 0;