began work on a msg command
This commit is contained in:
parent
e2bdd05775
commit
a164afe170
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 }
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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
79
ncdc/src/msg.c
Normal 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;
|
||||
}
|
@ -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,);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user