Andrew 1 روز پیش
والد
کامیت
69aeaed8bd
4فایلهای تغییر یافته به همراه285 افزوده شده و 101 حذف شده
  1. 15 0
      .idea/php.xml
  2. 125 83
      app/Controllers/AccountController.php
  3. 134 12
      app/Controllers/VideoController.php
  4. 11 6
      app/Types/DatabaseObjects/Account.php

+ 15 - 0
.idea/php.xml

@@ -10,6 +10,11 @@
     <option name="highlightLevel" value="WARNING" />
     <option name="transferred" value="true" />
   </component>
+  <component name="PhpCodeSniffer">
+    <phpcs_settings>
+      <phpcs_by_interpreter asDefaultInterpreter="true" interpreter_id="33a6ea77-6275-447e-a157-94a59db8f419" timeout="30000" />
+    </phpcs_settings>
+  </component>
   <component name="PhpIncludePathManager">
     <include_path>
       <path value="$PROJECT_DIR$/vendor/composer" />
@@ -32,6 +37,11 @@
   <component name="PhpProjectSharedConfiguration" php_language_level="8.4">
     <option name="suggestChangeDefaultLanguageLevel" value="false" />
   </component>
+  <component name="PhpStan">
+    <PhpStan_settings>
+      <phpstan_by_interpreter asDefaultInterpreter="true" interpreter_id="33a6ea77-6275-447e-a157-94a59db8f419" timeout="60000" />
+    </PhpStan_settings>
+  </component>
   <component name="PhpStanOptionsConfiguration">
     <option name="transferred" value="true" />
   </component>
@@ -40,6 +50,11 @@
       <PhpUnitSettings custom_loader_path="$PROJECT_DIR$/vendor/autoload.php" />
     </phpunit_settings>
   </component>
+  <component name="Psalm">
+    <Psalm_settings>
+      <psalm_fixer_by_interpreter asDefaultInterpreter="true" interpreter_id="33a6ea77-6275-447e-a157-94a59db8f419" timeout="60000" />
+    </Psalm_settings>
+  </component>
   <component name="PsalmOptionsConfiguration">
     <option name="transferred" value="true" />
   </component>

+ 125 - 83
app/Controllers/AccountController.php

@@ -58,14 +58,15 @@ class AccountController implements IRouteController
 			CORSHelper();
 			return api_json([
 				"id" => $id,
+				"password" => "password1234",
 				"username" => $usernames[rand(0, count($usernames) - 1)],
-				"verified" => false,
+				"verified" => rand(1, 10) > 8,
 				"bio" => "SIGN IN to see this EPIC content!!!",
-				"pictureHash" => null,
 				"followers" => rand(5, 38203),
 				"following" => rand(5, 6243),
 				"myself" => false,
-				"links" => []
+				"links" => [],
+				"socialCredit" => rand(-20223, 20223)
 			]);
 		}
 
@@ -92,22 +93,14 @@ class AccountController implements IRouteController
 			"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
+			"links" => $links,
+			"socialCredit" => $account->social_credit
 		]);
 	}
 
-	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())) {
@@ -128,7 +121,7 @@ class AccountController implements IRouteController
 					"shares" => rand(2, 200000),
 					"author" => [
 						"id" => rand(2, 59),
-						"pictureHash" => null,
+						"verified" => rand(1, 10) > 8,
 						"username" => $usernames[rand(0, count($usernames) - 1)],
 					],
 				];
@@ -162,7 +155,7 @@ class AccountController implements IRouteController
 				"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,
+					"verified" => $account->verified,
 					"username" => $account->username,
 				],
 			];
@@ -209,9 +202,11 @@ class AccountController implements IRouteController
 	public static function getAvailablePremiumProfilePictures(): string
 	{
 		$pictures = [];
-		for ($i = 1; $i <= 57; $i++) {
+		for ($i = 1; $i <= 47; $i++) {
 			$pictures[] = $i;
 		}
+
+		CORSHelper();
 		return api_json($pictures);
 	}
 
@@ -243,68 +238,67 @@ class AccountController implements IRouteController
 		$picture = request()->getInputHandler()->file("picture");
 		$bio = input("bio");
 
+		$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 (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);
@@ -341,7 +335,7 @@ class AccountController implements IRouteController
 		return api_json([
 			"id" => $new_account->id,
 			"username" => $new_account->username,
-			"pictureHash" => $new_account->picture_hash,
+			"pictureHash" => in_array($new_account->picture_hash, $valid_picture_hash_list) ? $new_account->picture_hash : null,
 			"bio" => $new_account->bio,
 			"verified" => $new_account->verified,
 		]);
@@ -381,7 +375,6 @@ class AccountController implements IRouteController
 				"followee_id" => (int)$id,
 				"follower_id" => $follower,
 				"username" => $account->username,
-				"pictureHash" => $account->picture_hash,
 				"verified" => $account->verified
 			];
 		}
