Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ We give you a shareable URL and we'll randomly pick your side; the next person g

Anyone else who opens the link is a spectator.

Players can react with any emoji using the built-in emoji picker.

## Links

- Production: https://tinychess.bitchimfabulo.us
Expand Down
5 changes: 0 additions & 5 deletions internal/handlers/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,6 @@ func (h *Handler) HandleReact(w http.ResponseWriter, r *http.Request) {
return
}

if !isAllowedEmoji(body.Emoji) {
WriteJSON(w, http.StatusOK, map[string]any{"ok": false, "error": "unsupported emoji"})
return
}

canReact, wait := g.CanReact(body.Sender)
if !canReact {
WriteJSON(w, http.StatusOK, map[string]any{"ok": false, "error": fmt.Sprintf("cooldown %ds", wait)})
Expand Down
14 changes: 0 additions & 14 deletions internal/handlers/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,3 @@ func parseSquare(s string) chess.Square {
}
return chess.Square(rank*8 + file)
}

// isAllowedEmoji checks if an emoji is in the allowed list
func isAllowedEmoji(emoji string) bool {
allowed := map[string]struct{}{
"👍": {}, "👎": {}, "❤️": {}, "😠": {}, "😢": {}, "🎉": {}, "👏": {},
"😂": {}, "🤣": {}, "😎": {}, "🤔": {}, "😏": {}, "🙃": {}, "😴": {}, "🫡": {}, "🤯": {}, "🤡": {},
"♟️": {}, "♞": {}, "♝": {}, "♜": {}, "♛": {}, "♚": {}, "⏱️": {}, "🏳️": {}, "🔄": {}, "🏆": {},
"🔥": {}, "💀": {}, "🩸": {}, "⚡": {}, "🚀": {}, "🕳️": {}, "🎯": {}, "💥": {}, "🧠": {},
"🍿": {}, "☕": {}, "🐢": {}, "🐇": {}, "🤝": {}, "🤬": {},
"🪦": {}, "🐌": {}, "🎭": {}, "🐙": {}, "🦄": {}, "🐒": {},
}
_, ok := allowed[emoji]
return ok
}
106 changes: 25 additions & 81 deletions internal/templates/game.html
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,12 @@
}

.wrap {
max-width: 1000px;
max-width: 640px;
margin: 0 auto;
padding: 16px;
display: grid;
grid-template-columns: 1fr 320px;
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
}

Expand Down Expand Up @@ -172,6 +173,7 @@
border: 1px solid #2a3345;
border-radius: 12px;
padding: 12px;
width: 100%;
}

.btn {
Expand Down Expand Up @@ -278,12 +280,6 @@
border-radius: 4px;
}

.reactions {
display: flex;
gap: 6px;
flex-wrap: wrap;
}

.react {
font-size: 18px;
background: transparent;
Expand Down Expand Up @@ -350,11 +346,6 @@
}
}

@media (max-width: 860px) {
.wrap {
grid-template-columns: 1fr;
}
}
</style>
</head>

Expand Down Expand Up @@ -409,7 +400,6 @@
</header>

<div class="wrap">
<div class="board" id="board" aria-label="Chess board"></div>
<div class="panel">
<div class="row">
<strong>Game:</strong> <span id="gameid" class="mono"></span>
Expand All @@ -429,7 +419,7 @@

<div class="rx" id="rx"></div>
<div class="row">
<div class="reactions" id="reactbar" aria-label="Reactions"></div>
<button class="react" id="reactbtn" title="Send reaction">😀</button>
</div>
<p style="margin-top: 10px; opacity: 0.8">
Tip: Click one square, then another to move. Promotions auto-queen.
Expand All @@ -443,7 +433,11 @@
<pre id="pgn" style="white-space: pre-wrap"></pre>
</details>
</div>
<div class="board" id="board" aria-label="Chess board"></div>
</div>
<dialog id="emojiDialog">
<emoji-picker id="emojiPicker"></emoji-picker>
</dialog>
<footer>
Built with Go & vanilla JS — with ❤️ by Dusty and his traumatized 🤖
<div class="version">
Expand All @@ -462,6 +456,10 @@
data-domain="tinychess.bitchimfabulo.us"
src="https://plausible.io/js/script.outbound-links.js"
></script>
<script
type="module"
src="https://cdn.jsdelivr.net/npm/emoji-picker-element@^1/index.js"
></script>
<script>
(function () {
const START_FEN =
Expand All @@ -486,7 +484,9 @@
const capWhiteEl = document.getElementById("cap_by_white");
const capBlackEl = document.getElementById("cap_by_black");
const rxEl = document.getElementById("rx");
const reactBar = document.getElementById("reactbar");
const reactBtn = document.getElementById("reactbtn");
const emojiDialog = document.getElementById("emojiDialog");
const emojiPicker = document.getElementById("emojiPicker");
gameIdEl.textContent = gameId || "(none)";

// Orientation (default white; updated from server message)
Expand Down Expand Up @@ -562,70 +562,15 @@
let lastMoveSquares = []; // [from, to]

// Reactions
const EMOJIS = [
"👍",
"👎",
"❤️",
"😠",
"😢",
"🎉",
"👏",
"😂",
"🤣",
"😎",
"🤔",
"😏",
"🙃",
"😴",
"🫡",
"🤯",
"🤡",
"♟️",
"♞",
"♝",
"♜",
"♛",
"♚",
"⏱️",
"🏳️",
"🔄",
"🏆",
"🔥",
"💀",
"🩸",
"⚡",
"🚀",
"🕳️",
"🎯",
"💥",
"🧠",
"🍿",
"☕",
"🐢",
"🐇",
"🤝",
"🤬",
"🪦",
"🐌",
"🎭",
"🐙",
"🦄",
"🐒",
];
const COOLDOWN_MS = 5000;
let lastReact = 0;
function buildReactBar() {
if (!reactBar) return;
reactBar.innerHTML = "";
EMOJIS.forEach(function (e) {
var b = document.createElement("button");
b.className = "react";
b.textContent = e;
b.title = "Send reaction";
b.addEventListener("click", function () {
sendReaction(e, b);
});
reactBar.appendChild(b);
if (reactBtn && emojiDialog && emojiPicker) {
reactBtn.addEventListener("click", function () {
emojiDialog.showModal();
});
emojiPicker.addEventListener("emoji-click", function (ev) {
emojiDialog.close();
sendReaction(ev.detail.unicode, reactBtn);
});
}

Expand All @@ -637,7 +582,7 @@
document.body.appendChild(big);
setTimeout(() => big.remove(), 1200);

// Small burst under reactions bar
// Small burst under reactions area
if (rxEl) {
const small = document.createElement("span");
small.textContent = e;
Expand Down Expand Up @@ -693,7 +638,6 @@
}
}

buildReactBar();

// --- board helpers ---
function cellSquare(row, col) {
Expand Down