Implement post submission, start using new json object layout parser

master
teknomunk 1 year ago
parent bc2d58266b
commit bc36480af3

@ -1,4 +1,5 @@
#include "notice.h"
#include "status.h"
#include "http_server/http_request.h"

@ -10,12 +10,24 @@
#include <stdlib.h>
#include <string.h>
void write_json_escaped( FILE* f, const char* str );
void api_status_write_as_json( struct status* s, FILE* f )
{
struct account* account = account_from_id( s->account_id );
#include "src/view/api/status.json.inc"
cleanup:
account_free(account);
}
void show_status( struct http_request* req, struct status* s )
{
http_request_send_headers( req, 200, "application/json", true );
FILE* f = http_request_get_response_body( req );
status_write_as_json(s,f);
api_status_write_as_json(s,f);
}
void show_status_context( struct http_request* req, struct status* s )
{
@ -24,6 +36,7 @@ void show_status_context( struct http_request* req, struct status* s )
fprintf( f, "{\"ancestors\":[],\"descendants\":[]}" );
}
void show_statuses( struct http_request* req, struct status* ss, int count )
{
http_request_send_headers( req, 200, "application/json", true );
@ -34,24 +47,27 @@ void show_statuses( struct http_request* req, struct status* ss, int count )
if( i > 0 ) {
fprintf( f, "," );
}
status_write_as_json(&ss[i],f);
api_status_write_as_json(&ss[i],f);
}
fprintf( f, "]" );
}
bool handle_post( struct http_request* req, struct account* a )
{
printf( "TODO: new post" );
bool result = false;
struct status* s = NULL;
FILE* data = http_request_get_request_data( req );
// {"media_ids":[],"sensitive":false,"status":"Test","visibility":"public","spoiler_text":""}
struct json_pull_parser* jpp = json_pull_parser_new( data );
if( !jpp ) { return false; }
int save;
if( !json_pull_parser_begin_object( jpp, &save ) ) { return false; }
struct status s;
bool sensitive = false;
s = malloc(sizeof(struct status));
s->account_id = 0;
s->sensitive = false;
char* key;
while( key = json_pull_parser_read_object_key(jpp) ) {
@ -59,31 +75,43 @@ bool handle_post( struct http_request* req, struct account* a )
json_pull_parser_read_value(jpp);
} else if( 0 == strcmp(key,"sensitive") ) {
json_pull_parser_read_bool(jpp,&sensitive);
json_pull_parser_read_bool(jpp,&s->sensitive);
} else if( 0 == strcmp(key,"status") ) {
json_pull_parser_read_string(jpp);
s->content = json_pull_parser_read_string(jpp);
} else if( 0 == strcmp(key,"visibility") ) {
json_pull_parser_read_string(jpp);
free(json_pull_parser_read_string(jpp));
} else if( 0 == strcmp(key,"spoiler_text") ) {
json_pull_parser_read_string(jpp);
free(json_pull_parser_read_string(jpp));
} else {
json_pull_parser_read_value(jpp);
}
}
free(key);
if( !json_pull_parser_end_object(jpp, &save ) ) {
return false;
}
if( !json_pull_parser_end_object(jpp, &save ) ) { goto failed; }
// {"media_ids":[],"sensitive":false,"status":"Test","visibility":"public","spoiler_text":""}
status_save_new(s);
char ch;
while( (ch = fgetc(data)) != EOF ) {
printf( "%c", ch );
}
/*
struct account* owner = account_from_id(0);
struct timeline* tl = account_get_home_timeline(owner);
timeline_insert_status( tl, s );
*/
return false;
http_request_send_headers( req, 200, "application/json", true );
FILE* f = http_request_get_response_body(req);
api_status_write_as_json(s,f);
result = true;
cleanup:
free(s->content);
free(s);
return result;
failed:
result = false;
goto cleanup;
}

@ -1,6 +1,7 @@
#pragma once
#include <stdbool.h>
#include <stdio.h>
struct http_request;
struct status;
@ -12,3 +13,5 @@ void show_statuses( struct http_request* req, struct status* ss, int count );
bool handle_post( struct http_request* req, struct account* a );
void api_status_write_as_json( struct status* s, FILE* f );

