summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorilotterytea <iltsu@alright.party>2025-06-13 02:47:14 +0500
committerilotterytea <iltsu@alright.party>2025-06-13 02:47:14 +0500
commit03607513ee46ef2fbd89bcfd89092ab4cc11b679 (patch)
tree97a37af44b662e8c15de6731e85c9aee6ce84cac
parent6140ce63a3516406db54a3e9abfd5b96a3fdd166 (diff)
feat: index page
-rw-r--r--public/index.php288
-rw-r--r--public/static/favicon.icobin0 -> 1150 bytes
-rw-r--r--public/static/img/logo.pngbin0 -> 2642 bytes
3 files changed, 288 insertions, 0 deletions
diff --git a/public/index.php b/public/index.php
new file mode 100644
index 0000000..0187f5b
--- /dev/null
+++ b/public/index.php
@@ -0,0 +1,288 @@
+<html>
+
+<head>
+ <title>TTours</title>
+ <link rel="shortcut icon" href="/static/favicon.ico" type="image/x-icon">
+</head>
+
+<style>
+ * {
+ margin: 0;
+ padding: 0;
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 24px;
+ }
+
+ h1 {
+ font-size: 32px;
+ }
+
+ a {
+ color: black;
+ }
+
+ a:hover {
+ color: white;
+ background: black;
+ text-decoration: line-through;
+ }
+
+ .navbar a {
+ font-size: 8px;
+ }
+
+ .container {
+ width: 100%;
+ min-height: 100vh;
+ display: flex;
+ justify-content: center;
+ }
+
+ .wrapper {
+ display: flex;
+ flex-direction: column;
+ padding: 16px;
+ gap: 16px;
+ width: 70%;
+ }
+
+ .navbar {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ gap: 8px;
+ }
+
+ .content {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+ flex-grow: 1;
+ }
+
+ .content-body {
+ display: flex;
+ flex-direction: row;
+ gap: 8px;
+ flex-grow: 1;
+ }
+
+ #search-box {
+ padding: 4px;
+ }
+
+ .messages {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+ }
+
+ .message-list {
+ height: 256px;
+ display: flex;
+ flex-direction: column;
+ overflow-y: scroll;
+ border: 1px solid gray;
+ border-radius: 2px;
+ flex-grow: 1;
+ }
+
+ .message-list:has(.message) {
+ background: #101010;
+ }
+
+ .message {
+ display: flex;
+ flex-direction: row;
+ gap: 4px;
+ padding: 8px;
+ background: linear-gradient(0deg, #202020, #303030);
+ color: #fff;
+ }
+
+ .message-list>button:nth-child(even) .message {
+ background: linear-gradient(0deg, #353535, #454545);
+ border-top: 1px solid #707070;
+ border-bottom: 1px solid #707070;
+ }
+
+ .message:hover {
+ cursor: pointer;
+ background: linear-gradient(0deg, #505050, #606060);
+ }
+
+ .message-list>button:nth-child(even) .message:hover {
+ background: linear-gradient(0deg, #606060, #656565);
+ }
+
+ button:has(.message) {
+ border: none;
+ background: none;
+ }
+
+ .screenshot {
+ display: flex;
+ flex-grow: 1;
+ flex-direction: column;
+ gap: 8px;
+ padding: 8px;
+ align-items: center;
+ }
+
+ .screenshot img {
+ border: 1px solid gray;
+ border-radius: 2px;
+ }
+</style>
+
+<body>
+ <div class="container">
+ <div class="wrapper">
+ <noscript>Please enable JavaScript!</noscript>
+ <section class="navbar">
+ <img src="/static/img/logo.png" alt="">
+ <h2>TTours</h2>
+ <p style="font-size:8px;">by <a href="https://ilotterytea.kz">ilotterytea</a></p>
+ </section>
+ <section class="content">
+ <div>
+ <h1>Screenshot Twitch messages</h1>
+ <p>like your Pikaso bot <a href="https://bot.ilotterytea.kz">(included in ilotterytea's bot btw)</a>
+ </p>
+ </div>
+
+ <div class="content-body">
+ <div class="messages">
+ <input type="text" id="search-box" placeholder="Enter channel name..." onkeyup="search(event)">
+ <div class="message-list" id="messages" style="display: none">
+ </div>
+ </div>
+
+ <div class="screenshot" id="screenshot-wrapper" style="display: none;">
+ </div>
+ </div>
+ </section>
+ </div>
+ </div>
+</body>
+
+<script>
+ let searchBox = document.getElementById('search-box');
+ searchBox.value = '';
+ let generationLock = false;
+
+ let searchTimeout = null;
+ function search(e) {
+ clearTimeout(searchTimeout);
+ searchTimeout = setTimeout(function () {
+ sendSearchRequest();
+ }, 500);
+ }
+
+ function sendSearchRequest() {
+ const messages = document.getElementById('messages');
+ const channelLogin = searchBox.value.trim();
+
+ if (channelLogin.length == 0) {
+ messages.innerHTML = '';
+ messages.style.display = 'none';
+ return;
+ }
+
+ fetch(`https://recent-messages.robotty.de/api/v2/recent-messages/${channelLogin}?hide_moderation_messages=true&clearchat_to_notice=true`)
+ .then((r) => r.json())
+ .then((json) => {
+ messages.style.display = 'flex';
+ if (json.messages.length == 0) {
+ console.log('xd');
+ messages.innerHTML = '<p>Not found!</p>';
+ return;
+ }
+
+ let messagesHTML = '';
+
+ for (const ircMessage of json.messages) {
+ const parts = ircMessage.split(' ');
+
+ // searching message ID
+ let tags = parts[0];
+
+ if (tags.startsWith('@')) {
+ tags = tags.substring(1);
+ }
+
+ const tagParts = tags.split(';');
+ let messageId = '';
+ let colorHex = '#fff';
+
+ for (const tag of tagParts) {
+ const parts = tag.split('=');
+
+ if (parts[0] == 'id') {
+ messageId = parts[1];
+ } else if (parts[0] == 'color') {
+ colorHex = parts[1];
+ }
+ }
+
+ if (messageId.length == 0) {
+ continue;
+ }
+
+ // searching username
+ let username = parts[1].split('!')[0];
+ if (username.startsWith(':')) {
+ username = username.substring(1);
+ }
+
+ // searching message
+ let message = parts.slice(4).join(' ');
+ if (message.startsWith(':')) {
+ message = message.substring(1);
+ }
+
+ messagesHTML += `
+ <button onclick="generateScreenshot('${messageId}', '${channelLogin}')">
+ <p class="message">
+ <span style="color: ${colorHex}">${username}</span>:
+ ${message}
+ </p>
+ </button>
+ `;
+ }
+
+ messages.innerHTML = messagesHTML;
+ messages.scrollTo(0, messages.scrollHeight);
+ })
+ .catch((err) => console.error(err));
+ }
+
+ function generateScreenshot(messageId, channelLogin) {
+ if (generationLock) {
+ return;
+ }
+
+ generationLock = true;
+
+ const wrapper = document.getElementById('screenshot-wrapper');
+
+ wrapper.style.display = 'flex';
+
+ fetch(`/generate.php?message_id=${messageId}&channel_login=${channelLogin}&base64=true`)
+ .then((r) => r.text())
+ .then((t) => {
+ wrapper.innerHTML = `
+ <img src="${t}" alt="screenshot" id="screenshot">
+ ${wrapper.innerHTML}
+ `;
+ generationLock = false;
+ })
+ .catch((err) => {
+ wrapper.style.display = 'none';
+ console.error(err);
+ generationLock = false;
+ });
+ }
+</script>
+
+</html> \ No newline at end of file
diff --git a/public/static/favicon.ico b/public/static/favicon.ico
new file mode 100644
index 0000000..49e2595
--- /dev/null
+++ b/public/static/favicon.ico
Binary files differ
diff --git a/public/static/img/logo.png b/public/static/img/logo.png
new file mode 100644
index 0000000..d6eaf3b
--- /dev/null
+++ b/public/static/img/logo.png
Binary files differ