Federate emoji reacts

master
teknomunk 1 year ago
parent 70e27e0d23
commit 9ab772b661

@ -72,6 +72,7 @@ static bool process_envelope( int id )
struct http_signature hs;
if( !http_signature_make( to_account->inbox, keys, &hs ) ) {
printf( "! Failed to make HTTP signature\n" );
goto failed;
}
@ -111,6 +112,8 @@ static bool process_envelope( int id )
goto discard;
}
printf( "\nServer returned status code %d\n", status_code );
goto failed;
cleanup:
@ -124,6 +127,7 @@ cleanup:
return result;
failed:
sleep(10);
result = false;
goto cleanup;
discard:
@ -137,10 +141,11 @@ static bool process_one()
int tail = fs_list_get("data/outbox/TAIL");
if( tail < head ) {
printf( "Processing outbox/%d.json\n", tail+1 );
if( process_one(tail+1) ) {
if( process_envelope(tail+1) ) {
printf( "Done with outbox/%d.json\n", tail );
fs_list_set( "data/outbox/TAIL", tail + 1 );
}
printf("after\n" );
return true;
}

@ -1,9 +1,27 @@
#define _GNU_SOURCE
#include "ffdb/fs_list.h"
#include "collections/array.h"
#include "model/account.h"
#include "model/ap/account.h"
#include "model/ap/activity.h"
#include "model/ap/activity/rsa_signature_2017.h"
#include "model/ap/outbox_envelope.h"
#include "model/status.h"
#include "model/server.h"
#include "format.h"
#include <string.h>
#include <time.h>
void develop()
{
struct ap_account* a = ap_account_from_file( "account.json" );
ap_account_free(a);
struct status* s = status_from_id(89);
ap_activity_react( s, "👍" );
status_free(s);
}

@ -1,3 +1,4 @@
#define _GNU_SOURCE
#include "format.h"
#include <stdarg.h>
@ -12,4 +13,14 @@ const char* format( char* buffer, int size, const char* f, ... )
return buffer;
}
char* aformat( const char* f, ... )
{
va_list args;
va_start(args,f);
char* res = NULL;
vasprintf( &res, f, args );
va_end(args);
return res;
}

@ -1,4 +1,5 @@
#pragma once
const char* format( char* buffer, int size, const char* f, ... );
char* aformat( const char* f, ... );

@ -1 +1 @@
Subproject commit 41c0f0e1d4dd8072589515927624b044106c8405
Subproject commit f4b7a303cb6a3a87fd8f8089bf85688158522580

@ -1 +1 @@
Subproject commit 1a302a180b0eb93a4c716975dd5a35c5b98957de
Subproject commit 05780d2140b239538f23f666c998130f3ec32cb8

