From 9c2f42e423096bdf56b7f96e07221f6420b0e337 Mon Sep 17 00:00:00 2001 From: ilotterytea Date: Sat, 19 Apr 2025 16:47:23 +0500 Subject: feat: upload emotes --- .gitignore | 2 +- database.sql | 5 +++ public/emotes/upload.php | 112 +++++++++++++++++++++++++++++++++++++++++++++++ src/images.php | 48 ++++++++++++++++++++ src/utils.php | 33 ++++++++++++++ 5 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 database.sql create mode 100644 public/emotes/upload.php create mode 100644 src/images.php create mode 100644 src/utils.php diff --git a/.gitignore b/.gitignore index 696fd05..c5801c5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ /.vscode -/userdata +userdata/ *.db \ No newline at end of file diff --git a/database.sql b/database.sql new file mode 100644 index 0000000..b4da2c1 --- /dev/null +++ b/database.sql @@ -0,0 +1,5 @@ +CREATE TABLE IF NOT EXISTS "emotes" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "code" TEXT NOT NULL, + "created_at" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); \ No newline at end of file diff --git a/public/emotes/upload.php b/public/emotes/upload.php new file mode 100644 index 0000000..e68aea4 --- /dev/null +++ b/public/emotes/upload.php @@ -0,0 +1,112 @@ +prepare("DELETE FROM emotes WHERE id = :id"); + $stmt->bindValue(":id", $id, SQLITE3_INTEGER); + $stmt->execute(); + $db->close(); + + array_map("unlink", glob("$path/*.*")); + rmdir($path); + http_response_code($response_code); + exit($response_text); +} + +include "../../src/utils.php"; +include "../../src/images.php"; + +if ($_SERVER['REQUEST_METHOD'] != "POST") { + echo 'imagine there is a page'; + exit; +} + +if (!isset($_FILES["file"])) { + http_response_code(400); + echo json_encode([ + "status_code" => 400, + "message" => "No file set", + "data" => null + ]); + exit; +} + +$code = str_safe($_POST["code"] ?? "", 500); + +if ($code == "") { + http_response_code(400); + echo json_encode([ + "status_code" => 400, + "message" => "Invalid code", + "data" => null + ]); + exit; +} + +// creating a new emote record +$db = new SQLite3("../../database.db"); + +$stmt = $db->prepare("INSERT INTO emotes(code) VALUES (:code)"); +$stmt->bindValue(":code", $code); +$results = $stmt->execute(); + +$id = $db->lastInsertRowID(); + +if ($id == 0) { + $db->close(); + http_response_code(500); + echo json_encode([ + "status_code" => 500, + "message" => "Failed to create an emote record", + "data" => null + ]); + exit; +} + +$path = "../static/userdata/emotes/$id"; + +if (!is_dir($path)) { + mkdir($path, 0777, true); +} + +$image = $_FILES["file"]; + +// resizing the image + +// TODO: make it configurable later +$max_width = max(128, 1); +$max_height = max(128, 1); + +// 3x image +$resized_image = resize_image($image["tmp_name"], "$path/3x", $max_width, $max_height); +if ($resized_image) { + abort_upload($path, $db, $id, $resized_image); +} + +// 2x image +$resized_image = resize_image($image["tmp_name"], "$path/2x", $max_width / 2, $max_height / 2); +if ($resized_image) { + abort_upload($path, $db, $id, $resized_image); +} + +// 1x image +$resized_image = resize_image($image["tmp_name"], "$path/1x", $max_width / 4, $max_height / 4); +if ($resized_image) { + abort_upload($path, $db, $id, $resized_image); +} + +$db->close(); + +if (isset($_SERVER["HTTP_ACCEPT"]) && $_SERVER["HTTP_ACCEPT"] == "application/json") { + http_response_code(201); + echo json_encode([ + "status_code" => 201, + "message" => null, + "data" => [ + "id" => $id, + "code" => $code + ] + ]); + exit; +} + +header("Location: /emotes/$id", true, 307); \ No newline at end of file diff --git a/src/images.php b/src/images.php new file mode 100644 index 0000000..0e09814 --- /dev/null +++ b/src/images.php @@ -0,0 +1,48 @@ + 400, + "message" => "Not an image", + "data" => null + ]); + } + + $imagick = new Imagick(); + + $imagick->readImage($src_path); + $format = strtolower($imagick->getImageFormat()); + + if ($imagick->getNumberImages() > 1) { + $imagick = $imagick->coalesceImages(); + + foreach ($imagick as $frame) { + $width = $frame->getImageWidth(); + $height = $frame->getImageHeight(); + $ratio = min($max_width / $width, $max_height / $height); + $new_width = (int) ($width * $ratio); + $new_height = (int) ($height * $ratio); + + $frame->resizeImage($new_width, $new_height, Imagick::FILTER_TRIANGLE, 1); + $frame->setImagePage($new_width, $new_height, 0, 0); + } + + $imagick = $imagick->deconstructImages(); + $imagick->writeImages("$dst_path.$format", true); + } else { + $width = $imagick->getImageWidth(); + $height = $imagick->getImageHeight(); + $ratio = min($max_width / $width, $max_height / $height); + $new_width = (int) ($width * $ratio); + $new_height = (int) ($height * $ratio); + + $imagick->resizeImage($new_width, $new_height, Imagick::FILTER_TRIANGLE, 1); + $imagick->writeImage("$dst_path.$format"); + } + + $imagick->clear(); + $imagick->destroy(); + + return null; +} \ No newline at end of file diff --git a/src/utils.php b/src/utils.php new file mode 100644 index 0000000..59ecad4 --- /dev/null +++ b/src/utils.php @@ -0,0 +1,33 @@ +