#include "timeline.h" // Submodules #include "http/server/request.h" #include "http/query.h" // Model #include "model/timeline.h" #include "model/status.h" // Controller #include "controller/api/status.h" #include bool handle_timeline( struct http_request* req, int timeline_id ) { struct params_t { int since_id; int max_id; int limit; bool hide_muted; bool pinned; } params = { .since_id = 0, .limit = 32, .max_id = 2147483647, .hide_muted = true, .pinned = false, }; #define OBJ_TYPE struct params_t static struct http_query_fields fields[] = { HTTP_QUERY_FIELD_INT( since_id ) HTTP_QUERY_FIELD_INT( limit ) HTTP_QUERY_FIELD_INT( max_id ) HTTP_QUERY_FIELD_BOOL( hide_muted ) HTTP_QUERY_FIELD_BOOL( pinned ) HTTP_QUERY_FIELD_END }; #undef OBJ_TYPE // handle query parameters if( http_request_route( req, "?" ) ) { http_query_parse( req, fields, ¶ms ); } if( params.limit > 100 ) { params.limit = 100; } 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[params.limit]; memset(ss,0,sizeof(ss)); struct status* items[params.limit]; struct { struct status** items; int count; } show = { .items = items, .count = 0 }; int offset = 0; int count = 0; int max_loops = 5; load_statuses: //printf( "loading offset=%d,limit=%d\n", offset, params.limit ); count = timeline_load_statuses( tl, offset, params.limit, ss ); //printf( "count=%d\n", count ); if( count == 0 ) { goto done; } // Filter for( int i = 0; i < count; ++i ) { struct status* s = ss[i]; if( s->id <= params.since_id ) { goto filtered; } if( s->id >= params.max_id ) { goto filtered; } if( s->pinned != params.pinned ) { goto filtered; } show.items[show.count] = s; show.count += 1; if( 0 ) { filtered: status_free(s); //printf( "Filtered out %d\n", s->id ); } } // Try to load more statuses if( count < params.limit ) { offset += params.limit; params.limit -= show.count; if( max_loops > 0 ) { max_loops -= 1; goto load_statuses; } } done: show_statuses( req, show.items, show.count ); for( int i = 0; i < show.count; ++i ) { status_free( show.items[i] ); } timeline_free(tl); return true; }