Add support for receiving federated quote posts and displaying quote posts (can't source them yet)

master
teknomunk 1 year ago
parent 0bfecc9929
commit 837a3b62f9

2
.gitignore vendored

@ -6,7 +6,7 @@ src.bin
debug debug
release release
data/ data/
assets/soapbox/ assets/soapbox*
backup/ backup/
vgcore.* vgcore.*
apogee* apogee*

@ -1 +1 @@
Subproject commit 7f73d77dd53ce619d2000bec8b5a706b3ba1b366 Subproject commit 9b6e7725a6356f2a6e776dde60c18201a82d6f88

@ -46,6 +46,7 @@ static struct json_object_field status_layout[] = {
JSON_FIELD_DATETIME( published, false ), JSON_FIELD_DATETIME( published, false ),
JSON_FIELD_INTEGER( in_reply_to, false ), JSON_FIELD_INTEGER( in_reply_to, false ),
JSON_FIELD_INTEGER( quote_id, false ),
JSON_FIELD_INTEGER( repost_id, false ), JSON_FIELD_INTEGER( repost_id, false ),
JSON_FIELD_INTEGER( root_status_id, false ), JSON_FIELD_INTEGER( root_status_id, false ),
JSON_FIELD_INTEGER( reposted_status_id, false ), JSON_FIELD_INTEGER( reposted_status_id, false ),
@ -57,6 +58,7 @@ static struct json_object_field status_layout[] = {
JSON_FIELD_ARRAY_OF_INTS( likes, false ), JSON_FIELD_ARRAY_OF_INTS( likes, false ),
JSON_FIELD_ARRAY_OF_INTS( replies, false ), JSON_FIELD_ARRAY_OF_INTS( replies, false ),
JSON_FIELD_ARRAY_OF_INTS( reposts, false ), JSON_FIELD_ARRAY_OF_INTS( reposts, false ),
JSON_FIELD_ARRAY_OF_INTS( quotes, false ),
JSON_FIELD_ARRAY_OF_INTS( mentions, false ), JSON_FIELD_ARRAY_OF_INTS( mentions, false ),
JSON_FIELD_ARRAY_OF_TYPE( emoji, false, emoji_type ), JSON_FIELD_ARRAY_OF_TYPE( emoji, false, emoji_type ),
@ -229,7 +231,31 @@ void status_add_mention( struct status* s, int id )
} }
void status_add_repost( struct status* s, struct status* repost ) void status_add_repost( struct status* s, struct status* repost )
{ {
// TODO: implement if( repost->id == 0 ) { return; }
for( int i = 0; i < s->reposts.count; ++i ) {
if( s->reposts.items[i] == repost->id ) {
return;
}
}
int id = repost->id;
array_append( &s->reposts, sizeof(id), &id );
status_save(s);
}
void status_add_quote( struct status* s, struct status* quote )
{
if( quote->id == 0 ) { return; }
for( int i = 0; i < s->quotes.count; ++i ) {
if( s->quotes.items[i] == quote->id ) {
return;
}
}
int id = quote->id;
array_append( &s->quotes, sizeof(id), &id );
status_save(s);
} }
bool status_sync_from_activity_pub( struct status* s, struct ap_object* act ) bool status_sync_from_activity_pub( struct status* s, struct ap_object* act )
{ {
@ -260,6 +286,14 @@ bool status_sync_from_activity_pub( struct status* s, struct ap_object* act )
status_free(parent); status_free(parent);
} }
} }
if( act->quote_url ) {
struct status* parent = status_from_uri_or_fetch( act->quote_url );
if( parent ) {
status_make_quote_of( s, parent->id );
// DO NOT SAVE parent! This is done inside status_make_quote_of
status_free(parent);
}
}
for( int i = 0; i < s->emoji.count; ++i ) { for( int i = 0; i < s->emoji.count; ++i ) {
emoji_free( s->emoji.items[i] ); emoji_free( s->emoji.items[i] );
@ -588,6 +622,7 @@ void status_free( struct status* s )
free(s->likes.items); free(s->likes.items);
free(s->replies.items); free(s->replies.items);
free(s->reposts.items); free(s->reposts.items);
free(s->quotes.items);
free(s->mentions.items); free(s->mentions.items);
for( int i = 0; i < s->emoji.count; ++i ) { for( int i = 0; i < s->emoji.count; ++i ) {
@ -634,26 +669,45 @@ void status_make_reply_to( struct status* s, int in_reply_to_id )
struct status* in_reply_to = status_from_id( in_reply_to_id ); struct status* in_reply_to = status_from_id( in_reply_to_id );
if( !in_reply_to ) { if( !in_reply_to ) {
s->in_reply_to = 0; s->in_reply_to = 0;
} else { 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;
// Record in parent as reply // Setup this status's reply fields
status_add_reply( in_reply_to, s ); s->in_reply_to = in_reply_to_id;
s->root_status_id = in_reply_to->root_status_id;
// Mention the account that made the post being replied to // Record in parent as reply
status_add_mention( s, in_reply_to->account_id ); status_add_reply( in_reply_to, s );
// Mention everytone else in that post // Mention the account that made the post being replied to
for( int i = 0; i < in_reply_to->mentions.count; ++i ) { status_add_mention( s, in_reply_to->account_id );
status_add_mention( s, in_reply_to->mentions.items[i] );
}
status_save(in_reply_to); // Mention everyone else in that post
for( int i = 0; i < in_reply_to->mentions.count; ++i ) {
status_add_mention( s, in_reply_to->mentions.items[i] );
} }
status_save(in_reply_to);
status_free(in_reply_to); status_free(in_reply_to);
} }
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;
return;
}
// Set quoted id
s->quote_id = id_quote_of;
// Record quote in parent
status_add_quote( quoted_post, s );
// Save and cleanup
status_save( quoted_post );
status_free( quoted_post );
}
void status_get_context( struct status* s, void* ancestors_ptr, void* replies_ptr ) void status_get_context( struct status* s, void* ancestors_ptr, void* replies_ptr )
{ {
struct array_of_status { struct array_of_status {

@ -26,6 +26,7 @@ struct status
time_t published; time_t published;
int in_reply_to; int in_reply_to;
int quote_id;
int repost_id; int repost_id;
int root_status_id; int root_status_id;
int reposted_status_id; // if this post was reposted, this will be the id of that status int reposted_status_id; // if this post was reposted, this will be the id of that status
@ -60,6 +61,11 @@ struct status
int count; int count;
} reposts; } reposts;
struct {
int* items;
int count;
} quotes;
struct { struct {
int* items; int* items;
int count; int count;
@ -101,7 +107,9 @@ void status_get_context( struct status* s, void* ancestors, void* replies );
void status_add_reply( struct status* s, struct status* child ); void status_add_reply( struct status* s, struct status* child );
void status_add_mention( struct status* s, int id ); void status_add_mention( struct status* s, int id );
void status_add_repost( struct status* s, struct status* repost ); void status_add_repost( struct status* s, struct status* repost );
void status_add_quote( struct status* s, struct status* quote );
void status_make_reply_to( struct status* s, int in_reply_to ); void status_make_reply_to( struct status* s, int in_reply_to );
void status_make_quote_of( struct status* s, int id_quote_of );
void status_add_react( struct status* s, const char* react, struct account* a ); void status_add_react( struct status* s, const char* react, struct account* a );
void status_remove_react( struct status* s, const char* react, struct account* a ); void status_remove_react( struct status* s, const char* react, struct account* a );
void status_add_like( struct status* s, struct account* a ); void status_add_like( struct status* s, struct account* a );

@ -278,6 +278,27 @@ bool is_local_callback( void* field_data, bool is_read, bool* val )
*val = !s->remote; *val = !s->remote;
return true; return true;
} }
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; }
struct status* quoted_post = status_from_id(s->quote_id);
*val = strdup(quoted_post->url );
status_free(quoted_post);
return true;
}
bool quote_visible_callback( void* field_data, bool is_read, bool* val )
{
if( is_read ) { return false; }
struct status* s = field_data;
*val = ( s->quote_id != 0 );
return true;
}
#define OBJ_TYPE struct status #define OBJ_TYPE struct status
static struct json_object_field content_layout[] = { static struct json_object_field content_layout[] = {
@ -332,9 +353,28 @@ static struct json_object_field pleroma_layout[] = {
}, },
JSON_FIELD_FIXED_BOOL( parent_visible, true ), JSON_FIELD_FIXED_BOOL( parent_visible, true ),
JSON_FIELD_FIXED_NULL( pinned_at ), JSON_FIELD_FIXED_NULL( pinned_at ),
JSON_FIELD_FIXED_NULL( quote ), {
JSON_FIELD_FIXED_NULL( quote_url ), .key = "quote",
JSON_FIELD_FIXED_BOOL( quote_visible, false ), .offset = offsetof( OBJ_TYPE, quote_id ),
.type = &Status_reference_type,
},
{
.key = "quote_url",
.offset = 0,
.type = &json_field_callback_string,
.string_callback = quote_url_callback,
},
{
.key = "quote_visible",
.offset = 0,
.type = &json_field_bool_callback,
.bool_callback = quote_visible_callback,
},
{
.key = "quotes_count",
.offset = offsetof( OBJ_TYPE, quotes.count ),
.type = &json_field_integer,
},
/* /*
"spoiler_text": { "spoiler_text": {
"text/plain": "" "text/plain": ""

Loading…
Cancel
Save