Start filling out model and api

master
teknomunk 1 year ago
parent d01e24d650
commit b7bbc71eee

@ -6,8 +6,11 @@
#include <string.h>
#include "form.h"
#include "json/json.h"
#include "model/client_app.h"
#include "model/status.h"
#include "model/account.h"
#include "model/notification.h"
bool handle_mastodon_api_apps( struct http_request* req )
{
@ -65,26 +68,123 @@ bool check_bearer_token( struct http_request* req )
return true;
}
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);
}
void show_status_context( struct http_request* req, struct status* s )
{
http_request_send_headers( req, 200, "application/json", true );
FILE* f = http_request_get_response_body( req );
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 );
FILE* f = http_request_get_response_body( req );
fprintf( f, "[" );
for( int i = 0; i < count; ++i ) {
if( i > 0 ) {
fprintf( f, "," );
}
status_write_as_json(&ss[i],f);
}
fprintf( f, "]" );
}
void show_notifications( struct http_request* req, struct notification* ns, int count )
{
http_request_send_headers( req, 200, "application/json", true );
FILE* f = http_request_get_response_body( req );
fprintf( f, "[" );
for( int i = 0; i < count; ++i ) {
if( i > 0 ) {
fprintf( f, "," );
}
notification_write_as_json(&ns[i],f);
}
fprintf( f, "]" );
}
bool handle_timeline( struct http_request* req, const char* which )
{
// "GET /api/v1/timelines/home?with_muted=true&limit=31"
bool with_muted = false;
unsigned int limit = 100;
http_request_send_headers( req, 200, "application/json", true );
FILE* f = http_request_get_response_body( req );
struct status s = {
.id = 1,
.account_id = 1,
};
fprintf( f, "[" );
status_write_as_json(&s,f);
fprintf( f, "]" );
show_statuses( req, &s, 1 );
return true;
}
bool handle_mastodon_api_show_account( struct http_request* req, struct account* a )
{
http_request_send_headers( req, 200, "application/json", true );
FILE* f = http_request_get_response_body( req );
account_write_as_json(a,f);
return true;
}
bool handle_post( struct http_request* req, struct account* a )
{
printf( "TODO: new post" );
FILE* data = http_request_get_request_data( req );
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;
char* key;
while( key = json_pull_parser_read_object_key(jpp) ) {
if( 0 == strcmp(key,"media_ids") ) {
json_pull_parser_read_value(jpp);
} else if( 0 == strcmp(key,"sensitive") ) {
json_pull_parser_read_bool(jpp,&sensitive);
} else if( 0 == strcmp(key,"status") ) {
json_pull_parser_read_string(jpp);
} else if( 0 == strcmp(key,"visibility") ) {
json_pull_parser_read_string(jpp);
} else if( 0 == strcmp(key,"spoiler_text") ) {
json_pull_parser_read_string(jpp);
}
}
free(key);
if( !json_pull_parser_end_object(jpp, &save ) ) {
return false;
}
// {"media_ids":[],"sensitive":false,"status":"Test","visibility":"public","spoiler_text":""}
char ch;
while( (ch = fgetc(data)) != EOF ) {
printf( "%c", ch );
}
return false;
}
bool route_mastodon_api( struct http_request* req )
{
if( http_request_route( req, "apps" ) ) {
@ -93,13 +193,87 @@ bool route_mastodon_api( struct http_request* req )
}
}
if( http_request_route( req, "timelines/public" ) ) {
show_statuses( req, NULL, 0 );
return true;
}
/*
if( !check_bearer_token(req) ) { return false; }
printf( "authorization still valid\n" );
//*/
struct account* owner = account_from_id(0);
if( http_request_route( req, "notifications" ) ) {
struct notification note = {
.account_id = 1,
.status_id = 1,
};
show_notifications( req, &note, 1 );
return true;
}
if( http_request_route( req, "statuses" ) ) {
if( http_request_route( req, "/" ) ) {
char* id_str = http_request_route_get_dir_or_file(req);
if( !id_str || !*id_str ) { return false; }
int id = -1;
sscanf( id_str, "%d", &id );
free(id_str);
if( id == -1 ) { return false; }
struct status* s = status_from_id(id);
if( http_request_route( req, "context" ) ) {
show_status_context( req, s );
} else {
show_status( req, s );
}
return true;
} else if( http_request_route_method( req, "POST" ) ) {
return handle_post(req, owner);
}
}
if( http_request_route( req, "timelines/home" ) ) {
return handle_timeline( req, "home" );
} else if( http_request_route( req, "accounts/verify_credentials" ) ) {
return true;
} else if( http_request_route( req, "accounts/" ) ) {
if( http_request_route( req, "verify_credentials" ) ) {
return true;
} else if( http_request_route( req, "statuses" ) ) {
show_statuses( req, NULL, 0 );
return true;
}
char* id_str = http_request_route_get_dir_or_file(req);
int id = -1;
printf( "id_str = %s\n", id_str );
if( !id_str ) { return false; }
if( !*id_str ) {
id = 0;
return handle_mastodon_api_show_account( req, owner );
} else {
sscanf( id_str, "%d", &id );
free( id_str );
if( id == -1 ) {
printf( "Invalid id\n" );
return false;
}
}
struct account* a = account_from_id( id );
if( !a ) { return false; }
if( http_request_route( req, "statuses" ) ) {
printf( "TODO: statuses\n" );
show_statuses( req, NULL, 0 );
return true;
} else {
return handle_mastodon_api_show_account( req, a );
}
}
return false;