@ -7,7 +7,7 @@
#include <stdlib.h>
#include <time.h>
static void write_json_escaped( FILE* f, const char* str )
void write_json_escaped( FILE* f, const char* str )
{
while( *str ) {
switch( *str ) {

@ -44,8 +44,11 @@ bool route_request( struct http_request* req )
if( http_request_route( req, "/webfinger?" ) ) {
return route_wellknown_webfinger( req );
} else if( http_request_route( req, "/nodeinfo" ) ) {
printf( "Nodeinfo\n" );
return route_wellknown_nodeinfo( req );
}
} else if( http_request_route( req, "/nodeinfo" ) ) {
return route_nodeinfo(req);
} else if( http_request_route( req, "/assets/" ) ) {
printf( "handling asset\n" );
return route_asset(req);

@ -21,12 +21,9 @@ bool handle_timeline( struct http_request* req, const char* which )
bool with_muted = false;
unsigned int limit = 100;
struct status s = {
.id = 1,
.account_id = 1,
};
show_statuses( req, &s, 1 );
struct status* s = status_from_id(1);
show_statuses( req, s, 1 );
status_free(s);
return true;
}
@ -87,12 +84,12 @@ bool route_mastodon_api( struct http_request* req )
if( http_request_route_id( req, &id ) ) {
struct status* s = status_from_id(id);
if( http_request_route( req, "context" ) ) {
show_status_context( req, s );
} else {
show_status( req, s );
}
status_free(s);
return true;
}
} else if( http_request_route_method( req, "POST" ) ) {

@ -25,6 +25,7 @@ bool route_nodeinfo( struct http_request* req )
return true;
}
return false;
}

@ -28,7 +28,7 @@ class Templator
end
def process()
@o.puts "#ifndef RENDER"
@o.puts "#ifdef HEADERS"
@o.puts "\t#include \"#{ @filename.gsub(/\.template$/,'.h') }\""
@o.puts "#else"

@ -1 +1 @@
Subproject commit 336a374c4cbb4fb8bcd5b2aea8d289ee556c4090
Subproject commit 8f145d989b96f45fb37e80e26789891328fa7a5d

@ -1 +1 @@
Subproject commit 4fff189159f80cf980ce65f2d3ebcb58f25a2d46
Subproject commit 962ab0069d67747d29b1a2bbfd3efb07d2a9b890

@ -49,6 +49,8 @@ int main( int argc, char* argv[] )
return 1;
}
http_server_set_debug( srv, true );
while(!terminate) {
http_server_process( srv );
usleep(1);

@ -53,6 +53,9 @@ struct account* account_from_id( unsigned int id )
} else if( 0 == strcmp( key, "avatar" ) ) {
a->avatar.url = json_pull_parser_read_string(jpp);
} else if( 0 == strcmp( key, "account_url" ) ) {
a->account_url = json_pull_parser_read_string(jpp);
} else if( 0 == strcmp( key, "avatar_static" ) ) {
a->avatar.static_url = json_pull_parser_read_string(jpp);
}

@ -10,6 +10,8 @@ struct account
char* server;
char* display_name;
char* account_url;
struct {
char* url;
char* static_url;

@ -18,7 +18,7 @@
"pleroma": {
"accepts_chat_messages": true,
"also_known_as": [],
"ap_id": "https://poa.st/users/PinochetsCommieCopter",
"ap_id": "%s{a->account_url}",
"background_image": null,
"favicon": null,
"hide_favorites": true,
@ -42,7 +42,7 @@
},
"sensitive": false
},
"statuses_count": 5133,
"url": "https://poa.st/users/PinochetsCommieCopter",
"username": "PinochetsCommieCopter"
"statuses_count": 0,
"url": "%s{a->account_url}",
"username": "%s{a->handle}"
}

@ -112,9 +112,7 @@ void client_app_save( struct client_app* app )
if( !f ) {
return;
}
#define RENDER
#include "model/client_app.json.inc"
#undef RENDER
#include "model/client_app.json.inc"
fclose(f);
rename( tmp_filename, filename );
}

