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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user