/ src / modules / commands / language.ts
language.ts
  1  import { __h_dc, locales, localesMap } from './../messages';
  2  import { Locale, SlashCommandBuilder, EmbedBuilder } from 'discord.js';
  3  import { Command } from '../commandHandler';
  4  import { prepare, getGuildConfig, getLang, getUserConfig } from '../db';
  5  import { __ } from '../messages';
  6  import config from '../config';
  7  import { createHash } from 'crypto';
  8  
  9  export default {
 10    data: new SlashCommandBuilder()
 11      .setName('language')
 12      .setDescription('Sets the language of the bot')
 13      .setDescriptionLocalizations(__h_dc('Sets the language of the bot'))
 14      .addSubcommand(subcommand =>
 15        subcommand
 16          .setName('guild')
 17          .setDescription('sets the language for the guild')
 18          .setDescriptionLocalizations(__h_dc('sets the language for the guild'))
 19          .addStringOption(option =>
 20            option
 21              .setName('language')
 22              .setDescription('The language to set the bot to')
 23              .setRequired(false)
 24              .addChoices(
 25                ...locales.map(locale => {
 26                  return { name: localesMap[locale], value: locale };
 27                })
 28              )
 29          )
 30      )
 31      .addSubcommand(subcommand =>
 32        subcommand
 33          .setName('user')
 34          .setDescription('sets the language for the user. Overwrites the guild language.')
 35          .setDescriptionLocalizations(
 36            __h_dc('sets the language for the user. Overwrites the guild language.')
 37          )
 38          .addStringOption(option =>
 39            option
 40              .setName('language')
 41              .setDescription('The language to set the bot to')
 42              .setRequired(false)
 43              .addChoices(
 44                { name: 'Undefined', value: 'none' },
 45                ...locales.map(locale => {
 46                  return { name: localesMap[locale], value: locale };
 47                })
 48              )
 49          )
 50      ),
 51    execute: async interaction => {
 52      let locale = getLang(interaction);
 53      //@ts-ignore: getSubcommand() is not defined in the typings
 54      const subcommand = interaction.options.getSubcommand() as 'guild' | 'user';
 55      const newLanguage = interaction.options.get('language')?.value as Locale | 'none' | undefined;
 56  
 57      if (subcommand === 'guild') {
 58        if (!interaction.guild) {
 59          interaction.reply({
 60            content: __({ phrase: 'You can only set the guild language in a guild!', locale }),
 61            ephemeral: true
 62          });
 63          return;
 64        }
 65  
 66        const guildLanguage = getGuildConfig(interaction.guild.id).language;
 67        if (!newLanguage) {
 68          interaction.reply({
 69            embeds: [
 70              new EmbedBuilder()
 71                .setTitle(__({ phrase: 'Languages', locale }))
 72                .setDescription(
 73                  __(
 74                    { phrase: 'The current guild language is **`%s`**.', locale },
 75                    localesMap[guildLanguage]
 76                  ) +
 77                  '\n\n' +
 78                  __(
 79                    {
 80                      phrase:
 81                        'If you want to help translating the bot, you can do so at %s. Thanks!',
 82                      locale
 83                    },
 84                    'https://crowdin.com/project/activity-roles'
 85                  )
 86                )
 87                .setColor(config.COLOR)
 88            ]
 89          }); //TODO reply with language list with percentages and link to crowdin and credits.
 90          return;
 91        }
 92  
 93        if (!interaction.memberPermissions?.has('ManageRoles')) {
 94          interaction.reply({
 95            content: __({
 96              phrase: 'You need the `manage roles` permission to set the guild language.',
 97              locale
 98            }),
 99            ephemeral: true
100          });
101          return;
102        }
103        if (guildLanguage === newLanguage) {
104          interaction.reply({
105            content:
106              __(
107                { phrase: 'The language is already set to **`%s`**.', locale },
108                localesMap[newLanguage]
109              ) +
110              '\n\n' +
111              __({
112                phrase:
113                  'The language of the command names and description is managed by your Discord language.',
114                locale
115              }),
116            ephemeral: true
117          });
118          return;
119        }
120        prepare('UPDATE guilds SET language = ? WHERE guildID = ?').run(
121          newLanguage,
122          interaction.guild.id
123        );
124        locale = getLang(interaction);
125        interaction.reply({
126          embeds: [
127            new EmbedBuilder()
128              .setDescription(
129                __(
130                  { phrase: 'Guild language set to **`%s`**', locale },
131                  localesMap[newLanguage]
132                )
133              )
134              .setColor(config.COLOR)
135          ],
136          ephemeral: true
137        });
138      } else if (subcommand === 'user') {
139        const userLanguage = getUserConfig(interaction.user.id).language;
140        if (!newLanguage) {
141          interaction.reply({
142            embeds: [
143              new EmbedBuilder()
144                .setTitle(__({ phrase: 'Languages', locale }))
145                .setDescription(
146                  __(
147                    { phrase: 'The current user language is **`%s`**.%s', locale },
148                    localesMap[userLanguage] || __({ phrase: 'undefined', locale }),
149                    userLanguage === 'none'
150                      ? __({ phrase: ' The guild language will be used.', locale })
151                      : ''
152                  ) +
153                  '\n\n' +
154                  __({
155                    phrase:
156                      'The language of the command names and description is managed by your Discord language.',
157                    locale
158                  }) +
159                  '\n\n' +
160                  __(
161                    {
162                      phrase:
163                        'If you want to help translating the bot, you can do so at %s. Thanks!',
164                      locale
165                    },
166                    'https://crowdin.com/project/activity-roles'
167                  )
168                )
169                .setColor(config.COLOR)
170            ]
171          }); //TODO reply with language list with percentages and link to crowdin and credits.
172          return;
173        }
174  
175        if (getUserConfig(interaction.user.id).language === newLanguage) {
176          interaction.reply({
177            content:
178              __(
179                { phrase: 'The language is already set to **`%s`**.%s', locale },
180                localesMap[newLanguage] || 'undefined',
181                newLanguage === 'none'
182                  ? __({ phrase: ' The guild language will be used.', locale })
183                  : ''
184              ) +
185              '\n\n' +
186              __({
187                phrase:
188                  'The language of the command names and description is managed by your Discord language.',
189                locale
190              }),
191            ephemeral: true
192          });
193          return;
194        }
195        prepare('UPDATE users SET language = ? WHERE userIDHash = ?').run(
196          newLanguage,
197          createHash('sha256').update(interaction.user.id).digest('base64')
198        );
199        locale = getLang(interaction);
200        interaction.reply({
201          embeds: [
202            new EmbedBuilder()
203              .setDescription(
204                __(
205                  { phrase: 'User language set to **`%s`**.%s', locale },
206                  localesMap[newLanguage] || 'undefined',
207                  newLanguage === 'none'
208                    ? __({ phrase: ' The guild language will be used.', locale })
209                    : ''
210                ) +
211                '\n\n' +
212                __({
213                  phrase:
214                    'The language of the command names and description is managed by your Discord language.',
215                  locale
216                })
217              )
218              .setColor(config.COLOR)
219          ],
220          ephemeral: true
221        });
222      }
223    }
224  } as Command;