Start adding automatic directory creaction to model, implement working /inbox forwarding for owner, implement activity_deliver, rework account federation to use activity_deliver

master
teknomunk 1 year ago
parent b0a4f53375
commit e4c6c42975

@ -134,7 +134,7 @@ static bool context_writer( struct json_writer* jw, const char* field_name, void
json_write_string( jw->f, ctx->extra.items[i] );
}
if( ctx->language ) {
fprintf( jw->f, ",{ \"@language\":\"%s\"", langs[ctx->language] );
fprintf( jw->f, ",{ \"@language\":\"%s\"", langs[ctx->language-1] );
}
}
fprintf( jw->f, "]" );

@ -178,19 +178,9 @@ bool handle_repost( struct http_request* req, struct status* s )
{
bool result = false;
struct account* owner = account_from_id(owner_account_id);
struct status* repost = status_new_repost( s, owner );
// Flag the status as reposted
s->reposted_status_id = repost->id;
status_save(s);
// Add repost to timelines
status_add_to_timeline( repost, owner->id );
status_add_to_timeline( repost, home_timeline_id );
status_add_to_timeline( repost, public_timeline_id );
// Federate
account_announce( owner, s, repost );
struct status* repost = account_announce( owner, s, NULL, NULL );
// Show the new status as the response
show_status( req, repost );

@ -4,6 +4,7 @@
#include "ap/object.h"
#include "model/account.h"
#include "model/status.h"
#include "model/activity.h"
#include "model/inbox_envelope.h"
@ -33,6 +34,9 @@ bool handle_forward( struct ap_envelope* env, struct ap_object* act )
a = account_from_uri( act->actor );
if( !a->local ) { goto failed; };
act->published = time(NULL);
act->id = strdup( a->account_url );
// Save to disk
activity_allocate_local_id(act);
activity_save(act);
@ -41,10 +45,22 @@ bool handle_forward( struct ap_envelope* env, struct ap_object* act )
printf( "Forwarding activity. act=" );
ap_object_write_to_FILE( act, stdout );
// TODO: try to inject to create a status
// Deliver activity
activity_deliver( act );
// Try to inject to create a status
if( act->type == ap_Create ) {
struct status* s = status_from_activity( act );
if( s ) {
status_save_new(s);
account_create( a, s );
}
} else if( act->type == ap_Announce ) {
struct status* s = status_from_uri( act->object.ref );
if( s ) {
status_free( account_announce( a, s, NULL, act ) );
}
} else {
// Deliver activity
activity_deliver( act );
}
goto failed;
cleanup:

@ -28,6 +28,7 @@ static bool process_envelope( struct outbox_envelope* env )
struct crypto_keys* keys = NULL;
FILE* f = NULL;
struct ap_object* act = NULL;
struct account* to_account = NULL;
if( env->sent ) { return false; }
if( env->retry_after > time(NULL) ) { return false; }
@ -38,7 +39,7 @@ static bool process_envelope( struct outbox_envelope* env )
printf( "activity_id=%d\n", env->activity_id );
// Get outbox URL
struct account* to_account = account_from_id( env->account_id );
to_account = account_from_id( env->account_id );
// Load crypto keys
keys = crypto_keys_new();

@ -4,6 +4,7 @@
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
const char* format( char* buffer, int size, const char* f, ... )
{
@ -31,3 +32,16 @@ char* safe_strdup( const char* str )
return strdup(str);
}
void mkdir_p( const char* ch, int mode )
{
char buffer[512];
strncpy(buffer,ch,512);
char* rem = NULL;
char next_create[512] = "";
for( char* iter = strtok_r(buffer,"/",&rem); iter; iter = strtok_r(NULL,"/",&rem) ) {
strcat(next_create,iter);
mkdir( next_create, mode );
strcat(next_create,"/");
}
}

@ -3,4 +3,5 @@
const char* format( char* buffer, int size, const char* f, ... );
char* aformat( const char* f, ... );
char* safe_strdup( const char* str );
void mkdir_p( const char* ch, int mode );

@ -119,7 +119,7 @@ bool account_does_follow( struct account* a, int account_id );
void account_deliver_activity( struct account* a, struct ap_object* act, struct outbox_envelope_list* oel );
void account_deliver_activity_to_followers( struct account* a, struct ap_object* act, struct outbox_envelope_list* oel );
void account_create( struct account* a, struct status* s );
void account_announce( struct account* a, struct status* original_post, struct status* local_repost );
struct status* account_announce( struct account* a, struct status* original_post, struct status* local_repost, struct ap_object* act );
void account_follow( struct account* a, struct account* to_follow );
void account_unfollow( struct account* a, struct account* to_unfollow );
void account_update( struct account* a );

@ -89,51 +89,54 @@ void account_create( struct account* a, struct status* s )
status_add_to_timeline( s, home_timeline_id );
//status_add_post_to_timeline( s, federated_timeline_id );
struct outbox_envelope_list oel;
memset(&oel,0,sizeof(oel));
account_deliver_activity_to_followers( a, create, &oel );
printf( "Delivering to %d inboxes\n", oel.count );
outbox_envelope_list_save(&oel);
outbox_envelope_list_free_composite(&oel);
//account_deliver_activity_to_followers( a, create, &oel );
activity_deliver( create );
ap_object_free(create);
ap_object_free(note);
}
void account_announce( struct account* a, struct status* original_post, struct status* local_repost )
struct status* account_announce( struct account* a, struct status* original_post, struct status* local_repost, struct ap_object* act )
{
struct ap_object* act = ap_object_new();
activity_allocate_local_id(act);
act->id = aformat( "https://%s/activity/%d", g_server->domain, act->local_id );
act->published = time(NULL);
act->type = ap_Announce;
act->actor = strdup(a->account_url);
act->object.tag = apaot_ref;
act->object.ref = strdup(original_post->url);
// Create To: list
char* str = strdup("https://www.w3.org/ns/activitystreams#Public");
array_append( &act->to, sizeof(str), &str );
str = aformat("https://%s/owner/followers", g_server->domain );
array_append( &act->to, sizeof(str), &str );
struct account* origin_post_account = account_from_id(original_post->account_id);
str = strdup(origin_post_account->account_url);
array_append( &act->to, sizeof(str), &str );
if( !local_repost ) {
local_repost = status_new_repost( original_post, a );
struct outbox_envelope_list oel;
memset(&oel,0,sizeof(oel));
// Flag the status as reposted
original_post->reposted_status_id = local_repost->id;
status_save(original_post);
account_deliver_activity_to_followers( a, act, &oel );
account_deliver_activity( origin_post_account, act, &oel );
// Add repost to timelines
status_add_to_timeline( local_repost, a->id );
if( a->id == owner_account_id ) {
status_add_to_timeline( local_repost, home_timeline_id );
}
status_add_to_timeline( local_repost, public_timeline_id );
}
printf( "Delivering to %d inboxes\n", oel.count );
outbox_envelope_list_save(&oel);
outbox_envelope_list_free_composite(&oel);
if( !act ) {
act = ap_object_new();
activity_allocate_local_id(act);
act->id = aformat( "https://%s/activity/%d", g_server->domain, act->local_id );
act->published = time(NULL);
act->type = ap_Announce;
act->object.tag = apaot_ref;
act->object.ref = strdup(original_post->url);
act->actor = strdup(a->account_url);
// Create To: list
char* str = strdup("https://www.w3.org/ns/activitystreams#Public");
array_append( &act->to, sizeof(str), &str );
str = aformat("https://%s/owner/followers", g_server->domain );
array_append( &act->to, sizeof(str), &str );
struct account* origin_post_account = account_from_id(original_post->account_id);
str = strdup(origin_post_account->account_url);
array_append( &act->to, sizeof(str), &str );
account_free(origin_post_account);
}
activity_save(act);
ap_object_write_to_FILE( act, stdout );
activity_deliver( act );
// Link status to activity
local_repost->activity_id = act->local_id;
@ -143,8 +146,9 @@ void account_announce( struct account* a, struct status* original_post, struct s
status_save(original_post);
cleanup:
account_free(origin_post_account);
ap_object_free(act);
return local_repost;
}
void account_follow( struct account* a, struct account* to_follow )
@ -216,14 +220,7 @@ void account_update( struct account* a )
char* str = aformat("https://%s/owner/followers", g_server->domain );
array_append( &act->to, sizeof(str), &str );
struct outbox_envelope_list oel;
memset(&oel,0,sizeof(oel));
account_deliver_activity_to_followers( a, act, &oel );
printf( "Delivering to %d inboxes\n", oel.count );
outbox_envelope_list_save(&oel);
outbox_envelope_list_free_composite(&oel);
activity_deliver( act );
activity_save(act);
ap_object_free(act);

@ -230,7 +230,9 @@ struct ap_object* activity_create_Note( struct status* s )
act->id = aformat( "https://%s/note/%d", g_server->domain, s->id );
act->type = ap_Note;
act->published = s->published;
act->source.content = strdup(s->source);
if( s->source ) {
act->source.content = strdup(s->source);
}
act->content.content = strdup(status_render_source(s));
if( s->in_reply_to ) {
struct status* s_in_reply_to = status_from_id( s->in_reply_to );
@ -327,9 +329,51 @@ struct ap_object* activity_create_Create( struct ap_object* object )
return act;
}
void activity_deliver( struct ap_object* obj )
static void deliver_to( struct outbox_envelope_list* oel, struct ap_object* act, const char* uri )
{
char owner_followers[512];
snprintf( owner_followers,512, "https://%s/owner/followers", g_server->domain );
if( 0 == strcmp( owner_followers, uri ) ) {
struct account* owner = account_from_id( owner_account_id );
account_deliver_activity_to_followers( owner, act, oel );
account_free(owner);
return;
}
struct account* a = account_from_uri( uri );
if( a ) {
account_deliver_activity( a, act, oel );
account_free(a);
return;
}
}
void activity_deliver( struct ap_object* act )
{
// TODO: handle delivery
printf( "activity_deliver( act = %s )\n", act->id );
struct outbox_envelope_list oel;
memset(&oel,0,sizeof(oel));
// Build the outbox list based on to,cc,bcc
for( int i = 0; i < act->to.count; ++i ) {
deliver_to( &oel, act, act->to.items[i] );
}
for( int i = 0; i < act->cc.count; ++i ) {
deliver_to( &oel, act, act->cc.items[i] );
}
for( int i = 0; i < act->bcc.count; ++i ) {
deliver_to( &oel, act, act->bcc.items[i] );
}
printf( "Delivering to %d inboxes\n", oel.count );
outbox_envelope_list_save(&oel);
outbox_envelope_list_free_composite(&oel);
activity_save(act);
ap_object_write_to_FILE( act, stdout );
printf( "Delivery scheduling finished.\n" );
}

@ -5,6 +5,7 @@
// Submodules
#include "json/json.h"
#include "json/layout.h"
#include "ffdb/fs_list.h"
#include "ffdb/hash_index.h"
#include "ffdb/trie.h"
#include "sha256/sha256.h"
@ -345,6 +346,7 @@ bool status_sync_from_uri( struct status* s, const char* uri )
FILE* f = NULL;
bool result = false;
mkdir_p( "data/statuses/ap", 0755 );
// Fetch the object from the remote server
char filename[512];
snprintf( filename, sizeof(filename), "data/statuses/ap/%d.json", s->id );
@ -480,23 +482,22 @@ struct status* status_from_activity( struct ap_object* act )
return s;
}
bool status_save_new( struct status* s )
void status_assign_local_id( struct status* s )
{
// TODO: change to fs_list_get/set
int head = -1;
FILE* f = fopen("data/statuses/HEAD","r");
fscanf(f,"%d",&head);
if( head == -1 ) { return false; }
fclose(f);
if( s->id ) { return; }
s->id = head + 1;
s->root_status_id = s->id;
mkdir_p( "data/statuses", 0755 );
f = fopen("data/statuses/HEAD.tmp","w");
fprintf( f, "%d", s->id );
fclose(f);
rename( "data/statuses/HEAD.tmp", "data/statuses/HEAD" );
int head = fs_list_get( "data/statuses/HEAD" ) + 1;
fs_list_set( "data/statuses/HEAD", head );
s->id = head;
s->root_status_id = s->id;
}
bool status_save_new( struct status* s )
{
status_assign_local_id( s );
status_save( s );
return true;
@ -513,7 +514,7 @@ void status_save( struct status* s )
}
if( s->stub ) {
mkdir( "data/statuses/stubs", 0755 );
mkdir_p( "data/statuses/stubs", 0755 );
ffdb_trie_set( "data/statuses/stubs", format(filename,512,"%d",s->id), "T" );
} else {
ffdb_trie_remove( "data/statuses/stubs", format(filename,512,"%d",s->id) );
@ -774,7 +775,7 @@ void status_add_like( struct status* s, struct account* a )
void status_set_bookmark( struct status* s )
{
s->bookmarked = true;
mkdir( "data/bookmarks", 0755 );
mkdir_p( "data/bookmarks", 0755 );
char key[32];
ffdb_trie_set( "data/owner/bookmarks", format(key,32,"%d",s->id), "T" );
status_save(s);
@ -782,7 +783,6 @@ void status_set_bookmark( struct status* s )
void status_clear_bookmark( struct status* s )
{
s->bookmarked = false;
mkdir( "data/bookmarks", 0755 );
char key[32];
ffdb_trie_set( "data/owner/bookmarks", format(key,32,"%d",s->id), NULL );
status_save(s);

@ -65,6 +65,7 @@ struct status
} emoji;
};
void status_assign_local_id( struct status* s );
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 );

Loading…
Cancel
Save