A feature-rich Discord bot built with TypeScript, Discord.js v14, and Bun runtime. Designed for translation, role management, and server moderation.
| Feature | Description |
|---|---|
| 🌐 Translation | Translate text via slash commands or context menu |
| 🎭 Self-Roles | Interactive role selection panel for members |
| 🗣️ Language Roles | Set target translation language via role buttons |
| 🔗 URL Moderation | Automatic URL detection and removal |
| 🖼️ Avatar Fetcher | Retrieve any user's profile picture by ID |
Parrot-bot/
├── src/
│ ├── commands/
│ │ ├── context/ # Context menu commands
│ │ │ └── translate.ts
│ │ └── slash/ # Slash commands
│ │ ├── langpanel.ts
│ │ ├── ping.ts
│ │ ├── selfroles.ts
│ │ ├── translate.ts
│ │ └── userpfp.ts
│ ├── config/
│ │ └── env.ts # Environment configuration
│ ├── constants/
│ │ ├── languages.ts # Language codes & mappings
│ │ └── roles.ts # Role configuration
│ ├── embeds/
│ │ └── translateEmbed.ts # Translation result embed
│ ├── events/
│ │ ├── interactionCreate.ts
│ │ └── messageCreate.ts
│ ├── handlers/
│ │ ├── langButtonHandler.ts
│ │ └── selfRolesHandler.ts
│ ├── services/
│ │ └── translateService.ts
│ ├── types/
│ │ ├── discord.d.ts # Discord.js type extensions
│ │ └── index.ts # Shared type definitions
│ ├── utils/
│ │ ├── arrays.ts
│ │ └── strings.ts
│ ├── main.ts # Bot entry point
│ └── register.ts # Command registration
├── .env # Environment variables (not committed)
├── .gitignore
├── package.json
├── tsconfig.json
└── README.md
- Bun v1.0 or higher
- Discord Bot Token (Create one here)
- Node.js 18+ (for Discord.js compatibility)
1. Clone the repository
git clone https://github.com/your-username/parrot-bot.git
cd parrot-bot2. Install dependencies
bun install3. Configure environment variables
Create a .env file in the project root:
TOKEN=your_discord_bot_token
CLIENT_ID=your_application_client_id
GUILD_ID=your_development_server_id # Optional: for guild-specific commands4. Register commands
bun run register5. Start the bot
bun run startRun with hot reload:
bun run dev| Command | Description | Permission |
|---|---|---|
/ping |
Check bot latency | Everyone |
/translate |
Translate text to a specified language | Everyone |
/stealpfp |
Get a user's profile picture by ID | Everyone |
/langpanel |
Post language role selection panel | Administrator |
/selfroles |
Post self-role selection panel | Administrator |
| Command | Type | Description |
|---|---|---|
Translate (Target Role) |
Message | Translate selected message based on your language role |
Slash Command:
/translate msg:Hello, how are you? langcode:ja
Context Menu:
- Right-click any message
- Navigate to Apps → Translate (Target Role)
- Translation uses your assigned language role (defaults to English)
Administrators can create a language selection panel:
/langpanel
Users click buttons to set their target translation language. Only one language role is active at a time.
Supported Languages:
- 🇬🇧 English (en)
- 🇹🇭 Thai (th)
- 🇯🇵 Japanese (ja)
- 🇵🇭 Filipino (fil)
- 🇮🇩 Indonesian (id)
- 🇪🇬 Arabic - Egyptian (ar-eg)
- 🇬🇭 Akan (ak)
- 🇬🇭 Ewe (ee)
- 🇬🇭 Ga (gaa)
- 🇬🇭 Dagbani (dag)
Administrators can create a role selection panel:
/selfroles
- Users select roles from the dropdown menu
- Press Submit to apply selected roles
- Press Reset to clear selection
- Developer role is auto-assigned when submitting
Create a new file in src/commands/slash/:
import { SlashCommandBuilder } from "discord.js";
import type { Command } from "../../types";
export const command: Command = {
data: new SlashCommandBuilder()
.setName("example")
.setDescription("An example command"),
async execute(interaction) {
await interaction.reply("Hello from example command!");
},
};Create a new file in src/commands/context/:
import {
ApplicationCommandType,
ContextMenuCommandBuilder,
MessageFlags,
} from "discord.js";
import type { MessageContextMenuCommandInteraction } from "discord.js";
import type { Command } from "../../types";
export const command: Command<MessageContextMenuCommandInteraction> = {
data: new ContextMenuCommandBuilder()
.setName("Example Action")
.setType(ApplicationCommandType.Message),
async execute(interaction) {
const message = interaction.targetMessage;
await interaction.reply({
content: `Message content: ${message.content}`,
flags: MessageFlags.Ephemeral,
});
},
};Register the new commands with Discord:
bun run registerThen restart the bot:
bun run start| Script | Description |
|---|---|
bun run start |
Start the bot |
bun run dev |
Start with hot reload |
bun run register |
Register commands to Discord |
bun run test |
Run tests with Vitest |
bun run lint |
Type-check with TypeScript |
| Variable | Required | Description |
|---|---|---|
TOKEN |
✅ | Discord bot token |
CLIENT_ID |
✅ | Discord application ID |
GUILD_ID |
❌ | Guild ID for dev commands (instant updates) |
Edit src/constants/roles.ts to customize:
EXCLUDED_ROLE_NAMES- Roles excluded from self-role selectionDEVELOPER_ROLE_NAME- Auto-assigned developer role name
Edit src/constants/languages.ts to:
- Add/remove supported languages in
LANG_CODES - Map language codes to Google Translate codes in
TRANSLATE_TARGET
- Ensure
bun run registercompleted successfully - Check bot has
applications.commandsscope - Wait up to 1 hour for global commands (instant for guild commands)
Ensure the bot role has:
Manage Roles- For role assignment featuresSend Messages- For responding to commandsManage Messages- For URL moderation
- Google Translate API may rate-limit frequent requests
- Check network connectivity
- Verify the language code is valid
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m "Add: amazing feature") - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Discord.js - Discord API wrapper
- Bun - JavaScript runtime
- Google Translate - Translation service

