implement adding friends
This commit is contained in:
		
							parent
							
								
									2e563b724a
								
							
						
					
					
						commit
						efce6a6543
					
				| @ -8,8 +8,19 @@ | ||||
| struct dc_account_; | ||||
| typedef struct dc_account_ *dc_account_t; | ||||
| 
 | ||||
| typedef enum { | ||||
|     FRIEND_STATE_NONE = 0, | ||||
|     /* accountt is a mutual friend
 | ||||
|      */ | ||||
|     FRIEND_STATE_FRIEND = 1, | ||||
|     /* pending account, the other side hasn't accepted yet
 | ||||
|      */ | ||||
|     FRIEND_STATE_PENDING = 4, | ||||
| } dc_account_friend_states; | ||||
| 
 | ||||
| dc_account_t dc_account_new(void); | ||||
| dc_account_t dc_account_new2(char const *email, char const *pass); | ||||
| dc_account_t dc_account_from_fullid(char const *fullid); | ||||
| 
 | ||||
| void dc_account_set_email(dc_account_t a, char const *email); | ||||
| char const *dc_account_email(dc_account_t a); | ||||
| @ -37,5 +48,7 @@ bool dc_account_has_token(dc_account_t a); | ||||
| 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); | ||||
| int dc_account_friend_state(dc_account_t a); | ||||
| void dc_account_set_friend_state(dc_account_t a, int state); | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
| @ -65,4 +65,9 @@ bool dc_api_get_userguilds(dc_api_t api, dc_account_t login, | ||||
|  */ | ||||
| bool dc_api_get_friends(dc_api_t api, dc_account_t login); | ||||
| 
 | ||||
| /**
 | ||||
|  * Add a given account as a friend to the friends list | ||||
|  */ | ||||
| bool dc_api_add_friend(dc_api_t api, dc_account_t login, dc_account_t friend); | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
| @ -34,6 +34,9 @@ struct dc_account_ | ||||
|     /* friends we have
 | ||||
|      */ | ||||
|     GPtrArray *friends; | ||||
|     /* our own friend state
 | ||||
|      */ | ||||
|     int friend_state; | ||||
| }; | ||||
| 
 | ||||
| static void dc_account_free(dc_account_t ptr) | ||||
| @ -81,6 +84,38 @@ dc_account_t dc_account_new2(char const *email, char const *pass) | ||||
|     return ptr; | ||||
| } | ||||
| 
 | ||||
