diff options
| author | ilotterytea <iltsu@alright.party> | 2025-05-14 21:40:06 +0500 |
|---|---|---|
| committer | ilotterytea <iltsu@alright.party> | 2025-05-14 21:42:03 +0500 |
| commit | 4e29d4041e7cf254041e22d2052e94a7c53c9066 (patch) | |
| tree | 456bab310bf572bd562fb0c0f269cc0f4f44ab78 | |
| parent | ef2129093b31c488b17d90cf35fab5f46ba436b5 (diff) | |
feat: personal badges
| -rw-r--r-- | database.sql | 6 | ||||
| -rw-r--r-- | public/account/index.php | 39 | ||||
| -rw-r--r-- | public/emotes/index.php | 9 | ||||
| -rw-r--r-- | public/users.php | 25 | ||||
| -rw-r--r-- | src/config.sample.php | 1 |
5 files changed, 76 insertions, 4 deletions
diff --git a/database.sql b/database.sql index 36beec8..a92ad46 100644 --- a/database.sql +++ b/database.sql @@ -87,6 +87,12 @@ CREATE TABLE IF NOT EXISTS badges ( created_at TIMESTAMP NOT NULL DEFAULT UTC_TIMESTAMP ); +CREATE TABLE IF NOT EXISTS user_badges ( + id CHAR(32) NOT NULL PRIMARY KEY DEFAULT REPLACE(UUID(),'-',''), + user_id CHAR(32) NOT NULL REFERENCES users(id) ON DELETE CASCADE, + badge_id CHAR(32) NOT NULL REFERENCES badges(id) ON DELETE CASCADE +); + CREATE TABLE IF NOT EXISTS roles ( id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, priority INTEGER NOT NULL DEFAULT 0, diff --git a/public/account/index.php b/public/account/index.php index d62f87f..6cf3fc7 100644 --- a/public/account/index.php +++ b/public/account/index.php @@ -72,6 +72,28 @@ if ($_SERVER['REQUEST_METHOD'] == "POST") { } } + if (isset($_FILES["badge"]) && !empty($_FILES["badge"]["tmp_name"])) { + $badge = $_FILES["badge"]; + $badge_id = bin2hex(random_bytes(16)); + if ( + $err = create_image_bundle( + $badge["tmp_name"], + $_SERVER["DOCUMENT_ROOT"] . "/static/userdata/badges/" . $badge_id, + ACCOUNT_BADGE_MAX_SIZE[0], + ACCOUNT_BADGE_MAX_SIZE[1], + true, + true + ) + ) { + generate_alert("/account", sprintf("Error occurred while processing the personal badge (%d)", $err)); + exit; + } + + $db->prepare("DELETE FROM user_badges WHERE badge_id != ? AND user_id = ?")->execute([$badge_id, $_SESSION["user_id"]]); + $db->prepare("INSERT INTO badges(id, uploaded_by) VALUES (?, ?)")->execute([$badge_id, $_SESSION["user_id"]]); + $db->prepare("INSERT INTO user_badges(badge_id, user_id) VALUES (?, ?)")->execute([$badge_id, $_SESSION["user_id"]]); + } + $db = null; generate_alert("/account", "Your changes have been applied!", 200); exit; @@ -119,6 +141,23 @@ if ($_SERVER['REQUEST_METHOD'] == "POST") { ?> <input type="file" name="banner"> + <h3>Personal badge</h3> + <?php + $stmt = $db->prepare("SELECT badge_id FROM user_badges WHERE user_id = ?"); + $stmt->execute([$_SESSION["user_id"]]); + + if ($row = $stmt->fetch()) { + echo '<div class="box row items-center justify-between">'; + echo '<img src="/static/userdata/badges/' . $row["badge_id"] . '/1x.webp" id="badge">'; + echo '<img src="/static/userdata/badges/' . $row["badge_id"] . '/2x.webp" id="badge">'; + echo '<img src="/static/userdata/badges/' . $row["badge_id"] . '/3x.webp" id="badge">'; + echo '</div>'; + } else { + echo "<p>You don't have personal badge</p>"; + } + ?> + <input type="file" name="badge"> + <h3>Username</h3> <input type="text" name="username" id="username" value="<?php echo $_SESSION["user_name"] ?>"> diff --git a/public/emotes/index.php b/public/emotes/index.php index 9a33d1d..ad4df09 100644 --- a/public/emotes/index.php +++ b/public/emotes/index.php @@ -338,13 +338,15 @@ if (CLIENT_REQUIRES_JSON) { $link = "#"; $show_private_badge = false; $badge = null; + $custom_badge = null; if ($emote->get_uploaded_by()) { - $stmt = $db->prepare("SELECT u.username, up.private_profile, r.name AS role_name, r.badge_id AS role_badge_id + $stmt = $db->prepare("SELECT u.username, up.private_profile, r.name AS role_name, r.badge_id AS role_badge_id, ub.badge_id AS custom_badge_id FROM users u INNER JOIN user_preferences up ON up.id = u.id LEFT JOIN role_assigns ra ON ra.user_id = u.id LEFT JOIN roles r ON r.id = ra.role_id + LEFT JOIN user_badges ub ON ub.user_id = u.id WHERE u.id = ? "); $stmt->execute([$emote->get_uploaded_by()]); @@ -355,6 +357,7 @@ if (CLIENT_REQUIRES_JSON) { $username = $row["username"]; $link = "/users.php?id=" . $emote->get_uploaded_by(); $badge = ["role_name" => $row["role_name"], "role_badge_id" => $row["role_badge_id"]]; + $custom_badge = $row["custom_badge_id"]; } } @@ -370,6 +373,10 @@ if (CLIENT_REQUIRES_JSON) { echo ' <img src="/static/userdata/badges/' . $badge["role_badge_id"] . '/1x.webp" alt="## ' . $badge["role_name"] . '" title="' . $badge["role_name"] . '" />'; } + if ($custom_badge) { + echo " <img src='/static/userdata/badges/$custom_badge/1x.webp' alt='' title='Personal badge' />"; + } + echo ', <span title="'; echo date("M d, Y H:i:s", $emote->get_created_at()); echo ' UTC">about ' . format_timestamp(time() - $emote->get_created_at()) . " ago</span>"; diff --git a/public/users.php b/public/users.php index fced3eb..fcfd92b 100644 --- a/public/users.php +++ b/public/users.php @@ -280,6 +280,18 @@ $fav_reactions = $stmt->fetchAll(PDO::FETCH_ASSOC); // getting favorite emote $fav_emote = 1; +// getting custom badge +$stmt = $db->prepare("SELECT b.* FROM badges b + INNER JOIN user_badges ub ON ub.user_id = ? + WHERE b.id = ub.badge_id +"); +$stmt->execute([$user->id()]); + +$custom_badge = null; +if ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + $custom_badge = $row; +} + if ($is_json) { header("Content-type: application/json"); echo json_encode([ @@ -299,7 +311,8 @@ if ($is_json) { "active_emote_set_id" => $active_emote_set["id"], "emote_sets" => $emote_sets, "uploaded_emotes" => $uploaded_emotes, - "actions" => $actions + "actions" => $actions, + "custom_badge" => $custom_badge ] ]); exit; @@ -327,8 +340,14 @@ if ($is_json) { <section class="sidebar flex column small-gap"> <!-- User --> <section class="box"> - <div class="box navtab"> - <?php echo $user->username() ?> + <div class="box navtab flex items-center small-gap"> + <?php + echo $user->username(); + + if ($custom_badge) { + echo ' <img src="/static/userdata/badges/' . $custom_badge["id"] . '/1x.webp" alt="" title="Personal badge" />'; + } + ?> </div> <div class="box content justify-center items-center"> <?php diff --git a/src/config.sample.php b/src/config.sample.php index 5e57ef6..d6114b5 100644 --- a/src/config.sample.php +++ b/src/config.sample.php @@ -50,6 +50,7 @@ define("ACCOUNT_PASSWORD_MIN_LENGTH", 10); // Minimal length for passwords. define("ACCOUNT_SECRET_KEY_LENGTH", 32); // The length for secret keys. define("ACCOUNT_PFP_MAX_SIZE", [128, 128]); // Max dimensions for account pictures. define("ACCOUNT_BANNER_MAX_SIZE", [1920, 1080]); // Max dimensions for account banners. +define("ACCOUNT_BADGE_MAX_SIZE", [72, 72]); // Max dimensions for account badges. define("ACCOUNT_PUBLIC_LIST", true); // The public list of accounts. define("ACCOUNT_LOG_ACTIONS", true); // Log user's actions (emote addition, etc.). |
