Add error reporting to account_sync_from_acitvity_pub, add handling of likes, index statuses by uri, make reposts and likes report correct values in mastodon api, fix adding post to empty timeline

master
teknomunk 1 year ago
parent 7b35934e18
commit 3f0b5dac86

@ -186,6 +186,34 @@ failed:
goto cleanup;
}
static bool route_like( struct ap_activity* act )
{
struct status* s = NULL;
switch( act->object.tag ) {
case apaot_ref:
s = status_from_uri( act->object.ref );
break;
case apaot_activity:
s = status_from_uri( act->object.ptr->id );
if( !s ) {
printf( "! Status %s doesn't exist locally\n", act->object.ptr->id );
return false;
}
break;
}
// Get actor account
struct account* liker = account_from_uri( act->actor );
if( !liker ) {
liker = account_fetch_from_uri( act->actor );
}
status_add_like( s, liker );
return true;
}
static bool route_create( struct ap_activity* act )
{
return route_follower_post(act)
@ -201,6 +229,7 @@ static bool route_activity( struct ap_activity* act )
switch( act->type ) {
case apat_undo: return route_undo_activity(act);
case apat_follow: return route_follow(act);
case apat_like: return route_like(act);
case apat_create: return route_create(act);
default:
printf( "Unhandled activity type: %d\n", act->type );

@ -1 +1 @@
Subproject commit 3bd10ea74624264342c02976abc91a84f87d88ed
Subproject commit 0b4becf5ae27c8fdd941b8559b797ec74c9ef4a3

@ -76,7 +76,7 @@ int main( int argc, char* argv[] )
int section = 0;
sscanf(argv[1],"--section=%d",&section);
switch( section ) {
//case 1: process_inbox(); goto exit;
case 1: process_inbox(); goto exit;
case 2: process_outbox(); goto exit;
case 3: built_in_test(); goto exit;
@ -86,11 +86,13 @@ int main( int argc, char* argv[] )
// Process inbox
//*
int inbox_handler_pid = -1;
if( !( inbox_handler_pid = fork() ) ) {
prctl(PR_SET_PDEATHSIG, SIGHUP);
process_inbox();
}
//*/
//*
// Process outbox

@ -48,9 +48,9 @@ static struct json_object_field account_layout[] = {
{ "avatar", offsetof( struct account, avatar.url ), true, &json_field_string },
{ "avatar_static", offsetof( struct account, avatar.static_url ), true, &json_field_string },
{ "account_type", offsetof( struct account, account_type ), true, &json_field_enum, account_types_enum },
{ "account_url", offsetof( struct account, account_url ), true, &json_field_string },
{ "inbox", offsetof( struct account, inbox ), false, &json_field_string },
{ "note", offsetof( struct account, note ), false, &json_field_string },
{ "account_url", offsetof( struct account, account_url ), true, &json_field_string },
{ NULL },
};
@ -139,13 +139,17 @@ struct account* account_from_webfinger( const char* handle )
return account_from_id(id);
}
void account_sync_from_acitvity_pub( unsigned int account_id )
bool account_sync_from_acitvity_pub( unsigned int account_id )
{
char filename[512];
snprintf( filename, 512, "data/accounts/%d/ap.json", account_id );
struct ap_account* ap = ap_account_from_file( filename );
//printf( "ap = " ); ap_account_debug_dump(ap);
if( !ap ) {
printf( "! Failed to sync account %d from %s\n", account_id, filename );
return false;
}
printf( "ap = " ); ap_account_debug_dump(ap);
struct account* a = malloc(sizeof(struct account));
memset(a,0,sizeof(*a));
@ -180,6 +184,8 @@ void account_sync_from_acitvity_pub( unsigned int account_id )
ap_account_free(ap);
account_free(a);
return true;
}
struct crypto_keys* account_get_public_key( struct account* a, const char* key_name )
{
@ -264,7 +270,10 @@ struct account* account_fetch_from_uri( const char* uri )
rename(tmp_filename,filename);
}
account_sync_from_acitvity_pub( account_id );
// Fail if we can't sync
if( !account_sync_from_acitvity_pub( account_id ) ) {
return NULL;
}
return account_from_id(account_id);
}

@ -45,7 +45,7 @@ struct account* account_fetch_from_uri( const char* uri );
struct account* account_new();
void account_free( struct account* a );
void account_save( struct account* a );
void account_sync_from_acitvity_pub( unsigned int id );
bool account_sync_from_acitvity_pub( unsigned int id );
struct crypto_keys* account_get_public_key( struct account* a, const char* key_name );
struct crypto_keys* account_get_private_key( struct account* a );

@ -19,6 +19,7 @@ static struct json_enum notification_type_enum[] = {
{ "mention", nt_mention },
{ "unfollow", nt_unfollow },
{ "block", nt_block },
{ "like", nt_like },
{ NULL, -1 },
};

@ -23,6 +23,7 @@ enum notification_type
nt_mention = 3,
nt_unfollow = 4,
nt_block = 5,
nt_like = 6,
};
struct notification* notification_from_id( int id );

@ -11,11 +11,12 @@
%( } )
"type": "%(
switch(n->type) {
case nt_favorite: fprintf(f,"favourite"); break;
case nt_follow: fprintf(f,"follow"); break;
case nt_favorite: fprintf(f,"favourite"); break;
case nt_follow: fprintf(f,"follow"); break;
case nt_like: fprintf(f,"favourite"); break;
case nt_unfollow:
case nt_block:
case nt_mention: fprintf(f,"mention"); break;
case nt_mention: fprintf(f,"mention"); break;
default: fprintf(f,"unknown-%d",n->type); break;
}; )"
}

