Full Code of IgorKowalczyk/majobot for AI

master 7a451fb2b950 cached
492 files
2.4 MB
658.9k tokens
396 symbols
1 requests
Download .txt
Showing preview only (2,633K chars total). Download the full file or copy to clipboard to get everything.
Repository: IgorKowalczyk/majobot
Branch: master
Commit: 7a451fb2b950
Files: 492
Total size: 2.4 MB

Directory structure:
gitextract_ftazrc3x/

├── .dockerignore
├── .github/
│   ├── codeowners
│   ├── renovate.json
│   └── workflows/
│       ├── codeql-analysis.yml
│       ├── format-check.yml
│       └── lint.yml
├── .gitignore
├── .npmrc
├── .prettierignore
├── CONTRIBUTING.md
├── README.md
├── apps/
│   ├── bot/
│   │   ├── .env.example
│   │   ├── .prettierignore
│   │   ├── Dockerfile
│   │   ├── README.md
│   │   ├── commands/
│   │   │   ├── Fun/
│   │   │   │   ├── 8ball.ts
│   │   │   │   ├── advice.ts
│   │   │   │   ├── anime.ts
│   │   │   │   ├── cat.ts
│   │   │   │   ├── comic.ts
│   │   │   │   ├── dice.ts
│   │   │   │   ├── flip.ts
│   │   │   │   ├── iq.ts
│   │   │   │   ├── joke.ts
│   │   │   │   ├── letmegpt.ts
│   │   │   │   ├── lmgtfy.ts
│   │   │   │   ├── meme.ts
│   │   │   │   ├── rate.ts
│   │   │   │   ├── ship.ts
│   │   │   │   └── why.ts
│   │   │   ├── General/
│   │   │   │   ├── about.ts
│   │   │   │   ├── contact.ts
│   │   │   │   ├── dashboard.ts
│   │   │   │   ├── donate.ts
│   │   │   │   ├── help.ts
│   │   │   │   ├── invite.ts
│   │   │   │   ├── opensource.ts
│   │   │   │   ├── permissions.ts
│   │   │   │   ├── ping.ts
│   │   │   │   ├── servers.ts
│   │   │   │   ├── suggestion.ts
│   │   │   │   └── uptime.ts
│   │   │   ├── Giveaway/
│   │   │   │   └── giveaway.ts
│   │   │   ├── Image/
│   │   │   │   ├── achievement.ts
│   │   │   │   ├── ai.ts
│   │   │   │   ├── bangladesh.ts
│   │   │   │   ├── change-my-mind.ts
│   │   │   │   ├── dog-say.ts
│   │   │   │   ├── fbi.ts
│   │   │   │   ├── flag.ts
│   │   │   │   ├── galaxy-note.ts
│   │   │   │   ├── image.ts
│   │   │   │   ├── iq-graph.ts
│   │   │   │   ├── jail.ts
│   │   │   │   ├── note.ts
│   │   │   │   ├── ph-comment.ts
│   │   │   │   ├── sonic-says.ts
│   │   │   │   ├── trash.ts
│   │   │   │   ├── trigger.ts
│   │   │   │   ├── type-c.ts
│   │   │   │   └── yt-comment.ts
│   │   │   ├── Levels/
│   │   │   │   ├── leaderboard.ts
│   │   │   │   ├── rank.ts
│   │   │   │   ├── reset-xp.ts
│   │   │   │   └── xp-settings.ts
│   │   │   ├── Moderation/
│   │   │   │   ├── automod.ts
│   │   │   │   ├── emoji.ts
│   │   │   │   ├── leave.ts
│   │   │   │   ├── logs.ts
│   │   │   │   ├── member.ts
│   │   │   │   ├── role.ts
│   │   │   │   ├── slowmode.ts
│   │   │   │   ├── statistics.ts
│   │   │   │   ├── warn.ts
│   │   │   │   └── welcome.ts
│   │   │   ├── Reputation/
│   │   │   │   └── rep.ts
│   │   │   └── Utility/
│   │   │       ├── ascii.ts
│   │   │       ├── base64.ts
│   │   │       ├── color.ts
│   │   │       ├── minecraft.ts
│   │   │       ├── qrcode.ts
│   │   │       └── translate.ts
│   │   ├── events/
│   │   │   ├── client/
│   │   │   │   ├── GuildCreate.ts
│   │   │   │   ├── GuildDelete.ts
│   │   │   │   └── clientReady.ts
│   │   │   └── guild/
│   │   │       ├── channelCreate.ts
│   │   │       ├── channelDelete.ts
│   │   │       ├── channelPinsUpdate.ts
│   │   │       ├── channelUpdate.ts
│   │   │       ├── emojiCreate.ts
│   │   │       ├── emojiDelete.ts
│   │   │       ├── emojiUpdate.ts
│   │   │       ├── guildBanAdd.ts
│   │   │       ├── guildBanRemove.ts
│   │   │       ├── guildMemberAdd.ts
│   │   │       ├── guildMemberRemove.ts
│   │   │       ├── guildUpdate.ts
│   │   │       ├── interactionCreate.ts
│   │   │       ├── inviteCreate.ts
│   │   │       ├── inviteDelete.ts
│   │   │       ├── messageBulkDelete.ts
│   │   │       ├── messageCreate.ts
│   │   │       ├── messageDelete.ts
│   │   │       ├── messageUpdate.ts
│   │   │       ├── roleCreate.ts
│   │   │       ├── roleDelete.ts
│   │   │       ├── roleUpdate.ts
│   │   │       ├── stickerCreate.ts
│   │   │       ├── stickerDelete.ts
│   │   │       └── stickerUpdate.ts
│   │   ├── index.ts
│   │   ├── modals/
│   │   │   └── suggestion.ts
│   │   ├── package.json
│   │   ├── tsconfig.json
│   │   └── util/
│   │       ├── giveaway/
│   │       │   ├── core.ts
│   │       │   ├── endGiveaway.ts
│   │       │   ├── findGiveaways.ts
│   │       │   ├── pauseGiveaway.ts
│   │       │   ├── rerollGiveaway.ts
│   │       │   ├── resumeGiveaway.ts
│   │       │   └── startGiveaway.ts
│   │       ├── images/
│   │       │   ├── createUserGuildCard.ts
│   │       │   └── createXPCard.ts
│   │       ├── loaders/
│   │       │   ├── loadCommands.ts
│   │       │   ├── loadEmojis.ts
│   │       │   ├── loadEvents.ts
│   │       │   ├── loadFonts.ts
│   │       │   └── loadModals.ts
│   │       ├── moderation/
│   │       │   ├── automod/
│   │       │   │   ├── antiBadWords/
│   │       │   │   │   ├── disable.ts
│   │       │   │   │   └── enable.ts
│   │       │   │   ├── antiInvite/
│   │       │   │   │   ├── disable.ts
│   │       │   │   │   └── enable.ts
│   │       │   │   ├── antiLinks/
│   │       │   │   │   ├── disable.ts
│   │       │   │   │   └── enable.ts
│   │       │   │   ├── antiMention/
│   │       │   │   │   ├── disable.ts
│   │       │   │   │   └── enable.ts
│   │       │   │   ├── antiSpam/
│   │       │   │   │   ├── disable.ts
│   │       │   │   │   └── enable.ts
│   │       │   │   ├── index.ts
│   │       │   │   └── settings/
│   │       │   │       └── index.ts
│   │       │   ├── ban.ts
│   │       │   ├── changeMemberNickname.ts
│   │       │   ├── getMemberImages.ts
│   │       │   ├── getMemberInfo.ts
│   │       │   ├── kick.ts
│   │       │   └── unban.ts
│   │       └── types/
│   │           └── Command.ts
│   └── dashboard/
│       ├── .env.example
│       ├── .gitignore
│       ├── .prettierignore
│       ├── README.md
│       ├── app/
│       │   ├── _components/
│       │   │   ├── AddReaction.tsx
│       │   │   ├── BotReplacement.tsx
│       │   │   ├── ExampleChart.tsx
│       │   │   ├── LevelUp.tsx
│       │   │   └── Notifications.tsx
│       │   ├── api/
│       │   │   ├── auth/
│       │   │   │   └── [...nextauth]/
│       │   │   │       └── route.ts
│       │   │   ├── cron/
│       │   │   │   └── cleanup/
│       │   │   │       └── route.ts
│       │   │   ├── invite/
│       │   │   │   ├── [invite]/
│       │   │   │   │   └── route.ts
│       │   │   │   └── route.ts
│       │   │   ├── logs/
│       │   │   │   └── [serverId]/
│       │   │   │       └── route.ts
│       │   │   ├── settings/
│       │   │   │   ├── automod/
│       │   │   │   │   ├── anti-invite/
│       │   │   │   │   │   └── route.ts
│       │   │   │   │   ├── anti-link/
│       │   │   │   │   │   └── route.ts
│       │   │   │   │   ├── anti-mention/
│       │   │   │   │   │   └── route.ts
│       │   │   │   │   └── anti-spam/
│       │   │   │   │       └── route.ts
│       │   │   │   ├── categories/
│       │   │   │   │   └── route.ts
│       │   │   │   ├── change-reputation/
│       │   │   │   │   └── route.ts
│       │   │   │   ├── commands/
│       │   │   │   │   └── route.ts
│       │   │   │   ├── delete-data/
│       │   │   │   │   └── route.ts
│       │   │   │   ├── download/
│       │   │   │   │   └── [id]/
│       │   │   │   │       └── route.ts
│       │   │   │   ├── embed-color/
│       │   │   │   │   └── route.ts
│       │   │   │   ├── messages/
│       │   │   │   │   ├── leave/
│       │   │   │   │   │   └── route.ts
│       │   │   │   │   └── welcome/
│       │   │   │   │       └── route.ts
│       │   │   │   ├── public-dashboard/
│       │   │   │   │   └── route.ts
│       │   │   │   ├── public-vanity/
│       │   │   │   │   └── route.ts
│       │   │   │   ├── reset-user-xp/
│       │   │   │   │   └── route.ts
│       │   │   │   └── update-logs/
│       │   │   │       └── route.ts
│       │   │   ├── user/
│       │   │   │   ├── avatar/
│       │   │   │   │   └── [id]/
│       │   │   │   │       └── route.ts
│       │   │   │   ├── avatar-decoration/
│       │   │   │   │   └── [id]/
│       │   │   │   │       └── route.ts
│       │   │   │   ├── banner/
│       │   │   │   │   └── [id]/
│       │   │   │   │       └── route.ts
│       │   │   │   ├── delete/
│       │   │   │   │   └── route.ts
│       │   │   │   └── download/
│       │   │   │       └── route.ts
│       │   │   └── warns/
│       │   │       └── [serverId]/
│       │   │           └── [warnId]/
│       │   │               └── route.ts
│       │   ├── auth/
│       │   │   ├── error/
│       │   │   │   └── page.tsx
│       │   │   └── login/
│       │   │       └── page.tsx
│       │   ├── commands/
│       │   │   └── page.tsx
│       │   ├── dashboard/
│       │   │   ├── [server]/
│       │   │   │   ├── automod/
│       │   │   │   │   ├── components/
│       │   │   │   │   │   ├── AntiInvite.tsx
│       │   │   │   │   │   ├── AntiLink.tsx
│       │   │   │   │   │   ├── AntiMention.tsx
│       │   │   │   │   │   ├── AntiSpam.tsx
│       │   │   │   │   │   ├── DeleteMessage.tsx
│       │   │   │   │   │   ├── Limit.tsx
│       │   │   │   │   │   ├── LogChannel.tsx
│       │   │   │   │   │   └── TimeoutMember.tsx
│       │   │   │   │   ├── loading.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── dashboard-logs/
│       │   │   │   │   ├── components/
│       │   │   │   │   │   └── Logs.tsx
│       │   │   │   │   ├── loading.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── giveaways/
│       │   │   │   │   ├── components/
│       │   │   │   │   │   └── Giveaways.tsx
│       │   │   │   │   ├── loading.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── layout.tsx
│       │   │   │   ├── leaderboard/
│       │   │   │   │   ├── components/
│       │   │   │   │   │   └── Leaderboard.tsx
│       │   │   │   │   ├── loading.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── loading.tsx
│       │   │   │   ├── logs/
│       │   │   │   │   ├── components/
│       │   │   │   │   │   ├── UpdateLogs.tsx
│       │   │   │   │   │   └── handleLogText.ts
│       │   │   │   │   ├── loading.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── messages/
│       │   │   │   │   ├── components/
│       │   │   │   │   │   └── ChangeCustomMessages.tsx
│       │   │   │   │   ├── loading.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── modules/
│       │   │   │   │   ├── loading.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── page.tsx
│       │   │   │   ├── settings/
│       │   │   │   │   ├── components/
│       │   │   │   │   │   ├── ChangeEmbedColor.tsx
│       │   │   │   │   │   ├── DeleteServerData.tsx
│       │   │   │   │   │   └── PublicDashboard.tsx
│       │   │   │   │   ├── loading.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── statistics/
│       │   │   │   │   ├── components/
│       │   │   │   │   │   └── StatisticCharts.tsx
│       │   │   │   │   ├── loading.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── user/
│       │   │   │   │   ├── [id]/
│       │   │   │   │   │   ├── loading.tsx
│       │   │   │   │   │   └── page.tsx
│       │   │   │   │   └── components/
│       │   │   │   │       ├── ChangeUserReputation.tsx
│       │   │   │   │       └── ResetUserXP.tsx
│       │   │   │   └── warns/
│       │   │   │       ├── components/
│       │   │   │       │   └── Warns.tsx
│       │   │   │       ├── loading.tsx
│       │   │   │       └── page.tsx
│       │   │   ├── loading.tsx
│       │   │   └── page.tsx
│       │   ├── error.tsx
│       │   ├── layout.tsx
│       │   ├── legal/
│       │   │   ├── layout.tsx
│       │   │   ├── privacy-policy/
│       │   │   │   └── page.mdx
│       │   │   └── terms-of-service/
│       │   │       └── page.mdx
│       │   ├── not-found.tsx
│       │   ├── opengraph-image.tsx
│       │   ├── page.tsx
│       │   ├── robots.ts
│       │   ├── server/
│       │   │   └── [server]/
│       │   │       ├── layout.tsx
│       │   │       ├── loading.tsx
│       │   │       └── page.tsx
│       │   ├── sitemap.ts
│       │   └── user/
│       │       ├── components/
│       │       │   └── DeleteUserData.tsx
│       │       └── profile/
│       │           └── page.tsx
│       ├── components/
│       │   ├── CategoryBar.tsx
│       │   ├── DiscordEmojis.tsx
│       │   ├── DiscordLogin.tsx
│       │   ├── Footer.tsx
│       │   ├── Hotjar.tsx
│       │   ├── LoginButton.tsx
│       │   ├── Session.tsx
│       │   ├── TailwindIndicator.tsx
│       │   ├── client/
│       │   │   ├── charts/
│       │   │   │   └── ServerStatsChart.tsx
│       │   │   └── commands/
│       │   │       ├── DiscordCommands.tsx
│       │   │       ├── UpdateCategories.tsx
│       │   │       └── UpdateCommands.tsx
│       │   ├── nav/
│       │   │   ├── GuildMenuDropdown.tsx
│       │   │   ├── ProgressBar.tsx
│       │   │   ├── SideMenuControl.tsx
│       │   │   ├── SideNavigation.tsx
│       │   │   ├── TopNavigation.tsx
│       │   │   ├── UserMenuDropdown.tsx
│       │   │   └── VisibilityContext.tsx
│       │   └── ui/
│       │       ├── Accordion.tsx
│       │       ├── Badge.tsx
│       │       ├── Block.tsx
│       │       ├── Buttons.tsx
│       │       ├── ChannelsSelect.tsx
│       │       ├── Chart.tsx
│       │       ├── Command.tsx
│       │       ├── Dialog.tsx
│       │       ├── Disclosure.tsx
│       │       ├── DropdownMenu.tsx
│       │       ├── Embed.tsx
│       │       ├── GraphCard.tsx
│       │       ├── Headers.tsx
│       │       ├── Icons.tsx
│       │       ├── Image.tsx
│       │       ├── Input.tsx
│       │       ├── Loaders.tsx
│       │       ├── Popover.tsx
│       │       ├── RolesSelect.tsx
│       │       ├── Select.tsx
│       │       ├── Skeletons.tsx
│       │       ├── SparkChart.tsx
│       │       ├── Switch.tsx
│       │       ├── Table.tsx
│       │       ├── TimeSelect.tsx
│       │       ├── Tooltip.tsx
│       │       ├── ViewSelect.tsx
│       │       └── effects/
│       │           ├── AnimatedBeam.tsx
│       │           ├── AnimatedList.tsx
│       │           ├── AnimatedShinyText.tsx
│       │           ├── BorderBeam.tsx
│       │           ├── FadeText.tsx
│       │           ├── FlickeringGrid.tsx
│       │           ├── Globe.tsx
│       │           ├── Meteors.tsx
│       │           ├── NumberTicker.tsx
│       │           ├── Particles.tsx
│       │           ├── Ripple.tsx
│       │           └── WordPullUp.tsx
│       ├── env.ts
│       ├── eslint.config.ts
│       ├── jsconfig.json
│       ├── lib/
│       │   ├── authOptions.ts
│       │   ├── session.ts
│       │   ├── types.ts
│       │   └── utils.ts
│       ├── mdx-components.tsx
│       ├── next.config.ts
│       ├── package.json
│       ├── postcss.config.mjs
│       ├── styles/
│       │   └── globals.css
│       ├── tsconfig.json
│       └── vercel.json
├── docker-compose.yaml
├── eslint.config.ts
├── license.md
├── package.json
├── packages/
│   ├── config/
│   │   ├── .prettierignore
│   │   ├── configs/
│   │   │   ├── bot.ts
│   │   │   ├── dashboard.ts
│   │   │   ├── debugger.ts
│   │   │   ├── global.ts
│   │   │   └── permissions.ts
│   │   ├── index.ts
│   │   ├── package.json
│   │   └── tsconfig.json
│   ├── database/
│   │   ├── .env.example
│   │   ├── .prettierignore
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── prisma/
│   │   │   ├── migrations/
│   │   │   │   ├── 20230516174916_/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516200625_add_auth/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516201206_add_discord_schema/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516202208_save_only_required/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516202300_bigint_for_flags/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516202517_make_email_unique/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516202902_fix_unique/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516210849_add_maps/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516211309_add_verification_token/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516212035_fix_unique_values/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516212254_switch_datatype_nitro/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516212512_add_email_verified/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230521135936_add_suggestions/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230521142039_add_guild_id/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230521143031_add_guild_model/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230521184416_add_guild_logs/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230521185323_fix_guild_logs/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230521221630_add_avatar/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230522210912_link_user_to_logs/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230528212858_add_embed_color/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230529160641_add_ratelimit_for_server_change/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230604182342_add_guild_xp/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230609200921_migrate_to_discord_handles/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230610181051_update_account/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230610195213_update_rows_names/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230716165214_add_guild_joins/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230807093042_add_reputation/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230807100800_fix_user_fields/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230809192933_add_giveaways/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230809193154_change_giveaways_name/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230810131104_add_channel_id/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230810131904_remove_channel_id/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230813164922_add_messages_count/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230829161606_add_xp_settings/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230901110432_add_vanity_urls/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231008115944_add_guild_controlled_commands/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231008120512_fix_commands/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231008120900_add_default_options/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231008143223_update_default_member_permissions/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231008163839_fix_fields/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231008165157_remove_perms_and_created_at/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231008170130_update_command_categories/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231008171003_fix_schema/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231015105007_remove_email_adresses/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231017181219_fix_user_emails/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231018085005_add_automod_rules/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231030220258_add_warning_system/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231030222116_fix_ids/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231030230714_add_created_by_id_to_warnings/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231031083245_add_warn_id/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231117165927_add_last_login_field/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231119203658_remove_enabled_disable_state_from_automod/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231216135714_add_welcome_and_leave_messages/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231216145835_remove_unused_fields/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231218000910_add_titles_and_descriptions_for_custom_messages/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231228221226_add_embed_color_and_enabled_state/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20241209125259_add_better_logs/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20241209132307_add_vanity_update_event/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20241209140053_add_giveaway_events/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20241220180643_add_guild_settings/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20241220180800_change_name_of_guild_logs_settings/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20241220181109_add_type_as_unique/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20241221205356_remove_not_used_log_types/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20241228112527_allow_channel_id_to_be_null/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20241228131412_add_log_update_event/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20241231150633_remove_message_polls/
│   │   │   │   │   └── migration.sql
│   │   │   │   └── migration_lock.toml
│   │   │   └── schema.prisma
│   │   ├── prisma.config.ts
│   │   ├── src/
│   │   │   ├── client.ts
│   │   │   ├── logger.ts
│   │   │   ├── redis/
│   │   │   │   ├── cache.ts
│   │   │   │   └── client.ts
│   │   │   ├── seed.ts
│   │   │   └── types.ts
│   │   └── tsconfig.json
│   ├── typescript-config/
│   │   ├── base.json
│   │   ├── index.ts
│   │   └── package.json
│   └── utils/
│       ├── .prettierignore
│       ├── content/
│       │   ├── advices.json
│       │   └── why.json
│       ├── database/
│       │   ├── index.ts
│       │   ├── logs/
│       │   │   ├── createLog.ts
│       │   │   ├── events.ts
│       │   │   ├── fetchLogs.ts
│       │   │   └── getGuildLogSettings.ts
│       │   ├── moderation/
│       │   │   ├── automod/
│       │   │   │   ├── createDatabaseAutoModRule.ts
│       │   │   │   ├── deleteDatabaseAutoModRule.ts
│       │   │   │   ├── fetchDatabaseAutoModRules.ts
│       │   │   │   ├── index.ts
│       │   │   │   ├── syncDatabaseAutoModRule.ts
│       │   │   │   └── updateDatabaseAutoModRule.ts
│       │   │   └── warn/
│       │   │       ├── clearWarns.ts
│       │   │       ├── listWarns.ts
│       │   │       ├── removeWarn.ts
│       │   │       └── warnUser.ts
│       │   ├── reputation/
│       │   │   ├── checkReputation.ts
│       │   │   ├── giveReputation.ts
│       │   │   ├── setReputation.ts
│       │   │   └── takeReputation.ts
│       │   ├── settings/
│       │   │   └── XPSettings.ts
│       │   ├── user/
│       │   │   └── createUser.ts
│       │   └── xp/
│       │       ├── checkXP.ts
│       │       └── resetXP.ts
│       ├── embeds/
│       │   ├── createErrorEmbed.ts
│       │   └── index.ts
│       ├── functions/
│       │   ├── automod/
│       │   │   ├── createDiscordAutoModRule.ts
│       │   │   ├── deleteDiscordAutoModRule.ts
│       │   │   ├── fetchDiscordAutoModRules.ts
│       │   │   ├── index.ts
│       │   │   ├── types.ts
│       │   │   ├── validateAutoModIgnores.ts
│       │   │   └── validateAutoModRuleActions.ts
│       │   ├── files/
│       │   │   ├── index.ts
│       │   │   └── readDir.ts
│       │   ├── guild/
│       │   │   ├── getGuild.ts
│       │   │   ├── getGuildChannels.ts
│       │   │   ├── getGuildFromMemberGuilds.ts
│       │   │   ├── getGuildPreview.ts
│       │   │   ├── getGuildRoles.ts
│       │   │   ├── getMemberGuilds.ts
│       │   │   ├── index.ts
│       │   │   └── isBotInServer.ts
│       │   ├── user/
│       │   │   ├── getDiscordUser.ts
│       │   │   ├── getFlags.ts
│       │   │   ├── getPermissionNames.ts
│       │   │   ├── index.ts
│       │   │   └── isApiUser.ts
│       │   └── util/
│       │       ├── adjustColor.ts
│       │       ├── capitalize.ts
│       │       ├── fillMissingDates.ts
│       │       ├── flipText.ts
│       │       ├── formatDate.ts
│       │       ├── formatDuration.ts
│       │       ├── formatNumber.ts
│       │       ├── generateDates.ts
│       │       ├── index.ts
│       │       ├── isNumeric.ts
│       │       ├── logger.ts
│       │       ├── percentageBar.ts
│       │       ├── randomness.ts
│       │       ├── shortenText.ts
│       │       ├── splitCamelCase.ts
│       │       └── sumArray.ts
│       ├── images/
│       │   ├── index.ts
│       │   ├── invertColor.ts
│       │   └── linesHelper.ts
│       ├── package.json
│       └── tsconfig.json
├── pnpm-workspace.yaml
├── prettier.config.js
├── tsconfig.json
└── turbo.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .dockerignore
================================================
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/.next
**/.cache
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/charts
**/docker-compose*
**/compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
**/build
**/dist
LICENSE
README.md


================================================
FILE: .github/codeowners
================================================
license.md @igorkowalczyk


================================================
FILE: .github/renovate.json
================================================
{
 "$schema": "https://docs.renovatebot.com/renovate-schema.json",
 "extends": ["github>igorkowalczyk/shared-configs//packages/renovate-config/index.json"],
 "packageRules": [
  {
   "matchFiles": ["/packages/dashboard/**"],
   "labels": ["dependencies", "dashboard"]
  },
  {
   "matchFiles": ["/packages/bot/**"],
   "labels": ["dependencies"]
  },
  {
   "matchPaths": ["+(package.json)"],
   "labels": ["dependencies"]
  }
 ]
}


================================================
FILE: .github/workflows/codeql-analysis.yml
================================================
name: "CodeQL Checks"

on: [push, pull_request]

jobs:
 analyze:
  name: Analyze
  runs-on: ubuntu-latest
  permissions:
   actions: read
   contents: read
   security-events: write
  strategy:
   fail-fast: false
   matrix:
    language: ["javascript-typescript"]
  steps:
   - name: 🧱 Checkout repository
     uses: actions/checkout@v6
   - name: 🚀 Initialize CodeQL
     uses: github/codeql-action/init@v4
     with:
      languages: ${{ matrix.language }}
   - name: 🚀 Perform CodeQL Analysis
     uses: github/codeql-action/analyze@v4
     with:
      category: "/language:${{matrix.language}}"


================================================
FILE: .github/workflows/format-check.yml
================================================
name: Prettier check

on: [push, pull_request]

jobs:
 check:
  timeout-minutes: 15
  name: Format check
  runs-on: ubuntu-latest
  env:
   TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
   TURBO_TEAM: ${{ vars.TURBO_TEAM }}
  strategy:
   fail-fast: false
   matrix:
    node: ["lts/*"]
  steps:
   - name: 🧱 Checkout repository
     uses: actions/checkout@v6
   - name: 🔩 Setup PNPM
     uses: pnpm/action-setup@v4
     with:
      standalone: true
   - name: 🔩 Setup Node ${{ matrix.node }}
     uses: actions/setup-node@v6
     with:
      node-version: ${{ matrix.node }}
      cache: "pnpm"
   - name: 🚀 Install dependencies
     run: pnpm install
   - name: 🚀 Check formatting
     run: "pnpm run format:check"


================================================
FILE: .github/workflows/lint.yml
================================================
name: Lint

on: [push, pull_request]

jobs:
 lint:
  timeout-minutes: 15
  name: ESLint
  runs-on: ubuntu-latest
  env:
   TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
   TURBO_TEAM: ${{ vars.TURBO_TEAM }}
  strategy:
   fail-fast: false
   matrix:
    node: ["lts/*"]
  steps:
   - name: 🧱 Checkout repository
     uses: actions/checkout@v6
   - name: 🔩 Setup PNPM
     uses: pnpm/action-setup@v4
     with:
      standalone: true
   - name: 🔩 Setup Node ${{ matrix.node }}
     uses: actions/setup-node@v6
     with:
      node-version: ${{ matrix.node }}
      cache: "pnpm"
   - name: 🚀 Install dependencies
     run: pnpm install
   - name: 🚀 Run ESLint
     run: pnpm lint


================================================
FILE: .gitignore
================================================
# .gitignore

# Logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Coverage directory used by tools like istanbul
coverage
*.lcov

# Dependency directories and files
node_modules/
jspm_packages/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz
*.zip

# dotenv environment variables file
.env*
!.env.example

# Stores VSCode versions used for testing VSCode extensions
.vscode-test
.vscode

# Next.js build output
.next

# Certificates
*.key
*.cert

# Turborepo & Vercel
.turbo
.vercel

# Prisma
packages/database/prisma/client

================================================
FILE: .npmrc
================================================
public-hoist-pattern[]=*prisma*

================================================
FILE: .prettierignore
================================================
package.json
pnpm-lock.yaml

*/*/package.json
*/*/pnpm-lock.yaml

