Andrew 14 hours ago
parent
commit
565174c938

+ 1 - 0
.idea/sqldialects.xml

@@ -2,5 +2,6 @@
 <project version="4">
   <component name="SqlDialectMappings">
     <file url="file://$PROJECT_DIR$/app/Controllers/VideoController.php" dialect="GenericSQL" />
+    <file url="file://$PROJECT_DIR$/app/Types/DatabaseObjects/Follow.php" dialect="GenericSQL" />
   </component>
 </project>

+ 1 - 0
README.md

@@ -18,6 +18,7 @@ mkdir usercontent
 cd usercontent
 mkdir videos
 mkdir pictures
+mkdir fake_videos
 cd ..
 
 # PHP Setup

+ 32 - 3
app/Controllers/AccountController.php

@@ -66,7 +66,8 @@ class AccountController implements IRouteController
 				"following" => rand(5, 6243),
 				"myself" => false,
 				"links" => [],
-				"socialCredit" => rand(-20223, 20223)
+				"socialCredit" => rand(-20223, 20223),
+                "followed" => false
 			]);
 		}
 
@@ -86,8 +87,10 @@ class AccountController implements IRouteController
 			$links = [];
 		}
 
+        $followed = new Follow(followee_id: $id, follower_id: get_token_id(request()))->Exists();
 
 		CORSHelper();
+
 		return api_json([
 			"id" => $id,
 			"username" => $account->username,
@@ -97,7 +100,8 @@ class AccountController implements IRouteController
 			"following" => $following,
 			"myself" => $id == get_token_id(request()),
 			"links" => $links,
-			"socialCredit" => $account->social_credit
+			"socialCredit" => $account->social_credit,
+            "followed" => $followed
 		]);
 	}
 
@@ -194,7 +198,7 @@ class AccountController implements IRouteController
 		$response = response();
 		$response->header("Content-Type: $mime");
 		$response->header("Content-Length: $picture_size");
-		$response->header("Cache-Control: max-age=3600, public");
+		$response->header("Cache-Control: max-age=1800, public");
 
 		return $picture_contents;
 	}
@@ -328,6 +332,7 @@ class AccountController implements IRouteController
 			picture_hash: $picture_hash ?? $old_account->picture_hash,
 			verified: $old_account->verified,
 			bio: $bio ?? $old_account->bio,
+            social_credit: $old_account->social_credit,
 		);
 
 		CORSHelper();
@@ -338,6 +343,7 @@ class AccountController implements IRouteController
 			"pictureHash" => in_array($new_account->picture_hash, $valid_picture_hash_list) ? $new_account->picture_hash : null,
 			"bio" => $new_account->bio,
 			"verified" => $new_account->verified,
+            "social_credit" => $old_account->social_credit,
 		]);
 	}
 
@@ -447,6 +453,28 @@ class AccountController implements IRouteController
 		return api_json($accounts);
 	}
 
+    public static function follow($id): string {
+        $signed_in = signed_in(request());
+        if(!$signed_in) throw new UnauthenticatedException(0, 401);
+        $follower_id = get_token_id(request());
+
+        $message = "Successful";
+        $successful = true;
+        $follow = new Follow(follower_id: $follower_id, followee_id: $id);
+        if($follow->Exists()) {
+            $successful = false;
+            $message = "You already follow this account...";
+        } else {
+            $follow->Save();
+        }
+
+        CORSHelper();
+        return api_json([
+            "successful" => $successful,
+            "message" => $message,
+        ]);
+    }
+
 	public static function RegisterRoutes(): void
 	{
 		SimpleRouter::group([
@@ -459,6 +487,7 @@ class AccountController implements IRouteController
 			SimpleRouter::get("/{id}/picture", [AccountController::class, "getPicture"]);
 			//SimpleRouter::get("/{id}/followers", [AccountController::class, "getFollowers"]);
 			//SimpleRouter::get("/{id}/following", [AccountController::class, "getFollowing"]);
+            SimpleRouter::post("/{id}/follow", [AccountController::class, "follow"]);
 			SimpleRouter::post("/token", [AccountController::class, "getToken"]);
 			SimpleRouter::post("/update", [AccountController::class, "updateAccount"]);
 			SimpleRouter::post("/addLink", [AccountController::class, "addLink"]);

+ 29 - 0
app/Controllers/HomeController.php

@@ -2,6 +2,8 @@
 
 namespace app\Controllers;
 
+use app\Exceptions\UnauthenticatedException;
+use app\Types\WebhookMessage;
 use Pecee\SimpleRouter\SimpleRouter;
 use app\Interfaces\IRouteController;
 use app\Hajeebtok;
@@ -13,6 +15,32 @@ class HomeController implements IRouteController
 		response()->redirect("https://" . Hajeebtok::$Config->GetByDotKey("Instance.URL"));
 	}
 
+    public static function contact(): string {
+        $signed_in = signed_in(request());
+        if(!$signed_in) throw new UnauthenticatedException(0, 401);
+        $message = input("message");
+        $email = input("email");
+        $name = input("name");
+
+        $webhook = new WebhookMessage();
+        $webhook->SetContent("this is ground control to major tom");
+        $webhook->AddEmbed([
+            "description" => $message,
+            "fields" => [],
+            "title" => "New message from $name",
+            "footer" => [
+                "text" => $email,
+            ],
+            "color" => 16711680 // red
+        ]);
+        $webhook->Send();
+
+        CORSHelper();
+        return api_json([
+            "message" => "sent successfully. we will try to answer in less than 15 days."
+        ]);
+    }
+
 	public static function RegisterRoutes(): void
 	{
 		SimpleRouter::group([
@@ -20,6 +48,7 @@ class HomeController implements IRouteController
 
 		], function () {
 			SimpleRouter::get("/", [HomeController::class, "redirect"]);
+            SimpleRouter::post("/contact", [HomeController::class, "contact"]);
 		});
 	}
 }

+ 16 - 0
app/Exceptions/InvalidWebhookMessageException.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace app\Exceptions;
+
+use app\Logger;
+use \Exception;
+use \Throwable;
+
+class InvalidWebhookMessageException extends Exception
+{
+	public function __construct(int $id, int $code = 0, ?Throwable $previous = null)
+	{
+		Logger::Error("Invalid webhook message exception. ($id)");
+		parent::__construct("Invalid webhook message exception. ($id)", $code, $previous);
+	}
+}

+ 1 - 0
app/Hajeebtok.php

@@ -5,6 +5,7 @@ namespace app;
 use app\Controllers\AccountController;
 use app\Types\DatabaseObjects\Message;
 use app\Types\DatabaseObjects\Comment;
+use app\Types\WebhookMessage;
 use Exception;
 use Pecee\Http\Request;
 use Pecee\SimpleRouter\SimpleRouter;

+ 10 - 0
app/Types/DatabaseObjects/Follow.php

@@ -82,4 +82,14 @@ class Follow implements IDatabaseObject
         
         return Hajeebtok::$Database->Query($command, $array);
     }
