diff --git a/locale/Messages.resx b/locale/Messages.resx
index 6957663..1a5da43 100644
--- a/locale/Messages.resx
+++ b/locale/Messages.resx
@@ -1,6 +1,7 @@
-
+
+
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
- PublicKeyToken=b77a5c561934e089
-
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
- PublicKeyToken=b77a5c561934e089
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
I'm ready!
-
+
Deleted message by {0}:
-
+
Cleared message from {0} in channel {1}: {2}
-
+
Edited message by {0}:
-
+
{0}, welcome to {1}
-
+
Bah!
-
+
Bop!
-
+
Beep!
-
+
I do not have permission to execute this command!
-
+
You do not have permission to execute this command!
-
+
You were banned
-
+
Punishment expired
-
+
You specified less than {0} messages!
-
+
You specified more than {0} messages!
-
+
Command help:
-
+
You were kicked
-
+
ms
-
+
Member is already muted!
-
+
Not specified
-
+
Not specified
-
+
Current settings:
-
+
Language
-
+
Prefix
-
+
Remove roles on mute
-
+
Send welcome messages
-
+
Mute role
-
- Language not supported!
-
-
+
+ Language not supported!
+
+
Yes
-
+
No
-
+
This user is not banned!
-
+
Member not muted!
-
+
Welcome message
-
+
You need to specify an integer from {0} to {1} instead of {2}!
-
+
{0} was banned
-
+
That setting doesn't exist!
-
+
Receive startup messages
-
+
Invalid setting value specified!
-
+
This role does not exist!
-
+
This channel does not exist!
-
+
I cannot mute someone for more than 28 days using timeouts! Either specify a duration shorter than 28 days, or set a mute role in settings
-
+
I cannot use time-outs on other bots! Try to set a mute role in settings
-
+
{0} has created event {1}! It will take place in {2} and will start <t:{3}:R>! \n {4}
-
+
Role for event creation notifications
-
+
Channel for event notifications
-
+
Event start notifications receivers
-
+
Event "{0}" started
-
+
:(
-
+
Event "{0}" is cancelled!
-
+
Event "{0}" has completed!
-
+
ever
-
+
Cleared {0} messages
-
+
Kicked {0}: {1}
-
+
Muted {0} for{1}: {2}
-
+
Unbanned {0}: {1}
-
+
Unmuted {0}: {1}
-
+
Nothing changed! `{0}` is already set to {1}
-
+
Not specified
-
+
Value of setting `{0}` is now set to {1}
-
+
Bans a user
-
+
Deletes a specified amount of messages in this channel
-
+
Shows this message
-
+
Kicks a member
-
+
Mutes a member
-
+
Shows (inaccurate) latency
-
+
Allows you to change certain preferences for this guild
-
+
Unbans a user
-
+
Unmutes a member
-
+
You need to specify an integer from {0} to {1}!
-
+
You need to specify a user!
-
+
You need to specify a user instead of {0}!
-
+
You need to specify a guild member!
-
+
You need to specify a member of this guild!
-
+
You cannot ban users from this guild!
-
+
You cannot manage messages in this guild!
-
+
You cannot kick members from this guild!
-
+
You cannot moderate members in this guild!
-
+
You cannot manage this guild!
-
+
I cannot ban users from this guild!
-
+
I cannot manage messages in this guild!
-
+
I cannot kick members from this guild!
-
+
I cannot moderate members in this guild!
-
+
I cannot manage this guild!
-
+
You need to specify a reason to ban this user!
-
+
You need to specify a reason to kick this member!
-
+
You need to specify a reason to mute this member!
-
+
You need to specify a reason to unban this user!
-
+
You need to specify a reason for unmute this member!
-
+
You cannot ban the owner of this guild!
-
+
You cannot ban yourself!
-
+
You cannot ban me!
-
+
I cannot ban this user!
-
+
You cannot ban this user!
-
+
You cannot kick the owner of this guild!
-
+
You cannot kick yourself!
-
+
You cannot kick me!
-
+
I cannot kick this member!
-
+
You cannot kick this member!
-
+
You cannot mute the owner of this guild!
-
+
You cannot mute yourself!
-
+
You cannot mute me!
-
+
I cannot mute this member!
-
+
You cannot mute this member!
-
+
You don't need to unmute the owner of this guild!
-
+
You are muted!
-
+
...
-
+
I cannot unmute this member!
-
+
You cannot unmute this user!
-
+
Event "{0}" will start {1}!
-
+
Early event start notification offset
-
+
I could not find this user in any guild I'm a member of! Check if the ID is correct and that the user was on this server no longer than 30 days ago
-
+
Default role
-
+
Adds a reminder
-
+
Channel for public notifications
-
+
Channel for private notifications
-
+
Return roles on rejoin
-
+
Automatically start scheduled events
-
+
You need to specify reminder text!
-
+
You need to specify when I should send you the reminder!
-
+
Issued by
-
+
{0} has created a new event:
-
+
The event will start at {0} in {1}
-
+
The event will start at {0} until {1} in {2}
-
+
Event details
-
+
The event has lasted for `{0}`
-
+
The event is happening at {0}
-
+
The event is happening at {0} until {1}
-
+
This user is already banned!
-
+
{0} was unbanned
-
+
{0} was muted
-
+
{0} was unmuted
-
+
This member is not muted!
-
+
I could not find this user!
-
+
{0} was kicked
-
+
Reason: {0}
-
+
Expires at: {0}
-
+
This user is already muted!
-
+
From {0}:
-
+
Developers:
-
- Boyfriend's source code
-
-
+
+ Boyfriend's source code
+
+
About Boyfriend
-
- developer & designer, Boyfriend's Wiki creator
-
-
+
+ developer & designer, Boyfriend's Wiki creator
+
+
main developer
-
+
developer
-
- Reminder for {0} created
-
-
- Reminder for {0}
-
-
- You asked me to remind you {0}
-
-
- Boyfriend's Settings
-
-
- Setting successfully changed
-
-
- Setting not changed
-
-
- is now
-
-
- Rename members who attempt to hoist themselves
-
-
- Page
-
-
- Page not found!
-
-
- There are {0} total pages
-
-
- Next
-
-
- Previous
-
+
+ Reminder for {0} created
+
+
+ Reminder for {0}
+
+
+ You asked me to remind you {0}
+
+
+ Boyfriend's Settings
+
+
+ Setting successfully changed
+
+
+ Setting not changed
+
+
+ is now
+
+
+ Rename members who attempt to hoist themselves
+
+
+ Page
+
+
+ Page not found!
+
+
+ There are {0} total pages
+
+
+ Next
+
+
+ Previous
+
- {0}'s reminders
-
+ {0}'s reminders
+
- There's no reminder with that index!
-
+ There's no reminder with that index!
+
- Reminder deleted
-
-
- You don't have any reminders created!
-
-
- Setting {0} reset
-
-
- All settings have been reset
-
-
- Jump to message: {0}
-
-
- Jump to channel: {0}
-
-
- Index: {0}
-
-
- The reminder will be sent on: {0}
-
-
- Reminder text: {0}
-
-
+ Reminder deleted
+
+
+ You don't have any reminders created!
+
+
+ Setting {0} reset
+
+
+ All settings have been reset
+
+
+ Jump to message: {0}
+
+
+ Jump to channel: {0}
+
+
+ Index: {0}
+
+
+ The reminder will be sent on: {0}
+
+
+ Reminder text: {0}
+
+
+ Display name
+
+
+ Information about {0}
+
+
+ Muted
+
+
+ Discord user since
+
+
+ Banned
+
+
+ Punishments
+
+
+ Banned permanently
+
+
+ Not in the guild
+
+
+ Muted by timeout
+
+
+ Muted by mute role
+
+
+ Guild member since
+
+
+ Nickname
+
+
+ Roles
+
+
+ Nitro booster since
+
+
\ No newline at end of file
diff --git a/locale/Messages.ru.resx b/locale/Messages.ru.resx
index 9d9d99d..6f19804 100644
--- a/locale/Messages.ru.resx
+++ b/locale/Messages.ru.resx
@@ -1,6 +1,7 @@
-
+
+
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
- PublicKeyToken=b77a5c561934e089
-
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
- PublicKeyToken=b77a5c561934e089
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
Я запустился!
-
+
Сообщение {0} удалено:
-
+
Очищено сообщение от {0} в канале {1}: {2}
-
+
Сообщение {0} отредактировано:
-
+
{0}, добро пожаловать на сервер {1}
-
+
Бап!
-
+
Боп!
-
+
Бип!
-
+
У меня недостаточно прав для выполнения этой команды!
-
+
У тебя недостаточно прав для выполнения этой команды!
-
+
Время наказания истекло
-
+
Указано менее {0} сообщений!
-
+
Указано более {0} сообщений!
-
+
Справка по командам:
-
+
Вы были выгнаны
-
+
мс
-
+
Участник уже заглушен!
-
+
Не указан
-
+
Не указана
-
+
Текущие настройки:
-
+
Язык
-
+
Префикс
-
+
Удалять роли при муте
-
+
Отправлять приветствия
-
+
Роль мута
-
- Язык не поддерживается!
-
-
+
+ Язык не поддерживается!
+
+
Да
-
+
Нет
-
+
Этот пользователь не забанен!
-
+
Участник не заглушен!
-
+
Приветствие
-
+
Надо указать целое число от {0} до {1} вместо {2}!
-
+
{0} был(-а) забанен(-а)
-
+
Такая настройка не существует!
-
+
Получать сообщения о запуске
-
+
Указано недействительное значение для настройки!
-
+
Эта роль не существует!
-
+
Этот канал не существует!
-
+
Я не могу заглушить кого-то на более чем 28 дней, используя тайм-ауты! Или укажи продолжительность менее 28 дней, или установи роль мута в настройках
-
+
Я не могу использовать тайм-ауты на других ботах! Попробуй указать роль мута в настройках
-
+
{0} создал событие {1}! Оно пройдёт в {2} и начнётся <t:{3}:R>!{4}
-
+
Роль для уведомлений о создании событий
-
+
Канал для уведомлений о событиях
-
+
Получатели уведомлений о начале событий
-
+
Событие "{0}" началось
-
+
:(
-
+
Событие "{0}" отменено!
-
+
Событие "{0}" завершено!
-
+
всегда
-
+
Очищено {0} сообщений
-
+
Выгнан {0}: {1}
-
+
Заглушен {0} на{1}: {2}
-
+
Возвращён из бана {0}: {1}
-
+
Разглушен {0}: {1}
-
+
Ничего не изменилось! Значение настройки `{0}` уже {1}
-
+
Не указано
-
+
Значение настройки `{0}` теперь установлено на {1}
-
+
Банит пользователя
-
+
Удаляет указанное количество сообщений в этом канале
-
+
Показывает эту справку
-
+
Выгоняет участника
-
+
Глушит участника
-
+
Показывает (неточную) задержку
-
+
Позволяет менять некоторые настройки под этот сервер
-
+
Возвращает пользователя из бана
-
+
Разглушает участника
-
+
Надо указать целое число от {0} до {1}!
-
+
Надо указать пользователя!
-
+
Надо указать пользователя вместо {0}!
-
+
Надо указать участника сервера!
-
+
Надо указать участника этого сервера!
-
+
Ты не можешь банить пользователей на этом сервере!
-
+
Ты не можешь управлять сообщениями этого сервера!
-
+
Ты не можешь выгонять участников с этого сервера!
-
+
Ты не можешь модерировать участников этого сервера!
-
+
Ты не можешь настраивать этот сервер!
-
+
Я не могу банить пользователей на этом сервере!
-
+
Я не могу управлять сообщениями этого сервера!
-
+
Я не могу выгонять участников с этого сервера!
-
+
Я не могу модерировать участников этого сервера!
-
+
Я не могу настраивать этот сервер!
-
+
Надо указать причину для бана этого участника!
-
+
Надо указать причину для кика этого участника!
-
+
Надо указать причину для мута этого участника!
-
+
Надо указать причину для разбана этого пользователя!
-
+
Надо указать причину для размута этого участника!
-
+
Ты не можешь меня забанить!
-
+
Ты не можешь забанить владельца этого сервера!
-
+
Ты не можешь забанить этого участника!
-
+
Ты не можешь себя забанить!
-
+
Я не могу забанить этого пользователя!
-
+
Ты не можешь выгнать владельца этого сервера!
-
+
Ты не можешь себя выгнать!
-
+
Ты не можешь меня выгнать!
-
+
Я не могу выгнать этого участника
-
+
Ты не можешь выгнать этого участника!
-
+
Ты не можешь заглушить владельца этого сервера!
-
+
Ты не можешь себя заглушить!
-
+
Ты не можешь заглушить меня!
-
+
Я не могу заглушить этого пользователя!
-
+
Ты не можешь заглушить этого участника!
-
+
Тебе не надо возвращать из мута владельца этого сервера!
-
+
Ты заглушен!
-
+
...
-
+
Ты не можешь вернуть из мута этого пользователя!
-
+
Я не могу вернуть из мута этого пользователя!
-
+
Событие "{0}" начнется {1}!
-
+
Офсет отправки преждевременного уведомления о начале события
-
+
Я не смог найти этого пользователя ни в одном из серверов, в которых я есть. Проверь правильность ID и нахождение пользователя на этом сервере максимум 30 дней назад
-
- Роль по умолчанию
-
-
+
+ Роль по умолчанию
+
+
Добавляет напоминание
-
+
Канал для публичных уведомлений
-
+
Канал для приватных уведомлений
-
+
Возвращать роли при перезаходе
-
+
Автоматически начинать события
-
+
Тебе нужно указать текст напоминания!
-
+
Нужно указать время, через которое придёт напоминание!
-
+
Ответственный
-
+
{0} создаёт новое событие:
-
+
Событие пройдёт {0} в канале {1}
-
+
Событие пройдёт с {0} до {1} в {2}
-
+
Подробнее о событии
-
+
Событие длилось `{0}`
-
+
Событие происходит в {0}
-
+
Событие происходит в {0} до {1}
-
+
Этот пользователь уже забанен!
-
+
{0} был(-а) разбанен(-а)
-
+
{0} был(-а) заглушен(-а)
-
+
Этот участник не заглушен!
-
+
{0} был(-а) разглушен(-а)
-
+
Я не смог найти этого пользователя!
-
+
{0} был(-а) выгнан(-а)
-
+
Причина: {0}
-
+
Закончится: {0}
-
+
Этот пользователь уже в муте!
-
+
Вы были забанены
-
+
От {0}:
-
+
Разработчики:
-
- Исходный код Boyfriend
-
-
+
+ Исходный код Boyfriend
+
+
О Boyfriend
-
- разработчик
-
-
+
+ разработчик
+
+
основной разработчик
-
- разработчик и дизайнер, создатель Boyfriend's Wiki
-
-
- Напоминание для {0} создано
-
-
- Напоминание для {0}
-
-
- Вы просили напомнить вам {0}
-
-
- Настройки Boyfriend
-
-
- Настройка успешно изменена
-
-
- Настройка не редактирована
-
-
- теперь имеет значение
-
-
- Переименовывать участников, которые пытаются поднять себя
-
-
- Страница
-
-
- Страница не найдена!
-
-
- Всего есть {0} страниц(-ы)
-
-
- Далее
-
-
- Назад
-
-
- Напоминания {0}
-
-
- У тебя нет напоминания с указанным индексом!
-
-
- Напоминание удалено
-
-
- У вас нет созданных напоминаний!
-
-
- Настройка {0} сброшена
-
-
- Все настройки были сброшены
-
-
- Перейти к сообщению: {0}
-
-
- Перейти к каналу: {0}
-
-
- Индекс: {0}
-
-
- Напоминание будет отправлено: {0}
-
-
- Текст напоминалки: {0}
-
-
+
+ разработчик и дизайнер, создатель Boyfriend's Wiki
+
+
+ Напоминание для {0} создано
+
+
+ Напоминание для {0}
+
+
+ Вы просили напомнить вам {0}
+
+
+ Настройки Boyfriend
+
+
+ Настройка успешно изменена
+
+
+ Настройка не редактирована
+
+
+ теперь имеет значение
+
+
+ Переименовывать участников, которые пытаются поднять себя
+
+
+ Страница
+
+
+ Страница не найдена!
+
+
+ Всего есть {0} страниц(-ы)
+
+
+ Далее
+
+
+ Назад
+
+
+ Напоминания {0}
+
+
+ У тебя нет напоминания с указанным индексом!
+
+
+ Напоминание удалено
+
+
+ У вас нет созданных напоминаний!
+
+
+ Настройка {0} сброшена
+
+
+ Все настройки были сброшены
+
+
+ Перейти к сообщению: {0}
+
+
+ Перейти к каналу: {0}
+
+
+ Индекс: {0}
+
+
+ Напоминание будет отправлено: {0}
+
+
+ Текст напоминалки: {0}
+
+
+ Отображаемое имя
+
+
+ Информация о {0}
+
+
+ Заглушен
+
+
+ Вступил в Discord
+
+
+ Забанен
+
+
+ Наказания
+
+
+ Забанен навсегда
+
+
+ Не на сервере
+
+
+ Заглушен с помощью тайм-аута
+
+
+ Заглушен с помощью роли мута
+
+
+ Вступил на сервер
+
+
+ Никнейм
+
+
+ Роли
+
+
+ Начал бустить сервер
+
+
\ No newline at end of file
diff --git a/locale/Messages.tt-ru.resx b/locale/Messages.tt-ru.resx
index a3da5f7..b0335a8 100644
--- a/locale/Messages.tt-ru.resx
+++ b/locale/Messages.tt-ru.resx
@@ -1,6 +1,6 @@
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
- PublicKeyToken=b77a5c561934e089
-
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
- PublicKeyToken=b77a5c561934e089
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
я родился!
-
+
сообщение {0} вырезано:
-
+
вырезано сообщение (используя `!clear`) от {0} в канале {1}: {2}
-
+
сообщение {0} переделано:
-
+
{0}, добро пожаловать на сервер {1}
-
+
брах!
-
+
брох!
-
+
брух!
-
+
у меня прав нету, сделай что нибудь.
-
+
у тебя прав нету, твои проблемы.
-
+
вы были забанены
-
+
время бана закончиловсь
-
+
ты выбрал менее {0} сообщений
-
+
ты выбрал более {0} сообщений
-
+
туториал по приколам:
-
+
вы были кикнуты
-
+
мс
-
+
шизоид уже замучен!
-
+
*тут ничего нет*
-
+
нъет
-
+
настройки:
-
+
язык
-
+
префикс
-
+
удалять звание при муте
-
+
разглашать о том что пришел новый шизоид
-
+
звание замученного
-
- такого языка нету...
-
-
+
+ такого языка нету...
+
+
да
-
+
нъет
-
+
шизик не забанен
-
+
шизоид не замучен!
-
+
здравствуйте (типо настройка)
-
+
выбери число от {0} до {1} вместо {2}!
-
+
{0} забанен
-
+
такой прикол не существует
-
+
получать инфу о старте бота
-
+
криво настроил прикол, давай по новой
-
+
этого звания нету, ты шо
-
+
этого канала нету, ты шо
-
+
ты шо, мутить больше чем на 28 дней таймаут не разрешает, вот настроишь роль мута, тогда поговорим
-
+
я не могу замутить ботов, сделай что нибудь
-
+
{0} приготовил новую движуху {1}! она пройдёт в {2} и начнётся <t:{3}:R>!{4}
-
+
роль для уведомлений о создании движухи
-
+
канал для уведомлений о движухах
-
+
получатели уведомлений о начале движух
-
+
движуха "{0}" начинается
-
+
оъмъомоъемъъео((((
-
- движуха "{0}" отменена!
-
-
- движуха "{0}" завершена!
-
-
+
+ движуха "{0}" отменена!
+
+
+ движуха "{0}" завершена!
+
+
всегда
-
+
вырезано {0} забавных сообщений
-
+
выгнан {0}: {1}
-
+
замучен {0} на{1}: {2}
-
+
раззабанен {0}: {1}
-
+
раззамучен {0}: {1}
-
+
ты все сломал! значение прикола `{0}` и так {1}
-
+
нъет
-
+
прикол для `{0}` теперь установлен на {1}
-
+
возводит великий банхаммер над шизоидом
-
+
удаляет сообщения. сколько хош, столько и удалит
-
+
показывает то, что ты сейчас видишь прямо сейчас
-
+
выпинывает шизоида
-
+
мутит шизоида
-
+
показывает пинг (сверхмегаточный (нет))
-
+
настройки бота под этот сервер
-
+
отводит великий банхаммер от шизоида
-
+
раззамучивает шизоида
-
+
укажи целое число от {0} до {1}
-
+
укажи самого шизика
-
+
надо указать юзверя вместо {0}!
-
+
укажи самого шизика
-
+
укажи шизоида сервера!
-
+
бан
-
+
тебе нельзя иметь власть над сообщениями шизоидов
-
+
кик шизиков нельзя
-
+
тебе нельзя управлять шизоидами
-
+
тебе нельзя редактировать дурку
-
+
я не могу ваще никого банить чел.
-
+
я не могу исправлять орфографический кринж участников, сделай что нибудь.
-
+
я не могу ваще никого кикать чел.
-
+
я не могу контроллировать за всеми ними, сделай что нибудь.
-
+
я не могу этому серверу хоть че либо нибудь изменить, сделай что нибудь.
-
+
укажи зачем банить шизика
-
+
укажи зачем кикать шизика
-
+
укажи зачем мутить шизика
-
+
укажи зачем раззабанивать шизика
-
+
укажи зачам размучивать шизика
-
+
ээбля френдли фаер огонь по своим
-
+
бан админу нельзя
-
+
бан этому шизику нельзя
-
+
самобан нельзя
-
+
я не могу его забанить...
-
+
кик админу нельзя
-
+
самокик нельзя
-
+
ээбля френдли фаер огонь по своим
-
+
я не могу его кикнуть...
-
+
кик этому шизику нельзя
-
+
мут админу нельзя
-
+
самомут нельзя
-
+
ээбля френдли фаер огонь по своим
-
+
я не могу его замутить...
-
+
мут этому шизику нельзя
-
+
сильно
-
+
ты замучен.
-
+
...
-
+
тебе нельзя раззамучивать
-
+
я не могу его раззамутить...
-
+
движуха "{0}" начнется {1}!
-
+
заранее пнуть в минутах до начала движухи
-
+
у нас такого шизоида нету, проверь, валиден ли ID уважаемого (я забываю о шизоидах если они ливнули минимум месяц назад)
-
+
дефолтное звание
-
+
крафтит напоминалку
-
+
канал для секретных уведомлений
-
+
канал для не секретных уведомлений
-
+
вернуть звания при переподключении в дурку
-
+
автоматом стартить движухи
-
+
для крафта напоминалки нужен текст
-
+
шизоид у меня на часах такого нету
-
+
ответственный
-
+
{0} создает новое событие:
-
+
движуха произойдет {0} в канале {1}
-
+
движуха будет происходить с {0} до {1} в {2}
-
+
побольше о движухе
-
+
все это длилось `{0}`
-
+
движуха происходит в {0}
-
+
движуха происходит в {0} до {1}
-
+
этот шизоид уже лежит в бане
-
+
{0} раззабанен
-
+
{0} в муте
-
+
{0} в размуте
-
+
этого шизоида никто не мутил.
-
+
у нас такого шизоида нету...
-
+
{0} вышел с посторонней помощью
-
+
причина: {0}
-
+
до: {0}
-
+
этот шизоид УЖЕ замучился
-
+
от {0}
-
+
девелоперы:
-
- репа Boyfriend (тык)
-
-
+
+ репа Boyfriend (тык)
+
+
немного о Boyfriend
-
- скучный девелопер + дизайнер создавший Boyfriend's Wiki
-
-
+
+ скучный девелопер + дизайнер создавший Boyfriend's Wiki
+
+
ВАЖНЫЙ соучастник кодинг-стримов @Octol1ttle
-
+
САМЫЙ ВАЖНЫЙ чел написавший кода больше всех (99.99%)
-
- напоминалка для {0} скрафченА
-
-
- напоминалка для {0}
-
-
- ты хотел чтоб я напомнил тебе {0}
-
-
- приколы Boyfriend
-
-
- прикол редактирован
-
-
- прикол сдох
-
-
- стало
-
-
- переобувать шизоидов пытающихся поднять себя в табе
-
-
- это страница
-
-
- если я был бы html, я бы сказал 404
-
-
- ну а если быть точнее, тут всего {0} страниц(-ы)
-
-
- следующее
-
-
- предыдущее
-
-
- напоминалки {0}
-
-
- у тебя нет напоминалки с этим индексом!
-
-
- напоминалка уничтожена
-
-
- ты еще не крафтил напоминалки
-
-
- {0} откачен к заводским
-
-
- откатываемся к заводским...
-
-
- чекнуть сообщение: {0}
-
-
- чекнуть канал: {0}
-
-
- индекс: {0}
-
-
- я пну тебе это: {0}
-
-
- че там в напоминалке: {0}
-
-
+
+ напоминалка для {0} скрафченА
+
+
+ напоминалка для {0}
+
+
+ ты хотел чтоб я напомнил тебе {0}
+
+
+ приколы Boyfriend
+
+
+ прикол редактирован
+
+
+ прикол сдох
+
+
+ стало
+
+
+ переобувать шизоидов пытающихся поднять себя в табе
+
+
+ это страница
+
+
+ если я был бы html, я бы сказал 404
+
+
+ ну а если быть точнее, тут всего {0} страниц(-ы)
+
+
+ следующее
+
+
+ предыдущее
+
+
+ напоминалки {0}
+
+
+ у тебя нет напоминалки с этим индексом!
+
+
+ напоминалка уничтожена
+
+
+ ты еще не крафтил напоминалки
+
+
+ {0} откачен к заводским
+
+
+ откатываемся к заводским...
+
+
+ чекнуть сообщение: {0}
+
+
+ чекнуть канал: {0}
+
+
+ индекс: {0}
+
+
+ я пну тебе это: {0}
+
+
+ че там в напоминалке: {0}
+
+
+ дисплейнейм
+
+
+ деанон {0}
+
+
+ замучен
+
+
+ юзер Discord со времен
+
+
+ забанен
+
+
+ приколы полученные по заслугам
+
+
+ забанен
+
+
+ вышел из сервера
+
+
+ замучен таймаутом
+
+
+ замучен ролькой
+
+
+ участник сервера со времен
+
+
+ сервернейм
+
+
+ рольки
+
+
+ бустит сервер со времен
+
+
\ No newline at end of file
diff --git a/src/Boyfriend.cs b/src/Boyfriend.cs
index 246869e..4ba43f8 100644
--- a/src/Boyfriend.cs
+++ b/src/Boyfriend.cs
@@ -102,7 +102,8 @@ public sealed class Boyfriend
.WithCommandGroup()
.WithCommandGroup()
.WithCommandGroup()
- .WithCommandGroup();
+ .WithCommandGroup()
+ .WithCommandGroup();
var responderTypes = typeof(Boyfriend).Assembly
.GetExportedTypes()
.Where(t => t.IsResponder());
diff --git a/src/Commands/ToolsCommandGroup.cs b/src/Commands/ToolsCommandGroup.cs
new file mode 100644
index 0000000..3ac8b70
--- /dev/null
+++ b/src/Commands/ToolsCommandGroup.cs
@@ -0,0 +1,231 @@
+using System.ComponentModel;
+using System.Drawing;
+using System.Text;
+using Boyfriend.Data;
+using Boyfriend.Services;
+using JetBrains.Annotations;
+using Remora.Commands.Attributes;
+using Remora.Commands.Groups;
+using Remora.Discord.API.Abstractions.Objects;
+using Remora.Discord.API.Abstractions.Rest;
+using Remora.Discord.Commands.Attributes;
+using Remora.Discord.Commands.Contexts;
+using Remora.Discord.Commands.Feedback.Services;
+using Remora.Discord.Extensions.Embeds;
+using Remora.Discord.Extensions.Formatting;
+using Remora.Rest.Core;
+using Remora.Results;
+
+namespace Boyfriend.Commands;
+
+///
+/// Handles commands related to tools: /showinfo.
+///
+[UsedImplicitly]
+public class ToolsCommandGroup : CommandGroup
+{
+ private readonly ICommandContext _context;
+ private readonly FeedbackService _feedback;
+ private readonly IDiscordRestGuildAPI _guildApi;
+ private readonly GuildDataService _guildData;
+ private readonly IDiscordRestUserAPI _userApi;
+
+ public ToolsCommandGroup(
+ ICommandContext context, FeedbackService feedback,
+ GuildDataService guildData, IDiscordRestGuildAPI guildApi,
+ IDiscordRestUserAPI userApi, IDiscordRestChannelAPI channelApi)
+ {
+ _context = context;
+ _guildData = guildData;
+ _feedback = feedback;
+ _guildApi = guildApi;
+ _userApi = userApi;
+ }
+
+ ///
+ /// A slash command that shows information about user.
+ ///
+ ///
+ /// Information in the output:
+ ///
+ /// - Display name
+ /// - Discord user since
+ /// - Guild nickname
+ /// - Guild member since
+ /// - Nitro booster since
+ /// - Guild roles
+ /// - Active mute information
+ /// - Active ban information
+ /// - Is on guild status
+ ///
+ ///
+ /// The user to show info about.
+ ///
+ /// A feedback sending result which may or may not have succeeded.
+ ///
+ [Command("showinfo")]
+ [DiscordDefaultDMPermission(false)]
+ [Description("Shows info about user")]
+ [UsedImplicitly]
+ public async Task ExecuteShowInfoAsync(
+ [Description("User to show info about")]
+ IUser? target = null)
+ {
+ if (!_context.TryGetContextIDs(out var guildId, out _, out var userId))
+ {
+ return new ArgumentInvalidError(nameof(_context), "Unable to retrieve necessary IDs from command context");
+ }
+
+ var userResult = await _userApi.GetUserAsync(userId, CancellationToken);
+ if (!userResult.IsDefined(out var user))
+ {
+ return Result.FromError(userResult);
+ }
+
+ var currentUserResult = await _userApi.GetCurrentUserAsync(CancellationToken);
+ if (!currentUserResult.IsDefined(out var currentUser))
+ {
+ return Result.FromError(currentUserResult);
+ }
+
+ var data = await _guildData.GetData(guildId, CancellationToken);
+ Messages.Culture = GuildSettings.Language.Get(data.Settings);
+
+ return await ShowUserInfoAsync(target ?? user, currentUser, data, guildId, CancellationToken);
+ }
+
+ private async Task ShowUserInfoAsync(
+ IUser user, IUser currentUser, GuildData data, Snowflake guildId, CancellationToken ct = default)
+ {
+ var builder = new StringBuilder().AppendLine($"### <@{user.ID}>");
+
+ if (user.GlobalName is not null)
+ {
+ builder.Append("- ").AppendLine(Messages.ShowInfoDisplayName)
+ .AppendLine(Markdown.InlineCode(user.GlobalName));
+ }
+
+ builder.Append("- ").AppendLine(Messages.ShowInfoDiscordUserSince)
+ .AppendLine(Markdown.Timestamp(user.ID.Timestamp));
+
+ var memberData = data.GetOrCreateMemberData(user.ID);
+
+ var embedColor = ColorsList.Cyan;
+
+ var guildMemberResult = await _guildApi.GetGuildMemberAsync(guildId, user.ID, ct);
+ DateTimeOffset? communicationDisabledUntil = null;
+ if (guildMemberResult.IsDefined(out var guildMember))
+ {
+ communicationDisabledUntil = guildMember.CommunicationDisabledUntil.OrDefault(null);
+
+ embedColor = AppendGuildInformation(embedColor, guildMember, builder);
+ }
+
+ var isMuted = (memberData.MutedUntil is not null && DateTimeOffset.UtcNow <= memberData.MutedUntil) ||
+ communicationDisabledUntil is not null;
+
+ var existingBanResult = await _guildApi.GetGuildBanAsync(guildId, user.ID, ct);
+
+ if (isMuted || existingBanResult.IsDefined())
+ {
+ builder.Append("### ")
+ .AppendLine(Markdown.Bold(Messages.ShowInfoPunishments));
+ }
+
+ if (isMuted)
+ {
+ AppendMuteInformation(memberData, communicationDisabledUntil, builder);
+
+ embedColor = ColorsList.Red;
+ }
+
+ if (existingBanResult.IsDefined())
+ {
+ AppendBanInformation(memberData, builder);
+
+ embedColor = ColorsList.Black;
+ }
+
+ if (!guildMemberResult.IsSuccess && !existingBanResult.IsDefined())
+ {
+ builder.Append("### ")
+ .AppendLine(Markdown.Bold(Messages.ShowInfoNotOnGuild));
+
+ embedColor = ColorsList.Default;
+ }
+
+ var embed = new EmbedBuilder().WithSmallTitle(
+ string.Format(Messages.ShowInfoTitle, user.GetTag()), currentUser)
+ .WithDescription(builder.ToString())
+ .WithColour(embedColor)
+ .WithLargeAvatar(user)
+ .WithFooter($"ID: {user.ID.ToString()}")
+ .Build();
+
+ return await _feedback.SendContextualEmbedResultAsync(embed, ct);
+ }
+
+ private static Color AppendGuildInformation(Color color, IGuildMember guildMember, StringBuilder builder)
+ {
+ if (guildMember.Nickname.IsDefined(out var nickname))
+ {
+ builder.Append("- ").AppendLine(Messages.ShowInfoGuildNickname)
+ .AppendLine(Markdown.InlineCode(nickname));
+ }
+
+ builder.Append("- ").AppendLine(Messages.ShowInfoGuildMemberSince)
+ .AppendLine(Markdown.Timestamp(guildMember.JoinedAt));
+
+ if (guildMember.PremiumSince.IsDefined(out var premiumSince))
+ {
+ builder.Append("- ").AppendLine(Messages.ShowInfoGuildMemberPremiumSince)
+ .AppendLine(Markdown.Timestamp(premiumSince.Value));
+ color = ColorsList.Magenta;
+ }
+
+ if (guildMember.Roles.Count > 0)
+ {
+ builder.Append("- ").AppendLine(Messages.ShowInfoGuildRoles);
+ for (var i = 0; i < guildMember.Roles.Count - 1; i++)
+ {
+ builder.Append($"<@&{guildMember.Roles[i]}>, ");
+ }
+
+ builder.AppendLine($"<@&{guildMember.Roles[^1]}>");
+ }
+
+ return color;
+ }
+
+ private static void AppendBanInformation(MemberData memberData, StringBuilder builder)
+ {
+ if (memberData.BannedUntil < DateTimeOffset.MaxValue)
+ {
+ builder.Append("- ").AppendLine(Messages.ShowInfoBanned)
+ .Append(" - ").AppendLine(string.Format(
+ Messages.DescriptionActionExpiresAt, Markdown.Timestamp(memberData.BannedUntil.Value)));
+ return;
+ }
+
+ builder.Append("- ").AppendLine(Messages.ShowInfoBannedPermanently);
+ }
+
+ private static void AppendMuteInformation(
+ MemberData memberData, DateTimeOffset? communicationDisabledUntil, StringBuilder builder)
+ {
+ builder.Append("- ").AppendLine(Messages.ShowInfoMuted);
+ if (memberData.MutedUntil is not null && DateTimeOffset.UtcNow <= memberData.MutedUntil)
+ {
+ builder.Append(" - ").AppendLine(Messages.ShowInfoMutedByMuteRole)
+ .Append(" - ").AppendLine(string.Format(
+ Messages.DescriptionActionExpiresAt, Markdown.Timestamp(memberData.MutedUntil.Value)));
+ }
+
+ if (communicationDisabledUntil is not null)
+ {
+ builder.Append(" - ").AppendLine(Messages.ShowInfoMutedByTimeout)
+ .Append(" - ").AppendLine(string.Format(
+ Messages.DescriptionActionExpiresAt, Markdown.Timestamp(communicationDisabledUntil.Value)));
+ }
+ }
+}
diff --git a/src/Extensions.cs b/src/Extensions.cs
index 47c7369..c06c4ce 100644
--- a/src/Extensions.cs
+++ b/src/Extensions.cs
@@ -58,6 +58,23 @@ public static class Extensions
return builder;
}
+ ///
+ /// Adds a user avatar in the thumbnail field.
+ ///
+ /// The builder to add the thumbnail to.
+ /// The user whose avatar to use in the thumbnail field.
+ /// The builder with the added avatar in the thumbnail field.
+ public static EmbedBuilder WithLargeAvatar(
+ this EmbedBuilder builder, IUser avatarSource)
+ {
+ var avatarUrlResult = CDN.GetUserAvatarUrl(avatarSource, imageSize: 256);
+ var avatarUrl = avatarUrlResult.IsSuccess
+ ? avatarUrlResult.Entity
+ : CDN.GetDefaultUserAvatarUrl(avatarSource, imageSize: 256).Entity;
+
+ return builder.WithThumbnailUrl(avatarUrl.AbsoluteUri);
+ }
+
///
/// Adds a footer representing that the action was performed in the .
///
diff --git a/src/Messages.Designer.cs b/src/Messages.Designer.cs
index 175e441..974660d 100644
--- a/src/Messages.Designer.cs
+++ b/src/Messages.Designer.cs
@@ -1035,6 +1035,89 @@ namespace Boyfriend {
internal static string ReminderText {
get {
return ResourceManager.GetString("ReminderText", resourceCulture);
+ }
+
+ internal static string ShowInfoTitle {
+ get {
+ return ResourceManager.GetString("ShowInfoTitle", resourceCulture);
+ }
+ }
+
+ internal static string ShowInfoDisplayName {
+ get {
+ return ResourceManager.GetString("ShowInfoDisplayName", resourceCulture);
+ }
+ }
+
+ internal static string ShowInfoDiscordUserSince {
+ get {
+ return ResourceManager.GetString("ShowInfoDiscordUserSince", resourceCulture);
+ }
+ }
+
+ internal static string ShowInfoMuted {
+ get {
+ return ResourceManager.GetString("ShowInfoMuted", resourceCulture);
+ }
+ }
+
+ internal static string ShowInfoBanned {
+ get {
+ return ResourceManager.GetString("ShowInfoBanned", resourceCulture);
+ }
+ }
+
+ internal static string ShowInfoPunishments {
+ get {
+ return ResourceManager.GetString("ShowInfoPunishments", resourceCulture);
+ }
+ }
+
+ internal static string ShowInfoBannedPermanently {
+ get {
+ return ResourceManager.GetString("ShowInfoBannedPermanently", resourceCulture);
+ }
+ }
+
+ internal static string ShowInfoNotOnGuild {
+ get {
+ return ResourceManager.GetString("ShowInfoNotOnGuild", resourceCulture);
+ }
+ }
+
+ internal static string ShowInfoMutedByTimeout {
+ get {
+ return ResourceManager.GetString("ShowInfoMutedByTimeout", resourceCulture);
+ }
+ }
+
+ internal static string ShowInfoMutedByMuteRole {
+ get {
+ return ResourceManager.GetString("ShowInfoMutedByMuteRole", resourceCulture);
+ }
+ }
+
+ internal static string ShowInfoGuildMemberSince {
+ get {
+ return ResourceManager.GetString("ShowInfoGuildMemberSince", resourceCulture);
+ }
+ }
+
+ internal static string ShowInfoGuildNickname {
+ get {
+ return ResourceManager.GetString("ShowInfoGuildNickname", resourceCulture);
+ }
+ }
+
+ internal static string ShowInfoGuildRoles {
+ get {
+ return ResourceManager.GetString("ShowInfoGuildRoles", resourceCulture);
+ }
+ }
+
+ internal static string ShowInfoGuildMemberPremiumSince {
+ get {
+ return ResourceManager.GetString("ShowInfoGuildMemberPremiumSince", resourceCulture);
}
}
}