diff options
| author | ilotterytea <iltsu@alright.party> | 2025-06-13 02:47:14 +0500 |
|---|---|---|
| committer | ilotterytea <iltsu@alright.party> | 2025-06-13 02:47:14 +0500 |
| commit | 03607513ee46ef2fbd89bcfd89092ab4cc11b679 (patch) | |
| tree | 97a37af44b662e8c15de6731e85c9aee6ce84cac | |
| parent | 6140ce63a3516406db54a3e9abfd5b96a3fdd166 (diff) | |
feat: index page
| -rw-r--r-- | public/index.php | 288 | ||||
| -rw-r--r-- | public/static/favicon.ico | bin | 0 -> 1150 bytes | |||
| -rw-r--r-- | public/static/img/logo.png | bin | 0 -> 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 Binary files differnew file mode 100644 index 0000000..49e2595 --- /dev/null +++ b/public/static/favicon.ico diff --git a/public/static/img/logo.png b/public/static/img/logo.png Binary files differnew file mode 100644 index 0000000..d6eaf3b --- /dev/null +++ b/public/static/img/logo.png |
