Andrew 3 giorni fa
parent
commit
fa89b1a8fc
4 ha cambiato i file con 467 aggiunte e 365 eliminazioni
  1. 410 339
      app/Controllers/AccountController.php
  2. 51 14
      app/Controllers/VideoController.php
  3. 0 11
      app/Hajeebtok.php
  4. 6 1
      config.ini.example

+ 410 - 339
app/Controllers/AccountController.php

@@ -21,343 +21,414 @@ use Pecee\SimpleRouter\SimpleRouter;
 
 class AccountController implements IRouteController
 {
-    public static function getToken(): string
-    {
-        $username = input("username");
-        $password = password_hash(input("password"), PASSWORD_DEFAULT);
-
-        $account = new Account(
-            username: $username,
-            password: $password,
-            picture_hash: "default",
-            verified: false
-        );
-
-        if ($account->Exists()) { // Account already exists
-            $account->Load();
-            if (password_verify($password, $account->password)) throw new UnauthenticatedException($account->id, 401);
-            $session = new Session(account_id: $account->id);
-        } else { // Create a new account
-            $session = new Session(account_id: $account->Save());
-        }
-
-        CORSHelper();
-        $token = $session->Save();
-        $session->Load();
-        return api_json([
-            "token" => $token,
-            "auth_date" => $session->date_authenticated
-        ]);
-    }
-
-    public static function getAccount($id): string
-    {
-        if($id === "myself") $id = get_token_id(request());
-        Logger::Debug($id);
-        Logger::Debug("Getting account id ($id).");
-
-        $account = new Account(id: $id);
-        $account->Load();
-
-        $followers = count(new Follow(followee_id: $id)->LoadMany());
-        $following = count(new Follow(follower_id: $id)->LoadMany());
-
-        try {
-            $links = new Link(account_id: $id)->LoadMany();
-        } catch (Exception $e) {
-            $links = [];
-        }
-
-
-        CORSHelper();
-        return api_json([
-            "id" => $id,
-            "username" => $account->username,
-            "verified" => $account->verified,
-            "bio" => $account->bio,
-            "pictureHash" => $account->picture_hash,
-            "followers" => $followers,
-            "following" => $following,
-            "myself" => $id == get_token_id(request()),
-            "links" => $links
-        ]);
-    }
-
-    public static function search(): string
-    {
-        $query = input("query");
-        $account = new Account(username: $query);
-        $accounts = $account->LoadMany();
-        return api_json($accounts);
-    }
-
-    public static function getVideos($id): string
-    {
-        if($id === "myself") $id = get_token_id(request());
-        $account = new Account(id: $id);
-        $data = Hajeebtok::$Database->Query("SELECT * FROM videos WHERE author_id = :author_id", ["author_id" => $account->id]);
-        if (empty($data)) throw new VideoNotFoundException(0, 404);
-
-        // todo: make it return in feed format!!!!
-        CORSHelper();
-        return api_json($data);
-    }
-
-    public static function getPicture($id): string
-    {
-        $signed_in = signed_in(request());
-        if($id === "myself") $id = get_token_id(request());
-
-        if($signed_in) {
-            try {
-                $account = new Account(id: $id);
-                $account->Load();
-
-                $picture_path = APP_ROOT . "/usercontent/pictures/$account->picture_hash.png";
-            } catch (Exception $e) {
-                $picture_path = APP_ROOT . "/usercontent/pictures/not_found.png";
-            }
-        } else {
-            // this is hardcoded because i dont care
-            $picture_path = APP_ROOT . "/usercontent/pictures/premium_" . rand(1, 57) . ".png";
-        }
-
-        $mimeTypes = new MimeTypes();
-
-        $picture_contents = file_get_contents($picture_path);
-        $picture_size = filesize($picture_path);
-
-        $mime = $mimeTypes->getMimeType(pathinfo($picture_path, PATHINFO_EXTENSION));
-
-        $response = response();
-        $response->header("Content-Type: $mime");
-        $response->header("Content-Length: $picture_size");
-        $response->header("Cache-Control: max-age=3600, public");
-
-        return $picture_contents;
-    }
-
-    public static function getAvailablePremiumProfilePictures(): string
-    {
-        $pictures = [];
-        for ($i = 1; $i <= 57; $i++) {
-            $pictures[] = $i;
-        }
-        return api_json($pictures);
-    }
-
-    public static function getPremiumProfilePicture($id): string
-    {
-        $picture_path = APP_ROOT . "/usercontent/pictures/premium_$id.png";
-
-        $mime_types = new MimeTypes();
-
-        $picture_contents = file_get_contents($picture_path);
-        $picture_size = filesize($picture_path);
-
-        $mime = $mime_types->getMimeType(pathinfo($picture_path, PATHINFO_EXTENSION));
-
-        $response = response();
-        $response->header("Content-Type: $mime");
-        $response->header("Content-Length: $picture_size");
-        $response->header("Cache-Control: max-age=3600, public");
-
-        return $picture_contents;
-    }
-
-    public static function updateAccount(): string
-    {
-        if(!signed_in(request())) throw new UnauthenticatedException(0, 401);
-        $id = get_token_id(request());
-
-        $picture_hash = input("picture_hash");
-        $picture = request()->getInputHandler()->file("picture");
-        $bio = input("bio");
-
-        if(empty($picture) && !empty($picture_hash)) {
-            $valid_picture_hash_list = [
-                "default",
-                "premium_1",
-                "premium_2",
-                "premium_3",
-                "premium_4",
-                "premium_5",
-                "premium_6",
-                "premium_7",
-                "premium_8",
-                "premium_9",
-                "premium_10",
-                "premium_11",
-                "premium_12",
-                "premium_13",
-                "premium_14",
-                "premium_15",
-                "premium_16",
-                "premium_17",
-                "premium_18",
-                "premium_19",
-                "premium_20",
-                "premium_21",
-                "premium_22",
-                "premium_23",
-                "premium_24",
-                "premium_25",
-                "premium_26",
-                "premium_27",
-                "premium_28",
-                "premium_29",
-                "premium_30",
-                "premium_31",
-                "premium_32",
-                "premium_33",
-                "premium_34",
-                "premium_35",
-                "premium_36",
-                "premium_37",
-                "premium_38",
-                "premium_39",
-                "premium_40",
-                "premium_41",
-                "premium_42",
-                "premium_43",
-                "premium_44",
-                "premium_45",
-                "premium_46",
-                "premium_47",
-                "premium_48",
-                "premium_49",
-                "premium_50",
-                "premium_51",
-                "premium_52",
-                "premium_53",
-                "premium_54",
-                "premium_55",
-                "premium_56",
-                "premium_57"
-            ];
-
-            if(!in_array($picture_hash, $valid_picture_hash_list)) throw new SecurityFaultException("Attempt to path trace on /update endpoint.",400);
-        } else if (!empty($picture) && empty($picture_hash)) {
-            $picture_hash = hash("sha256", $picture);
-            $picture_path =  APP_ROOT . "/usercontent/pictures/$picture_hash.png";
-
-            $size = getimagesize($picture);
-            $crop = min($size[0], $size[1]);
-            $image_contents = file_get_contents($picture);
-            $image_string = imagecreatefromstring($image_contents);
-            $cropped_image = imagecrop($image_string, [
-                "x" => 0,
-                "y" => 0,
-                "width" => $crop,
-                "height" => $crop
-            ]);
-            imagepng($cropped_image, $picture_path); // save image and crop and turn into png (i love php)
-        } else if(!empty($picture) && !empty($picture_hash)) {
-            throw new InvalidRequestException(400);
-        }
-
-        $old_account = new Account(id: $id);
-        $old_account->Load();
-        $new_account = new Account(
-            id: $id,
-            username: $old_account->username,
-            password: $old_account->password,
-            picture_hash: $picture_hash ?? $old_account->picture_hash,
-            verified: $old_account->verified,
-            bio: $bio ?? $old_account->bio,
-        );
-
-        CORSHelper();
-        $new_account->Update();
-        return api_json([
-            "id" => $new_account->id,
-            "username" => $new_account->username,
-            "pictureHash" => $new_account->picture_hash,
-            "bio" => $new_account->bio,
-            "verified" => $new_account->verified,
-        ]);
-    }
-
-    public static function addLink(): string
-    {
-        if(!signed_in(request())) throw new UnauthenticatedException(0, 401);
-        $account_id = get_token_id(request());
-        $link = input("link");
-        $link_type = input("linkType");
-
-        $link_enum_type = LinkEnum::tryFrom($link_type);
-        // todo: add enum type filtering
-
-        $link = new Link(account_id: $account_id, type: $link_enum_type, url: $link);
-        $link->Save();
-        return api_json([
-            "id" => $link->id,
-            "url" => $link->url,
-            "type" => $link->type->value,
-            "account_id" => $link->account_id
-        ]);
-    }
-
-    public static function getFollowers($id): string {
-        if($id === "myself") $id = get_token_id(request());
-        $followers = new Follow(followee_id: $id)->LoadMany();
-        if(empty($followers)) throw new FollowNotFoundException(0, 404);
-        for ($i = 0; $i < count($followers); $i++) {
-            $follower = $followers[$i]["follower_id"];
-            $account = new Account(id: $follower);
-            $account->Load();
-
-            $followers[$i] = [
-                "followee_id" => (int)$id,
-                "follower_id" => $follower,
-                "username" => $account->username,
-                "pictureHash" => $account->picture_hash,
-                "verified" => $account->verified
-            ];
-        }
-        return api_json($followers);
-    }
-
-    public static function getFollowing($id): string {
-        if($id === "myself") $id = get_token_id(request());
-        $following = new Follow(follower_id: $id)->LoadMany();
-        if(empty($following)) throw new FollowNotFoundException(0, 404);
-        for ($i = 0; $i < count($following); $i++) {
-            $followee = $following[$i]["followee_id"];
-            $account = new Account(id: $followee);
-            $account->Load();
-
-            $following[$i] = [
-                "followee_id" => $followee,
-                "follower_id" => (int)$id,
-                "username" => $account->username,
-                "pictureHash" => $account->picture_hash,
-                "verified" => $account->verified
-            ];
-        }
-        return api_json($following);
-    }
-
-    public static function RegisterRoutes(): void
-    {
-        SimpleRouter::group([
-            "prefix" => "/account/",
-        ], function () {
-            SimpleRouter::get("/availablePremiumProfilePictures", [AccountController::class, "getAvailablePremiumProfilePictures"]);
-            SimpleRouter::get("/getPremiumProfilePicture/{id}", [AccountController::class, "getPremiumProfilePicture"]);
-            SimpleRouter::get("/{id}/get", [AccountController::class, "getAccount"]);
-            SimpleRouter::get("/{id}/videos", [AccountController::class, "getVideos"]);
-            SimpleRouter::get("/{id}/picture", [AccountController::class, "getPicture"]);
-            SimpleRouter::get("/{id}/followers", [AccountController::class, "getFollowers"]);
-            SimpleRouter::get("/{id}/following", [AccountController::class, "getFollowing"]);
-            SimpleRouter::post("/token", [AccountController::class, "getToken"]);
-            SimpleRouter::post("/search", [AccountController::class, "search"]);
-            SimpleRouter::post("/update", [AccountController::class, "updateAccount"]);
-            SimpleRouter::post("/addLink", [AccountController::class, "addLink"]);
-            SimpleRouter::options("/update", "CORSHelper");
-            SimpleRouter::options("/token", "CORSHelper");
-            SimpleRouter::options("/{id}/get", "CORSHelper");
-            SimpleRouter::options("/{id}/videos", "CORSHelper");
-        });
-    }
+	public static function getToken(): string
+	{
+		$username = input("username");
+		$password = password_hash(input("password"), PASSWORD_DEFAULT);
+
+		$account = new Account(
+			username: $username,
+			password: $password,
+			picture_hash: "default",
+			verified: false
+		);
+
+		if ($account->Exists()) { // Account already exists
+			$account->Load();
+			if (password_verify($password, $account->password)) throw new UnauthenticatedException($account->id, 401);
+			$session = new Session(account_id: $account->id);
+		} else { // Create a new account
+			$session = new Session(account_id: $account->Save());
+		}
+
+		CORSHelper();
+		$token = $session->Save();
+		$session->Load();
+		return api_json([
+			"token" => $token,
+			"auth_date" => $session->date_authenticated
+		]);
+	}
+
+	public static function getAccount($id): string
+	{
+		if (!signed_in(request())) {
+			$usernames = explode(",", Hajeebtok::$Config->GetByDotKey("Service.FakeUsernames"));
+
+			CORSHelper();
+			return api_json([
+				"id" => $id,
+				"username" => $usernames[rand(0, count($usernames) - 1)],
+				"verified" => false,
+				"bio" => "SIGN IN to see this EPIC content!!!",
+				"pictureHash" => null,
+				"followers" => rand(5, 38203),
+				"following" => rand(5, 6243),
+				"myself" => false,
+				"links" => []
+			]);
+		}
+
+		if ($id === "myself") $id = get_token_id(request());
+		Logger::Debug($id);
+		Logger::Debug("Getting account id ($id).");
+
+		$account = new Account(id: $id);
+		$account->Load();
+
+		$followers = count(new Follow(followee_id: $id)->LoadMany());
+		$following = count(new Follow(follower_id: $id)->LoadMany());
+
+		try {
+			$links = new Link(account_id: $id)->LoadMany();
+		} catch (Exception $e) {
+			$links = [];
+		}
+
+
+		CORSHelper();
+		return api_json([
+			"id" => $id,
+			"username" => $account->username,
+			"verified" => $account->verified,
+			"bio" => $account->bio,
+			"pictureHash" => $account->picture_hash,
+			"followers" => $followers,
+			"following" => $following,
+			"myself" => $id == get_token_id(request()),
+			"links" => $links
+		]);
+	}
+
+	public static function search(): string
+	{
+		$query = input("query");
+		$account = new Account(username: $query);
+		$accounts = $account->LoadMany();
+		return api_json($accounts);
+	}
+
+	public static function getVideos($id): string
+	{
+		if(!signed_in(request())) {
+			$titles = explode(",", Hajeebtok::$Config->GetByDotKey("Service.FakeTitles"));
+			$descriptions = explode(",", Hajeebtok::$Config->GetByDotKey("Service.FakeDescriptions"));
+			$usernames = explode(",", Hajeebtok::$Config->GetByDotKey("Service.FakeUsernames"));
+
+			$feed = [];
+
+			for($i = 0; $i < rand(6, 20); $i++) {
+				$feed[] = [
+					"id" => rand(1, 10),
+					"title" => $titles[rand(0, count($titles) - 1)],
+					"description" => $descriptions[rand(0, count($descriptions) - 1)],
+					"likes" => rand(20000, 37020),
+					"dislikes" =>  rand(2, 12343),
+					"comments" => rand(2, 1029),
+					"shares" => rand(2, 200000),
+					"author" => [
+						"id" => rand(2, 59),
+						"pictureHash" => null,
+						"username" => $usernames[rand(0, count($usernames) - 1)],
+					],
+				];
+			}
+
+			CORSHelper();
+			return api_json($feed);
+		}
+		if ($id === "myself") $id = get_token_id(request());
+		$account = new Account(id: $id);
+		$video_number = intval(input("video") ?? "0");
+		$data = Hajeebtok::$Database->Query("SELECT * FROM videos WHERE author_id = :author_id", ["author_id" => $account->id]);
+		if (empty($data)) throw new VideoNotFoundException(0, 404);
+
+		$videos = [];
+		$valid_video = false;
+		foreach ($data as $video) {
+			if($video_number === 0) $valid_video = true;
+			if($video["id"] === $video_number) $valid_video = true;
+			if(!$valid_video) continue;
+
+			$account = new Account($video["author_id"]);
+			$account->Load();
+
+			$videos[] = ["id" => $video["id"],
+				"title" => $video["title"],
+				"description" => $video["description"],
+				"likes" => $video["likes"],
+				"dislikes" => $video["dislikes"],
+				"comments" => Hajeebtok::$Database->Single("SELECT COUNT(*) FROM comments WHERE video_id = :id", ["id" => $video["id"]]),
+				"shares" => Hajeebtok::$Database->Single("SELECT COUNT(*) FROM messages INNER JOIN videos ON messages.video_id = videos.id WHERE videos.id = :id", ["id" => $video["id"]]),
+				"author" => [
+					"id" => $video["author_id"],
+					"pictureHash" => $account->picture_hash,
+					"username" => $account->username,
+				],
+			];
+		}
+
+		CORSHelper();
+		return api_json($videos);
+	}
+
+	public static function getPicture($id): string
+	{
+		$signed_in = signed_in(request());
+		if ($id === "myself") $id = get_token_id(request());
+
+		if ($signed_in) {
+			try {
+				$account = new Account(id: $id);
+				$account->Load();
+
+				$picture_path = APP_ROOT . "/usercontent/pictures/$account->picture_hash.png";
+			} catch (Exception $e) {
+				$picture_path = APP_ROOT . "/usercontent/pictures/not_found.png";
+			}
+		} else {
+			// this is hardcoded because i dont care
+			$picture_path = APP_ROOT . "/usercontent/pictures/premium_" . rand(1, 57) . ".png";
+		}
+
+		$mimeTypes = new MimeTypes();
+
+		$picture_contents = file_get_contents($picture_path);
+		$picture_size = filesize($picture_path);
+
+		$mime = $mimeTypes->getMimeType(pathinfo($picture_path, PATHINFO_EXTENSION));
+
+		$response = response();
+		$response->header("Content-Type: $mime");
+		$response->header("Content-Length: $picture_size");
+		$response->header("Cache-Control: max-age=3600, public");
+
+		return $picture_contents;
+	}
+
+	public static function getAvailablePremiumProfilePictures(): string
+	{
+		$pictures = [];
+		for ($i = 1; $i <= 57; $i++) {
+			$pictures[] = $i;
+		}
+		return api_json($pictures);
+	}
+
+	public static function getPremiumProfilePicture($id): string
+	{
+		$picture_path = APP_ROOT . "/usercontent/pictures/premium_$id.png";
+
+		$mime_types = new MimeTypes();
+
+		$picture_contents = file_get_contents($picture_path);
+		$picture_size = filesize($picture_path);
+
+		$mime = $mime_types->getMimeType(pathinfo($picture_path, PATHINFO_EXTENSION));
+
+		$response = response();
+		$response->header("Content-Type: $mime");
+		$response->header("Content-Length: $picture_size");
+		$response->header("Cache-Control: max-age=3600, public");
+
+		return $picture_contents;
+	}
+
+	public static function updateAccount(): string
+	{
+		if (!signed_in(request())) throw new UnauthenticatedException(0, 401);
+		$id = get_token_id(request());
+
+		$picture_hash = input("picture_hash");
+		$picture = request()->getInputHandler()->file("picture");
+		$bio = input("bio");
+
+		if (empty($picture) && !empty($picture_hash)) {
+			$valid_picture_hash_list = [
+				"default",
+				"premium_1",
+				"premium_2",
+				"premium_3",
+				"premium_4",
+				"premium_5",
+				"premium_6",
+				"premium_7",
+				"premium_8",
+				"premium_9",
+				"premium_10",
+				"premium_11",
+				"premium_12",
+				"premium_13",
+				"premium_14",
+				"premium_15",
+				"premium_16",
+				"premium_17",
+				"premium_18",
+				"premium_19",
+				"premium_20",
+				"premium_21",
+				"premium_22",
+				"premium_23",
+				"premium_24",
+				"premium_25",
+				"premium_26",
+				"premium_27",
+				"premium_28",
+				"premium_29",
+				"premium_30",
+				"premium_31",
+				"premium_32",
+				"premium_33",
+				"premium_34",
+				"premium_35",
+				"premium_36",
+				"premium_37",
+				"premium_38",
+				"premium_39",
+				"premium_40",
+				"premium_41",
+				"premium_42",
+				"premium_43",
+				"premium_44",
+				"premium_45",
+				"premium_46",
+				"premium_47",
+				"premium_48",
+				"premium_49",
+				"premium_50",
+				"premium_51",
+				"premium_52",
+				"premium_53",
+				"premium_54",
+				"premium_55",
+				"premium_56",
+				"premium_57"
+			];
+
+			if (!in_array($picture_hash, $valid_picture_hash_list)) throw new SecurityFaultException("Attempt to path trace on /update endpoint.", 400);
+		} else if (!empty($picture) && empty($picture_hash)) {
+			$picture_hash = hash("sha256", $picture);
+			$picture_path = APP_ROOT . "/usercontent/pictures/$picture_hash.png";
+
+			$size = getimagesize($picture);
+			$crop = min($size[0], $size[1]);
+			$image_contents = file_get_contents($picture);
+			$image_string = imagecreatefromstring($image_contents);
+			$cropped_image = imagecrop($image_string, [
+				"x" => 0,
+				"y" => 0,
+				"width" => $crop,
+				"height" => $crop
+			]);
+			imagepng($cropped_image, $picture_path); // save image and crop and turn into png (i love php)
+		} else if (!empty($picture) && !empty($picture_hash)) {
+			throw new InvalidRequestException(400);
+		}
+
+		$old_account = new Account(id: $id);
+		$old_account->Load();
+		$new_account = new Account(
+			id: $id,
+			username: $old_account->username,
+			password: $old_account->password,
+			picture_hash: $picture_hash ?? $old_account->picture_hash,
+			verified: $old_account->verified,
+			bio: $bio ?? $old_account->bio,
+		);
+
+		CORSHelper();
+		$new_account->Update();
+		return api_json([
+			"id" => $new_account->id,
+			"username" => $new_account->username,
+			"pictureHash" => $new_account->picture_hash,
+			"bio" => $new_account->bio,
+			"verified" => $new_account->verified,
+		]);
+	}
+
+	public static function addLink(): string
+	{
+		if (!signed_in(request())) throw new UnauthenticatedException(0, 401);
+		$account_id = get_token_id(request());
+		$link = input("link");
+		$link_type = input("linkType");
+
+		$link_enum_type = LinkEnum::tryFrom($link_type);
+		// todo: add enum type filtering
+
+		$link = new Link(account_id: $account_id, type: $link_enum_type, url: $link);
+		$link->Save();
+		return api_json([
+			"id" => $link->id,
+			"url" => $link->url,
+			"type" => $link->type->value,
+			"account_id" => $link->account_id
+		]);
+	}
+
+	public static function getFollowers($id): string
+	{
+		if ($id === "myself") $id = get_token_id(request());
+		$followers = new Follow(followee_id: $id)->LoadMany();
+		if (empty($followers)) throw new FollowNotFoundException(0, 404);
+		for ($i = 0; $i < count($followers); $i++) {
+			$follower = $followers[$i]["follower_id"];
+			$account = new Account(id: $follower);
+			$account->Load();
+
+			$followers[$i] = [
+				"followee_id" => (int)$id,
+				"follower_id" => $follower,
+				"username" => $account->username,
+				"pictureHash" => $account->picture_hash,
+				"verified" => $account->verified
+			];
+		}
+		return api_json($followers);
+	}
+
+	public static function getFollowing($id): string
+	{
+		if ($id === "myself") $id = get_token_id(request());
+		$following = new Follow(follower_id: $id)->LoadMany();
+		if (empty($following)) throw new FollowNotFoundException(0, 404);
+		for ($i = 0; $i < count($following); $i++) {
+			$followee = $following[$i]["followee_id"];
+			$account = new Account(id: $followee);
+			$account->Load();
+
+			$following[$i] = [
+				"followee_id" => $followee,
+				"follower_id" => (int)$id,
+				"username" => $account->username,
+				"pictureHash" => $account->picture_hash,
+				"verified" => $account->verified
+			];
+		}
+		return api_json($following);
+	}
+
+	public static function RegisterRoutes(): void
+	{
+		SimpleRouter::group([
+			"prefix" => "/account/",
+		], function () {
+			SimpleRouter::get("/availablePremiumProfilePictures", [AccountController::class, "getAvailablePremiumProfilePictures"]);
+			SimpleRouter::get("/getPremiumProfilePicture/{id}", [AccountController::class, "getPremiumProfilePicture"]);
+			SimpleRouter::get("/{id}/get", [AccountController::class, "getAccount"]);
+			SimpleRouter::get("/{id}/videos", [AccountController::class, "getVideos"]);
+			SimpleRouter::get("/{id}/picture", [AccountController::class, "getPicture"]);
+			SimpleRouter::get("/{id}/followers", [AccountController::class, "getFollowers"]);
+			SimpleRouter::get("/{id}/following", [AccountController::class, "getFollowing"]);
+			SimpleRouter::post("/token", [AccountController::class, "getToken"]);
+			SimpleRouter::post("/search", [AccountController::class, "search"]);
+			SimpleRouter::post("/update", [AccountController::class, "updateAccount"]);
+			SimpleRouter::post("/addLink", [AccountController::class, "addLink"]);
+			SimpleRouter::options("/update", "CORSHelper");
+			SimpleRouter::options("/token", "CORSHelper");
+			SimpleRouter::options("/{id}/get", "CORSHelper");
+			SimpleRouter::options("/{id}/videos", "CORSHelper");
+		});
+	}
 }

