summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorilotterytea <iltsu@alright.party>2025-05-14 21:40:06 +0500
committerilotterytea <iltsu@alright.party>2025-05-14 21:42:03 +0500
commit4e29d4041e7cf254041e22d2052e94a7c53c9066 (patch)
tree456bab310bf572bd562fb0c0f269cc0f4f44ab78
parentef2129093b31c488b17d90cf35fab5f46ba436b5 (diff)
feat: personal badges
-rw-r--r--database.sql6
-rw-r--r--public/account/index.php39
-rw-r--r--public/emotes/index.php9
-rw-r--r--public/users.php25
-rw-r--r--src/config.sample.php1
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.).