implement channel acking and new messages
This commit is contained in:
		
							parent
							
								
									b8fa202ce3
								
							
						
					
					
						commit
						ab65d49605
					
				| @ -96,6 +96,13 @@ bool dc_api_get_messages(dc_api_t api, dc_account_t login, dc_channel_t c); | ||||
| bool dc_api_post_message(dc_api_t api, dc_account_t login, | ||||
|                          dc_channel_t c, dc_message_t m); | ||||
| 
 | ||||
| /**
 | ||||
|  * "ack" a channel, meaning that you have read it its contents. You must provide | ||||
|  * a message, so that discord knows which message was the last you read. | ||||
|  */ | ||||
| bool dc_api_channel_ack(dc_api_t api, dc_account_t login, | ||||
|                         dc_channel_t c, dc_message_t msg); | ||||
| 
 | ||||
| /**
 | ||||
|  * Fetch a list of friends of the login account "login". The friends are stored | ||||
|  * within the login object. | ||||
|  | ||||
| @ -67,4 +67,7 @@ void dc_channel_add_messages(dc_channel_t c, dc_message_t *m, size_t s); | ||||
| 
 | ||||
| bool dc_channel_compare(dc_channel_t a, dc_channel_t b); | ||||
| 
 | ||||
| bool dc_channel_has_new_messages(dc_channel_t c); | ||||
| void dc_channel_mark_read(dc_channel_t c); | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
| @ -2,6 +2,40 @@ | ||||
| 
 | ||||
| #include "internal.h" | ||||
| 
 | ||||
| bool dc_api_channel_ack(dc_api_t api, dc_account_t login, | ||||
|                         dc_channel_t c, dc_message_t m) | ||||
| { | ||||
|     bool ret = false; | ||||
|     char *url = NULL; | ||||
|     json_t *reply = NULL, *j = NULL; | ||||
| 
 | ||||
|     return_if_true(api == NULL || login == NULL || | ||||
|                    c == NULL || m == NULL, false); | ||||
| 
 | ||||
|     asprintf(&url, "channels/%s/messages/%s/ack", | ||||
|              dc_channel_id(c), | ||||
|              dc_message_id(m) | ||||
|         ); | ||||
|     goto_if_true(url == NULL, cleanup); | ||||
| 
 | ||||
|     j = json_object(); | ||||
|     goto_if_true(j == NULL, cleanup); | ||||
|     json_object_set_new(j, "token", json_string(TOKEN(login))); | ||||
| 
 | ||||
|     reply = dc_api_call_sync(api, "POST", TOKEN(login), url, j); | ||||
|     goto_if_true(reply != NULL, cleanup); | ||||
| 
 | ||||
|     ret = true; | ||||
| 
 | ||||
| cleanup: | ||||
| 
 | ||||
|     free(url); | ||||
|     json_decref(reply); | ||||
|     json_decref(j); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| bool dc_api_post_message(dc_api_t api, dc_account_t login, | ||||
|                          dc_channel_t c, dc_message_t m) | ||||
| { | ||||
|  | ||||
| @ -46,6 +46,7 @@ struct dc_channel_ | ||||
| 
 | ||||
|     GHashTable *messages_byid; | ||||
|     GPtrArray *messages; | ||||
|     bool new_messages; | ||||
| }; | ||||
| 
 | ||||
| static void dc_channel_free(dc_channel_t c) | ||||
| @ -318,6 +319,8 @@ void dc_channel_add_messages(dc_channel_t c, dc_message_t *m, size_t s) | ||||
| 
 | ||||
|         g_hash_table_insert(c->messages_byid, strdup(id), dc_ref(m[i])); | ||||
|         g_ptr_array_add(c->messages, dc_ref(m[i])); | ||||
| 
 | ||||
|         c->new_messages = true; | ||||
|     } | ||||
| 
 | ||||
|     g_ptr_array_sort(c->messages, (GCompareFunc)dc_message_compare); | ||||
| @ -329,3 +332,15 @@ bool dc_channel_compare(dc_channel_t a, dc_channel_t b) | ||||
|     return_if_true(a->id == NULL || b->id == NULL, false); | ||||
|     return (strcmp(a->id, b->id) == 0); | ||||
| } | ||||
| 
 | ||||
| bool dc_channel_has_new_messages(dc_channel_t c) | ||||
| { | ||||
|     return_if_true(c == NULL, false); | ||||
|     return c->new_messages; | ||||
| } | ||||
| 
 | ||||
| void dc_channel_mark_read(dc_channel_t c) | ||||
| { | ||||
|     return_if_true(c == NULL,); | ||||
|     c->new_messages = false; | ||||
| } | ||||
|  | ||||
| @ -13,6 +13,7 @@ SET(SOURCES | ||||
|   "include/ncdc/mainwindow.h" | ||||
|   "include/ncdc/ncdc.h" | ||||
|   "include/ncdc/textview.h" | ||||
|   "src/ack.c" | ||||
|   "src/cmds.c" | ||||
|   "src/config.c" | ||||
|   "src/friends.c" | ||||
|  | ||||
| @ -30,6 +30,7 @@ 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_ack(ncdc_mainwindow_t n, size_t ac, wchar_t **av, wchar_t const *f); | ||||
| 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); | ||||
|  | ||||
							
								
								
									
										33
									
								
								ncdc/src/ack.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								ncdc/src/ack.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | ||||
| #include <ncdc/cmds.h> | ||||
| #include <ncdc/ncdc.h> | ||||
| 
 | ||||
| bool ncdc_cmd_ack(ncdc_mainwindow_t n, size_t ac, wchar_t **av, wchar_t const *f) | ||||
| { | ||||
|     dc_channel_t c = NULL; | ||||
|     dc_message_t m = NULL; | ||||
|     bool ret = false; | ||||
| 
 | ||||
|     if (!is_logged_in()) { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     c = ncdc_mainwindow_current_channel(n); | ||||
|     return_if_true(c == NULL, false); | ||||
|     return_if_true(dc_channel_messages(c) == 0, false); | ||||
|     m = dc_channel_nth_message(c, dc_channel_messages(c)-1); | ||||
| 
 | ||||
| 
 | ||||
|     ret = dc_api_channel_ack(dc_session_api(current_session), | ||||
|                              dc_session_me(current_session), | ||||
|                              c, m | ||||
|         ); | ||||
| 
 | ||||
|     if (!ret) { | ||||
|         LOG(n, L"ack: failed to ack the given channel"); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     dc_channel_mark_read(c); | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| @ -1,13 +1,15 @@ | ||||
| #include <ncdc/cmds.h> | ||||
| 
 | ||||
| ncdc_commands_t cmds[] = { | ||||
|     { L"/friend",  ncdc_cmd_friends }, | ||||
|     { L"/friends", ncdc_cmd_friends }, | ||||
|     { 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 }, | ||||
|     { L"/ack",      ncdc_cmd_ack }, | ||||
|     { L"/friend",   ncdc_cmd_friends }, | ||||
|     { L"/friends",  ncdc_cmd_friends }, | ||||
|     { L"/login",    ncdc_cmd_login }, | ||||
|     { L"/logout",   ncdc_cmd_logout }, | ||||
|     { L"/markread", ncdc_cmd_ack }, | ||||
|     { L"/msg",      ncdc_cmd_msg }, | ||||
|     { L"/post",     ncdc_cmd_post }, | ||||
|     { L"/quit",     ncdc_cmd_quit }, | ||||
|     { NULL, NULL } | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -119,7 +119,7 @@ ncdc_mainwindow_callback(ncdc_input_t i, wchar_t const *s, | ||||
|     if (s[0] == '/') { | ||||
|         ret = ncdc_dispatch(mainwin, s); | ||||
|     } else { | ||||
|         wchar_t *post = calloc(wcslen(s)+6, sizeof(wchar_t)); | ||||
|         wchar_t *post = calloc(wcslen(s)+7, sizeof(wchar_t)); | ||||
| 
 | ||||
|         wcscat(post, L"/post "); | ||||
|         wcscat(post, s); | ||||
| @ -202,6 +202,8 @@ static void ncdc_mainwindow_render_status(ncdc_mainwindow_t n) | ||||
|     FILE *f = open_wmemstream(&status, &statuslen); | ||||
|     wchar_t const *wintitle = NULL; | ||||
|     ncdc_textview_t view = NULL; | ||||
|     size_t i = 0; | ||||
|     dc_channel_t channel = NULL; | ||||
| 
 | ||||
|     werase(n->sep1); | ||||
|     return_if_true(f == NULL,); | ||||
| @ -221,8 +223,18 @@ static void ncdc_mainwindow_render_status(ncdc_mainwindow_t n) | ||||
|     fwprintf(f, L" [%d: %ls]", n->curview, | ||||
|              (wintitle != NULL ? wintitle : L"n/a") | ||||
|         ); | ||||
|     fclose(f); | ||||
| 
 | ||||
|     fwprintf(f, L" [Act:"); | ||||
|     for (i = 0; i < n->views->len; i++) { | ||||
|         view = g_ptr_array_index(n->views, i); | ||||
|         channel = ncdc_textview_channel(view); | ||||
|         if (channel != NULL && dc_channel_has_new_messages(channel)) { | ||||
|             fwprintf(f, L" %d", i); | ||||
|         } | ||||
|     } | ||||
|     fwprintf(f, L"]"); | ||||
| 
 | ||||
|     fclose(f); | ||||
|     mvwaddwstr(n->sep1, 0, 0, status); | ||||
|     free(status); | ||||
| } | ||||
| @ -287,6 +299,7 @@ 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; | ||||
| } | ||||
| 
 | ||||
| @ -329,16 +342,33 @@ void ncdc_mainwindow_log(ncdc_mainwindow_t w, wchar_t const *fmt, ...) | ||||
|     ncdc_textview_append(w->log, buf); | ||||
| } | ||||
| 
 | ||||
| static void ncdc_mainwindow_ack_view(ncdc_mainwindow_t n) | ||||
| { | ||||
| #if 0 | ||||
|     dc_channel_t c = ncdc_mainwindow_current_channel(n); | ||||
|     return_if_true(c == NULL,); | ||||
|     return_if_true(dc_channel_messages(c) == 0,); | ||||
| 
 | ||||
|     dc_message_t m = dc_channel_nth_message(c, dc_channel_messages(c)-1); | ||||
|     dc_api_channel_ack(dc_session_api(current_session), | ||||
|                        dc_session_me(current_session), | ||||
|                        c, m | ||||
|         ); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void ncdc_mainwindow_rightview(ncdc_mainwindow_t n) | ||||
| { | ||||
|     return_if_true(n == NULL,); | ||||
|     n->curview = (n->curview + 1) % n->views->len; | ||||
|     ncdc_mainwindow_ack_view(n); | ||||
| } | ||||
| 
 | ||||
| void ncdc_mainwindow_leftview(ncdc_mainwindow_t n) | ||||
| { | ||||
|     return_if_true(n == NULL,); | ||||
|     n->curview = (n->curview - 1) % n->views->len; | ||||
|     ncdc_mainwindow_ack_view(n); | ||||
| } | ||||
| 
 | ||||
| dc_channel_t ncdc_mainwindow_current_channel(ncdc_mainwindow_t n) | ||||
|  | ||||
							
								
								
									
										6
									
								
								todo.org
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								todo.org
									
									
									
									
									
								
							| @ -1,6 +1,8 @@ | ||||
| * Channels [1/4] | ||||
| * General | ||||
| ** TODO move key handling away from the thread the event_loop thread | ||||
| * Channels [2/4] | ||||
| ** TODO Automatically open window for 1:1 and 1:N | ||||
| ** TODO send v6/api/channels/$ID/ack for "I read that shit" | ||||
| ** DONE send v6/api/channels/$ID/ack for "I read that shit" | ||||
| ** TODO add timestamps from messages | ||||
| ** DONE add message sending | ||||
| * Guilds [0/3] | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user