@ -63,10 +63,10 @@ class Templator
@o.write c
end
end
if( (c=@i.read(1)) != "\n" )
puts "Expecting endline after %(), got #{c}"
exit
end
#if( (c=@i.read(1)) != "\n" )
# puts "Expecting endline after %(), got #{c}"
# exit
#end
@o.write "\n"
@o.write "\tfprintf( f, \""
@ -91,7 +91,7 @@ class Templator
elsif c == "\t"
output( "\\t" )
elsif c == "\\"
output( "\\" )
output( "\\\\" )
else
output(c)
end
@ -105,6 +105,8 @@ class Templator
arg_list = []
@o.write "\t);\n"
@o.puts "#endif"
@o.close
end
end

@ -1 +1 @@
Subproject commit 69c7584f8ea7861c726c2123145df4a03b11cd3d
Subproject commit acf1c752ae4bb099efd649e1110d39a7e0d75826

@ -1 +1 @@
Subproject commit 5dd89c8024b5ac0a3eb3675cc3871799e9c9c010
Subproject commit 4fff189159f80cf980ce65f2d3ebcb58f25a2d46

@ -0,0 +1,85 @@
#include "account.h"
#include "json/json.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static const char* safe( const char* value, const char* other )
{
if( !value ) { return other; }
return value;
}
static const char* b(bool value)
{
return value ? "true" : "false";
}
struct account* account_from_id( unsigned int id )
{
struct account* a = NULL;
char filename[512];
snprintf( filename, 512, "data/accounts/%d.json", id );
FILE* f = fopen(filename,"r");
if( !f) { return NULL; }
struct json_pull_parser* jpp = json_pull_parser_new( f );
if( !jpp ) { return NULL; }
a = malloc(sizeof(struct account));
a->id = id;
a->handle = NULL;
a->server = NULL;
a->display_name = NULL;
a->avatar.url = NULL;
a->avatar.static_url = NULL;
a->bot = false;
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, "handle" ) ) {
a->handle = json_pull_parser_read_string(jpp);
} else if( 0 == strcmp( key, "server" ) ) {
a->server = json_pull_parser_read_string(jpp);
} else if( 0 == strcmp( key, "display_name" ) ) {
a->display_name = json_pull_parser_read_string(jpp);
} else if( 0 == strcmp( key, "avatar" ) ) {
a->avatar.url = json_pull_parser_read_string(jpp);
} else if( 0 == strcmp( key, "avatar_static" ) ) {
a->avatar.static_url = json_pull_parser_read_string(jpp);
}
}
if( !json_pull_parser_end_object(jpp, &save ) ) { goto failed; }
cleanup:
json_pull_parser_release(jpp);
fclose(f);
return a;
failed:
account_free(a);
a = NULL;
goto cleanup;
}
void account_free( struct account* a )
{
if( !a ) { return; }
}
void account_write_as_json( struct account* a, FILE* f )
{
#define RENDER
#include "src/model/account.json.inc"
#undef RENDER
}

@ -0,0 +1,28 @@
#pragma once
#include <stdio.h>
#include <stdbool.h>
struct account
{
unsigned int id;
char* handle;
char* server;
char* display_name;
struct {
char* url;
char* static_url;
} avatar;
bool bot;
bool locked;
};
struct account* account_from_id( unsigned int id );
struct account* account_new();
void account_free( struct account* a );
void account_save( struct account* a );
void account_write_as_json( struct account* a, FILE* f );

@ -0,0 +1,48 @@
{
"acct": "%s{a->handle}%( if( a->server ) { )@%s{a->server}%( } )",
"avatar": "%s{safe(a->avatar.url,"")}",
"avatar_static": "%s{safe(a->avatar.static_url,"")}",
"bot": %s{ b(a->bot) },
"created_at": "2022-03-18T19:33:06.000Z",
"display_name": "%s{ safe( a->display_name, a->handle )}",
"emojis": [],
"fields": [],
"followers_count": 0,
"following_count": 0,
"fqn": "%s{a->handle}%( if( a->server ) { )@%s{a->server}%( } )",
"header": "https://pl.polaris-1.work/images/banner.png",
"header_static": "https://pl.polaris-1.work/images/banner.png",
"id": "%d{ a->id }",
"locked": %s{b(a->locked)},
"note": "Humble twitter aggregator for all those banned from it, feel free so steal my stuff and post it anywhere almost all of my stuff is stolen from twitter anyways, also im not Kinochet<br/>",
"pleroma": {
"accepts_chat_messages": true,
"also_known_as": [],
"ap_id": "https://poa.st/users/PinochetsCommieCopter",
"background_image": null,
"favicon": null,
"hide_favorites": true,
"hide_followers": false,
"hide_followers_count": false,
"hide_follows": false,
"hide_follows_count": false,
"is_admin": false,
"is_confirmed": true,
"is_moderator": false,
"relationship": {},
"skip_thread_containment": false,
"tags": []
},
"source": {
"fields": [],
"note": "",
"pleroma": {
"actor_type": "Person",
"discoverable": true
},
"sensitive": false
},
"statuses_count": 5133,
"url": "https://poa.st/users/PinochetsCommieCopter",
"username": "PinochetsCommieCopter"
}

