diff --git a/src/controller/fetch.c b/src/controller/fetch.c index 5006469..4001659 100644 --- a/src/controller/fetch.c +++ b/src/controller/fetch.c @@ -61,6 +61,7 @@ static void process_fetch_once() printf( "new count = %d\n", ffdb_trie_count(STUBS) ); } +/* static void process_account_sync_once() { for( int i = 0; i < 10; ++i ) { @@ -81,12 +82,13 @@ static void process_account_sync_once() return; } } +*/ void process_fetch() { while(true) { process_fetch_once(); - process_account_sync_once(); + //process_account_sync_once(); for( int i = 0; i < 30; ++i ) { if( terminate ) { return; }; diff --git a/src/controller/inbox/announce.c b/src/controller/inbox/announce.c index e26228e..217664d 100644 --- a/src/controller/inbox/announce.c +++ b/src/controller/inbox/announce.c @@ -56,7 +56,8 @@ bool route_announce( struct ap_object* act ) s->url = strdup(act->id); s->published = act->published; - s->repost_id = original_post->id; + s->repost.url = strdup(act->object.ref); + s->repost.id = original_post->id; s->account_id = actor_account->id; s->sensitive = act->sensitive; status_save_new(s); diff --git a/src/controller/main.c b/src/controller/main.c index eab8478..8586c1d 100644 --- a/src/controller/main.c +++ b/src/controller/main.c @@ -14,6 +14,7 @@ #include "controller/did.h" #include "controller/inbox.h" #include "controller/mastodon_api.h" +#include "controller/mastodon_api/v2.h" #include "controller/nodeinfo.h" #include "controller/oauth.h" #include "controller/owner.h" @@ -227,8 +228,12 @@ bool route_request( struct http_request* req ) } if( g_server->configured ) { - if( http_request_route( req, "/api/v1/" ) ) { - return route_mastodon_api( req ); + if( http_request_route( req, "/api/" ) ) { + if( http_request_route( req, "v1/" ) ) { + return route_mastodon_api( req ); + } else if( http_request_route( req, "v2/" ) ) { + return route_mastodon_api_v2( req ); + } } else if( http_request_route( req, "/api/pleroma" ) ) { return route_pleroma_api2( req ); } else if( http_request_route( req, "/admin" ) ) { diff --git a/src/controller/mastodon_api/v2.c b/src/controller/mastodon_api/v2.c new file mode 100644 index 0000000..263055d --- /dev/null +++ b/src/controller/mastodon_api/v2.c @@ -0,0 +1,7 @@ +#include "v2.h" + +bool route_mastodon_api_v2( struct http_request* req ) +{ + return false; +} + diff --git a/src/controller/mastodon_api/v2.h b/src/controller/mastodon_api/v2.h new file mode 100644 index 0000000..dd9a30f --- /dev/null +++ b/src/controller/mastodon_api/v2.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +struct http_request; + +bool route_mastodon_api_v2( struct http_request* req ); + diff --git a/src/controller/outbox.c b/src/controller/outbox.c index 0a04795..e74e08e 100644 --- a/src/controller/outbox.c +++ b/src/controller/outbox.c @@ -28,6 +28,7 @@ #include #include #include +#include static bool blacklisted( struct outbox_envelope* env ) { @@ -164,7 +165,7 @@ static bool delivery_succeeded( long status_code ) return false; } -static bool process_envelope( struct outbox_envelope* env ) +static bool process_envelope( struct outbox_envelope* env, bool fast_only ) { bool result = false; char* postdata = NULL; @@ -198,13 +199,12 @@ static bool process_envelope( struct outbox_envelope* env ) p = peer_create_from_domain( domain ); // Handle tor delivery - //* if( p->tor_hidden_service ) { char* path = strchr( inbox + 9, '/' ); tor_inbox = aformat( "http://%s%s", p->tor_hidden_service, path ); printf( "Using TOR inbox: %s\n", tor_inbox ); } - //*/ + struct fetch_data fd; fd.p = p; @@ -253,54 +253,62 @@ static bool process_envelope( struct outbox_envelope* env ) // Force null termination postdata = realloc( postdata, size + 1 ); postdata[size] = '\0'; - printf( "post: %s\n", postdata ); + //printf( "post: %s\n", postdata ); long status_code; - if( !p->admin_disable_tor ) { - // Try TOR Hidden Service delivery - if( tor_inbox ) { - status_code = submit_activity( postdata, inbox, tor_inbox, keys, &fd, true ); + if( !fast_only || ( time(NULL) - p->last_hidden_service_delivery < (3600*24*30) ) ) { + if( !p->admin_disable_tor ) { + // Try TOR Hidden Service delivery + if( tor_inbox ) { + status_code = submit_activity( postdata, inbox, tor_inbox, keys, &fd, true ); + if( delivery_succeeded(status_code) ) { + p->last_hidden_service_delivery = time(NULL); + goto success; + } + } + + // Try TOR delivery + status_code = submit_activity( postdata, inbox, inbox, keys, &fd, true ); if( delivery_succeeded(status_code) ) { - p->last_hidden_service_delivery = time(NULL); + p->last_tor_delivery = time(NULL); goto success; } } + } - // Try TOR delivery - status_code = submit_activity( postdata, inbox, inbox, keys, &fd, true ); + if( !fast_only || ( time(NULL) - p->last_successful_delivery < (3600*24*30 ) ) ) { + // Try clearnet delivery + status_code = submit_activity( postdata, inbox, inbox, keys, &fd, false ); if( delivery_succeeded(status_code) ) { - p->last_tor_delivery = time(NULL); + p->last_successful_delivery = time(NULL); goto success; } - } - // Try clearnet delivery - status_code = submit_activity( postdata, inbox, inbox, keys, &fd, false ); + // delivery failed + printf( "\nServer returned status code %ld\n", status_code ); + if( env->retry_after ) { + env->retries += 1; + } + if( p ) { + p->last_failed_delivery = time(NULL); - // delivery failed - printf( "\nServer returned status code %ld\n", status_code ); - if( env->retry_after ) { - env->retries += 1; - } - if( p ) { - p->last_failed_delivery = time(NULL); + if( p->last_successful_delivery - p->last_failed_delivery > 60*60*24*7 ) { + // At least one week since last successful delivery + printf( "Over a week since last successful delivery, marking for discard.\n" ); + env->retries = g_server->outbox_discard_limit; + } - if( p->last_successful_delivery - p->last_failed_delivery > 60*60*24*7 ) { - // At least one week since last successful delivery - printf( "Over a week since last successful delivery, marking for discard.\n" ); - env->retries = g_server->outbox_discard_limit; + peer_save(p); } - - peer_save(p); - } - if( env->retries >= g_server->outbox_discard_limit ) { - // Force discard after 10 delivery attempts - // TODO: change this to a configuration option - goto discard; + if( env->retries >= g_server->outbox_discard_limit ) { + // Force discard after 10 delivery attempts + // TODO: change this to a configuration option + goto discard; + } + env->retry_after = time(NULL) + 60 * ( env->retries + 1 ) * ( env->retries + 1 ); + outbox_envelope_save(env); } - env->retry_after = time(NULL) + 60 * ( env->retries + 1 ) * ( env->retries + 1 ); - outbox_envelope_save(env); goto failed; @@ -333,33 +341,36 @@ discard: goto cleanup; } -static bool process_pending() +static bool process_pending( bool fast_only ) { - int head = fs_list_get("data/outbox/HEAD"); - int tail = fs_list_get("data/outbox/TAIL"); + DIR* d = opendir("data/outbox"); + if( !d ) { return false; } + + struct dirent* entry; + bool result = false; - for( int i = head; i > tail; --i ) { + while( (entry=readdir(d)) ) { + char* remain; + int i = strtol(entry->d_name,&remain,10); + if( 0 != strcmp( remain, ".json" ) ) { continue; } + struct outbox_envelope* env = outbox_envelope_from_id( i ); - if( !env ) { - if( i == tail+1 ) { - // Envelope already sent, advance tail - fs_list_set( "data/outbox/TAIL", i ); - tail += 1; - result = true; - } - } else { + if( env ) { if( env->sent ) { outbox_envelope_delete(env); - } else if( process_envelope(env) ) { - printf( "Done with outbox/%d.json\n", i ); + } else if( process_envelope(env, fast_only ) ) { + printf( "Envelope data/outbox/%d.json sent\n", i ); outbox_envelope_delete(env); - return true; + env = NULL; } } + outbox_envelope_free(env); fflush(stdout); } + closedir(d); + return result; } bool cleanup_box( const char* box ); @@ -371,8 +382,8 @@ void process_outbox() while( !terminate ) { bool activity = false; - activity |= process_pending(); - //activity |= cleanup_box("data/outbox"); + activity |= process_pending(true); + activity |= process_pending(false); if( !activity ) { fflush(stdout); diff --git a/src/model/account/ap_sync.c b/src/model/account/ap_sync.c index 8947755..114730c 100644 --- a/src/model/account/ap_sync.c +++ b/src/model/account/ap_sync.c @@ -78,7 +78,8 @@ succeeded: goto cleanup; cleanup: if( a ) { - a->next_update = time(NULL) + (60*60*24*3) + (rand() % (60*60*24*2)); // Next update in 3-5 days + //a->next_update = time(NULL) + (60*60*24*1) + (rand() % (60*60*24*2)); // Next update in 1-3 days + a->next_update = time(NULL) + (60*60*3); // 3 hours until next update printf( "Account saved.\n" ); account_save(a); account_index_webfinger(a); diff --git a/src/model/activity.c b/src/model/activity.c index 77ef051..20e8b90 100644 --- a/src/model/activity.c +++ b/src/model/activity.c @@ -245,15 +245,21 @@ struct ap_object* activity_create_Note( struct status* s ) act->source.content = strdup(s->source); } act->content.content = strdup(status_render_source(s,g_server->domain)); - if( s->in_reply_to ) { - struct status* s_in_reply_to = status_from_id( s->in_reply_to ); - if( s_in_reply_to ) { - act->in_reply_to = strdup( s_in_reply_to->url ); - status_free(s_in_reply_to); + if( s->in_reply_to.id ) { + if( s->in_reply_to.url ) { + act->in_reply_to = strdup( s->in_reply_to.url ); + } else { + struct status* s_in_reply_to = status_from_id( s->in_reply_to.id ); + if( s_in_reply_to ) { + act->in_reply_to = strdup( s_in_reply_to->url ); + status_free(s_in_reply_to); + } } } - if( s->quote_id ) { - struct status* s_quote_post = status_from_id( s->quote_id ); + if( s->quote.url ) { + act->quote_url = strdup(s->quote.url); + } else if( s->quote.id ) { + struct status* s_quote_post = status_from_id( s->quote.id ); if( s_quote_post ) { act->quote_url = strdup( s_quote_post->url ); status_free(s_quote_post); diff --git a/src/model/fetch.c b/src/model/fetch.c index 3ec8c70..f125212 100644 --- a/src/model/fetch.c +++ b/src/model/fetch.c @@ -90,7 +90,7 @@ static bool do_fetch_tor( const char* uri, struct fetch_data* fd, const char* re HTTP_REQ_RESULT_STATUS, &status_code, HTTP_RES_HEADER_CALLBACK, fetch_handle_header, (void*)fd, HTTP_REQ_PROXY, proxy, - HTTP_REQ_TIMEOUT, (void*)5, + HTTP_REQ_TIMEOUT, (void*)10, NULL, }; printf( "GET %s\n", uri ); diff --git a/src/model/gc.c b/src/model/gc.c index 8c9202b..2f27d4b 100644 --- a/src/model/gc.c +++ b/src/model/gc.c @@ -47,7 +47,9 @@ void mark_post( struct bitmap* b, int status_id, bool force ) if( s->published > time(NULL) - 3600 * 24 * 2 ) { // keep all posts in the last 2 days e->marked = true; } else if( s->account_id == owner_account_id ) { // Keep all owner posts - if( s->repost_id ) { + if( s->repost.id ) { + e->marked = true; + } else if( s->quote.id ) { e->marked = true; } } else if( s->bookmarked ) { @@ -64,11 +66,14 @@ void mark_post( struct bitmap* b, int status_id, bool force ) } // Flood fill to keep all related posts alive - if( s->repost_id ) { - mark_post( b, s->repost_id, true ); + if( s->repost.id ) { + mark_post( b, s->repost.id, true ); + } + if( s->in_reply_to.id ) { + mark_post( b, s->in_reply_to.id, true ); } - if( s->in_reply_to ) { - mark_post( b, s->in_reply_to, true ); + if( s->quote.id ) { + mark_post( b, s->quote.id, true ); } for( int i = 0; i < s->replies.count; ++i ) { mark_post( b, s->replies.items[i], true ); diff --git a/src/model/inbox_envelope.c b/src/model/inbox_envelope.c index f1476f5..967474b 100644 --- a/src/model/inbox_envelope.c +++ b/src/model/inbox_envelope.c @@ -6,7 +6,6 @@ #include "json/layout.h" #include "http/server/request.h" #include "http/server/header.h" -#include "ffdb/fs_list.h" #include "collections/collection.h" #include "collections/array.h" @@ -89,6 +88,7 @@ bool envelope_create_from_request( struct http_request* req ) memset( &env, 0, sizeof(env) ); // Read body in + printf("reading body..." ); fflush(stdout); FILE* body = http_request_get_request_data(req); size_t s; FILE* mem = open_memstream(&env.body, &s); @@ -96,6 +96,7 @@ bool envelope_create_from_request( struct http_request* req ) fclose(mem); env.body = realloc(env.body,s+1); env.body[s] = '\0'; + printf( "done.\n" ); // Create timestamp uint64_t time_ns; @@ -120,7 +121,8 @@ bool envelope_create_from_request( struct http_request* req ) } // Get a space in the inbox - int head = fs_list_inc( "data/inbox/HEAD" ); + int head = ts.tv_sec * 1000 + ts.tv_nsec / 1000000; + printf( "using head=%d\n", head ); // Setup filenames char filename[512]; diff --git a/src/model/outbox_envelope.c b/src/model/outbox_envelope.c index da34bcd..3b4fc48 100644 --- a/src/model/outbox_envelope.c +++ b/src/model/outbox_envelope.c @@ -1,12 +1,12 @@ #include "outbox_envelope.h" #include "json/layout.h" -#include "ffdb/fs_list.h" #include #include #include #include +#include #define OBJ_TYPE struct outbox_envelope static struct json_object_field layout[] = { @@ -50,7 +50,11 @@ void outbox_envelope_free( struct outbox_envelope* env ) void outbox_envelope_save( struct outbox_envelope* env ) { if( env->id == 0 ) { - int id = fs_list_inc( "data/outbox/HEAD" ); + struct timespec ts; + clock_gettime( CLOCK_REALTIME, &ts ); + + int id = ts.tv_sec * 1000 + ts.tv_nsec / (100*1000*1000) + (rand() % 100); + //int id = fs_list_inc( "data/outbox/HEAD" ); env->id = id; } @@ -78,11 +82,6 @@ struct outbox_envelope* outbox_envelope_from_id( int id ) return env; } -struct outbox_envelope* outbox_envelope_load_next() -{ - return outbox_envelope_from_id( fs_list_get( "data/outbox/TAIL" ) + 1 ); -} - void outbox_envelope_delete( struct outbox_envelope* env ) { char filename[512]; diff --git a/src/model/outbox_envelope.h b/src/model/outbox_envelope.h index 2565128..f0bedab 100644 --- a/src/model/outbox_envelope.h +++ b/src/model/outbox_envelope.h @@ -21,7 +21,6 @@ void outbox_envelope_free( struct outbox_envelope* env ); struct outbox_envelope* outbox_envelope_from_id( int id ); void outbox_envelope_save( struct outbox_envelope* env ); -//struct outbox_envelope* outbox_envelope_load_next(); void outbox_envelope_delete( struct outbox_envelope* env ); struct outbox_envelope_list diff --git a/src/model/status.c b/src/model/status.c index 3637453..63230d5 100644 --- a/src/model/status.c +++ b/src/model/status.c @@ -54,10 +54,58 @@ static struct json_object_field status_layout[] = { JSON_FIELD_ENUM( visibility, visibility_enum, false ), JSON_FIELD_DATETIME( published, false ), - JSON_FIELD_INTEGER( in_reply_to, false ), - JSON_FIELD_INTEGER( quote_id, false ), - JSON_FIELD_INTEGER( repost_id, false ), - JSON_FIELD_INTEGER( root_status_id, false ), + { + .key = "in_reply_to", + .offset = offsetof( OBJ_TYPE, in_reply_to.id ), + .required = false, + .type = &json_field_integer, + }, + { + .key = "in_reply_to_url", + .offset = offsetof( OBJ_TYPE, in_reply_to.url ), + .required = false, + .type = &json_field_string, + }, + + { + .key = "quote_id", + .offset = offsetof( OBJ_TYPE, quote.id ), + .required = false, + .type = &json_field_integer, + }, + { + .key = "quote_url", + .offset = offsetof( OBJ_TYPE, quote.url ), + .required = false, + .type = &json_field_string, + }, + + { + .key = "repost_id", + .offset = offsetof( OBJ_TYPE, repost.id ), + .required = false, + .type = &json_field_integer, + }, + { + .key = "repost_url", + .offset = offsetof( OBJ_TYPE, repost.url ), + .required = false, + .type = &json_field_string, + }, + + + { + .key = "root_status_id", + .offset = offsetof( OBJ_TYPE, root_status.id ), + .required = false, + .type = &json_field_integer, + }, + { + .key = "root_status_url", + .offset = offsetof( OBJ_TYPE, root_status.url ), + .required = false, + .type = &json_field_string, + }, JSON_FIELD_INTEGER( reposted_status_id, false ), JSON_FIELD_ARRAY_OF_STRINGS( media, false ), @@ -137,6 +185,7 @@ struct status* status_from_id( unsigned int id ) if( id == 0 ) { return NULL; } struct status* s = NULL; + bool needs_save = false; FILE* f = open_status_data_file( id, "r" ); if( !f ) { return NULL; } @@ -175,18 +224,53 @@ struct status* status_from_id( unsigned int id ) free( s->media.items ); memset( &s->media, 0, sizeof(s->media) ); - status_save(s); + needs_save = true; } + // Fix source field if( !s->source ) { s->source = strdup(""); } + // Fix remote field + if( s->account_id == owner_account_id ) { + s->remote =false; + } + + // Fix url field if( !s->remote && !s->url ) { s->url = aformat( "https://%s/note/%d", g_server->domain, s->id ); } - if( s->account_id == owner_account_id ) { - s->remote =false; + + // Fill in reference urls + if( s->in_reply_to.id && !s->in_reply_to.url ) { + struct status* in_reply_to = status_from_id( s->in_reply_to.id ); + if( in_reply_to && in_reply_to->url ) { + s->in_reply_to.url = strdup(in_reply_to->url); + needs_save = true; + } + status_free(in_reply_to); + } + if( s->quote.id && !s->quote.url ) { + struct status* quote = status_from_id( s->quote.id ); + if( quote && quote->url ) { + s->quote.url = strdup(quote->url); + needs_save = true; + } + status_free(quote); + } + if( s->root_status.id && ( s->root_status.id != s->id ) && !s->root_status.url ) { + struct status* root_status = status_from_id( s->root_status.id ); + if( root_status && root_status->url ) { + s->root_status.url = strdup(root_status->url); + needs_save = true; + } + status_free(root_status); + } + + // Save changes + if( needs_save ) { + status_save(s); } return s; @@ -198,7 +282,8 @@ struct status* status_new_repost( struct status* s, struct account* a ) memset(repost,0,sizeof(*repost)); repost->account_id = a->id; - repost->repost_id = s->id; + repost->repost.id = s->id; + repost->repost.url = strdup(s->url); repost->published = time(NULL); status_add_repost( s, repost ); @@ -382,6 +467,13 @@ bool status_sync_from_activity_pub( struct status* s, struct ap_object* act ) goto failed; } + // Update account if it should be + if( time(NULL) >= a->next_update ) { + printf( "* Updating account %s\n", a->account_url ); + account_sync_from_activity_pub( a->id, true ); + } + + // Handle post visibility bool is_public = false; for( int i = 0; i < act->to.count; ++i ) { @@ -534,7 +626,8 @@ bool status_sync_from_activity_pub( struct status* s, struct ap_object* act ) if( parent_id ) { status_make_reply_to( s, parent_id ); - s->in_reply_to = parent_id; + s->in_reply_to.id = parent_id; + s->in_reply_to.url = strdup(act->in_reply_to); } //printf( "Status %d has been marked as a reply to %d (%s)\n", s->id, parent_id, act->in_reply_to ); } @@ -738,7 +831,10 @@ void status_assign_local_id( struct status* s ) int head = fs_list_inc( "data/statuses/HEAD" ); s->id = head; - s->root_status_id = s->id; + s->root_status.id = s->id; + if( s->url ) { + s->root_status.url = strdup(s->url); + } } bool status_save_new( struct status* s ) @@ -814,6 +910,11 @@ void status_free( struct status* s ) } free(s->reacts.items); + free(s->in_reply_to.url ); + free(s->quote.url); + free(s->repost.url); + free(s->root_status.url); + free(s->likes.items); free(s->replies.items); free(s->reposts.items); @@ -890,13 +991,16 @@ void status_make_reply_to( struct status* s, int in_reply_to_id ) // Add this status to the other struct status* in_reply_to = status_from_id( in_reply_to_id ); if( !in_reply_to ) { - s->in_reply_to = 0; + s->in_reply_to.id = 0; return; } // Setup this status's reply fields - s->in_reply_to = in_reply_to_id; - s->root_status_id = in_reply_to->root_status_id; + s->in_reply_to.id = in_reply_to_id; + s->root_status.id = in_reply_to->root_status.id; + if( in_reply_to->root_status.url ) { + s->root_status.url = strdup( in_reply_to->root_status.url ); + } // Record in parent as reply status_add_reply( in_reply_to, s ); @@ -917,12 +1021,13 @@ void status_make_quote_of( struct status* s, int id_quote_of ) { struct status* quoted_post = status_from_id( id_quote_of ); if( !quoted_post ) { - s->quote_id = 0; + s->quote.id = 0; return; } // Set quoted id - s->quote_id = id_quote_of; + s->quote.id = id_quote_of; + s->quote.url = strdup(quoted_post->url); // Record quote in parent status_add_quote( quoted_post, s ); @@ -953,7 +1058,7 @@ void status_get_context( struct status* s, void* ancestors_ptr, void* replies_pt memset(replies,0,sizeof(*replies)); struct status* parent = NULL; - for( int i = s->in_reply_to; i != 0; i = parent->in_reply_to ) { + for( int i = s->in_reply_to.id; i != 0; i = parent->in_reply_to.id ) { parent = status_from_id( i ); if( !parent ) { break; } array_append( ancestors, sizeof(parent), &parent ); @@ -991,8 +1096,8 @@ void status_get_quotes( struct status* s, void* quotes_ptr ) void status_add_react( struct status* s, const char* react, struct account* a ) { - if( s->repost_id ) { - struct status* reposted_status = status_from_id( s->repost_id ); + if( s->repost.id ) { + struct status* reposted_status = status_from_id( s->repost.id ); status_add_react(reposted_status,react,a); status_free(reposted_status); return; @@ -1050,8 +1155,8 @@ done: } void status_remove_react( struct status* s, const char* react, struct account* a ) { - if( s->repost_id ) { - struct status* reposted_status = status_from_id( s->repost_id ); + if( s->repost.id ) { + struct status* reposted_status = status_from_id( s->repost.id ); status_remove_react(reposted_status,react,a); status_free(reposted_status); return; @@ -1097,8 +1202,8 @@ update_entry: } void status_add_like( struct status* s, struct account* a ) { - if( s->repost_id ) { - struct status* reposted_status = status_from_id( s->repost_id ); + if( s->repost.id ) { + struct status* reposted_status = status_from_id( s->repost.id ); status_add_like(reposted_status,a); status_free(reposted_status); return; @@ -1136,8 +1241,8 @@ void status_add_like( struct status* s, struct account* a ) } void status_remove_like( struct status* s, struct account* a ) { - if( s->repost_id ) { - struct status* reposted_status = status_from_id( s->repost_id ); + if( s->repost.id ) { + struct status* reposted_status = status_from_id( s->repost.id ); status_remove_like(reposted_status,a); status_free(reposted_status); return; diff --git a/src/model/status.h b/src/model/status.h index 1cfb7d3..13d8963 100644 --- a/src/model/status.h +++ b/src/model/status.h @@ -17,6 +17,8 @@ enum status_visibility_direct = 3, }; +#include "model/status/ref.h" + struct status { unsigned int id; @@ -36,10 +38,10 @@ struct status time_t published; int visibility; - int in_reply_to; - int quote_id; - int repost_id; - int root_status_id; + struct status_ref in_reply_to; + struct status_ref quote; + struct status_ref repost; + struct status_ref root_status; int reposted_status_id; // if this post was reposted, this will be the id of that status struct { diff --git a/src/model/status/ref.h b/src/model/status/ref.h new file mode 100644 index 0000000..18afc37 --- /dev/null +++ b/src/model/status/ref.h @@ -0,0 +1,11 @@ +#pragma once + +struct status_ref +{ + int id; + char* url; +}; + +extern struct json_field_type status_ref_type; +void status_ref_free_composite( struct status_ref* ref ); + diff --git a/src/view/api/Status.c b/src/view/api/Status.c index cc64798..e8d8f1a 100644 --- a/src/view/api/Status.c +++ b/src/view/api/Status.c @@ -60,7 +60,7 @@ bool owner_favorited_callback( void* field_data, bool is_read, bool* value ) static bool write_in_reply_to( struct json_writer* jw, const char* field_name, void* field_data, struct json_reflection* layout_field_data, int offset ) { struct status* s = field_data; - struct status* in_reply_to = status_from_id( s->in_reply_to ); + struct status* in_reply_to = status_from_id( s->in_reply_to.id ); if( in_reply_to ) { json_write_field_name(jw,"in_reply_to_account_id"); fprintf( jw->f, "\"%d\"", in_reply_to->account_id ); @@ -320,7 +320,7 @@ bool context_url_callback( void* field_data, bool is_read, char** res ) { struct status* s = field_data; if( !is_read ) { - *res = aformat( "https://%s/contexts/%d", g_server->domain, s->root_status_id ); + *res = aformat( "https://%s/contexts/%d", g_server->domain, s->root_status.id ); return true; } return false; @@ -336,9 +336,9 @@ bool quote_url_callback( void* field_data, bool is_read, char** val ) if( is_read ) { return false; } struct status* s = field_data; - if( s->quote_id == 0 ) { return false; } + if( s->quote.id == 0 ) { return false; } - struct status* quoted_post = status_from_id(s->quote_id); + struct status* quoted_post = status_from_id(s->quote.id); if( !quoted_post ) { return false; } *val = strdup(quoted_post->url ); status_free(quoted_post); @@ -350,7 +350,7 @@ bool quote_visible_callback( void* field_data, bool is_read, bool* val ) struct status* s = field_data; - *val = ( s->quote_id != 0 ); + *val = ( s->quote.id != 0 ); return true; } @@ -380,7 +380,7 @@ static struct json_object_field pleroma_layout[] = { }, { .key = "conversation_id", - .offset = offsetof( OBJ_TYPE, root_status_id ), + .offset = offsetof( OBJ_TYPE, root_status.id ), .type = &json_field_integer, }, JSON_FIELD_FIXED_NULL( direct_conversation_id ), // Maybe this is breaking things in the home feed? @@ -409,7 +409,7 @@ static struct json_object_field pleroma_layout[] = { JSON_FIELD_FIXED_NULL( pinned_at ), { .key = "quote", - .offset = offsetof( OBJ_TYPE, quote_id ), + .offset = offsetof( OBJ_TYPE, quote.id ), .type = &Status_reference_type, }, { @@ -526,7 +526,7 @@ struct json_object_field api_Status_layout[] = { }, { .key = "reblog", - .offset = offsetof(OBJ_TYPE, repost_id), + .offset = offsetof(OBJ_TYPE, repost.id), .type = &Status_reference_type, }, {