@ -102,7 +102,11 @@ int main( int argc, char* argv[] )
int section = -1;
for( int i = 1; i < argc; ++i ) {
if( sscanf(argv[i],"--section=%d",&section) ) {
const char* arg = argv[i];
if( sscanf(arg,"--section=%d",&section) ) {
} else if( 0 == strcmp(argv[i],"--devel") ) {
section = 100;
} else {
printf( "Unknown argument: %s\n", argv[i] );
return 1;
@ -117,7 +121,7 @@ int main( int argc, char* argv[] )
case 3: built_in_test(); break;
case 4: reindex(); break;
case 100: develop(); return 0;
case 100: develop(); break;
default: code = !run_everything(args); break;
}

@ -4,8 +4,11 @@
#include "ffdb/fs_list.h"
#include "collections/array.h"
#include "format.h"
#include "model/server.h"
#include "model/account.h"
#include "model/status.h"
#include "model/ap/outbox_envelope.h"
#include <stddef.h>
@ -77,6 +80,7 @@ void ap_activity_free_composite( struct ap_activity* act )
{
free(act->id);
free(act->actor);
free(act->content);
for( int i = 0; i < act->to.count; ++i ) {
free(act->to.items[i]);
@ -113,16 +117,13 @@ struct ap_activity* ap_activity_create_accept( struct ap_activity* act )
int id = fs_list_get("data/activities/HEAD") + 1;
fs_list_set( "data/activities/HEAD", id );
char* act_id; asprintf( &act_id,"https://%s/activity/%d", g_server_name, id );
char* actor; asprintf( &actor, "https://%s/owner/actor", g_server_name );
struct ap_activity* accept = malloc(sizeof(struct ap_activity));
memset(accept,0,sizeof(*accept));
accept->id = act_id;
asprintf( &accept->id,"https://%s/activity/%d", g_server_name, id );
accept->local_id = id;
accept->type = apat_accept;
accept->actor = actor;
asprintf( &accept->actor, "https://%s/owner/actor", g_server_name );
char* new_act_actor = strdup(act->actor);
array_append( &accept->to, sizeof(char*), &new_act_actor );
accept->object.tag = apaot_activity;
@ -144,3 +145,51 @@ void ap_activity_accept( struct ap_activity* act, int deliver_to_account_id )
ap_activity_free(accept);
}
struct ap_activity* ap_activity_create_emoji_react( struct status* s, const char* react )
{
struct account* a = account_from_id( s->account_id );
int id = fs_list_get("data/activities/HEAD") + 1;
fs_list_set( "data/activities/HEAD", id );
struct ap_activity* act = ap_activity_new();
act->local_id = id;
act->id = aformat( "https://%s/activity/%d", g_server_name, id );
act->actor = aformat( "https://%s/owner/actor", g_server_name );
act->type = apat_emoji_react;
act->content = strdup(react);
act->published = time(NULL);
act->object.tag = apaot_ref;
act->object.ref = strdup( s->url );
char* to = aformat( "%s/followers", a->account_url );
array_append( &act->to, sizeof(to), &to );
char* cc = strdup( "https://www.w3.org/ns/activitystreams#Public" );
array_append( &act->cc, sizeof(cc), &cc );
cc = strdup( a->account_url );
array_append( &act->cc, sizeof(cc), &cc );
account_free(a);
return act;
}
void ap_activity_react( struct status* s, const char* react )
{
struct ap_activity* act = ap_activity_create_emoji_react(s,react);
/*
ap_activity_write_to_FILE( act, stdout );
printf("\nRDF:\n");
ap_activity_write_normalized_rdf(act, stdout);
*/
ap_activity_save(act);
struct outbox_envelope* env = outbox_envelope_new();
env->activity_id = act->local_id;
env->account_id = s->account_id;
outbox_envelope_save( env );
outbox_envelope_free( env );
ap_activity_free(act);
}

@ -127,4 +127,7 @@ void ap_activity_save( struct ap_activity* act );
struct ap_activity* ap_activity_create_accept( struct ap_activity* act );
void ap_activity_accept( struct ap_activity* act, int deliver_to_account_id );
struct status;
struct ap_activity* ap_activity_create_emoji_react( struct status* s, const char* react );
void ap_activity_react( struct status* s, const char* react );

@ -86,7 +86,11 @@ static bool context_writer( struct json_writer* jw, const char* field_name, void
json_write_field_name( jw, field_name );
struct ap_activity_context* ctx = field_data;
int items = 1 + ctx->extra.count + (ctx->language ? 1 : 0 );
int items = 1;
if( ctx ) {
ctx->extra.count + (ctx->language ? 1 : 0 );
}
if( items == 1 ) {
json_write_string( jw->f, "https://www.w3.org/ns/activitystreams" );

@ -41,6 +41,8 @@ struct rdf_serialize_field ap_activity_rdf[] = {
{ "", offsetof( struct ap_activity, id ), &rdf_id_field },
{ "<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>", offsetof( struct ap_activity, type ), &rdf_enum_field, &types },
{ "<https://www.w3.org/ns/activitystreams#actor>", offsetof( struct ap_activity, actor ), &rdf_string_ref_field },
{ "<https://www.w3.org/ns/activitystreams#content>", offsetof( struct ap_activity, content ), &rdf_string_field },
{ "<https://www.w3.org/ns/activitystreams#published>", offsetof( struct ap_activity, published ), &rdf_date_field },
{ "<https://www.w3.org/ns/activitystreams#to>", offsetof( struct ap_activity, to ), &rdf_array_of_field, &rdf_string_ref_field },
{ "<https://www.w3.org/ns/activitystreams#cc>", offsetof( struct ap_activity, cc ), &rdf_array_of_field, &rdf_string_ref_field },
{ "<https://www.w3.org/ns/activitystreams#bcc>", offsetof( struct ap_activity, bcc ), &rdf_array_of_field, &rdf_string_ref_field },
@ -55,7 +57,8 @@ struct rdf_serialize_field ap_activity_signature_rdf[] = {
{ NULL },
};
char* serialize_normalized_object( struct rdf_serialize_field* layout, void* object, size_t* result_size )
static void write_normalized_rdf( struct rdf_serialize_field* layout, void* object, FILE* f )
{
// Serialize activity to RDF
struct rdf_serializer rs;
@ -72,21 +75,31 @@ char* serialize_normalized_object( struct rdf_serialize_field* layout, void* obj
rdf_memory_store_as_collection( ms, &i );
rdf_normalize(i);
rdf_memory_store_dump( ms, f );
rdf_memory_store_free(ms);
free((char*)rs.subject);
free((char*)rs.graph);
}
void ap_activity_write_normalized_rdf( struct ap_activity* act, FILE* out )
{
write_normalized_rdf( ap_activity_rdf, act, out );
}
static char* serialize_normalized_object( struct rdf_serialize_field* layout, void* object, size_t* result_size )
{
char* outbuf = NULL;
FILE* f = open_memstream( &outbuf, result_size );
if( !f ) {
printf( "Error opening memstream\n" );
goto cleanup;
return NULL;
}
rdf_memory_store_dump( ms, f );
write_normalized_rdf( layout, object, f );
fclose(f);
rdf_memory_store_free(ms);
cleanup:
free((char*)rs.subject);
free((char*)rs.graph);
return outbuf;
}

@ -1,9 +1,11 @@
#pragma once
#include <stdbool.h>
#include <stdio.h>
struct ap_activity;
struct crypto_keys;
bool ap_activity_create_rsa_signature_2017( struct ap_activity* act, struct crypto_keys* keys );
void ap_activity_write_normalized_rdf( struct ap_activity* act, FILE* out );

@ -35,8 +35,8 @@ static struct json_field_type http_header_type = {
static struct json_object_field envelope_layout[] = {
{ "when", offsetof(struct ap_envelope, when), true, &json_field_string },
{ "headers", offsetof(struct ap_envelope, headers), true, &json_field_array_of, &http_header_type },
{ "body", offsetof(struct ap_envelope, body), true, &json_field_string },
{ "validated", offsetof(struct ap_envelope, validated), false, &json_field_bool },
{ "body", offsetof(struct ap_envelope, body), true, &json_field_string },
{ NULL },
};

@ -184,8 +184,17 @@ void status_free( struct status* s )
void status_add_react( struct status* s, const char* react, struct account* a )
{
// TODO generate outbox element
printf( "TODO: generate outbox activity for adding reaction '%s' to status #%d by account #%d\n", react, s->id, a->id );
// generate outbox element
if( a->id == owner_account_id ) {
if( s->account_id == owner_account_id ) {
// De
printf( "TODO: generate outbox activity for adding reaction '%s' to status #%d by account #%d, deliver to followers\n", react, s->id );
} else {
// Deliver react to post owner
//printf( "TODO: generate outbox activity for adding reaction '%s' to status #%d by account #%d, deliver to account #%d\n", react, s->id, a->id, s->account_id );
ap_activity_react( s, react );
}
}
// TODO: generate notification
if( s->account_id == owner_account_id && a->id != owner_account_id ) {
@ -225,8 +234,10 @@ done:
}
void status_remove_react( struct status* s, const char* react, struct account* a )
{
// TODO generate outbox element
// TODO: generate outbox element
printf( "TODO: generate outbox activity for removing reaction '%s' to status #%d by account #%d\n", react, s->id, a->id );
/// Find react activity we need to Undo
/// Generate Undo Activity
// TODO: generate notification
if( s->account_id == owner_account_id && a->id != owner_account_id ) {

@ -1,5 +1,5 @@
{
"access_token": "%s{app->access_token}",
"token_type": "Bearer",
"scope": "read write follow"
"scope": "read write follow push"
}

Loading…
Cancel
Save