@ -0,0 +1,16 @@
#include "notification.h"
#include "model/account.h"
#include "model/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
}

@ -0,0 +1,19 @@
#pragma once
#include <stdio.h>
struct notification
{
unsigned int id;
unsigned int account_id;
unsigned int status_id;
int type;
};
enum notification_type
{
nt_favorite = 1,
};
void notification_write_as_json( struct notification* n, FILE* f );

@ -0,0 +1,11 @@
{
"account": %( account_write_as_json(a,f); ),
"created_at": "2022-12-12T15:31:54.000Z",
"id": "%d{n->id}",
"pleroma": {
"is_muted": false,
"is_seen": false
},
"status": %( status_write_as_json(s,f); ),
"type": "favourite"
}

@ -1,13 +1,66 @@
#include "status.h"
#include "model/account.h"
#include "json/json.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static const char* host()
{
return "apogee.polaris-1.work";
}
struct status* status_from_id( unsigned int id )
{
struct status* s = NULL;
char filename[512];
snprintf( filename, 512, "data/statuses/%d.json", id );
FILE* f = fopen( filename, "r" );
if( !f ) { return NULL; }
struct json_pull_parser* jpp = json_pull_parser_new( f );
if( !jpp ) { return NULL; }
s = malloc(sizeof(struct status));
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; }
cleanup:
json_pull_parser_release(jpp);
fclose(f);
return s;
failed:
//status_free(s);
s = NULL;
goto cleanup;
}
void status_write_as_json( struct status* s, FILE* f )
{
struct account* account = account_from_id( s->account_id );
#define RENDER
#include "src/model/status.json.inc"
#undef RENDER
cleanup:
account_free(account);
}

@ -5,7 +5,9 @@
struct status
{
unsigned int id;
unsigned int account_id;
};
struct status* status_from_id( unsigned int id );
void status_write_as_json( struct status* s, FILE* f );

@ -1,111 +1,64 @@
{
"account": {
"acct": "PinochetsCommieCopter@poa.st",
"avatar": "https://i.poastcdn.org/8eed7003b59feae1b66cab96577cd18fedf5c13a55193bc78dadba50cae5c9aa.jpg",
"avatar_static": "https://i.poastcdn.org/8eed7003b59feae1b66cab96577cd18fedf5c13a55193bc78dadba50cae5c9aa.jpg",
"bot": false,
"created_at": "2022-03-18T19:33:06.000Z",
"display_name": "PinochetsCommieCopter",
"emojis": [],
"fields": [],
"followers_count": 0,
"following_count": 0,
"fqn": "PinochetsCommieCopter@poa.st",
"header": "https://pl.polaris-1.work/images/banner.png",
"header_static": "https://pl.polaris-1.work/images/banner.png",
"id": "AHXybo2KIxbkUzvewC",
"locked": false,
"note": "Humble twitter aggregator for all those banned from it, feel free so steal my stuff and post it anywhere almost all of my stuff is stolen from twitter anyways, also im not Kinochet<br/>",
"pleroma": {
"accepts_chat_messages": true,
"also_known_as": [],
"ap_id": "https://poa.st/users/PinochetsCommieCopter",
"background_image": null,
"favicon": null,
"hide_favorites": true,
"hide_followers": false,
"hide_followers_count": false,
"hide_follows": false,
"hide_follows_count": false,
"is_admin": false,
"is_confirmed": true,
"is_moderator": false,
"relationship": {},
"skip_thread_containment": false,
"tags": []
},
"source": {
"fields": [],
"note": "",
"pleroma": {
"actor_type": "Person",
"discoverable": true
},
"sensitive": false
},
"statuses_count": 5133,
"url": "https://poa.st/users/PinochetsCommieCopter",
"username": "PinochetsCommieCopter"
},
"application": null,
"bookmarked": false,
"card": null,
"content": "",
"created_at": "2022-12-12T02:52:24.000Z",
"emojis": [],
"favourited": false,
"favourites_count": 0,
"id": "AQW7nAyGMWDVvDO47E",
"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": %( 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"
}

Loading…
Cancel
Save