+
+    public function Exists(): bool {
+        if(empty($this->follower_id) || empty($this->followee_id)) throw new FollowNotFoundException(0, 400);
+        $data = Hajeebtok::$Database->Query("SELECT * FROM follows WHERE follower_id = :follower_id AND followee_id = :followee_id", [
+            "follower_id" => $this->follower_id,
+            "followee_id" => $this->followee_id
+        ]);
+
+        return !empty($data);
+    }
 }

+ 73 - 0
app/Types/WebhookMessage.php

@@ -0,0 +1,73 @@
+<?php
+
+namespace app\Types;
+
+use app\Exceptions\InvalidRequestException;
+use app\Exceptions\InvalidWebhookMessageException;
+use app\Hajeebtok;
+
+class WebhookMessage
+{
+    public private(set) ?string $url;
+    public private(set) ?array $embeds;
+
+    public private(set) ?string $content;
+    public private(set) ?string $username;
+    public private(set) ?string $avatar_url;
+
+    public function __construct(?string $url=null)
+    {
+        if(empty($url)) $this->url = Hajeebtok::$Config->GetByDotKey("Instance.DiscordWebhookURL");
+        else $this->url = $url;
+    }
+
+    public function SetAvatarURL(string $avatar_url): void {
+        $this->avatar_url = $avatar_url;
+    }
+
+    public function SetUsername(string $username): void {
+        $this->username = $username;
+    }
+
+    public function AddEmbed(array $embed): void {
+        $this->embeds[] = $embed;
+    }
+
+    public function SetContent(string $content): void {
+        $this->content = $content;
+    }
+
+    public function Send(): void {
+        $data = [];
+        if(!empty($this->username)) $data["username"] = $this->username;
+        if(!empty($this->avatar_url)) $data["avatar_url"] = $this->avatar_url;
+        if(!empty($this->embeds)) $data["embeds"] = $this->embeds;
+        if(!empty($this->content)) $data["content"] = $this->content;
+        if(empty($this->embeds) && empty($this->content)) throw new InvalidWebhookMessageException(0, 400);
+
+        $this->PostRequest($this->url, $data);
+    }
+
+    public static function postRequest(string $url, array $payload): string
+    {
+        $ch = curl_init($url);
+        curl_setopt($ch, CURLOPT_POST, true);
+        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
+        curl_setopt($ch, CURLOPT_HTTPHEADER, [
+            'Content-Type: application/json',
+            'Content-Length: ' . strlen(json_encode($payload)),
+        ]);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+
+        $response = curl_exec($ch);
+        $error = curl_error($ch);
+
+        curl_close($ch);
+
+        if ($error) {
+            throw new \Exception("Curl error: " . $error);
+        }
+
+        return $response;
+    }
+}

+ 2 - 1
composer.json

@@ -3,7 +3,8 @@
         "pecee/simple-router": "^5.4",
         "ralouphie/mimey": "^1.0",
         "php-ffmpeg/php-ffmpeg": "^1.3",
-        "ext-gd": "*"
+        "ext-gd": "*",
+        "ext-curl": "*"
     },
     "autoload": {
         "psr-4": {

+ 0 - 0
log.ps1