@ -3,14 +3,14 @@
#include "model/account.h"
#include "model/status.h"
#include "controller/api/status.h"
void notification_write_as_json( struct notification* n, FILE* f )
{
struct account* a = account_from_id( n->account_id );
struct account* owner = account_from_id( 0 );
struct status* s = status_from_id( n->status_id );
#define RENDER
#include "src/model/notification.json.inc"
#undef RENDER
#include "src/model/notification.json.inc"
}

@ -6,6 +6,6 @@
"is_muted": false,
"is_seen": false
},
"status": %( status_write_as_json(s,f); ),
"status": %( api_status_write_as_json(s,f); ),
"type": "favourite"
}

@ -3,16 +3,31 @@
#include "model/account.h"
#include "json/json.h"
#include "json/layout.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
void write_json_escaped( FILE* f, const char* str );
static const char* b( bool value )
{
return value ? "true" : "false";
}
static const char* host()
{
return "apogee.polaris-1.work";
}
static struct json_object_field status_layout[] = {
{ "account_id", offsetof( struct status, account_id ), true, &json_field_integer },
{ "sensitive", offsetof( struct status, sensitive ), true, &json_field_bool },
{ "content", offsetof( struct status, content ), true, &json_field_string },
{ NULL }
};
struct status* status_from_id( unsigned int id )
{
struct status* s = NULL;
@ -29,18 +44,7 @@ struct status* status_from_id( unsigned int id )
s->id = id;
s->account_id = -1;
int save;
if( !json_pull_parser_begin_object( jpp, &save ) ) { goto failed; }
char* key;
while( key = json_pull_parser_read_object_key(jpp) ) {
if( 0 == strcmp( key, "account_id" ) ) {
if( !json_pull_parser_read_int( jpp, &s->account_id ) ) { goto failed; }
}
}
if( !json_pull_parser_end_object(jpp, &save ) ) { goto failed; }
if( !json_read_object_layout( jpp, status_layout, s ) ) { goto failed; }
cleanup:
json_pull_parser_release(jpp);
@ -53,14 +57,45 @@ failed:
goto cleanup;
}
void status_write_as_json( struct status* s, FILE* f )
bool status_save_new( struct status* s )
{
struct account* account = account_from_id( s->account_id );
int head = -1;
FILE* f = fopen("data/statuses/HEAD","r");
fscanf(f,"%d",&head);
if( head == -1 ) { return false; }
fclose(f);
#define RENDER
#include "src/model/status.json.inc"
#undef RENDER
s->id = head + 1;
cleanup:
account_free(account);
f = fopen("data/statuses/HEAD.tmp","w");
fprintf( f, "%d", s->id );
fclose(f);
rename( "data/statuses/HEAD.tmp", "data/statuses/HEAD" );
status_save( s );
return true;
}
void status_save( struct status* s )
{
char filename[512];
char tmp_filename[512+32];
snprintf( filename, 512, "data/statuses/%d.json", s->id );
snprintf( tmp_filename, 512+32, "%s.tmp", filename );
FILE* f = fopen( tmp_filename, "w" );
#include "src/model/status.json.inc"
fclose(f);
rename( tmp_filename, filename );
}
void status_free( struct status* s )
{
if( !s ) { return; }
free(s->content);
free(s);
}

@ -1,13 +1,20 @@
#pragma once
#include <stdio.h>
#include <stdbool.h>
struct status
{
unsigned int id;
unsigned int account_id;
char* content;
bool sensitive;
};
struct status* status_from_id( unsigned int id );
void status_write_as_json( struct status* s, FILE* f );
bool status_save_new( struct status* s );
void status_save( struct status* s );
void status_free( struct status* s );

