<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Ajitesh Gogula]]></title><description><![CDATA[This is the Hashnode page for the writings of Ajitesh Gogula]]></description><link>https://ajiteshgo.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/6a23eeae11c3ac872a91bd59/af803b3c-2f9d-456a-a6d7-6b36935ecabd.png</url><title>Ajitesh Gogula</title><link>https://ajiteshgo.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 20 Sep 2026 17:38:40 GMT</lastBuildDate><atom:link href="https://ajiteshgo.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Building Arlo — A Custom Discord Bot for a Writers Community]]></title><description><![CDATA[When making a community server on Social Media platform like Discord, we would want a moderation application which can look after day to day duties, there are a wide variety of applications which can ]]></description><link>https://ajiteshgo.hashnode.dev/building-arlo-a-custom-discord-bot-for-a-writers-community</link><guid isPermaLink="true">https://ajiteshgo.hashnode.dev/building-arlo-a-custom-discord-bot-for-a-writers-community</guid><category><![CDATA[discord]]></category><category><![CDATA[Discord bot]]></category><category><![CDATA[discord.js]]></category><dc:creator><![CDATA[Ajitesh Gogula]]></dc:creator><pubDate>Sat, 06 Jun 2026 13:23:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6a23eeae11c3ac872a91bd59/da7a0354-c4e3-4bbc-88f5-74f1d4483d34.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When making a community server on Social Media platform like Discord, we would want a moderation application which can look after day to day duties, there are a wide variety of applications which can help with different functionality and many with unused features which creates a overwhelming feeling while surfing through their commands and other features.</p>
<p>Facing a similar problem, I have decided to start my programming journey by building a discord application for the Writer Community – <strong>Nova Archives</strong>, <strong>Arlo</strong>, which can manage day to day moderation duties on the server and other community related commands tirelessly throughout the server.</p>
<p><strong>Arlo</strong> is purely built on <strong>JavaScript</strong>, being able to react to messages when called out, to banning members on the will of the moderators. It’s a widely customizable bot, with action logging features.</p>
<h2><strong>Decisions During Development</strong></h2>
<p>Every project has moments where you could have gone one way and chose another. These are the ones that actually shaped how Arlo works.</p>
<h4><strong>Splitting the Files</strong></h4>
<p>The first version of <strong>Arlo</strong> was a single <code>index.js</code> file that did everything — message creation logic, slash commands logic, bot startup, all of it in one place. It worked perfectly, but every time I needed to find something specific to edit a small typo or to implement a small change I was scrolling through hundreds of lines looking for the right block. The moment I added the report command and the availability toggle in the same week, the file became genuinely difficult to navigate.</p>
<p>I restructured it into an events folder with separate files — <code>messageaction.js</code> for everything Arlo responds to in messages, <code>slashcom.js</code> for every slash command and <code>buttonhandlers.js</code> for button logic. <code>index.js</code> now just starts the bot and loads everything else. The actual code didn’t change at all. But the moment I needed to debug something, I knew exactly which file to open. That’s the whole point of structure — not performance, not best practice for its own sake, just not wasting your own time later.</p>
<h4><strong>Why report commands opens a thread automatically under the Embed</strong></h4>
<p>The basic version of a report command sends an embed to the respective staff channel and that’s it. Mods see it, handle it, move on. I built it that way first.</p>
<p>The problem is that “handle it” has no paper trail. <em>Who responded? What was decided? When was it closed?</em> A channel full of lifeless report embeds with no conversation attached to them is just noise — you can’t tell at a glance which ones were resolved and which ones were ignored.</p>
<p>Making Arlo open a thread on every report embed changed the whole workflow. The discussion about the reporting of a user happens inside the opened thread, the resolution gets posted inside the thread and later closing the thread signals completion. Six months from now if someone asks “what happened with that report about X,” the answer is findable because the thread exists. I didn’t plan this upfront — I noticed the problem after about a week of using the simpler version and it just took one afternoon to fix. But it’s probably the decision that made the most practical difference to how the server actually runs.</p>
<h4><strong>The availability toggle removing mod roles instead of just adding one</strong></h4>
<p>When I built the “<strong>Shelved Editor</strong>” toggle button that lets staff mark themselves as unavailable — my first instinct was to just add a role. Press button, get role, everyone can see you’re unavailable. Simple.</p>
<p>Then I thought about what actually happens when a mod is marked unavailable but still has their mod role visible. When the moderator roles are pinged by other moderators or Arlo when opening threads, the moderator gets pinged anyway if they still had their role on their profile. So I made the toggle remove the active mod roles when it adds the unavailable one, and restore them after it’s toggled off. Now the member list tells the truth — if you don’t see a mod role, that person genuinely isn’t available right now. The role isn’t cosmetic anymore, it’s functional. One extra line of code, completely different meaning.</p>
<h2>What's On The Desk</h2>
<h3>💬 Message Interactions</h3>
<table>
<thead>
<tr>
<th>Trigger</th>
<th>What Arlo Does</th>
<th>Comment</th>
</tr>
</thead>
<tbody><tr>
<td>Any message containing <code>Arlo</code></td>
<td>Reacts with 👀</td>
<td>Global Interaction</td>
</tr>
<tr>
<td><code>Arlo, pin this</code></td>
<td>Reacts with 📌 and pins the message containing the command</td>
<td>Staff Only Interaction</td>
</tr>
<tr>
<td><code>Arlo, pin it</code> (as a reply)</td>
<td>Reacts with 📌 and pins the replied message</td>
<td>Staff Only Interaction</td>
</tr>
<tr>
<td><code>Arlo, start knitting</code></td>
<td>Reacts with 🧶 and starts a thread on the message</td>
<td>Staff Only Interaction</td>
</tr>
<tr>
<td><code>Arlo, Update Guide</code></td>
<td>Sends the Guide Embed in Guide Channel</td>
<td>Staff Only Interaction</td>
</tr>
<tr>
<td><code>Arlo, Update Staff</code></td>
<td>Sends the Guide Embed in a Staff Channel</td>
<td>Staff Only Interaction</td>
</tr>
<tr>
<td><code>Arlo, Reload the Gun</code></td>
<td>Sends the Prompt Roulette Embed Set in Prompt Roulette Channel</td>
<td>Staff Only Interaction</td>
</tr>
</tbody></table>
<blockquote>
<p>Message interactions marked as <strong>Staff Only Interaction</strong> require one of the following roles: <code>✦ Quill Master</code>, <code>Senior Editor</code>, <code>Copy Editor</code>, <code>Proofreader</code>, <code>Event Curator</code>, or <code>Archivist</code>.</p>
</blockquote>
<h3>⚡ Slash Commands</h3>
<table>
<thead>
<tr>
<th>Command</th>
<th>Description</th>
<th>Comment</th>
</tr>
</thead>
<tbody><tr>
<td><code>/report</code> <code>[user] [reason] [message-link] [evidence]</code></td>
<td>Report a member to the moderation team. Sends an embed to the staff channel and confirms with an ephemeral reply to the user.</td>
<td>Global Command</td>
</tr>
<tr>
<td><code>/warn</code> <code>[user] [reason] [message-link]</code></td>
<td>Warn a member in the community. Sends an embed to the staff channel and confirms with an ephemeral reply to the moderator.</td>
<td>Staff Only Command</td>
</tr>
<tr>
<td><code>/mute [user] [reason] [message-link]</code> <code>[duration]</code></td>
<td>Mute / Timeout a member in the community. Sends an embed to the staff channel and confirms with an ephemeral reply to the moderator.</td>
<td>Staff Only Command</td>
</tr>
<tr>
<td><code>/ban</code> <code>[user] [reason] [message-link]</code></td>
<td>Ban a member in the community. Sends an embed to the staff channel and confirms with an ephemeral reply to the moderator.</td>
<td>Staff Only Command</td>
</tr>
<tr>
<td><code>/speak-embed</code> <code>[title] [description] [thumbnail] [image] [url]</code></td>
<td>Member can send an embed with custom Title, Description, Thumbnail, Image and Url. The bot will make a note of who triggered the embed.</td>
<td>Staff Only Command</td>
</tr>
<tr>
<td><code>/ping</code></td>
<td>Check the Latency of the Bot and the API.</td>
<td>Staff Only Command</td>
</tr>
</tbody></table>
<blockquote>
<p>Slash commands marked as <strong>Staff Only Command</strong> require one of the following roles: <code>✦ Quill Master</code>, <code>Senior Editor</code>, <code>Copy Editor</code>, <code>Proofreader</code>, <code>Event Curator</code>, or <code>Archivist</code>.</p>
</blockquote>
<h3>🤝🏻 Passive Interactions</h3>
<table>
<thead>
<tr>
<th>Trigger</th>
<th>Description</th>
<th>Comment</th>
</tr>
</thead>
<tbody><tr>
<td>Any message in <code>#🖋️・introduction</code></td>
<td>Arlo reacts with 👋🏻</td>
<td>Global Interaction</td>
</tr>
<tr>
<td>Any message in <code>#🎉・milestones</code></td>
<td>Arlo reacts with 👏🏻 and 🎉</td>
<td>Global Interaction</td>
</tr>
<tr>
<td><code>User Information</code></td>
<td>Check the User Information such as User ID, Usertag and Avatar. Triggered through Context Menu.</td>
<td>Staff Only Interaction</td>
</tr>
<tr>
<td><code>Message Information</code></td>
<td>Check the Message Information such as Message ID, Message Author tag and Message Link. Triggered through Context Menu.</td>
<td>Staff Only Interaction</td>
</tr>
</tbody></table>
<blockquote>
<p>Interactions marked as <strong>Staff Only Interactions</strong> require one of the following roles: <code>✦ Quill Master</code>, <code>Senior Editor</code>, <code>Copy Editor</code>, <code>Proofreader</code>, <code>Event Curator</code>, or <code>Archivist</code>.</p>
</blockquote>
<h2>What's Next on the Board</h2>
<table>
<thead>
<tr>
<th>Feature</th>
<th>Description</th>
<th>Status</th>
</tr>
</thead>
<tbody><tr>
<td>Edited Message Logs</td>
<td>Logs the Edited Messages in a staff channel</td>
<td>Not Started</td>
</tr>
<tr>
<td>Deleted Message Logs</td>
<td>Logs the Deleted Messages in a staff channel</td>
<td>Not Started</td>
</tr>
<tr>
<td><code>/help</code></td>
<td>Helps the users navigate (select menu) to through categories and understand importance of each thing in the server</td>
<td>Not Started</td>
</tr>
<tr>
<td><code>/wordgoal [target]</code></td>
<td>User sets their daily word goal. Bot stores it and they can check in against it later with <code>/wordcheck</code></td>
<td>Not Started</td>
</tr>
<tr>
<td><code>/wordcheck</code></td>
<td>Users can check their set daily word goal any time</td>
<td>Not Started</td>
</tr>
<tr>
<td><code>/wip [title] [status]</code></td>
<td>User registers their current WIP with a status tag like <em>drafting / revising / shelved</em>.</td>
<td>Not Started</td>
</tr>
<tr>
<td><code>/wipboard</code></td>
<td>Bot can display a server-wide <code>/wipboard</code> showing everyone's active projects</td>
<td>Not Started</td>
</tr>
<tr>
<td><code>/sprint [minutes]</code></td>
<td>Starts a personal sprint timer just for the user who called it. Bot DMs them when time is up</td>
<td>Not Started</td>
</tr>
<tr>
<td><code>/shelf-add [title] [author]</code></td>
<td>Adds a book to the user's personal reading shelf tracked by the bot</td>
<td>Not Started</td>
</tr>
<tr>
<td><code>/shelf-show [user]</code></td>
<td>Lets anyone peek at someone else's shelf</td>
<td>Not Started</td>
</tr>
<tr>
<td><code>/recommend [genre]</code></td>
<td>Bot pulls a random book recommendation from a curated list</td>
<td>Not Started</td>
</tr>
<tr>
<td><code>/quietroom [hours]</code></td>
<td>Toggles a Do Not Ping status for a set number of hours</td>
<td>Not Started</td>
</tr>
<tr>
<td>Unrelated URL Deletion</td>
<td>Only few links like <code>ao3</code>, <code>Wattpad</code> are allowed but YouTube and Instagram such are instantly deleted</td>
<td>Not Started</td>
</tr>
<tr>
<td><code>/lock [channel]</code></td>
<td>Locks the channel used in, from member messages during emergencies</td>
<td>Not Started</td>
</tr>
<tr>
<td><code>/unlock [channel]</code></td>
<td>Reverses the Lock</td>
<td>Not Started</td>
</tr>
<tr>
<td><code>/purge [num]</code></td>
<td>Bulk deletes X messages in a channel, useful for spam cleanup</td>
<td>Not Started</td>
</tr>
<tr>
<td><code>/note [user]</code></td>
<td>Adds a private staff note to a user that only mods can see</td>
<td>Not Started</td>
</tr>
</tbody></table>
<h2>What Arlo Taught Me</h2>
<p>The biggest thing this project taught me was that Discord's interaction model punishes you immediately for not understanding async — everything that felt like a bot problem was actually a timing problem.</p>
<blockquote>
<p>Arlo isn't finished. Honestly, I'm not sure it ever will be — and I think that's the point. Nova Archives needed a librarian. I needed a project that would fight back. We found each other.</p>
</blockquote>
]]></content:encoded></item></channel></rss>