From a55af3fc94897efb13e4a736f0f20b591be1d139 Mon Sep 17 00:00:00 2001 From: teknomunk Date: Mon, 20 Nov 2023 08:40:13 -0600 Subject: [PATCH] Add more code for account searching, add struct account_list, bugfix: system status for blocks now shows correct account name instead of a blank, add debug to URL rendering --- src/controller/api/accounts.c | 82 ++++++++++++++++++++++++++--------- src/model/account.c | 14 ++++++ src/model/account.h | 14 +++++- src/model/account/ap_sync.c | 9 +++- src/model/status.c | 3 +- src/model/status/render.c | 7 ++- 6 files changed, 103 insertions(+), 26 deletions(-) diff --git a/src/controller/api/accounts.c b/src/controller/api/accounts.c index d5a5ce9..5ac16a6 100644 --- a/src/controller/api/accounts.c +++ b/src/controller/api/accounts.c @@ -12,6 +12,10 @@ #include "controller/api/timeline.h" +// Submodules +#include "collections/array.h" + +// Platform libraries #include #include @@ -54,43 +58,79 @@ bool handle_mastodon_api_show_account( struct http_request* req, struct account* return true; } +struct search_params +{ + const char* q; + int limit; + bool resolve; + bool following; +}; + +static void search_accounts( struct search_params* params, struct account_list* al ) +{ + if( strstr( params->q, "https://" ) || strstr( params->q, "http://" ) ) { + //// Is URL + struct account* a = NULL; + + // TODO: try to fetch RSS account from url + a = account_from_rss( params->q ); + if( a ) { + array_append( al, sizeof(a), &a ); + return; + } + + // TODO: try to fetch account from url + a = account_from_uri_or_fetch( params->q ); + if( a ) { + array_append( al, sizeof(a), &a ); + } + } else if( strstr( params->q, "@" ) ) { + // Has @, assume this is a webfinger search + struct account* a = account_from_webfinger( params->q, NULL ); + if( a ) { + array_append( al, sizeof(a), &a ); + } + + if( !a && params->resolve ) { + printf( "TODO: perform webfinger lookup\n" ); + } + } +} + +// Route: /api/v1/accounts/search? static bool handle_search( struct http_request* req ) { - struct params_t - { - const char* q; - int limit; - bool resolve; - bool following; - } params; - memset(¶ms,0,sizeof(params)); + struct search_params params = {0}; + #define OBJ_TYPE struct search_params static struct http_query_fields fields[] = { - { "q", offsetof(struct params_t,q), qf_string }, - { "limit", offsetof(struct params_t,limit), qf_integer }, - { "resolve", offsetof(struct params_t,resolve), qf_bool }, - { "following", offsetof(struct params_t,following), qf_bool }, + { "q", offsetof(OBJ_TYPE,q), qf_string }, + { "limit", offsetof(OBJ_TYPE,limit), qf_integer }, + { "resolve", offsetof(OBJ_TYPE,resolve), qf_bool }, + { "following", offsetof(OBJ_TYPE,following), qf_bool }, { NULL }, }; + #undef OBJ_TYPE http_query_parse( req, fields, ¶ms ); + struct account_list al = {0}; + search_accounts( ¶ms, &al ); + http_request_send_headers( req, 200, "application/json", true ); FILE* f = http_request_get_response_body( req ); - struct account* a = account_from_webfinger( params.q, NULL ); - if( !a && params.resolve ) { - printf( "TODO: perform webfinger lookup\n" ); - return false; - } - fprintf( f, "[" ); - if( a ) { - api_Account_write(a,f,1,false); + for( int i = 0; i < al.count; ++i ) { + if( i != 0 ) { + fprintf( f, ",\n" ); + } + + api_Account_write(al.items[i],f,1,false); } fprintf( f, "]" ); - account_free(a); + account_list_free(&al); return true; } diff --git a/src/model/account.c b/src/model/account.c index fe3a01f..072624e 100644 --- a/src/model/account.c +++ b/src/model/account.c @@ -39,6 +39,8 @@ static struct json_enum account_types_enum[] = { { "bot", at_bot }, { "activity_pub", at_remote_activity_pub }, { "rss", at_rss_feed }, + { "group", at_group }, + { "stub", at_stub }, { NULL }, }; @@ -503,6 +505,11 @@ struct account* account_fetch_from_uri( const char* uri ) return account_from_id(account_id); } +struct account* account_from_rss( const char* url ) +{ + printf( "TODO: fetch document at %s and check to see if it is an RSS feed\n", url ); + return NULL; +} void account_free( struct account* a ) { @@ -543,6 +550,13 @@ void account_free( struct account* a ) free(a); } +void account_list_free( struct account_list* al ) +{ + for( int i = 0; i < al->count; ++i ) { + account_free( al->items[i] ); + } + free( al->items ); +} void account_save( struct account* a ) { diff --git a/src/model/account.h b/src/model/account.h index 1da95aa..8bc5988 100644 --- a/src/model/account.h +++ b/src/model/account.h @@ -29,10 +29,12 @@ struct string_pair enum account_type { + at_remote_activity_pub = 0, at_owner = 1, at_bot = 2, - at_remote_activity_pub = 3, - at_rss_feed = 4, + at_rss_feed = 3, + at_group = 4, + at_stub = 9999, }; struct account @@ -95,6 +97,12 @@ struct account bool notify_for_posts; }; +struct account_list +{ + struct account** items; + int count; +}; + void account_reindex(); void account_index_webfinger( struct account* a ); @@ -105,8 +113,10 @@ struct account* account_from_webfinger( const char* handle, const char* default_ struct account* account_new(); struct account* account_from_uri_or_fetch( const char* uri ); struct account* account_fetch_from_uri( const char* uri ); +struct account* account_from_rss( const char* url ); struct account* account_load_next_update(); void account_free( struct account* a ); +void account_list_free( struct account_list* al ); void account_save( struct account* a ); // Update from external activity pub data diff --git a/src/model/account/ap_sync.c b/src/model/account/ap_sync.c index 3d65306..8947755 100644 --- a/src/model/account/ap_sync.c +++ b/src/model/account/ap_sync.c @@ -57,6 +57,8 @@ bool account_sync_from_activity_pub( unsigned int account_id, bool force ) obj = account_get_activity_pub_data(a); if( !obj ) { + a->account_type = at_stub; + account_save(a); printf( "! Failed to load AP data for %s (%d)\n", a->account_url, a->id ); goto failed; } @@ -114,7 +116,12 @@ bool account_sync_from_activity( struct account* a, struct ap_object* obj ) array_append( &a->aliases, sizeof(str), &str ); } - a->handle = strdup(obj->preferred_username); + if( obj->preferred_username ) { + a->handle = strdup(obj->preferred_username); + } else { + a->handle = strdup("no-name"); + } + if( obj->name ) { a->display_name = strdup(obj->name); } else { diff --git a/src/model/status.c b/src/model/status.c index 92d6ca3..e7f63d2 100644 --- a/src/model/status.c +++ b/src/model/status.c @@ -678,7 +678,8 @@ struct status* status_new_system_block( int account_id ) s->id = -system_status_id; s->published = time(NULL); s->account_id = -1; - asprintf( &s->content, "%s blocked you. View their account here.", a->display_name, a->account_url ); + + asprintf( &s->content, "%s@%s blocked you. View their account here.", a->handle, a->server, a->account_url ); account_free(a); diff --git a/src/model/status/render.c b/src/model/status/render.c index 6fd5d8d..663c003 100644 --- a/src/model/status/render.c +++ b/src/model/status/render.c @@ -43,7 +43,9 @@ char* status_render_source( struct status* s, const char* default_server ) while( *i && !index(" ,\r\n\t",*i) ) ++i; char* url = strndup( start, i - start ); + printf( "link, count = %d, url = '%s'\n", (int)(i - start), url ); fprintf( f, "%s", url, url ); + printf( "%s", url, url ); free(url); } else if( isalpha(i[1]) && *i == '#' ) { @@ -122,7 +124,10 @@ char* status_render_source( struct status* s, const char* default_server ) // Ignore } - if( !*i ) { break; } + if( !*i ) { + printf( "break\n" ); + break; + } fputc( *i, f ); }