+ 51 - 14
app/Controllers/VideoController.php

@@ -27,19 +27,20 @@ class VideoController implements IRouteController
 	{
 		$signed_in = signed_in(request());
 
-		$video_information = new Video($id);
-		$video_information->Load();
-		$mime_types = new MimeTypes();
-
-		if ($signed_in) { // Signed in
+		if($signed_in) {
+			$video_information = new Video($id);
+			$video_information->Load();
 			$video_path = APP_ROOT . "/usercontent/videos/$id/video.mp4";
-		} else { // not signed in
-			$rand = rand(1, 48);
+		}
+		else { // not signed in
+			$rand = rand(1, 47);
 			$video_path = APP_ROOT . "/usercontent/fake_videos/$rand/video.mp4";
 		}
 
 		CORSHelper();
+		Logger::Debug($video_path);
 		if (file_exists($video_path)) {
+			$mime_types = new MimeTypes();
 			$video_contents = file_get_contents($video_path);
 			$video_size = filesize($video_path);
 
@@ -48,7 +49,7 @@ class VideoController implements IRouteController
 			$response = response();
 			$response->header("Content-Type: $mime");
 			$response->header("Content-Length: $video_size");
-			$response->header("Cache-Control: max-age=86400, public");
+			$response->header("Cache-Control: no-cache");
 
 			return $video_contents;
 		} else {
@@ -115,10 +116,11 @@ class VideoController implements IRouteController
 	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
+			//$video_information = new Video($id);
+			//$video_information->Load();
+
 			$seconds = 2;
 			$video_path = APP_ROOT . "/usercontent/videos/$id/video.mp4";
 			$frame_path = APP_ROOT . "/usercontent/videos/$id/thumbnail.png";
@@ -144,21 +146,55 @@ class VideoController implements IRouteController
 		$mime = $mime_types->getMimeType(pathinfo($frame_path, PATHINFO_EXTENSION));
 		$response = response();
 		$response->header("Content-Type: $mime");
-		$response->header("Cache-Control: max-age=86400, public");
+		$response->header("Cache-Control: max-age=no-cache");
 
 		return file_get_contents($frame_path);
 	}
 
 	public static function getFeed(): string
 	{
-		// todo: implement offset & limit
+		$offset = intval(input("offset") ?? "0");
+		$limit = intval(Hajeebtok::$Config->GetByDotKey("Service.VideoFeedLimit"));
+
 		$signed_in = signed_in(request());
-		if (!$signed_in) throw new AccountNotFoundException(0, 404);
+		if (!$signed_in) {
+			$titles = explode(",", Hajeebtok::$Config->GetByDotKey("Service.FakeTitles"));
+			$descriptions = explode(",", Hajeebtok::$Config->GetByDotKey("Service.FakeDescriptions"));
+			$usernames = explode(",", Hajeebtok::$Config->GetByDotKey("Service.FakeUsernames"));
+
+			$feed = [];
+
+			for($i = 0; $i < $limit; $i++) {
+				$feed[] = [
+					"id" => rand(1, 10),
+					"title" => $titles[rand(0, count($titles) - 1)],
+					"description" => $descriptions[rand(0, count($descriptions) - 1)],
+					"likes" => rand(20000, 37020),
+					"dislikes" =>  rand(2, 12343),
+					"comments" => rand(2, 1029),
+					"shares" => rand(2, 200000),
+					"author" => [
+						"id" => rand(2, 59),
+						"pictureHash" => null,
+						"username" => $usernames[rand(0, count($usernames) - 1)],
+					],
+				];
+			}
+
+			CORSHelper();
+			return api_json($feed);
+		}
 		$id = get_token_id(request());
 
 		$feed = [];
 
-		$videos = Hajeebtok::$Database->Query("SELECT * FROM videos WHERE id NOT IN (SELECT video_id FROM views WHERE account_id = :account_id AND video_id > :offset) ORDER BY id DESC", ["account_id" => $id,  "offset" => $offset]);
+		$videos = Hajeebtok::$Database->Query("SELECT * FROM videos WHERE id NOT IN (SELECT video_id FROM views WHERE account_id = :account_id) ORDER BY id DESC LIMIT :limit OFFSET :offset", ["account_id" => $id, "offset" => $offset, "limit" => $limit]);
+		$vid_count = count($videos);
+		if ($vid_count < $limit) {
+			$fallback_videos = Hajeebtok::$Database->Query("SELECT * FROM videos ORDER BY id DESC LIMIT :remainder OFFSET :offset", ["offset" => $offset + $vid_count, "remainder" => $limit - $vid_count]);
+			$videos = array_merge($videos, $fallback_videos);
+		}
+
 		foreach ($videos as $video) {
 			$account = new Account($video["author_id"]);
 			$account->Load();
@@ -247,6 +283,7 @@ class VideoController implements IRouteController
 			SimpleRouter::options("/{id}/thumbnail", "CORSHelper");
 			SimpleRouter::options("/upload", "CORSHelper");
 			SimpleRouter::options("/search", "CORSHelper");
+			SimpleRouter::options("/feed", "CORSHelper");
 		});
 	}
 }

