implement message sending to channels
This commit is contained in:
parent
0c9432c269
commit
b8fa202ce3
@ -90,6 +90,12 @@ bool dc_api_create_channel(dc_api_t api, dc_account_t login,
|
||||
*/
|
||||
bool dc_api_get_messages(dc_api_t api, dc_account_t login, dc_channel_t c);
|
||||
|
||||
/**
|
||||
* post a message to the given channel
|
||||
*/
|
||||
bool dc_api_post_message(dc_api_t api, dc_account_t login,
|
||||
dc_channel_t c, dc_message_t m);
|
||||
|
||||
/**
|
||||
* Fetch a list of friends of the login account "login". The friends are stored
|
||||
* within the login object.
|
||||
|
@ -10,6 +10,7 @@ struct dc_message_;
|
||||
typedef struct dc_message_ *dc_message_t;
|
||||
|
||||
dc_message_t dc_message_new(void);
|
||||
dc_message_t dc_message_new_content(char const *s, int len);
|
||||
dc_message_t dc_message_from_json(json_t *j);
|
||||
json_t *dc_message_to_json(dc_message_t m);
|
||||
|
||||
|
@ -52,6 +52,12 @@ bool dc_session_has_token(dc_session_t s);
|
||||
*/
|
||||
dc_account_t dc_session_me(dc_session_t s);
|
||||
|
||||
/**
|
||||
* Return the API handle in use by the session. Do not unref the reference
|
||||
* and if you need it for something else, dc_ref() it yourself.
|
||||
*/
|
||||
dc_api_t dc_session_api(dc_session_t s);
|
||||
|
||||
/**
|
||||
* access to the internal account cache
|
||||
*/
|
||||
|
@ -2,6 +2,36 @@
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
bool dc_api_post_message(dc_api_t api, dc_account_t login,
|
||||
dc_channel_t c, dc_message_t m)
|
||||
{
|
||||
bool ret = false;
|
||||
char *url = NULL;
|
||||
json_t *j = NULL, *reply = NULL;
|
||||
|
||||
return_if_true(api == NULL || login == NULL || m == NULL, false);
|
||||
return_if_true(dc_message_content(m) == NULL, false);
|
||||
|
||||
asprintf(&url, "channels/%s/messages", dc_channel_id(c));
|
||||
goto_if_true(url == NULL, cleanup);
|
||||
|
||||
j = dc_message_to_json(m);
|
||||
goto_if_true(j == NULL, cleanup);
|
||||
|
||||
reply = dc_api_call_sync(api, "POST", TOKEN(login), url, j);
|
||||
goto_if_true(reply != NULL, cleanup);
|
||||
|
||||
ret = true;
|
||||
|
||||
cleanup:
|
||||
|
||||
free(url);
|
||||
json_decref(j);
|
||||
json_decref(reply);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool dc_api_get_messages(dc_api_t api, dc_account_t login, dc_channel_t c)
|
||||
{
|
||||
bool ret = false;
|
||||
|
@ -40,6 +40,24 @@ dc_message_t dc_message_new(void)
|
||||
return dc_ref(m);
|
||||
}
|
||||
|
||||
dc_message_t dc_message_new_content(char const *s, int len)
|
||||
{
|
||||
dc_message_t m = dc_message_new();
|
||||
return_if_true(m == NULL, NULL);
|
||||
|
||||
if (len < 0) {
|
||||
len = strlen(s);
|
||||
}
|
||||
|
||||
m->content = strndup(s, len);
|
||||
if (m->content == NULL) {
|
||||
dc_unref(m);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
dc_message_t dc_message_from_json(json_t *j)
|
||||
{
|
||||
dc_message_t m = NULL;
|
||||
|
@ -227,6 +227,12 @@ bool dc_session_has_token(dc_session_t s)
|
||||
return dc_account_has_token(s->login);
|
||||
}
|
||||
|
||||
dc_api_t dc_session_api(dc_session_t s)
|
||||
{
|
||||
return_if_true(s == NULL, NULL);
|
||||
return s->api;
|
||||
}
|
||||
|
||||
dc_account_t dc_session_me(dc_session_t s)
|
||||
{
|
||||
return_if_true(s == NULL, NULL);
|
||||
|
@ -23,6 +23,7 @@ SET(SOURCES
|
||||
"src/mainwindow.c"
|
||||
"src/msg.c"
|
||||
"src/ncdc.c"
|
||||
"src/post.c"
|
||||
"src/textview.c"
|
||||
"src/util.c"
|
||||
)
|
||||
|
@ -4,8 +4,14 @@
|
||||
#include <ncdc/ncdc.h>
|
||||
#include <ncdc/mainwindow.h>
|
||||
|
||||
/**
|
||||
* n .. the main window handle
|
||||
* ac,av .. the full string parsed up along white spaces
|
||||
* f .. the full string, without the /command bit
|
||||
*/
|
||||
typedef bool (*ncdc_command_t)(ncdc_mainwindow_t n,
|
||||
size_t argc, wchar_t **argv);
|
||||
size_t argc, wchar_t **argv,
|
||||
wchar_t const *f);
|
||||
|
||||
typedef struct {
|
||||
wchar_t const *name;
|
||||
@ -24,10 +30,11 @@ bool ncdc_dispatch(ncdc_mainwindow_t n, wchar_t const *s);
|
||||
*/
|
||||
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_logout(ncdc_mainwindow_t n, size_t ac, wchar_t **av);
|
||||
bool ncdc_cmd_msg(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_friends(ncdc_mainwindow_t n, size_t ac, wchar_t **av, wchar_t const *f);
|
||||
bool ncdc_cmd_login(ncdc_mainwindow_t n, size_t ac, wchar_t **av, wchar_t const *f);
|
||||
bool ncdc_cmd_logout(ncdc_mainwindow_t n, size_t ac, wchar_t **av, wchar_t const *f);
|
||||
bool ncdc_cmd_msg(ncdc_mainwindow_t n, size_t ac, wchar_t **av, wchar_t const *f);
|
||||
bool ncdc_cmd_post(ncdc_mainwindow_t n, size_t ac, wchar_t **av, wchar_t const *f);
|
||||
bool ncdc_cmd_quit(ncdc_mainwindow_t n, size_t ac, wchar_t **av, wchar_t const *f);
|
||||
|
||||
#endif
|
||||
|
@ -15,6 +15,7 @@ ncdc_mainwindow_t ncdc_mainwindow_new(void);
|
||||
void ncdc_mainwindow_log(ncdc_mainwindow_t w, wchar_t const *fmt, ...);
|
||||
|
||||
GPtrArray *ncdc_mainwindow_views(ncdc_mainwindow_t n);
|
||||
dc_channel_t ncdc_mainwindow_current_channel(ncdc_mainwindow_t n);
|
||||
void ncdc_mainwindow_switchview(ncdc_mainwindow_t n, int idx);
|
||||
|
||||
void ncdc_mainwindow_refresh(ncdc_mainwindow_t n);
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <wctype.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -6,6 +6,7 @@ ncdc_commands_t cmds[] = {
|
||||
{ L"/login", ncdc_cmd_login },
|
||||
{ L"/logout", ncdc_cmd_logout },
|
||||
{ L"/msg", ncdc_cmd_msg },
|
||||
{ L"/post", ncdc_cmd_post },
|
||||
{ L"/quit", ncdc_cmd_quit },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
@ -17,6 +18,7 @@ static pthread_cond_t cnd;
|
||||
|
||||
typedef struct {
|
||||
ncdc_commands_t *cmd;
|
||||
wchar_t *f;
|
||||
size_t ac;
|
||||
wchar_t **av;
|
||||
ncdc_mainwindow_t mainwindow;
|
||||
@ -43,9 +45,12 @@ static void *async_dispatcher(void *arg)
|
||||
} else {
|
||||
/* call the handler
|
||||
*/
|
||||
item->cmd->handler(item->mainwindow, item->ac, item->av);
|
||||
item->cmd->handler(item->mainwindow, item->ac,
|
||||
item->av, item->f
|
||||
);
|
||||
|
||||
w_strfreev(item->av);
|
||||
free(item->f);
|
||||
free(item);
|
||||
}
|
||||
}
|
||||
@ -109,6 +114,8 @@ bool ncdc_dispatch(ncdc_mainwindow_t n, wchar_t const *s)
|
||||
wchar_t **tokens = NULL;
|
||||
ncdc_commands_t *it = NULL;
|
||||
queue_item *item = NULL;
|
||||
wchar_t *f = NULL;
|
||||
size_t len = 0, cmdlen = 0;
|
||||
|
||||
tokens = w_tokenise(s);
|
||||
return_if_true(tokens == NULL, false);
|
||||
@ -121,12 +128,21 @@ bool ncdc_dispatch(ncdc_mainwindow_t n, wchar_t const *s)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* make a complete string without the /command part
|
||||
*/
|
||||
len = wcslen(s);
|
||||
cmdlen = wcslen(it->name);
|
||||
f = wcsdup(s);
|
||||
return_if_true(f == NULL, false);
|
||||
memmove(f, f+cmdlen, len-cmdlen);
|
||||
|
||||
item = calloc(1, sizeof(queue_item));
|
||||
|
||||
item->ac = w_strlenv(tokens);
|
||||
item->av = tokens;
|
||||
item->cmd = it;
|
||||
item->mainwindow = n;
|
||||
item->f = f;
|
||||
|
||||
pthread_mutex_lock(&mtx);
|
||||
g_queue_push_tail(queue, item);
|
||||
@ -136,7 +152,8 @@ bool ncdc_dispatch(ncdc_mainwindow_t n, wchar_t const *s)
|
||||
return true;
|
||||
}
|
||||
|
||||
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, wchar_t const *f)
|
||||
{
|
||||
exit_main();
|
||||
return true;
|
||||
|
@ -2,7 +2,8 @@
|
||||
#include <ncdc/ncdc.h>
|
||||
|
||||
static bool
|
||||
ncdc_cmd_friends_list(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
|
||||
ncdc_cmd_friends_list(ncdc_mainwindow_t n, size_t ac,
|
||||
wchar_t **av, wchar_t const *f)
|
||||
{
|
||||
size_t i = 0;
|
||||
char c = ' ';
|
||||
@ -23,7 +24,8 @@ ncdc_cmd_friends_list(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
|
||||
}
|
||||
|
||||
static bool
|
||||
ncdc_cmd_friends_add(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
|
||||
ncdc_cmd_friends_add(ncdc_mainwindow_t n, size_t ac,
|
||||
wchar_t **av, wchar_t const *f)
|
||||
{
|
||||
char *name = NULL;
|
||||
dc_account_t friend = NULL;
|
||||
@ -60,7 +62,8 @@ cleanup:
|
||||
}
|
||||
|
||||
static bool
|
||||
ncdc_cmd_friends_remove(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
|
||||
ncdc_cmd_friends_remove(ncdc_mainwindow_t n, size_t ac,
|
||||
wchar_t **av, wchar_t const *f)
|
||||
{
|
||||
char *name = NULL;
|
||||
dc_account_t friend = NULL;
|
||||
@ -104,7 +107,8 @@ cleanup:
|
||||
}
|
||||
|
||||
static bool
|
||||
ncdc_cmd_friends_accept(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
|
||||
ncdc_cmd_friends_accept(ncdc_mainwindow_t n, size_t ac,
|
||||
wchar_t **av, wchar_t const *f)
|
||||
{
|
||||
char *name = NULL;
|
||||
dc_account_t friend = NULL;
|
||||
@ -156,7 +160,8 @@ static ncdc_commands_t subcmds[] = {
|
||||
{ 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 const *f)
|
||||
{
|
||||
wchar_t *subcmd = NULL;
|
||||
ncdc_commands_t *it = NULL;
|
||||
@ -167,7 +172,7 @@ bool ncdc_cmd_friends(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
|
||||
}
|
||||
|
||||
if (ac <= 1) {
|
||||
return ncdc_cmd_friends_list(n, ac, av);
|
||||
return ncdc_cmd_friends_list(n, ac, av, f);
|
||||
}
|
||||
|
||||
subcmd = av[1];
|
||||
@ -180,5 +185,5 @@ bool ncdc_cmd_friends(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
|
||||
return false;
|
||||
}
|
||||
|
||||
return it->handler(n, ac, av);
|
||||
return it->handler(n, ac, av, f);
|
||||
}
|
||||
|
@ -2,7 +2,8 @@
|
||||
#include <ncdc/ncdc.h>
|
||||
#include <ncdc/config.h>
|
||||
|
||||
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, wchar_t const *f)
|
||||
{
|
||||
char *arg = NULL;
|
||||
bool ret = false;
|
||||
|
@ -2,7 +2,8 @@
|
||||
#include <ncdc/ncdc.h>
|
||||
#include <ncdc/config.h>
|
||||
|
||||
bool ncdc_cmd_logout(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
|
||||
bool ncdc_cmd_logout(ncdc_mainwindow_t n, size_t ac,
|
||||
wchar_t **av, wchar_t const *f)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
|
@ -110,16 +110,25 @@ ncdc_mainwindow_callback(ncdc_input_t i, wchar_t const *s,
|
||||
size_t len, void *arg)
|
||||
{
|
||||
ncdc_mainwindow_t mainwin = (ncdc_mainwindow_t)arg;
|
||||
bool ret = false;
|
||||
|
||||
if (s != NULL && s[0] == '/') {
|
||||
if (s[1] == '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ncdc_dispatch(mainwin, s);
|
||||
if (s == NULL || s[0] == '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
if (s[0] == '/') {
|
||||
ret = ncdc_dispatch(mainwin, s);
|
||||
} else {
|
||||
wchar_t *post = calloc(wcslen(s)+6, sizeof(wchar_t));
|
||||
|
||||
wcscat(post, L"/post ");
|
||||
wcscat(post, s);
|
||||
|
||||
ret = ncdc_dispatch(mainwin, post);
|
||||
free(post);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ncdc_mainwindow_resize(ncdc_mainwindow_t n)
|
||||
@ -331,3 +340,13 @@ void ncdc_mainwindow_leftview(ncdc_mainwindow_t n)
|
||||
return_if_true(n == NULL,);
|
||||
n->curview = (n->curview - 1) % n->views->len;
|
||||
}
|
||||
|
||||
dc_channel_t ncdc_mainwindow_current_channel(ncdc_mainwindow_t n)
|
||||
{
|
||||
return_if_true(n == NULL, NULL);
|
||||
ncdc_textview_t view = g_ptr_array_index(n->views, n->curview);
|
||||
/* can't post to the log channel, that's for internal use only
|
||||
*/
|
||||
return_if_true(view == n->log, NULL);
|
||||
return ncdc_textview_channel(view);
|
||||
}
|
||||
|
@ -2,13 +2,15 @@
|
||||
#include <ncdc/ncdc.h>
|
||||
#include <ncdc/textview.h>
|
||||
|
||||
bool ncdc_cmd_msg(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
|
||||
bool ncdc_cmd_msg(ncdc_mainwindow_t n, size_t ac,
|
||||
wchar_t **av, wchar_t const *fullmsg)
|
||||
{
|
||||
return_if_true(ac <= 1, false);
|
||||
|
||||
char * target = NULL;
|
||||
wchar_t *full_message = NULL;
|
||||
char * message = NULL;
|
||||
dc_message_t m = NULL;
|
||||
bool ret = false;
|
||||
dc_channel_t c = NULL;
|
||||
ncdc_textview_t v = NULL;
|
||||
@ -64,15 +66,34 @@ bool ncdc_cmd_msg(ncdc_mainwindow_t n, size_t ac, wchar_t **av)
|
||||
ncdc_mainwindow_switchview(n, ncdc_mainwindow_views(n)->len-1);
|
||||
}
|
||||
|
||||
if (ac > 2) {
|
||||
/* also post the rest of the content as a message to the channel
|
||||
*/
|
||||
full_message = wcsstr(fullmsg, av[2]);
|
||||
goto_if_true(full_message == NULL, cleanup);
|
||||
|
||||
message = w_convert(full_message);
|
||||
goto_if_true(message == NULL, cleanup);
|
||||
|
||||
m = dc_message_new_content(message, -1);
|
||||
goto_if_true(m == NULL, cleanup);
|
||||
|
||||
ret = dc_api_post_message(
|
||||
dc_session_api(current_session),
|
||||
dc_session_me(current_session),
|
||||
c, m
|
||||
);
|
||||
}
|
||||
|
||||
ret = true;
|
||||
|
||||
cleanup:
|
||||
|
||||
dc_unref(c);
|
||||
dc_unref(v);
|
||||
dc_unref(m);
|
||||
|
||||
free(target);
|
||||
free(full_message);
|
||||
free(message);
|
||||
|
||||
return ret;
|
||||
|
50
ncdc/src/post.c
Normal file
50
ncdc/src/post.c
Normal file
@ -0,0 +1,50 @@
|
||||
#include <ncdc/cmds.h>
|
||||
#include <ncdc/ncdc.h>
|
||||
|
||||
bool ncdc_cmd_post(ncdc_mainwindow_t n, size_t ac, wchar_t **av,
|
||||
wchar_t const *f)
|
||||
{
|
||||
char *str = NULL;
|
||||
bool ret = false;
|
||||
dc_message_t m = NULL;
|
||||
dc_channel_t chan = NULL;
|
||||
size_t i = 0;
|
||||
|
||||
if (!is_logged_in()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
chan = ncdc_mainwindow_current_channel(n);
|
||||
goto_if_true(chan == NULL, cleanup);
|
||||
|
||||
/* the API only uses multi-byte strings, so convert from wchar_t
|
||||
*/
|
||||
str = w_convert(f);
|
||||
goto_if_true(str == NULL, cleanup);
|
||||
|
||||
/* trim string at least on the left
|
||||
*/
|
||||
for (i = 0; isspace(str[i]) && str[i] != '\0'; i++)
|
||||
;
|
||||
goto_if_true (str[i] == '\0', cleanup);
|
||||
memmove(str, str+i, strlen(str)+1-i);
|
||||
|
||||
m = dc_message_new_content(str, -1);
|
||||
goto_if_true(m == NULL, cleanup);
|
||||
|
||||
ret = dc_api_post_message(
|
||||
dc_session_api(current_session),
|
||||
dc_session_me(current_session),
|
||||
chan, m
|
||||
);
|
||||
goto_if_true(ret == false, cleanup);
|
||||
|
||||
ret = true;
|
||||
|
||||
cleanup:
|
||||
|
||||
dc_unref(m);
|
||||
free(str);
|
||||
|
||||
return ret;
|
||||
}
|
4
todo.org
4
todo.org
@ -1,8 +1,8 @@
|
||||
* Channels [0/4]
|
||||
* Channels [1/4]
|
||||
** TODO Automatically open window for 1:1 and 1:N
|
||||
** TODO send v6/api/channels/$ID/ack for "I read that shit"
|
||||
** TODO add timestamps from messages
|
||||
** TODO add message sending
|
||||
** DONE add message sending
|
||||
* Guilds [0/3]
|
||||
** TODO Guild support code
|
||||
** TODO Guild view on the left pane
|
||||
|
Loading…
Reference in New Issue
Block a user