{"id":20022158,"url":"https://github.com/CuteNikki/DiscordBot","last_synced_at":"2025-05-05T01:31:16.828Z","repository":{"id":236986811,"uuid":"793566904","full_name":"CuteNikki/DiscordBot","owner":"CuteNikki","description":"An advanced and feature-rich TypeScript Discord bot.","archived":false,"fork":false,"pushed_at":"2025-04-22T10:01:21.000Z","size":2889,"stargazers_count":5,"open_issues_count":6,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-22T11:22:12.793Z","etag":null,"topics":["advanced","bot","cluster","discord","discord-bot","discordbot","feature","i18next","mongodb","multi-purpose","pino","shard","sharded","template","translations","v14"],"latest_commit_sha":null,"homepage":"https://yanera.xyz","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CuteNikki.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-04-29T13:15:14.000Z","updated_at":"2025-03-22T01:51:18.000Z","dependencies_parsed_at":"2025-03-13T10:19:56.397Z","dependency_job_id":"d4001fd4-b107-4b9f-9ba7-523927dcd95c","html_url":"https://github.com/CuteNikki/DiscordBot","commit_stats":null,"previous_names":["cutenikki/discord-bot","cutenikki/discordbot"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CuteNikki%2FDiscordBot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CuteNikki%2FDiscordBot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CuteNikki%2FDiscordBot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CuteNikki%2FDiscordBot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CuteNikki","download_url":"https://codeload.github.com/CuteNikki/DiscordBot/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252423086,"owners_count":21745543,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["advanced","bot","cluster","discord","discord-bot","discordbot","feature","i18next","mongodb","multi-purpose","pino","shard","sharded","template","translations","v14"],"created_at":"2024-11-13T08:39:22.606Z","updated_at":"2025-05-05T01:31:11.816Z","avatar_url":"https://github.com/CuteNikki.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"###### - A WORK IN PROGRESS -\n\n# DiscordJS V14 Bot written in TypeScript\n\nThis discord bot was built with custom classes, \u003ca href=\"https://www.i18next.com/\"\u003ei18next\u003c/a\u003e for translations, \u003ca href=\"https://getpino.io/\"\u003ePino\u003c/a\u003e as logger and \u003ca href=\"https://www.mongodb.com/\"\u003eMongoDB\u003c/a\u003e as database.\u003c/p\u003e\n\n[\u003cimg src=\"https://img.shields.io/badge/pino-%23687634.svg?style=for-the-badge\u0026logo=pino\u0026logoColor=white\" alt=\"pino\" /\u003e](https://getpino.io) [\u003cimg src=\"https://img.shields.io/badge/mongodb-%2347A248.svg?style=for-the-badge\u0026logo=mongodb\u0026logoColor=white\" alt=\"mongodb\" /\u003e](https://mongodb.com) [\u003cimg src=\"https://img.shields.io/badge/i18next-%2326A69A.svg?style=for-the-badge\u0026logo=i18next\u0026logoColor=white\" alt=\"i18next\" /\u003e](https://i18next.com) [\u003cimg src=\"https://img.shields.io/badge/discordjs_v14\u0026#46;16\u0026#46;3-%235865F2.svg?style=for-the-badge\u0026logo=discord\u0026logoColor=white\" alt=\"discord.js\" /\u003e](https://discord.js.org)\u003cbr /\u003e [\u003cimg src=\"https://img.shields.io/github/stars/CuteNikki/discord-bot?style=for-the-badge\u0026color=%23d4a72a\" alt=\"Repository Stars\" /\u003e](https://github.com/CuteNikki/discord-bot/stargazers) [\u003cimg src=\"https://img.shields.io/github/issues/CuteNikki/discord-bot?style=for-the-badge\u0026color=%2371d42a\" alt=\"Repository Issues\" /\u003e](https://github.com/CuteNikki/discord-bot/issues) [\u003cimg src=\"https://img.shields.io/github/forks/CuteNikki/discord-bot?style=for-the-badge\u0026color=%232ad48a\" alt=\"Repository Forks\" /\u003e](https://github.com/CuteNikki/discord-bot/forks) [\u003cimg src=\"https://img.shields.io/github/license/cutenikki/discord-bot?style=for-the-badge\u0026color=%232a90d4\" alt=\"License\" /\u003e]()\n\n###### Made with 💖 by \u003ca href=\"https://github.com/CuteNikki/\"\u003eNikki\u003c/a\u003e.\n\n## Table of Contents\n\n- [Run it locally](#run-it-locally)\n- [How to create new commands, events, buttons and more](#how-to-create-new-commands-events-buttons-and-more)\n  - [Creating a slash command](#creating-a-slash-command)\n  - [Creating an event](#creating-an-event)\n  - [Creating a button](#creating-a-button)\n  - [Translating commands](#translating-commands)\n  - [Translating messages](#translating-messages)\n- [Contributing](#contributing)\n- [Show your support](#show-your-support)\n- [License](#license)\n- [TO-DO](#to-do)\n\n## Run it locally\n\nAll it takes is just 6-7 simple steps.\n\n1. Clone the repository.\n\n```bash\ngit clone https://github.com/CuteNikki/discord-bot.git\n```\n\n2. Navigate into the project directory.\n\n```bash\ncd discord-bot\n```\n\n3. Install all the dependencies.\n\n```bash\nbun install\n```\n\n4. Set up your config file.\n\n```bash\n# copy example.config.json and rename to config.json\n# or use this command if you are on Linux.\ncp example.config.json config.json\n# fill in all values (more details in the config file).\n```\n\n5. Deploy the slash commands.\n\n```bash\nbun run deploy\n# you may also use the /register-commands slash command on discord,\n# once the commands have been registered using the deploy command.\n```\n\n6. Run the bot using a script.\n\n```bash\n# Run in development:\nbun run dev\n\n# or compile:\nbun run build\n# and run:\nbun run start\n\n# You may also use --debug for more detailed console logs!\n```\n\n7. (optional) Configure more settings using the developer command.\n\n```bash\n# This is used for giving Supporter Badge on support server boost.\n/developer-configuration support-guild-id set \u003cguildId\u003e\n\n# This is used for the /support command.\n/developer-configuration support-invite-url set \u003curl\u003e\n\n# This is used for the /invite command.\n/developer-configuration bot-invite-url set \u003curl\u003e\n\n# This is used to manage badges of a user.\n/developer-configuration badges add/remove/show \u003cuser\u003e [badge]\n\n# This is used to manage bans.\n/developer-configuration bans add/remove/list [user]\n```\n\n## How to create new commands, events, buttons and more\n\n### Creating a slash command\n\nThis displays the use of i18next, the command class, and all its properties including autocomplete.\n\n```ts\nimport {\n  Colors, // All of default discord colors.\n  EmbedBuilder,\n  PermissionFlagsBits,\n  SlashCommandBuilder,\n  InteractionContextType,\n  ApplicationIntegrationType,\n  type ColorResolvable\n} from 'discord.js';\nimport { t } from 'i18next';\n\nimport { Command, ModuleType } from 'classes/command';\n\nimport { logger } from 'utils/logger';\n\nexport default new Command({\n  // The module this command belongs to.\n  // It categorizes commands in the commands list.\n  // It disables this command if the module is disabled.\n  module: ModuleType.General,\n  // 1 second cooldown between command uses.\n  cooldown: 1_000,\n  // Only developers can use this command.\n  isDeveloperOnly: false,\n  // The bot needs to have this permission to be able to use this command.\n  botPermissions: ['SendMessages'],\n  // The slash command data.\n  data: new SlashCommandBuilder()\n    .setName('preview-color')\n    .setDescription('Sends an embed with a color to preview')\n    // Allowing the command to be used in guilds, DMs and private channels.\n    .setIntegrationTypes(ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall)\n    // Allowing the command to be used in guilds, DMs and private channels.\n    .setContexts(InteractionContextType.BotDM, InteractionContextType.Guild, InteractionContextType.PrivateChannel)\n    // By default only users with the manage messages permission can see and use this command.\n    // UNLESS it was changed in the server settings under the integrations tab (per user or role).\n    .setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages)\n    // Adding options\n    .addStringOption(\n      (option) =\u003e\n        option\n          .setName('color')\n          .setDescription('The color to preview')\n          .setRequired(true) // Makes the option required.\n          .setAutocomplete(true) // Enable autocompletion.\n    ),\n  // On input, the autocomplete function is called.\n  async autocomplete({ interaction, client }) {\n    // This gets us whatever the user has typed.\n    const input = interaction.options.getFocused();\n\n    const colors = [\n      { name: 'white', value: Colors.White.toString(16) },\n      { name: 'aqua', value: Colors.Aqua.toString(16) },\n      { name: 'green', value: Colors.Green.toString(16) },\n      { name: 'blue', value: Colors.Blue.toString(16) },\n      { name: 'yellow', value: Colors.Yellow.toString(16) },\n      { name: 'purple', value: Colors.Purple.toString(16) },\n      { name: 'luminous-vivid-pink', value: Colors.LuminousVividPink.toString(16) },\n      { name: 'fuchsia', value: Colors.Fuchsia.toString(16) },\n      { name: 'gold', value: Colors.Gold.toString(16) },\n      { name: 'orange', value: Colors.Orange.toString(16) },\n      { name: 'red', value: Colors.Red.toString(16) },\n      { name: 'grey', value: Colors.Grey.toString(16) },\n      { name: 'navy', value: Colors.Navy.toString(16) },\n      { name: 'dark-aqua', value: Colors.DarkAqua.toString(16) },\n      { name: 'dark-green', value: Colors.DarkGreen.toString(16) },\n      { name: 'dark-blue', value: Colors.DarkBlue.toString(16) },\n      { name: 'dark-purple', value: Colors.DarkPurple.toString(16) },\n      { name: 'dark-vivid-pink', value: Colors.DarkVividPink.toString(16) },\n      { name: 'dark-gold', value: Colors.DarkGold.toString(16) },\n      { name: 'dark-orange', value: Colors.DarkOrange.toString(16) },\n      { name: 'dark-red', value: Colors.DarkRed.toString(16) },\n      { name: 'dark-grey', value: Colors.DarkGrey.toString(16) },\n      { name: 'darker-grey', value: Colors.DarkerGrey.toString(16) },\n      { name: 'light-grey', value: Colors.LightGrey.toString(16) },\n      { name: 'dark-navy', value: Colors.DarkNavy.toString(16) },\n      { name: 'blurple', value: Colors.Blurple.toString(16) },\n      { name: 'greyple', value: Colors.Greyple.toString(16) },\n      { name: 'dark-but-not-black', value: Colors.DarkButNotBlack.toString(16) },\n      { name: 'not-quite-black', value: Colors.NotQuiteBlack.toString(16) }\n    ];\n\n    // If the input is empty, return all colors but limit to 25!\n    // Discord API only allows for a max of 25 choices.\n    if (!input.length) {\n      await interaction.respond(colors.slice(0, 25));\n      return;\n    }\n\n    await interaction.respond(\n      colors\n        // Filter the colors to only respond with the ones that match the input.\n        .filter((color) =\u003e color.name.toLowerCase().includes(input.toLowerCase()))\n        // Again, making sure we only ever return max of 25 results.\n        .slice(0, 25)\n    );\n  },\n  // On command, the execute function is called.\n  // order of interaction, client and lng does not matter.\n  async execute({ interaction, client, lng }) {\n    // get a guilds language:\n    // import { getGuildLanguage } from 'db/language';\n    // const guildLng = await getGuildLanguage(guildId);\n\n    // get a different users language:\n    // import { getUserLanguage } from 'db/language';\n    // const otherLng = await getUserLanguage(userId);\n\n    // get the color the user provided\n    const color = interaction.options.getString('color', true);\n\n    // Autocomplete allows you to give the user a list to choose from,\n    // but they will still be able to type in whatever they want!\n    // it's a must to check if they actually provided a valid color.\n\n    try {\n      // Send the embed with the color preview if the color is valid.\n      await interaction.reply({\n        embeds: [\n          new EmbedBuilder()\n            // We get a type error here without the casting.\n            .setColor(color as ColorResolvable)\n            .setDescription(t('preview-color.preview', { lng, color }))\n        ]\n      });\n    } catch (err) {\n      // This block runs if an invalid color is provided.\n\n      logger.debug({ err }, 'Error while previewing color');\n\n      // In case something else went wrong and the reply was actually sent, edit it.\n      if (!interaction.replied) {\n        await interaction.reply({ content: t('preview-color.invalid', { lng }), ephemeral: true });\n      } else {\n        await interaction.editReply({ content: t('preview-color.invalid', { lng }) });\n      }\n    }\n  }\n});\n```\n\n\n#### Creating an event\n\n```ts\nimport { Events } from 'discord.js';\n\nimport { Event } from 'classes/event';\n\nimport { logger } from 'utils/logger';\n\nexport default new Event({\n  // the name of the event\n  name: Events.ClientReady,\n  // only run this once, won't run again even if another ready event is emitted\n  once: true,\n  // it is important to always have client first\n  // and other events properties after that\n  execute(client, readyClient) {\n    logger.info(`Logged in as ${readyClient.user.username}#${readyClient.user.discriminator}`);\n  }\n});\n```\n\n### Creating a button\n\n```ts\nimport { Button } from 'classes/button';\n\nexport default new Button({\n  // The module this button belongs to.\n  module: ModuleType.General,\n  // The custom identifier of the button.\n  customId: 'ping',\n  // If the button was received by a command, only the command sender can use this button.\n  isAuthorOnly: true,\n  // If true then a button with the custom id of \"abc-ping-abc\" would still\n  // trigger this button because the custom id includes \"ping\".\n  // This is useful to pass an id or other information to the button.\n  isCustomIdIncluded: false, // In this case, we don't need it.\n  // The permissions required by a member to use this button.\n  permissions: ['SendMessages'], // Ignored in DMs.\n  // Permissions the bot needs to execute this function.\n  botPermissions: ['SendMessages'], // Ignored in DMs.\n  // On button click, the execute function is called.\n  async execute({ interaction, client, lng }) {\n    await interaction.channel?.send({ content: 'pong!' }); // Send a response in the channel.\n  }\n});\n```\n\n### Translating commands\n\n`src/structure/locales/{lng}-commands.json`\n\n```json\n{\n  \"preview-color\": {\n    \"name\": \"preview-color\",\n    \"description\": \"Sends an embed with a color to preview\",\n    \"options\": [\n      {\n        \"name\": \"color\",\n        \"description\": \"The color to preview\"\n      }\n    ]\n  }\n}\n```\n\n### Translating messages\n\n`src/structure/locales/{lng}-messages.json`\n\n```json\n{\n  \"preview-color\": {\n    \"preview\": \"Heres a preview of the color {{color}}!\",\n    \"invalid\": \"The color you provided is invalid!\"\n  }\n}\n```\n\n## Contributing\n\nContributions, issues and feature requests are welcome.\nFeel free to check \u003ca href=\"https://github.com/CuteNikki/discord-bot/issues\"\u003eissues page\u003c/a\u003e if you want to contribute.\n\n## Show your support\n\nPlease ⭐️ this repository if this project helped you!\n\n## License\n\nCopyright © 2024 \u003ca href=\"https://github.com/CuteNikki\"\u003eCuteNikki\u003c/a\u003e.\nThis project is \u003ca href=\"https://github.com/CuteNikki/discord-bot/blob/main/LICENSE\"\u003eMIT\u003c/a\u003e licensed.\n\n## TO-DO\n\n- [x] utility module (more features might be added)\n- [x] developer module (more features might be added)\n- [ ] fun module (more features will be added)\n  - [x] game command\n    - [ ] 2048 (maybe?)\n    - [ ] Lights Out (maybe?)\n- [ ] config\n  - [x] reaction roles (already implemented)\n    - [ ] fully customizable message\n  - [ ] word chain game (next word needs to start with the last letter of the previous word)\n  - [ ] economy\n    - [x] config\n    - [x] balance\n    - [x] deposit\n    - [x] withdraw\n    - [x] pay\n    - [x] inventory\n    - [x] daily\n    - [x] transfer\n    - [x] marry\n    - [x] divorce\n    - [x] leaderboard\n    - [x] rob\n    - [x] work\n    - [x] bet\n    - [x] coinflip\n    - [x] profile\n    - [x] profile context\n    - [ ] shop\n  - [ ] confession\n    - [ ] config command\n    - [ ] confess\n  - [ ] suggestions\n    - [ ] config command\n    - [ ] suggest\n  - [ ] level config\n    - [x] text and voice levelling is fully implemented with ignored \u0026 enabled channels, announcements, reward and multiplier roles\n    - [x] levelup announcement\n      - [ ] fully customizable message\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCuteNikki%2FDiscordBot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FCuteNikki%2FDiscordBot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCuteNikki%2FDiscordBot/lists"}