diff options
| author | ilotterytea <me@ilotterytea.kz> | 2025-10-10 20:55:37 +0500 |
|---|---|---|
| committer | ilotterytea <me@ilotterytea.kz> | 2025-10-10 20:55:37 +0500 |
| commit | b1a885ac229892bac528e6fea4e011a1b240867b (patch) | |
| tree | 48152aa48c41defe7f850390ea1c99db2c725438 | |
initial commit
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | database.sql | 13 | ||||
| -rw-r--r-- | favicon.ico | bin | 0 -> 1150 bytes | |||
| -rw-r--r-- | index.php | 93 | ||||
| -rw-r--r-- | lib/time.php | 21 | ||||
| -rw-r--r-- | links.json | 22 | ||||
| -rw-r--r-- | projects.json | 46 | ||||
| -rw-r--r-- | rss.php | 49 | ||||
| -rw-r--r-- | static/img/bot.png | bin | 0 -> 6136 bytes | |||
| -rw-r--r-- | static/img/git.png | bin | 0 -> 302 bytes | |||
| -rwxr-xr-x | static/img/letter.png | bin | 0 -> 641 bytes | |||
| -rwxr-xr-x | static/img/pepe.png | bin | 0 -> 65268 bytes | |||
| -rw-r--r-- | static/img/pfp.png | bin | 0 -> 3280 bytes | |||
| -rw-r--r-- | static/img/radicle.png | bin | 0 -> 1082 bytes | |||
| -rw-r--r-- | static/img/rain.gif | bin | 0 -> 92393 bytes | |||
| -rwxr-xr-x | static/img/rss.png | bin | 0 -> 691 bytes | |||
| -rwxr-xr-x | static/img/wiki.png | bin | 0 -> 593 bytes | |||
| -rw-r--r-- | static/projects/maxon/banner.png | bin | 0 -> 43859 bytes | |||
| -rw-r--r-- | static/projects/maxon/screenshots/1.png | bin | 0 -> 114418 bytes | |||
| -rw-r--r-- | static/projects/maxon/screenshots/2.png | bin | 0 -> 68548 bytes | |||
| -rw-r--r-- | static/projects/voxelphalia/banner.png | bin | 0 -> 42425 bytes | |||
| -rw-r--r-- | static/projects/voxelphalia/screenshots/1.png | bin | 0 -> 173964 bytes | |||
| -rw-r--r-- | static/projects/voxelphalia/screenshots/2.png | bin | 0 -> 141993 bytes | |||
| -rw-r--r-- | static/style.css | 174 | ||||
| -rw-r--r-- | status/index.php | 52 | ||||
| -rw-r--r-- | status/post.php | 84 |
26 files changed, 556 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..14ab828 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.db +*.ini
\ No newline at end of file diff --git a/database.sql b/database.sql new file mode 100644 index 0000000..ab284a5 --- /dev/null +++ b/database.sql @@ -0,0 +1,13 @@ +CREATE TABLE IF NOT EXISTS statuses ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + title TEXT NOT NULL, + contents TEXT, + posted_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE IF NOT EXISTS comments ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT, + contents TEXT NOT NULL, + posted_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +);
\ No newline at end of file diff --git a/favicon.ico b/favicon.ico Binary files differnew file mode 100644 index 0000000..0541c52 --- /dev/null +++ b/favicon.ico diff --git a/index.php b/index.php new file mode 100644 index 0000000..6126901 --- /dev/null +++ b/index.php @@ -0,0 +1,93 @@ +<?php +include_once $_SERVER['DOCUMENT_ROOT'] . '/lib/time.php'; +if (file_exists("{$_SERVER['DOCUMENT_ROOT']}/projects.json") && $contents = file_get_contents("{$_SERVER['DOCUMENT_ROOT']}/projects.json")) { + $projects = json_decode($contents, true); +} +if (file_exists("{$_SERVER['DOCUMENT_ROOT']}/links.json") && $contents = file_get_contents("{$_SERVER['DOCUMENT_ROOT']}/links.json")) { + $links = json_decode($contents, true); +} +$db = new PDO("sqlite:{$_SERVER['DOCUMENT_ROOT']}/database.db"); +$stmt = $db->query("SELECT id, title, posted_at FROM statuses ORDER BY posted_at DESC LIMIT 1"); +$last_status = $stmt->fetch(PDO::FETCH_ASSOC) ?: null; +?> +<!DOCTYPE html> +<html> + +<head> + <title>ilotterytea</title> + <meta name="description" content="my personal website."> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> + <link rel="stylesheet" href="/static/style.css"> + <link rel="shortcut icon" href="favicon.ico" type="image/x-icon"> + <meta name="robots" content="nofollow"> +</head> + +<body> + <main> + <div class="rain"> + <p><img src="/static/img/pepe.png" alt="FeelsBadMan ☔ " width="18" height="18"> I'm just a memer</p> + </div> + <?php if (isset($projects)): ?> + <section class="projects"> + <?php foreach ($projects as $p): ?> + <div class="project"> + <div class="icon-wrapper"> + <img src="<?= $p['banner'] ?? '' ?>" alt=""> + </div> + <div class="summary"> + <div class="title"> + <h2><?= $p['title'] ?? 'No title.' ?> <span class="year"><?= $p['year'] ?></span></h2> + <?php if (isset($p['links'])): ?> + <div class="links"> + <?php foreach ($p['links'] as $l): ?> + <a href="<?= $l['url'] ?>" class="button <?= $l['style'] ?? '' ?>"><?= $l['name'] ?></a> + <?php endforeach; ?> + </div> + <?php endif; ?> + </div> + <p><?= $p['description'] ?? '<i>No description</i>' ?></p> + <?php if (isset($p['screenshots'])): ?> + <div class="screenshots"> + <?php foreach ($p['screenshots'] as $s): ?> + <a href="<?= $s ?>" target="_BLANK"><img src="<?= $s ?>" alt="Screenshot"></a> + <?php endforeach; ?> + </div> + <?php endif; ?> + </div> + </div> + <?php endforeach; ?> + </section> + <?php endif; ?> + <?php if (isset($last_status)): ?> + <div class="status"> + <p>Last status posted <?= format_timestamp(time() - strtotime($last_status['posted_at'])) ?> ago: <a + href="/status/?id=<?= $last_status['id'] ?>"><?= $last_status['title'] ?? 'No title.' ?></a></p> + <p style="font-size:10px;"><a href="/status/">[more...]</a> <a href="/rss.php"><img + src="/static/img/rss.png" alt="[rss]"></a></p> + </div> + <?php endif; ?> + <?php if (isset($links)): ?> + <div class="main-links"> + <?php foreach ($links as $l): ?> + <a href="<?= $l['url'] ?>"><img src="/static/img/<?= $l['icon'] ?>.png" alt=""><?= $l['title'] ?></a> + <?php endforeach; ?> + </div> + <?php endif; ?> + </main> +</body> + +<script> + const links = document.querySelector(".main-links"); + if (links) { + const link = document.createElement("a"); + link.href = [109, 97, 105, 108, 116, 111, 58, 105, 108, 116, 115, 117, 64, 97, 108, 114, 105, 103, 104, 116, 46, 112, 97, 114, 116, 121].map(x => String.fromCharCode(x)).join(''); + const img = document.createElement("img"); + img.src = "/static/img/letter.png"; + img.alt = ""; + link.appendChild(img); + link.innerHTML += atob(["bWFpb", "CB", "tZSE="].join('')); + links.appendChild(link); + } +</script> + +</html>
\ No newline at end of file diff --git a/lib/time.php b/lib/time.php new file mode 100644 index 0000000..dc8b54f --- /dev/null +++ b/lib/time.php @@ -0,0 +1,21 @@ +<?php +function format_timestamp(int $timestamp) +{ + $days = (int) floor($timestamp / (60.0 * 60.0 * 24.0)); + $years = (int) floor($days / 365); + $hours = (int) floor(round($timestamp / (60 * 60)) % 24); + $minutes = (int) floor(round($timestamp % (60 * 60)) / 60); + $seconds = (int) floor($timestamp % 60); + + if ($years == 0 && $days == 0 && $hours == 0 && $minutes == 0) { + return "$seconds second" . ($seconds > 1 ? "s" : ""); + } else if ($years == 0 && $days == 0 && $hours == 0) { + return "$minutes minute" . ($minutes > 1 ? "s" : ""); + } else if ($years == 0 && $days == 0) { + return "$hours hour" . ($hours > 1 ? "s" : ""); + } else if ($years == 0) { + return "$days day" . ($days > 1 ? "s" : ""); + } else { + return "$years year" . ($years > 1 ? "s" : ""); + } +}
\ No newline at end of file diff --git a/links.json b/links.json new file mode 100644 index 0000000..033c4e6 --- /dev/null +++ b/links.json @@ -0,0 +1,22 @@ +[ + { + "title": "wiki", + "icon": "wiki", + "url": "https://wiki.alright.party" + }, + { + "title": "@teabot", + "icon": "bot", + "url": "https://bot.alright.party" + }, + { + "title": "radicle", + "icon": "radicle", + "url": "https://app.radicle.xyz/nodes/seed.ilt.su" + }, + { + "title": "git", + "icon": "git", + "url": "https://git.ilt.su" + } +]
\ No newline at end of file diff --git a/projects.json b/projects.json new file mode 100644 index 0000000..15491ff --- /dev/null +++ b/projects.json @@ -0,0 +1,46 @@ +[ + { + "title": "Maxon Petting Simulator", + "year": "2022", + "description": "A clicker game about a cute kitty whose cheeks must always be squished.", + "banner": "/static/projects/maxon/banner.png", + "links": [ + { + "url": "https://ilotterytea.itch.io/maxon", + "name": "Download", + "style": "green" + }, + { + "url": "https://git.ilt.su/maxon.git", + "name": "Source code", + "style": "gray" + } + ], + "screenshots": [ + "/static/projects/maxon/screenshots/1.png", + "/static/projects/maxon/screenshots/2.png" + ] + }, + { + "title": "Voxelphalia", + "year": "2025", + "description": "Another voxel-based sandbox game where you can build whatever you want...", + "banner": "/static/projects/voxelphalia/banner.png", + "links": [ + { + "url": "https://ilotterytea.itch.io/voxelphalia", + "name": "Download", + "style": "green" + }, + { + "url": "https://git.ilt.su/voxelphalia.git", + "name": "Source code", + "style": "gray" + } + ], + "screenshots": [ + "/static/projects/voxelphalia/screenshots/1.png", + "/static/projects/voxelphalia/screenshots/2.png" + ] + } +]
\ No newline at end of file @@ -0,0 +1,49 @@ +<?php +include_once $_SERVER['DOCUMENT_ROOT'] . '/lib/time.php'; +$db = new PDO("sqlite:{$_SERVER['DOCUMENT_ROOT']}/database.db"); +$stmt = $db->query("SELECT * FROM statuses ORDER BY posted_at DESC"); +$statuses = $stmt->fetchAll(PDO::FETCH_ASSOC); + +header('Content-Type: application/xml'); + +echo "<?xml version='1.0' encoding='UTF-8'?>"; +echo "<rss version='2.0' xmlns:content='http://purl.org/rss/1.0/modules/content/'>"; +echo "<channel>"; + +echo "<title>ilt.su</title>"; +echo "<link>https://ilt.su</link>"; +echo "<description>ilotterytea's racist schizo thoughts. read and learn.</description>"; +echo "<language>en-us</language>"; + + +if (!empty($statuses)) { + $date = new DateTime($statuses[0]['posted_at']); + echo "<lastBuildDate>"; + echo $date->format('D, d M Y H:i:s O'); + echo "</lastBuildDate>"; +} + +foreach ($statuses as $s) { + $date = new DateTime($s['posted_at']); + + echo "<item>"; + echo "<title>"; + echo $s['title'] ?: '-NO TITLE-'; + echo "</title>"; + + echo '<guid isPermaLink="true">'; + echo "https://ilt.su/statuses/?id=" . $s['id']; + echo "</guid>"; + + echo "<pubDate>"; + echo $date->format('D, d M Y H:i:s O'); + echo "</pubDate>"; + + echo "<content:encoded><![CDATA["; + echo $s['contents'] ?: '-NO CONTENT-'; + echo "]]></content:encoded>"; + echo "</item>"; +} + +echo "</channel></rss>"; +?>
\ No newline at end of file diff --git a/static/img/bot.png b/static/img/bot.png Binary files differnew file mode 100644 index 0000000..4a30b26 --- /dev/null +++ b/static/img/bot.png diff --git a/static/img/git.png b/static/img/git.png Binary files differnew file mode 100644 index 0000000..e1f8acf --- /dev/null +++ b/static/img/git.png diff --git a/static/img/letter.png b/static/img/letter.png Binary files differnew file mode 100755 index 0000000..7348aed --- /dev/null +++ b/static/img/letter.png diff --git a/static/img/pepe.png b/static/img/pepe.png Binary files differnew file mode 100755 index 0000000..d5bf04f --- /dev/null +++ b/static/img/pepe.png diff --git a/static/img/pfp.png b/static/img/pfp.png Binary files differnew file mode 100644 index 0000000..e3cf428 --- /dev/null +++ b/static/img/pfp.png diff --git a/static/img/radicle.png b/static/img/radicle.png Binary files differnew file mode 100644 index 0000000..429f5c2 --- /dev/null +++ b/static/img/radicle.png diff --git a/static/img/rain.gif b/static/img/rain.gif Binary files differnew file mode 100644 index 0000000..ad0426b --- /dev/null +++ b/static/img/rain.gif diff --git a/static/img/rss.png b/static/img/rss.png Binary files differnew file mode 100755 index 0000000..315c4f4 --- /dev/null +++ b/static/img/rss.png diff --git a/static/img/wiki.png b/static/img/wiki.png Binary files differnew file mode 100755 index 0000000..b0f4dd7 --- /dev/null +++ b/static/img/wiki.png diff --git a/static/projects/maxon/banner.png b/static/projects/maxon/banner.png Binary files differnew file mode 100644 index 0000000..baac0a6 --- /dev/null +++ b/static/projects/maxon/banner.png diff --git a/static/projects/maxon/screenshots/1.png b/static/projects/maxon/screenshots/1.png Binary files differnew file mode 100644 index 0000000..30823a2 --- /dev/null +++ b/static/projects/maxon/screenshots/1.png diff --git a/static/projects/maxon/screenshots/2.png b/static/projects/maxon/screenshots/2.png Binary files differnew file mode 100644 index 0000000..35f9bc6 --- /dev/null +++ b/static/projects/maxon/screenshots/2.png diff --git a/static/projects/voxelphalia/banner.png b/static/projects/voxelphalia/banner.png Binary files differnew file mode 100644 index 0000000..981ae05 --- /dev/null +++ b/static/projects/voxelphalia/banner.png diff --git a/static/projects/voxelphalia/screenshots/1.png b/static/projects/voxelphalia/screenshots/1.png Binary files differnew file mode 100644 index 0000000..54df9a8 --- /dev/null +++ b/static/projects/voxelphalia/screenshots/1.png diff --git a/static/projects/voxelphalia/screenshots/2.png b/static/projects/voxelphalia/screenshots/2.png Binary files differnew file mode 100644 index 0000000..8ea6616 --- /dev/null +++ b/static/projects/voxelphalia/screenshots/2.png diff --git a/static/style.css b/static/style.css new file mode 100644 index 0000000..74332eb --- /dev/null +++ b/static/style.css @@ -0,0 +1,174 @@ +* { + margin: 0; + padding: 0; +} + +body { + width: 100%; + min-height: 100vh; + display: flex; + justify-content: center; +} + +main { + width: 50%; + display: flex; + flex-direction: column; + gap: 32px; + margin-top: 32px; +} + +a { + color: black; +} + +a.gray { + background: lightgray; +} + +a.green { + background: lime; +} + +a:hover { + color: white; + background: black; + text-decoration: line-through; +} + +p img { + vertical-align: bottom; +} + +.status { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.main-links { + display: flex; + flex-direction: row; + justify-content: space-around; +} + +.main-links img { + vertical-align: middle; +} + +.rain { + width: 100%; + min-height: 10%; + background-image: url('/static/img/rain.gif'); + background-repeat: repeat; + + display: flex; + justify-content: end; + align-items: end; +} + +.rain p { + padding: 0 32px; + font-family: cursive, serif; +} + +.rain img { + vertical-align: bottom; +} + +.projects { + display: flex; + flex-direction: column; + gap: 8px; +} + +.project { + padding-top: 16px; + display: flex; + flex-direction: row; + gap: 8px; +} + +.project .icon-wrapper { + display: flex; + justify-content: center; + align-items: center; +} + +.icon-wrapper img { + width: 256px; +} + +.project .summary { + display: flex; + flex-direction: column; + justify-content: space-between; +} + +.summary .title { + display: flex; + flex-direction: row; + gap: 16px; +} + +.title .year { + font-size: 10px; +} + +.project .screenshots { + display: flex; + flex-direction: row; + gap: 8px; +} + +.screenshots a:hover { + background: unset; + color: unset +} + +.screenshots img { + vertical-align: bottom; + width: 128px; +} + +.links { + display: flex; + flex-direction: row; + gap: 8px; + align-items: center; +} + +.projects>.project { + border-top: 1px solid black; +} + +.projects>.project:first-child { + border-top: none; +} + +@media only screen and (max-width: 1400px) { + main { + width: 70%; + } +} + +@media only screen and (max-width: 1200px) { + main { + width: 80%; + } +} + +@media only screen and (max-width: 1000px) { + main { + width: unset; + } + + .project { + flex-direction: column; + } + + .screenshots { + justify-content: center; + } +}
\ No newline at end of file diff --git a/status/index.php b/status/index.php new file mode 100644 index 0000000..13d5405 --- /dev/null +++ b/status/index.php @@ -0,0 +1,52 @@ +<?php +include_once $_SERVER['DOCUMENT_ROOT'] . '/lib/time.php'; +$db = new PDO("sqlite:{$_SERVER['DOCUMENT_ROOT']}/database.db"); + +if (isset($_GET['id']) && !empty(trim($_GET['id']))) { + $stmt = $db->prepare('SELECT * FROM statuses WHERE id = ?'); + $stmt->execute([$_GET['id']]); + + $status = $stmt->fetch(PDO::FETCH_ASSOC) ?: null; +} else { + $stmt = $db->query('SELECT id, title, posted_at FROM statuses ORDER BY posted_at DESC'); + $statuses = $stmt->fetchAll(PDO::FETCH_ASSOC); +} +?> +<!DOCTYPE html> +<html> + +<head> + <title>statuses - ilt.su</title> + <meta name="description" content="my statuses."> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> + <link rel="stylesheet" href="/static/style.css"> + <link rel="shortcut icon" href="favicon.ico" type="image/x-icon"> + <meta name="robots" content="noindex, nofollow"> +</head> + +<body> + <main> + <p><a href="/">ilt.su</a> - <a href="/status/">statuses</a></p> + <?php if (isset($status)): ?> + <h1><?= $status['title'] ?? '<i>No title.</i>' ?></h1> + <div> + <?= $status['contents'] ?? '<i>No contents.</i>' ?> + </div> + <p><i>Posted <?= format_timestamp(time() - strtotime($status['posted_at'])) ?> ago</i></p> + <?php endif; ?> + + <?php if (isset($statuses)): ?> + <h1>Statuses</h1> + <ul> + <?php foreach ($statuses as $s): ?> + <li><a href="/status/?id=<?= $s['id'] ?>"><?= $s['title'] ?></a> + <i><?= format_timestamp(time() - strtotime($s['posted_at'])) ?> + ago</i> + </li> + <?php endforeach; ?> + </ul> + <?php endif; ?> + </main> +</body> + +</html>
\ No newline at end of file diff --git a/status/post.php b/status/post.php new file mode 100644 index 0000000..064d86f --- /dev/null +++ b/status/post.php @@ -0,0 +1,84 @@ +<?php +include_once $_SERVER['DOCUMENT_ROOT'] . '/lib/time.php'; + +function str_safe(string $s, int|null $max_length, bool $remove_new_lines = true): string +{ + $output = $s; + + if ($remove_new_lines) { + $output = str_replace(PHP_EOL, "", $output); + } + + $output = htmlspecialchars($output); + $output = strip_tags($output); + + if ($max_length) { + $output = substr($output, 0, $max_length); + } + + $output = trim($output); + + return $output; +} + +$db = new PDO("sqlite:{$_SERVER['DOCUMENT_ROOT']}/database.db"); + +if ($_SERVER['REQUEST_METHOD'] == 'POST') { + $title = str_safe($_POST['title'], 500, true) ?: null; + $contents = str_safe($_POST['contents'], null, false) ?: null; + + $db->prepare('INSERT INTO statuses(title, contents) VALUES (?, ?)') + ->execute([$title, $contents]); + + $id = $db->lastInsertId(); + + header("Location: /status/?id=$id"); + exit; +} + +if (isset($_GET['id']) && !empty(trim($_GET['id']))) { + $stmt = $db->prepare('SELECT * FROM statuses WHERE id = ?'); + $stmt->execute([$_GET['id']]); + + $status = $stmt->fetch(PDO::FETCH_ASSOC) ?: null; +} else { + $stmt = $db->query('SELECT id, title, posted_at FROM statuses ORDER BY posted_at DESC'); + $statuses = $stmt->fetchAll(PDO::FETCH_ASSOC); +} +?> +<!DOCTYPE html> +<html> + +<head> + <title>new status - ilt.su</title> + <meta name="description" content="my statuses."> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> + <link rel="stylesheet" href="/static/style.css"> + <link rel="shortcut icon" href="favicon.ico" type="image/x-icon"> + <meta name="robots" content="noindex, nofollow"> +</head> + +<body> + <main> + <p><a href="/">ilt.su</a> - <a href="/status/">statuses</a></p> + <h1>post a new status</h1> + <form action="/status/post.php" method="post"> + <table> + <tr> + <th>title:</th> + <td><input type="text" name="title" required></td> + </tr> + <tr> + <th>contents:</th> + <td><textarea name="contents" placeholder="Can be empty"></textarea></td> + </tr> + <tr> + <th></th> + <td><button type="submit">post</button></td> + </tr> + </table> + </form> + </main> +</body> + +</html>
\ No newline at end of file |