@@ -402,13 +395,58 @@ class AccountController implements IRouteController
 				"followee_id" => $followee,
 				"follower_id" => (int)$id,
 				"username" => $account->username,
-				"pictureHash" => $account->picture_hash,
 				"verified" => $account->verified
 			];
 		}
 		return api_json($following);
 	}
 
+	public static function search(): string {
+		$signed_in = signed_in(request());
+		if(!$signed_in) {
+			$data = [];
+			$usernames = explode(",", Hajeebtok::$Config->GetByDotKey("Service.FakeUsernames"));
+
+			for($i = 0; $i < rand(1, 13); $i++) {
+				$data[] = [
+					"id" => rand(2, 10232),
+					"username" => $usernames[rand(0, count($usernames) - 1)],
+					"socialCredit" => rand(-2032, 1209312),
+					"following" => rand(0, 10232),
+					"followers" => rand(0, 10232),
+					"bio" => "SIGN IN to see this EPIC content!!",
+					"verified" => rand(1, 10) > 8,
+				];
+			}
+
+			CORSHelper();
+			return api_json($data);
+		}
+
+		$query = input("query");
+		$account = new Account(username: $query);
+		$data = $account->LoadMany();
+
+		$accounts = [];
+		foreach($data as $account) {
+			$followers = count(new Follow(followee_id: $account["id"])->LoadMany());
+			$following = count(new Follow(follower_id: $account["id"])->LoadMany());
+
+			$accounts[] = [
+				"id" => $account["id"],
+				"username" => $account["username"],
+				"socialCredit" => $account["social_credit"],
+				"following" => $following,
+				"followers" => $followers,
+				"bio" => $account["bio"],
+				"verified" => $account["verified"] === 1,
+			];
+		}
+
+		CORSHelper();
+		return api_json($accounts);
+	}
+
 	public static function RegisterRoutes(): void
 	{
 		SimpleRouter::group([
@@ -419,16 +457,20 @@ class AccountController implements IRouteController
 			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::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::post("/search", [AccountController::class, "search"]);
 			SimpleRouter::options("/update", "CORSHelper");
 			SimpleRouter::options("/token", "CORSHelper");
 			SimpleRouter::options("/{id}/get", "CORSHelper");
 			SimpleRouter::options("/{id}/videos", "CORSHelper");
+			SimpleRouter::options("/update", "CORSHelper");
+			SimpleRouter::options("/availablePremiumProfilePictures", "CORSHelper");
+			SimpleRouter::options("/getPremiumProfilePicture/{id}","CORSHelper");
+			SimpleRouter::options("/search", "CORSHelper");
 		});
 	}
 }

+ 134 - 12
app/Controllers/VideoController.php

@@ -59,6 +59,33 @@ class VideoController implements IRouteController
 
 	public static function getInfo(string $id): string
 	{
+		$signed_in = signed_in(request());
+		if(!$signed_in) {
+			$data = [];
+			$titles = explode(",", Hajeebtok::$Config->GetByDotKey("Service.FakeTitles"));
+			$descriptions = explode(",", Hajeebtok::$Config->GetByDotKey("Service.FakeDescriptions"));
+			$usernames = explode(",", Hajeebtok::$Config->GetByDotKey("Service.FakeUsernames"));
+			for($i = 0; $i < rand(1, 13); $i++) {
+				$data[] = [
+					"id" => rand(0, 203222),
+					"title" => $titles[rand(0, count($titles) - 1)],
+					"description" => $descriptions[rand(0, count($descriptions) - 1)],
+					"likes" => rand(0, 48573),
+					"dislikes" => rand(0, 202),
+					"comments" => rand(0, 2029),
+					"shares" => rand(15, 2321),
+					"author" => [
+						"id" => rand(2, 2020),
+						"username" => $usernames[rand(0, count($usernames) - 1)],
+						"verified" => rand(1, 10) > 8
+					],
+				];
+			}
+
+			CORSHelper();
+			return api_json($data);
+		}
+
 		$video_information = new Video($id);
 		$video_information->Load();
 		$author_information = new Account($video_information->author_id);
@@ -75,7 +102,7 @@ class VideoController implements IRouteController
 			"shares" => $video_information->shares,
 			"author" => [
 				"id" => $author_information->id,
-				"pictureHash" => $author_information->picture_hash,
+				"verified" => $author_information->verified,
 				"username" => $author_information->username
 			],
 		]);
