diff options
| author | ilotterytea <iltsu@alright.party> | 2025-04-22 02:56:09 +0500 |
|---|---|---|
| committer | ilotterytea <iltsu@alright.party> | 2025-04-22 03:23:46 +0500 |
| commit | df783376d2b3bdd8fe5e0e558fa781f40babd7f3 (patch) | |
| tree | 3cad6b62b81a70e73cc5df60b96740e7cf3ec992 | |
| parent | 55c5c9ca935a9077a1fd4003e93a10c5144a6bce (diff) | |
feat: users
| -rw-r--r-- | public/index.php | 2 | ||||
| -rw-r--r-- | public/static/img/icons/clock.png | bin | 0 -> 882 bytes | |||
| -rw-r--r-- | public/static/img/icons/door_in.png | bin | 0 -> 693 bytes | |||
| -rw-r--r-- | public/static/img/icons/emoticon_happy.png | bin | 0 -> 731 bytes | |||
| -rw-r--r-- | public/static/img/icons/heart.png | bin | 0 -> 749 bytes | |||
| -rw-r--r-- | public/static/img/icons/star.png | bin | 0 -> 670 bytes | |||
| -rw-r--r-- | public/static/img/icons/user.png | bin | 0 -> 741 bytes | |||
| -rw-r--r-- | public/static/style.css | 88 | ||||
| -rw-r--r-- | public/users.php | 418 | ||||
| -rw-r--r-- | src/emotes/single_page.php | 4 | ||||
| -rw-r--r-- | src/partials.php | 3 | ||||
| -rw-r--r-- | src/user.php | 36 |
12 files changed, 518 insertions, 33 deletions
diff --git a/public/index.php b/public/index.php index 5619208..a9b88bd 100644 --- a/public/index.php +++ b/public/index.php @@ -15,7 +15,7 @@ include_once "../src/config.php"; <div class="items row" style="gap:32px;"> <a href="/emotes">Emotes</a> - <a href="/users">Users</a> + <a href="/users.php">Users</a> <a href="/emotes/upload.php">Upload</a> <a href="/account">Account</a> <a href="/software">Chat clients</a> diff --git a/public/static/img/icons/clock.png b/public/static/img/icons/clock.png Binary files differnew file mode 100644 index 0000000..e2672c2 --- /dev/null +++ b/public/static/img/icons/clock.png diff --git a/public/static/img/icons/door_in.png b/public/static/img/icons/door_in.png Binary files differnew file mode 100644 index 0000000..41676a0 --- /dev/null +++ b/public/static/img/icons/door_in.png diff --git a/public/static/img/icons/emoticon_happy.png b/public/static/img/icons/emoticon_happy.png Binary files differnew file mode 100644 index 0000000..6b7336e --- /dev/null +++ b/public/static/img/icons/emoticon_happy.png diff --git a/public/static/img/icons/heart.png b/public/static/img/icons/heart.png Binary files differnew file mode 100644 index 0000000..d9ee53e --- /dev/null +++ b/public/static/img/icons/heart.png diff --git a/public/static/img/icons/star.png b/public/static/img/icons/star.png Binary files differnew file mode 100644 index 0000000..b88c857 --- /dev/null +++ b/public/static/img/icons/star.png diff --git a/public/static/img/icons/user.png b/public/static/img/icons/user.png Binary files differnew file mode 100644 index 0000000..79f35cc --- /dev/null +++ b/public/static/img/icons/user.png diff --git a/public/static/style.css b/public/static/style.css index 86013be..cb9a996 100644 --- a/public/static/style.css +++ b/public/static/style.css @@ -1,11 +1,14 @@ :root { - --background-color: #d7dfcd; + --background-color: #c4d1b5; --background-color-hover: #e4eed8; --background-color-disabled: #bec6b3; - --border-color: #b0b9a5; + --border-color: #95a186; - --foreground-color: #7f9c3c; - --foreground-color-hover: #4b5632; + --background-color-2: #cfdfbd; + --border-color-2: #849275; + + --foreground-color: #425514; + --foreground-color-hover: #1c220c; } * { @@ -15,14 +18,34 @@ font-family: Arial, Helvetica, sans-serif; } +h1 { + font-size: 26px; +} + +h2 { + font-size: 20px; +} + +h3 { + font-size: 16px; +} + div { display: unset; } +table { + text-align: left; +} + table.vertical th { text-align: right; } +table.vertical.left th { + text-align: left; +} + table.vertical th, table.vertical td { padding: 2px; @@ -50,9 +73,6 @@ form { gap: 4px; } -.row { - flex-direction: row; -} .container { width: 100%; @@ -66,7 +86,7 @@ form { flex-direction: column; } -section.content { +.content { flex-grow: 1; display: flex; flex-direction: column; @@ -79,15 +99,6 @@ section.content { flex-direction: row; } -.big-gap { - gap: 32px; -} - -.center { - justify-content: center; - align-items: center; -} - /** ------------ COUNTER @@ -236,12 +247,6 @@ button.purple:hover, flex-grow: 1; } -.row { - display: flex; - flex-direction: row; - align-items: center; -} - .right { justify-content: flex-end; } @@ -282,6 +287,16 @@ button.purple:hover, padding: 16px; } +.box .content .box { + background: var(--background-color-2); + border-color: var(--border-color-2); +} + +.box .content a.box:hover { + background: linear-gradient(0deg, var(--background-color-hover), var(--background-color-2)); + cursor: pointer; +} + .box hr { border-color: var(--border-color); border-width: 1px; @@ -358,14 +373,29 @@ a.box:hover { gap: 16px; } -.accman h1 { - font-size: 26px; +.row { + display: flex; + flex-direction: row; } -.accman h2 { - font-size: 20px; +.column { + display: flex; + flex-direction: column; } -.accman h3 { - font-size: 16px; +.flex { + flex-grow: 1; +} + +.small-gap { + gap: 8px; +} + +.big-gap { + gap: 32px; +} + +.center { + justify-content: center; + align-items: center; }
\ No newline at end of file diff --git a/public/users.php b/public/users.php new file mode 100644 index 0000000..73f1d54 --- /dev/null +++ b/public/users.php @@ -0,0 +1,418 @@ +<?php +include_once "../src/config.php"; +include_once "../src/user.php"; +include_once "../src/partials.php"; +include_once "../src/utils.php"; +include_once "../src/accounts.php"; +authorize_user(); +session_start(); + +$is_json = isset($_SERVER["HTTP_ACCEPT"]) && $_SERVER["HTTP_ACCEPT"] == "application/json"; + +$id = $_GET["id"] ?? ""; + +$db = new PDO(DB_URL, DB_USER, DB_PASS); + +if ($id == "") { + $page = $_GET["p"] ?? "0"; + $limit = 50; + $offset = $page * $limit; + $stmt = $db->prepare("SELECT id, username, joined_at, last_active_at FROM users ORDER BY last_active_at DESC LIMIT ? OFFSET ?"); + $stmt->bindParam(1, $limit, PDO::PARAM_INT); + $stmt->bindParam(2, $offset, PDO::PARAM_INT); + $stmt->execute(); + + $all_user_count = $db->query("SELECT COUNT(*) FROM users")->fetch()[0]; + + if ($is_json) { + header("Content-Type: application/json"); + echo json_encode([ + "status_code" => 200, + "message" => null, + "data" => [ + "all_user_count" => intval($all_user_count), + "users" => $stmt->fetchAll(PDO::FETCH_ASSOC) + ] + ]); + exit; + } + + echo '' ?> + <html> + + <head> + <title>User list - alright.party</title> + <link rel="stylesheet" href="/static/style.css"> + </head> + + <body> + <div class="container"> + <div class="wrapper"> + <?php html_navigation_bar() ?> + <section class="content row"> + <section class="sidebar"> + <?php html_navigation_search(); ?> + </section> + <section class="content"> + <section class="box"> + <div class="box navtab"> + <p><?php echo $all_user_count ?> Users</p> + </div> + <div class="box content"> + <?php + if ($stmt->rowCount() != 0) { + echo '<table>'; + echo '<tr>'; + echo '<th></th><th style="width:80%;">Username</th><th>Last active</th>'; + echo '<tr>'; + while ($row = $stmt->fetch()) { + $diff = time() - strtotime($row["last_active_at"]); + + $last_active = "moments"; + + if ($diff > 5) { + $last_active = format_timestamp($diff); + } + + echo '<tr>'; + echo '<td><img src="/static/userdata/avatars/' . $row["id"] . '" width="24" height="24"></td>'; + echo '<td><a href="/users.php?id=' . $row["id"] . '">' . $row["username"] . '</a></td>'; + echo "<td>$last_active ago</td>"; + echo '</tr>'; + } + echo '</table>'; + } else { + echo '<p>Nothing found...</p>'; + } + ?> + </div> + </section> + </section> + </section> + </div> + </div> + </body> + + </html> + <?php ; + exit; +} + +$stmt = $db->prepare("SELECT * FROM users WHERE id = ?"); +$stmt->execute([$id]); + +$user = null; + +if ($row = $stmt->fetch()) { + $user = new User($row); +} + +if ($user == null) { + header("Location: /404.php"); + exit; +} + +// --- EMOTE SETS --- +// TODO: OPTIMIZE IT ASAP!!! +$emote_sets = []; +$active_emote_set = null; + +// gathering acquired emote sets +$stmt = $db->prepare("SELECT emote_set_id, is_default FROM acquired_emote_sets WHERE user_id = ?"); +$stmt->execute([$user->id()]); + +while ($row = $stmt->fetch()) { + // getting more info about set + $set_stmt = $db->prepare("SELECT id, name, size FROM emote_sets WHERE id = ?"); + $set_stmt->execute([$row["emote_set_id"]]); + $set = $set_stmt->fetch(); + + // getting info about emote set content + $em_stmt = $db->prepare( + "SELECT e.id, e.code, e.ext FROM emotes e + INNER JOIN emote_set_contents AS esc + ON esc.emote_set_id = ? + WHERE esc.emote_id = e.id + " . ($row["is_default"] ? '' : ' LIMIT 5') + ); + $em_stmt->execute([$row["emote_set_id"]]); + + $emote_set = [ + "id" => $set["id"], + "name" => $set["name"], + "size" => $set["size"], + "emotes" => $em_stmt->fetchAll(PDO::FETCH_ASSOC) + ]; + + if ($row["is_default"]) { + $active_emote_set = count($emote_sets); + } + + array_push($emote_sets, $emote_set); +} + +$active_emote_set = &$emote_sets[$active_emote_set]; + +// gathering uploaded emotes +$stmt = $db->prepare("SELECT e.*, + CASE WHEN EXISTS ( + SELECT 1 + FROM emote_set_contents ec + INNER JOIN emote_sets es ON es.id = ec.emote_set_id + WHERE ec.emote_id = e.id AND es.owner_id = ? + ) THEN 1 ELSE 0 END AS is_in_user_set + FROM emotes e + WHERE e.uploaded_by = ? + ORDER BY e.created_at ASC + "); +$stmt->execute([$user->id(), $user->id()]); + +$uploaded_emotes = $stmt->fetchAll(PDO::FETCH_ASSOC); + +// gathering actions +// TODO: update it when we will have action logs +$actions = []; + +// TODO: add functionality + +// calculating contributions +$stmt = $db->prepare("SELECT COUNT(*) FROM emotes WHERE uploaded_by = ?"); +$stmt->execute([$user->id()]); +$contributions = $stmt->fetch()[0]; + +// getting status +$status = 1; + +// getting favorite reaction +$fav_reaction = 1; + +// getting favorite emote +$fav_emote = 1; + +if ($is_json) { + header("Content-type: application/json"); + echo json_encode([ + "status_code" => 200, + "message" => null, + "data" => [ + "id" => intval($user->id()), + "username" => $user->username(), + "joined_at" => $user->joined_at(), + "last_active_at" => $user->last_active_at(), + "stats" => [ + "status_id" => $status, + "contributions" => $contributions, + "favorite_reaction_id" => $fav_reaction, + "favorite_emote_id" => $fav_emote + ], + "active_emote_set_id" => $active_emote_set["id"], + "emote_sets" => $emote_sets, + "uploaded_emotes" => $uploaded_emotes, + "actions" => $actions + ] + ]); + exit; +} +?> + +<html> + +<head> + <title><?php echo $user->username() ?> - alright.party</title> + <link rel="stylesheet" href="/static/style.css"> +</head> + +<body> + <div class="container"> + <div class="wrapper"> + <?php echo html_navigation_bar() ?> + <section class="content row"> + <!-- User information --> + <section class="user-bar column small-gap"> + <section class="box"> + <div class="box navtab"> + <p>User #<?php echo $user->id() ?></p> + </div> + <div class="box content"> + <img src="/static/userdata/avatars/<?php echo $user->id() ?>" width="96" height="96"> + <h1><?php echo $user->username() ?></h1> + </div> + </section> + + <!-- STATS --> + <section class="box"> + <table class="vertical left"> + <tr> + <th><img src="/static/img/icons/user.png"> I am </th> + <td><?php + if ($status == 1) { + echo "Gemposter"; + } else { + echo "Unknown"; + } + ?></td> + </tr> + <tr> + <th><img src="/static/img/icons/door_in.png"> Joined</th> + <?php + echo '<td title="'; + echo date("M d, Y H:i:s", $user->joined_at()); + echo ' UTC">about ' . format_timestamp(time() - $user->joined_at()) . " ago</td>"; + ?> + </tr> + <tr> + <th><img src="/static/img/icons/clock.png"> Last activity</th> + <?php + $diff = time() - $user->last_active_at(); + if ($diff > 60) { + echo '<td title="'; + echo date("M d, Y H:i:s", $user->last_active_at()); + echo ' UTC">about ' . format_timestamp($diff) . " ago</td>"; + } else { + echo '<td>Online</td>'; + } + ?> + </tr> + <tr> + <th><img src="/static/img/icons/star.png"> Contributed emotes</th> + <td><?php echo $contributions ?></td> + </tr> + <tr> + <th><img src="/static/img/icons/emoticon_happy.png"> Favorite reaction</th> + <td> + <?php + if ($fav_reaction == 1) { + echo 'Gem <img src="/static/img/icons/gem.png">'; + } else { + echo 'Coal <img src="/static/img/icons/coal.png">'; + } + ?> + </td> + </tr> + <?php + $stmt = $db->prepare("SELECT code, ext FROM emotes WHERE id = ?"); + $stmt->execute([$fav_emote]); + + if ($row = $stmt->fetch()) { + echo '<tr>'; + echo '<th><img src="/static/img/icons/heart.png"> Favorite emote</th>'; + echo '<td>'; + echo "<a href=\"/emotes/$fav_emote\">"; + echo $row["code"] . ' <img src="/static/userdata/emotes/' . $fav_emote . '/1x.' . $row["ext"] . '" width="16" height="16">'; + echo '</a></td></tr>'; + } + ?> + </table> + </section> + + <!-- ACTIONS --> + <section class="box column"> + <a href="/message/send.php?user=<?php echo $user->id() ?>">Send a message</a> + <a href="/report.php?user=<?php echo $user->id() ?>">Report user</a> + </section> + </section> + + <!-- Emotes --> + <section class="column small-gap flex"> + <!-- Emoteset --> + <section class="box"> + <div class="box navtab"> + <p>Emotes</p> + </div> + <div class="box content items"> + <?php + if (!empty($emote_sets)) { + foreach ($emote_sets as $set_row) { ?> + <a href="/emotesets/<?php echo $set_row["id"] ?>" class="box"> + <div> + <?php + echo '<p>' . $set_row["name"] . '</p>'; + + if ($set_row["size"]) { + echo '<p class="circled black">' . $set_row["size"] . '</p>'; + } + ?> + </div> + + <div> + <?php + foreach ($set_row["emotes"] as $e) { + echo '<img src="/static/userdata/emotes/' . $e["id"] . '/1x.' . $e["ext"] . '">'; + } + ?> + </div> + </a> + <?php } + } else { + echo '<p>No emote sets found... ' . ((($_SESSION["user_id"] ?? "") == $id) ? 'Start adding emotes and you will have one! :)</p>' : '</p>'); + } + ?> + </div> + </section> + + <!-- Active emoteset --> + <?php + if ($active_emote_set != null) { + echo '' ?> + <section class="box"> + <div class="content items"> + <?php + if (!empty($active_emote_set["emotes"])) { + foreach ($active_emote_set["emotes"] as $emote_row) { + echo '<a class="box emote" href="/emotes/' . $emote_row["id"] . '">'; + echo '<img src="/static/userdata/emotes/' . $emote_row["id"] . '/2x.' . $emote_row["ext"] . '" alt="' . $emote_row["code"] . '"/>'; + echo '<p>' . $emote_row["code"] . '</p>'; + echo '</a>'; + } + } else { + echo '<p>No emotes found... ' . ((($_SESSION["user_id"] ?? "") == $id) ? 'Start adding emotes and they will appear here! :)</p>' : '</p>'); + } + ?> + </div> + </section><?php + } + ?> + + <!-- Uploaded emotes --> + <?php + if (!empty($uploaded_emotes)) { + echo '' ?> + <section class="box"> + <div class="box navtab"> + <p>Uploaded emotes</p> + </div> + <div class="box content items"> + <?php + foreach ($uploaded_emotes as $emote_row) { + echo '<a class="box emote" href="/emotes/' . $emote_row["id"] . '">'; + echo '<img src="/static/userdata/emotes/' . $emote_row["id"] . '/2x.' . $emote_row["ext"] . '" alt="' . $emote_row["code"] . '"/>'; + echo '<p>' . $emote_row["code"] . '</p>'; + echo '</a>'; + } + ?> + </div> + </section><?php + } + ?> + + <!-- Actions --> + <section class="box"> + <div class="box navtab"> + <p>Actions</p> + </div> + <div class="box content"> + <?php + if (!empty($actions)) { + } else { + echo "<p>This user has done nothing bad or good...</p>"; + } + ?> + </div> + </section> + </section> + </section> + </div> + </div> +</body> + +</html>
\ No newline at end of file diff --git a/src/emotes/single_page.php b/src/emotes/single_page.php index 92b4e24..d1fc4e8 100644 --- a/src/emotes/single_page.php +++ b/src/emotes/single_page.php @@ -108,7 +108,7 @@ include_once "../../src/config.php"; if ($row = $stmt->fetch()) { $username = $row["username"]; - $link = "/users/" . $emote->get_uploaded_by(); + $link = "/users.php?id=" . $emote->get_uploaded_by(); } $db = null; @@ -154,7 +154,7 @@ include_once "../../src/config.php"; <div class="items row"> <?php while ($row = $stmt->fetch()) { - echo '<a href="/users/' . $row["id"] . '">' . $row["username"] . '</a>'; + echo '<a href="/users.php?id=' . $row["id"] . '">' . $row["username"] . '</a>'; } ?> </div> diff --git a/src/partials.php b/src/partials.php index 8f2d2ab..0087df4 100644 --- a/src/partials.php +++ b/src/partials.php @@ -9,13 +9,14 @@ function html_navigation_bar() </a> <div class="links"> <a href="/emotes" class="button">Emotes</a> + <a href="/users.php" class="button">Users</a> <a href="/emotes/upload.php" class="button">Upload</a> <a href="/account" class="button">Account</a> </div> <?php if (isset($_SESSION["user_id"])) { echo '' ?> - <a href="/users/<?php echo $_SESSION["user_id"] ?>" class="links" style="margin-left:auto;"> + <a href="/users.php?id=<?php echo $_SESSION["user_id"] ?>" class="links" style="margin-left:auto;"> Signed in as <?php echo $_SESSION["user_name"] ?> <img src="/static/userdata/avatars/<?php echo $_SESSION["user_id"] ?>" width="24" height="24" /> </a> diff --git a/src/user.php b/src/user.php new file mode 100644 index 0000000..c09c5d5 --- /dev/null +++ b/src/user.php @@ -0,0 +1,36 @@ +<?php +class User +{ + private int $id; + private string $username; + private int $joined_at; + private int $last_active_at; + + function __construct($row) + { + $this->id = $row["id"]; + $this->username = $row["username"]; + $this->joined_at = strtotime($row["joined_at"]); + $this->last_active_at = strtotime($row["last_active_at"]); + } + + function id() + { + return $this->id; + } + + function username() + { + return $this->username; + } + + function joined_at() + { + return $this->joined_at; + } + + function last_active_at() + { + return $this->last_active_at; + } +}
\ No newline at end of file |
