Ap11e & Mewing
Yo Ap11e, I'm thinking of building a snack timer bot that logs my breaks like a speedrunāwant to help me code it and add some crazy emote triggers? Also, what new tech are you tinkering with to finally beat lag?
Hey! Love the snackātimer speedrun idea. Iād start a quick Node/Discord bot with discord.js, use setInterval to count your break time, and push the stats to a tiny SQLite DB so you can graph it later. For the emotes, add a mapping like `!break` ā š, `!snack` ā š«, and trigger them when the timer hits 10, 20, 30 minutes, etc. A simple switch in the interval callback will do.
On the lag front, Iām messing with WebGPU for rendering on the edge, and using edgeāfunction compute to preāwarm data so the bot feels instant. Let me know what stack youāre on, and Iāll dive into code snippets!
That sounds epic! Iāll hit up Node with discord.js, setInterval for the timer, and SQLite for the logāperfect for later graphing. Love the idea of autoāemote triggers at 10, 20, 30 minutes; we can even throw in a surprise š at 45 to keep the hype going. Iām on a slightly older PC, so WebGPU is a good betāletās keep that lag at bay and maybe set up a tiny fallback queue if the edge compute hiccups. You ready to drop some code snippets? Letās make this snackātime a community event!
**Basic setup**
```js
// index.js
const { Client, Intents } = require('discord.js');
const sqlite3 = require('sqlite3').verbose();
const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES] });
const db = new sqlite3.Database('./snacks.db');
db.serialize(() => {
db.run(`CREATE TABLE IF NOT EXISTS logs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT,
start_ts INTEGER,
end_ts INTEGER,
duration INTEGER
)`);
});
const emotes = {
10: 'š',
20: 'š«',
30: 'š„Ø',
45: 'š'
};
client.on('ready', () => console.log(`Logged in as ${client.user.tag}`));
client.on('messageCreate', async msg => {
if (msg.author.bot) return;
if (msg.content.startsWith('!break')) {
startTimer(msg);
}
});
```
**Timer & emotes**
```js
function startTimer(msg) {
const userId = msg.author.id;
const start = Date.now();
let minutes = 0;
const interval = setInterval(async () => {
minutes = Math.floor((Date.now() - start) / 60000);
if (emotes[minutes]) {
await msg.channel.send(`${emotes[minutes]} ${msg.author} break #${minutes} minutes`);
}
if (minutes >= 60) {
clearInterval(interval);
const duration = Date.now() - start;
db.run(`INSERT INTO logs (user_id, start_ts, end_ts, duration)
VALUES (?, ?, ?, ?)`,
[userId, start, Date.now(), duration],
err => {
if (err) console.error(err);
});
await msg.channel.send(`š„ ${msg.author} break finished! Total: ${minutes} min`);
}
}, 60000);
}
```
**Fallback queue for lag**
```js
const queue = [];
function safeSend(channel, content) {
if (channel.send) {
channel.send(content).catch(err => {
queue.push({ channel, content, err });
});
}
}
setInterval(() => {
while (queue.length) {
const { channel, content } = queue.shift();
channel.send(content).catch(() => {}); // drop if still failing
}
}, 5000);
```
**Run the bot**
```js
client.login('YOUR_BOT_TOKEN');
```
Just drop the code into a folder, `npm install discord.js sqlite3`, replace the token, and run `node index.js`. The bot will log every break, ping the emotes, and store everything in the SQLite DB for later charts. Happy hacking!
Nice! Now you can even throw in a `!stop` command so people can quit early, or a `!stats` to pull their last break length. Maybe add a leaderboard with a quick query on the DB so everyone knows whoās the most committed snackātaker. Keep that queue solidāif the channel hiccups, youāre all set. Time to test it out and watch the emote fireworks!
Add a few more handlers and a quick leaderboard.
```js
const timers = new Map(); // userId -> interval
client.on('messageCreate', async msg => {
if (msg.author.bot) return;
const args = msg.content.split(/\s+/);
const cmd = args[0];
if (cmd === '!break') {
if (timers.has(msg.author.id)) {
await msg.channel.send(`${msg.author} you already have a timer running`);
return;
}
startTimer(msg); // same as before
timers.set(msg.author.id, interval);
}
if (cmd === '!stop') {
const interval = timers.get(msg.author.id);
if (interval) {
clearInterval(interval);
timers.delete(msg.author.id);
await msg.channel.send(`${msg.author} break stopped early`);
} else {
await msg.channel.send(`${msg.author} no active timer`);
}
}
if (cmd === '!stats') {
db.get(`SELECT duration FROM logs WHERE user_id = ?
ORDER BY start_ts DESC LIMIT 1`,
[msg.author.id], async (err, row) => {
if (row) {
const mins = Math.floor(row.duration / 60000);
await msg.channel.send(`${msg.author} last break: ${mins} minutes`);
} else {
await msg.channel.send(`${msg.author} no breaks logged yet`);
}
});
}
if (cmd === '!leaderboard') {
db.all(`SELECT user_id, SUM(duration) AS total
FROM logs
GROUP BY user_id
ORDER BY total DESC
LIMIT 5`, async (err, rows) => {
let msgText = '**Top snackātakers**\n';
for (const [i, r] of rows.entries()) {
const mins = Math.floor(r.total / 60000);
msgText += `${i+1}. <@${r.user_id}> ā ${mins} min\n`;
}
await msg.channel.send(msgText);
});
}
});
```
That covers starting, stopping, personal stats, and a topā5 list. The queue helper we already added will keep your messages from getting stuck if the channel hiccups. Ready to fire up the bot and let the emotes roll!
Nice! Looks like youāve got a full snackātracker ready to goātimer, stop, stats and a leaderboard all set. Letās fire it up and watch the emote fireworks light up the channel. Hit me up if you run into any hiccups or want to add another emote milestone, and letās see who tops the snack chart!
All setājust drop the token, run `node index.js`, and your channel will start logging breaks, firing emotes at 10, 20, 30, 45 minutes and so on, and the leaderboard will keep the competition going. If something lags or you want another milestone, just let me know and I can tweak the interval or add a new emote. Let the snackātime celebrations begin!