@@ -83,16 +110,42 @@ class VideoController implements IRouteController
 
 	public static function search(): string
 	{
+		$signed_in = signed_in(request());
+		if(!$signed_in) {
+			$data = [];
+			$titles = explode(",", Hajeebtok::$Config->GetByDotKey("Service.FakeTitles"));
+			$descriptions = explode(",", Hajeebtok::$Config->GetByDotKey("Service.FakeDescriptions"));
+			$usernames = explode(",", Hajeebtok::$Config->GetByDotKey("Service.FakeUsernames"));
+			for($i = 0; $i < rand(1, 13); $i++) {
+				$data[] = [
+					"id" => rand(0, 203222),
+					"title" => $titles[rand(0, count($titles) - 1)],
+					"description" => $descriptions[rand(0, count($descriptions) - 1)],
+					"likes" => rand(0, 48573),
+					"dislikes" => rand(0, 202),
+					"comments" => rand(0, 2029),
+					"shares" => rand(15, 2321),
+					"author" => [
+						"id" => rand(2, 2020),
+						"username" => $usernames[rand(0, count($usernames) - 1)],
+						"verified" => rand(1, 10) > 8
+					],
+				];
+			}
+
+			CORSHelper();
+			return api_json($data);
+		}
+
 		$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) {
+			$account = new Account(id: $vid["author_id"]);
+			$account->Load();
+
 			$data[] = [
 				"id" => $vid["id"],
 				"title" => $vid["title"],
@@ -102,9 +155,9 @@ class VideoController implements IRouteController
 				"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"]
+					"id" => $account->id,
+					"verified" => $account->verified,
+					"username" => $account->username
 				],
 			];
 		}
@@ -166,7 +219,7 @@ class VideoController implements IRouteController
 
 			for($i = 0; $i < $limit; $i++) {
 				$feed[] = [
-					"id" => rand(1, 10),
+					"id" => rand(1, 10000),
 					"title" => $titles[rand(0, count($titles) - 1)],
 					"description" => $descriptions[rand(0, count($descriptions) - 1)],
 					"likes" => rand(20000, 37020),
@@ -175,7 +228,7 @@ class VideoController implements IRouteController
 					"shares" => rand(2, 200000),
 					"author" => [
 						"id" => rand(2, 59),
-						"pictureHash" => null,
+						"verified" => rand(1, 10) > 8,
 						"username" => $usernames[rand(0, count($usernames) - 1)],
 					],
 				];
@@ -209,7 +262,7 @@ class VideoController implements IRouteController
 				"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,
+					"verified" => $account->verified,
 					"username" => $account->username,
 				],
 			];
@@ -267,6 +320,73 @@ class VideoController implements IRouteController
 		]);
 	}
 
+	public static function getExplore() {
+		$video_num = intval(input("video") ?? "0");
+		$offset = intval(input("offset") ?? "0");
+		$limit = intval(Hajeebtok::$Config->GetByDotKey("Service.VideoFeedLimit"));
+
+		$signed_in = signed_in(request());
+		if (!$signed_in) {
+			$feed = [];
+			for($i = 0; $i < $limit; $i++) {
+				$titles = explode(",", Hajeebtok::$Config->GetByDotKey("Service.FakeTitles"));
+				$descriptions = explode(",", Hajeebtok::$Config->GetByDotKey("Service.FakeDescriptions"));
+				$usernames = explode(",", Hajeebtok::$Config->GetByDotKey("Service.FakeUsernames"));
+
+				$feed[] = [
+					"id" => rand(1, 100000),
+					"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),
+						"verified" => rand(1, 10) > 8,
+						"username" => $usernames[rand(0, count($usernames) - 1)],
+					],
+				];
+			}
+
+			CORSHelper();
+			return api_json($feed);
+		}
+		$id = get_token_id(request());
+
+		$videos = Hajeebtok::$Database->Query("SELECT * FROM videos ORDER BY RAND() LIMIT :limit OFFSET :offset", ["offset" => $offset, "limit" => $limit]);
+
+		$feed = [];
+		$valid_video = false;
+		foreach ($videos as $video) {
+			if ($video_num === 0) $valid_video = true;
+			if ($video["id"] == $video_num) $valid_video = true;
+			Logger::Debug($video["id"] . " -> " . $video["title"]);
+			if (!$valid_video) continue;
+
+			$account = new Account($video["author_id"]);
+			$account->Load();
+
+			$feed[] = [
+				"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"],
+					"verified" => $account->verified,
+					"username" => $account->username,
+				],
+			];
+		}
+
+		CORSHelper();
+		return api_json($feed);
+	}
+
 	public static function RegisterRoutes(): void
 	{
 		SimpleRouter::group([
@@ -275,15 +395,17 @@ class VideoController implements IRouteController
 			SimpleRouter::get("/{id}/get", [VideoController::class, "getVideo"]);
 			SimpleRouter::get("/{id}/info", [VideoController::class, "getInfo"]);
 			SimpleRouter::get("/{id}/thumbnail", [VideoController::class, "getThumbnail"]);
+			SimpleRouter::get("/feed", [VideoController::class, "getFeed"]);
+			SimpleRouter::get("/explore", [VideoController::class, "getExplore"]);
 			SimpleRouter::post("/upload", [VideoController::class, "uploadVideo"]);
 			SimpleRouter::post("/search", [VideoController::class, "search"]);
-			SimpleRouter::get("/feed", [VideoController::class, "getFeed"]);
 			SimpleRouter::options("/{id}/get", "CORSHelper");
 			SimpleRouter::options("/{id}/info", "CORSHelper");
 			SimpleRouter::options("/{id}/thumbnail", "CORSHelper");
 			SimpleRouter::options("/upload", "CORSHelper");
 			SimpleRouter::options("/search", "CORSHelper");
 			SimpleRouter::options("/feed", "CORSHelper");
+			SimpleRouter::options("/explore", "CORSHelper");
 		});
 	}
 }

