#include "mastodon_api.h" #include "http_server/http_request.h" #include "form.h" #include "json/json.h" #include "model/status.h" #include "model/account.h" #include "model/notification.h" #include "model/timeline.h" #include "model/server.h" #include "api/client_apps.h" #include "api/status.h" #include "api/notice.h" #include #include #include #include enum timeline_ids { tli_owner = 0, tli_public = 1, tli_home = 2, }; bool handle_timeline( struct http_request* req, int timeline_id ) { bool hide_muted = true; unsigned int limit = 32; int max_id = INT_MAX; int since_id = 0; // handle query parameters if( http_request_route( req, "?" ) ) { const char* key; while( key = http_request_route_query_key(req) ) { const char* value = http_request_route_query_value(req); //printf( "%s = %s\n", key, value ); if( !value ) { } else if( 0 == strcmp(key,"limit") ) { int new_limit; sscanf(value,"%d",&new_limit); if( new_limit < limit ) { limit = new_limit; } } else if( 0 == strcmp(key,"with_muted") ) { hide_muted = false; } else if( 0 == strcmp(key,"since_id") ) { sscanf(value,"%d",&since_id); } else if( 0 == strcmp(key,"max_id") ) { sscanf(value,"%d",&max_id); } //printf( "Filter: limit=%d, max_id=%d, since_id=%d\n", limit, max_id, since_id ); } } struct timeline* tl = timeline_from_id( timeline_id ); if( !tl ) { http_request_send_headers( req, 200, "application/json", true ); FILE* f = http_request_get_response_body( req ); fprintf( f, "[]" ); return true; } struct status* ss[limit]; int count = timeline_load_statuses( tl, 0, limit, ss ); for( int i = 0; i < count; ++i ) { if( ss[i]->id <= since_id ) { count = i; break; } } int base = 0; for( int i = 0; i < count; ++i ) { if( ss[i]->id >= max_id ) { base = i + 1; } } //printf( "limit=%d, since_id=%d, base=%d\n", limit, since_id, base ); //printf( "count=%d\n", count - base ); show_statuses( req, &ss[base], count - base ); for( int i = 0; i < count; ++i ) { status_free( ss[i] ); } timeline_free(tl); 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; } static bool http_request_route_id( struct http_request* req, int* id ) { char* id_str = http_request_route_get_dir_or_file(req); if( !id_str || !*id_str ) { return false; } *id = -1; sscanf( id_str, "%d", id ); free(id_str); if( *id == -1 ) { return false; } return true; } bool route_mastodon_api( struct http_request* req ) { if( http_request_route_term( req, "apps" ) ) { if( http_request_route_method( req, "POST" ) ) { return handle_mastodon_api_apps(req); } } else if( http_request_route( req, "timelines/public" ) ) { return handle_timeline( req, tli_public ); } else if( http_request_route( req, "instance" ) ) { http_request_send_headers( req, 200, "application/json", true ); FILE* f = http_request_get_response_body( req ); #include "src/view/api/instance_data.json.inc" return true; } //* if( !check_bearer_token(req) ) { return false; } //printf( "authorization still valid\n" ); //*/ if( http_request_route( req, "notifications" ) ) { return handle_notifications(req); } else if( http_request_route( req, "filters" ) ) { http_request_send_headers( req, 200, "application/json", true ); FILE* f = http_request_get_response_body( req ); fprintf( f, "[]" ); return true; } else if( http_request_route( req, "statuses" ) ) { if( http_request_route( req, "/" ) ) { int id = -1; 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" ) ) { struct account* owner = account_from_id(0); bool res = handle_post(req, owner); account_free(owner); return res; } } else if( http_request_route( req, "timelines/" ) ) { if( http_request_route( req, "home" ) ) { return handle_timeline( req, tli_home ); } else if( http_request_route( req, "public" ) ) { return handle_timeline( req, tli_public ); } } else if( http_request_route( req, "apps/" ) ) { if( http_request_route( req, "verify_credentials" ) ) { http_request_send_headers( req, 200, "application/json", true ); FILE* f = http_request_get_response_body( req ); #include "src/view/api/verify_credentials.json.inc" return true; } } else if( http_request_route( req, "accounts/" ) ) { if( http_request_route( req, "verify_credentials" ) ) { struct account* owner = account_from_id(0); bool res = handle_mastodon_api_show_account( req, owner ); account_free(owner); return res; } else if( http_request_route( req, "relationships" ) ) { http_request_send_headers( req, 200, "application/json", true ); FILE* f = http_request_get_response_body( req ); fprintf( f, "[]" ); return true; } else if( http_request_route( req, "statuses" ) ) { return handle_timeline( req, tli_owner ); } int id = 0; if( http_request_route_id( req, &id ) ) { struct account* a = account_from_id( id ); if( !a ) { return false; } if( http_request_route( req, "statuses" ) ) { bool res = handle_timeline( req, id ); account_free(a); return res; } else { bool res = handle_mastodon_api_show_account( req, a ); account_free(a); return res; } } else if( id == 0 ) { struct account* owner = account_from_id(0); bool res = handle_mastodon_api_show_account( req, owner ); account_free(owner); return res; } } return false; }