+ 0 - 11
app/Hajeebtok.php

@@ -45,17 +45,6 @@ class Hajeebtok {
 		
 		Logger::Info("Hajeebtok application initialized.");
 
-		/*
-		$hajeebtokAcc = new Account(username: "hajeebtok", password: "CENSORED", picture_hash: "default", verified: true, bio: "The best short form content platform!");
-		$hajeebtokAcc->Save();
-
-		$johnClapperAcc = new Account(username: "johnclapper", password: "CENSORED", picture_hash: "default", verified: true, bio: "My name is John Clapper. I clap everyone. I clap first at the cinema. No one else claps. Why does a jewish vrchat furry avatar bring a brisket to the vrchat furry convention? Because even in the metaverse they never show up empty handed!");
-		$johnClapperAcc->Save();
-
-		$hajeebtokVideo = new Video(title: "Habibi video", description: "🌹❤❤❤😍😍😍💖💖🎶🎶✌✌", author_id: 1, likes: 1000000, dislikes: 0);
-		$hajeebtokVideo->Save();
-		*/
-
         SimpleRouter::error(function (Request $request, Exception $error) {
             Logger::Error("Route fault: $error");
             $request->setRewriteCallback(function () use ($error) {

+ 6 - 1
config.ini.example

@@ -7,4 +7,9 @@ Database = "Database"
 Charset = "utf8mb4"
 
 [Instance]
-DebugMode = "false"
+URL = "hajeebtok.example.com"
+DebugURL = "hajeebtok.example.com"
+DebugMode = "true"
+
+[Service]
+VideoFeedLimit = 10