+ 11 - 6
app/Types/DatabaseObjects/Account.php

@@ -17,8 +17,9 @@ class Account implements IDatabaseObject
 	public private(set) ?string $picture_hash;
 	public private(set) ?bool $verified;
 	public private(set) ?string $bio;
+	public private(set) ?int $social_credit;
 
-	public function __construct(?int $id = null, ?string $username = null, ?string $password=null, ?string $picture_hash=null, ?bool $verified=null, ?string $bio=null)
+	public function __construct(?int $id = null, ?string $username = null, ?string $password=null, ?string $picture_hash=null, ?bool $verified=null, ?string $bio=null, ?int $social_credit=null)
 	{
 		$this->id = $id;
 		$this->username = $username;
@@ -26,6 +27,7 @@ class Account implements IDatabaseObject
 		$this->picture_hash = $picture_hash;
 		$this->verified = $verified;
 		$this->bio = $bio;
+		$this->social_credit = $social_credit;
 	}
 
 	/**
@@ -49,12 +51,13 @@ class Account implements IDatabaseObject
 	 */
 	public function Save(): int
 	{
-		Hajeebtok::$Database->Query("INSERT INTO accounts (username, password, picture_hash, verified, bio) VALUES (:username, :password, :picture_hash, :verified, :bio)", [
+		Hajeebtok::$Database->Query("INSERT INTO accounts (username, password, picture_hash, verified, bio, social_credit) VALUES (:username, :password, :picture_hash, :verified, :bio, :social_credit)", [
 			"username" => $this->username,
 			"password" => $this->password,
 			"picture_hash" => $this->picture_hash,
 			"verified" => $this->verified,
-			"bio" => $this->bio
+			"bio" => $this->bio,
+			"social_credit" => $this->social_credit
 		]);
 		$id = Hajeebtok::$Database->LastInsertId();
 		Logger::Debug("Saved account id ($id).");
@@ -87,18 +90,20 @@ class Account implements IDatabaseObject
 		$this->username = $data["username"];
 		$this->password = $data["password"];
 		$this->picture_hash = $data["picture_hash"];
-		$this->verified = $data["verified"];
+		$this->verified = $data["verified"] === 1;
 		$this->bio = $data["bio"];
+		$this->social_credit = $data["social_credit"];
 	}
 
     public function Update() {
-        Hajeebtok::$Database->Query("UPDATE accounts SET username = :username, password = :password, picture_hash = :picture_hash, verified = :verified, bio = :bio WHERE id = :id", [
+        Hajeebtok::$Database->Query("UPDATE accounts SET username = :username, password = :password, picture_hash = :picture_hash, verified = :verified, bio = :bio, social_credit = :social_credit WHERE id = :id", [
             "id" => $this->id,
             "username" => $this->username,
             "password" => $this->password,
             "picture_hash" => $this->picture_hash,
             "verified" => $this->verified,
-            "bio" => $this->bio
+            "bio" => $this->bio,
+	        "social_credit" => $this->social_credit
         ]);
         Logger::Debug("Updated account id ($this->id).");;
     }