@ -1,64 +1,5 @@
{
"account": %( account_write_as_json(account,f); ),
"application": null,
"bookmarked": false,
"card": null,
"content": "",
"created_at": "2022-12-12T02:52:24.000Z",
"emojis": [],
"favourited": false,
"favourites_count": 0,
"id": "%d{ s->id }",
"in_reply_to_account_id": null,
"in_reply_to_id": null,
"language": null,
"media_attachments": [ {
"blurhash": "eRH.A}xs0Kxv00xYR,R+t5R+9Gt6xaNG%%2-;xaM{NGRjD%%Rjs:xaxu",
"description": null,
"id": "1248813041",
"pleroma": {
"mime_type": "image/png"
},
"preview_url": "https://i.poastcdn.org/0ce6abff5d4838b9af4033a2567d94033b9b62a15aae394e7e48b5f597db76de.png",
"remote_url": "https://i.poastcdn.org/0ce6abff5d4838b9af4033a2567d94033b9b62a15aae394e7e48b5f597db76de.png",
"text_url": "https://i.poastcdn.org/0ce6abff5d4838b9af4033a2567d94033b9b62a15aae394e7e48b5f597db76de.png",
"type": "image",
"url": "https://i.poastcdn.org/0ce6abff5d4838b9af4033a2567d94033b9b62a15aae394e7e48b5f597db76de.png"
} ],
"mentions": [],
"muted": false,
"pinned": false,
"pleroma": {
"content": {
"text/plain": ""
},
"conversation_id": 2935699,
"direct_conversation_id": null,
"emoji_reactions": [ {
"count": 1,
"me": false,
"name": "😆"
} ],
"expires_at": null,
"in_reply_to_account_acct": null,
"local": false,
"parent_visible": false,
"pinned_at": null,
"spoiler_text": {
"text/plain": ""
},
"thread_muted": false
},
"poll": null,
"reblog": null,
"reblogged": false,
"reblogs_count": 1,
"replies_count": 0,
"sensitive": false,
"spoiler_text": "",
"tags": [],
"text": null,
"uri": "https://poa.st/objects/0db3a913-5007-464d-9829-995d5090c976",
"url": "https://poa.st/objects/0db3a913-5007-464d-9829-995d5090c976",
"visibility": "public"
"account_id": %d{s->account_id},
"content": "%( write_json_escaped(f,s->content); )",
"sensitive": %s{ b(s->sensitive) }
}

@ -0,0 +1,64 @@
{
"account": %( account_write_as_json(account,f); ),
"application": null,
"bookmarked": false,
"card": null,
"content": "%s{ s->content }",
"created_at": "2022-12-12T02:52:24.000Z",
"emojis": [],
"favourited": false,
"favourites_count": 0,
"id": "%d{ s->id }",
"in_reply_to_account_id": null,
"in_reply_to_id": null,
"language": null,
"media_attachments": [ {
"blurhash": "eRH.A}xs0Kxv00xYR,R+t5R+9Gt6xaNG%%2-;xaM{NGRjD%%Rjs:xaxu",
"description": null,
"id": "1248813041",
"pleroma": {
"mime_type": "image/png"
},
"preview_url": "https://i.poastcdn.org/0ce6abff5d4838b9af4033a2567d94033b9b62a15aae394e7e48b5f597db76de.png",
"remote_url": "https://i.poastcdn.org/0ce6abff5d4838b9af4033a2567d94033b9b62a15aae394e7e48b5f597db76de.png",
"text_url": "https://i.poastcdn.org/0ce6abff5d4838b9af4033a2567d94033b9b62a15aae394e7e48b5f597db76de.png",
"type": "image",
"url": "https://i.poastcdn.org/0ce6abff5d4838b9af4033a2567d94033b9b62a15aae394e7e48b5f597db76de.png"
} ],
"mentions": [],
"muted": false,
"pinned": false,
"pleroma": {
"content": {
"text/plain": ""
},
"conversation_id": 2935699,
"direct_conversation_id": null,
"emoji_reactions": [ {
"count": 1,
"me": false,
"name": "😆"
} ],
"expires_at": null,
"in_reply_to_account_acct": null,
"local": false,
"parent_visible": false,
"pinned_at": null,
"spoiler_text": {
"text/plain": ""
},
"thread_muted": false
},
"poll": null,
"reblog": null,
"reblogged": false,
"reblogs_count": 1,
"replies_count": 0,
"sensitive": false,
"spoiler_text": "",
"tags": [],
"text": null,
"uri": "https://poa.st/objects/0db3a913-5007-464d-9829-995d5090c976",
"url": "https://poa.st/objects/0db3a913-5007-464d-9829-995d5090c976",
"visibility": "public"
}
Loading…
Cancel
Save