| dc_account_t dc_account_from_fullid(char const *fullid) | ||||
| { | ||||
|     return_if_true(fullid == NULL, NULL); | ||||
| 
 | ||||
|     char *name = strdup(fullid), *discriminator = NULL; | ||||
|     dc_account_t acc = NULL; | ||||
| 
 | ||||
|     return_if_true(name == NULL, NULL); | ||||
| 
 | ||||
|     discriminator = strchr(name, '#'); | ||||
|     if (discriminator == NULL || *discriminator == '\0') { | ||||
|         free(name); | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     *discriminator = '\0'; | ||||
|     ++discriminator; | ||||
| 
 | ||||
|     acc = dc_account_new(); | ||||
|     if (acc == NULL) { | ||||
|         free(name); | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     dc_account_set_username(acc, name); | ||||
|     dc_account_set_discriminator(acc, discriminator); | ||||
| 
 | ||||
|     free(name); | ||||
| 
 | ||||
|     return acc; | ||||
| } | ||||
| 
 | ||||
| void dc_account_set_email(dc_account_t a, char const *email) | ||||
| { | ||||
|     return_if_true(a == NULL,); | ||||
| @ -219,3 +254,15 @@ size_t dc_account_friends_size(dc_account_t a) | ||||
|     return_if_true(a == NULL || a->friends == NULL, 0); | ||||
|     return a->friends->len; | ||||
| } | ||||
| 
 | ||||
| int dc_account_friend_state(dc_account_t a) | ||||
| { | ||||
|     return_if_true(a == NULL, 0); | ||||
|     return a->friend_state; | ||||
| } | ||||
| 
 | ||||
| void dc_account_set_friend_state(dc_account_t a, int state) | ||||
| { | ||||
|     return_if_true(a == NULL,); | ||||
|     a->friend_state = state; | ||||
| } | ||||
|  | ||||
| @ -349,6 +349,29 @@ error: | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| static json_t *dc_api_user_to_json(dc_account_t a) | ||||
| { | ||||
|     json_t *j = NULL; | ||||
| 
 | ||||
|     return_if_true(a == NULL, NULL); | ||||
|     return_if_true(dc_account_username(a) == NULL || | ||||
|                    dc_account_discriminator(a) == NULL, | ||||
|                    NULL | ||||
|         ); | ||||
| 
 | ||||
|     j = json_object(); | ||||
|     return_if_true(j == NULL, NULL); | ||||
| 
 | ||||
|     json_object_set_new(j, "username", | ||||
|                         json_string(dc_account_username(a)) | ||||
|         ); | ||||
|     json_object_set_new(j, "discriminator", | ||||
|                         json_string(dc_account_discriminator(a)) | ||||
|         ); | ||||
| 
 | ||||
|     return j; | ||||
| } | ||||
| 
 | ||||
| bool dc_api_get_userinfo(dc_api_t api, dc_account_t login, | ||||
|                          dc_account_t user) | ||||
| { | ||||
| @ -420,6 +443,15 @@ bool dc_api_get_friends(dc_api_t api, dc_account_t login) | ||||
|         if (a == NULL) { | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         /* read the type also known as "typ"
 | ||||
|          */ | ||||
|         val = json_object_get(c, "type"); | ||||
|         if (val != NULL && json_is_integer(val)) { | ||||
|             int state = json_integer_value(val); | ||||
|             dc_account_set_friend_state(a, state); | ||||
|         } | ||||
| 
 | ||||
|         g_ptr_array_add(f, a); | ||||
|     } | ||||
| 
 | ||||
| @ -440,6 +472,36 @@ cleanup: | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Add a given account as a friend to the friends list | ||||
|  */ | ||||
| bool dc_api_add_friend(dc_api_t api, dc_account_t login, dc_account_t friend) | ||||
| { | ||||
|     char const *url = "users/@me/relationships"; | ||||
|     json_t *reply = NULL, *post = NULL; | ||||
|     bool ret = false; | ||||
| 
 | ||||
|     return_if_true(api == NULL, false); | ||||
|     return_if_true(login == NULL, false); | ||||
| 
 | ||||
|     post = dc_api_user_to_json(friend); | ||||
|     return_if_true(post == NULL, false); | ||||
| 
 | ||||
|     reply = dc_api_call_sync(api, "POST", dc_account_token(login), url, post); | ||||
|     /* apparently if no data comes back, then the whole thing was a success
 | ||||
|      */ | ||||
|     goto_if_true(reply != NULL, cleanup); | ||||
| 
 | ||||
|     ret = true; | ||||
| 
 | ||||
| cleanup: | ||||
| 
 | ||||
|     json_decref(post); | ||||
|     json_decref(reply); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| bool dc_api_get_userguilds(dc_api_t api, dc_account_t login, GPtrArray **out) | ||||
| { | ||||
|     char const *url = "users/@me/guilds"; | ||||
|  | ||||
| @ -1,9 +1,10 @@ | ||||
| #include <ncdc/cmds.h> | ||||
| 
 | ||||
| ncdc_commands_t cmds[] = { | ||||
|     { L"friends", ncdc_cmd_friends }, | ||||
|     { L"login", ncdc_cmd_login }, | ||||
|     { L"quit", ncdc_cmd_quit }, | ||||
|     { L"/friend",  ncdc_cmd_friends }, | ||||
|     { L"/friends", ncdc_cmd_friends }, | ||||
|     { L"/login",   ncdc_cmd_login }, | ||||
|     { L"/quit",    ncdc_cmd_quit }, | ||||
|     { NULL, NULL } | ||||
| }; | ||||
| 
 | ||||
| @ -36,7 +37,6 @@ static void *async_dispatcher(void *arg) | ||||
|                 /* end of working orders
 | ||||
|                  */ | ||||
|                 pthread_mutex_unlock(&mtx); | ||||
|                 printf("got exit\n"); | ||||
|                 return NULL; | ||||
|             } else { | ||||
|                 /* call the handler
 | ||||
| @ -92,15 +92,17 @@ bool ncdc_dispatch_deinit(void) | ||||
| bool ncdc_dispatch(ncdc_mainwindow_t n, wchar_t const *s) | ||||
| { | ||||
|     wchar_t **tokens = NULL; | ||||
|     size_t i = 0; | ||||
|     size_t i = 0, tokenlen = 0; | ||||
|     ncdc_commands_t *it = NULL; | ||||
|     queue_item *item = NULL; | ||||
| 
 | ||||
|     tokens = w_tokenise(s); | ||||
|     return_if_true(tokens == NULL, false); | ||||
| 
 | ||||
|     tokenlen = wcslen(tokens[0]); | ||||
| 
 | ||||
|     for (i = 0; cmds[i].name != NULL; i++) { | ||||
|         if (wcscmp(cmds[i].name, tokens[0]) == 0) { | ||||
|         if (wcsncmp(cmds[i].name, tokens[0], tokenlen) == 0) { | ||||
|             it = cmds+i; | ||||
|             break; | ||||
|         } | ||||
|  | ||||
| @ -6,6 +6,7 @@ ncdc_cmd_friends_list(ncdc_mainwindow_t n, size_t ac, wchar_t **av) | ||||
| { | ||||
|     bool ret = false; | ||||
|     size_t i = 0; | ||||
|     wchar_t c = ' '; | ||||
| 
 | ||||
|     ret = dc_api_get_friends(api, current_account); | ||||
|     if (!ret) { | ||||
| @ -16,27 +17,67 @@ ncdc_cmd_friends_list(ncdc_mainwindow_t n, size_t ac, wchar_t **av) | ||||
|     LOG(n, L"/FRIENDS list"); | ||||
|     for (i = 0; i < dc_account_friends_size(current_account); i++) { | ||||
|         dc_account_t acc = dc_account_nthfriend(current_account, i); | ||||
|         LOG(n, L"  %s", dc_account_full_username(acc)); | ||||
|         switch (dc_account_friend_state(acc)) { | ||||
|         case FRIEND_STATE_PENDING: c = 'P'; break; | ||||
|         default: c = ' '; break; | ||||
|         } | ||||
|         LOG(n, L"%lc %s", c, dc_account_full_username(acc)); | ||||
|     } | ||||
|     LOG(n, L"End of /FRIENDS list"); | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| bool ncdc_cmd_friends(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) | ||||
| { | ||||
|     wchar_t *subcmd = NULL; | ||||
|     char *name = NULL; | ||||
|     dc_account_t friend = NULL; | ||||
|     bool ret = false; | ||||
| 
 | ||||
|     if (ac <= 1) { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     name = w_convert(av[1]); | ||||
|     return_if_true(name == NULL, false); | ||||
| 
 | ||||
|     friend = dc_account_from_fullid(name); | ||||
|     if (friend == NULL) { | ||||
|         LOG(n, L"friends: add: invalid username given, use the full ID"); | ||||
|         goto cleanup; | ||||
|     } | ||||
| 
 | ||||
|     if (!dc_api_add_friend(api, current_account, friend)) { | ||||
|         LOG(n, L"friends: add: failed to add friend, Vulkan would be sad"); | ||||
|         goto cleanup; | ||||
|     } | ||||
| 
 | ||||
|     LOG(n, L"friends: add: request for friendship sent"); | ||||
|     ret = true; | ||||
| 
 | ||||
| cleanup: | ||||
| 
 | ||||
|     dc_unref(friend); | ||||
|     free(name); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| bool ncdc_cmd_friends(ncdc_mainwindow_t n, size_t ac, wchar_t **av) | ||||
| { | ||||
|     wchar_t *subcmd = NULL; | ||||
| 
 | ||||
|     if (current_account == NULL || | ||||
|         !dc_account_has_token(current_account)) { | ||||
|         LOG(n, L"friends: not logged in"); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     if (ac <= 1) { | ||||
|         return ncdc_cmd_friends_list(n, ac, av); | ||||
|     } | ||||
| 
 | ||||
|     subcmd = av[1]; | ||||
| 
 | ||||
|     --ac; | ||||
| @ -44,6 +85,8 @@ bool ncdc_cmd_friends(ncdc_mainwindow_t n, size_t ac, wchar_t **av) | ||||
| 
 | ||||
|     if (wcscmp(subcmd, L"list") == 0) { | ||||
|         return ncdc_cmd_friends_list(n, ac, av); | ||||
|     } else if (wcscmp(subcmd, L"add") == 0) { | ||||
|         return ncdc_cmd_friends_add(n, ac, av); | ||||
|     } else { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
| @ -99,12 +99,12 @@ ncdc_mainwindow_callback(ncdc_input_t i, wchar_t const *s, | ||||
| { | ||||
|     ncdc_mainwindow_t mainwin = (ncdc_mainwindow_t)arg; | ||||
| 
 | ||||
|     if (s[0] == '/') { | ||||
|     if (s != NULL && s[0] == '/') { | ||||
|         if (s[1] == '\0') { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         return ncdc_dispatch(mainwin, s+1); | ||||
|         return ncdc_dispatch(mainwin, s); | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
|  | ||||
							
								
								
									
										105
									
								
								ncdc/src/util.c
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								ncdc/src/util.c
									
									
									
									
									
								
							| @ -33,11 +33,11 @@ int aswprintf(wchar_t **buffer, wchar_t const *fmt, ...) | ||||
|     return sz; | ||||
| } | ||||
| 
 | ||||
| wchar_t* wcsndup(const wchar_t* string, size_t maxlen) | ||||
| wchar_t* wcsndup(wchar_t const* string, size_t maxlen) | ||||
| { | ||||
|     size_t n = wcsnlen(string, maxlen) + 1; | ||||
|     wchar_t* r = calloc(n, sizeof(wchar_t)); | ||||
|     return r == NULL ? NULL : wmemcpy(r, string, n); | ||||
|     wchar_t* r = calloc(maxlen+1, sizeof(wchar_t)); | ||||
|     return_if_true(r == NULL, NULL); | ||||
|     return wmemcpy(r, string, maxlen); | ||||
| } | ||||
| 
 | ||||
| size_t w_strlenv(wchar_t **s) | ||||
| @ -61,28 +61,56 @@ void w_strfreev(wchar_t **s) | ||||
|     free(s); | ||||
| } | ||||
| 
 | ||||
| wchar_t **w_tokenise(wchar_t const *w) | ||||
| wchar_t **w_tokenise(wchar_t const *str) | ||||
| { | ||||
|     wchar_t const *p = NULL, *start_of_word = NULL; | ||||
|     wint_t c; | ||||
|     GPtrArray *array = g_ptr_array_new(); | ||||
|     wchar_t const *item = w; | ||||
|     wchar_t *dup = NULL; | ||||
|     size_t len = 0, origlen = 0; | ||||
|     enum states { DULL, IN_WORD, IN_STRING } state = DULL; | ||||
| 
 | ||||
|     while ((dup = w_next_tok(item)) != NULL) { | ||||
|         len = origlen = wcslen(dup); | ||||
|     for (p = str; *p != '\0'; p++) { | ||||
|         c = (wint_t) *p; | ||||
|         switch (state) { | ||||
|         case DULL: | ||||
|         { | ||||
|             if (iswspace(c)) { | ||||
|                 continue; | ||||
|             } | ||||
|             if (c == '"') { | ||||
|                 state = IN_STRING; | ||||
|                 start_of_word = p + 1; | ||||
|                 continue; | ||||
|             } | ||||
|             state = IN_WORD; | ||||
|             start_of_word = p; | ||||
|         } continue; | ||||
| 
 | ||||
|         if (*dup == '"') { | ||||
|             memmove(dup, dup+1, sizeof(wchar_t)*(len-1)); | ||||
|             --len; | ||||
|         case IN_STRING: | ||||
|         { | ||||
|             if (c == '"') { | ||||
|                 size_t len = (p - 2 - start_of_word); | ||||
|                 wchar_t *s = wcsndup(start_of_word, len); | ||||
|                 g_ptr_array_add(array, s); | ||||
|                 state = DULL; | ||||
|             } | ||||
|         } continue; | ||||
| 
 | ||||
|         case IN_WORD: | ||||
|         { | ||||
|             if (iswspace(c)) { | ||||
|                 size_t len = (p - start_of_word); | ||||
|                 wchar_t *s = wcsndup(start_of_word, len); | ||||
|                 g_ptr_array_add(array, s); | ||||
|                 state = DULL; | ||||
|             } | ||||
|         } continue; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|         if (len > 0 && dup[len-1] == '"') { | ||||
|             dup[len-1] = '\0'; | ||||
|             --len; | ||||
|         } | ||||
| 
 | ||||
|         g_ptr_array_add(array, dup); | ||||
|         item += origlen; | ||||
|     if (state != DULL) { | ||||
|         size_t len = (p - start_of_word); | ||||
|         wchar_t *s = wcsndup(start_of_word, len); | ||||
|         g_ptr_array_add(array, s); | ||||
|     } | ||||
| 
 | ||||
|     g_ptr_array_add(array, NULL); | ||||
| @ -103,40 +131,3 @@ char *w_convert(wchar_t const *w) | ||||
|     wcstombs(ptr, w, sz); | ||||
|     return ptr; | ||||
| } | ||||
| 
 | ||||
| wchar_t *w_next_tok(wchar_t const *w) | ||||
| { | ||||
|     bool quotes = false; | ||||
|     wchar_t const *start = NULL; | ||||
| 
 | ||||
|     /* skip first white spaces if there are any
 | ||||
|      */ | ||||
|     for (; *w != '\0' && iswspace(*w); w++) | ||||
|         ; | ||||
| 
 | ||||
|     if (*w == '\0') { | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     start = w; | ||||
|     quotes = (*w == '"'); | ||||
| 
 | ||||
|     do { | ||||
|         if (iswspace(*w) && !quotes) { | ||||
|             --w; | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         if (*w == '"' && *(w-1) != '\\' && quotes) { | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         if (*w == '\0') { | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         ++w; | ||||
|     } while (1); | ||||
| 
 | ||||
|     return wcsndup(start, (w - start)); | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user