@ -3,11 +3,14 @@
#include "status/react.h"
#include "model/account.h"
#include "model/timeline.h"
#include "model/ap/activity.h"
#include "model/notification.h"
// Submodules
#include "json/json.h"
#include "json/layout.h"
#include "ffdb/hash_index.h"
#include "sha256/sha256.h"
#include <stdio.h>
@ -17,12 +20,18 @@
static struct json_object_field status_layout[] = {
{ "account_id", offsetof( struct status, account_id ), true, &json_field_integer },
{ "url", offsetof( struct status, url ), false, &json_field_string },
{ "sensitive", offsetof( struct status, sensitive ), true, &json_field_bool },
{ "source", offsetof( struct status, source ), false, &json_field_string },
{ "content", offsetof( struct status, source ), false, &json_field_string },
{ "source", offsetof( struct status, source ), false, &json_field_string },
{ "sensitive", offsetof( struct status, sensitive ), true, &json_field_bool },
{ "media", offsetof( struct status, media ), false, &json_field_array_of, &json_field_string },
//{ "reacts", offsetof( struct status, reacts ), false, &json_field_array_of, &status_react_type },
{ "likes", offsetof( struct status, likes ), false, &json_field_array_of, &json_field_integer },
{ "reposts", offsetof( struct status, reposts ), false, &json_field_array_of, &json_field_integer },
{ NULL }
};
@ -54,6 +63,13 @@ struct status* status_from_id( unsigned int id )
return s;
}
struct status* status_from_uri( const char* uri )
{
int id = -1;
if( !hash_index_get( "data/statuses/uri", uri, &id ) ) { return NULL; }
return status_from_id(id);
}
struct status* status_new_system_unfollow( int account_id )
{
struct account* a = account_from_id(account_id);
@ -99,6 +115,12 @@ struct status* status_from_activity( struct ap_activity* act )
struct account* a = account_from_uri(act->actor);
s->account_id = a->id;
// Add status to account timeline
struct timeline* tl = timeline_from_id( a->id );
printf( "tl->id=%d\n", tl->id );
timeline_add_post(tl,s);
timeline_free(tl);
account_free(a);
s->source = strdup(act->source);
@ -134,6 +156,11 @@ void status_save( struct status* s )
snprintf( filename, 512, "data/statuses/%d.json", s->id );
json_write_object_layout_to_file( filename, "\t", status_layout, s );
// Index the status
if( s->url ) {
hash_index_set( "data/statuses/uri", s->url, s->id );
}
}
void status_free( struct status* s )
@ -150,6 +177,8 @@ void status_free( struct status* s )
}
free(s->reacts.items);
free(s->reposts.items);
free(s->content);
free(s);
}
@ -162,4 +191,24 @@ void status_add_react( struct status* s, const char* react )
// TODO generate outbox element
}
}
void status_add_like( struct status* s, struct account* a )
{
for( int i = 0; i < s->likes.count; ++i ) {
if( s->likes.items[i] == a->id ) {
return;
}
}
if( s->account_id == 0 ) {
// Create notification for liking the owner's post
struct notification* note = notification_new();
note->type = nt_like;
note->account_id = a->id;
note->created_at = time(NULL);
notification_save( note );
notification_free( note );
}
status_save(s);
}

@ -3,6 +3,8 @@
#include <stdbool.h>
#include <stdio.h>
struct account;
struct status
{
unsigned int id;
@ -22,11 +24,22 @@ struct status
struct status_react** items;
int count;
} reacts;
struct {
int* items;
int count;
} likes;
struct {
int* items;
int count;
} reposts;
};
struct status* status_from_id( unsigned int id );
struct status* status_new_system_unfollow( int account_id );
struct status* status_new_system_block( int account_id );
struct status* status_from_uri( const char* uri );
struct ap_activity;
struct status* status_from_activity( struct ap_activity* act );
@ -36,6 +49,7 @@ void status_save( struct status* s );
void status_free( struct status* s );
void status_add_react( struct status* s, const char* react );
void status_add_like( struct status* s, struct account* a );
char* status_render_source( struct status* s );

@ -36,12 +36,25 @@ struct timeline* timeline_block_load( int id, unsigned int head, unsigned int bl
tl->status_ids.items = NULL;
tl->status_ids.count = 0;
if( !json_read_object_layout_from_file( filename, timeline_block_layout, tl ) ) {
free(tl);
return NULL;
f = fopen( filename, "r" );
if( !f ) {
// New timeline
if( head == block && head == 0 ) {
return tl;
}
goto failed;
}
if( !json_read_object_layout_from_FILE( f, timeline_block_layout, tl ) ) { goto failed; }
cleanup:
return tl;
failed:
fclose(f);
free(tl);
tl = NULL;
goto cleanup;
}

@ -7,7 +7,7 @@
"created_at": "2022-12-12T02:52:24.000Z",
"emojis": [],
"favourited": false,
"favourites_count": 0,
"favourites_count": %d{ s->likes.count },
"id": "%d{ s->id }",
"in_reply_to_account_id": null,
"in_reply_to_id": null,
@ -27,7 +27,14 @@
"url": "%s{s->media.items[i]}"
}%s{ i < s->media.count - 1 ? "," : "" }
%( } )],
"mentions": [],
"mentions": [%(/*
{
"id": "0",
"username": "teknomunk",
"acct": "teknomunk@apogee.polaris-1.work",
"url": "https://apogee.polaris-1.work/owner"
}
*/)],
"muted": false,
"pinned": false,
"pleroma": {
@ -55,8 +62,8 @@
},
"poll": null,
"reblog": null,
"reblogged": false,
"reblogs_count": 1,
"reblogged": %s{ s->reposts.count > 0 ? "true": "false" },
"reblogs_count": %d{ s->reposts.count },
"replies_count": 0,
"sensitive": false,
"spoiler_text": "",

Loading…
Cancel
Save