================================================
FILE: CONTRIBUTING.md
================================================
![Header](https://github.com/IgorKowalczyk/majo.exe/assets/49127376/4df57b45-2900-40e0-bf34-707170fb83bc)

<p align="center">
 <a href="https://majoexe.com/server"><img src="https://img.shields.io/discord/695282860399001640?color=%234552ef&logo=discord&label=Discord&style=flat&logoColor=fff" alt="Discord" /></a>
 <a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/badge/Discord.js-v14-%234552ef?style=flat&logo=npm&logoColor=fff" alt="Discord.js" /></a>
 <a href="https://majoexe.com/"><img src="https://img.shields.io/github/actions/workflow/status/igorkowalczyk/majo.exe/codeql-analysis.yml?branch=master&style=flat&label=CodeQL&logo=github&color=%234552ef" alt="CodeQL Checks" /></a>
 <a href="https://majoexe.com"><img src="https://img.shields.io/github/license/igorkowalczyk/majo.exe?style=flat&;logo=github&label=License&color=%234552ef" alt="GitHub License" /></a>
</p>

<!-- prettier-ignore -->
> [!NOTE]
> If you are reading this, **you are probably interested in contributing to Majo.exe**. **We appreciate your interest** in improving the project and welcome your contributions. To ensure a smooth and productive collaboration, **please review the following guidelines.**

<!-- prettier-ignore-end -->

## 🆕 Submitting Contributions

We know that contributing to a project can be intimidating, especially if you are new to the community. However, we want to assure you that **contributing to Majo.exe is easy and fun**.

We have created a welcoming community that encourages collaboration and supports new contributors. **We are excited to have you on board!** 🙌

### 1. Choose existing issues or create your own 📝

Start by **reviewing the existing issues** to identify areas where your contributions **can make a significant impact**.

If you **have new features, enhancements, or bug fixes in mind**, you can create a **new issue** to propose your contributions. **Please provide comprehensive details to clearly explain your ideas.** This will help the project maintainers and fellow contributors to understand your suggestions and provide valuable feedback.

### 2. Fork the repository 🍴

To initiate your contribution, **fork the primary repository by clicking the "Fork" button.** This creates a copy of the repository in your personal GitHub account. You will use this copy to make and propose changes to the project.

![Forking igorkowalczyk/majo.exe repository on Github](https://github.com/IgorKowalczyk/majo.exe/assets/49127376/dfaedc7f-5a59-4332-b19b-5305d1c78935)

After forking the repository, **clone your forked repository to your local development environment** using the following command:

```bash
git clone https://github.com/your-username/majo.exe.git
cd majo.exe
```

This creates a local copy of your forked repository on your computer in directory `majo.exe`.

> [!NOTE]
> Replace `your-username` with your GitHub username

### 3. Set up the upstream remote ☝️

To keep your forked repository in sync with the primary repository, **set up the upstream remote** using the following command:

```bash
git remote add upstream https://github.com/IgorKowalczyk/majo.exe
git remote -v
```

### 4. Create a new branch 🔗

Before you can start working on your contribution, **create a new branch dedicated to your specific task**:

```bash
git checkout -b my-contribution
```

> [!NOTE]
> Replace `my-contribution` with a descriptive name that clearly identifies the purpose of your branch. Please use lowercase letters and hyphens instead of spaces.

### 5. Make Changes 🔥

Now you can start working on your contribution! Implement your awesome ideas, fix bugs, or add new features. **Be creative and have fun!** Ensure your contributions are well-structured, documented, and aligned with the project's objectives.

**Quick Tip:** To keep your forked repository in sync with the primary repository, **pull the latest changes** from the primary repository before making your contributions:

```bash
git pull upstream main
```

> [!IMPORTANT]
> Remember to test your changes before submitting them! **You can read the [README.md](https://github.com/igorkowalczyk/majo.exe/blob/master/README.md) file for instructions on how to set up the project locally.**

<!-- prettier-ignore -->
> [!NOTE]
> - **Please ensure your code is well-formatted and linted** before submitting your changes.
> - To **format your code**, use the following command: `pnpm run format`
> - To **lint your code**, use the following command: `pnpm run lint:fix`
> - To **build the project**, use the following command: `pnpm run build`

<!-- prettier-ignore-end -->

### 6. Commit Your Changes 📝

Commit your awesome contributions with informative commit messages that clearly explain the purpose of your changes:

```bash
git commit -m "Add a descriptive message here"
```

> [!WARNING]
> Please ensure your commit messages are descriptive and informative. This will help the project maintainers and fellow contributors to better understand your changes.
>
> **Please do not use vague commit messages like `Update README.md` or `Fix bugs`.** Instead, use messages like `Update README.md with instructions on how to set up the project locally` or `Fix bugs related to incorrect variable names`.

### 7. Push Your Changes 🚀

Push your commits to your forked repository on GitHub:

```bash
git push origin my-contribution
```

> [!NOTE]
> Replace `my-contribution` with the name of your branch.

### 8. Create a Pull Request 📩

**Visit your forked repository on GitHub and click the "Compare & pull request"** button to create a pull request from your branch to the primary repository.

**Please provide comprehensive details to clearly explain your changes.** This will help the project maintainers and fellow contributors to understand your contributions and provide valuable feedback.

<!-- prettier-ignore -->
> [!NOTE]
> **Please ensure your pull request is well-formatted and linted** before submitting it. This will help the project maintainers and fellow contributors to work with your code more efficiently, and it will increase the likelihood of your pull request being accepted.

<!-- prettier-ignore-end -->

### 9. Await review 👀

Wait for the project maintainers to review your pull request. **Be prepared to address any suggested changes or refinements.**
Reviewers may ask you to make changes to your pull request before it can be accepted. **Please be patient and respond to any questions or requests in a timely manner.**

We know that waiting for your pull request to be accepted can be stressful. **Please be assured that we will do our best to review your pull request as soon as possible.** We appreciate your patience and understanding ❤️‍🔥

---

## 📖 Additional Resources

### Join the Community 🤝

Want to contribute to Majo.exe but don't know where to start? **Join our community!** We have created a welcoming community that encourages collaboration and supports new contributors. **We are excited to have you on board!** 🙌

[We created a Discord server for the Majo.exe community.](https://majoexe.com/discord) **Join the server to connect with fellow contributors and get support from the project maintainers.** We look forward to collaborating with you! 🚀👾🙌

[![Join the Discord server](https://invidget.switchblade.xyz/sgt4QEyDxK)](https://majoexe.com/discord)

### Share Your Feedback 📣

We want to hear from you! **Your feedback is vital for the project's development and success.** If you have any questions, suggestions, or concerns, please feel free to contact the project maintainers. We are always happy to help! 🙌

You can contact the project maintainers by [joining the Discord server](https://majoexe.com/discord) or [opening an issue](https://github.com/igorkowalczyk/majo.exe/issues/new/choose) on GitHub.

[![Create a new issue on GitHub](https://github.com/IgorKowalczyk/majo.exe/assets/49127376/15422f9b-c7cc-48ef-a047-6a81c0e6c6e9)](https://github.com/igorkowalczyk/majo.exe/issues/new/choose)

### Spread the Word 📢

**Help us spread the word about Majo.exe!** We would love to see more people join our community and contribute to the project. **Please share the project with your friends and colleagues.** We appreciate your support! 🙌

**Thank you for your valuable contributions, and we look forward to collaborating with you on the Majo.exe project! 🚀👾🙌**


================================================
FILE: README.md
================================================
![Header](https://github.com/IgorKowalczyk/majo.exe/assets/49127376/8fd53e0b-1902-460c-9d6c-7d42ea84f8bb)

<p align="center">
 <a href="https://majoexe.com/server"><img src="https://img.shields.io/discord/695282860399001640?color=%234552ef&logo=discord&label=Discord&style=flat&logoColor=fff" alt="Discord" /></a>
 <a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/badge/Discord.js-v14-%234552ef?style=flat&logo=npm&logoColor=fff" alt="Discord.js" /></a>
 <a href="https://majoexe.com/"><img src="https://img.shields.io/github/actions/workflow/status/igorkowalczyk/majo.exe/codeql-analysis.yml?branch=master&style=flat&label=CodeQL&logo=github&color=%234552ef" alt="CodeQL Checks" /></a>
 <a href="https://majoexe.com"><img src="https://img.shields.io/github/license/igorkowalczyk/majo.exe?style=flat&;logo=github&label=License&color=%234552ef" alt="GitHub License" /></a>
</p>

## ✨ Features

- ⚙️ **Fully Customizable:** Tailor Majo.exe to your preferences with comprehensive customization options.
- 🌆 **Built-in Dashboard:** Manage your Majo.exe settings effortlessly through our intuitive dashboard.
- 📝 **Easy Configuration:** Streamlined configuration process that makes setting up a breeze.
- 💯 **150+ Commands:** Access over 150 versatile commands to enrich your server's experience.
- 📚 **Easy Hosting:** Effortlessly host Majo.exe on your servers and keep it online 24/7.

## 🔗 Invite

Go to [this link](https://discord.com/oauth2/authorize/?permissions=4294967287&scope=bot%20applications.commands&client_id=949342410150924319) and add the bot (this requires `MANAGE_GUILD` permission) to your server.

[Or to make it easier, visit our website](https://majoexe.com/)

## 🖥️ Hosting

We are hosting Majo.exe on our own servers. Majo.exe will be online 24/7. [Invite Majo here!](https://majoexe.com/api/invite)  
However, if you want to host Majo.exe yourself, you can do it. [Check out our tutorials](#-tutorials) to learn how to do it.

<!-- prettier-ignore-start -->
> [!IMPORTANT]
> **This project is not for beginners.** If you are not familiar with Node.js, Prisma, Discord.js or any other technology used in this project, you should not host Majo.exe yourself!
<!-- prettier-ignore-end -->

### 📝 Tutorials

- **[🤖 Bot setup tutorial](/apps/bot/README.md)**
- **[🔩 Dashboard setup tutorial](/apps/dashboard/README.md)**
- **[📝 Database setup tutorial](/packages/database/README.md)**

## ⚙️ System Requirements

Ensure your setup meets these prerequisites before setting up Majo.exe:

- `PostgreSQL 14x` or higher
- `Node.js 18x` or higher
- `(Any)` Linux x64¹
- `~512MB` of RAM (minimum)
- `~3GB` of hard drive space (minimum)

<!-- prettier-ignore-start -->
> [!NOTE]
> 1. Debian based distros are recommended, bot can also run on Windows and MacOS but it's not recommended.
<!-- prettier-ignore-end -->

## 🔒 `.env` files

| Variable                    | Description                                              | Required (Bot) | Required (Dashboard) |
| --------------------------- | -------------------------------------------------------- | -------------- | -------------------- |
| `TOKEN`                     | Discord bot token                                        | `✅ Yes`       | `✅ Yes`             |
| `CLIENT_ID`                 | Discord client ID                                        | `✅ Yes`       | `✅ Yes`             |
| `CLIENT_SECRET`             | Discord client secret                                    | `❌ No`        | `✅ Yes`             |
| `DATABASE_URL`              | Main database connection string                          | `✅ Yes`       | `✅ Yes`             |
| `DATABASE_URL_UNPOOLED`     | Non-pooling database connection string                   | `❌ No`        | `❌ No`              |
| `REDIS_URL`                 | Redis Cache connection string                            | `✅ Yes`       | `✅ Yes`             |
| `SECRET`                    | Secret string (minimum 32 characters)                    | `❌ No`        | `✅ Yes`             |
| `NEXTAUTH_URL`              | NextAuth.js URL (e.g., http://localhost:3000)            | `❌ No`        | `✅ Yes`             |
| `NEXT_PUBLIC_URL`           | Next.js public URL (e.g., http://localhost:3000)         | `❌ No`¹       | `✅ Yes`             |
| `HOTJAR_ID`                 | [Hotjar](https://hotjar.com) ID                          | `❌ No`        | `❌ No`              |
| `DISCORD_SUPPORT_SERVER_ID` | Discord support server ID                                | `❌ No`        | `❌ No`²             |
| `TOPGG_API_KEY`             | [top.gg](https://top.gg) API key                         | `❌ No`        | `❌ No`³             |
| `DISCORD_BOT_LIST_API_KEY`  | [discordbotlist.com](https://discordbotlist.com) API key | `❌ No`        | `❌ No`⁴             |

<!-- prettier-ignore-start -->
> [!NOTE]
> 1. `NEXT_PUBLIC_URL` is required only if you want to also host the dashboard.
> 2. `DISCORD_SUPPORT_SERVER_ID` is required only if you want to automatically add users to your own Discord server when they log in to the dashboard. Please note that the bot needs `Manage Server` permission in the server!\
> 3. `TOPGG_API_KEY` is required only if you want to automatically post server count to [top.gg](https://top.gg).
> 4. `DISCORD_BOT_LIST_API_KEY` is required only if you want to automatically post server count, stats and more to [discordbotlist.com](https://discordbotlist.com).

<!-- prettier-ignore-end -->

## 📝 Contributors

- [**@binary-blazer**](https://github.com/binary-blazer) - Hosting support
- [**@TsukiyoDevs**](https://github.com/TsukiyoDevs) - Bug fixes, New features, Testing
- [**@r-kjha**](https://github.com/r-kjha) - Emoji config support, Bug fixes, New features, Testing
- [**@Joao-Victor-Liporini**](https://github.com/Joao-Victor-Liporini) - Bug fixes, Command handler improvements, Testing, New features
- [**@evandev**](https://github.com/xefew) - Bug fixes, Testing
- [**iWeedy\_**](https://github.com/i-weedy) - Testing
- [**@krzesl0**](https://github.com/krzesl0) - New Features, Bug fixes, Testing
- [**@\_index1337**](https://github.com/index1337) - Readme tutorials
- [**@Wafelowski**](https://github.com/HeavyWolfPL) - Translation improvements
- [**@Sakshyam6966**](https://github.com/Sakshyam6966) - New Features, Bug fixes, Testing

<!-- ## 💝 Sponsors

**These wonderful people and services have helped develop Majo.exe, without them this project would not exist. Thanks goes to these wonderful people!**

|                                                                      | Sponsor                                                             | Description                                                                                                             |
| -------------------------------------------------------------------- | ------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------- |
| ![TrestHost Logo](https://majoexe.com/assets/sponsors/tresthost.png) | [**TrestHost**](https://dash.tresthost.me/register?ref=majonez.exe) | **TrestHost is a good and powerful hosting provider** providing servers from the **USA and Germany**. Try us out today! | -->

## ⁉️ Issues

If you have any issues with the page please create [new issue here](https://github.com/igorkowalczyk/majo.exe/issues). When creating new issue please provide as much information as possible. If you can, please provide logs from console.

We will review your pull request as soon as possible. We might suggest some changes or improvements.

## 📥 Pull Requests

When submitting a pull request:

- Clone the repository (`git clone https://github.com/igorkowalczyk/majo.exe`)
- Create a branch off of `master` and give it a meaningful name (e.g. `my-awesome-new-feature`).
- Open a [pull request](https://github.com/igorkowalczyk/majo.exe/pulls) on [GitHub](https://github.com) and describe the feature or fix.

## 📋 License

This project is licensed under the MIT. See the [LICENSE](https://github.com/igorkowalczyk/majo.exe/blob/master/license.md) file for details

<details>
 <summary>The cake is a lie 🍰</summary>

<a href="https://igorkowalczyk.dev"><img src="https://views.igorkowalczyk.vercel.app/api/badge/majo.exe?style=flat-square&color=333333&label=Repo+views" alt="Github repository views"></a>

</details>


================================================
FILE: apps/bot/.env.example
================================================
# Bot
TOKEN=
CLIENT_ID=
CLIENT_SECRET=
DISCORD_SUPPORT_SERVER_ID=

# Top.gg (Optional)
TOPGG_API_KEY=

# discordbotlist.com (Optional)
DISCORD_BOT_LIST_API_KEY=

================================================
FILE: apps/bot/.prettierignore
================================================
package.json

================================================
FILE: apps/bot/Dockerfile
================================================
ARG APP_PKG_NAME=@majoexe/bot

FROM node:24-alpine

RUN apk add curl

WORKDIR /app

ENV NODE_ENV=production
ENV TURBO_TELEMETRY_DISABLED=1

RUN corepack enable 
RUN corepack prepare pnpm@latest --activate

RUN curl -sfS https://dotenvx.sh/install.sh | sh

COPY . .

RUN pnpm install --recursive --prod

CMD ["dotenvx", "run", "--", "pnpm", "run", "deploy", "--filter", "!@majoexe/dashboard"]

================================================
FILE: apps/bot/README.md
================================================
![Header - Bot](https://github.com/IgorKowalczyk/majo.exe/assets/49127376/9a34b389-e710-435e-9514-1f4c5f733d74)

<p align="center">
 <a href="https://majoexe.com/server"><img src="https://img.shields.io/discord/695282860399001640?color=%234552ef&logo=discord&label=Discord&style=flat&logoColor=fff" alt="Discord" /></a>
 <a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/badge/Discord.js-v14-%234552ef?style=flat&logo=npm&logoColor=fff" alt="Discord.js" /></a>
 <a href="https://majoexe.com/"><img src="https://img.shields.io/github/actions/workflow/status/igorkowalczyk/majo.exe/codeql-analysis.yml?branch=master&style=flat&label=CodeQL&logo=github&color=%234552ef" alt="CodeQL Checks" /></a>
 <a href="https://majoexe.com"><img src="https://img.shields.io/github/license/igorkowalczyk/majo.exe?style=flat&;logo=github&label=License&color=%234552ef" alt="GitHub License" /></a>
</p>

## 🤖 Self-Hosting

1. Clone [this repository](https://github.com/igorkowalczyk/majo.exe) `git clone https://github.com/IgorKowalczyk/majo.exe.git`
2. Go to `/packages/database/` directory and follow [Database Setup](/packages/database/README.md) tutorial.
3. Grab a Discord Bot token and client secret on [Discord's developer portal](https://discord.com/developers/applications) [Tutorial](#-discord-credentials).
4. Create new file or edit existing `.env` file in `/apps/bot/` directory.
5. In `.env` file set this values:
   - `TOKEN` - Discord bot token [[Tutorial](#-discord-token)]
   - `SECRET` - Random string (min. length = 32 chars)
   - `CLIENT_SECRET` - Discord bot secret [[Tutorial](#-discord-secret)]
   - `DISCORD_SUPPORT_SERVER_ID` - Your Discord support server ID
   - `TOPGG_API_KEY` - Your Top.gg API key (optional)
   - `DISCORD_BOT_LIST_API_KEY` - Your discordbotlist.com API key (optional)
6. Run `pnpm i` to install all dependencies
7. Go to `/packages/config/` directory and change values in `/configs/bot.js` to your values.
8. Go back to main directory and run `pnpm run dev --filter="@majoexe/bot"` or `pnpm run deploy --filter="@majoexe/bot"` to start bot
9. That's it! You can now invite your bot to your server and use it!

## 🔒 Example `.env` file

```
# Bot
TOKEN=
CLIENT_ID=
CLIENT_SECRET=
DISCORD_SUPPORT_SERVER_ID=

# Top.gg (Optional)
TOPGG_API_KEY=

# discordbotlist.com (Optional)
DISCORD_BOT_LIST_API_KEY=
```

> [!WARNING]
> Make sure to not share your `.env` file with anyone, it contains sensitive information like your bot token and secrets.

---

## ⚙️ System Requirements

Ensure your setup meets these prerequisites before setting up Majo.exe:

- `PostgreSQL 14x` or higher
- `Node.js 18x` or higher
- `(Any)` Linux x64¹
- `~512MB` of RAM (minimum)
- `~3GB` of hard drive space (minimum)

> [!NOTE]
> 1: Debian based distros are recommended, Dashboard can also run on Windows and MacOS but it's not recommended.

## 🔓 Tokens tutorials

### 🔏 Discord Token

1. Go to <a href="https://discordapp.com/developers/applications)">Discord Developer Portal</a>
2. At the top right of the screen, click "New application" and assign it a name. Next in the left part of the screen on the navigation bar, find "Bot" then click it and find button named "Add Bot"
3. After confirming the bot creation, click the "Copy token" button
4. Paste your token in `.env` file - `TOKEN=BOT_TOKEN`

> Tutorial written by: <a href="https://github.com/index1337">\_index1337</a>

### 🔓 Discord Bot Secret

1. Go to <a href="https://discordapp.com/developers/applications)">Discord Developer Portal</a>
2. In the left part of the screen on the bar, find "OAuth2" then click it
3. Find section named "Client Secret", under the bot secret click "Copy" button
4. Paste client secret to `.env` - `CLIENT_SECRET=CLIENT_SECRET`

> Tutorial written by: <a href="https://github.com/index1337">\_index1337</a>

## 📝 Contributors

- [**@binary-blazer**](https://github.com/binary-blazer) - Hosting support
- [**@TsukiyoDevs**](https://github.com/TsukiyoDevs) - Bug fixes, New features, Testing
- [**@r-kjha**](https://github.com/r-kjha) - Emoji config support, Bug fixes, New features, Testing
- [**@Joao-Victor-Liporini**](https://github.com/Joao-Victor-Liporini) - Bug fixes, Command handler improvements, Testing, New features
- [**@evandev**](https://github.com/xefew) - Bug fixes, Testing
- [**iWeedy\_**](https://github.com/i-weedy) - Testing
- [**@krzesl0**](https://github.com/krzesl0) - New Features, Bug fixes, Testing
- [**@\_index1337**](https://github.com/index1337) - Readme tutorials
- [**@Wafelowski**](https://github.com/HeavyWolfPL) - Translation improvements
- [**@Sakshyam6966**](https://github.com/Sakshyam6966) - New Features, Bug fixes, Testing

<!-- ## 💝 Sponsors

**These wonderful people and services have helped develop Majo.exe, without them this project would not exist. Thanks goes to these wonderful people!**

|                                                                      | Sponsor                                                             | Description                                                                                                             |
| -------------------------------------------------------------------- | ------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------- |
| ![TrestHost Logo](https://majoexe.com/assets/sponsors/tresthost.png) | [**TrestHost**](https://dash.tresthost.me/register?ref=majonez.exe) | **TrestHost is a good and powerful hosting provider** providing servers from the **USA and Germany**. Try us out today! | -->

## ⁉️ Issues

If you have any issues with the bot please create [new issue here](https://github.com/igorkowalczyk/majo.exe/issues).
When creating new issue please provide as much information as possible. If you can, please provide logs from console.

## 📥 Pull Requests

When submitting a pull request:

- Clone the repo.
- Create a branch off of `master` and give it a meaningful name (e.g. `my-awesome-new-feature`).
- Open a [pull request](https://github.com/igorkowalczyk/majo.exe/pulls) on [GitHub](https://github.com) and describe the feature or fix.

We will review your pull request as soon as possible. We might suggest some changes or improvements.

## 📋 License

This project is licensed under the MIT. See the [LICENSE](https://github.com/igorkowalczyk/majo.exe/blob/master/license.md) file for details


================================================
FILE: apps/bot/commands/Fun/8ball.ts
================================================
import { ApplicationCommandType, ApplicationCommandOptionType, EmbedBuilder, ApplicationIntegrationType, InteractionContextType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "8ball",
  description: "🎱 Ask the 8ball a question",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/8ball <question>",
  options: [
    {
      name: "question",
      description: "Question to ask 8ball",
      required: true,
      type: ApplicationCommandOptionType.String,
      max_length: 100,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const args = interaction.options.getString("question");
      if (!args) return client.errorMessages.createSlashError(interaction, "❌ Please provide a valid question.");

      const images = [
        ["Yes.", "https://c.tenor.com/TFhmPga4xEwAAAAC/magic8ball-yes.gif"],
        ["It is certain", "https://c.tenor.com/eyI116E3kWYAAAAC/yoda-8ball.gif"],
        ["Without a doubt", "https://c.tenor.com/-0tatbxLQVQAAAAC/yoda-8ball.gif"],
        ["Yes definelty", "https://c.tenor.com/fc7fywg2oQQAAAAC/yoda-8ball.gif"],
        ["You may rely on it", "https://c.tenor.com/8J1uZFp8xMUAAAAC/yoda-8ball.gif"],
        ["As I see it, yes", "https://c.tenor.com/EIAYng3CUf0AAAAC/yoda-8ball.gif"],
        ["Most likely", "https://c.tenor.com/EIAYng3CUf0AAAAC/yoda-8ball.gif"],
        ["Outlook not so good", "https://c.tenor.com/Ji3GcuKvu1cAAAAC/magic8ball-simpsons.gif"],
        ["Signs point to yes", "https://c.tenor.com/mrN4WoxyRE8AAAAC/shaking8ball-stranger-things4.gif"],
        ["followUp hazy, try again", "https://c.tenor.com/BokmYoZhr1AAAAAC/yoda-8ball.gif"],
        ["Ask again later", "https://c.tenor.com/Voqiq18wUFIAAAAC/yoda-8ball.gif"],
        ["Better not tell you now...", "https://c.tenor.com/Voqiq18wUFIAAAAC/yoda-8ball.gif"],
        ["Cannot predict now", "https://c.tenor.com/fs_hXVg58LkAAAAC/yoda-8ball.gif"],
        ["Concentrate and ask again", "https://c.tenor.com/Voqiq18wUFIAAAAC/yoda-8ball.gif"],
        ["Don't count on it", "https://c.tenor.com/cw2aa9cnQ6QAAAAC/magic-eight.gif"],
        ["My followUp is no", "https://c.tenor.com/rJ1ioW_FkhUAAAAC/yoda-8ball.gif"],
      ];

      const parsed = images.map((x) => [x[0], x[1]]);
      const random = Math.floor(Math.random() * parsed.length);

      if (!parsed[random] || !parsed[random][0] || !parsed[random][1]) return client.errorMessages.createSlashError(interaction, "❌ No answer available.");

      const embed = new EmbedBuilder()
        .setDescription(`>>> **Q:** ${args} \n**A:** ${parsed[random][0] || "No answer available"}`)
        .setImage(parsed[random][1])
        .setTimestamp()
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({ size: 256 }),
        });

      return interaction.followUp({ embeds: [embed] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Fun/advice.ts
================================================
import advices from "@majoexe/util/content/advices.json";
import { ApplicationCommandType, ApplicationIntegrationType, EmbedBuilder, InteractionContextType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "advice",
  description: "🤌 Get a random helpful advice",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/advice",
  run: async (client, interaction, guildSettings) => {
    try {
      const parsed = advices[Math.floor(Math.random() * advices.length)];
      if (!parsed) return client.errorMessages.createSlashError(interaction, "❌ Failed to fetch advice. Please try again later.");

      const embed = new EmbedBuilder()
        .setTitle("🤌 My advice is:")
        .setDescription(`>>> **${parsed.advice}**`)
        .setTimestamp()
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setThumbnail(interaction.user.displayAvatarURL({ size: 256 }))
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({ size: 256 }),
        });
      return interaction.followUp({ embeds: [embed] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Fun/anime.ts
================================================
import {
  ApplicationCommandType,
  ApplicationCommandOptionType,
  EmbedBuilder,
  codeBlock,
  ActionRowBuilder,
  ButtonBuilder,
  ButtonStyle,
  ApplicationIntegrationType,
  InteractionContextType,
  MessageFlags,
} from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "anime",
  description: "💮 Search for information about Anime by given name",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/anime <anime name>",
  autocomplete: async (client, interaction) => {
    const focusedOption = interaction.options.getFocused(true);

    if (focusedOption.name === "query") {
      const query = focusedOption.value;
      const request = await fetch(`https://kitsu.app/api/edge/anime?filter[text]=${query}&page%5Boffset%5D=0&page%5Blimit%5D=5`, {
        method: "GET",
        headers: {
          "Content-Type": "application/vnd.api+json",
          Accept: "application/vnd.api+json",
        },
      });

      if (!request || !request.ok) {
        return;
      }
      const json = await request.json();
      if (!json || !json.data || json.data.length < 1) {
        return;
      }

      /* eslint-disable typescript/no-explicit-any */
      const results = json.data.map((result: any) => {
        const data = result.attributes;
        return {
          name: data.canonicalTitle,
          value: data.canonicalTitle,
        };
      });

      await interaction.respond(results);
    }
  },
  options: [
    {
      name: "query",
      description: "Anime name",
      required: true,
      autocomplete: true,
      type: ApplicationCommandOptionType.String,
      max_length: 256,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const query = interaction.options.getString("query");

      if (!query) return client.errorMessages.createSlashError(interaction, "❌ Please provide a valid anime name.");

      const request = await fetch(`https://kitsu.app/api/edge/anime?filter[text]=${query}&page%5Boffset%5D=0&page%5Blimit%5D=1`, {
        method: "GET",
        headers: {
          "Content-Type": "application/vnd.api+json",
          Accept: "application/vnd.api+json",
        },
      });

      if (!request || !request.ok) {
        return client.errorMessages.createSlashError(interaction, "❌ No results found.");
      }
      const json = await request.json();
      if (!json || !json.data || json.data.length < 1) {
        return client.errorMessages.createSlashError(interaction, "❌ No results found.");
      }
      const data = json.data[0].attributes;

      if (!data) {
        const embed = new EmbedBuilder()
          .setColor("#EF4444")
          .setTimestamp()
          .setTitle("❌ Error")
          .setDescription("> No results found.")
          .setFooter({
            text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
            iconURL: interaction.user.displayAvatarURL({
              size: 256,
            }),
          });
        return interaction.followUp({ flags: [MessageFlags.Ephemeral], embeds: [embed] });
      }

      if (data.synopsis.length > 1024) {
        data.synopsis = data.synopsis.slice(0, 1021) + "...";
      }

      const embed = new EmbedBuilder()
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setTitle(data.canonicalTitle || query.slice(0, 20))
        .setURL(`https://kitsu.io/anime/${data.slug}`)
        .setDescription(data.synopsis ? (data.synopsis.length > 1024 ? data.synopsis.slice(0, 1021) + "..." : data.synopsis) : "No description!")
        .addFields([
          {
            name: `${client.config.emojis.flag_gb} English Title`,
            value: codeBlock(data.titles?.en || "None!"),
            inline: false,
          },
          {
            name: `${client.config.emojis.flag_jp} Japanese Title`,
            value: codeBlock(data.titles?.ja_jp || "None!"),
            inline: false,
          },
          {
            name: `${client.config.emojis.book} Type`,
            value: codeBlock(data.showType || "N/A!"),
            inline: true,
          },
          {
            name: `${client.config.emojis.star} Score`,
            value: codeBlock(`${data.averageRating || "N/A!"} (${data.favoritesCount} favorites)`),
            inline: true,
          },
          {
            name: `${client.config.emojis.counting} Episodes`,
            value: codeBlock(`${data.episodeCount || "N/A!"} episodes (${data.episodeLength || "N/A!"} minutes each)`),
            inline: false,
          },
          {
            name: `${client.config.emojis.star2} Rating`,
            value: codeBlock(`${data.ageRating || "N/A!"} ${"- " + data.ageRatingGuide || ""}`),
            inline: false,
          },
          {
            name: `${client.config.emojis.calendar_spillar} Aired`,
            value: codeBlock(`${data.startDate || "N/A!"} - ${data.endDate || "N/A!"}`),
            inline: false,
          },
          {
            name: `${client.config.emojis.barchart} Popularity`,
            value: codeBlock(`#${data.popularityRank || "N/A!"} (Most Popular Anime)\n#${data.ratingRank || "N/A!"} (Highest Rated Anime)`),
            inline: false,
          },
        ])
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        });

      if (data.posterImage?.original) {
        embed.setThumbnail(data.posterImage.original);
      }

      const actionRow = new ActionRowBuilder<ButtonBuilder>() // prettier
        .addComponents([
          new ButtonBuilder() // prettier
            .setStyle(ButtonStyle.Link)
            .setLabel("View on Kitsu")
            .setURL(`https://kitsu.io/anime/${data.slug}`),
        ]);

      return interaction.followUp({ embeds: [embed], components: [actionRow] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Fun/cat.ts
================================================
import { ActionRowBuilder, ApplicationCommandType, ApplicationIntegrationType, ButtonBuilder, ButtonStyle, EmbedBuilder, InteractionContextType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "cat",
  description: "🐱 Get a random cat image",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/cat",
  run: async (client, interaction, guildSettings) => {
    try {
      const data = await fetch("https://api.thecatapi.com/v1/images/search");
      const json = await data.json();

      if (!json || !json[0]) {
        return client.errorMessages.createSlashError(interaction, "❌ No results found.");
      }

      const embed = new EmbedBuilder()
        .setTitle("🐱 Meow!")
        .setImage(json[0].url)
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({ size: 256 }),
        });

      const actionRow = new ActionRowBuilder<ButtonBuilder>() // prettier
        .addComponents(
          new ButtonBuilder() // prettier
            .setStyle(ButtonStyle.Link)
            .setLabel("View image")
            .setURL(json[0].url)
        );
      return interaction.followUp({ embeds: [embed], components: [actionRow] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Fun/comic.ts
================================================
import { load } from "cheerio";
import {
  ApplicationCommandType,
  EmbedBuilder,
  ActionRowBuilder,
  ButtonBuilder,
  ApplicationCommandOptionType,
  ButtonStyle,
  ApplicationIntegrationType,
  InteractionContextType,
} from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "comic",
  description: "📚 Get a comic from xkcd, phd or garfield",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/comic <comic>",
  options: [
    {
      name: "xkcd",
      description: "💬 Check out the latest xkcd comic",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          type: ApplicationCommandOptionType.Integer,
          name: "issue",
          description: "Issue number to see the comic.",
          min_value: 1,
        },
      ],
    },
    {
      name: "phd",
      description: "💬 Check out the latest phd comic",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          type: ApplicationCommandOptionType.Integer,
          name: "issue",
          description: "Issue number to see the comic.",
          min_value: 1,
        },
      ],
    },
    {
      name: "garfield",
      description: "💬 Check out the latest garfield comic",
      type: ApplicationCommandOptionType.Subcommand,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const command = interaction.options.getSubcommand();

      if (command === "xkcd") {
        const issue = interaction.options.getInteger("issue");
        const data = await fetch(`https://xkcd.com${issue ? `/${issue}` : ""}/info.0.json`);
        const json = await data.json();

        if (!json) {
          return client.errorMessages.createSlashError(interaction, "❌ No results found.");
        }

        const embed = new EmbedBuilder()
          .setTitle(`📚 xkcd ${json.num} - ${json.title}`)
          .setDescription(json.alt)
          .setImage(json.img)
          .setColor(guildSettings?.embedColor || client.config.defaultColor)
          .setTimestamp()
          .setFooter({
            text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
            iconURL: interaction.user.displayAvatarURL({ size: 256 }),
          });

        const actionRow = new ActionRowBuilder<ButtonBuilder>() // prettier
          .addComponents([
            new ButtonBuilder() // prettier
              .setStyle(ButtonStyle.Link)
              .setLabel("View on xkcd")
              .setURL(`https://xkcd.com/${json.num}`),
          ]);

        return interaction.followUp({ embeds: [embed], components: [actionRow] });
      }

      if (command === "phd") {
        const issue = interaction.options.getInteger("issue");
        const data = await fetch(`https://phdcomics.com${issue ? "/comics/archive.php?comicid=" + issue : ""}`);
        const text = await data.text();

        if (!text) {
          return client.errorMessages.createSlashError(interaction, "❌ No results found.");
        }

        const $ = load(text);

        const images: string[] = [];

        $("img[name='comic2']").each((_, element) => {
          const imageUrl = $(element).attr("src");
          if (imageUrl) images.push(imageUrl);
        });

        if (!images[0]) {
          return client.errorMessages.createSlashError(interaction, "❌ No results found.");
        }

        const embed = new EmbedBuilder()
          .setTitle(`📚 PHD Comics ${issue ? `#${issue}` : ""}`)
          .setImage(images[0])
          .setColor(guildSettings?.embedColor || client.config.defaultColor)
          .setTimestamp()
          .setFooter({
            text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
            iconURL: interaction.user.displayAvatarURL({ size: 256 }),
          });

        const actionRow = new ActionRowBuilder<ButtonBuilder>() // prettier
          .addComponents([
            new ButtonBuilder() // prettier
              .setStyle(ButtonStyle.Link)
              .setLabel("View on PHD Comics")
              .setURL(`https://phdcomics.com${issue ? "/comics/archive.php?comicid=" + issue : ""}`),
          ]);

        return interaction.followUp({ embeds: [embed], components: [actionRow] });
      }

      if (command === "garfield") {
        const date = new Date();
        const year = date.getUTCFullYear();
        const month = date.getUTCMonth() + 1;
        const day = date.getUTCDate();

        const request = await fetch(`https://www.gocomics.com/garfield/${year}/${month}/${day}`);
        const text = await request.text();

        if (!text) {
          return client.errorMessages.createSlashError(interaction, "❌ No results found.");
        }

        const $ = load(text);
        const image = $(".item-comic-image img").attr("src");

        if (!image) {
          return client.errorMessages.createSlashError(interaction, "❌ No results found.");
        }

        const embed = new EmbedBuilder()
          .setTitle(`📚 Garfield by Jim Davis (${year}/${month}/${day})`)
          .setImage(image)
          .setColor(guildSettings?.embedColor || client.config.defaultColor)
          .setTimestamp()
          .setFooter({
            text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
            iconURL: interaction.user.displayAvatarURL({ size: 256 }),
          });

        const actionRow = new ActionRowBuilder<ButtonBuilder>() //
          .addComponents([
            new ButtonBuilder() // prettier
              .setStyle(ButtonStyle.Link)
              .setLabel("View on GoComics")
              .setURL(`https://www.gocomics.com/garfield/${year}/${month}/${day}`),
          ]);

        return interaction.followUp({ embeds: [embed], components: [actionRow] });
      }
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Fun/dice.ts
================================================
import { ApplicationCommandType, ApplicationIntegrationType, EmbedBuilder, InteractionContextType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "dice",
  description: "🎲 Roll a dice",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/dice",
  run: async (client, interaction, guildSettings) => {
    try {
      const dice = Math.floor(Math.random() * 6) + 1;

      const embed = new EmbedBuilder()
        .setTitle("🎲 Dice")
        .setDescription(`>>> **You rolled a ${dice}!**`)
        .setTimestamp()
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setThumbnail(interaction.user.displayAvatarURL({ size: 256 }))
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({ size: 256 }),
        });
      return interaction.followUp({ embeds: [embed] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Fun/flip.ts
================================================
import { flipText } from "@majoexe/util/functions/util";
import { ApplicationCommandType, ApplicationCommandOptionType, EmbedBuilder, ApplicationIntegrationType, InteractionContextType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "flip",
  description: "🔁 Flip text (upside down) or 🪙 Flip coin (heads or tails)",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/flip <coin | text>",
  options: [
    {
      name: "coin",
      description: "🪙 Flip coin (heads or tails)",
      type: ApplicationCommandOptionType.Subcommand,
      usage: "/flip coin",
    },
    {
      name: "text",
      description: "🔁 Flip text (upside down)",
      type: ApplicationCommandOptionType.Subcommand,
      usage: "/flip text",
      options: [
        {
          name: "text",
          description: "Text to flip",
          required: true,
          type: ApplicationCommandOptionType.String,
          max_length: 100,
        },
      ],
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      if (interaction.options.getSubcommand() == "coin") {
        const coin = Math.floor(Math.random() * 2) + 1;
        const embed = new EmbedBuilder()
          .setTitle("🪙 Coin Flip")
          .setDescription(`>>> **You flipped a ${coin == 1 ? "heads" : "tails"}!**`)
          .setTimestamp()
          .setColor(guildSettings?.embedColor || client.config.defaultColor)
          .setThumbnail(interaction.user.displayAvatarURL({ size: 256 }))
          .setFooter({
            text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
            iconURL: interaction.user.displayAvatarURL({ size: 256 }),
          });
        return interaction.followUp({ embeds: [embed] });
      } else if (interaction.options.getSubcommand() == "text") {
        const text = interaction.options.getString("text");
        if (!text) return client.errorMessages.createSlashError(interaction, "❌ Please provide a valid text to flip.");

        const embed = new EmbedBuilder()
          .setTitle("🔁 Flipped Text")
          .setDescription(`>>> **${flipText(text)}**`)
          .setTimestamp()
          .setColor(guildSettings?.embedColor || client.config.defaultColor)
          .setThumbnail(interaction.user.displayAvatarURL({ size: 256 }))
          .setFooter({
            text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
            iconURL: interaction.user.displayAvatarURL({ size: 256 }),
          });
        return interaction.followUp({ embeds: [embed] });
      }
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Fun/iq.ts
================================================
import { ApplicationCommandType, ApplicationCommandOptionType, EmbedBuilder, ApplicationIntegrationType, InteractionContextType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "iq",
  description: "🧠 Get a random IQ score",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/iq (user)",
  options: [
    {
      name: "user",
      description: "User to get IQ score",
      type: ApplicationCommandOptionType.User,
      required: false,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const user = interaction.options.getUser("user") || interaction.user;
      const iq = Math.floor(Math.random() * 200) + 1;

      const embed = new EmbedBuilder()
        .setTitle("🧠 IQ")
        .setDescription(`>>> **${user} has an IQ of ${iq}!**`)
        .setTimestamp()
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setThumbnail(user.displayAvatarURL({ size: 256 }))
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({ size: 256 }),
        });
      return interaction.followUp({ embeds: [embed] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Fun/joke.ts
================================================
import { ApplicationCommandType, ApplicationIntegrationType, EmbedBuilder, InteractionContextType } from "discord.js";
import fetch from "node-fetch";
import type { SlashCommand } from "@/util/types/Command";

interface Joke {
  type: string;
  setup: string;
  punchline: string;
  id: number;
}

export default {
  name: "joke",
  description: "😂 Get a random joke",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/joke",
  run: async (client, interaction, guildSettings) => {
    try {
      const joke = await fetch("https://official-joke-api.appspot.com/random_joke");
      if (!joke.ok) return client.errorMessages.createSlashError(interaction, "❌ No jokes found! Please try again later.");

      const json = (await joke.json()) as Joke;

      if (!json || !json.setup || !json.punchline) {
        return client.errorMessages.createSlashError(interaction, "❌ No jokes found! Please try again later.");
      }

      const embed = new EmbedBuilder()
        .setTitle("😂 Joke")
        .setDescription(`>>> **${json.setup}**\n\n${json.punchline}`)
        .setTimestamp()
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setThumbnail(interaction.user.displayAvatarURL({ size: 256 }))
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({ size: 256 }),
        });
      return interaction.followUp({ embeds: [embed] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Fun/letmegpt.ts
================================================
import {
  ApplicationCommandType,
  ApplicationCommandOptionType,
  EmbedBuilder,
  ButtonBuilder,
  ButtonStyle,
  ActionRowBuilder,
  ApplicationIntegrationType,
  InteractionContextType,
} from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "letmegpt",
  description: "🔍 Let me GPT that for you",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/lmgtfy <query>",
  options: [
    {
      name: "query",
      description: "Search query",
      required: true,
      type: ApplicationCommandOptionType.String,
      max_length: 256,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const query = interaction.options.getString("query");
      if (!query) return client.errorMessages.createSlashError(interaction, "❌ Please provide a valid search query.");

      const embed = new EmbedBuilder()
        .setTitle("🔍 Let me GPT that for you")
        .setDescription(`>>> https://letmegpt.com/search?q=${encodeURIComponent(query)}`)
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({ size: 256 }),
        });

      const row = new ActionRowBuilder<ButtonBuilder>() // prettier
        .addComponents(
          new ButtonBuilder() // prettier
            .setLabel("Search")
            .setEmoji("🔍")
            .setStyle(ButtonStyle.Link)
            .setURL(`https://letmegpt.com/search?q=${encodeURIComponent(query)}`)
        );

      return interaction.followUp({ embeds: [embed], components: [row] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Fun/lmgtfy.ts
================================================
import {
  ApplicationCommandType,
  ApplicationCommandOptionType,
  EmbedBuilder,
  ButtonBuilder,
  ButtonStyle,
  ActionRowBuilder,
  ApplicationIntegrationType,
  InteractionContextType,
} from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "lmgtfy",
  description: "🔍 Let me google that for you",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/lmgtfy <query>",
  options: [
    {
      name: "query",
      description: "Search query",
      required: true,
      type: ApplicationCommandOptionType.String,
      max_length: 256,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const query = interaction.options.getString("query");
      if (!query) return client.errorMessages.createSlashError(interaction, "❌ Please provide a valid search query.");

      const embed = new EmbedBuilder()
        .setTitle("🔍 Let me google that for you")
        .setDescription(`>>> https://letmegooglethat.com/?q=${encodeURIComponent(query)}`)
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({ size: 256 }),
        });

      const row = new ActionRowBuilder<ButtonBuilder>() // prettier
        .addComponents(
          new ButtonBuilder() // prettier
            .setLabel("Search")
            .setEmoji("🔍")
            .setStyle(ButtonStyle.Link)
            .setURL(`https://letmegooglethat.com/?q=${encodeURIComponent(query)}`)
        );

      return interaction.followUp({ embeds: [embed], components: [row] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Fun/meme.ts
================================================
import { ActionRowBuilder, ApplicationCommandType, ApplicationIntegrationType, ButtonBuilder, ButtonStyle, EmbedBuilder, InteractionContextType } from "discord.js";
import fetch from "node-fetch";
import type { SlashCommand } from "@/util/types/Command";

interface RedditPost {
  title: string;
  url: string;
  permalink: string;
}

interface RedditChildren {
  data: RedditPost;
}

interface RedditData {
  children: RedditChildren[];
}

interface RedditResponse {
  kind: string;
  data: RedditData;
}

export default {
  name: "meme",
  description: "😂 Get a random meme",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/meme",
  run: async (client, interaction, guildSettings) => {
    try {
      const meme = await fetch("https://reddit.com/r/dankmemes/random/.json");
      if (!meme.ok) return client.errorMessages.createSlashError(interaction, "❌ No memes found! Please try again later.");

      const json = (await meme.json()) as RedditResponse[];

      if (
        !json ||
        !json[0] ||
        !json[0].data ||
        !json[0].data.children ||
        !json[0].data.children[0] ||
        !json[0].data.children[0].data ||
        !json[0].data.children[0].data.title ||
        !json[0].data.children[0].data.url
      ) {
        return client.errorMessages.createSlashError(interaction, "❌ No results found.");
      }

      const embed = new EmbedBuilder()
        .setTitle(json[0].data.children[0].data.title)
        .setImage(json[0].data.children[0].data.url)
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({ size: 256 }),
        });

      const actionRow = new ActionRowBuilder<ButtonBuilder>() // prettier
        .addComponents(
          new ButtonBuilder() // prettier
            .setStyle(ButtonStyle.Link)
            .setLabel("View on Reddit")
            .setURL(`https://reddit.com${json[0].data.children[0].data.permalink}`)
        );

      return interaction.followUp({ embeds: [embed], components: [actionRow] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Fun/rate.ts
================================================
import { ApplicationCommandType, ApplicationCommandOptionType, EmbedBuilder, type ColorResolvable, ApplicationIntegrationType, InteractionContextType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "rate",
  description: "📈 Rate something",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/rate (thing)",
  options: [
    {
      name: "thing",
      description: "Thing to rate",
      type: ApplicationCommandOptionType.String,
      max_length: 256,
      required: true,
    },
  ],
  run: async (client, interaction) => {
    try {
      const thing = interaction.options.getString("thing");
      const rate = Math.floor(Math.random() * 100) + 1;

      let color;
      if (rate <= 100 && rate >= 90) {
        color = "#57F287";
      } else if (rate >= 50 && rate <= 89) {
        color = "#FFFF00";
      } else if (rate >= 0 && rate <= 49) {
        color = "#ED4245";
      }

      const embed = new EmbedBuilder()
        .setTitle("📈 Rating")
        .setDescription(`>>> **I rate ${thing} a ${rate}/100!**`)
        .setTimestamp()
        .setColor(color as ColorResolvable)
        .setThumbnail(interaction.user.displayAvatarURL({ size: 256 }))
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({ size: 256 }),
        });
      return interaction.followUp({ embeds: [embed] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Fun/ship.ts
================================================
import { percentageBar } from "@majoexe/util/functions/util";
import { ApplicationCommandType, ApplicationCommandOptionType, EmbedBuilder, ApplicationIntegrationType, InteractionContextType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "ship",
  description: "❤️ Ship users together",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/ship <user1> <user2>",
  options: [
    {
      name: "first",
      description: "The first user to ship",
      type: ApplicationCommandOptionType.User,
      required: true,
    },
    {
      name: "second",
      description: "The second user to ship",
      type: ApplicationCommandOptionType.User,
      required: true,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const first = interaction.options.getUser("first");
      const second = interaction.options.getUser("second");

      if (!first || !second) {
        return client.errorMessages.createSlashError(interaction, "❌ You need to specify two users to ship");
      }

      if (first.id === second.id) {
        return client.errorMessages.createSlashError(interaction, "❌ You can't ship the same user with themselves");
      }

      const ship = Math.floor(Math.random() * 100) + 1;

      const embed = new EmbedBuilder()
        .setTitle(`❤️ Shipping ${first.globalName || first.username} and ${second.globalName || second.username}`)
        .setDescription(` **${ship > 50 ? "🔥 They are born for each other!" : "❄️ This isn't a match"}**\n\n${percentageBar(100, ship, 20)}`)
        .setTimestamp()
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        });

      if (ship > 50) {
        embed.setThumbnail("https://cdn.discordapp.com/emojis/797365365595439104.gif?v=1");
      } else {
        embed.setThumbnail("https://cdn.discordapp.com/emojis/853644938867769454.gif?v=1");
      }

      interaction.followUp({ embeds: [embed] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Fun/why.ts
================================================
import why from "@majoexe/util/content/why.json";
import { ApplicationCommandType, ApplicationIntegrationType, EmbedBuilder, InteractionContextType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "why",
  description: "🤔 Get a random why question",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/why",
  run: async (client, interaction, guildSettings) => {
    try {
      const parsed = why[Math.floor(Math.random() * why.length)];

      const embed = new EmbedBuilder()
        .setTitle("🤔 Why?")
        .setDescription(`> **${parsed}**\n\n*Some questions can be outdated or not make sense!\n Don't take them seriously!*`)
        .setTimestamp()
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setThumbnail(interaction.user.displayAvatarURL({ size: 256 }))
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({ size: 256 }),
        });
      return interaction.followUp({ embeds: [embed] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/General/about.ts
================================================
import { ActionRowBuilder, ApplicationCommandType, ButtonStyle, ButtonBuilder, EmbedBuilder, InteractionContextType, ApplicationIntegrationType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "about",
  description: "🏷️ Learn more about Majo.exe",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  usage: "/about",
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  run: async (client, interaction, guildSettings) => {
    try {
      if (!client.user) return client.errorMessages.createSlashError(interaction, "❌ Bot is not ready yet. Please try again later.");

      const embed = new EmbedBuilder() // Prettier
        .setTitle(`🤖 About ${client.user.username}`)
        .setDescription(
          `Majo.exe is a Discord bot made for **Memes, Image editing, Giveaways, Moderation, Anime and even more!** 🎉
     
     It is made by the awesome [Majo.exe Team & Contributors](https://github.com/IgorKowalczyk/majo.exe#-contributors) and is **completly open source and free**.
     
     **You can find the source code [on Github](https://github.com/igorkowalczyk/majo.exe).** If you want to help us with our journey and you know how to code, you can contribute to the project by forking the repository and making a pull request. **We really appreciate it!** ❤️‍🔥

     ${client.config.url ? `**If you want to invite Majo.exe to your server, you can do so by clicking [here](${client.config.url})**` : ""}
     `
        )
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        })
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp();

      if (client.config.url) {
        const action = new ActionRowBuilder<ButtonBuilder>() // prettier
          .addComponents(
            new ButtonBuilder() // prettier
              .setLabel("Dashboard")
              .setStyle(ButtonStyle.Link)
              .setURL(client.config.url),
            new ButtonBuilder() // prettier
              .setLabel("Invite")
              .setStyle(ButtonStyle.Link)
              .setURL(`${client.config.url}/invite`)
          );

        return interaction.followUp({ embeds: [embed], components: [action] });
      } else {
        return interaction.followUp({ embeds: [embed] });
      }
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/General/contact.ts
================================================
import { ApplicationCommandType, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, ApplicationIntegrationType, InteractionContextType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "contact",
  description: "📝 Contact the Majo.exe team",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/contact",
  run: async (client, interaction, guildSettings) => {
    try {
      if (!client.config.url) {
        const embed = new EmbedBuilder()
          .setTitle("😢 We are sorry!")
          .setDescription(
            "Apologies for the inconvenience, but our dashboard and contact page are currently experiencing technical difficulties. We kindly ask you to try again later."
          )
          .setFooter({
            text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
            iconURL: interaction.user.displayAvatarURL({
              size: 256,
            }),
          })
          .setColor(guildSettings?.embedColor || client.config.defaultColor)
          .setTimestamp()
          .setTitle("📝 Contact");
        return interaction.followUp({ embeds: [embed] });
      }

      const action = new ActionRowBuilder<ButtonBuilder>() // prettier
        .addComponents(
          new ButtonBuilder() // prettier
            .setLabel("Contact")
            .setStyle(ButtonStyle.Link)
            .setURL(`${client.config.url}/contact`),
          new ButtonBuilder() // prettier
            .setLabel("Commands")
            .setStyle(ButtonStyle.Link)
            .setURL(`${client.config.url}/commands`),
          new ButtonBuilder() // prettier
            .setLabel("Support")
            .setStyle(ButtonStyle.Link)
            .setURL(`${client.config.url}/support`)
        );

      const embed = new EmbedBuilder()
        .setDescription(
          `Click the button below or [click here](${client.config.url}/contact) to contact the Majo.exe team.\n\n>>> **Useful links:**\n- [View all Majo.exe commands](${client.config.url}/commands)\n- [Majo.exe support server](${client.config.url}/support)`
        )
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        })
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setTitle("📝 Contact");

      return interaction.followUp({ embeds: [embed], components: [action] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/General/dashboard.ts
================================================
import { ApplicationCommandType, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, ApplicationIntegrationType, InteractionContextType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "dashboard",
  description: "💻 Visit our dashboard",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/dashboard",
  run: async (client, interaction, guildSettings) => {
    try {
      if (!client.config.url) {
        const embed = new EmbedBuilder()
          .setDescription("Our dashboard is not working at the moment, please try again later!")
          .setFooter({
            text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
            iconURL: interaction.user.displayAvatarURL({
              size: 256,
            }),
          })
          .setColor(guildSettings?.embedColor || client.config.defaultColor)
          .setTimestamp()
          .setTitle("💻 Dashboard");
        return interaction.followUp({ embeds: [embed] });
      }

      const action = new ActionRowBuilder<ButtonBuilder>() // prettier
        .addComponents(
          new ButtonBuilder() // prettier
            .setLabel("Dashboard")
            .setStyle(ButtonStyle.Link)
            .setURL(client.config.url)
        );

      const embed = new EmbedBuilder()
        .setDescription(
          `Click the button below or [click here](${client.config.url}) to visit our dashboard.\n\n>>> **Useful links:**\n- [View all Majo.exe commands](${client.config.url}/commands)\n- [Majo.exe support server](${client.config.url}/support)`
        )
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        })
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setTitle("💻 Dashboard");

      return interaction.followUp({ embeds: [embed], components: [action] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/General/donate.ts
================================================
import { ApplicationCommandType, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, ApplicationIntegrationType, InteractionContextType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

interface DonateLink {
  icon: string;
  name: string;
  url: string;
}

export default {
  name: "donate",
  description: "🪙 Help us develop Majo.exe by donating",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/donate",
  run: async (client, interaction, guildSettings) => {
    try {
      if (!client.config.donate.enabled || !client.config.donate.links) {
        const embed = new EmbedBuilder()
          .setDescription("Currently, we do not accept any donation methods! Try again later")
          .setFooter({
            text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
            iconURL: interaction.user.displayAvatarURL({
              size: 256,
            }),
          })
          .setColor(guildSettings?.embedColor || client.config.defaultColor)
          .setTimestamp()
          .setTitle("🪙 Donate to Majo.exe");
        return interaction.followUp({ embeds: [embed] });
      }

      const embed = new EmbedBuilder()
        .setDescription(
          "> **You can donate to Majo.exe by using the following methods:**\n" +
            client.config.donate.links.map((link: DonateLink) => `- [${link.icon} ${link.name}](${link.url})`).join("\n")
        )
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        })
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setTitle("🪙 Donate to Majo.exe");

      const action = new ActionRowBuilder<ButtonBuilder>() // prettier
        .addComponents(
          client.config.donate.links.map((link: DonateLink) => {
            return new ButtonBuilder().setLabel(link.name).setStyle(ButtonStyle.Link).setURL(link.url).setEmoji(link.icon);
          })
        );

      return interaction.followUp({ embeds: [embed], components: [action] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/General/help.ts
================================================
import { formatDuration } from "@majoexe/util/functions/util";
import {
  ApplicationCommandType,
  ApplicationCommandOptionType,
  EmbedBuilder,
  codeBlock,
  ActionRowBuilder,
  ButtonBuilder,
  ButtonStyle,
  StringSelectMenuBuilder,
  ComponentType,
  ApplicationIntegrationType,
  InteractionContextType,
} from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

interface Category {
  name: string;
  emoji: string;
}

export default {
  name: "help",
  description: "❔ Display a list of all available commands",
  type: ApplicationCommandType.ChatInput,
  cooldown: 5000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/help [command]",
  options: [
    {
      name: "query",
      description: "The full name of command or category",
      autocomplete: true,
      type: ApplicationCommandOptionType.String,
      max_length: 256,
      required: false,
    },
  ],
  autocomplete: async (client, interaction) => {
    const focusedOption = interaction.options.getFocused(true);
    if (focusedOption.name === "query") {
      const commands = focusedOption.value // prettier
        ? Array.from(client.slashCommands.filter((cmd) => cmd.name.toLowerCase().includes(focusedOption.value.toLowerCase())).values())
        : Array.from(client.slashCommands.values());

      await interaction.respond(
        // prettier
        commands.slice(0, 25).map((choice) => ({
          name: `/${choice.name} - ${choice.description}`,
          value: choice.name,
        }))
      );
    }
  },
  run: async (client, interaction, guildSettings) => {
    try {
      if (!client.user) return client.errorMessages.createSlashError(interaction, "❌ Bot is not ready yet. Please try again later.");

      const globalActionRow: ActionRowBuilder<ButtonBuilder | StringSelectMenuBuilder>[] = [];
      const inviteLink = `https://discord.com/oauth2/authorize/?permissions=${client.config.permissions}&scope=${client.config.scopes}&client_id=${client.user.id}`;

      if (client.config.url) {
        const buttonRow = new ActionRowBuilder<ButtonBuilder>() // prettier
          .addComponents(
            new ButtonBuilder() // prettier
              .setStyle(ButtonStyle.Link)
              .setLabel("Dashboard")
              .setURL(client.config.url),
            new ButtonBuilder() // prettier
              .setStyle(ButtonStyle.Link)
              .setLabel("Invite")
              .setURL(inviteLink),
            new ButtonBuilder() // prettier
              .setStyle(ButtonStyle.Link)
              .setLabel("All Commands")
              .setURL(`${client.config.url}/commands`)
          );
        globalActionRow.push(buttonRow);
      }

      const query = interaction.options.getString("query") || "";
      const isCategory = client.slashCommands.map((cmd) => cmd.category?.toLowerCase()).includes(query?.toLowerCase());

      // #region Command
      if (query && !isCategory) {
        // If the query is a command, display the command's help menu.
        const command = client.slashCommands.get(query.toLowerCase());

        if (!command) {
          return client.errorMessages.createSlashError(interaction, `❌ The command \`${query}\` does not exist. Please check your spelling and try again.`);
        }

        const embed = new EmbedBuilder()
          .setTitle(`❔ Help for /${command.name}`)
          .addFields([
            {
              name: "Name",
              value: codeBlock(command.name),
              inline: true,
            },
            {
              name: "Usage",
              value: codeBlock(command.usage),
              inline: true,
            },
            {
              name: "Description",
              value: codeBlock(command.description),
            },
            {
              name: "Cooldown",
              value: codeBlock(formatDuration(command.cooldown || 0)),
              inline: true,
            },
            {
              name: "Category",
              value: codeBlock(command.category || "General"),
              inline: true,
            },
          ])
          .setColor(guildSettings?.embedColor || client.config.defaultColor)
          .setTimestamp()
          .setFooter({
            text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
            iconURL: interaction.user.displayAvatarURL({
              size: 256,
            }),
          });

        return interaction.followUp({ embeds: [embed], components: globalActionRow });
        // #endregion
        // #region Category
      } else if (query && isCategory) {
        // If the query is a category, display all commands in that category.
        const commands = client.slashCommands.filter((cmd) => cmd.category?.toLowerCase() === query.toLowerCase());
        const embed = new EmbedBuilder()
          .setTitle(`${client.config.emojis.categories.find((cat: Category) => cat.name === query.toLowerCase()).emoji} Available \`${query}\` commands \`(${commands.size})\``)
          .setDescription(`> ${commands.map((cmd) => `\`/${cmd.name}\``).join(", ")}`)
          .setColor(guildSettings?.embedColor || client.config.defaultColor)
          .setTimestamp()
          .setFooter({
            text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
            iconURL: interaction.user.displayAvatarURL({
              size: 256,
            }),
          });
        return interaction.followUp({ embeds: [embed], components: globalActionRow });
        // #endregion
        // #region Main menu
      } else {
        // If there is no query, display the main help menu.
        const categories = [...new Set(client.slashCommands.map((cmd) => cmd.category))];

        const embed = new EmbedBuilder()
          .setTitle("❔ Help")
          .setDescription(`> Use the menu, or use [\`/help [category]\`](${inviteLink}) to view commands based on their category!`)
          .addFields(
            categories
              .map((category) => ({
                name: `${client.config.emojis.categories.find((cat: Category) => cat.name === category?.toLowerCase()).emoji} ${category}`,
                value: codeBlock(`/help ${category?.toLowerCase()}`),
                inline: `/help ${category?.toLowerCase()}`.length < 15,
              }))
              .sort((a, b) => (a.inline === b.inline ? a.name.length - b.name.length : a.inline ? -1 : 1))
          )
          .setColor(guildSettings?.embedColor || client.config.defaultColor)
          .setTimestamp()
          .setThumbnail(client.user.displayAvatarURL({ size: 256 }))
          .setAuthor({
            name: `${client.user.username} Help`,
            iconURL: client.user.displayAvatarURL({ size: 256 }),
          })
          .setFooter({
            text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
            iconURL: interaction.user.displayAvatarURL({
              size: 256,
            }),
          });

        const selectRow = new ActionRowBuilder<StringSelectMenuBuilder>() // prettier
          .addComponents(
            new StringSelectMenuBuilder() // prettier
              .setCustomId("help_select")
              .setPlaceholder("Select a category")
              .addOptions(
                categories.map((category) => ({
                  label: `${client.config.emojis.categories.find((cat: Category) => cat.name === category?.toLowerCase()).emoji} ${category}`,
                  description: `View all ${client.slashCommands.filter((cmd) => cmd.category?.toLowerCase() === category?.toLowerCase()).size} commands`,
                  value: category?.toLowerCase() ?? "",
                }))
              )
          );
        const actionRow = [selectRow, ...globalActionRow];

        const response = await interaction.followUp({ embeds: [embed], components: actionRow });

        const collector = response.createMessageComponentCollector({
          componentType: ComponentType.StringSelect,
          filter: (i) => i.user.id === interaction.user.id,
          time: 3 * 60 * 1000, // 30 seconds
        });

        collector.on("collect", async (i) => {
          /* eslint-disable-next-line prefer-destructuring */
          const category = i.values[0];
          const commands = client.slashCommands.filter((cmd) => cmd.category?.toLowerCase() === (category ?? "").toLowerCase());
          const embed = new EmbedBuilder()
            .setTitle(
              `${client.config.emojis.categories.find((cat: Category) => cat.name === (category ?? "").toLowerCase()).emoji} Available \`${category ?? ""}\` commands \`(${commands.size})\``
            )
            .setDescription(`> ${commands.map((cmd) => `\`/${cmd.name}\``).join(", ")}`)
            .setColor(guildSettings?.embedColor || client.config.defaultColor)
            .setTimestamp()
            .setFooter({
              text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
              iconURL: interaction.user.displayAvatarURL({
                size: 256,
              }),
            });
          try {
            await i.update({ embeds: [embed], components: actionRow });
          } catch (_err) {
            return;
          }
        });

        collector.on("end", async () => {
          try {
            await interaction.editReply({ embeds: [embed], components: globalActionRow });
          } catch (_err) {
            return;
          }
        });

        return;
      }
      // #endregion
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/General/invite.ts
================================================
import { ApplicationCommandType, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, ApplicationIntegrationType, InteractionContextType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "invite",
  description: "🎉 Invite Majo.exe to your server!",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/invite",

  run: async (client, interaction, guildSettings) => {
    try {
      if (!client.user) return client.errorMessages.createSlashError(interaction, "❌ Bot is not ready yet. Please try again later.");

      const inviteLink = `https://discord.com/oauth2/authorize/?permissions=${client.config.permissions}&scope=${client.config.scopes}&client_id=${client.user.id}`;
      const inviteLinkRoot = `https://discord.com/oauth2/authorize/?permissions=8&scope=${client.config.scopes}&client_id=${client.user.id}`;

      const embed = new EmbedBuilder()
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setTitle(`🎉 Invite ${client.user.username} to your server!`)
        .setDescription(
          `> **[Click this link to invite me!](${inviteLink})** **__[Recomended!]__**\n\n *Or [click this link to invite me as administrator](${inviteLinkRoot}) [Not recomended!]*`
        )
        .setTimestamp()
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        });
      const row = new ActionRowBuilder<ButtonBuilder>() // Prettier
        .addComponents(
          new ButtonBuilder() // Prettier
            .setURL(inviteLink)
            .setLabel("Invite me!")
            .setStyle(ButtonStyle.Link)
        );
      return interaction.followUp({ embeds: [embed], components: [row] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/General/opensource.ts
================================================
import { ApplicationCommandType, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, time, ApplicationIntegrationType, InteractionContextType } from "discord.js";
import fetch from "node-fetch";
import type { SlashCommand } from "@/util/types/Command";

interface GithubResponse {
  sha: string;
  html_url: string;
  commit: {
    committer: {
      date: string;
    };
  };
}

export default {
  name: "opensource",
  description: "📚 Check out Majo.exe source code",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  usage: "/opensource",
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  run: async (client, interaction, guildSettings) => {
    try {
      if (!client.user) return client.errorMessages.createSlashError(interaction, "❌ Bot is not ready yet. Please try again later.");

      const request = await fetch("https://api.github.com/repos/igorkowalczyk/majo.exe/commits?per_page=1");
      if (!request.ok) return client.errorMessages.createSlashError(interaction, "❌ No results found. Please try again later.");
      const response = (await request.json()) as GithubResponse[];
      if (!response[0]) return client.errorMessages.createSlashError(interaction, "❌ No results found. Please try again later.");

      const lastTimestamp = Math.floor(new Date(response[0].commit.committer.date).getTime() / 1000);

      const embed = new EmbedBuilder() // Prettier
        .setTitle(`🐙 ${client.user.username} Github Repository`)
        .setDescription("**This project is open source: [@igorkowalczyk/majo.exe](https://github.com/igorkowalczyk/majo.exe)**")
        .addFields([
          {
            name: `📚 Latest commit ${time(lastTimestamp)} (${time(lastTimestamp, "R")})`,
            value: `🖇️ SHA: [\`${response[0].sha}\`](${response[0].html_url})`,
          },
        ])
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        })
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp();

      const row = new ActionRowBuilder<ButtonBuilder>()
        .addComponents(
          new ButtonBuilder() // Prettier
            .setURL("https://github.com/igorkowalczyk/majo.exe")
            .setLabel("Source code")
            .setStyle(ButtonStyle.Link)
        )
        .addComponents(
          new ButtonBuilder() // Prettier
            .setURL(response[0].html_url)
            .setLabel("Latest commit")
            .setStyle(ButtonStyle.Link)
        );
      return interaction.followUp({ embeds: [embed], components: [row] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/General/permissions.ts
================================================
import { ApplicationCommandType, ApplicationIntegrationType, EmbedBuilder, InteractionContextType, PermissionsBitField, codeBlock } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

function convertCamelCaseToWords(text: string) {
  return text.replace(/([A-Z])/g, " $1").replace(/^./, (str) => {
    return str.toUpperCase().trim();
  });
}

export default {
  name: "permissions",
  description: "🎛️ Check Majo.exe's permissions in your server",
  type: ApplicationCommandType.ChatInput,
  cooldown: 5000,
  contexts: [InteractionContextType.Guild],
  integrationTypes: [ApplicationIntegrationType.GuildInstall],
  usage: "/permissions",
  run: async (client, interaction, guildSettings) => {
    try {
      if (!client.user) return client.errorMessages.createSlashError(interaction, "❌ Bot is not ready yet. Please try again later.");
      if (!interaction.guild) return client.errorMessages.createSlashError(interaction, "❌ This command can only be used in a server.");
      if (!guildSettings) return client.errorMessages.createSlashError(interaction, "❌ Guild settings not found. Please try again later.");

      const clientMember = interaction.guild.members.cache.get(client.user.id);
      if (!clientMember) return client.errorMessages.createSlashError(interaction, "❌ Bot is not in the server.");
      const requiredPermissions = new PermissionsBitField(client.config.permissions);

      const permissionsText = requiredPermissions.toArray().map((permission) => {
        const hasPermission = clientMember.permissions.has(permission);
        const permissionName = convertCamelCaseToWords(permission.replace(/_/g, " "));

        return `${hasPermission ? "✅" : "❌"} ${permissionName}`;
      });

      const embed = new EmbedBuilder()
        .setColor(guildSettings.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setTitle(`🎛️ Permissions in ${interaction.guild.name}`)
        .setDescription(`> To work properly, ${client.user} needs **all** of the following permissions:\n${codeBlock(permissionsText.join("\n"))}`)
        .setTimestamp()
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        });
      return interaction.followUp({ embeds: [embed] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/General/ping.ts
================================================
import prismaClient from "@majoexe/database";
import { ApplicationCommandType, EmbedBuilder, codeBlock, Status, ApplicationIntegrationType, InteractionContextType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "ping",
  description: "🏓 Check the Majo.exe ping",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  usage: "/ping",
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  run: async (client, interaction, guildSettings) => {
    try {
      const dbTime = performance.now();
      await prismaClient.user.findUnique({ where: { id: "1" } });
      const dbTiming = performance.now() - dbTime;

      const waitEmbed = new EmbedBuilder() // prettier
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setDescription("🏓 Pong!...");
      const message = await interaction.followUp({ embeds: [waitEmbed] });

      const pingMessage = new EmbedBuilder()
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setTitle("🏓 Pong!")
        .addFields([
          {
            name: "Host Latency",
            value: codeBlock("yaml", client.ws.ping > 0 ? `${Math.floor(client.ws.ping)}ms` : "Calculating..."),
            inline: true,
          },
          {
            name: "Client Latency",
            value: codeBlock("yaml", `${Math.floor(message.createdTimestamp - interaction.createdTimestamp)}ms`),
            inline: true,
          },
          {
            name: "Database Latency",
            value: codeBlock("yaml", `${Math.floor(dbTiming)}ms`),
            inline: true,
          },
        ])
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        });

      if (interaction.guild) {
        const thisServerShard = client.ws.shards.get(interaction.guild.shardId);
        if (!thisServerShard) return interaction.editReply({ embeds: [pingMessage] });

        pingMessage.addFields([
          {
            name: "Websocket",
            value: codeBlock("yaml", `${Status[thisServerShard.status]}`),
            inline: true,
          },
          {
            name: "Shard",
            value: codeBlock("yaml", `${thisServerShard.id}/${client.ws.shards.size} (${thisServerShard.ping > 0 ? `${Math.floor(thisServerShard.ping)}ms` : "Calculating..."})`),
            inline: true,
          },
        ]);
      }

      await interaction.editReply({ embeds: [pingMessage] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/General/servers.ts
================================================
import { formatNumber } from "@majoexe/util/functions/util";
import { ApplicationCommandType, EmbedBuilder, ButtonBuilder, ActionRowBuilder, ButtonStyle, ApplicationIntegrationType, InteractionContextType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "servers",
  description: "🧭 Display the number of servers the Majo.exe is in",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/servers",
  run: async (client, interaction, guildSettings) => {
    try {
      if (!client.user) return client.errorMessages.createSlashError(interaction, "❌ Bot is not ready yet. Please try again later.");

      const allGuilds = client.guilds.cache;
      const allChannels = client.channels.cache;
      const allUsers = client.guilds.cache.reduce((acc, guild) => acc + guild.memberCount, 0);

      const inviteLink = `https://discord.com/oauth2/authorize/?permissions=${client.config.permissions}&scope=${client.config.scopes}&client_id=${client.user.id}`;
      const embed = new EmbedBuilder() // Prettier
        .setTitle(`🧭 ${client.user.username} is in ${allGuilds.size} servers!`)
        .setDescription(
          `**...thats a lot of servers!** To be exact, <@${client.user.id}> is serving commands to \`${formatNumber(allUsers) || "0"}\` users in \`${formatNumber(allChannels.size)}\` channels across \`${formatNumber(allGuilds.size)}\` servers!\n\n**If you want to invite Majo.exe to your server, you can do so by clicking [here](${inviteLink}).**`
        )
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        })
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setThumbnail(client.user.displayAvatarURL({ size: 256 }));

      const inviteButton = new ButtonBuilder() // prettier
        .setLabel("Invite")
        .setStyle(ButtonStyle.Link)
        .setURL(inviteLink);

      if (client.config.url) {
        const contactButton = new ButtonBuilder() // prettier
          .setLabel("Dashboard")
          .setStyle(ButtonStyle.Link)
          .setURL(client.config.url);

        const action = new ActionRowBuilder<ButtonBuilder>() // prettier
          .addComponents(
            // prettier
            inviteButton,
            contactButton
          );
        return interaction.followUp({ embeds: [embed], components: [action] });
      }

      const action = new ActionRowBuilder<ButtonBuilder>() // prettier
        .addComponents(
          // prettier
          inviteButton
        );

      return interaction.followUp({ embeds: [embed], components: [action] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/General/suggestion.ts
================================================
import { ApplicationCommandType, ActionRowBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, ApplicationIntegrationType, InteractionContextType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "suggestion",
  description: "📝 Send a suggestion to the Majo.exe team",
  type: ApplicationCommandType.ChatInput,
  cooldown: 10000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  defer: false,
  usage: "/suggestion",
  run: async (client, interaction) => {
    try {
      const modal = new ModalBuilder() // prettier
        .setCustomId("suggestion")
        .setTitle("📝 Suggestion");

      const action = new ActionRowBuilder<TextInputBuilder>() // prettier
        .addComponents(
          // prettier
          new TextInputBuilder() // prettier
            .setCustomId("suggestion")
            .setPlaceholder("Enter your suggestion here...")
            .setMinLength(5)
            .setMaxLength(500)
            .setRequired(true)
            .setStyle(TextInputStyle.Paragraph)
            .setLabel("Suggestion")
        );

      modal.addComponents(action);
      await interaction.showModal(modal);
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/General/uptime.ts
================================================
import { EmbedBuilder, time, ButtonBuilder, ActionRowBuilder, ApplicationCommandType, ButtonStyle, ApplicationIntegrationType, InteractionContextType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "uptime",
  description: "⌛ View Majo.exe bot uptime and past status",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/uptime",
  run: async (client, interaction, guildSettings) => {
    try {
      if (!client.user) return client.errorMessages.createSlashError(interaction, "❌ Bot is not ready yet. Please try again later.");

      const embed = new EmbedBuilder()
        .setTitle("📈 Majo.exe uptime")
        .setDescription(
          `**🚀 Date launched**: ${client.readyAt ? time(client.readyAt) : "Unknown"}
    **⏱️ Started:** ${client.readyAt ? time(client.readyAt, "R") : "Unknown"}
     
     **✨ Did you know?** From the time Majo.exe was launched it served \`${client.commandsRan}\` commands!
     `
        )
        .setTimestamp()
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        });

      if (client.config.url) {
        const action = new ActionRowBuilder<ButtonBuilder>() // prettier
          .addComponents(
            new ButtonBuilder() // prettier
              .setLabel("Status page")
              .setStyle(ButtonStyle.Link)
              .setURL(`${client.config.url}/status`)
          );
        return interaction.followUp({ embeds: [embed], components: [action] });
      } else {
        return interaction.followUp({ embeds: [embed] });
      }
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Giveaway/giveaway.ts
================================================
import { ApplicationCommandType, ApplicationCommandOptionType, ChannelType, PermissionFlagsBits, ApplicationIntegrationType, InteractionContextType } from "discord.js";
import { EndGiveaway } from "@/util/giveaway/endGiveaway";
import { FindGiveaways } from "@/util/giveaway/findGiveaways";
import { PauseGiveaway } from "@/util/giveaway/pauseGiveaway";
import { RerollGiveaway } from "@/util/giveaway/rerollGiveaway";
import { ResumeGiveaway } from "@/util/giveaway/resumeGiveaway";
import { StartDropGiveaway, StartGiveaway } from "@/util/giveaway/startGiveaway";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "giveaway",
  description: "🎉 Manage giveaway's",
  type: ApplicationCommandType.ChatInput,
  cooldown: 3000,
  contexts: [InteractionContextType.Guild],
  integrationTypes: [ApplicationIntegrationType.GuildInstall],
  defaultMemberPermissions: [PermissionFlagsBits.ManageGuild],
  defer: false,
  usage: "/giveaway <command>",
  options: [
    {
      name: "start",
      description: "🎉 Start giveaway",
      type: ApplicationCommandOptionType.Subcommand,
      //defaultMemberPermissions: [PermissionFlagsBits.ManageGuild],
      usage: "/giveaway start <time> <winners> <channel> <prize>",
      options: [
        {
          name: "time",
          description: "Time to end giveaway <d/h/m>",
          type: ApplicationCommandOptionType.String,
          min_length: 2,
          max_length: 15,
          required: true,
        },
        {
          name: "winners",
          description: "Winner count",
          type: ApplicationCommandOptionType.Integer,
          min_value: 1,
          max_value: 100,
          required: true,
        },
        {
          name: "channel",
          description: "Channel on which you want to create the giveaway",
          type: ApplicationCommandOptionType.Channel,
          channel_types: [ChannelType.GuildText],
          required: true,
        },
        {
          name: "prize",
          description: "Prize of the giveaway",
          type: ApplicationCommandOptionType.String,
          required: true,
          max_length: 100,
        },
      ],
    },
    {
      name: "drop",
      description: "🎉 Create a drop giveaway",
      type: ApplicationCommandOptionType.Subcommand,
      //defaultMemberPermissions: [PermissionFlagsBits.ManageGuild],
      usage: "/drop-giveaway <winners> <channel> <prize>",
      options: [
        {
          name: "winners",
          description: "Winner count",
          type: ApplicationCommandOptionType.Integer,
          min_value: 1,
          max_value: 100,
          required: true,
        },
        {
          name: "channel",
          description: "Channel on which you want to create the giveaway",
          type: ApplicationCommandOptionType.Channel,
          channel_types: [ChannelType.GuildText],
          required: true,
        },
        {
          name: "prize",
          description: "Prize of the giveaway",
          type: ApplicationCommandOptionType.String,
          required: true,
          max_length: 100,
        },
      ],
    },
    {
      name: "end",
      description: "🎉 End a giveaway",
      type: ApplicationCommandOptionType.Subcommand,
      //defaultMemberPermissions: [PermissionFlagsBits.ManageGuild],
      usage: "/giveaway end <giveaway id>",
      options: [
        {
          name: "query",
          description: "Giveaway ID (Message ID)",
          type: ApplicationCommandOptionType.String,
          required: true,
          max_length: 100,
        },
      ],
    },
    {
      name: "pause",
      description: "🎉 Pause a giveaway",
      type: ApplicationCommandOptionType.Subcommand,
      //defaultMemberPermissions: [PermissionFlagsBits.ManageGuild],
      usage: "/giveaway pause <giveaway id>",
      options: [
        {
          name: "query",
          description: "Giveaway ID (Message ID)",
          type: ApplicationCommandOptionType.String,
          required: true,
          max_length: 100,
        },
      ],
    },
    {
      name: "resume",
      description: "🎉 Resume a giveaway",
      type: ApplicationCommandOptionType.Subcommand,
      //defaultMemberPermissions: [PermissionFlagsBits.ManageGuild],
      usage: "/giveaway resume <giveaway id>",
      options: [
        {
          name: "query",
          description: "Giveaway ID (Message ID)",
          type: ApplicationCommandOptionType.String,
          required: true,
          max_length: 100,
        },
      ],
    },
    {
      name: "list",
      description: "🎉 Get list of all giveaways",
      type: ApplicationCommandOptionType.SubcommandGroup,
      //defaultMemberPermissions: [PermissionFlagsBits.ManageGuild],
      usage: "/giveaway list",
      options: [
        {
          name: "all",
          description: "🎉 Get list of all giveaways",
          type: ApplicationCommandOptionType.Subcommand,
          //usage: "/giveaway list all",
        },
        {
          name: "running",
          description: "🎉 Get list of all running giveaways",
          type: ApplicationCommandOptionType.Subcommand,
          //usage: "/giveaway list running",
        },
        {
          name: "ended",
          description: "🎉 Get list of all ended giveaways",
          type: ApplicationCommandOptionType.Subcommand,
          //usage: "/giveaway list ended",
        },
      ],
    },
    {
      name: "reroll",
      description: "🎉 Reroll a giveaway",
      type: ApplicationCommandOptionType.Subcommand,
      //defaultMemberPermissions: [PermissionFlagsBits.ManageGuild],
      usage: "/giveaway reroll <giveaway id>",
      options: [
        {
          name: "query",
          description: "Giveaway ID (Message ID)",
          type: ApplicationCommandOptionType.String,
          required: true,
          max_length: 100,
        },
      ],
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const type = interaction.options.getSubcommand();

      if (type === "start") {
        await StartGiveaway(client, interaction, guildSettings?.embedColor || client.config.defaultColor);
      } else if (type === "drop") {
        await StartDropGiveaway(client, interaction, guildSettings?.embedColor || client.config.defaultColor);
      } else if (type === "end") {
        await EndGiveaway(client, interaction, guildSettings?.embedColor || client.config.defaultColor);
      } else if (type === "pause") {
        await PauseGiveaway(client, interaction, guildSettings?.embedColor || client.config.defaultColor);
      } else if (type === "resume") {
        await ResumeGiveaway(client, interaction, guildSettings?.embedColor || client.config.defaultColor);
      } else if (type === "reroll") {
        await RerollGiveaway(client, interaction, guildSettings?.embedColor || client.config.defaultColor);
      } else if (type === "all" || type === "running" || type === "ended") {
        await FindGiveaways(client, interaction, guildSettings?.embedColor || client.config.defaultColor, type);
      }
    } catch (err: unknown) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Image/achievement.ts
================================================
import { loadImage, createCanvas } from "@napi-rs/canvas";
import { ApplicationCommandType, ApplicationCommandOptionType, AttachmentBuilder, EmbedBuilder, InteractionContextType, ApplicationIntegrationType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "achievement",
  description: "🏆 Generate a achievement image",
  type: ApplicationCommandType.ChatInput,
  cooldown: 5000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/achievement <text>",
  options: [
    {
      name: "text",
      description: "Text to put in achievement",
      type: ApplicationCommandOptionType.String,
      required: false,
      max_length: 50,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const text = interaction.options.getString("text") || "How Did We Get Here?";
      const background = await loadImage("./util/images/files/achievement.png");

      const canvas = createCanvas(background.width, background.height);
      const context = canvas.getContext("2d");
      context.drawImage(background, 0, 0, canvas.width, canvas.height);

      context.translate(120, 60);
      context.font = "24px Arial";
      context.fillStyle = "#c2c2c2";
      context.fillText(text, 10, 22, 330);

      const file = new AttachmentBuilder(canvas.toBuffer("image/png"), {
        name: "achievement.png",
      });

      const embed = new EmbedBuilder()
        .setTitle("🏆 Achievement")
        .setImage("attachment://achievement.png")
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        });

      return interaction.followUp({ embeds: [embed], files: [file] });
    } catch (err) {
      console.log(err);
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Image/ai.ts
================================================
import { ApplicationCommandType, ApplicationCommandOptionType, AttachmentBuilder, EmbedBuilder, codeBlock, InteractionContextType, ApplicationIntegrationType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "ai",
  description: "🖼️ Generate image with AI",
  type: ApplicationCommandType.ChatInput,
  cooldown: 6000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/ai [text]",
  options: [
    {
      name: "prompt",
      description: "Prompt to generate image, please be descriptive and provide as much detail as possible.",
      type: ApplicationCommandOptionType.String,
      required: true,
      max_length: 255,
    },
  ],

  run: async (client, interaction, guildSettings) => {
    try {
      const prompt = interaction.options.getString("prompt");
      if (!prompt) return client.errorMessages.createSlashError(interaction, "❌ Please provide a valid prompt to generate image.");

      if (!process.env.AI_DOMAIN || process.env.AI_DOMAIN === "" || !process.env.AI_TOKEN)
        return client.errorMessages.createSlashError(interaction, "❌ This feature is disabled right now, please try again later!");

      const loading = new EmbedBuilder() //
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTitle(`${client.config.emojis.loading} Generating image with AI...`)
        .setTimestamp()
        .setDescription("> Please wait while I generate an image with AI based on the prompt you provided. This may take a few seconds...")
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({ size: 256 }),
        });

      await interaction.followUp({ embeds: [loading] });

      const request = await fetch(`${process.env.AI_DOMAIN}v1/image?prompt=${encodeURIComponent(prompt)}&token=${process.env.AI_TOKEN}`);

      if (!request) return client.errorMessages.createSlashError(interaction, "❌ Failed to generate image, please try again.");

      if (!request.ok) {
        try {
          const error = await request.json();
          return client.errorMessages.createSlashError(interaction, `❌ Failed to generate image: \`${error.message}\``);
        } catch (_err) {
          return client.errorMessages.createSlashError(interaction, "❌ Failed to generate image, please try again.");
        }
      }

      const image = await request.arrayBuffer();

      if (!image) return client.errorMessages.createSlashError(interaction, "❌ Failed to generate image, please try again.");

      const attachment = new AttachmentBuilder(Buffer.from(image), {
        name: "generated-image.png",
      });

      const embed = new EmbedBuilder() // prettier
        .setTitle("🖼️ Generated Image")
        .setDescription(codeBlock("md", prompt))
        .setImage("attachment://generated-image.png")
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({ size: 256 }),
        });

      return await interaction.editReply({ embeds: [embed], files: [attachment] });
    } catch (err) {
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Image/bangladesh.ts
================================================
import { shortenText } from "@majoexe/util/functions/util";
import { loadImage, createCanvas } from "@napi-rs/canvas";
import { ApplicationCommandType, ApplicationCommandOptionType, AttachmentBuilder, EmbedBuilder, InteractionContextType, ApplicationIntegrationType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "bangladesh",
  description: "🇧🇩 I live in Bangladesh I live in Bangladesh",
  type: ApplicationCommandType.ChatInput,
  cooldown: 5000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/type-c [user]",
  options: [
    {
      name: "user",
      description: "User to put in Bandladesh",
      type: ApplicationCommandOptionType.User,
      required: false,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const user = interaction.options.getUser("user") || interaction.user;

      if (!user.displayAvatarURL({ size: 2048, extension: "png", forceStatic: true })) {
        return client.errorMessages.createSlashError(interaction, "❌ The user must have an avatar.");
      }

      const image = user.displayAvatarURL({
        size: 2048,
        extension: "png",
        forceStatic: true,
      });

      const [toFetch] = image.split("?");
      if (!toFetch || toFetch.length < 1) return client.errorMessages.createSlashError(interaction, "❌ The image URL is invalid.");
      const targetImage = await loadImage(toFetch);

      const background = await loadImage("./util/images/files/bangladesh.png");

      const canvas = createCanvas(background.width, background.height);
      const context = canvas.getContext("2d");

      const firstText = shortenText(user.globalName || user.username, 20) + " • 1 month ago";

      context.drawImage(background, 0, 0);
      context.save();
      context.beginPath();
      context.arc(39 + 66, 802 + 66, 66, 0, Math.PI * 2, true);
      context.closePath();
      context.clip();
      context.drawImage(targetImage, 39, 802, 132, 132);
      context.restore();
      context.font = "45px roboto-regular";

      context.fillStyle = "#494949";
      context.fillText(firstText, 205, 850);

      const file = new AttachmentBuilder(canvas.toBuffer("image/png"), {
        name: "bangladesh.png",
      });

      const embed = new EmbedBuilder()
        .setTitle("🇧🇩 Bangladesh")
        .setImage("attachment://bangladesh.png")
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        });

      return interaction.followUp({ embeds: [embed], files: [file] });
    } catch (err) {
      console.log(err);
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Image/change-my-mind.ts
================================================
import { getLines } from "@majoexe/util/images";
import { loadImage, createCanvas } from "@napi-rs/canvas";
import { ApplicationCommandType, ApplicationCommandOptionType, AttachmentBuilder, EmbedBuilder, InteractionContextType, ApplicationIntegrationType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "change-my-mind",
  description: "🤔 Change my mind",
  type: ApplicationCommandType.ChatInput,
  cooldown: 5000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/change-my-mind [text]",
  options: [
    {
      name: "text",
      description: "Text to put on the sign",
      type: ApplicationCommandOptionType.String,
      required: true,
      max_length: 120,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const text = interaction.options.getString("text");
      if (!text) return client.errorMessages.createSlashError(interaction, "❌ Please provide a valid text to put on the sign.");

      const background = await loadImage("./util/images/files/change-my-mind.png");
      const canvas = createCanvas(background.width, background.height);
      const context = canvas.getContext("2d");
      context.drawImage(background, 0, 0, canvas.width, canvas.height);

      // Inspired by https://github.com/jgoralcz/image-microservice/blob/dev/src/workers/canvas/ChangeMyMind.js

      const x = text.length;
      let fontSize = 70;
      const maxX = 780;
      const startX = 260;
      const startY = 580;

      context.translate(startX + 25, startY);

      context.rotate((1 * Math.PI) / 180);

      if (x <= 30) {
        fontSize = 50;
      } else if (x <= 70) {
        fontSize = 40;
      } else if (x <= 85) {
        fontSize = 32;
      } else if (x < 100) {
        fontSize = 26;
      } else if (x <= 120) {
        fontSize = 21;
      }

      context.font = `${fontSize}px 'Quicksand'`;
      context.fillStyle = "#000000";

      const lines = getLines(context, text, maxX - startX);

      for (let i = 0; i < lines.length; i++) {
        context.fillText(lines[i] as string, 10, i * fontSize + 10);
      }

      const file = new AttachmentBuilder(canvas.toBuffer("image/png"), {
        name: "change-my-mind.png",
      });

      const embed = new EmbedBuilder()
        .setTitle("🤔 Change my mind")
        .setImage("attachment://change-my-mind.png")
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        });

      return interaction.followUp({ embeds: [embed], files: [file] });
    } catch (err) {
      console.log(err);
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Image/dog-say.ts
================================================
import { getLines } from "@majoexe/util/images";
import { loadImage, createCanvas } from "@napi-rs/canvas";
import { ApplicationCommandType, ApplicationCommandOptionType, AttachmentBuilder, EmbedBuilder, InteractionContextType, ApplicationIntegrationType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "dog-say",
  description: "🐶 Make a dog say something, oh...",
  type: ApplicationCommandType.ChatInput,
  cooldown: 5000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/dog-say [text]",
  options: [
    {
      name: "text",
      description: "Text to say",
      type: ApplicationCommandOptionType.String,
      required: true,
      max_length: 55,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const text = interaction.options.getString("text");
      if (!text) return client.errorMessages.createSlashError(interaction, "❌ Please provide a valid text for the dog to say.");

      const background = await loadImage("./util/images/files/dog.png");
      const canvas = createCanvas(background.width, background.height);
      const context = canvas.getContext("2d");
      context.drawImage(background, 0, 0, canvas.width, canvas.height);

      const fontSize = 32;

      context.font = `${fontSize}px 'Arial'`;
      context.fillStyle = "#000000";

      context.translate(350, 50);
      const lines = getLines(context, text, 275);

      for (let i = 0; i < lines.length; i++) {
        if (lines[i]) {
          context.fillText(lines[i] as string, 0, i * fontSize);
        }
      }

      const file = new AttachmentBuilder(canvas.toBuffer("image/png"), {
        name: "dog-say.png",
      });

      const embed = new EmbedBuilder()
        .setTitle("🐶 Dog Say")
        .setImage("attachment://dog-say.png")
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        });

      return interaction.followUp({ embeds: [embed], files: [file] });
    } catch (err) {
      console.log(err);
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Image/fbi.ts
================================================
import { loadImage, createCanvas } from "@napi-rs/canvas";
import { ApplicationCommandType, ApplicationCommandOptionType, AttachmentBuilder, EmbedBuilder, InteractionContextType, ApplicationIntegrationType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "fbi",
  description: "🚨 Why FBI is here?",
  type: ApplicationCommandType.ChatInput,
  cooldown: 5000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/fbi [text]",
  options: [
    {
      name: "text",
      description: "Text to put in the image",
      type: ApplicationCommandOptionType.String,
      required: true,
      max_length: 120,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const text = interaction.options.getString("text");
      if (!text) return client.errorMessages.createSlashError(interaction, "❌ Please provide a valid text to put on the image.");

      const background = await loadImage("./util/images/files/why-fbi-here.png");
      const overlay = await loadImage("./util/images/files/why-fbi-here-overlay.png");
      const canvas = createCanvas(background.width, background.height);
      const context = canvas.getContext("2d");
      context.drawImage(background, 0, 0, canvas.width, canvas.height);

      context.font = "30px Arial";
      context.fillText(text, 40, 290);

      context.drawImage(overlay, 627, 0, overlay.width, overlay.height);

      const file = new AttachmentBuilder(canvas.toBuffer("image/png"), {
        name: "why-fbi-here.png",
      });

      const embed = new EmbedBuilder()
        .setTitle("🚨 Why is the FBI here?")
        .setImage("attachment://why-fbi-here.png")
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        });

      return interaction.followUp({ embeds: [embed], files: [file] });
    } catch (err) {
      console.log(err);
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Image/flag.ts
================================================
import { readFileSync } from "fs";
import { loadImage, createCanvas, ImageData } from "@napi-rs/canvas";
import decodeGif from "decode-gif";
import { ApplicationCommandType, ApplicationCommandOptionType, AttachmentBuilder, EmbedBuilder, InteractionContextType, ApplicationIntegrationType } from "discord.js";
// @ts-expect-error - No type definitions
import GIFEncoder from "gif-encoder-2";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "flag",
  description: "🏳️ Put a country flag on image",
  type: ApplicationCommandType.ChatInput,
  cooldown: 5000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/flag <country> [attachment/user]",
  options: [
    {
      name: "japan",
      description: "🇯🇵 Put a Japanese flag on image",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to put Japanese flag",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User to put Japanese flag",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
      ],
    },
    {
      name: "usa",
      description: "🇺🇸 Put a USA flag on image",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to put USA flag",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User to put USA flag",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
      ],
    },
    {
      name: "russia",
      description: "🇷🇺 Put a Russian flag on image",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to put Russian flag",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User to put Rusian flag",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
      ],
    },
    {
      name: "germany",
      description: "🇩🇪 Put a German flag on image",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to put German flag",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User to put German flag",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
      ],
    },
    {
      name: "poland",
      description: "🇵🇱 Put a Polish flag on image",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to put Polish flag",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User to put Polish flag",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
      ],
    },
    {
      name: "uk",
      description: "🇬🇧 Put a UK flag on image",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to put UK flag",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User to put UK flag",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
      ],
    },
    {
      name: "ukraine",
      description: "🇺🇦 Put a Ukrainian flag on image",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to put Ukrainian flag",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User to put Ukrainian flag",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
      ],
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const countryFlags: { [key: string]: string } = {
        japan: "🇯🇵",
        usa: "🇺🇸",
        russia: "🇷🇺",
        germany: "🇩🇪",
        ukraine: "🇺🇦",
        uk: "🇬🇧",
        poland: "🇵🇱",
      };
      const subcommand = interaction.options.getSubcommand();
      const attachment = interaction.options.getAttachment("attachment");
      const user = interaction.options.getUser("user") || interaction.user;
      let image;

      if (attachment) {
        if (attachment.contentType !== "image/png" && attachment.contentType !== "image/jpg" && attachment.contentType !== "image/jpeg") {
          return client.errorMessages.createSlashError(interaction, "❌ The attachment must be a png, jpg, or jpeg file.");
        }
        image = attachment.proxyURL;
      } else {
        if (!user.displayAvatarURL({ size: 2048, extension: "png", forceStatic: true })) {
          return client.errorMessages.createSlashError(interaction, "❌ The user must have an avatar.");
        }
        image = user.displayAvatarURL({
          size: 2048,
          extension: "png",
          forceStatic: true,
        });
      }

      const [toFetch] = image.split("?");
      if (!toFetch || toFetch.length < 1) return client.errorMessages.createSlashError(interaction, "❌ The image URL is invalid.");
      const targetImage = await loadImage(toFetch);
      const background = readFileSync(`./util/images/files/${subcommand}.gif`);
      const backgroundData = new Uint8Array(background);

      if (!backgroundData || backgroundData.length < 1) return client.errorMessages.createSlashError(interaction, "❌ The background data is undefined.");
      /* @ts-expect-error - Invalid types */
      const height = backgroundData[6] + backgroundData[7] * 256;
      /* @ts-expect-error - Invalid types */
      const width = backgroundData[8] + backgroundData[9] * 256;

      const gif = new GIFEncoder(width, height, "neuquant", true);
      gif.start();
      gif.setQuality(1);
      gif.setDelay(40);
      gif.setDispose(2);
      gif.setRepeat(0);

      const canvas = createCanvas(width, height);
      const context = canvas.getContext("2d");

      const { frames } = decodeGif(backgroundData);

      for (let i = 0; i < frames.length; i++) {
        context.globalAlpha = 1;
        const frame = frames[i];
        if (frame) {
          const imageData = new ImageData(frame.data, width, height);
          // @ts-expect-error - Invalid types in napi-rs/canvas
          context.putImageData(imageData, 0, 0);
        }
        context.globalAlpha = 0.5;
        context.drawImage(targetImage, 0, 0, width, height);
        gif.addFrame(context);
      }

      gif.finish();

      const file = new AttachmentBuilder(gif.out.getData(), {
        name: "flag.gif",
      });

      const embed = new EmbedBuilder()
        .setTitle(`${countryFlags[subcommand]} ${subcommand.charAt(0).toUpperCase() + subcommand.slice(1)}`)
        .setImage("attachment://flag.gif")
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        });

      if (attachment && attachment && attachment.width && attachment.height && (attachment.width > 512 || attachment.height > 512)) {
        embed.setDescription("⚠️ Your attachment was resized to 510x510px because it was too big.");
      }

      return interaction.followUp({ embeds: [embed], files: [file] });
    } catch (err) {
      console.log(err);
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Image/galaxy-note.ts
================================================
import { shortenText } from "@majoexe/util/functions/util";
import { loadImage, createCanvas } from "@napi-rs/canvas";
import { ApplicationCommandType, ApplicationCommandOptionType, AttachmentBuilder, EmbedBuilder, InteractionContextType, ApplicationIntegrationType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "galaxy-note",
  description: "📱 Say Hi to the new Galaxy Note",
  type: ApplicationCommandType.ChatInput,
  cooldown: 5000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/type-c [user]",
  options: [
    {
      name: "user",
      description: "User to put as user's profile picture",
      type: ApplicationCommandOptionType.User,
      required: false,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const user = interaction.options.getUser("user") || interaction.user;

      if (!user.displayAvatarURL({ size: 2048, extension: "png", forceStatic: true })) {
        return client.errorMessages.createSlashError(interaction, "❌ The user must have an avatar.");
      }

      const image = user.displayAvatarURL({
        size: 2048,
        extension: "png",
        forceStatic: true,
      });

      const [toFetch] = image.split("?");
      if (!toFetch || toFetch.length < 1) return client.errorMessages.createSlashError(interaction, "❌ The image URL is invalid.");
      const targetImage = await loadImage(toFetch);
      const background = await loadImage("./util/images/files/galaxy-note.png");

      const canvas = createCanvas(background.width, background.height);
      const context = canvas.getContext("2d");

      const firstText = shortenText(user.globalName || user.username, 20) + " • 24 minutes ago";

      context.drawImage(background, 0, 0);
      context.save();
      context.beginPath();
      context.arc(28 + 35, 433 + 35, 35, 0, Math.PI * 2, true);
      context.closePath();
      context.clip();
      context.drawImage(targetImage, 28, 433, 70, 70);
      context.restore();

      context.font = "32px roboto-regular";
      context.fillStyle = "#494949";
      context.fillText(firstText, 127, 462);

      const file = new AttachmentBuilder(canvas.toBuffer("image/png"), {
        name: "galaxy-note.png",
      });

      const embed = new EmbedBuilder()
        .setTitle("📱 Galaxy Note")
        .setImage("attachment://galaxy-note.png")
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        });

      return interaction.followUp({ embeds: [embed], files: [file] });
    } catch (err) {
      console.log(err);
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Image/image.ts
================================================
/* eslint-disable complexity */
import { createCanvas, loadImage } from "@napi-rs/canvas";
import { isColor } from "coloras";
import { ApplicationCommandType, ApplicationCommandOptionType, AttachmentBuilder, EmbedBuilder, InteractionContextType, ApplicationIntegrationType } from "discord.js";

const canvasSize = 510;

export default {
  name: "image",
  description: "🖼️ Edit image",
  type: ApplicationCommandType.ChatInput,
  cooldown: 5000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/image <command> [attachment/user]",
  options: [
    {
      name: "invert",
      description: "🖼️ Invert image colors",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to invert",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User avatar to invert",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
      ],
    },
    {
      name: "grayscale",
      description: "🖼️ Add grayscale to image",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to grayscale",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User avatar to grayscale",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
      ],
    },
    {
      name: "sepia",
      description: "🖼️ Add sepia effect to image",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to sepia",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User avatar to sepia",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
      ],
    },
    {
      name: "blur",
      description: "🖼️ Blur the whole image",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to blur",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User avatar to blur",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
        {
          name: "radius",
          description: "Blur radius",
          type: ApplicationCommandOptionType.Integer,
          min_value: 1,
          max_value: 100,
          required: false,
        },
      ],
    },
    {
      name: "sharpen",
      description: "🖼️ Sharpen the whole image",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to sharpen",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User avatar to sharpen",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
        {
          name: "radius",
          description: "Sharpen radius",
          type: ApplicationCommandOptionType.Integer,
          min_value: 1,
          max_value: 100,
          required: false,
        },
      ],
    },
    {
      name: "flip",
      description: "🖼️ Flip the image (x-axis)",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to flip",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User avatar to flip",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
      ],
    },
    {
      name: "flop",
      description: "🖼️ Flop the image (y-axis)",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to flip",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User avatar to flip",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
      ],
    },
    {
      name: "rotate",
      description: "🖼️ Rotate the image",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to flip",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User avatar to flip",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
        {
          name: "angle",
          description: "Rotate angle",
          type: ApplicationCommandOptionType.Integer,
          min_value: 1,
          max_value: 360,
          required: false,
        },
        {
          name: "background",
          description: "Background color",
          type: ApplicationCommandOptionType.String,
          required: false,
        },
      ],
    },
    {
      name: "round",
      description: "🖼️ Round the image corners",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to round",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User avatar to round",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
        {
          name: "radius",
          description: "Corner radius",
          type: ApplicationCommandOptionType.Integer,
          min_value: 1,
          max_value: 360,
          required: false,
        },
      ],
    },
    {
      name: "pixelate",
      description: "🖼️ Pixelate the image",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to pixelate",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User avatar to pixelate",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
        {
          name: "size",
          description: "Pixel size",
          type: ApplicationCommandOptionType.Integer,
          min_value: 1,
          max_value: 50,
          required: false,
        },
      ],
    },
    {
      name: "posterize",
      description: "🖼️ Posterize the image",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to posterize",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User avatar to posterize",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
        {
          name: "levels",
          description: "Number of posterization levels",
          type: ApplicationCommandOptionType.Integer,
          min_value: 2,
          max_value: 50,
          required: false,
        },
      ],
    },
    {
      name: "threshold",
      description: "🖼️ Apply threshold effect to the image",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to threshold",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User avatar to threshold",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
        {
          name: "level",
          description: "Threshold level (0-255)",
          type: ApplicationCommandOptionType.Integer,
          min_value: 0,
          max_value: 255,
          required: false,
        },
      ],
    },
    {
      name: "vignette",
      description: "🖼️ Apply vignette effect to the image",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to vignette",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User avatar to vignette",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
        {
          name: "size",
          description: "Vignette size (0-100)",
          type: ApplicationCommandOptionType.Integer,
          min_value: 0,
          max_value: 100,
          required: false,
        },
      ],
    },
    {
      name: "wavy",
      description: "🖼️ Apply wavy effect to the image",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to wavy",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User avatar to wavy",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
        {
          name: "amplitude",
          description: "Wave amplitude",
          type: ApplicationCommandOptionType.Integer,
          min_value: 1,
          max_value: 50,
          required: false,
        },
        {
          name: "frequency",
          description: "Wave frequency",
          type: ApplicationCommandOptionType.Integer,
          min_value: 1,
          max_value: 50,
          required: false,
        },
      ],
    },
    {
      name: "zoom",
      description: "🖼️ Zoom into the image",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to zoom",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User avatar to zoom",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
        {
          name: "factor",
          description: "Zoom factor (1-10)",
          type: ApplicationCommandOptionType.Integer,
          min_value: 1,
          max_value: 10,
          required: false,
        },
      ],
    },
    {
      name: "emboss",
      description: "🖼️ Apply emboss effect to the image",
      type: ApplicationCommandOptionType.Subcommand,
      options: [
        {
          name: "attachment",
          description: "Attachment to emboss",
          type: ApplicationCommandOptionType.Attachment,
          required: false,
        },
        {
          name: "user",
          description: "User avatar to emboss",
          type: ApplicationCommandOptionType.User,
          required: false,
        },
      ],
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const subcommand = interaction.options.getSubcommand();
      const attachment = interaction.options.getAttachment("attachment");
      const user = interaction.options.getUser("user") || interaction.user;
      let imageUrl;

      if (attachment) {
        if (!["image/png", "image/jpg", "image/jpeg"].includes(attachment.contentType)) {
          return client.errorMessages.createSlashError(interaction, "❌ The attachment must be a png, jpg, or jpeg file.");
        }
        imageUrl = attachment.proxyURL;
      } else {
        imageUrl = user.displayAvatarURL({ size: 2048, extension: "png", forceStatic: true });
      }

      const image = await loadImage(imageUrl);
      const canvas = createCanvas(canvasSize, canvasSize);
      const ctx = canvas.getContext("2d");

      ctx.drawImage(image, 0, 0, canvasSize, canvasSize);

      if (subcommand === "invert") {
        const imageData = ctx.getImageData(0, 0, canvasSize, canvasSize);
        for (let i = 0; i < imageData.data.length; i += 4) {
          imageData.data[i] = 255 - imageData.data[i]; // Red
          imageData.data[i + 1] = 255 - imageData.data[i + 1]; // Green
          imageData.data[i + 2] = 255 - imageData.data[i + 2]; // Blue
        }
        ctx.putImageData(imageData, 0, 0);
      } else if (subcommand === "grayscale") {
        const imageData = ctx.getImageData(0, 0, canvasSize, canvasSize);
        for (let i = 0; i < imageData.data.length; i += 4) {
          const avg = (imageData.data[i] + imageData.data[i + 1] + imageData.data[i + 2]) / 3;
          imageData.data[i] = avg; // Red
          imageData.data[i + 1] = avg; // Green
          imageData.data[i + 2] = avg; // Blue
        }
        ctx.putImageData(imageData, 0, 0);
      } else if (subcommand === "sepia") {
        const imageData = ctx.getImageData(0, 0, canvasSize, canvasSize);
        for (let i = 0; i < imageData.data.length; i += 4) {
          const red = imageData.data[i];
          const green = imageData.data[i + 1];
          const blue = imageData.data[i + 2];
          imageData.data[i] = red * 0.393 + green * 0.769 + blue * 0.189; // Red
          imageData.data[i + 1] = red * 0.349 + green * 0.686 + blue * 0.168; // Green
          imageData.data[i + 2] = red * 0.272 + green * 0.534 + blue * 0.131; // Blue
        }
        ctx.putImageData(imageData, 0, 0);
      } else if (subcommand === "sharpen") {
        const centerWeight = interaction.options.getInteger("radius") || 5;

        const weights = [0, -1, 0, -1, centerWeight, -1, 0, -1, 0];

        const side = Math.round(Math.sqrt(weights.length));
        const halfSide = Math.floor(side / 2);
        const imageData = ctx.getImageData(0, 0, canvasSize, canvasSize);
        const src = imageData.data;
        const sw = imageData.width;
        const sh = imageData.height;
        const w = sw;
        const h = sh;
        const output = ctx.createImageData(w, h);
        const dst = output.data;

        for (let y = 0; y < h; y++) {
          for (let x = 0; x < w; x++) {
            const sy = y;
            const sx = x;
            let r = 0,
              g = 0,
              b = 0;
            for (let cy = 0; cy < side; cy++) {
              for (let cx = 0; cx < side; cx++) {
                const scy = sy + cy - halfSide;
                const scx = sx + cx - halfSide;
                if (scy >= 0 && scy < sh && scx >= 0 && scx < sw) {
                  const srcOffset = (scy * sw + scx) * 4;
                  const wt = weights[cy * side + cx];
                  r += src[srcOffset] * wt;
                  g += src[srcOffset + 1] * wt;
                  b += src[srcOffset + 2] * wt;
                }
              }
            }
            const dstOffset = (y * w + x) * 4;
            dst[dstOffset] = Math.min(Math.max(r, 0), 255);
            dst[dstOffset + 1] = Math.min(Math.max(g, 0), 255);
            dst[dstOffset + 2] = Math.min(Math.max(b, 0), 255);
            dst[dstOffset + 3] = src[(y * sw + x) * 4 + 3];
          }
        }

        ctx.putImageData(output, 0, 0);
      } else if (subcommand === "flip") {
        ctx.scale(-1, 1);
        ctx.drawImage(image, -canvasSize, 0, canvasSize, canvasSize);
      } else if (subcommand === "flop") {
        ctx.scale(1, -1);
        ctx.drawImage(image, 0, -canvasSize, canvasSize, canvasSize);
      } else if (subcommand === "rotate") {
        const angle = (interaction.options.getInteger("angle") || 90) * (Math.PI / 180);
        const background = interaction.options.getString("background") || "#000000";
        if (!isColor(background)) {
          return client.errorMessages.createSlashError(interaction, "❌ The background color must be a valid hex color code.");
        }
        ctx.fillStyle = background;
        ctx.fillRect(0, 0, canvasSize, canvasSize);
        ctx.translate(canvasSize / 2, canvasSize / 2);
        ctx.rotate(angle);
        ctx.drawImage(image, -canvasSize / 2, -canvasSize / 2, canvasSize, canvasSize);
      } else if (subcommand === "round") {
        let radius = interaction.options.getInteger("radius") || 360;

        radius = Math.min(radius, canvasSize / 2);

        ctx.globalCompositeOperation = "destination-in";
        ctx.beginPath();

        if (radius === canvasSize / 2) {
          ctx.arc(canvasSize / 2, canvasSize / 2, radius, 0, Math.PI * 2);
        } else {
          ctx.moveTo(radius, 0);
          ctx.lineTo(canvasSize - radius, 0);
          ctx.quadraticCurveTo(canvasSize, 0, canvasSize, radius);
          ctx.lineTo(canvasSize, canvasSize - radius);
          ctx.quadraticCurveTo(canvasSize, canvasSize, canvasSize - radius, canvasSize);
          ctx.lineTo(radius, canvasSize);
          ctx.quadraticCurveTo(0, canvasSize, 0, canvasSize - radius);
          ctx.lineTo(0, radius);
          ctx.quadraticCurveTo(0, 0, radius, 0);
        }

        ctx.closePath();
        ctx.fill();
        ctx.globalCompositeOperation = "source-over";
      } else if (subcommand === "pixelate") {
        const size = interaction.options.getInteger("size") || 10;
        for (let y = 0; y < canvasSize; y += size) {
          for (let x = 0; x < canvasSize; x += size) {
            const pixel = ctx.getImageData(x, y, size, size);
            let r = 0,
              g = 0,
              b = 0;
            for (let py = 0; py < pixel.height; py++) {
              for (let px = 0; px < pixel.width; px++) {
                const index = (py * pixel.width + px) * 4;
                r += pixel.data[index];
                g += pixel.data[index + 1];
                b += pixel.data[index + 2];
              }
            }
            const totalPixels = pixel.width * pixel.height;
            r = Math.floor(r / totalPixels);
            g = Math.floor(g / totalPixels);
            b = Math.floor(b / totalPixels);
            ctx.fillStyle = `rgb(${r},${g},${b})`;
            ctx.fillRect(x, y, size, size);
          }
        }
      } else if (subcommand === "posterize") {
        const levels = interaction.options.getInteger("levels") || 5;
        const imageData = ctx.getImageData(0, 0, canvasSize, canvasSize);
        const step = Math.floor(255 / (levels - 1));
        for (let i = 0; i < imageData.data.length; i += 4) {
          imageData.data[i] = Math.floor(imageData.data[i] / step) * step; // Red
          imageData.data[i + 1] = Math.floor(imageData.data[i + 1] / step) * step; // Green
          imageData.data[i + 2] = Math.floor(imageData.data[i + 2] / step) * step; // Blue
        }
        ctx.putImageData(imageData, 0, 0);
      } else if (subcommand === "threshold") {
        const level = interaction.options.getInteger("level") || 128;
        const imageData = ctx.getImageData(0, 0, canvasSize, canvasSize);
        for (let i = 0; i < imageData.data.length; i += 4) {
          const avg = (imageData.data[i] + imageData.data[i + 1] + imageData.data[i + 2]) / 3;
          const value = avg >= level ? 255 : 0;
          imageData.data[i] = value; // Red
          imageData.data[i + 1] = value; // Green
          imageData.data[i + 2] = value; // Blue
        }
        ctx.putImageData(imageData, 0, 0);
      } else if (subcommand === "vignette") {
        const size = interaction.options.getInteger("size") || 50;
        const gradient = ctx.createRadialGradient(canvasSize / 2, canvasSize / 2, canvasSize / 2 - (canvasSize / 2) * (size / 100), canvasSize / 2, canvasSize / 2, canvasSize / 2);
        gradient.addColorStop(0, "rgba(0,0,0,0)");
        gradient.addColorStop(1, "rgba(0,0,0,0.5)");
        ctx.fillStyle = gradient;
        ctx.fillRect(0, 0, canvasSize, canvasSize);
      } else if (subcommand === "wavy") {
        const amplitude = interaction.options.getInteger("amplitude") || 10;
        const frequency = interaction.options.getInteger("frequency") || 10;
        const imageData = ctx.getImageData(0, 0, canvasSize, canvasSize);
        const tempCanvas = createCanvas(canvasSize, canvasSize);
        const tempCtx = tempCanvas.getContext("2d");
        tempCtx.putImageData(imageData, 0, 0);
        for (let y = 0; y < canvasSize; y++) {
          const offset = Math.floor(amplitude * Math.sin((2 * Math.PI * frequency * y) / canvasSize));
          ctx.drawImage(tempCanvas, 0, y, canvasSize, 1, offset, y, canvasSize, 1);
        }
      } else if (subcommand === "zoom") {
        const factor = interaction.options.getInteger("factor") || 2;
        const zoomSize = canvasSize / factor;
        const sx = (canvasSize - zoomSize) / 2;
        const sy = (canvasSize - zoomSize) / 2;
        ctx.clearRect(0, 0, canvasSize, canvasSize);
        ctx.drawImage(image, sx, sy, zoomSize, zoomSize, 0, 0, canvasSize, canvasSize);
      } else if (subcommand === "emboss") {
        const weights = [-2, -1, 0, -1, 1, 1, 0, 1, 2];
        const side = Math.round(Math.sqrt(weights.length));
        const halfSide = Math.floor(side / 2);
        const imageData = ctx.getImageData(0, 0, canvasSize, canvasSize);
        const src = imageData.data;
        const sw = imageData.width;
        const sh = imageData.height;
        const w = sw;
        const h = sh;
        const output = ctx.createImageData(w, h);
        const dst = output.data;

        for (let y = 0; y < h; y++) {
          for (let x = 0; x < w; x++) {
            const sy = y;
            const sx = x;
            let r = 0,
              g = 0,
              b = 0;
            for (let cy = 0; cy < side; cy++) {
              for (let cx = 0; cx < side; cx++) {
                const scy = sy + cy - halfSide;
                const scx = sx + cx - halfSide;
                if (scy >= 0 && scy < sh && scx >= 0 && scx < sw) {
                  const srcOffset = (scy * sw + scx) * 4;
                  const wt = weights[cy * side + cx];
                  r += src[srcOffset] * wt;
                  g += src[srcOffset + 1] * wt;
                  b += src[srcOffset + 2] * wt;
                }
              }
            }
            const dstOffset = (y * w + x) * 4;
            dst[dstOffset] = Math.min(Math.max(r + 128, 0), 255);
            dst[dstOffset + 1] = Math.min(Math.max(g + 128, 0), 255);
            dst[dstOffset + 2] = Math.min(Math.max(b + 128, 0), 255);
            dst[dstOffset + 3] = src[(y * sw + x) * 4 + 3];
          }
        }

        ctx.putImageData(output, 0, 0);
      }

      const buffer = canvas.toBuffer("image/png");
      const attachmentBuilder = new AttachmentBuilder(buffer, { name: "image.png" });
      const embed = new EmbedBuilder()
        .setTitle(`🖼️ Image with ${subcommand} effect`)
        .setImage("attachment://image.png")
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        });

      return interaction.followUp({ embeds: [embed], files: [attachmentBuilder] });
    } catch (err) {
      console.error(err);
      return client.errorMessages.internalError(interaction, err);
    }
  },
};


================================================
FILE: apps/bot/commands/Image/iq-graph.ts
================================================
import { getLines } from "@majoexe/util/images";
import { loadImage, createCanvas } from "@napi-rs/canvas";
import { ApplicationCommandType, ApplicationCommandOptionType, AttachmentBuilder, EmbedBuilder, InteractionContextType, ApplicationIntegrationType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "iq-graph",
  description: "🧠 Generate IQ graph",
  type: ApplicationCommandType.ChatInput,
  cooldown: 5000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/iq-graph <text-1> <text-2> <text-3>",
  options: [
    {
      name: "text-1",
      description: "Text to put as first person",
      type: ApplicationCommandOptionType.String,
      required: true,
      max_length: 100,
    },
    {
      name: "text-2",
      description: "Text to put as second person",
      type: ApplicationCommandOptionType.String,
      required: true,
      max_length: 100,
    },
    {
      name: "text-3",
      description: "Text to put as third person",
      type: ApplicationCommandOptionType.String,
      required: true,
      max_length: 100,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const text1 = interaction.options.getString("text-1") || "You";
      const text2 = interaction.options.getString("text-2") || "Me";
      const text3 = interaction.options.getString("text-3") || "Them";
      const background = await loadImage("./util/images/files/iq-graph.jpg");

      const canvas = createCanvas(background.width, background.height);
      const context = canvas.getContext("2d");
      context.drawImage(background, 0, 0, canvas.width, canvas.height);

      const calculateFontSize = (text: string) => {
        const { length } = text;
        if (length <= 10) return 32;
        if (length <= 20) return 26;
        if (length <= 30) return 20;
        return 16;
      };

      const fontSize1 = calculateFontSize(text1);
      const fontSize2 = calculateFontSize(text2);
      const fontSize3 = calculateFontSize(text3);

      context.font = `${fontSize1}px Arial`;
      context.fillStyle = "#000";
      const lines1 = getLines(context, text1, 220);
      lines1.forEach((line, i) => {
        const textWidth = context.measureText(line).width;
        const x = (220 - textWidth) / 2 + 17;
        const y = 238 + (50 - fontSize1 * lines1.length) / 2 + i * fontSize1;
        context.fillText(line, x, y);
      });

      context.font = `${fontSize2}px Arial`;
      const lines2 = getLines(context, text2, 250);
      lines2.forEach((line, i) => {
        const textWidth = context.measureText(line).width;
        const x = (250 - textWidth) / 2 + 223;
        const y = 15 + (50 - fontSize2 * lines2.length) / 2 + i * fontSize2;
        context.fillText(line, x, y);
      });

      context.font = `${fontSize3}px Arial`;
      const lines3 = getLines(context, text3, 200);
      lines3.forEach((line, i) => {
        const textWidth = context.measureText(line).width;
        const x = (200 - textWidth) / 2 + 457;
        const y = 189 + (50 - fontSize3 * lines3.length) / 2 + i * fontSize3;
        context.fillText(line, x, y);
      });

      const file = new AttachmentBuilder(canvas.toBuffer("image/png"), {
        name: "iq-graph.png",
      });

      const embed = new EmbedBuilder()
        .setTitle("🧠 IQ Graph")
        .setImage("attachment://iq-graph.png")
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        });

      return interaction.followUp({ embeds: [embed], files: [file] });
    } catch (err) {
      console.log(err);
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Image/jail.ts
================================================
import { loadImage, createCanvas } from "@napi-rs/canvas";
import { ApplicationCommandType, ApplicationCommandOptionType, AttachmentBuilder, EmbedBuilder, InteractionContextType, ApplicationIntegrationType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "jail",
  description: "🔐 Put someone in jail",
  type: ApplicationCommandType.ChatInput,
  cooldown: 5000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/jail [user/attachment]",
  options: [
    {
      name: "attachment",
      description: "Attachment to jail",
      type: ApplicationCommandOptionType.Attachment,
      required: false,
    },
    {
      name: "user",
      description: "User to put in jail",
      type: ApplicationCommandOptionType.User,
      required: false,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const attachment = interaction.options.getAttachment("attachment");
      const user = interaction.options.getUser("user") || interaction.user;
      let image;

      if (attachment) {
        if (attachment.contentType !== "image/png" && attachment.contentType !== "image/jpg" && attachment.contentType !== "image/jpeg") {
          return client.errorMessages.createSlashError(interaction, "❌ The attachment must be a png, jpg, or jpeg file.");
        }
        image = attachment.proxyURL;
      } else {
        if (!user.displayAvatarURL({ size: 2048, extension: "png", forceStatic: true })) {
          return client.errorMessages.createSlashError(interaction, "❌ The user must have an avatar.");
        }
        image = user.displayAvatarURL({
          size: 2048,
          extension: "png",
          forceStatic: true,
        });
      }

      const [toFetch] = image.split("?");
      if (!toFetch || toFetch.length < 1) return client.errorMessages.createSlashError(interaction, "❌ The image URL is invalid.");
      const targetImage = await loadImage(toFetch);
      const background = await loadImage("./util/images/files/jail.png");

      const canvas = createCanvas(350, 350);
      const context = canvas.getContext("2d");

      context.drawImage(targetImage, 0, 0, canvas.width, canvas.height);
      context.drawImage(background, 0, 0, canvas.width, canvas.height);

      const file = new AttachmentBuilder(canvas.toBuffer("image/png"), {
        name: "jail.png",
      });

      const embed = new EmbedBuilder()
        .setTitle("🔐 Jail")
        .setImage("attachment://jail.png")
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        });

      if (attachment && attachment.width && attachment.height && (attachment.width > 350 || attachment.height > 350)) {
        embed.setDescription("> ⚠️ Your attachment was resized to 350x350px because it was too big!");
      }

      return interaction.followUp({ embeds: [embed], files: [file] });
    } catch (err) {
      console.log(err);
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Image/note.ts
================================================
import { getLines } from "@majoexe/util/images";
import { loadImage, createCanvas } from "@napi-rs/canvas";
import { ApplicationCommandType, ApplicationCommandOptionType, AttachmentBuilder, EmbedBuilder, InteractionContextType, ApplicationIntegrationType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "note",
  description: "📝 Create a note",
  type: ApplicationCommandType.ChatInput,
  cooldown: 5000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/note <text>",
  options: [
    {
      name: "text",
      description: "Text to put in the note",
      type: ApplicationCommandOptionType.String,
      required: true,
      max_length: 256,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const text = interaction.options.getString("text");
      if (!text) return client.errorMessages.createSlashError(interaction, "❌ Please provide a valid text for the note.");
      if (text.length > 256) return client.errorMessages.createSlashError(interaction, "❌ The text must be less than 256 characters.");

      const background = await loadImage("./util/images/files/note.png");
      const canvas = createCanvas(background.width, background.height);
      const context = canvas.getContext("2d");
      context.drawImage(background, 0, 0, canvas.width, canvas.height);

      const x = text.length;
      const fontSize = Math.floor(0.0003 * (x * x) - 0.19 * x + 35.37) || 35;
      context.font = `${fontSize}px Arial`;
      context.fillStyle = "#000000";
      context.translate(425, 445);
      context.rotate(0.53);
      const lines = getLines(context, text, 160);

      lines.forEach((line, i) => {
        context.fillText(line, 0, i * fontSize);
      });

      const attachment = new AttachmentBuilder(canvas.toBuffer("image/png"), {
        name: "note.png",
      });

      const embed = new EmbedBuilder()
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setTitle("📝 Note")
        .setImage("attachment://note.png")
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({ size: 256 }),
        });

      return interaction.followUp({ embeds: [embed], files: [attachment] });
    } catch (err) {
      console.log(err);
      return client.errorMessages.createSlashError(interaction, "❌ An error occurred while executing this command.");
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Image/ph-comment.ts
================================================
import { loadImage, createCanvas } from "@napi-rs/canvas";
import { ApplicationCommandType, ApplicationCommandOptionType, AttachmentBuilder, EmbedBuilder, InteractionContextType, ApplicationIntegrationType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "ph-comment",
  description: "🔞 Generate a PH comment image",
  type: ApplicationCommandType.ChatInput,
  cooldown: 5000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/ph-comment <comment> [attachment/user] [username] ",
  options: [
    {
      name: "comment",
      description: "Comment of the user",
      type: ApplicationCommandOptionType.String,
      required: true,
      max_length: 256,
    },
    {
      name: "attachment",
      description: "Attachment to put as user's profile picture",
      type: ApplicationCommandOptionType.Attachment,
      required: false,
    },
    {
      name: "user",
      description: "User to put as user's profile picture",
      type: ApplicationCommandOptionType.User,
      required: false,
    },
    {
      name: "username",
      description: "Username of the user",
      type: ApplicationCommandOptionType.String,
      required: false,
      max_length: 32,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const attachment = interaction.options.getAttachment("attachment");
      const user = interaction.options.getUser("user") || interaction.user;
      const username = interaction.options.getString("username") || user.username;
      const comment = interaction.options.getString("comment");
      if (!comment) return client.errorMessages.createSlashError(interaction, "❌ Please provide a valid comment for the user.");

      let image;

      if (attachment) {
        if (attachment.contentType !== "image/png" && attachment.contentType !== "image/jpg" && attachment.contentType !== "image/jpeg") {
          return client.errorMessages.createSlashError(interaction, "❌ The attachment must be a png, jpg, or jpeg file.");
        }
        image = attachment.proxyURL;
      } else {
        if (!user.displayAvatarURL({ size: 2048, extension: "png", forceStatic: true })) {
          return client.errorMessages.createSlashError(interaction, "❌ The user must have an avatar.");
        }
        image = user.displayAvatarURL({
          size: 128,
          extension: "png",
          forceStatic: true,
        });
      }

      const [toFetch] = image.split("?");
      if (!toFetch || toFetch.length < 1) return client.errorMessages.createSlashError(interaction, "❌ The image URL is invalid.");
      const targetImage = await loadImage(toFetch);
      const background = await loadImage("./util/images/files/ph-comment.png");

      const canvas = createCanvas(background.width, background.height);
      const context = canvas.getContext("2d");

      context.drawImage(background, 0, 0, canvas.width, canvas.height);

      context.save();
      context.beginPath();
      context.arc(25 + 25, 130 + 25, 25, 0, Math.PI * 2, true);
      context.closePath();
      context.clip();
      context.drawImage(targetImage, 25, 130, 50, 50);
      context.restore();

      context.font = "bold 16px Arial";
      context.fillStyle = "#F28705";

      const usernameWidth = context.measureText(username).width;

      context.fillText(username, 85, 160);

      context.font = "16px Arial";
      context.fillStyle = "#969696";
      context.fillText("26 minutes ago", 85 + usernameWidth + 10, 160);

      context.font = "20px Arial";
      context.fillStyle = "#c6c6c6";
      context.fillText(comment, 25, 215);

      const file = new AttachmentBuilder(canvas.toBuffer("image/png"), {
        name: "ph-comment.png",
      });

      const embed = new EmbedBuilder()
        .setTitle("🔞 PH Comment")
        .setImage("attachment://ph-comment.png")
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        });

      return interaction.followUp({ embeds: [embed], files: [file] });
    } catch (err) {
      console.log(err);
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Image/sonic-says.ts
================================================
import { getLines } from "@majoexe/util/images";
import { loadImage, createCanvas } from "@napi-rs/canvas";
import { ApplicationCommandType, ApplicationCommandOptionType, AttachmentBuilder, EmbedBuilder, InteractionContextType, ApplicationIntegrationType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "sonic-says",
  description: "🦔 Sonic says",
  type: ApplicationCommandType.ChatInput,
  cooldown: 5000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/sonic-says <text>",
  options: [
    {
      name: "text",
      description: "Text to put on the sign",
      type: ApplicationCommandOptionType.String,
      required: true,
      max_length: 120,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const text = interaction.options.getString("text");
      if (!text) return client.errorMessages.createSlashError(interaction, "❌ Please provide a valid text to put on the sign.");

      const background = await loadImage("./util/images/files/sonic-says.png");
      const canvas = createCanvas(background.width, background.height);
      const context = canvas.getContext("2d");
      context.drawImage(background, 0, 0, canvas.width, canvas.height);

      const fontSize = 42;

      context.font = `bold ${fontSize}px 'Quicksand'`;
      context.fillStyle = "#ffffff";

      const lines = getLines(context, text, 500);
      lines.forEach((line, i) => {
        context.fillText(line, 260, 200 + i * fontSize);
      });

      const file = new AttachmentBuilder(canvas.toBuffer("image/png"), {
        name: "sonic-says.png",
      });

      const embed = new EmbedBuilder()
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setTitle("🦔 Sonic Says")
        .setImage("attachment://sonic-says.png")
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({ size: 256 }),
        });

      return interaction.followUp({ embeds: [embed], files: [file] });
    } catch (err) {
      console.log(err);
      return client.errorMessages.createSlashError(interaction, "❌ An error occurred while executing this command.");
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Image/trash.ts
================================================
import { loadImage, createCanvas } from "@napi-rs/canvas";
import { ApplicationCommandType, ApplicationCommandOptionType, AttachmentBuilder, EmbedBuilder, InteractionContextType, ApplicationIntegrationType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "trash",
  description: "🗑️ Put someone or something in the trash",
  type: ApplicationCommandType.ChatInput,
  cooldown: 5000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/trash [user/attachment]",
  options: [
    {
      name: "attachment",
      description: "Attachment to trash",
      type: ApplicationCommandOptionType.Attachment,
      required: false,
    },
    {
      name: "user",
      description: "User to put in trash",
      type: ApplicationCommandOptionType.User,
      required: false,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const attachment = interaction.options.getAttachment("attachment");
      const user = interaction.options.getUser("user") || interaction.user;
      let image;

      if (attachment) {
        if (attachment.contentType !== "image/png" && attachment.contentType !== "image/jpg" && attachment.contentType !== "image/jpeg") {
          return client.errorMessages.createSlashError(interaction, "❌ The attachment must be a png, jpg, or jpeg file.");
        }
        image = attachment.proxyURL;
      } else {
        if (!user.displayAvatarURL({ size: 2048, extension: "png", forceStatic: true })) {
          return client.errorMessages.createSlashError(interaction, "❌ The user must have an avatar.");
        }
        image = user.displayAvatarURL({
          size: 2048,
          extension: "png",
          forceStatic: true,
        });
      }

      const [toFetch] = image.split("?");
      if (!toFetch || toFetch.length < 1) return client.errorMessages.createSlashError(interaction, "❌ The image URL is invalid.");
      const targetImage = await loadImage(toFetch);
      const background = await loadImage("./util/images/files/trash.png");

      const canvas = createCanvas(background.width, background.height);
      const context = canvas.getContext("2d");

      context.drawImage(background, 0, 0);
      context.drawImage(targetImage, 309, 0, 309, 309);

      const file = new AttachmentBuilder(canvas.toBuffer("image/png"), {
        name: "trash.png",
      });

      const embed = new EmbedBuilder()
        .setTitle("🗑️ Trash")
        .setImage("attachment://trash.png")
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        });

      if (attachment && attachment.width && attachment.height && (attachment.width > 309 || attachment.height > 309)) {
        embed.setDescription("> ⚠️ Your attachment was resized to 309x309 pixels because it was too big!");
      }

      return interaction.followUp({ embeds: [embed], files: [file] });
    } catch (err) {
      console.log(err);
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Image/trigger.ts
================================================
import { loadImage, createCanvas } from "@napi-rs/canvas";
import { ApplicationCommandType, ApplicationCommandOptionType, AttachmentBuilder, EmbedBuilder, InteractionContextType, ApplicationIntegrationType } from "discord.js";
// @ts-expect-error - No type definitions
import GIFEncoder from "gif-encoder-2";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "trigger",
  description: "😠 Generate a triggered gif from an image",
  type: ApplicationCommandType.ChatInput,
  cooldown: 5000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/trigger [user/attachment]",
  options: [
    {
      name: "attachment",
      description: "Attachment to trigger",
      type: ApplicationCommandOptionType.Attachment,
      required: false,
    },
    {
      name: "user",
      description: "User to trigger",
      type: ApplicationCommandOptionType.User,
      required: false,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const attachment = interaction.options.getAttachment("attachment");
      const user = interaction.options.getUser("user") || interaction.user;
      let image;

      if (attachment) {
        if (attachment.contentType !== "image/png" && attachment.contentType !== "image/jpg" && attachment.contentType !== "image/jpeg") {
          return client.errorMessages.createSlashError(interaction, "❌ The attachment must be a png, jpg, or jpeg file.");
        }
        image = attachment.proxyURL;
      } else {
        if (!user.displayAvatarURL({ size: 2048, extension: "png", forceStatic: true })) {
          return client.errorMessages.createSlashError(interaction, "❌ The user must have an avatar.");
        }
        image = user.displayAvatarURL({
          size: 2048,
          extension: "png",
          forceStatic: true,
        });
      }

      const [toFetch] = image.split("?");
      if (!toFetch || toFetch.length < 1) return client.errorMessages.createSlashError(interaction, "❌ The image URL is invalid.");
      const targetImage = await loadImage(toFetch);
      const background = await loadImage("./util/images/files/triggered.png");

      const gif = new GIFEncoder(256, 310, "neuquant", true);

      gif.start();
      gif.setRepeat(0);
      gif.setDelay(15);

      const canvas = createCanvas(256, 310);
      const context = canvas.getContext("2d");

      const BR = 30;
      const LR = 20;

      for (let index = 0; index < 9; index++) {
        context.clearRect(0, 0, 256, 310);

        const targetImageOffsetX = Math.floor(Math.random() * BR) - BR;
        const targetImageOffsetY = Math.floor(Math.random() * BR) - BR;
        context.drawImage(targetImage, targetImageOffsetX, targetImageOffsetY, 256 + BR, 310 - 54 + BR);

        context.fillStyle = "#FF000033";
        context.fillRect(0, 0, 256, 310);

        const backgroundOffsetX = Math.floor(Math.random() * LR) - LR;
        const backgroundOffsetY = 310 - 54 + Math.floor(Math.random() * LR) - LR;
        context.drawImage(background, backgroundOffsetX, backgroundOffsetY, 256 + LR, 54 + LR);

        gif.addFrame(context);
      }

      gif.finish();

      const file = new AttachmentBuilder(gif.out.getData(), {
        name: "triggered.gif",
      });

      const embed = new EmbedBuilder()
        .setTitle("😠 Triggered")
        .setImage("attachment://triggered.gif")
        .setColor(guildSettings?.embedColor || client.config.defaultColor)
        .setTimestamp()
        .setFooter({
          text: `Requested by ${interaction.user.globalName || interaction.user.username}`,
          iconURL: interaction.user.displayAvatarURL({
            size: 256,
          }),
        });

      if (attachment && attachment.width && attachment.height && (attachment.width > 256 || attachment.height > 310)) {
        embed.setDescription("> ⚠️ Your attachment was resized to 256x310 pixels because it was too big!");
      }

      return interaction.followUp({ embeds: [embed], files: [file] });
    } catch (err) {
      console.log(err);
      client.errorMessages.internalError(interaction, err);
    }
  },
} satisfies SlashCommand;


================================================
FILE: apps/bot/commands/Image/type-c.ts
================================================
import { shortenText } from "@majoexe/util/functions/util";
import { loadImage, createCanvas } from "@napi-rs/canvas";
import { ApplicationCommandType, ApplicationCommandOptionType, AttachmentBuilder, EmbedBuilder, InteractionContextType, ApplicationIntegrationType } from "discord.js";
import type { SlashCommand } from "@/util/types/Command";

export default {
  name: "type-c",
  description: "⚡ Type C for fast charging",
  type: ApplicationCommandType.ChatInput,
  cooldown: 5000,
  contexts: [InteractionContextType.Guild, InteractionContextType.BotDM, InteractionContextType.PrivateChannel],
  integrationTypes: [ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.UserInstall],
  usage: "/type-c [user]",
  options: [
    {
      name: "user",
      description: "User to put in the image",
      type: ApplicationCommandOptionType.User,
      required: false,
    },
  ],
  run: async (client, interaction, guildSettings) => {
    try {
      const user = interaction.options.getUser("user") || interaction.user;

      if (!user.displayAvatarURL({ size: 2048, extension: "png", forceStatic: true })) {
        return client.errorMessages.createSlashError(interaction, "❌ The user must have an avatar.");
      }

      const image = user.displayAvatarURL({
        size: 2048,
        extension: "png",
        forceStatic: true,
      });

      const [toFetch] = image.split("?");
      if (!toFetch || toFetch.length < 1) return client.errorMessages.createSlashError(interaction, "❌ The image URL is invalid.");
      const targetImage = await loadImage(toFetch);
      const background = await loadImage("./util/images/files/type-c.jpg");

      const canvas = createCanvas(background.width, background.height);
      const context = canvas.getContext("2d");

      const firstText = shortenText(user.globalName || user.username, 20);

      context.drawImage(background, 0, 0);
      context.save();
      context.beginPath();
      context.arc(27 + 72, 1113 + 72, 72, 0, Math.PI * 2, true);
      context.closePath();
      context.clip();
      context.drawImage(targetImage, 28, 1114, 145, 145);
      context.restore();
      context.font = "42px helvetica-neue-regular";
      const firstTextWidth = context.measureText(firstText).width;

      context.font = "36px helvetica-neue-regular";
      const secondText = `@${user.username} ∙ 5m ago`;
      const secondTextWidth = context.measureText(secondText).width;

      const totalWidth =
Download .txt
gitextract_ftazrc3x/

├── .dockerignore
├── .github/
│   ├── codeowners
│   ├── renovate.json
│   └── workflows/
│       ├── codeql-analysis.yml
│       ├── format-check.yml
│       └── lint.yml
├── .gitignore
├── .npmrc
├── .prettierignore
├── CONTRIBUTING.md
├── README.md
├── apps/
│   ├── bot/
│   │   ├── .env.example
│   │   ├── .prettierignore
│   │   ├── Dockerfile
│   │   ├── README.md
│   │   ├── commands/
│   │   │   ├── Fun/
│   │   │   │   ├── 8ball.ts
│   │   │   │   ├── advice.ts
│   │   │   │   ├── anime.ts
│   │   │   │   ├── cat.ts
│   │   │   │   ├── comic.ts
│   │   │   │   ├── dice.ts
│   │   │   │   ├── flip.ts
│   │   │   │   ├── iq.ts
│   │   │   │   ├── joke.ts
│   │   │   │   ├── letmegpt.ts
│   │   │   │   ├── lmgtfy.ts
│   │   │   │   ├── meme.ts
│   │   │   │   ├── rate.ts
│   │   │   │   ├── ship.ts
│   │   │   │   └── why.ts
│   │   │   ├── General/
│   │   │   │   ├── about.ts
│   │   │   │   ├── contact.ts
│   │   │   │   ├── dashboard.ts
│   │   │   │   ├── donate.ts
│   │   │   │   ├── help.ts
│   │   │   │   ├── invite.ts
│   │   │   │   ├── opensource.ts
│   │   │   │   ├── permissions.ts
│   │   │   │   ├── ping.ts
│   │   │   │   ├── servers.ts
│   │   │   │   ├── suggestion.ts
│   │   │   │   └── uptime.ts
│   │   │   ├── Giveaway/
│   │   │   │   └── giveaway.ts
│   │   │   ├── Image/
│   │   │   │   ├── achievement.ts
│   │   │   │   ├── ai.ts
│   │   │   │   ├── bangladesh.ts
│   │   │   │   ├── change-my-mind.ts
│   │   │   │   ├── dog-say.ts
│   │   │   │   ├── fbi.ts
│   │   │   │   ├── flag.ts
│   │   │   │   ├── galaxy-note.ts
│   │   │   │   ├── image.ts
│   │   │   │   ├── iq-graph.ts
│   │   │   │   ├── jail.ts
│   │   │   │   ├── note.ts
│   │   │   │   ├── ph-comment.ts
│   │   │   │   ├── sonic-says.ts
│   │   │   │   ├── trash.ts
│   │   │   │   ├── trigger.ts
│   │   │   │   ├── type-c.ts
│   │   │   │   └── yt-comment.ts
│   │   │   ├── Levels/
│   │   │   │   ├── leaderboard.ts
│   │   │   │   ├── rank.ts
│   │   │   │   ├── reset-xp.ts
│   │   │   │   └── xp-settings.ts
│   │   │   ├── Moderation/
│   │   │   │   ├── automod.ts
│   │   │   │   ├── emoji.ts
│   │   │   │   ├── leave.ts
│   │   │   │   ├── logs.ts
│   │   │   │   ├── member.ts
│   │   │   │   ├── role.ts
│   │   │   │   ├── slowmode.ts
│   │   │   │   ├── statistics.ts
│   │   │   │   ├── warn.ts
│   │   │   │   └── welcome.ts
│   │   │   ├── Reputation/
│   │   │   │   └── rep.ts
│   │   │   └── Utility/
│   │   │       ├── ascii.ts
│   │   │       ├── base64.ts
│   │   │       ├── color.ts
│   │   │       ├── minecraft.ts
│   │   │       ├── qrcode.ts
│   │   │       └── translate.ts
│   │   ├── events/
│   │   │   ├── client/
│   │   │   │   ├── GuildCreate.ts
│   │   │   │   ├── GuildDelete.ts
│   │   │   │   └── clientReady.ts
│   │   │   └── guild/
│   │   │       ├── channelCreate.ts
│   │   │       ├── channelDelete.ts
│   │   │       ├── channelPinsUpdate.ts
│   │   │       ├── channelUpdate.ts
│   │   │       ├── emojiCreate.ts
│   │   │       ├── emojiDelete.ts
│   │   │       ├── emojiUpdate.ts
│   │   │       ├── guildBanAdd.ts
│   │   │       ├── guildBanRemove.ts
│   │   │       ├── guildMemberAdd.ts
│   │   │       ├── guildMemberRemove.ts
│   │   │       ├── guildUpdate.ts
│   │   │       ├── interactionCreate.ts
│   │   │       ├── inviteCreate.ts
│   │   │       ├── inviteDelete.ts
│   │   │       ├── messageBulkDelete.ts
│   │   │       ├── messageCreate.ts
│   │   │       ├── messageDelete.ts
│   │   │       ├── messageUpdate.ts
│   │   │       ├── roleCreate.ts
│   │   │       ├── roleDelete.ts
│   │   │       ├── roleUpdate.ts
│   │   │       ├── stickerCreate.ts
│   │   │       ├── stickerDelete.ts
│   │   │       └── stickerUpdate.ts
│   │   ├── index.ts
│   │   ├── modals/
│   │   │   └── suggestion.ts
│   │   ├── package.json
│   │   ├── tsconfig.json
│   │   └── util/
│   │       ├── giveaway/
│   │       │   ├── core.ts
│   │       │   ├── endGiveaway.ts
│   │       │   ├── findGiveaways.ts
│   │       │   ├── pauseGiveaway.ts
│   │       │   ├── rerollGiveaway.ts
│   │       │   ├── resumeGiveaway.ts
│   │       │   └── startGiveaway.ts
│   │       ├── images/
│   │       │   ├── createUserGuildCard.ts
│   │       │   └── createXPCard.ts
│   │       ├── loaders/
│   │       │   ├── loadCommands.ts
│   │       │   ├── loadEmojis.ts
│   │       │   ├── loadEvents.ts
│   │       │   ├── loadFonts.ts
│   │       │   └── loadModals.ts
│   │       ├── moderation/
│   │       │   ├── automod/
│   │       │   │   ├── antiBadWords/
│   │       │   │   │   ├── disable.ts
│   │       │   │   │   └── enable.ts
│   │       │   │   ├── antiInvite/
│   │       │   │   │   ├── disable.ts
│   │       │   │   │   └── enable.ts
│   │       │   │   ├── antiLinks/
│   │       │   │   │   ├── disable.ts
│   │       │   │   │   └── enable.ts
│   │       │   │   ├── antiMention/
│   │       │   │   │   ├── disable.ts
│   │       │   │   │   └── enable.ts
│   │       │   │   ├── antiSpam/
│   │       │   │   │   ├── disable.ts
│   │       │   │   │   └── enable.ts
│   │       │   │   ├── index.ts
│   │       │   │   └── settings/
│   │       │   │       └── index.ts
│   │       │   ├── ban.ts
│   │       │   ├── changeMemberNickname.ts
│   │       │   ├── getMemberImages.ts
│   │       │   ├── getMemberInfo.ts
│   │       │   ├── kick.ts
│   │       │   └── unban.ts
│   │       └── types/
│   │           └── Command.ts
│   └── dashboard/
│       ├── .env.example
│       ├── .gitignore
│       ├── .prettierignore
│       ├── README.md
│       ├── app/
│       │   ├── _components/
│       │   │   ├── AddReaction.tsx
│       │   │   ├── BotReplacement.tsx
│       │   │   ├── ExampleChart.tsx
│       │   │   ├── LevelUp.tsx
│       │   │   └── Notifications.tsx
│       │   ├── api/
│       │   │   ├── auth/
│       │   │   │   └── [...nextauth]/
│       │   │   │       └── route.ts
│       │   │   ├── cron/
│       │   │   │   └── cleanup/
│       │   │   │       └── route.ts
│       │   │   ├── invite/
│       │   │   │   ├── [invite]/
│       │   │   │   │   └── route.ts
│       │   │   │   └── route.ts
│       │   │   ├── logs/
│       │   │   │   └── [serverId]/
│       │   │   │       └── route.ts
│       │   │   ├── settings/
│       │   │   │   ├── automod/
│       │   │   │   │   ├── anti-invite/
│       │   │   │   │   │   └── route.ts
│       │   │   │   │   ├── anti-link/
│       │   │   │   │   │   └── route.ts
│       │   │   │   │   ├── anti-mention/
│       │   │   │   │   │   └── route.ts
│       │   │   │   │   └── anti-spam/
│       │   │   │   │       └── route.ts
│       │   │   │   ├── categories/
│       │   │   │   │   └── route.ts
│       │   │   │   ├── change-reputation/
│       │   │   │   │   └── route.ts
│       │   │   │   ├── commands/
│       │   │   │   │   └── route.ts
│       │   │   │   ├── delete-data/
│       │   │   │   │   └── route.ts
│       │   │   │   ├── download/
│       │   │   │   │   └── [id]/
│       │   │   │   │       └── route.ts
│       │   │   │   ├── embed-color/
│       │   │   │   │   └── route.ts
│       │   │   │   ├── messages/
│       │   │   │   │   ├── leave/
│       │   │   │   │   │   └── route.ts
│       │   │   │   │   └── welcome/
│       │   │   │   │       └── route.ts
│       │   │   │   ├── public-dashboard/
│       │   │   │   │   └── route.ts
│       │   │   │   ├── public-vanity/
│       │   │   │   │   └── route.ts
│       │   │   │   ├── reset-user-xp/
│       │   │   │   │   └── route.ts
│       │   │   │   └── update-logs/
│       │   │   │       └── route.ts
│       │   │   ├── user/
│       │   │   │   ├── avatar/
│       │   │   │   │   └── [id]/
│       │   │   │   │       └── route.ts
│       │   │   │   ├── avatar-decoration/
│       │   │   │   │   └── [id]/
│       │   │   │   │       └── route.ts
│       │   │   │   ├── banner/
│       │   │   │   │   └── [id]/
│       │   │   │   │       └── route.ts
│       │   │   │   ├── delete/
│       │   │   │   │   └── route.ts
│       │   │   │   └── download/
│       │   │   │       └── route.ts
│       │   │   └── warns/
│       │   │       └── [serverId]/
│       │   │           └── [warnId]/
│       │   │               └── route.ts
│       │   ├── auth/
│       │   │   ├── error/
│       │   │   │   └── page.tsx
│       │   │   └── login/
│       │   │       └── page.tsx
│       │   ├── commands/
│       │   │   └── page.tsx
│       │   ├── dashboard/
│       │   │   ├── [server]/
│       │   │   │   ├── automod/
│       │   │   │   │   ├── components/
│       │   │   │   │   │   ├── AntiInvite.tsx
│       │   │   │   │   │   ├── AntiLink.tsx
│       │   │   │   │   │   ├── AntiMention.tsx
│       │   │   │   │   │   ├── AntiSpam.tsx
│       │   │   │   │   │   ├── DeleteMessage.tsx
│       │   │   │   │   │   ├── Limit.tsx
│       │   │   │   │   │   ├── LogChannel.tsx
│       │   │   │   │   │   └── TimeoutMember.tsx
│       │   │   │   │   ├── loading.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── dashboard-logs/
│       │   │   │   │   ├── components/
│       │   │   │   │   │   └── Logs.tsx
│       │   │   │   │   ├── loading.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── giveaways/
│       │   │   │   │   ├── components/
│       │   │   │   │   │   └── Giveaways.tsx
│       │   │   │   │   ├── loading.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── layout.tsx
│       │   │   │   ├── leaderboard/
│       │   │   │   │   ├── components/
│       │   │   │   │   │   └── Leaderboard.tsx
│       │   │   │   │   ├── loading.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── loading.tsx
│       │   │   │   ├── logs/
│       │   │   │   │   ├── components/
│       │   │   │   │   │   ├── UpdateLogs.tsx
│       │   │   │   │   │   └── handleLogText.ts
│       │   │   │   │   ├── loading.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── messages/
│       │   │   │   │   ├── components/
│       │   │   │   │   │   └── ChangeCustomMessages.tsx
│       │   │   │   │   ├── loading.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── modules/
│       │   │   │   │   ├── loading.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── page.tsx
│       │   │   │   ├── settings/
│       │   │   │   │   ├── components/
│       │   │   │   │   │   ├── ChangeEmbedColor.tsx
│       │   │   │   │   │   ├── DeleteServerData.tsx
│       │   │   │   │   │   └── PublicDashboard.tsx
│       │   │   │   │   ├── loading.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── statistics/
│       │   │   │   │   ├── components/
│       │   │   │   │   │   └── StatisticCharts.tsx
│       │   │   │   │   ├── loading.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── user/
│       │   │   │   │   ├── [id]/
│       │   │   │   │   │   ├── loading.tsx
│       │   │   │   │   │   └── page.tsx
│       │   │   │   │   └── components/
│       │   │   │   │       ├── ChangeUserReputation.tsx
│       │   │   │   │       └── ResetUserXP.tsx
│       │   │   │   └── warns/
│       │   │   │       ├── components/
│       │   │   │       │   └── Warns.tsx
│       │   │   │       ├── loading.tsx
│       │   │   │       └── page.tsx
│       │   │   ├── loading.tsx
│       │   │   └── page.tsx
│       │   ├── error.tsx
│       │   ├── layout.tsx
│       │   ├── legal/
│       │   │   ├── layout.tsx
│       │   │   ├── privacy-policy/
│       │   │   │   └── page.mdx
│       │   │   └── terms-of-service/
│       │   │       └── page.mdx
│       │   ├── not-found.tsx
│       │   ├── opengraph-image.tsx
│       │   ├── page.tsx
│       │   ├── robots.ts
│       │   ├── server/
│       │   │   └── [server]/
│       │   │       ├── layout.tsx
│       │   │       ├── loading.tsx
│       │   │       └── page.tsx
│       │   ├── sitemap.ts
│       │   └── user/
│       │       ├── components/
│       │       │   └── DeleteUserData.tsx
│       │       └── profile/
│       │           └── page.tsx
│       ├── components/
│       │   ├── CategoryBar.tsx
│       │   ├── DiscordEmojis.tsx
│       │   ├── DiscordLogin.tsx
│       │   ├── Footer.tsx
│       │   ├── Hotjar.tsx
│       │   ├── LoginButton.tsx
│       │   ├── Session.tsx
│       │   ├── TailwindIndicator.tsx
│       │   ├── client/
│       │   │   ├── charts/
│       │   │   │   └── ServerStatsChart.tsx
│       │   │   └── commands/
│       │   │       ├── DiscordCommands.tsx
│       │   │       ├── UpdateCategories.tsx
│       │   │       └── UpdateCommands.tsx
│       │   ├── nav/
│       │   │   ├── GuildMenuDropdown.tsx
│       │   │   ├── ProgressBar.tsx
│       │   │   ├── SideMenuControl.tsx
│       │   │   ├── SideNavigation.tsx
│       │   │   ├── TopNavigation.tsx
│       │   │   ├── UserMenuDropdown.tsx
│       │   │   └── VisibilityContext.tsx
│       │   └── ui/
│       │       ├── Accordion.tsx
│       │       ├── Badge.tsx
│       │       ├── Block.tsx
│       │       ├── Buttons.tsx
│       │       ├── ChannelsSelect.tsx
│       │       ├── Chart.tsx
│       │       ├── Command.tsx
│       │       ├── Dialog.tsx
│       │       ├── Disclosure.tsx
│       │       ├── DropdownMenu.tsx
│       │       ├── Embed.tsx
│       │       ├── GraphCard.tsx
│       │       ├── Headers.tsx
│       │       ├── Icons.tsx
│       │       ├── Image.tsx
│       │       ├── Input.tsx
│       │       ├── Loaders.tsx
│       │       ├── Popover.tsx
│       │       ├── RolesSelect.tsx
│       │       ├── Select.tsx
│       │       ├── Skeletons.tsx
│       │       ├── SparkChart.tsx
│       │       ├── Switch.tsx
│       │       ├── Table.tsx
│       │       ├── TimeSelect.tsx
│       │       ├── Tooltip.tsx
│       │       ├── ViewSelect.tsx
│       │       └── effects/
│       │           ├── AnimatedBeam.tsx
│       │           ├── AnimatedList.tsx
│       │           ├── AnimatedShinyText.tsx
│       │           ├── BorderBeam.tsx
│       │           ├── FadeText.tsx
│       │           ├── FlickeringGrid.tsx
│       │           ├── Globe.tsx
│       │           ├── Meteors.tsx
│       │           ├── NumberTicker.tsx
│       │           ├── Particles.tsx
│       │           ├── Ripple.tsx
│       │           └── WordPullUp.tsx
│       ├── env.ts
│       ├── eslint.config.ts
│       ├── jsconfig.json
│       ├── lib/
│       │   ├── authOptions.ts
│       │   ├── session.ts
│       │   ├── types.ts
│       │   └── utils.ts
│       ├── mdx-components.tsx
│       ├── next.config.ts
│       ├── package.json
│       ├── postcss.config.mjs
│       ├── styles/
│       │   └── globals.css
│       ├── tsconfig.json
│       └── vercel.json
├── docker-compose.yaml
├── eslint.config.ts
├── license.md
├── package.json
├── packages/
│   ├── config/
│   │   ├── .prettierignore
│   │   ├── configs/
│   │   │   ├── bot.ts
│   │   │   ├── dashboard.ts
│   │   │   ├── debugger.ts
│   │   │   ├── global.ts
│   │   │   └── permissions.ts
│   │   ├── index.ts
│   │   ├── package.json
│   │   └── tsconfig.json
│   ├── database/
│   │   ├── .env.example
│   │   ├── .prettierignore
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── prisma/
│   │   │   ├── migrations/
│   │   │   │   ├── 20230516174916_/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516200625_add_auth/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516201206_add_discord_schema/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516202208_save_only_required/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516202300_bigint_for_flags/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516202517_make_email_unique/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516202902_fix_unique/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516210849_add_maps/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516211309_add_verification_token/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516212035_fix_unique_values/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516212254_switch_datatype_nitro/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230516212512_add_email_verified/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230521135936_add_suggestions/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230521142039_add_guild_id/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230521143031_add_guild_model/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230521184416_add_guild_logs/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230521185323_fix_guild_logs/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230521221630_add_avatar/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230522210912_link_user_to_logs/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230528212858_add_embed_color/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230529160641_add_ratelimit_for_server_change/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230604182342_add_guild_xp/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230609200921_migrate_to_discord_handles/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230610181051_update_account/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230610195213_update_rows_names/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230716165214_add_guild_joins/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230807093042_add_reputation/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230807100800_fix_user_fields/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230809192933_add_giveaways/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230809193154_change_giveaways_name/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230810131104_add_channel_id/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230810131904_remove_channel_id/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230813164922_add_messages_count/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230829161606_add_xp_settings/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20230901110432_add_vanity_urls/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231008115944_add_guild_controlled_commands/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231008120512_fix_commands/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231008120900_add_default_options/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231008143223_update_default_member_permissions/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231008163839_fix_fields/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231008165157_remove_perms_and_created_at/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231008170130_update_command_categories/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231008171003_fix_schema/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231015105007_remove_email_adresses/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231017181219_fix_user_emails/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231018085005_add_automod_rules/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231030220258_add_warning_system/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231030222116_fix_ids/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231030230714_add_created_by_id_to_warnings/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231031083245_add_warn_id/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231117165927_add_last_login_field/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231119203658_remove_enabled_disable_state_from_automod/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231216135714_add_welcome_and_leave_messages/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231216145835_remove_unused_fields/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231218000910_add_titles_and_descriptions_for_custom_messages/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20231228221226_add_embed_color_and_enabled_state/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20241209125259_add_better_logs/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20241209132307_add_vanity_update_event/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20241209140053_add_giveaway_events/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20241220180643_add_guild_settings/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20241220180800_change_name_of_guild_logs_settings/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20241220181109_add_type_as_unique/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20241221205356_remove_not_used_log_types/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20241228112527_allow_channel_id_to_be_null/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20241228131412_add_log_update_event/
│   │   │   │   │   └── migration.sql
│   │   │   │   ├── 20241231150633_remove_message_polls/
│   │   │   │   │   └── migration.sql
│   │   │   │   └── migration_lock.toml
│   │   │   └── schema.prisma
│   │   ├── prisma.config.ts
│   │   ├── src/
│   │   │   ├── client.ts
│   │   │   ├── logger.ts
│   │   │   ├── redis/
│   │   │   │   ├── cache.ts
│   │   │   │   └── client.ts
│   │   │   ├── seed.ts
│   │   │   └── types.ts
│   │   └── tsconfig.json
│   ├── typescript-config/
│   │   ├── base.json
│   │   ├── index.ts
│   │   └── package.json
│   └── utils/
│       ├── .prettierignore
│       ├── content/
│       │   ├── advices.json
│       │   └── why.json
│       ├── database/
│       │   ├── index.ts
│       │   ├── logs/
│       │   │   ├── createLog.ts
│       │   │   ├── events.ts
│       │   │   ├── fetchLogs.ts
│       │   │   └── getGuildLogSettings.ts
│       │   ├── moderation/
│       │   │   ├── automod/
│       │   │   │   ├── createDatabaseAutoModRule.ts
│       │   │   │   ├── deleteDatabaseAutoModRule.ts
│       │   │   │   ├── fetchDatabaseAutoModRules.ts
│       │   │   │   ├── index.ts
│       │   │   │   ├── syncDatabaseAutoModRule.ts
│       │   │   │   └── updateDatabaseAutoModRule.ts
│       │   │   └── warn/
│       │   │       ├── clearWarns.ts
│       │   │       ├── listWarns.ts
│       │   │       ├── removeWarn.ts
│       │   │       └── warnUser.ts
│       │   ├── reputation/
│       │   │   ├── checkReputation.ts
│       │   │   ├── giveReputation.ts
│       │   │   ├── setReputation.ts
│       │   │   └── takeReputation.ts
│       │   ├── settings/
│       │   │   └── XPSettings.ts
│       │   ├── user/
│       │   │   └── createUser.ts
│       │   └── xp/
│       │       ├── checkXP.ts
│       │       └── resetXP.ts
│       ├── embeds/
│       │   ├── createErrorEmbed.ts
│       │   └── index.ts
│       ├── functions/
│       │   ├── automod/
│       │   │   ├── createDiscordAutoModRule.ts
│       │   │   ├── deleteDiscordAutoModRule.ts
│       │   │   ├── fetchDiscordAutoModRules.ts
│       │   │   ├── index.ts
│       │   │   ├── types.ts
│       │   │   ├── validateAutoModIgnores.ts
│       │   │   └── validateAutoModRuleActions.ts
│       │   ├── files/
│       │   │   ├── index.ts
│       │   │   └── readDir.ts
│       │   ├── guild/
│       │   │   ├── getGuild.ts
│       │   │   ├── getGuildChannels.ts
│       │   │   ├── getGuildFromMemberGuilds.ts
│       │   │   ├── getGuildPreview.ts
│       │   │   ├── getGuildRoles.ts
│       │   │   ├── getMemberGuilds.ts
│       │   │   ├── index.ts
│       │   │   └── isBotInServer.ts
│       │   ├── user/
│       │   │   ├── getDiscordUser.ts
│       │   │   ├── getFlags.ts
│       │   │   ├── getPermissionNames.ts
│       │   │   ├── index.ts
│       │   │   └── isApiUser.ts
│       │   └── util/
│       │       ├── adjustColor.ts
│       │       ├── capitalize.ts
│       │       ├── fillMissingDates.ts
│       │       ├── flipText.ts
│       │       ├── formatDate.ts
│       │       ├── formatDuration.ts
│       │       ├── formatNumber.ts
│       │       ├── generateDates.ts
│       │       ├── index.ts
│       │       ├── isNumeric.ts
│       │       ├── logger.ts
│       │       ├── percentageBar.ts
│       │       ├── randomness.ts
│       │       ├── shortenText.ts
│       │       ├── splitCamelCase.ts
│       │       └── sumArray.ts
│       ├── images/
│       │   ├── index.ts
│       │   ├── invertColor.ts
│       │   └── linesHelper.ts
│       ├── package.json
│       └── tsconfig.json
├── pnpm-workspace.yaml
├── prettier.config.js
├── tsconfig.json
└── turbo.json
Download .txt
SYMBOL INDEX (396 symbols across 296 files)

FILE: apps/bot/commands/Fun/joke.ts
  type Joke (line 5) | interface Joke {

FILE: apps/bot/commands/Fun/meme.ts
  type RedditPost (line 5) | interface RedditPost {
  type RedditChildren (line 11) | interface RedditChildren {
  type RedditData (line 15) | interface RedditData {
  type RedditResponse (line 19) | interface RedditResponse {

FILE: apps/bot/commands/General/donate.ts
  type DonateLink (line 4) | interface DonateLink {

FILE: apps/bot/commands/General/help.ts
  type Category (line 17) | interface Category {

FILE: apps/bot/commands/General/opensource.ts
  type GithubResponse (line 5) | interface GithubResponse {

FILE: apps/bot/commands/General/permissions.ts
  function convertCamelCaseToWords (line 4) | function convertCamelCaseToWords(text: string) {

FILE: apps/bot/commands/Moderation/statistics.ts
  function generateChart (line 19) | async function generateChart(data: GuildJoin[] | GuildLeave[] | GuildMes...

FILE: apps/bot/commands/Utility/minecraft.ts
  type MinecraftServer (line 5) | interface MinecraftServer {

FILE: apps/bot/commands/Utility/translate.ts
  type Translator (line 6) | type Translator = typeof translate & {

FILE: apps/bot/events/client/GuildCreate.ts
  function GuildCreate (line 5) | async function GuildCreate({ guild }: { guild: Guild }): Promise<void> {

FILE: apps/bot/events/client/GuildDelete.ts
  function GuildDelete (line 5) | async function GuildDelete({ guild }: { guild: Guild }): Promise<void> {

FILE: apps/bot/events/client/clientReady.ts
  function clientReady (line 6) | async function clientReady(client: Majobot) {

FILE: apps/bot/events/guild/channelCreate.ts
  function channelCreate (line 6) | async function channelCreate(client: Majobot, channel: NonThreadGuildBas...

FILE: apps/bot/events/guild/channelDelete.ts
  function channelDelete (line 6) | async function channelDelete(client: Majobot, channel: DMChannel | NonTh...

FILE: apps/bot/events/guild/channelPinsUpdate.ts
  function channelPinsUpdate (line 6) | async function channelPinsUpdate(client: Majobot, channel: NonThreadGuil...

FILE: apps/bot/events/guild/channelUpdate.ts
  function channelUpdate (line 6) | async function channelUpdate(client: Majobot, oldChannel: DMChannel | No...

FILE: apps/bot/events/guild/emojiCreate.ts
  function emojiCreate (line 6) | async function emojiCreate(client: Majobot, emoji: GuildEmoji) {

FILE: apps/bot/events/guild/emojiDelete.ts
  function emojiDelete (line 6) | async function emojiDelete(client: Majobot, emoji: GuildEmoji) {

FILE: apps/bot/events/guild/emojiUpdate.ts
  function emojiUpdate (line 6) | async function emojiUpdate(client: Majobot, oldEmoji: GuildEmoji, newEmo...

FILE: apps/bot/events/guild/guildBanAdd.ts
  function guildBanAdd (line 6) | async function guildBanAdd(client: Majobot, ban: GuildBan) {

FILE: apps/bot/events/guild/guildBanRemove.ts
  function guildBanRemove (line 6) | async function guildBanRemove(client: Majobot, ban: GuildBan) {

FILE: apps/bot/events/guild/guildMemberAdd.ts
  function guildMemberAdd (line 7) | async function guildMemberAdd(client: Majobot, member: GuildMember): Pro...

FILE: apps/bot/events/guild/guildMemberRemove.ts
  function guildMemberRemove (line 7) | async function guildMemberRemove(client: Majobot, member: GuildMember): ...

FILE: apps/bot/events/guild/guildUpdate.ts
  function guildUpdate (line 6) | async function guildUpdate(client: Majobot, oldGuild: Guild, newGuild: G...

FILE: apps/bot/events/guild/interactionCreate.ts
  function interactionCreate (line 8) | async function interactionCreate(client: Majobot, interaction: Interacti...

FILE: apps/bot/events/guild/inviteCreate.ts
  function inviteCreate (line 6) | async function inviteCreate(client: Majobot, invite: Invite) {

FILE: apps/bot/events/guild/inviteDelete.ts
  function inviteDelete (line 6) | async function inviteDelete(client: Majobot, invite: Invite) {

FILE: apps/bot/events/guild/messageBulkDelete.ts
  function messageBulkDelete (line 6) | async function messageBulkDelete(client: Majobot, messages: Collection<s...

FILE: apps/bot/events/guild/messageCreate.ts
  function messageCreate (line 8) | async function messageCreate(client: Majobot, message: Message): Promise...

FILE: apps/bot/events/guild/messageDelete.ts
  function messageDelete (line 6) | async function messageDelete(client: Majobot, message: Message): Promise...

FILE: apps/bot/events/guild/messageUpdate.ts
  function messageUpdate (line 6) | async function messageUpdate(client: Majobot, oldMessage: Message, newMe...

FILE: apps/bot/events/guild/roleCreate.ts
  function roleCreate (line 6) | async function roleCreate(client: Majobot, role: Role) {

FILE: apps/bot/events/guild/roleDelete.ts
  function roleDelete (line 6) | async function roleDelete(client: Majobot, role: Role) {

FILE: apps/bot/events/guild/roleUpdate.ts
  function roleUpdate (line 6) | async function roleUpdate(client: Majobot, oldRole: Role, newRole: Role) {

FILE: apps/bot/events/guild/stickerCreate.ts
  function stickerCreate (line 6) | async function stickerCreate(client: Majobot, sticker: Sticker) {

FILE: apps/bot/events/guild/stickerDelete.ts
  function stickerDelete (line 6) | async function stickerDelete(client: Majobot, sticker: Sticker) {

FILE: apps/bot/events/guild/stickerUpdate.ts
  function stickerUpdate (line 6) | async function stickerUpdate(client: Majobot, oldSticker: Sticker, newSt...

FILE: apps/bot/index.ts
  class Majobot (line 24) | class Majobot extends Client {

FILE: apps/bot/util/giveaway/core.ts
  function giveaway (line 8) | function giveaway(client: Majobot) {

FILE: apps/bot/util/giveaway/endGiveaway.ts
  function EndGiveaway (line 7) | async function EndGiveaway(client: Majobot, interaction: ChatInputComman...

FILE: apps/bot/util/giveaway/findGiveaways.ts
  function FindGiveaways (line 6) | async function FindGiveaways(client: Majobot, interaction: ChatInputComm...

FILE: apps/bot/util/giveaway/pauseGiveaway.ts
  function PauseGiveaway (line 7) | async function PauseGiveaway(client: Majobot, interaction: ChatInputComm...

FILE: apps/bot/util/giveaway/rerollGiveaway.ts
  function RerollGiveaway (line 7) | async function RerollGiveaway(client: Majobot, interaction: ChatInputCom...

FILE: apps/bot/util/giveaway/resumeGiveaway.ts
  function ResumeGiveaway (line 7) | async function ResumeGiveaway(client: Majobot, interaction: ChatInputCom...

FILE: apps/bot/util/giveaway/startGiveaway.ts
  function StartGiveaway (line 7) | async function StartGiveaway(client: Majobot, interaction: ChatInputComm...
  function StartDropGiveaway (line 86) | async function StartDropGiveaway(client: Majobot, interaction: ChatInput...

FILE: apps/bot/util/images/createUserGuildCard.ts
  function createUserGuildCard (line 5) | async function createUserGuildCard(user: User, guild: Guild): Promise<Bu...

FILE: apps/bot/util/images/createXPCard.ts
  function calculateProgress (line 5) | function calculateProgress(currentXp: number, requiredXp: number): number {
  function createXPCard (line 17) | async function createXPCard(user: User, xp: { xp: number; xpNeeded: numb...

FILE: apps/bot/util/loaders/loadCommands.ts
  function loadCommands (line 6) | async function loadCommands(client: Majobot): Promise<void> {

FILE: apps/bot/util/loaders/loadEmojis.ts
  function uploadEmoji (line 47) | async function uploadEmoji(clientId: string, client: Majobot, { name, im...
  function loadEmojis (line 90) | async function loadEmojis(client: Majobot): Promise<void> {

FILE: apps/bot/util/loaders/loadEvents.ts
  function loadEvents (line 6) | async function loadEvents(client: Majobot): Promise<void> {

FILE: apps/bot/util/loaders/loadFonts.ts
  function loadFonts (line 5) | async function loadFonts(client: Majobot): Promise<void> {

FILE: apps/bot/util/loaders/loadModals.ts
  type Modal (line 5) | interface Modal {
  function loadModals (line 10) | async function loadModals(client: Majobot): Promise<void> {

FILE: apps/bot/util/moderation/automod/antiBadWords/disable.ts
  function disableAntiBadWords (line 6) | async function disableAntiBadWords(client: Majobot, interaction: ChatInp...

FILE: apps/bot/util/moderation/automod/antiBadWords/enable.ts
  function enableAntiBadWords (line 19) | async function enableAntiBadWords(client: Majobot, interaction: ChatInpu...

FILE: apps/bot/util/moderation/automod/antiInvite/disable.ts
  function disableAntiInvite (line 6) | async function disableAntiInvite(client: Majobot, interaction: ChatInput...

FILE: apps/bot/util/moderation/automod/antiInvite/enable.ts
  function enableAntiInvite (line 18) | async function enableAntiInvite(client: Majobot, interaction: ChatInputC...

FILE: apps/bot/util/moderation/automod/antiLinks/disable.ts
  function disableAntiLink (line 6) | async function disableAntiLink(client: Majobot, interaction: ChatInputCo...

FILE: apps/bot/util/moderation/automod/antiLinks/enable.ts
  function enableAntiLink (line 18) | async function enableAntiLink(client: Majobot, interaction: ChatInputCom...

FILE: apps/bot/util/moderation/automod/antiMention/disable.ts
  function disableAntiMention (line 6) | async function disableAntiMention(client: Majobot, interaction: ChatInpu...

FILE: apps/bot/util/moderation/automod/antiMention/enable.ts
  function enableAntiMention (line 18) | async function enableAntiMention(client: Majobot, interaction: ChatInput...

FILE: apps/bot/util/moderation/automod/antiSpam/disable.ts
  function disableAntiSpam (line 6) | async function disableAntiSpam(client: Majobot, interaction: ChatInputCo...

FILE: apps/bot/util/moderation/automod/antiSpam/enable.ts
  function enableAntiSpam (line 18) | async function enableAntiSpam(client: Majobot, interaction: ChatInputCom...

FILE: apps/bot/util/moderation/automod/settings/index.ts
  function autoModSettings (line 6) | async function autoModSettings(client: Majobot, interaction: ChatInputCo...

FILE: apps/bot/util/moderation/ban.ts
  function banMember (line 4) | async function banMember(client: Majobot, interaction: ChatInputCommandI...

FILE: apps/bot/util/moderation/changeMemberNickname.ts
  function changememberNickname (line 4) | async function changememberNickname(client: Majobot, interaction: ChatIn...

FILE: apps/bot/util/moderation/getMemberImages.ts
  function getUserAvatar (line 4) | async function getUserAvatar(client: Majobot, interaction: ChatInputComm...
  function getUserBanner (line 62) | async function getUserBanner(client: Majobot, interaction: ChatInputComm...

FILE: apps/bot/util/moderation/getMemberInfo.ts
  function getMemberInfo (line 4) | function getMemberInfo(client: Majobot, interaction: ChatInputCommandInt...

FILE: apps/bot/util/moderation/kick.ts
  function kickMember (line 4) | async function kickMember(client: Majobot, interaction: ChatInputCommand...

FILE: apps/bot/util/moderation/unban.ts
  function unBanMember (line 4) | async function unBanMember(client: Majobot, interaction: ChatInputComman...

FILE: apps/bot/util/types/Command.ts
  type GuildSettings (line 5) | interface GuildSettings extends Pick<Guild, "embedColor" | "publicPage" ...
  type ExtendedApplicationCommandOptionData (line 11) | type ExtendedApplicationCommandOptionData = ApplicationCommandOptionData...
  type SlashCommand (line 13) | interface SlashCommand extends ChatInputApplicationCommandData {

FILE: apps/dashboard/app/_components/AddReaction.tsx
  function AddReaction (line 8) | function AddReaction({ reaction, countL = 2 }: { reaction: string; count...

FILE: apps/dashboard/app/_components/BotReplacement.tsx
  function BotReplacement (line 19) | function BotReplacement({ className }: { className?: string }) {

FILE: apps/dashboard/app/_components/LevelUp.tsx
  type LevelUpProps (line 8) | interface LevelUpProps extends React.ComponentProps<"div"> {

FILE: apps/dashboard/app/api/cron/cleanup/route.ts
  function GET (line 7) | async function GET(request: NextRequest) {

FILE: apps/dashboard/app/api/invite/[invite]/route.ts
  function GET (line 5) | async function GET(request: NextRequest, props: { params: Promise<{ invi...

FILE: apps/dashboard/app/api/invite/route.ts
  function GET (line 5) | function GET() {

FILE: apps/dashboard/app/api/logs/[serverId]/route.ts
  function GET (line 6) | async function GET(request: NextRequest, props: { params: Promise<{ serv...

FILE: apps/dashboard/app/api/settings/automod/anti-invite/route.ts
  function POST (line 11) | async function POST(request: NextRequest) {

FILE: apps/dashboard/app/api/settings/automod/anti-link/route.ts
  function POST (line 11) | async function POST(request: NextRequest) {

FILE: apps/dashboard/app/api/settings/automod/anti-mention/route.ts
  function POST (line 11) | async function POST(request: NextRequest) {

FILE: apps/dashboard/app/api/settings/automod/anti-spam/route.ts
  function POST (line 11) | async function POST(request: NextRequest) {

FILE: apps/dashboard/app/api/settings/categories/route.ts
  function POST (line 8) | async function POST(request: NextRequest) {

FILE: apps/dashboard/app/api/settings/change-reputation/route.ts
  function POST (line 10) | async function POST(request: NextRequest) {

FILE: apps/dashboard/app/api/settings/commands/route.ts
  function POST (line 8) | async function POST(request: NextRequest) {

FILE: apps/dashboard/app/api/settings/delete-data/route.ts
  function POST (line 6) | async function POST(request: NextRequest) {

FILE: apps/dashboard/app/api/settings/download/[id]/route.ts
  function GET (line 6) | async function GET(request: NextRequest, props: { params: Promise<{ id: ...

FILE: apps/dashboard/app/api/settings/embed-color/route.ts
  function POST (line 10) | async function POST(request: NextRequest) {
  function PUT (line 201) | async function PUT(request: NextRequest) {

FILE: apps/dashboard/app/api/settings/messages/leave/route.ts
  function POST (line 10) | async function POST(request: NextRequest) {

FILE: apps/dashboard/app/api/settings/messages/welcome/route.ts
  function POST (line 12) | async function POST(request: NextRequest) {

FILE: apps/dashboard/app/api/settings/public-dashboard/route.ts
  function POST (line 8) | async function POST(request: NextRequest) {

FILE: apps/dashboard/app/api/settings/public-vanity/route.ts
  function POST (line 8) | async function POST(request: NextRequest) {

FILE: apps/dashboard/app/api/settings/reset-user-xp/route.ts
  function POST (line 7) | async function POST(request: NextRequest) {

FILE: apps/dashboard/app/api/settings/update-logs/route.ts
  function POST (line 11) | async function POST(request: NextRequest) {

FILE: apps/dashboard/app/api/user/avatar-decoration/[id]/route.ts
  function GET (line 5) | async function GET(request: NextRequest, props: { params: Promise<{ id: ...

FILE: apps/dashboard/app/api/user/avatar/[id]/route.ts
  function GET (line 5) | async function GET(request: NextRequest, props: { params: Promise<{ id: ...

FILE: apps/dashboard/app/api/user/banner/[id]/route.ts
  function GET (line 5) | async function GET(request: NextRequest, props: { params: Promise<{ id: ...

FILE: apps/dashboard/app/api/user/delete/route.ts
  function POST (line 5) | async function POST() {

FILE: apps/dashboard/app/api/user/download/route.ts
  function GET (line 7) | async function GET() {

FILE: apps/dashboard/app/api/warns/[serverId]/[warnId]/route.ts
  function DELETE (line 8) | async function DELETE(request: NextRequest, props: { params: Promise<{ s...

FILE: apps/dashboard/app/auth/error/page.tsx
  function ErrorPage (line 12) | async function ErrorPage(props: { searchParams: Promise<{ error: string ...

FILE: apps/dashboard/app/auth/login/page.tsx
  function LoginPage (line 18) | async function LoginPage(props: { searchParams: Promise<{ error: string ...

FILE: apps/dashboard/app/commands/page.tsx
  function CommandsPage (line 19) | async function CommandsPage() {

FILE: apps/dashboard/app/dashboard/[server]/automod/components/AntiInvite.tsx
  type AntiInviteProps (line 20) | interface AntiInviteProps {

FILE: apps/dashboard/app/dashboard/[server]/automod/components/AntiLink.tsx
  type AntiLinkProps (line 20) | interface AntiLinkProps {

FILE: apps/dashboard/app/dashboard/[server]/automod/components/AntiMention.tsx
  type AntiMentionProps (line 33) | interface AntiMentionProps {

FILE: apps/dashboard/app/dashboard/[server]/automod/components/AntiSpam.tsx
  type AntiSpamProps (line 19) | interface AntiSpamProps {

FILE: apps/dashboard/app/dashboard/[server]/automod/components/DeleteMessage.tsx
  type DeleteMessageProps (line 9) | interface DeleteMessageProps {

FILE: apps/dashboard/app/dashboard/[server]/automod/components/Limit.tsx
  type MentionSelectProps (line 30) | interface MentionSelectProps extends React.ComponentProps<typeof Select> {

FILE: apps/dashboard/app/dashboard/[server]/automod/components/LogChannel.tsx
  type LogChannelProps (line 8) | interface LogChannelProps {

FILE: apps/dashboard/app/dashboard/[server]/automod/components/TimeoutMember.tsx
  type TimeoutMemberProps (line 9) | interface TimeoutMemberProps {

FILE: apps/dashboard/app/dashboard/[server]/automod/loading.tsx
  function Loading (line 47) | function Loading() {

FILE: apps/dashboard/app/dashboard/[server]/automod/page.tsx
  function AutomodPage (line 26) | async function AutomodPage(props: { params: Promise<{ server: string }> ...

FILE: apps/dashboard/app/dashboard/[server]/dashboard-logs/components/Logs.tsx
  type LogItem (line 18) | interface LogItem extends Omit<GuildLogs, "createdAt"> {
  function LogDisclosure (line 23) | function LogDisclosure({ item, guildId, preview = false }: { item: LogIt...
  function Logs (line 82) | function Logs({ initialItems, server }: { initialItems: LogItem[]; serve...

FILE: apps/dashboard/app/dashboard/[server]/dashboard-logs/loading.tsx
  function Loading (line 8) | function Loading() {

FILE: apps/dashboard/app/dashboard/[server]/dashboard-logs/page.tsx
  function LogsPage (line 18) | async function LogsPage(props: { params: Promise<{ server: string }> }) {

FILE: apps/dashboard/app/dashboard/[server]/giveaways/components/Giveaways.tsx
  type Giveaway (line 16) | interface Giveaway {
  function Giveaways (line 35) | function Giveaways({ data = [] }: { data: Giveaway[] }) {

FILE: apps/dashboard/app/dashboard/[server]/giveaways/loading.tsx
  function Loading (line 7) | function Loading() {

FILE: apps/dashboard/app/dashboard/[server]/giveaways/page.tsx
  function GiveawaysPage (line 20) | async function GiveawaysPage(props: { params: Promise<{ server: string }...

FILE: apps/dashboard/app/dashboard/[server]/layout.tsx
  function generateMetadata (line 6) | function generateMetadata(): Metadata {
  function Layout (line 17) | async function Layout(props: { params: Promise<{ server: string }>; chil...

FILE: apps/dashboard/app/dashboard/[server]/leaderboard/components/Leaderboard.tsx
  type LeaderboardData (line 15) | interface LeaderboardData {
  function Leaderboard (line 22) | function Leaderboard({ data, showControls = true, showSearch = true }: {...

FILE: apps/dashboard/app/dashboard/[server]/leaderboard/loading.tsx
  function Loading (line 7) | function Loading() {

FILE: apps/dashboard/app/dashboard/[server]/leaderboard/page.tsx
  function LeaderboardPage (line 19) | async function LeaderboardPage(props: { params: Promise<{ server: string...

FILE: apps/dashboard/app/dashboard/[server]/loading.tsx
  function Loading (line 9) | function Loading() {

FILE: apps/dashboard/app/dashboard/[server]/logs/components/UpdateLogs.tsx
  type UpdateLog (line 21) | type UpdateLog = Pick<GuildLogsSettings, "type" | "enabled" | "channelId">;
  type UpdateLogsProps (line 23) | interface UpdateLogsProps extends React.ComponentProps<"div"> {
  type UpdateLogProps (line 184) | interface UpdateLogProps extends Omit<React.ComponentProps<typeof Block>...

FILE: apps/dashboard/app/dashboard/[server]/logs/components/handleLogText.ts
  function handleLogText (line 4) | function handleLogText(log: GuildLogType, toUpperCase = true): string {

FILE: apps/dashboard/app/dashboard/[server]/logs/loading.tsx
  function Loading (line 7) | function Loading() {

FILE: apps/dashboard/app/dashboard/[server]/logs/page.tsx
  function LogsPage (line 23) | async function LogsPage(props: { params: Promise<{ server: string }> }) {

FILE: apps/dashboard/app/dashboard/[server]/messages/components/ChangeCustomMessages.tsx
  type ChangeCustomMessagesProps (line 20) | interface ChangeCustomMessagesProps extends React.ComponentPropsWithRef<...

FILE: apps/dashboard/app/dashboard/[server]/messages/loading.tsx
  function Loading (line 9) | function Loading() {

FILE: apps/dashboard/app/dashboard/[server]/messages/page.tsx
  function Page (line 19) | async function Page(props: { params: Promise<{ server: string }> }) {

FILE: apps/dashboard/app/dashboard/[server]/modules/loading.tsx
  function Loading (line 8) | function Loading() {

FILE: apps/dashboard/app/dashboard/[server]/modules/page.tsx
  function Page (line 17) | async function Page(props: { params: Promise<{ server: string }> }) {

FILE: apps/dashboard/app/dashboard/[server]/page.tsx
  function Page (line 25) | async function Page(props: { params: Promise<{ server: string }> }) {

FILE: apps/dashboard/app/dashboard/[server]/settings/components/ChangeEmbedColor.tsx
  type ChangeEmbedColorProps (line 14) | interface ChangeEmbedColorProps extends React.ComponentProps<"div"> {

FILE: apps/dashboard/app/dashboard/[server]/settings/components/DeleteServerData.tsx
  type DeleteServerDataProps (line 12) | interface DeleteServerDataProps extends React.ComponentProps<"div"> {

FILE: apps/dashboard/app/dashboard/[server]/settings/components/PublicDashboard.tsx
  type PublicDashboardProps (line 15) | interface PublicDashboardProps extends React.ComponentProps<"div"> {

FILE: apps/dashboard/app/dashboard/[server]/settings/loading.tsx
  function Loading (line 9) | function Loading() {

FILE: apps/dashboard/app/dashboard/[server]/settings/page.tsx
  function Page (line 19) | async function Page(props: { params: Promise<{ server: string }> }) {

FILE: apps/dashboard/app/dashboard/[server]/statistics/components/StatisticCharts.tsx
  type StatisticChartsProps (line 9) | interface StatisticChartsProps {
  function StatisticCharts (line 16) | function StatisticCharts({ guildJoin, guildLeave, guildMessage, chartCon...

FILE: apps/dashboard/app/dashboard/[server]/statistics/loading.tsx
  function Loading (line 9) | function Loading() {

FILE: apps/dashboard/app/dashboard/[server]/statistics/page.tsx
  function Page (line 30) | async function Page(props: { params: Promise<{ server: string }> }) {

FILE: apps/dashboard/app/dashboard/[server]/user/[id]/loading.tsx
  function Loading (line 8) | function Loading() {

FILE: apps/dashboard/app/dashboard/[server]/user/[id]/page.tsx
  function generateMetadata (line 23) | async function generateMetadata({ params }: { params: Promise<{ server: ...
  function User (line 58) | async function User(props: { params: Promise<{ server: string; id: strin...

FILE: apps/dashboard/app/dashboard/[server]/user/components/ChangeUserReputation.tsx
  type ChangeUserReputationProps (line 12) | interface ChangeUserReputationProps extends React.ComponentProps<"form"> {

FILE: apps/dashboard/app/dashboard/[server]/user/components/ResetUserXP.tsx
  type ResetUserXPProps (line 10) | interface ResetUserXPProps extends React.ComponentProps<"div"> {

FILE: apps/dashboard/app/dashboard/[server]/warns/components/Warns.tsx
  type WarnItems (line 19) | interface WarnItems extends Omit<GuildWarns, "createdAt"> {
  type UserWarns (line 122) | interface UserWarns extends Omit<GuildWarns, "createdById" | "link"> {

FILE: apps/dashboard/app/dashboard/[server]/warns/loading.tsx
  function Loading (line 7) | function Loading() {

FILE: apps/dashboard/app/dashboard/[server]/warns/page.tsx
  function Page (line 18) | async function Page(props: { params: Promise<{ server: string }> }) {

FILE: apps/dashboard/app/dashboard/loading.tsx
  function Loading (line 7) | function Loading() {

FILE: apps/dashboard/app/dashboard/page.tsx
  function Page (line 12) | async function Page() {

FILE: apps/dashboard/app/error.tsx
  function Error (line 11) | function Error({ reset }: { error: Error & { digest?: string }; reset: (...

FILE: apps/dashboard/app/layout.tsx
  function RootLayout (line 62) | function RootLayout({ children }: { children: React.ReactNode }) {

FILE: apps/dashboard/app/legal/layout.tsx
  function MdxLayout (line 3) | function MdxLayout({ children }: { children: React.ReactNode }) {

FILE: apps/dashboard/app/not-found.tsx
  function NotFound (line 9) | function NotFound() {

FILE: apps/dashboard/app/opengraph-image.tsx
  function Image (line 5) | async function Image() {

FILE: apps/dashboard/app/page.tsx
  function Page (line 49) | async function Page() {

FILE: apps/dashboard/app/robots.ts
  function robots (line 4) | function robots(): MetadataRoute.Robots {

FILE: apps/dashboard/app/server/[server]/layout.tsx
  function Layout (line 3) | function Layout({ children }: { children: React.ReactNode }) {

FILE: apps/dashboard/app/server/[server]/loading.tsx
  function Loading (line 6) | function Loading() {

FILE: apps/dashboard/app/server/[server]/page.tsx
  function generateMetadata (line 15) | async function generateMetadata({ params }: { params: Promise<{ server: ...
  function Page (line 63) | async function Page(props: { params: Promise<{ server: string }> }) {

FILE: apps/dashboard/app/sitemap.ts
  function sitemap (line 4) | function sitemap(): MetadataRoute.Sitemap {

FILE: apps/dashboard/app/user/profile/page.tsx
  function Page (line 22) | async function Page() {

FILE: apps/dashboard/components/CategoryBar.tsx
  type CategoryBarProps (line 4) | interface CategoryBarProps extends HTMLAttributes<HTMLDivElement> {

FILE: apps/dashboard/components/DiscordLogin.tsx
  function DiscordLogin (line 7) | function DiscordLogin() {

FILE: apps/dashboard/components/Hotjar.tsx
  function Hotjar (line 3) | function Hotjar({ id }: { id: string | null }) {

FILE: apps/dashboard/components/LoginButton.tsx
  function LoginButton (line 9) | async function LoginButton() {

FILE: apps/dashboard/components/Session.tsx
  function Session (line 5) | function Session({ children }: { children: React.ReactElement }) {

FILE: apps/dashboard/components/TailwindIndicator.tsx
  function TailwindIndicator (line 1) | function TailwindIndicator() {

FILE: apps/dashboard/components/client/charts/ServerStatsChart.tsx
  type DateRange (line 22) | type DateRange = (typeof dateRanges)[number];
  type StatsChartProps (line 24) | interface StatsChartProps {

FILE: apps/dashboard/components/client/commands/DiscordCommands.tsx
  type DiscordCommandsProps (line 13) | interface DiscordCommandsProps extends React.ComponentProps<"div"> {

FILE: apps/dashboard/components/client/commands/UpdateCategories.tsx
  type UpdateCategoriesProps (line 10) | interface UpdateCategoriesProps extends Omit<React.ComponentProps<typeof...

FILE: apps/dashboard/components/client/commands/UpdateCommands.tsx
  type UpdateCommandsProps (line 10) | interface UpdateCommandsProps extends Omit<React.ComponentProps<typeof T...

FILE: apps/dashboard/components/nav/ProgressBar.tsx
  function ProgressBar (line 5) | function ProgressBar({ children }: { children: React.ReactElement }) {

FILE: apps/dashboard/components/nav/SideNavigation.tsx
  type SideNavigationProps (line 41) | interface SideNavigationProps extends React.ComponentProps<"aside"> {

FILE: apps/dashboard/components/nav/UserMenuDropdown.tsx
  type UserSession (line 14) | type UserSession = Awaited<ReturnType<typeof getSession>>;

FILE: apps/dashboard/components/nav/VisibilityContext.tsx
  type VisibilityContextProps (line 5) | interface VisibilityContextProps {
  type VisibilityProviderProps (line 15) | interface VisibilityProviderProps {

FILE: apps/dashboard/components/ui/Accordion.tsx
  function AccordionItem (line 10) | function AccordionItem({ className, ...props }: React.ComponentProps<typ...
  function AccordionTrigger (line 14) | function AccordionTrigger({ className, children, ...props }: React.Compo...
  function AccordionContent (line 28) | function AccordionContent({ className, children, ...props }: React.Compo...

FILE: apps/dashboard/components/ui/Block.tsx
  type ErrorBlockProps (line 25) | interface ErrorBlockProps extends React.ComponentProps<"div"> {

FILE: apps/dashboard/components/ui/ChannelsSelect.tsx
  type ChannelsSelectProps (line 13) | interface ChannelsSelectProps extends React.ComponentProps<typeof Popove...

FILE: apps/dashboard/components/ui/Chart.tsx
  constant THEMES (line 11) | const THEMES = { light: "", dark: ".dark" } as const;
  type ChartConfig (line 13) | type ChartConfig = Record<
  type ChartContextProps (line 21) | interface ChartContextProps {
  function useChart (line 27) | function useChart() {
  function getPayloadConfigFromPayload (line 34) | function getPayloadConfigFromPayload(config: ChartConfig, payload: unkno...
  function ChartContainer (line 81) | function ChartContainer({
  type CustomTooltipProps (line 113) | type CustomTooltipProps = TooltipContentProps<ValueType, NameType> & {
  function ChartTooltipContent (line 132) | function ChartTooltipContent({
  type ChartLegendContentProps (line 235) | type ChartLegendContentProps = {
  function ChartLegendContent (line 243) | function ChartLegendContent({ className, hideIcon = false, payload, vert...

FILE: apps/dashboard/components/ui/Dialog.tsx
  function DialogOverlay (line 13) | function DialogOverlay({ className, ...props }: React.ComponentProps<typ...
  function DialogContent (line 25) | function DialogContent({ className, children, ...props }: React.Componen...
  function DialogTitle (line 52) | function DialogTitle({ className, ...props }: React.ComponentProps<typeo...
  function DialogDescription (line 56) | function DialogDescription({ className, ...props }: React.ComponentProps...

FILE: apps/dashboard/components/ui/Disclosure.tsx
  type DisclosureProps (line 6) | interface DisclosureProps {

FILE: apps/dashboard/components/ui/Embed.tsx
  type EmbedProps (line 8) | interface EmbedProps extends React.ComponentProps<"div"> {
  type EmbedImageProps (line 41) | interface EmbedImageProps extends Omit<React.ComponentProps<typeof Image...

FILE: apps/dashboard/components/ui/GraphCard.tsx
  type GraphCardProps (line 5) | interface GraphCardProps extends React.ComponentProps<"div"> {

FILE: apps/dashboard/components/ui/Icons.tsx
  type Icon (line 24) | type Icon = LucideIcon;

FILE: apps/dashboard/components/ui/Image.tsx
  type ImageWithFallbackProps (line 6) | interface ImageWithFallbackProps extends Omit<React.ComponentProps<typeo...

FILE: apps/dashboard/components/ui/RolesSelect.tsx
  type RolesSelectProps (line 12) | interface RolesSelectProps extends React.ComponentProps<typeof Popover> {

FILE: apps/dashboard/components/ui/Select.tsx
  type CustomSelectItemProps (line 61) | interface CustomSelectItemProps extends React.ComponentPropsWithRef<type...

FILE: apps/dashboard/components/ui/Skeletons.tsx
  function Skeleton (line 4) | function Skeleton({ className, ...props }: React.ComponentProps<"div">) {

FILE: apps/dashboard/components/ui/SparkChart.tsx
  type SparkLineChartProps (line 7) | interface SparkLineChartProps {
  function SparkLineChart (line 13) | function SparkLineChart({ data, categories, index }: SparkLineChartProps) {

FILE: apps/dashboard/components/ui/Table.tsx
  type TableProps (line 13) | interface TableProps<TData, TValue> {
  type DataTableColumnHeaderProps (line 21) | interface DataTableColumnHeaderProps<TData, TValue> extends React.HTMLAt...
  function TableColumnHeader (line 26) | function TableColumnHeader<TData, TValue>({ column, title, className }: ...

FILE: apps/dashboard/components/ui/TimeSelect.tsx
  type TimeSelectProps (line 46) | interface TimeSelectProps extends React.ComponentProps<typeof Select> {

FILE: apps/dashboard/components/ui/Tooltip.tsx
  type TooltipProps (line 7) | interface TooltipProps extends React.ComponentProps<typeof Content> {

FILE: apps/dashboard/components/ui/ViewSelect.tsx
  type ViewSelectProps (line 6) | interface ViewSelectProps extends React.ComponentProps<typeof Select> {

FILE: apps/dashboard/components/ui/effects/AnimatedBeam.tsx
  type AnimatedBeamProps (line 7) | interface AnimatedBeamProps {

FILE: apps/dashboard/components/ui/effects/AnimatedList.tsx
  function AnimatedListItem (line 6) | function AnimatedListItem({ children }: { children: React.ReactNode }) {
  type AnimatedListProps (line 21) | interface AnimatedListProps {

FILE: apps/dashboard/components/ui/effects/AnimatedShinyText.tsx
  type AnimatedShinyTextProps (line 4) | interface AnimatedShinyTextProps extends React.ComponentProps<"p"> {

FILE: apps/dashboard/components/ui/effects/BorderBeam.tsx
  type BorderBeamProps (line 3) | interface BorderBeamProps extends React.ComponentProps<"div"> {

FILE: apps/dashboard/components/ui/effects/FadeText.tsx
  type FadeTextProps (line 6) | interface FadeTextProps extends React.ComponentProps<"div"> {

FILE: apps/dashboard/components/ui/effects/FlickeringGrid.tsx
  type FlickeringGridProps (line 5) | interface FlickeringGridProps {

FILE: apps/dashboard/components/ui/effects/Globe.tsx
  function GlobeClient (line 134) | function GlobeClient() {

FILE: apps/dashboard/components/ui/effects/Meteors.tsx
  type MeteorsProps (line 6) | interface MeteorsProps {

FILE: apps/dashboard/components/ui/effects/NumberTicker.tsx
  function NumberTicker (line 7) | function NumberTicker({

FILE: apps/dashboard/components/ui/effects/Particles.tsx
  type MousePosition (line 6) | interface MousePosition {
  function MousePosition (line 11) | function MousePosition(): MousePosition {
  type ParticlesProps (line 32) | interface ParticlesProps {
  function hexToRgb (line 44) | function hexToRgb(hex: string): number[] {
  type Circle (line 61) | type Circle = {

FILE: apps/dashboard/components/ui/effects/Ripple.tsx
  type RippleProps (line 4) | interface RippleProps {

FILE: apps/dashboard/components/ui/effects/WordPullUp.tsx
  type WordPullUpProps (line 6) | interface WordPullUpProps {
  function WordPullUp (line 15) | function WordPullUp({

FILE: apps/dashboard/lib/authOptions.ts
  type Session (line 8) | interface Session extends DefaultSession, Account, DiscordProfile {}
  method profile (line 18) | async profile(profile, tokens) {
  method jwt (line 111) | jwt({ token, account, profile }) {
  method session (line 123) | session({ session, token }) {

FILE: apps/dashboard/lib/session.ts
  function getSession (line 6) | async function getSession() {
  function getCurrentUser (line 10) | async function getCurrentUser() {

FILE: apps/dashboard/lib/types.ts
  type ExtendedApplicationCommandOptionData (line 4) | type ExtendedApplicationCommandOptionData = APIApplicationCommandOption ...
  type Command (line 6) | interface Command {
  type LogItem (line 13) | interface LogItem extends Omit<GuildLogs, "createdAt"> {

FILE: apps/dashboard/lib/utils.ts
  function cn (line 4) | function cn(...inputs: ClassValue[]) {

FILE: apps/dashboard/mdx-components.tsx
  function normalize (line 4) | function normalize(text: string) {
  type HeadingProps (line 17) | interface HeadingProps extends HTMLAttributes<HTMLHeadingElement> {
  function useMDXComponents (line 21) | function useMDXComponents(components: MDXComponents) {

FILE: apps/dashboard/next.config.ts
  method redirects (line 54) | async redirects() {
  method headers (line 58) | async headers() {

FILE: packages/database/prisma/migrations/20230516174916_/migration.sql
  type "users" (line 2) | CREATE TABLE "users" (
  type "users" (line 15) | CREATE UNIQUE INDEX "users_email_key" ON "users"("email")

FILE: packages/database/prisma/migrations/20230516200625_add_auth/migration.sql
  type "Account" (line 15) | CREATE TABLE "Account" (
  type "Session" (line 34) | CREATE TABLE "Session" (
  type "Account" (line 45) | CREATE UNIQUE INDEX "Account_provider_providerAccountId_key" ON "Account...
  type "Session" (line 48) | CREATE UNIQUE INDEX "Session_sessionToken_key" ON "Session"("sessionToken")

FILE: packages/database/prisma/migrations/20230516202208_save_only_required/migration.sql
  type "users" (line 53) | CREATE UNIQUE INDEX "users_discordId_global_name_key" ON "users"("discor...

FILE: packages/database/prisma/migrations/20230516202517_make_email_unique/migration.sql
  type "users" (line 11) | CREATE UNIQUE INDEX "users_discordId_global_name_email_key" ON "users"("...

FILE: packages/database/prisma/migrations/20230516202902_fix_unique/migration.sql
  type "Account" (line 18) | CREATE UNIQUE INDEX "Account_provider_key" ON "Account"("provider")
  type "Account" (line 21) | CREATE UNIQUE INDEX "Account_providerAccountId_key" ON "Account"("provid...
  type "users" (line 24) | CREATE UNIQUE INDEX "users_discordId_key" ON "users"("discordId")
  type "users" (line 27) | CREATE UNIQUE INDEX "users_global_name_key" ON "users"("global_name")
  type "users" (line 30) | CREATE UNIQUE INDEX "users_email_key" ON "users"("email")

FILE: packages/database/prisma/migrations/20230516210849_add_maps/migration.sql
  type "accounts" (line 21) | CREATE TABLE "accounts" (
  type "sessions" (line 40) | CREATE TABLE "sessions" (
  type "accounts" (line 51) | CREATE UNIQUE INDEX "accounts_provider_key" ON "accounts"("provider")
  type "accounts" (line 54) | CREATE UNIQUE INDEX "accounts_providerAccountId_key" ON "accounts"("prov...
  type "sessions" (line 57) | CREATE UNIQUE INDEX "sessions_sessionToken_key" ON "sessions"("sessionTo...

FILE: packages/database/prisma/migrations/20230516211309_add_verification_token/migration.sql
  type "VerificationToken" (line 2) | CREATE TABLE "VerificationToken" (
  type "VerificationToken" (line 9) | CREATE UNIQUE INDEX "VerificationToken_token_key" ON "VerificationToken"...
  type "VerificationToken" (line 12) | CREATE UNIQUE INDEX "VerificationToken_identifier_token_key" ON "Verific...

FILE: packages/database/prisma/migrations/20230516212035_fix_unique_values/migration.sql
  type "accounts" (line 8) | CREATE UNIQUE INDEX "accounts_provider_providerAccountId_key" ON "accoun...

FILE: packages/database/prisma/migrations/20230521135936_add_suggestions/migration.sql
  type "verification_tokens" (line 11) | CREATE TABLE "verification_tokens" (
  type "suggestions" (line 18) | CREATE TABLE "suggestions" (
  type "verification_tokens" (line 29) | CREATE UNIQUE INDEX "verification_tokens_token_key" ON "verification_tok...
  type "verification_tokens" (line 32) | CREATE UNIQUE INDEX "verification_tokens_identifier_token_key" ON "verif...

FILE: packages/database/prisma/migrations/20230521143031_add_guild_model/migration.sql
  type "guilds" (line 2) | CREATE TABLE "guilds" (
  type "guilds" (line 12) | CREATE UNIQUE INDEX "guilds_discord_id_key" ON "guilds"("discord_id")

FILE: packages/database/prisma/migrations/20230521184416_add_guild_logs/migration.sql
  type "guild_logs" (line 2) | CREATE TABLE "guild_logs" (

FILE: packages/database/prisma/migrations/20230604182342_add_guild_xp/migration.sql
  type "guild_xp" (line 2) | CREATE TABLE "guild_xp" (

FILE: packages/database/prisma/migrations/20230610181051_update_account/migration.sql
  type "accounts" (line 32) | CREATE UNIQUE INDEX "accounts_provider_provider_account_id_key" ON "acco...

FILE: packages/database/prisma/migrations/20230610195213_update_rows_names/migration.sql
  type "guilds" (line 76) | CREATE UNIQUE INDEX "guilds_guild_id_key" ON "guilds"("guild_id")
  type "sessions" (line 79) | CREATE UNIQUE INDEX "sessions_session_token_key" ON "sessions"("session_...
  type "users" (line 82) | CREATE UNIQUE INDEX "users_discord_id_key" ON "users"("discord_id")

FILE: packages/database/prisma/migrations/20230716165214_add_guild_joins/migration.sql
  type "guild_joins" (line 2) | CREATE TABLE "guild_joins" (
  type "guild_leaves" (line 12) | CREATE TABLE "guild_leaves" (

FILE: packages/database/prisma/migrations/20230807093042_add_reputation/migration.sql
  type "reputation" (line 2) | CREATE TABLE "reputation" (

FILE: packages/database/prisma/migrations/20230809192933_add_giveaways/migration.sql
  type "Giveaway" (line 2) | CREATE TABLE "Giveaway" (
  type "Giveaway" (line 13) | CREATE UNIQUE INDEX "Giveaway_message_id_key" ON "Giveaway"("message_id")

FILE: packages/database/prisma/migrations/20230809193154_change_giveaways_name/migration.sql
  type "Giveaways" (line 14) | CREATE TABLE "Giveaways" (
  type "Giveaways" (line 25) | CREATE UNIQUE INDEX "Giveaways_message_id_key" ON "Giveaways"("message_id")

FILE: packages/database/prisma/migrations/20230813164922_add_messages_count/migration.sql
  type "GuildMessage" (line 2) | CREATE TABLE "GuildMessage" (

FILE: packages/database/prisma/migrations/20230901110432_add_vanity_urls/migration.sql
  type "guilds" (line 13) | CREATE UNIQUE INDEX "guilds_vanity_key" ON "guilds"("vanity")

FILE: packages/database/prisma/migrations/20231008115944_add_guild_controlled_commands/migration.sql
  type "CommandCategories" (line 2) | CREATE TABLE "CommandCategories" (
  type "commands" (line 11) | CREATE TABLE "commands" (
  type "guild_disabled_commands" (line 23) | CREATE TABLE "guild_disabled_commands" (
  type "guild_disabled_categories" (line 33) | CREATE TABLE "guild_disabled_categories" (
  type "CommandCategories" (line 43) | CREATE UNIQUE INDEX "CommandCategories_name_key" ON "CommandCategories"(...
  type "commands" (line 46) | CREATE UNIQUE INDEX "commands_command_key" ON "commands"("command")

FILE: packages/database/prisma/migrations/20231008120512_fix_commands/migration.sql
  type "commands" (line 22) | CREATE UNIQUE INDEX "commands_name_key" ON "commands"("name")

FILE: packages/database/prisma/migrations/20231018085005_add_automod_rules/migration.sql
  type "auto_mod" (line 2) | CREATE TABLE "auto_mod" (
  type "auto_mod" (line 14) | CREATE UNIQUE INDEX "auto_mod_rule_id_key" ON "auto_mod"("rule_id")

FILE: packages/database/prisma/migrations/20231030220258_add_warning_system/migration.sql
  type "guild_warns" (line 6) | CREATE TABLE "guild_warns" (

FILE: packages/database/prisma/migrations/20231216135714_add_welcome_and_leave_messages/migration.sql
  type "guild_welcome_message" (line 2) | CREATE TABLE "guild_welcome_message" (
  type "guild_leave_message" (line 12) | CREATE TABLE "guild_leave_message" (
  type "guild_welcome_message" (line 22) | CREATE UNIQUE INDEX "guild_welcome_message_guild_id_key" ON "guild_welco...
  type "guild_leave_message" (line 25) | CREATE UNIQUE INDEX "guild_leave_message_guild_id_key" ON "guild_leave_m...

FILE: packages/database/prisma/migrations/20241220180643_add_guild_settings/migration.sql
  type "guild_logs_settings" (line 2) | CREATE TABLE "guild_logs_settings" (

FILE: packages/database/prisma/migrations/20241220181109_add_type_as_unique/migration.sql
  type "guild_logs_settings" (line 8) | CREATE UNIQUE INDEX "guild_logs_settings_guild_id_type_key" ON "guild_lo...

FILE: packages/database/src/client.ts
  method $allOperations (line 16) | async $allOperations({ operation, model, args, query }) {

FILE: packages/database/src/logger.ts
  function Logger (line 12) | function Logger(type: keyof typeof colors, ...args: (string | unknown)[]) {

FILE: packages/database/src/redis/cache.ts
  function cacheSet (line 12) | async function cacheSet(key: string, value: object | string, ttl: number...
  function cacheGet (line 25) | async function cacheGet(key: string): Promise<string | null> {
  function cacheTTL (line 36) | async function cacheTTL(key: string): Promise<number> {
  function cacheDel (line 46) | async function cacheDel(key: string): Promise<void> {

FILE: packages/utils/database/logs/createLog.ts
  function createLog (line 5) | async function createLog(guildId: Snowflake, userId: Snowflake, data: Om...

FILE: packages/utils/database/logs/fetchLogs.ts
  function fetchLogs (line 4) | async function fetchLogs(guildId: Snowflake, page: number, count = 20) {
  function countLogs (line 27) | async function countLogs(guildId: Snowflake) {

FILE: packages/utils/database/logs/getGuildLogSettings.ts
  function getGuildLogSettings (line 5) | async function getGuildLogSettings(guildId: Snowflake, type: GuildLogTyp...

FILE: packages/utils/database/moderation/automod/createDatabaseAutoModRule.ts
  function createDatabaseAutoModRule (line 4) | async function createDatabaseAutoModRule(guildId: Snowflake, ruleId: Sno...

FILE: packages/utils/database/moderation/automod/deleteDatabaseAutoModRule.ts
  function deleteDatabaseAutoModRule (line 4) | async function deleteDatabaseAutoModRule(guildId: Snowflake, ruleId: Sno...

FILE: packages/utils/database/moderation/automod/fetchDatabaseAutoModRules.ts
  function fetchDatabaseAutoModRules (line 5) | async function fetchDatabaseAutoModRules(guildId: Snowflake) {
  function fetchDatabaseAutoModRule (line 20) | async function fetchDatabaseAutoModRule(guildId: Snowflake, ruleId: Auto...

FILE: packages/utils/database/moderation/automod/syncDatabaseAutoModRule.ts
  function syncDatabaseAutoModRule (line 8) | async function syncDatabaseAutoModRule(guildId: Snowflake, ruleType: Aut...

FILE: packages/utils/database/moderation/automod/updateDatabaseAutoModRule.ts
  function updateDatabaseAutoModRule (line 4) | async function updateDatabaseAutoModRule(guildId: Snowflake, ruleId: Sno...

FILE: packages/utils/database/moderation/warn/clearWarns.ts
  function clearWarns (line 4) | async function clearWarns(userId: Snowflake, guildId: Snowflake) {

FILE: packages/utils/database/moderation/warn/listWarns.ts
  function listWarns (line 4) | async function listWarns(guildId: Snowflake, userId: Snowflake) {

FILE: packages/utils/database/moderation/warn/removeWarn.ts
  function removeWarn (line 5) | async function removeWarn(guildId: Snowflake, userId: Snowflake, warnId:...

FILE: packages/utils/database/moderation/warn/warnUser.ts
  function warnUser (line 6) | async function warnUser(guildId: Snowflake, user: APIUser | User, reason...

FILE: packages/utils/database/reputation/checkReputation.ts
  function checkReputation (line 4) | async function checkReputation(userId: Snowflake, guildId: Snowflake) {

FILE: packages/utils/database/reputation/giveReputation.ts
  function giveReputation (line 6) | async function giveReputation(user: APIUser | User, guildId: Snowflake) {

FILE: packages/utils/database/reputation/setReputation.ts
  function setReputation (line 6) | async function setReputation(user: APIUser | User, guildId: Snowflake, a...

FILE: packages/utils/database/reputation/takeReputation.ts
  function takeReputation (line 6) | async function takeReputation(user: APIUser | User, guildId: Snowflake) {

FILE: packages/utils/database/settings/XPSettings.ts
  function fetchXPSettings (line 4) | async function fetchXPSettings(guildId: Snowflake) {
  function setXPSettings (line 39) | async function setXPSettings(guildId: Snowflake, enableXP: boolean) {
  function setXPLevelUpMessageSettings (line 58) | async function setXPLevelUpMessageSettings(guildId: Snowflake, enableXPL...

FILE: packages/utils/database/user/createUser.ts
  function createUser (line 6) | async function createUser(user: APIUser | User) {

FILE: packages/utils/database/xp/checkXP.ts
  function checkXP (line 4) | async function checkXP(userId: Snowflake, guildId: Snowflake) {

FILE: packages/utils/database/xp/resetXP.ts
  function resetXP (line 4) | async function resetXP(userId: Snowflake, guildId: Snowflake) {

FILE: packages/utils/embeds/createErrorEmbed.ts
  function createErrorEmbed (line 3) | function createErrorEmbed(description: string, title?: string): EmbedBui...

FILE: packages/utils/functions/automod/createDiscordAutoModRule.ts
  function createDiscordAutoModRule (line 7) | async function createDiscordAutoModRule(serverId: string, ruleType: stri...

FILE: packages/utils/functions/automod/deleteDiscordAutoModRule.ts
  function deleteDiscordAutoModRules (line 4) | async function deleteDiscordAutoModRules(guildId: Snowflake, ruleId: Sno...

FILE: packages/utils/functions/automod/fetchDiscordAutoModRules.ts
  function fetchDiscordAutoModRules (line 5) | async function fetchDiscordAutoModRules(guildId: Snowflake) {

FILE: packages/utils/functions/automod/types.ts
  type AutoModerationRuleCreationData (line 3) | interface AutoModerationRuleCreationData {

FILE: packages/utils/functions/automod/validateAutoModIgnores.ts
  function validateAutoModIgnores (line 4) | async function validateAutoModIgnores(

FILE: packages/utils/functions/automod/validateAutoModRuleActions.ts
  type ValidationResult (line 13) | interface ValidationResult {
  function validateAutoModRuleActions (line 18) | async function validateAutoModRuleActions(

FILE: packages/utils/functions/files/readDir.ts
  function readDir (line 4) | function readDir(dir: PathLike, recursive = false, extensions = [".js"]) {

FILE: packages/utils/functions/guild/getGuild.ts
  function getGuild (line 6) | async function getGuild(id: Snowflake) {

FILE: packages/utils/functions/guild/getGuildChannels.ts
  function getGuildChannels (line 5) | async function getGuildChannels(guildId: Snowflake, types: GuildChannelT...

FILE: packages/utils/functions/guild/getGuildFromMemberGuilds.ts
  function getGuildFromMemberGuilds (line 4) | async function getGuildFromMemberGuilds(guildId: Snowflake, token: strin...

FILE: packages/utils/functions/guild/getGuildPreview.ts
  function getGuildPreview (line 5) | async function getGuildPreview(id: Snowflake): Promise<APIGuildPreview |...

FILE: packages/utils/functions/guild/getGuildRoles.ts
  function getGuildRoles (line 6) | async function getGuildRoles(guildId: Snowflake): Promise<RESTGetAPIGuil...

FILE: packages/utils/functions/guild/getMemberGuilds.ts
  type ExtendedAPIGuild (line 6) | interface ExtendedAPIGuild extends APIGuild {
  function getMemberGuilds (line 11) | async function getMemberGuilds(token: string) {

FILE: packages/utils/functions/guild/isBotInServer.ts
  function isBotInServer (line 4) | async function isBotInServer(guildId: Snowflake): Promise<boolean> {

FILE: packages/utils/functions/user/getDiscordUser.ts
  function getDiscordUser (line 4) | async function getDiscordUser(userId: Snowflake) {

FILE: packages/utils/functions/user/getFlags.ts
  type UserFlagsObject (line 1) | interface UserFlagsObject {
  function getFlags (line 70) | function getFlags(number: number): UserFlagsObject[] {

FILE: packages/utils/functions/user/getPermissionNames.ts
  function getPermissionNames (line 3) | function getPermissionNames(permissionNumber: bigint | string) {

FILE: packages/utils/functions/user/isApiUser.ts
  function isAPIUser (line 4) | function isAPIUser(user: APIUser | User): user is APIUser {

FILE: packages/utils/functions/util/adjustColor.ts
  function adjustColor (line 1) | function adjustColor(hexColor: string, percent: number, action: "darken"...

FILE: packages/utils/functions/util/capitalize.ts
  function capitalize (line 1) | function capitalize(str: string) {

FILE: packages/utils/functions/util/fillMissingDates.ts
  type DataEntry (line 3) | interface DataEntry {
  function fillMissingDates (line 9) | function fillMissingDates(array: DataEntry[], property: string) {

FILE: packages/utils/functions/util/formatDate.ts
  function formatDate (line 1) | function formatDate(date: string | number | Date) {

FILE: packages/utils/functions/util/formatDuration.ts
  function formatDuration (line 3) | function formatDuration(durationInMs: number | string) {

FILE: packages/utils/functions/util/formatNumber.ts
  function formatNumber (line 1) | function formatNumber(num: number): string {

FILE: packages/utils/functions/util/generateDates.ts
  function generateDates (line 1) | function generateDates(startDate: Date, endDate: Date): Date[] {

FILE: packages/utils/functions/util/isNumeric.ts
  function isNumeric (line 1) | function isNumeric(num: string | number): boolean {

FILE: packages/utils/functions/util/logger.ts
  function Logger (line 12) | function Logger(type: keyof typeof colors, ...args: (string | unknown)[]) {

FILE: packages/utils/functions/util/percentageBar.ts
  function percentageBar (line 1) | function percentageBar(full: number, curr: number, numBars: number = 25)...

FILE: packages/utils/functions/util/randomness.ts
  function pseudoRandom (line 1) | function pseudoRandom(index: number) {

FILE: packages/utils/functions/util/shortenText.ts
  function shortenText (line 1) | function shortenText(text: string, maxLen: number | 25 = 25): string {

FILE: packages/utils/functions/util/splitCamelCase.ts
  function splitCamelCase (line 1) | function splitCamelCase(str: string) {

FILE: packages/utils/images/invertColor.ts
  function invertColor (line 1) | function invertColor(hex: string): string {

FILE: packages/utils/images/linesHelper.ts
  function getLines (line 3) | function getLines(context: SKRSContext2D, text: string, maxWidth: number...
Condensed preview — 492 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,721K chars).
[
  {
    "path": ".dockerignore",
    "chars": 345,
    "preview": "**/.classpath\n**/.dockerignore\n**/.env\n**/.git\n**/.gitignore\n**/.project\n**/.settings\n**/.toolstarget\n**/.vs\n**/.vscode\n"
  },
  {
    "path": ".github/codeowners",
    "chars": 26,
    "preview": "license.md @igorkowalczyk\n"
  },
  {
    "path": ".github/renovate.json",
    "chars": 432,
    "preview": "{\n \"$schema\": \"https://docs.renovatebot.com/renovate-schema.json\",\n \"extends\": [\"github>igorkowalczyk/shared-configs//pa"
  },
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "chars": 600,
    "preview": "name: \"CodeQL Checks\"\n\non: [push, pull_request]\n\njobs:\n analyze:\n  name: Analyze\n  runs-on: ubuntu-latest\n  permissions:"
  },
  {
    "path": ".github/workflows/format-check.yml",
    "chars": 711,
    "preview": "name: Prettier check\n\non: [push, pull_request]\n\njobs:\n check:\n  timeout-minutes: 15\n  name: Format check\n  runs-on: ubun"
  },
  {
    "path": ".github/workflows/lint.yml",
    "chars": 674,
    "preview": "name: Lint\n\non: [push, pull_request]\n\njobs:\n lint:\n  timeout-minutes: 15\n  name: ESLint\n  runs-on: ubuntu-latest\n  env:\n"
  },
  {
    "path": ".gitignore",
    "chars": 791,
    "preview": "# .gitignore\n\n# Logs\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlerna-debug.log*\n\n# Diagnostic reports (https://node"
  },
  {
    "path": ".npmrc",
    "chars": 31,
    "preview": "public-hoist-pattern[]=*prisma*"
  },
  {
    "path": ".prettierignore",
    "chars": 64,
    "preview": "package.json\npnpm-lock.yaml\n\n*/*/package.json\n*/*/pnpm-lock.yaml"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 8339,
    "preview": "![Header](https://github.com/IgorKowalczyk/majo.exe/assets/49127376/4df57b45-2900-40e0-bf34-707170fb83bc)\n\n<p align=\"cen"
  },
  {
    "path": "README.md",
    "chars": 8432,
    "preview": "![Header](https://github.com/IgorKowalczyk/majo.exe/assets/49127376/8fd53e0b-1902-460c-9d6c-7d42ea84f8bb)\n\n<p align=\"cen"
  },
  {
    "path": "apps/bot/.env.example",
    "chars": 160,
    "preview": "# Bot\nTOKEN=\nCLIENT_ID=\nCLIENT_SECRET=\nDISCORD_SUPPORT_SERVER_ID=\n\n# Top.gg (Optional)\nTOPGG_API_KEY=\n\n# discordbotlist."
  },
  {
    "path": "apps/bot/.prettierignore",
    "chars": 12,
    "preview": "package.json"
  },
  {
    "path": "apps/bot/Dockerfile",
    "chars": 391,
    "preview": "ARG APP_PKG_NAME=@majoexe/bot\n\nFROM node:24-alpine\n\nRUN apk add curl\n\nWORKDIR /app\n\nENV NODE_ENV=production\nENV TURBO_TE"
  },
  {
    "path": "apps/bot/README.md",
    "chars": 6484,
    "preview": "![Header - Bot](https://github.com/IgorKowalczyk/majo.exe/assets/49127376/9a34b389-e710-435e-9514-1f4c5f733d74)\n\n<p alig"
  },
  {
    "path": "apps/bot/commands/Fun/8ball.ts",
    "chars": 3387,
    "preview": "import { ApplicationCommandType, ApplicationCommandOptionType, EmbedBuilder, ApplicationIntegrationType, InteractionCont"
  },
  {
    "path": "apps/bot/commands/Fun/advice.ts",
    "chars": 1552,
    "preview": "import advices from \"@majoexe/util/content/advices.json\";\nimport { ApplicationCommandType, ApplicationIntegrationType, E"
  },
  {
    "path": "apps/bot/commands/Fun/anime.ts",
    "chars": 6341,
    "preview": "import {\n  ApplicationCommandType,\n  ApplicationCommandOptionType,\n  EmbedBuilder,\n  codeBlock,\n  ActionRowBuilder,\n  Bu"
  },
  {
    "path": "apps/bot/commands/Fun/cat.ts",
    "chars": 1755,
    "preview": "import { ActionRowBuilder, ApplicationCommandType, ApplicationIntegrationType, ButtonBuilder, ButtonStyle, EmbedBuilder,"
  },
  {
    "path": "apps/bot/commands/Fun/comic.ts",
    "chars": 6186,
    "preview": "import { load } from \"cheerio\";\nimport {\n  ApplicationCommandType,\n  EmbedBuilder,\n  ActionRowBuilder,\n  ButtonBuilder,\n"
  },
  {
    "path": "apps/bot/commands/Fun/dice.ts",
    "chars": 1319,
    "preview": "import { ApplicationCommandType, ApplicationIntegrationType, EmbedBuilder, InteractionContextType } from \"discord.js\";\ni"
  },
  {
    "path": "apps/bot/commands/Fun/flip.ts",
    "chars": 2962,
    "preview": "import { flipText } from \"@majoexe/util/functions/util\";\nimport { ApplicationCommandType, ApplicationCommandOptionType, "
  },
  {
    "path": "apps/bot/commands/Fun/iq.ts",
    "chars": 1594,
    "preview": "import { ApplicationCommandType, ApplicationCommandOptionType, EmbedBuilder, ApplicationIntegrationType, InteractionCont"
  },
  {
    "path": "apps/bot/commands/Fun/joke.ts",
    "chars": 1836,
    "preview": "import { ApplicationCommandType, ApplicationIntegrationType, EmbedBuilder, InteractionContextType } from \"discord.js\";\ni"
  },
  {
    "path": "apps/bot/commands/Fun/letmegpt.ts",
    "chars": 2071,
    "preview": "import {\n  ApplicationCommandType,\n  ApplicationCommandOptionType,\n  EmbedBuilder,\n  ButtonBuilder,\n  ButtonStyle,\n  Act"
  },
  {
    "path": "apps/bot/commands/Fun/lmgtfy.ts",
    "chars": 2077,
    "preview": "import {\n  ApplicationCommandType,\n  ApplicationCommandOptionType,\n  EmbedBuilder,\n  ButtonBuilder,\n  ButtonStyle,\n  Act"
  },
  {
    "path": "apps/bot/commands/Fun/meme.ts",
    "chars": 2543,
    "preview": "import { ActionRowBuilder, ApplicationCommandType, ApplicationIntegrationType, ButtonBuilder, ButtonStyle, EmbedBuilder,"
  },
  {
    "path": "apps/bot/commands/Fun/rate.ts",
    "chars": 1826,
    "preview": "import { ApplicationCommandType, ApplicationCommandOptionType, EmbedBuilder, type ColorResolvable, ApplicationIntegratio"
  },
  {
    "path": "apps/bot/commands/Fun/ship.ts",
    "chars": 2533,
    "preview": "import { percentageBar } from \"@majoexe/util/functions/util\";\nimport { ApplicationCommandType, ApplicationCommandOptionT"
  },
  {
    "path": "apps/bot/commands/Fun/why.ts",
    "chars": 1463,
    "preview": "import why from \"@majoexe/util/content/why.json\";\nimport { ApplicationCommandType, ApplicationIntegrationType, EmbedBuil"
  },
  {
    "path": "apps/bot/commands/General/about.ts",
    "chars": 2738,
    "preview": "import { ActionRowBuilder, ApplicationCommandType, ButtonStyle, ButtonBuilder, EmbedBuilder, InteractionContextType, App"
  },
  {
    "path": "apps/bot/commands/General/contact.ts",
    "chars": 2909,
    "preview": "import { ApplicationCommandType, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, ApplicationIntegrationType,"
  },
  {
    "path": "apps/bot/commands/General/dashboard.ts",
    "chars": 2396,
    "preview": "import { ApplicationCommandType, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, ApplicationIntegrationType,"
  },
  {
    "path": "apps/bot/commands/General/donate.ts",
    "chars": 2543,
    "preview": "import { ApplicationCommandType, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, ApplicationIntegrationType,"
  },
  {
    "path": "apps/bot/commands/General/help.ts",
    "chars": 9825,
    "preview": "import { formatDuration } from \"@majoexe/util/functions/util\";\nimport {\n  ApplicationCommandType,\n  ApplicationCommandOp"
  },
  {
    "path": "apps/bot/commands/General/invite.ts",
    "chars": 2226,
    "preview": "import { ApplicationCommandType, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, ApplicationIntegrationType,"
  },
  {
    "path": "apps/bot/commands/General/opensource.ts",
    "chars": 2970,
    "preview": "import { ApplicationCommandType, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, time, ApplicationIntegratio"
  },
  {
    "path": "apps/bot/commands/General/permissions.ts",
    "chars": 2509,
    "preview": "import { ApplicationCommandType, ApplicationIntegrationType, EmbedBuilder, InteractionContextType, PermissionsBitField, "
  },
  {
    "path": "apps/bot/commands/General/ping.ts",
    "chars": 2906,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { ApplicationCommandType, EmbedBuilder, codeBlock, Status, Applicat"
  },
  {
    "path": "apps/bot/commands/General/servers.ts",
    "chars": 3120,
    "preview": "import { formatNumber } from \"@majoexe/util/functions/util\";\nimport { ApplicationCommandType, EmbedBuilder, ButtonBuilde"
  },
  {
    "path": "apps/bot/commands/General/suggestion.ts",
    "chars": 1463,
    "preview": "import { ApplicationCommandType, ActionRowBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, ApplicationIntegratio"
  },
  {
    "path": "apps/bot/commands/General/uptime.ts",
    "chars": 2134,
    "preview": "import { EmbedBuilder, time, ButtonBuilder, ActionRowBuilder, ApplicationCommandType, ButtonStyle, ApplicationIntegratio"
  },
  {
    "path": "apps/bot/commands/Giveaway/giveaway.ts",
    "chars": 7216,
    "preview": "import { ApplicationCommandType, ApplicationCommandOptionType, ChannelType, PermissionFlagsBits, ApplicationIntegrationT"
  },
  {
    "path": "apps/bot/commands/Image/achievement.ts",
    "chars": 2220,
    "preview": "import { loadImage, createCanvas } from \"@napi-rs/canvas\";\nimport { ApplicationCommandType, ApplicationCommandOptionType"
  },
  {
    "path": "apps/bot/commands/Image/ai.ts",
    "chars": 3590,
    "preview": "import { ApplicationCommandType, ApplicationCommandOptionType, AttachmentBuilder, EmbedBuilder, codeBlock, InteractionCo"
  },
  {
    "path": "apps/bot/commands/Image/bangladesh.ts",
    "chars": 3096,
    "preview": "import { shortenText } from \"@majoexe/util/functions/util\";\nimport { loadImage, createCanvas } from \"@napi-rs/canvas\";\ni"
  },
  {
    "path": "apps/bot/commands/Image/change-my-mind.ts",
    "chars": 3090,
    "preview": "import { getLines } from \"@majoexe/util/images\";\nimport { loadImage, createCanvas } from \"@napi-rs/canvas\";\nimport { App"
  },
  {
    "path": "apps/bot/commands/Image/dog-say.ts",
    "chars": 2533,
    "preview": "import { getLines } from \"@majoexe/util/images\";\nimport { loadImage, createCanvas } from \"@napi-rs/canvas\";\nimport { App"
  },
  {
    "path": "apps/bot/commands/Image/fbi.ts",
    "chars": 2392,
    "preview": "import { loadImage, createCanvas } from \"@napi-rs/canvas\";\nimport { ApplicationCommandType, ApplicationCommandOptionType"
  },
  {
    "path": "apps/bot/commands/Image/flag.ts",
    "chars": 8397,
    "preview": "import { readFileSync } from \"fs\";\nimport { loadImage, createCanvas, ImageData } from \"@napi-rs/canvas\";\nimport decodeGi"
  },
  {
    "path": "apps/bot/commands/Image/galaxy-note.ts",
    "chars": 3099,
    "preview": "import { shortenText } from \"@majoexe/util/functions/util\";\nimport { loadImage, createCanvas } from \"@napi-rs/canvas\";\ni"
  },
  {
    "path": "apps/bot/commands/Image/image.ts",
    "chars": 23883,
    "preview": "/* eslint-disable complexity */\nimport { createCanvas, loadImage } from \"@napi-rs/canvas\";\nimport { isColor } from \"colo"
  },
  {
    "path": "apps/bot/commands/Image/iq-graph.ts",
    "chars": 4104,
    "preview": "import { getLines } from \"@majoexe/util/images\";\nimport { loadImage, createCanvas } from \"@napi-rs/canvas\";\nimport { App"
  },
  {
    "path": "apps/bot/commands/Image/jail.ts",
    "chars": 3437,
    "preview": "import { loadImage, createCanvas } from \"@napi-rs/canvas\";\nimport { ApplicationCommandType, ApplicationCommandOptionType"
  },
  {
    "path": "apps/bot/commands/Image/note.ts",
    "chars": 2736,
    "preview": "import { getLines } from \"@majoexe/util/images\";\nimport { loadImage, createCanvas } from \"@napi-rs/canvas\";\nimport { App"
  },
  {
    "path": "apps/bot/commands/Image/ph-comment.ts",
    "chars": 4581,
    "preview": "import { loadImage, createCanvas } from \"@napi-rs/canvas\";\nimport { ApplicationCommandType, ApplicationCommandOptionType"
  },
  {
    "path": "apps/bot/commands/Image/sonic-says.ts",
    "chars": 2504,
    "preview": "import { getLines } from \"@majoexe/util/images\";\nimport { loadImage, createCanvas } from \"@napi-rs/canvas\";\nimport { App"
  },
  {
    "path": "apps/bot/commands/Image/trash.ts",
    "chars": 3451,
    "preview": "import { loadImage, createCanvas } from \"@napi-rs/canvas\";\nimport { ApplicationCommandType, ApplicationCommandOptionType"
  },
  {
    "path": "apps/bot/commands/Image/trigger.ts",
    "chars": 4322,
    "preview": "import { loadImage, createCanvas } from \"@napi-rs/canvas\";\nimport { ApplicationCommandType, ApplicationCommandOptionType"
  },
  {
    "path": "apps/bot/commands/Image/type-c.ts",
    "chars": 4087,
    "preview": "import { shortenText } from \"@majoexe/util/functions/util\";\nimport { loadImage, createCanvas } from \"@napi-rs/canvas\";\ni"
  },
  {
    "path": "apps/bot/commands/Image/yt-comment.ts",
    "chars": 4731,
    "preview": "import { loadImage, createCanvas } from \"@napi-rs/canvas\";\nimport { ApplicationCommandType, ApplicationCommandOptionType"
  },
  {
    "path": "apps/bot/commands/Levels/leaderboard.ts",
    "chars": 3953,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { fetchXPSettings } from \"@majoexe/util/database\";\nimport {\n  Appli"
  },
  {
    "path": "apps/bot/commands/Levels/rank.ts",
    "chars": 3605,
    "preview": "import { checkXP, fetchXPSettings } from \"@majoexe/util/database\";\nimport {\n  ApplicationCommandType,\n  ApplicationComma"
  },
  {
    "path": "apps/bot/commands/Levels/reset-xp.ts",
    "chars": 2772,
    "preview": "import { resetXP, fetchXPSettings } from \"@majoexe/util/database\";\nimport {\n  ApplicationCommandType,\n  ApplicationComma"
  },
  {
    "path": "apps/bot/commands/Levels/xp-settings.ts",
    "chars": 8695,
    "preview": "import { setXPLevelUpMessageSettings, setXPSettings, fetchXPSettings } from \"@majoexe/util/database\";\nimport {\n  Applica"
  },
  {
    "path": "apps/bot/commands/Moderation/automod.ts",
    "chars": 12469,
    "preview": "import {\n  ApplicationCommandType,\n  ChannelType,\n  ApplicationCommandOptionType,\n  PermissionsBitField,\n  PermissionFla"
  },
  {
    "path": "apps/bot/commands/Moderation/emoji.ts",
    "chars": 14724,
    "preview": "/* eslint-disable complexity */\n\nimport {\n  ApplicationCommandType,\n  ApplicationCommandOptionType,\n  EmbedBuilder,\n  Pe"
  },
  {
    "path": "apps/bot/commands/Moderation/leave.ts",
    "chars": 10830,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { shortenText } from \"@majoexe/util/functions/util\";\nimport {\n  App"
  },
  {
    "path": "apps/bot/commands/Moderation/logs.ts",
    "chars": 3331,
    "preview": "import { fetchLogs, countLogs } from \"@majoexe/util/database\";\nimport {\n  ApplicationCommandType,\n  ApplicationCommandOp"
  },
  {
    "path": "apps/bot/commands/Moderation/member.ts",
    "chars": 7415,
    "preview": "import { ApplicationCommandType, ApplicationCommandOptionType, PermissionFlagsBits, InteractionContextType, ApplicationI"
  },
  {
    "path": "apps/bot/commands/Moderation/role.ts",
    "chars": 11290,
    "preview": "import {\n  ApplicationCommandType,\n  ApplicationCommandOptionType,\n  PermissionsBitField,\n  EmbedBuilder,\n  Role,\n  Guil"
  },
  {
    "path": "apps/bot/commands/Moderation/slowmode.ts",
    "chars": 3959,
    "preview": "import {\n  ApplicationCommandType,\n  ApplicationCommandOptionType,\n  PermissionsBitField,\n  EmbedBuilder,\n  PermissionFl"
  },
  {
    "path": "apps/bot/commands/Moderation/statistics.ts",
    "chars": 7087,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport type { GuildJoin, GuildLeave, GuildMessage } from \"@majoexe/databas"
  },
  {
    "path": "apps/bot/commands/Moderation/warn.ts",
    "chars": 8577,
    "preview": "import { clearWarns, listWarns, warnUser, removeWarn } from \"@majoexe/util/database\";\nimport {\n  ApplicationCommandType,"
  },
  {
    "path": "apps/bot/commands/Moderation/welcome.ts",
    "chars": 10986,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { shortenText } from \"@majoexe/util/functions/util\";\nimport {\n  App"
  },
  {
    "path": "apps/bot/commands/Reputation/rep.ts",
    "chars": 9017,
    "preview": "import { cacheGet, cacheSet, cacheTTL } from \"@majoexe/database/redis\";\nimport { checkReputation, giveReputation, takeRe"
  },
  {
    "path": "apps/bot/commands/Utility/ascii.ts",
    "chars": 3000,
    "preview": "import { ApplicationCommandType, ApplicationCommandOptionType, EmbedBuilder, AttachmentBuilder, ApplicationIntegrationTy"
  },
  {
    "path": "apps/bot/commands/Utility/base64.ts",
    "chars": 3350,
    "preview": "import { ApplicationCommandType, ApplicationCommandOptionType, EmbedBuilder, InteractionContextType, ApplicationIntegrat"
  },
  {
    "path": "apps/bot/commands/Utility/color.ts",
    "chars": 3496,
    "preview": "import { invertColor } from \"@majoexe/util/images\";\nimport { createCanvas } from \"@napi-rs/canvas\";\nimport { Color, isCo"
  },
  {
    "path": "apps/bot/commands/Utility/minecraft.ts",
    "chars": 4816,
    "preview": "import { ApplicationCommandType, ApplicationCommandOptionType, EmbedBuilder, ApplicationIntegrationType, InteractionCont"
  },
  {
    "path": "apps/bot/commands/Utility/qrcode.ts",
    "chars": 2122,
    "preview": "import { ApplicationCommandType, ApplicationCommandOptionType, EmbedBuilder, AttachmentBuilder, ApplicationIntegrationTy"
  },
  {
    "path": "apps/bot/commands/Utility/translate.ts",
    "chars": 4330,
    "preview": "import translate from \"@iamtraction/google-translate\";\nimport { shortenText } from \"@majoexe/util/functions/util\";\nimpor"
  },
  {
    "path": "apps/bot/events/client/GuildCreate.ts",
    "chars": 488,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { Logger } from \"@majoexe/util/functions/util\";\nimport type { Guild"
  },
  {
    "path": "apps/bot/events/client/GuildDelete.ts",
    "chars": 578,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { Logger } from \"@majoexe/util/functions/util\";\nimport type { Guild"
  },
  {
    "path": "apps/bot/events/client/clientReady.ts",
    "chars": 2725,
    "preview": "import topggSDK from \"@top-gg/sdk\";\nimport { PresenceUpdateStatus, ActivityType, RESTPutAPIApplicationCommandsJSONBody }"
  },
  {
    "path": "apps/bot/events/guild/channelCreate.ts",
    "chars": 1506,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/events/guild/channelDelete.ts",
    "chars": 1675,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/events/guild/channelPinsUpdate.ts",
    "chars": 1423,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/events/guild/channelUpdate.ts",
    "chars": 1998,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/events/guild/emojiCreate.ts",
    "chars": 1499,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/events/guild/emojiDelete.ts",
    "chars": 1371,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/events/guild/emojiUpdate.ts",
    "chars": 1681,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/events/guild/guildBanAdd.ts",
    "chars": 1352,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/events/guild/guildBanRemove.ts",
    "chars": 1258,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/events/guild/guildMemberAdd.ts",
    "chars": 3746,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { shortenText } from \"@majoexe/util/functions/util\";\nimport { Embed"
  },
  {
    "path": "apps/bot/events/guild/guildMemberRemove.ts",
    "chars": 3714,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { shortenText } from \"@majoexe/util/functions/util\";\nimport { Embed"
  },
  {
    "path": "apps/bot/events/guild/guildUpdate.ts",
    "chars": 4462,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/events/guild/interactionCreate.ts",
    "chars": 6385,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { cacheGet, cacheSet, cacheTTL } from \"@majoexe/database/redis\";\nim"
  },
  {
    "path": "apps/bot/events/guild/inviteCreate.ts",
    "chars": 1575,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/events/guild/inviteDelete.ts",
    "chars": 1575,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/events/guild/messageBulkDelete.ts",
    "chars": 1507,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/events/guild/messageCreate.ts",
    "chars": 5993,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { cacheGet, cacheSet } from \"@majoexe/database/redis\";\nimport { fet"
  },
  {
    "path": "apps/bot/events/guild/messageDelete.ts",
    "chars": 1553,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/events/guild/messageUpdate.ts",
    "chars": 1828,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/events/guild/roleCreate.ts",
    "chars": 1619,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/events/guild/roleDelete.ts",
    "chars": 1634,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/events/guild/roleUpdate.ts",
    "chars": 2235,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/events/guild/stickerCreate.ts",
    "chars": 1852,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/events/guild/stickerDelete.ts",
    "chars": 1864,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/events/guild/stickerUpdate.ts",
    "chars": 2603,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { getGuildLogSettings } from \"@majoexe/util/database\";\nim"
  },
  {
    "path": "apps/bot/index.ts",
    "chars": 4960,
    "preview": "import { dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { globalConfig, botConfig, debugge"
  },
  {
    "path": "apps/bot/modals/suggestion.ts",
    "chars": 2768,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { cacheGet, cacheSet, cacheTTL } from \"@majoexe/database/redis\";\nim"
  },
  {
    "path": "apps/bot/package.json",
    "chars": 2118,
    "preview": "{\n  \"name\": \"@majoexe/bot\",\n  \"version\": \"6.0.0\",\n  \"description\": \"Majo.exe have almost everything - Fun, Memes, Images"
  },
  {
    "path": "apps/bot/tsconfig.json",
    "chars": 141,
    "preview": "{\n  \"extends\": \"@majoexe/typescript-config/base\",\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"@/*\":"
  },
  {
    "path": "apps/bot/util/giveaway/core.ts",
    "chars": 1910,
    "preview": "import { globalConfig } from \"@majoexe/config\";\nimport prismaClient from \"@majoexe/database\";\nimport type { Prisma } fro"
  },
  {
    "path": "apps/bot/util/giveaway/endGiveaway.ts",
    "chars": 2813,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { createLog } from \"@majoexe/util/database\";\nimport type "
  },
  {
    "path": "apps/bot/util/giveaway/findGiveaways.ts",
    "chars": 3124,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { GiveawayData } from \"discord-giveaways\";\nimport { type ChatInputC"
  },
  {
    "path": "apps/bot/util/giveaway/pauseGiveaway.ts",
    "chars": 2814,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { createLog } from \"@majoexe/util/database\";\nimport type "
  },
  {
    "path": "apps/bot/util/giveaway/rerollGiveaway.ts",
    "chars": 2820,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { createLog } from \"@majoexe/util/database\";\nimport type "
  },
  {
    "path": "apps/bot/util/giveaway/resumeGiveaway.ts",
    "chars": 2820,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { createLog } from \"@majoexe/util/database\";\nimport type "
  },
  {
    "path": "apps/bot/util/giveaway/startGiveaway.ts",
    "chars": 8337,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { createLog } from \"@majoexe/util/database\";\nimport { typ"
  },
  {
    "path": "apps/bot/util/images/createUserGuildCard.ts",
    "chars": 1196,
    "preview": "import { shortenText } from \"@majoexe/util/functions/util\";\nimport { loadImage, createCanvas } from \"@napi-rs/canvas\";\ni"
  },
  {
    "path": "apps/bot/util/images/createXPCard.ts",
    "chars": 2624,
    "preview": "import { formatNumber, shortenText } from \"@majoexe/util/functions/util\";\nimport { loadImage, createCanvas } from \"@napi"
  },
  {
    "path": "apps/bot/util/loaders/loadCommands.ts",
    "chars": 2332,
    "preview": "import { readDir } from \"@majoexe/util/functions/files/readDir.js\";\nimport { type ApplicationCommandOption, ApplicationC"
  },
  {
    "path": "apps/bot/util/loaders/loadEmojis.ts",
    "chars": 6762,
    "preview": "import { globalConfig } from \"@majoexe/config\";\nimport { Logger } from \"@majoexe/util/functions/util\";\nimport type { API"
  },
  {
    "path": "apps/bot/util/loaders/loadEvents.ts",
    "chars": 970,
    "preview": "import { basename } from \"node:path\";\nimport { readDir } from \"@majoexe/util/functions/files/readDir.js\";\nimport type { "
  },
  {
    "path": "apps/bot/util/loaders/loadFonts.ts",
    "chars": 808,
    "preview": "import { readDir } from \"@majoexe/util/functions/files/readDir.js\";\nimport { GlobalFonts } from \"@napi-rs/canvas\";\nimpor"
  },
  {
    "path": "apps/bot/util/loaders/loadModals.ts",
    "chars": 1492,
    "preview": "import { readDir } from \"@majoexe/util/functions/files/readDir.js\";\nimport type { ModalSubmitInteraction } from \"discord"
  },
  {
    "path": "apps/bot/util/moderation/automod/antiBadWords/disable.ts",
    "chars": 1478,
    "preview": "import { syncDatabaseAutoModRule } from \"@majoexe/util/database\";\nimport { ChatInputCommandInteraction, EmbedBuilder } f"
  },
  {
    "path": "apps/bot/util/moderation/automod/antiBadWords/enable.ts",
    "chars": 7557,
    "preview": "import { createDatabaseAutoModRule, syncDatabaseAutoModRule } from \"@majoexe/util/database\";\nimport {\n  ChannelType,\n  A"
  },
  {
    "path": "apps/bot/util/moderation/automod/antiInvite/disable.ts",
    "chars": 1470,
    "preview": "import { syncDatabaseAutoModRule } from \"@majoexe/util/database\";\nimport { ChatInputCommandInteraction, EmbedBuilder } f"
  },
  {
    "path": "apps/bot/util/moderation/automod/antiInvite/enable.ts",
    "chars": 7619,
    "preview": "import { createDatabaseAutoModRule, syncDatabaseAutoModRule } from \"@majoexe/util/database\";\nimport {\n  ChannelType,\n  A"
  },
  {
    "path": "apps/bot/util/moderation/automod/antiLinks/disable.ts",
    "chars": 1450,
    "preview": "import { syncDatabaseAutoModRule } from \"@majoexe/util/database\";\nimport { ChatInputCommandInteraction, EmbedBuilder } f"
  },
  {
    "path": "apps/bot/util/moderation/automod/antiLinks/enable.ts",
    "chars": 7479,
    "preview": "import { createDatabaseAutoModRule, syncDatabaseAutoModRule } from \"@majoexe/util/database\";\nimport {\n  ChannelType,\n  A"
  },
  {
    "path": "apps/bot/util/moderation/automod/antiMention/disable.ts",
    "chars": 1468,
    "preview": "import { syncDatabaseAutoModRule } from \"@majoexe/util/database\";\nimport { ChatInputCommandInteraction, EmbedBuilder } f"
  },
  {
    "path": "apps/bot/util/moderation/automod/antiMention/enable.ts",
    "chars": 7525,
    "preview": "import { createDatabaseAutoModRule, syncDatabaseAutoModRule } from \"@majoexe/util/database\";\nimport {\n  ChannelType,\n  A"
  },
  {
    "path": "apps/bot/util/moderation/automod/antiSpam/disable.ts",
    "chars": 1453,
    "preview": "import { syncDatabaseAutoModRule } from \"@majoexe/util/database\";\nimport { ChatInputCommandInteraction, EmbedBuilder } f"
  },
  {
    "path": "apps/bot/util/moderation/automod/antiSpam/enable.ts",
    "chars": 6701,
    "preview": "import { createDatabaseAutoModRule, syncDatabaseAutoModRule } from \"@majoexe/util/database\";\nimport {\n  ChannelType,\n  A"
  },
  {
    "path": "apps/bot/util/moderation/automod/index.ts",
    "chars": 496,
    "preview": "// AntiBadWords\nexport * from \"./antiBadWords/disable\";\nexport * from \"./antiBadWords/enable\";\n\n// AntiInvite\nexport * f"
  },
  {
    "path": "apps/bot/util/moderation/automod/settings/index.ts",
    "chars": 2399,
    "preview": "import { syncDatabaseAutoModRule } from \"@majoexe/util/database\";\nimport { ChatInputCommandInteraction, EmbedBuilder, co"
  },
  {
    "path": "apps/bot/util/moderation/ban.ts",
    "chars": 2994,
    "preview": "import { ChatInputCommandInteraction, EmbedBuilder, GuildMember, GuildMemberRoleManager, PermissionsBitField, type Color"
  },
  {
    "path": "apps/bot/util/moderation/changeMemberNickname.ts",
    "chars": 5146,
    "preview": "import { ChatInputCommandInteraction, EmbedBuilder, GuildMember, GuildMemberRoleManager, PermissionsBitField, type Color"
  },
  {
    "path": "apps/bot/util/moderation/getMemberImages.ts",
    "chars": 4811,
    "preview": "import { EmbedBuilder, ActionRowBuilder, ButtonStyle, ButtonBuilder, ChatInputCommandInteraction, type ColorResolvable, "
  },
  {
    "path": "apps/bot/util/moderation/getMemberInfo.ts",
    "chars": 3652,
    "preview": "import { ChatInputCommandInteraction, EmbedBuilder, GuildMember, type ColorResolvable } from \"discord.js\";\nimport type {"
  },
  {
    "path": "apps/bot/util/moderation/kick.ts",
    "chars": 2902,
    "preview": "import { ChatInputCommandInteraction, EmbedBuilder, GuildMember, GuildMemberRoleManager, PermissionsBitField, type Color"
  },
  {
    "path": "apps/bot/util/moderation/unban.ts",
    "chars": 2116,
    "preview": "import { ChatInputCommandInteraction, EmbedBuilder, PermissionsBitField, type ColorResolvable } from \"discord.js\";\nimpor"
  },
  {
    "path": "apps/bot/util/types/Command.ts",
    "chars": 1088,
    "preview": "import type { Guild, GuildDisabledCategories, GuildDisabledCommands } from \"@majoexe/database/types\";\nimport { type Chat"
  },
  {
    "path": "apps/dashboard/.env.example",
    "chars": 85,
    "preview": "# Dashboard\nSECRET=\nNEXTAUTH_URL=\nNEXT_PUBLIC_URL=\n\n# Hotjar ID (Optional)\nHOTJAR_ID="
  },
  {
    "path": "apps/dashboard/.gitignore",
    "chars": 12,
    "preview": "node_modules"
  },
  {
    "path": "apps/dashboard/.prettierignore",
    "chars": 18,
    "preview": "package.json\n.next"
  },
  {
    "path": "apps/dashboard/README.md",
    "chars": 7784,
    "preview": "![Header - Dashboard](https://github.com/IgorKowalczyk/majo.exe/assets/49127376/4056d368-0400-415a-b647-4d97bd8009c1)\n\n<"
  },
  {
    "path": "apps/dashboard/app/_components/AddReaction.tsx",
    "chars": 1234,
    "preview": "\"use client\";\n\nimport { useState } from \"react\";\nimport { toast } from \"sonner\";\nimport Image from \"@/components/ui/Imag"
  },
  {
    "path": "apps/dashboard/app/_components/BotReplacement.tsx",
    "chars": 3012,
    "preview": "\"use client\";\n\nimport { globalConfig } from \"@majoexe/config\";\nimport { BotIcon, UserIcon } from \"lucide-react\";\nimport "
  },
  {
    "path": "apps/dashboard/app/_components/ExampleChart.tsx",
    "chars": 1515,
    "preview": "\"use client\";\n\nimport { pseudoRandom } from \"@majoexe/util/functions/util\";\nimport React from \"react\";\nimport { Suspense"
  },
  {
    "path": "apps/dashboard/app/_components/LevelUp.tsx",
    "chars": 1464,
    "preview": "\"use client\";\n\nimport React, { useState } from \"react\";\nimport { toast } from \"sonner\";\nimport Image from \"@/components/"
  },
  {
    "path": "apps/dashboard/app/_components/Notifications.tsx",
    "chars": 2919,
    "preview": "import Image from \"next/image\";\nimport avatar01 from \"public/assets/avatars/01.webp\";\nimport avatar02 from \"public/asset"
  },
  {
    "path": "apps/dashboard/app/api/auth/[...nextauth]/route.ts",
    "chars": 161,
    "preview": "import authOptions from \"lib/authOptions\";\nimport NextAuth from \"next-auth\";\n\nconst handler = NextAuth(authOptions);\nexp"
  },
  {
    "path": "apps/dashboard/app/api/cron/cleanup/route.ts",
    "chars": 3042,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { Logger } from \"@majoexe/util/functions/util\";\nimport { NextReques"
  },
  {
    "path": "apps/dashboard/app/api/invite/[invite]/route.ts",
    "chars": 715,
    "preview": "import { globalPermissions } from \"@majoexe/config/permissions\";\nimport { NextRequest, NextResponse } from \"next/server\""
  },
  {
    "path": "apps/dashboard/app/api/invite/route.ts",
    "chars": 462,
    "preview": "import { globalPermissions } from \"@majoexe/config/permissions\";\nimport { NextResponse } from \"next/server\";\nimport { en"
  },
  {
    "path": "apps/dashboard/app/api/logs/[serverId]/route.ts",
    "chars": 3616,
    "preview": "import { fetchLogs } from \"@majoexe/util/database\";\nimport { getGuild, getGuildFromMemberGuilds } from \"@majoexe/util/fu"
  },
  {
    "path": "apps/dashboard/app/api/settings/automod/anti-invite/route.ts",
    "chars": 8373,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { GuildLogType } from \"@majoexe/database/types\";\nimport { createLog"
  },
  {
    "path": "apps/dashboard/app/api/settings/automod/anti-link/route.ts",
    "chars": 8317,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { GuildLogType } from \"@majoexe/database/types\";\nimport { createLog"
  },
  {
    "path": "apps/dashboard/app/api/settings/automod/anti-mention/route.ts",
    "chars": 8434,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { GuildLogType } from \"@majoexe/database/types\";\nimport { createLog"
  },
  {
    "path": "apps/dashboard/app/api/settings/automod/anti-spam/route.ts",
    "chars": 8109,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { GuildLogType } from \"@majoexe/database/types\";\nimport { createLog"
  },
  {
    "path": "apps/dashboard/app/api/settings/categories/route.ts",
    "chars": 6995,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { GuildLogType } from \"@majoexe/database/types\";\nimport { createLog"
  },
  {
    "path": "apps/dashboard/app/api/settings/change-reputation/route.ts",
    "chars": 6371,
    "preview": "import { GuildLogType } from \"@majoexe/database/types\";\nimport { createLog, setReputation } from \"@majoexe/util/database"
  },
  {
    "path": "apps/dashboard/app/api/settings/commands/route.ts",
    "chars": 7382,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { GuildLogType } from \"@majoexe/database/types\";\nimport { createLog"
  },
  {
    "path": "apps/dashboard/app/api/settings/delete-data/route.ts",
    "chars": 3819,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { getGuild, getGuildFromMemberGuilds } from \"@majoexe/util/function"
  },
  {
    "path": "apps/dashboard/app/api/settings/download/[id]/route.ts",
    "chars": 5702,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { getGuild, getGuildFromMemberGuilds } from \"@majoexe/util/function"
  },
  {
    "path": "apps/dashboard/app/api/settings/embed-color/route.ts",
    "chars": 8872,
    "preview": "import { globalConfig } from \"@majoexe/config\";\nimport prismaClient from \"@majoexe/database\";\nimport { GuildLogType } fr"
  },
  {
    "path": "apps/dashboard/app/api/settings/messages/leave/route.ts",
    "chars": 7655,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { GuildLogType } from \"@majoexe/database/types\";\nimport { createLog"
  },
  {
    "path": "apps/dashboard/app/api/settings/messages/welcome/route.ts",
    "chars": 7993,
    "preview": "import { globalConfig } from \"@majoexe/config\";\nimport prismaClient from \"@majoexe/database\";\nimport { GuildLogType } fr"
  },
  {
    "path": "apps/dashboard/app/api/settings/public-dashboard/route.ts",
    "chars": 4524,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { GuildLogType } from \"@majoexe/database/types\";\nimport { createLog"
  },
  {
    "path": "apps/dashboard/app/api/settings/public-vanity/route.ts",
    "chars": 5675,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { GuildLogType } from \"@majoexe/database/types\";\nimport { createLog"
  },
  {
    "path": "apps/dashboard/app/api/settings/reset-user-xp/route.ts",
    "chars": 4220,
    "preview": "import { resetXP } from \"@majoexe/util/database\";\nimport { getGuild, getGuildFromMemberGuilds } from \"@majoexe/util/func"
  },
  {
    "path": "apps/dashboard/app/api/settings/update-logs/route.ts",
    "chars": 5098,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { GuildLogType } from \"@majoexe/database/types\";\nimport { createLog"
  },
  {
    "path": "apps/dashboard/app/api/user/avatar/[id]/route.ts",
    "chars": 854,
    "preview": "import { getDiscordUser } from \"@majoexe/util/functions/user\";\nimport { redirect } from \"next/navigation\";\nimport { Next"
  },
  {
    "path": "apps/dashboard/app/api/user/avatar-decoration/[id]/route.ts",
    "chars": 965,
    "preview": "import { getDiscordUser } from \"@majoexe/util/functions/user\";\nimport { redirect } from \"next/navigation\";\nimport { Next"
  },
  {
    "path": "apps/dashboard/app/api/user/banner/[id]/route.ts",
    "chars": 854,
    "preview": "import { getDiscordUser } from \"@majoexe/util/functions/user\";\nimport { redirect } from \"next/navigation\";\nimport { Next"
  },
  {
    "path": "apps/dashboard/app/api/user/delete/route.ts",
    "chars": 1791,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { getSession } from \"lib/session\";\nimport { NextResponse } from \"ne"
  },
  {
    "path": "apps/dashboard/app/api/user/download/route.ts",
    "chars": 2996,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { getSession } from \"lib/session\";\nimport { NextResponse } from \"ne"
  },
  {
    "path": "apps/dashboard/app/api/warns/[serverId]/[warnId]/route.ts",
    "chars": 4134,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { GuildLogType } from \"@majoexe/database/types\";\nimport { createLog"
  },
  {
    "path": "apps/dashboard/app/auth/error/page.tsx",
    "chars": 1732,
    "preview": "import { HomeIcon } from \"lucide-react\";\nimport Link from \"next/link\";\nimport { buttonVariants } from \"@/components/ui/B"
  },
  {
    "path": "apps/dashboard/app/auth/login/page.tsx",
    "chars": 2853,
    "preview": "import { getSession } from \"lib/session\";\nimport { HomeIcon, XIcon } from \"lucide-react\";\nimport Link from \"next/link\";\n"
  },
  {
    "path": "apps/dashboard/app/commands/page.tsx",
    "chars": 3159,
    "preview": "import { dashboardConfig } from \"@majoexe/config\";\nimport prismaClient from \"@majoexe/database\";\nimport { ApplicationCom"
  },
  {
    "path": "apps/dashboard/app/dashboard/[server]/automod/components/AntiInvite.tsx",
    "chars": 8151,
    "preview": "\"use client\";\n\nimport { APIAutoModerationRule, APIGuildChannel, GuildChannelType } from \"discord-api-types/v10\";\nimport "
  },
  {
    "path": "apps/dashboard/app/dashboard/[server]/automod/components/AntiLink.tsx",
    "chars": 8131,
    "preview": "\"use client\";\n\nimport { APIAutoModerationRule, APIGuildChannel, GuildChannelType } from \"discord-api-types/v10\";\nimport "
  },
  {
    "path": "apps/dashboard/app/dashboard/[server]/automod/components/AntiMention.tsx",
    "chars": 9935,
    "preview": "\"use client\";\n\nimport { APIAutoModerationRule, APIGuildChannel, GuildChannelType } from \"discord-api-types/v10\";\nimport "
  },
  {
    "path": "apps/dashboard/app/dashboard/[server]/automod/components/AntiSpam.tsx",
    "chars": 8171,
    "preview": "\"use client\";\n\nimport { APIAutoModerationRule, APIGuildChannel, GuildChannelType } from \"discord-api-types/v10\";\nimport "
  },
  {
    "path": "apps/dashboard/app/dashboard/[server]/automod/components/DeleteMessage.tsx",
    "chars": 1961,
    "preview": "import { AutoModerationActionType, APIAutoModerationAction } from \"discord-api-types/v10\";\nimport { TrashIcon } from \"lu"
  },
  {
    "path": "apps/dashboard/app/dashboard/[server]/automod/components/Limit.tsx",
    "chars": 2304,
    "preview": "\"use client\";\n\nimport React from \"react\";\nimport { Icons, iconVariants } from \"@/components/ui/Icons\";\nimport { Select, "
  },
  {
    "path": "apps/dashboard/app/dashboard/[server]/automod/components/LogChannel.tsx",
    "chars": 2323,
    "preview": "import { APIAutoModerationAction, APIGuildChannel, AutoModerationActionType, GuildChannelType } from \"discord-api-types/"
  },
  {
    "path": "apps/dashboard/app/dashboard/[server]/automod/components/TimeoutMember.tsx",
    "chars": 2031,
    "preview": "import { AutoModerationActionType, type APIAutoModerationAction } from \"discord-api-types/v10\";\nimport { TimerIcon } fro"
  },
  {
    "path": "apps/dashboard/app/dashboard/[server]/automod/loading.tsx",
    "chars": 10704,
    "preview": "import {\n  HashIcon,\n  UsersIcon,\n  BotIcon,\n  ShieldMinusIcon,\n  MoveVerticalIcon,\n  CheckIcon,\n  ShieldBanIcon,\n  Arro"
  },
  {
    "path": "apps/dashboard/app/dashboard/[server]/automod/page.tsx",
    "chars": 7054,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { syncDatabaseAutoModRule } from \"@majoexe/util/database\";\nimport {"
  },
  {
    "path": "apps/dashboard/app/dashboard/[server]/dashboard-logs/components/Logs.tsx",
    "chars": 6987,
    "preview": "\"use client\";\n\nimport type { GuildLogs, User } from \"@majoexe/database/types\";\nimport { formatDate, formatDuration } fro"
  },
  {
    "path": "apps/dashboard/app/dashboard/[server]/dashboard-logs/loading.tsx",
    "chars": 954,
    "preview": "import { LogsIcon } from \"lucide-react\";\nimport { Block } from \"@/components/ui/Block\";\nimport Header, { headerVariants "
  },
  {
    "path": "apps/dashboard/app/dashboard/[server]/dashboard-logs/page.tsx",
    "chars": 2924,
    "preview": "import prismaClient from \"@majoexe/database\";\nimport { getGuildFromMemberGuilds, getGuild } from \"@majoexe/util/function"
  },
  {
    "path": "apps/dashboard/app/dashboard/[server]/giveaways/components/Giveaways.tsx",
    "chars": 6215,
    "preview": "\"use client\";\n\nimport type { User } from \"@majoexe/database/types\";\nimport { formatDate, formatDuration } from \"@majoexe"
  }
]

// ... and 292 more files (download for full content)

About this extraction

This page contains the full source code of the IgorKowalczyk/majobot GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 492 files (2.4 MB), approximately 658.9k tokens, and a symbol index with 396 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!