You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
3.9 KiB
C
169 lines
3.9 KiB
C
#include "model/account.h"
|
|
|
|
// Model
|
|
#include "model/fetch.h"
|
|
|
|
// Submodules
|
|
#include "collections/array.h"
|
|
#include "util/format.h"
|
|
#include "ap/object.h"
|
|
|
|
// Standard Library
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <sys/stat.h>
|
|
|
|
bool account_sync_from_activity_pub( unsigned int account_id )
|
|
{
|
|
bool result = false;
|
|
struct account* a = NULL;
|
|
|
|
char filename[512];
|
|
snprintf( filename, 512, "data/accounts/%d/ap.json", account_id );
|
|
|
|
printf( "ap_object_from_file( %s )\n", filename );
|
|
struct ap_object* obj = ap_object_from_file(filename);
|
|
if( !obj ) {
|
|
// Try to fetch using the account_url field
|
|
a = account_from_id(account_id);
|
|
if( !a ) { goto failed; }
|
|
pull_remote_file( filename, a->account_url );
|
|
obj = ap_object_from_file(filename);
|
|
account_free(a); a = NULL;
|
|
if( !obj ) { goto failed; }
|
|
} else {
|
|
struct stat s;
|
|
stat( filename, &s );
|
|
if( time(NULL) - s.st_mtime > 60*60*24*3 ) {
|
|
// Refresh if over 3 days old
|
|
pull_remote_file( filename, obj->id );
|
|
ap_object_free(obj);
|
|
obj = ap_object_from_file(filename);
|
|
if( !obj ) { goto failed; }
|
|
}
|
|
}
|
|
|
|
printf( "obj = "); ap_object_write_to_FILE(obj,stdout);
|
|
printf( "\n" );
|
|
|
|
a = malloc(sizeof(struct account));
|
|
memset(a,0,sizeof(*a));
|
|
a->id = account_id;
|
|
|
|
if( !obj ) {
|
|
printf( "? Failed to sync account %d from %s, creating stub\n", account_id, filename );
|
|
goto failed;
|
|
}
|
|
|
|
a->handle = strdup(obj->preferred_username);
|
|
if( obj->name ) {
|
|
a->display_name = strdup(obj->name);
|
|
} else {
|
|
a->display_name = strdup(obj->preferred_username);
|
|
}
|
|
if( obj->icon && obj->icon->url ) {
|
|
a->avatar.url = strdup(obj->icon->url);
|
|
a->avatar.static_url = strdup(a->avatar.url);
|
|
}
|
|
if( obj->image && obj->image->url ) {
|
|
a->banner = strdup(obj->image->url);
|
|
}
|
|
a->bot = ( obj->type != ap_Person );
|
|
a->account_type = at_remote_activity_pub;
|
|
if( obj->url ) {
|
|
a->account_url = strdup(obj->url);
|
|
} else if( obj->id ) {
|
|
a->account_url = strdup(obj->id);
|
|
} else {
|
|
goto failed;
|
|
}
|
|
if( obj->inbox ) {
|
|
a->inbox = strdup(obj->inbox);
|
|
}
|
|
if( obj->summary ) {
|
|
a->note = strdup(obj->summary);
|
|
}
|
|
if( obj->endpoints.shared_inbox ) {
|
|
a->shared_inbox = strdup(obj->endpoints.shared_inbox);
|
|
}
|
|
|
|
if( 0 == strncmp( obj->id, "https://", 8 ) ) {
|
|
char* server_name = strdup(&obj->id[8]);
|
|
char* discard;
|
|
strtok_r(server_name,"/",&discard);
|
|
|
|
a->server = server_name;
|
|
}
|
|
|
|
// Clear out existing emoji
|
|
for( int i = 0; i < a->emoji.count; ++i ) {
|
|
free( a->emoji.items[i].key );
|
|
free( a->emoji.items[i].value );
|
|
}
|
|
a->emoji.count = 0;
|
|
|
|
// Pull in emoji
|
|
for( int i = 0; i < obj->tags.count; ++i ) {
|
|
struct ap_activity_tag* tag = obj->tags.items[i];
|
|
|
|
if( tag->type == aptag_emoji ) {
|
|
struct string_pair item;
|
|
memset(&item,0,sizeof(item));
|
|
item.key = strndup(&tag->name[1],strlen(tag->name)-2);
|
|
item.value = strdup(tag->icon.url);
|
|
array_append( &a->emoji, sizeof(item), &item );
|
|
}
|
|
}
|
|
|
|
// Extract out the public key
|
|
char* id = strdup(obj->public_key->id);
|
|
char* key_id = NULL;
|
|
strtok_r( id, "#", &key_id );
|
|
FILE* key_pem = fopen( format(filename,sizeof(filename),"data/accounts/%d/%s.pem", a->id, key_id), "w" );
|
|
if( !key_pem ) {
|
|
printf( "Unable to save public key to %s\n", filename );
|
|
} else {
|
|
printf( "Writing public key to %s\n", filename );
|
|
fprintf( key_pem, "%s", obj->public_key->public_key );
|
|
fclose(key_pem);
|
|
}
|
|
free(id);
|
|
|
|
account_save(a);
|
|
account_index_webfinger(a);
|
|
|
|
goto succeeded;
|
|
succeeded:
|
|
result = true;
|
|
goto cleanup;
|
|
cleanup:
|
|
ap_object_free(obj);
|
|
account_free(a);
|
|
|
|
return result;
|
|
failed:
|
|
result = false;
|
|
goto cleanup;
|
|
}
|
|
|
|
bool account_sync_from_activity( struct account* a, struct ap_object* act )
|
|
{
|
|
for( int i = 0; i < a->aliases.count; ++i ) {
|
|
free( a->aliases.items[i] );
|
|
}
|
|
a->aliases.count = 0;
|
|
|
|
for( int i = 0; i < act->also_known_as.count; ++i ) {
|
|
char* str = strdup(act->also_known_as.items[i]);
|
|
array_append( &a->aliases, sizeof(str), &str );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void account_sync_following_list( struct account* a )
|
|
{
|
|
// TODO: implement
|
|
}
|
|
|