Discord bot for managing Arma unit recruitment ads with a 14-day cooldown, in-place edit/delete, and clean embed posts.
/advertiseslash command opens a 5-field modal (unit name, op times, era(s), important info, Discord invite)- Posts a tidy embed alongside an
@user is recruiting for **Unit Name**message + the invite, so Discord still auto-embeds the unit's server preview - 14-day cooldown between fresh posts
- Edit and Delete buttons on every confirmation reply (no need to re-run the command)
- Modal pre-fills with previous values when editing
- Cooldown messages use Discord's relative timestamp format (renders as "in 3 days", localised per user)
- Discord invite validation: accepts
discord.gg/x,https://discord.gg/x, ordiscord.com/invite/x, normalised to canonical form - Editing during cooldown preserves the original timestamp (you can't game the cooldown by bumping)
- After cooldown expires, posting deletes the old message and posts fresh, bumping the ad to the bottom of the channel
- Configurable embed colour via
EMBED_COLORenv var - All ads stored in
ads.json(auto-created)
You need Node.js 18 or newer. Get it from nodejs.org if you don't have it.
- Download the source zip from the repo (green Code button → Download ZIP) or grab a tagged release zip.
- Extract it.
- Open a terminal in the extracted folder.
cp .env.example .envand fill inTOKENandAD_CHANNEL_ID.npm installnpm run buildnpm start
git clone https://github.com/IsoBones/Wedgetail.git
cd Wedgetail
cp .env.example .env # then edit .env
npm install
npm run build
npm startnpm install
npm run devUsing AMP's Generic Module / Node.js App Runner:
- Create a new instance using the Node.js App Runner template.
- Upload the bot files (or extract the zip into the instance's working directory).
- Set the start command to
node dist/bot.js. - In the instance's environment variables, set
TOKENandAD_CHANNEL_ID(and optionallyEMBED_COLOR). You can use.envinstead if you'd rather. - From the AMP console, run
npm installthennpm run buildonce. - Start the instance.
| Variable | Required | Default | Description |
|---|---|---|---|
TOKEN |
yes | — | Discord bot token from the Developer Portal |
AD_CHANNEL_ID |
yes | — | Channel where ads are posted |
EMBED_COLOR |
no | #14B8A6 |
6-digit hex colour for the embed |
CLIENT_ID |
no | — | Reserved for future use |
GUILD_ID |
no | — | Reserved for future use |
The bot needs the following permissions in the ad channel:
- Send Messages
- Embed Links
- Read Message History
- Use Application Commands
(No Manage Messages needed — the bot only edits and deletes its own posts.)
wedgetail/
├── src/
│ ├── bot.ts # Entry point, client, login, signal handling
│ ├── config.ts # Env loading + theme
│ ├── logger.ts # Console + file logging
│ ├── storage.ts # ads.json persistence (in-memory cache)
│ ├── util.ts # Invite validation + time helpers
│ ├── components.ts # Modal, embed, and button builders
│ └── handlers.ts # Interaction handlers + router
├── dist/ # Compiled JS (generated by `npm run build`)
├── ads.json # User ad data (auto-generated)
├── console_output.txt # Bot logs (auto-generated)
├── .env # Your credentials (DON'T COMMIT)
├── .env.example
├── package.json
└── tsconfig.json
First post: User runs /advertise → modal opens → submits → bot posts message + embed in ad channel and stores the message ID. Cooldown starts.
During cooldown: Re-running /advertise shows an ephemeral notice with the unlock time (relative timestamp) plus Edit/Delete buttons. Editing updates the same message in-place; the cooldown timer is preserved. Deleting removes the message and resets the cooldown.
After cooldown expires: Running /advertise opens the modal pre-filled with previous values. Submitting deletes the old message and posts a fresh one at the bottom of the channel. Cooldown resets.
If the ad message gets manually deleted: Bot detects the missing message on next edit/submit and posts a fresh one.
- Stop the bot.
- Pull / re-download the new version (overwrite the source files but keep your
.envandads.json). npm install(in case dependencies changed).npm run buildnpm start
Old ads.json records auto-migrate, so no data loss when upgrading from earlier versions.
Bot won't start: Check TOKEN and AD_CHANNEL_ID are set in .env (or in your environment). The bot exits with a clear error if either is missing.
Commands not showing in Discord: Bot needs the applications.commands scope when invited. After first run, wait a few minutes for Discord to register the global command.
Can't post ads: Verify AD_CHANNEL_ID is correct and the bot has Send Messages + Embed Links permission in that channel.
"Invalid invite" error when submitting: The invite needs to be in one of these forms: discord.gg/code, https://discord.gg/code, discord.com/invite/code. Vanity URLs and custom domains aren't supported.
GPL-3.0 — see LICENSE.