Load(); $mime_types = new MimeTypes(); if($signed_in) { // Signed in $video_path = APP_ROOT . "/usercontent/videos/$id/video.mp4"; } else { // not signed in $rand = rand(1, 48); $video_path = APP_ROOT . "/usercontent/fake_videos/$rand/video.mp4"; } CORSHelper(); if (file_exists($video_path)) { $video_contents = file_get_contents($video_path); $video_size = filesize($video_path); $mime = $mime_types->getMimeType(pathinfo($video_path, PATHINFO_EXTENSION)); $response = response(); $response->header("Content-Type: $mime"); $response->header("Content-Length: $video_size"); $response->header("Cache-Control: max-age=86400, public"); return $video_contents; } else { throw new VideoNotFoundException($id, 404); } } public static function getInfo(string $id): string { $video_information = new Video($id); $video_information->Load(); $author_information = new Account($video_information->author_id); $author_information->Load(); return api_json([ "title" => $video_information->title, "description" => $video_information->description, "likes" => $video_information->likes, "dislikes" => $video_information->dislikes, "comments" => $video_information->comments, "shares" => $video_information->shares, "author" => [ "id" => $author_information->id, "pictureHash" => $author_information->picture_hash, "username" => $author_information->username ], ]); } public static function search(): string { $query = input("query"); $video = new Video(title: $query); $videos = $video->LoadMany(); // idk if this is the greatest thing to do but jetbrains phpfart ai recommended it and it looks fine to me /shurg $accounts = Hajeebtok::$Database->Query("SELECT * FROM accounts WHERE id IN (SELECT author_id FROM videos WHERE title LIKE :title)", ["title" => "%$query%"]); if(empty($accounts)) throw new AccountNotFoundException(0, 404); $data = []; foreach($videos as $vid) { $data[] = [ "id" => $vid["id"], "title" => $vid["title"], "description" => $vid["description"], "likes" => $vid["likes"], "dislikes" => $vid["dislikes"], "comments" => Hajeebtok::$Database->Single("SELECT COUNT(*) FROM comments WHERE video_id = :id", ["id" => $vid["id"]]), "shares" => Hajeebtok::$Database->Single("SELECT COUNT(*) FROM messages INNER JOIN videos ON messages.video_id = videos.id WHERE videos.id = :id", ["id" => $vid["id"]]), "author" => [ "id" => $vid["author_id"], "pictureHash" => $accounts[$vid["author_id"] - 1]["picture_hash"], // kinda scuffed fix "username" => $accounts[$vid["author_id"] - 1]["username"] ], ]; } CORSHelper(); return api_json($data); } public static function getThumbnail(string $id): string { $signed_in = signed_in(request()); $video_information = new Video($id); $video_information->Load(); if($signed_in) { // Signed in $seconds = 2; $video_path = APP_ROOT . "/usercontent/videos/$id/video.mp4"; $frame_path = APP_ROOT . "/usercontent/videos/$id/thumbnail.png"; } else { // not signed in $rand = rand(1, 47); $seconds = 6; $video_path = APP_ROOT . "/usercontent/fake_videos/$rand/video.mp4"; $frame_path = APP_ROOT . "/usercontent/fake_videos/$rand/thumbnail.png"; } $mime_types = new MimeTypes(); if(!file_exists($video_path)) throw new VideoNotFoundException($id, 404); if(!file_exists($frame_path)) { Logger::Debug("Generating thumbnail for video $id"); $ffmpeg = FFMpeg\FFMpeg::create(); $video = $ffmpeg->open($video_path); $frame = $video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds($seconds)); $frame->save($frame_path); } CORSHelper(); $mime = $mime_types->getMimeType(pathinfo($frame_path, PATHINFO_EXTENSION)); $response = response(); $response->header("Content-Type: $mime"); $response->header("Cache-Control: max-age=86400, public"); return file_get_contents($frame_path); } public static function RegisterRoutes(): void { SimpleRouter::group([ "prefix" => "/video", ], function () { SimpleRouter::get("/{id}", [VideoController::class, "getVideo"]); SimpleRouter::get("/{id}/info", [VideoController::class, "getInfo"]); SimpleRouter::get("/{id}/thumbnail", [VideoController::class, "getThumbnail"]); SimpleRouter::post("/upload", [VideoController::class, "uploadVideo"]); SimpleRouter::post("/search", [VideoController::class, "search"]); SimpleRouter::options("/{id}", "CORSHelper"); SimpleRouter::options("/{id}/info", "CORSHelper"); SimpleRouter::options("/{id}/thumbnail", "CORSHelper"); SimpleRouter::options("/upload", "CORSHelper"); SimpleRouter::options("/search", "CORSHelper"); }); } }