Removed discrim from the database
Added .translateflags command Added captcha to timely, configurable in .conf gambling Changed bonuses for patreon rewards Fixed nunchi message color
This commit is contained in:
parent
41f1c7aa11
commit
d1bc423b99
29 changed files with 12080 additions and 4732 deletions
134
CHANGELOG.md
134
CHANGELOG.md
|
@ -2,20 +2,49 @@
|
||||||
|
|
||||||
Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except date format. a-c-f-r-o
|
Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except date format. a-c-f-r-o
|
||||||
|
|
||||||
## [5.1.16] - 29.10.2024
|
## [5.1.18] - 03.11.2024
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added `.translateflags` / `.trfl` command.
|
||||||
|
- Enable on a per-channel basis.
|
||||||
|
- Reacting on any message in that channel with a flag emoji will post the translation of that message in the
|
||||||
|
language of that country
|
||||||
|
- 5 second cooldown per user
|
||||||
|
- The message can only be translated once per language (counter resets every 24h)
|
||||||
|
- `.timely` now has a captcha. Togglable via `.conf gambling`
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
|
||||||
|
- [public bot] Patreon reward bonus for flowers reduced. Timely bonuses stay the same
|
||||||
|
- discriminators removed from the databases. All users who had ???? as discriminator have been renamed to ??username.
|
||||||
|
- all new unknown users will have ??Unknown as their name
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
|
||||||
|
- nunchi join game message is now ok color instead of error color
|
||||||
|
|
||||||
|
## [5.1.17] - 29.10.2024
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- fix: Bot will now not accept .aar Role if that Role is higher than or equal to bot's role. Previously bot would just
|
||||||
|
fail silently, now there is a proper error message.
|
||||||
|
|
||||||
|
## [5.1.16] - 28.10.2024
|
||||||
|
|
||||||
## Added
|
## Added
|
||||||
|
|
||||||
- Added .ncanvas and related commands.
|
- Added .ncanvas and related commands.
|
||||||
- You can set pixel colors (and text) on a 500x350 canvas, pepega version of r/place
|
- You can set pixel colors (and text) on a 500x350 canvas, pepega version of r/place
|
||||||
- You use currency to set pixels.
|
- You use currency to set pixels.
|
||||||
- Commands:
|
- Commands:
|
||||||
- see the entire canvas: `.nc`
|
- see the entire canvas: `.nc`
|
||||||
- zoom: `.ncz <pos>` or `.ncz x y`
|
- zoom: `.ncz <pos>` or `.ncz x y`
|
||||||
- set pixel: `.ncsp <pos> <color> <text?>`
|
- set pixel: `.ncsp <pos> <color> <text?>`
|
||||||
- get pixel: `.ncp <pos>`
|
- get pixel: `.ncp <pos>`
|
||||||
- Owners can use .ncsetimg to set a starting image, use `.h .setimg` for instructions
|
- Owners can use .ncsetimg to set a starting image, use `.h .setimg` for instructions
|
||||||
- Owners can reset the whole canvas via `.ncreset`
|
- Owners can reset the whole canvas via `.ncreset`
|
||||||
|
|
||||||
## [5.1.15] - 21.10.2024
|
## [5.1.15] - 21.10.2024
|
||||||
|
|
||||||
|
@ -70,8 +99,9 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added `%user.displayname%` placeholder. It will show users nickname, if there is one, otherwise it will show the username.
|
- Added `%user.displayname%` placeholder. It will show users nickname, if there is one, otherwise it will show the
|
||||||
- Nickname won't be shown in bye messages.
|
username.
|
||||||
|
- Nickname won't be shown in bye messages.
|
||||||
- Added initial version of grpc api. Beta
|
- Added initial version of grpc api. Beta
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
@ -82,9 +112,9 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Youtube now always uses `yt-dlp`. Dropped support for `youtube-dl`
|
- Youtube now always uses `yt-dlp`. Dropped support for `youtube-dl`
|
||||||
- If you've previously renamed your yt-dlp file to youtube-dl, please rename it back.
|
- If you've previously renamed your yt-dlp file to youtube-dl, please rename it back.
|
||||||
- ytProvider in data/searches.yml now also controls where you're getting your song streams from.
|
- ytProvider in data/searches.yml now also controls where you're getting your song streams from.
|
||||||
- (Invidious support added for .q)
|
- (Invidious support added for .q)
|
||||||
|
|
||||||
## [5.1.10] - 24.09.2024
|
## [5.1.10] - 24.09.2024
|
||||||
|
|
||||||
|
@ -103,26 +133,28 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
|
||||||
- Fixed `.greettest`, and other `.*test` commands if you didn't have them enabled.
|
- Fixed `.greettest`, and other `.*test` commands if you didn't have them enabled.
|
||||||
- Fixed `.greetdmtest` sending messages twice.
|
- Fixed `.greetdmtest` sending messages twice.
|
||||||
- Fixed a serious bug which caused greet messages to be jumbled up, and wrong ones to be sent for the wrong events.
|
- Fixed a serious bug which caused greet messages to be jumbled up, and wrong ones to be sent for the wrong events.
|
||||||
- There is no database issue, all greet messages are safe, the cache was caching any setting every 3 seconds with no regard for the type of the event
|
- There is no database issue, all greet messages are safe, the cache was caching any setting every 3 seconds with no
|
||||||
- This also caused `.greetdm` messages to not be sent if `.greet` is enabled
|
regard for the type of the event
|
||||||
- This bug was introduced in 5.1.8. PLEASE UPDATE if you are on 5.1.8
|
- This also caused `.greetdm` messages to not be sent if `.greet` is enabled
|
||||||
|
- This bug was introduced in 5.1.8. PLEASE UPDATE if you are on 5.1.8
|
||||||
- Selfhosters only: Fixed marmalade dependency loading
|
- Selfhosters only: Fixed marmalade dependency loading
|
||||||
- Note: Make sure to not publish any other DLLs besides the ones you are sure you will need, as there can be version conflicts which didn't happen before.
|
- Note: Make sure to not publish any other DLLs besides the ones you are sure you will need, as there can be version
|
||||||
|
conflicts which didn't happen before.
|
||||||
|
|
||||||
## [5.1.8] - 20.09.2024
|
## [5.1.8] - 20.09.2024
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added `.leaveunkeptservers` which will make the bot leave all servers on all shards whose owners didn't run `.keep` command.
|
- Added `.leaveunkeptservers` which will make the bot leave all servers on all shards whose owners didn't run `.keep` command.
|
||||||
- This is a dangerous and irreversible command, don't use it. Meant for use on the public bot.
|
- This is a dangerous and irreversible command, don't use it. Meant for use on the public bot.
|
||||||
- `.adpl` now supports custom statuses (you no longer need to specify Playing, Watching, etc...)
|
- `.adpl` now supports custom statuses (you no longer need to specify Playing, Watching, etc...)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- `.quote` commands cleaned up and improved
|
- `.quote` commands cleaned up and improved
|
||||||
- All quote commands now start with `.q<whatever>` and follow the same naming pattern as Expression commands
|
- All quote commands now start with `.q<whatever>` and follow the same naming pattern as Expression commands
|
||||||
- `.liqu` renamed to `.qli`
|
- `.liqu` renamed to `.qli`
|
||||||
- `.quotesearch` / `.qse` is now paginated for easier searching
|
- `.quotesearch` / `.qse` is now paginated for easier searching
|
||||||
- `.whosplaying` is now paginated
|
- `.whosplaying` is now paginated
|
||||||
- `.img` is now paginated
|
- `.img` is now paginated
|
||||||
- `.setgame` renamed to`.setactivity` and now supports custom text activity. You don't have to specify playing, listening etc before the activity
|
- `.setgame` renamed to`.setactivity` and now supports custom text activity. You don't have to specify playing, listening etc before the activity
|
||||||
|
@ -142,7 +174,7 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- Removed mysql support as it didn't work for a while, and requires some special handling/maintenance
|
- Removed mysql support as it didn't work for a while, and requires some special handling/maintenance
|
||||||
- Sqlite and Postgres support stays
|
- Sqlite and Postgres support stays
|
||||||
|
|
||||||
## [5.1.7] - 09.08.2024
|
## [5.1.7] - 09.08.2024
|
||||||
|
|
||||||
|
@ -166,15 +198,16 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
|
||||||
- Possible fix for `.remind` timestamp
|
- Possible fix for `.remind` timestamp
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- Removed old bloat / semi broken / dumb commands
|
- Removed old bloat / semi broken / dumb commands
|
||||||
- `.memelist` / `.memegen` (too inconvenient to use)
|
- `.memelist` / `.memegen` (too inconvenient to use)
|
||||||
- `.activity` (useless owner-only command)
|
- `.activity` (useless owner-only command)
|
||||||
- `.rafflecur` (Just use raffle and then award manually instead)
|
- `.rafflecur` (Just use raffle and then award manually instead)
|
||||||
- `.rollduel` (we had this command?)
|
- `.rollduel` (we had this command?)
|
||||||
- You can no longer bet on `.connect4`
|
- You can no longer bet on `.connect4`
|
||||||
- `.economy` Removed.
|
- `.economy` Removed.
|
||||||
- Was buggy and didn.t really show the real state of the economy.
|
- Was buggy and didn't really show the real state of the economy.
|
||||||
- It might come back improved in the future
|
- It might come back improved in the future
|
||||||
- `.mal` Removed. Useless information / semi broken
|
- `.mal` Removed. Useless information / semi broken
|
||||||
|
|
||||||
## [5.1.5] - 01.08.2024
|
## [5.1.5] - 01.08.2024
|
||||||
|
@ -182,9 +215,9 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added: Added a `.afk <msg>?` command which sets an afk message which will trigger whenever someone pings you
|
- Added: Added a `.afk <msg>?` command which sets an afk message which will trigger whenever someone pings you
|
||||||
- Message will when you type a message in any channel that the bot sees, or after 8 hours, whichever comes first
|
- Message will when you type a message in any channel that the bot sees, or after 8 hours, whichever comes first
|
||||||
- The specified message will be prefixed with "The user is afk: "
|
- The specified message will be prefixed with "The user is afk: "
|
||||||
- The afk message will disappear 30 seconds after being triggered
|
- The afk message will disappear 30 seconds after being triggered
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -192,7 +225,7 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
|
||||||
- Updated some bet descriptions to include 'all' 'half' usage instructions
|
- Updated some bet descriptions to include 'all' 'half' usage instructions
|
||||||
- Updated some command strings
|
- Updated some command strings
|
||||||
- dev: Vastly simplified marmalade creation using dotnet templates, docs updated
|
- dev: Vastly simplified marmalade creation using dotnet templates, docs updated
|
||||||
- Slight refactor of .wiki, .time, .catfact, .wikia, .define, .bible and .quran commands, no significant change in functionality
|
- Slight refactor of .wiki, time, .catfact, .wikia, .define, .bible and .quran commands, no significant change in functionality
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
@ -211,8 +244,10 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
|
||||||
- Added Clubs rank in the leaderboard to `.clubinfo`
|
- Added Clubs rank in the leaderboard to `.clubinfo`
|
||||||
- Bot owners can now check other people's bank balance (Not server owners, only bot owner, the person who is hosting the bot)
|
- Bot owners can now check other people's bank balance (Not server owners, only bot owner, the person who is hosting the bot)
|
||||||
- You can now send multiple waifu gifts at once to waifus. For example `.waifugift 3xRose @user` will give that user 3 roses
|
- You can now send multiple waifu gifts at once to waifus. For example `.waifugift 3xRose @user` will give that user 3 roses
|
||||||
- The format is `<NUMBER>x<ITEM>`, no spaces
|
- The format is `<NUMBER>x<ITEM>`, no spaces
|
||||||
- Added `.boosttest` command
|
- Added `.boosttest` command
|
||||||
|
- Added support for any openai compatible api for the chatterbot feature change:
|
||||||
|
- Changed games.yml to allow input of the apiUrl (needs to be openai compatible) and modelName as a string.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -254,9 +289,9 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added `.honeypot` command, which automatically softbans (ban and immediate unban) any user who posts in that channel.
|
- Added `.honeypot` command, which automatically softbans (ban and immediate unban) any user who posts in that channel.
|
||||||
- Useful to auto softban bots who spam every channel upon joining
|
- Useful to auto softban bots who spam every channel upon joining
|
||||||
- Users who run commands or expressions won't be softbanned.
|
- Users who run commands or expressions won't be softbanned.
|
||||||
- Users who have ban member permissions are also excluded.
|
- Users who have ban member permissions are also excluded.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
@ -270,7 +305,6 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
|
||||||
- Added support for `gpt-4o` in `data/games.yml`
|
- Added support for `gpt-4o` in `data/games.yml`
|
||||||
- Added EllieAiToken to `creds.yml`
|
- Added EllieAiToken to `creds.yml`
|
||||||
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Remind will now show a timestamp tag for durations
|
- Remind will now show a timestamp tag for durations
|
||||||
|
@ -283,8 +317,8 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
|
||||||
|
|
||||||
- Fixed xp bg buy button not working, and possibly some other buttons too
|
- Fixed xp bg buy button not working, and possibly some other buttons too
|
||||||
- Fixed shopbuy %user% placeholders and updated help text
|
- Fixed shopbuy %user% placeholders and updated help text
|
||||||
- All 'feed overloads should now work"
|
- All .feed overloads should now work"
|
||||||
- `'xpexclude` should will now work with forums too. If you exclude a forum you won't be able to gain xp in any of the threads.
|
- `.xpexclude` should will now work with forums too. If you exclude a forum you won't be able to gain xp in any of the threads.
|
||||||
- Fixed remind not showing correct time
|
- Fixed remind not showing correct time
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
@ -296,12 +330,14 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added `'setserverbanner` and `'setservericon` commands
|
- Added `.setserverbanner` and `.setservericon` commands
|
||||||
- Added overloads section to `'h command` which will show you all versions of command usage with param names
|
- Added overloads section to `.h command` which will show you all versions of command usage with param names
|
||||||
- You can now check commands for submodules, for example `'cmds SelfAssignedRoles` will show brief help for each of the commands in that submodule
|
- You can now check commands for submodules, for example `.cmds SelfAssignedRoles` will show brief help for each of the
|
||||||
- Added dropdown menus for 'mdls and 'cmds (both module and group versions) which will give you the option to see more detailed help for each specific module, group or command respectively
|
commands in that submodule
|
||||||
|
- Added dropdown menus for .mdls and .cmds (both module and group versions) which will give you the option to see more
|
||||||
|
detailed help for each specific module, group or command respectively
|
||||||
- Self-Hosters only:
|
- Self-Hosters only:
|
||||||
- Added a dangerous cleanup command that you don't have to know about
|
- Added a dangerous cleanup command that you don't have to know about
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -309,7 +345,7 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- `'verbose` will now be respected for expression errors
|
- `.verbose` will now be respected for expression errors
|
||||||
- Using `'pick` will now correctly show the name of the user who picked the currency
|
- Using `.pick` will now correctly show the name of the user who picked the currency
|
||||||
- Fixed `'h` not working on some commands
|
- Fixed `.h` not working on some commands
|
||||||
- `'langset` and `'langsetd` should no longer allow unsupported languages and nonsense to be typed in
|
- `.langset` and `.langsetd` should no longer allow unsupported languages and nonsense to be typed in
|
||||||
|
|
|
@ -73,6 +73,14 @@ public abstract class EllieContext : DbContext
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
|
#region Flag Translate
|
||||||
|
|
||||||
|
modelBuilder.Entity<FlagTranslateChannel>()
|
||||||
|
.HasIndex(x => new { x.GuildId, x.ChannelId })
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region NCanvas
|
#region NCanvas
|
||||||
|
|
||||||
modelBuilder.Entity<NCPixel>()
|
modelBuilder.Entity<NCPixel>()
|
||||||
|
|
|
@ -25,7 +25,6 @@ public static class DiscordUserExtensions
|
||||||
{
|
{
|
||||||
UserId = userId,
|
UserId = userId,
|
||||||
Username = username,
|
Username = username,
|
||||||
Discriminator = discrim,
|
|
||||||
AvatarId = avatarId,
|
AvatarId = avatarId,
|
||||||
TotalXp = 0,
|
TotalXp = 0,
|
||||||
CurrencyAmount = 0
|
CurrencyAmount = 0
|
||||||
|
@ -33,7 +32,6 @@ public static class DiscordUserExtensions
|
||||||
old => new()
|
old => new()
|
||||||
{
|
{
|
||||||
Username = username,
|
Username = username,
|
||||||
Discriminator = discrim,
|
|
||||||
AvatarId = avatarId
|
AvatarId = avatarId
|
||||||
},
|
},
|
||||||
() => new()
|
() => new()
|
||||||
|
@ -49,8 +47,7 @@ public static class DiscordUserExtensions
|
||||||
() => new()
|
() => new()
|
||||||
{
|
{
|
||||||
UserId = userId,
|
UserId = userId,
|
||||||
Username = "Unknown",
|
Username = "??Unknown",
|
||||||
Discriminator = "????",
|
|
||||||
AvatarId = string.Empty,
|
AvatarId = string.Empty,
|
||||||
TotalXp = 0,
|
TotalXp = 0,
|
||||||
CurrencyAmount = 0
|
CurrencyAmount = 0
|
||||||
|
|
|
@ -6,7 +6,7 @@ public class DiscordUser : DbEntity
|
||||||
{
|
{
|
||||||
public ulong UserId { get; set; }
|
public ulong UserId { get; set; }
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
public string Discriminator { get; set; }
|
// public string Discriminator { get; set; }
|
||||||
public string AvatarId { get; set; }
|
public string AvatarId { get; set; }
|
||||||
|
|
||||||
public int? ClubId { get; set; }
|
public int? ClubId { get; set; }
|
||||||
|
@ -26,9 +26,6 @@ public class DiscordUser : DbEntity
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(Discriminator) || Discriminator == "0000")
|
return Username;
|
||||||
return Username;
|
|
||||||
|
|
||||||
return Username + "#" + Discriminator;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
8
src/EllieBot/Db/Models/FlagTranslateChannel.cs
Normal file
8
src/EllieBot/Db/Models/FlagTranslateChannel.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#nullable disable
|
||||||
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
|
public class FlagTranslateChannel : DbEntity
|
||||||
|
{
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
|
public ulong ChannelId { get; set; }
|
||||||
|
}
|
|
@ -5,6 +5,11 @@ namespace EllieBot.Migrations;
|
||||||
|
|
||||||
public static class MigrationQueries
|
public static class MigrationQueries
|
||||||
{
|
{
|
||||||
|
public static void UpdateUsernames(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.Sql("UPDATE DiscordUser SET Username = '??' + Username WHERE Discriminator = '????';");
|
||||||
|
}
|
||||||
|
|
||||||
public static void MigrateRero(MigrationBuilder migrationBuilder)
|
public static void MigrateRero(MigrationBuilder migrationBuilder)
|
||||||
{
|
{
|
||||||
if (migrationBuilder.IsSqlite())
|
if (migrationBuilder.IsSqlite())
|
||||||
|
|
3851
src/EllieBot/Migrations/PostgreSql/20241102022956_no-discrim-and-flag-translate.Designer.cs
generated
Normal file
3851
src/EllieBot/Migrations/PostgreSql/20241102022956_no-discrim-and-flag-translate.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,56 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace EllieBot.Migrations.PostgreSql
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class nodiscrimandflagtranslate : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
MigrationQueries.UpdateUsernames(migrationBuilder);
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "discriminator",
|
||||||
|
table: "discorduser");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "flagtranslatechannel",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
guildid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||||
|
channelid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||||
|
dateadded = table.Column<DateTime>(type: "timestamp without time zone", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_flagtranslatechannel", x => x.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_flagtranslatechannel_guildid_channelid",
|
||||||
|
table: "flagtranslatechannel",
|
||||||
|
columns: new[] { "guildid", "channelid" },
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "flagtranslatechannel");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "discriminator",
|
||||||
|
table: "discorduser",
|
||||||
|
type: "text",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
2973
src/EllieBot/Migrations/Sqlite/20241102022949_no-discrim-and-flag-translate.Designer.cs
generated
Normal file
2973
src/EllieBot/Migrations/Sqlite/20241102022949_no-discrim-and-flag-translate.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,55 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace EllieBot.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class nodiscrimandflagtranslate : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
MigrationQueries.UpdateUsernames(migrationBuilder);
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "Discriminator",
|
||||||
|
table: "DiscordUser");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "FlagTranslateChannel",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
GuildId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||||
|
ChannelId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||||
|
DateAdded = table.Column<DateTime>(type: "TEXT", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_FlagTranslateChannel", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_FlagTranslateChannel_GuildId_ChannelId",
|
||||||
|
table: "FlagTranslateChannel",
|
||||||
|
columns: new[] { "GuildId", "ChannelId" },
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "FlagTranslateChannel");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "Discriminator",
|
||||||
|
table: "DiscordUser",
|
||||||
|
type: "TEXT",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -453,7 +453,6 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, IEService
|
||||||
{
|
{
|
||||||
x.UserId,
|
x.UserId,
|
||||||
x.Username,
|
x.Username,
|
||||||
x.Discriminator
|
|
||||||
})
|
})
|
||||||
.Where(x => users.Select(y => y.Id).Contains(x.UserId))
|
.Where(x => users.Select(y => y.Id).Contains(x.UserId))
|
||||||
.ToArrayAsyncEF();
|
.ToArrayAsyncEF();
|
||||||
|
@ -465,12 +464,11 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, IEService
|
||||||
UserId = x.Id,
|
UserId = x.Id,
|
||||||
AvatarId = x.AvatarId,
|
AvatarId = x.AvatarId,
|
||||||
Username = x.Username,
|
Username = x.Username,
|
||||||
Discriminator = x.Discriminator
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var added = (await ctx.BulkCopyAsync(usersToAdd)).RowsCopied;
|
var added = (await ctx.BulkCopyAsync(usersToAdd)).RowsCopied;
|
||||||
var toUpdateUserIds = presentDbUsers
|
var toUpdateUserIds = presentDbUsers
|
||||||
.Where(x => x.Username == "Unknown" && x.Discriminator == "????")
|
.Where(x => x.Username.StartsWith("??"))
|
||||||
.Select(x => x.UserId)
|
.Select(x => x.UserId)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
|
@ -481,7 +479,6 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, IEService
|
||||||
.UpdateAsync(x => new DiscordUser()
|
.UpdateAsync(x => new DiscordUser()
|
||||||
{
|
{
|
||||||
Username = user.Username,
|
Username = user.Username,
|
||||||
Discriminator = user.Discriminator,
|
|
||||||
|
|
||||||
// .award tends to set AvatarId and DateAdded to NULL, so account for that.
|
// .award tends to set AvatarId and DateAdded to NULL, so account for that.
|
||||||
AvatarId = user.AvatarId,
|
AvatarId = user.AvatarId,
|
||||||
|
|
|
@ -603,7 +603,7 @@ public class WaifuService : IEService, IReadyExecutor
|
||||||
.Where(wi => wi.ClaimerId == waifuId)
|
.Where(wi => wi.ClaimerId == waifuId)
|
||||||
.Select(wi => wi.WaifuId)
|
.Select(wi => wi.WaifuId)
|
||||||
.Contains(x.Id))
|
.Contains(x.Id))
|
||||||
.Select(x => $"{x.Username}#{x.Discriminator}")
|
.Select(x => x.Username)
|
||||||
.ToListAsyncEF();
|
.ToListAsyncEF();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -615,7 +615,7 @@ public class WaifuService : IEService, IReadyExecutor
|
||||||
.Where(wi => wi.AffinityId == waifuId)
|
.Where(wi => wi.AffinityId == waifuId)
|
||||||
.Select(wi => wi.WaifuId)
|
.Select(wi => wi.WaifuId)
|
||||||
.Contains(x.Id))
|
.Contains(x.Id))
|
||||||
.Select(x => $"{x.Username}#{x.Discriminator}")
|
.Select(x => x.Username)
|
||||||
.ToListAsyncEF();
|
.ToListAsyncEF();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,15 +42,12 @@ public static class WaifuExtensions
|
||||||
{
|
{
|
||||||
Affinity = x.Affinity == null
|
Affinity = x.Affinity == null
|
||||||
? null
|
? null
|
||||||
: x.Affinity.Username
|
: x.Affinity.Username,
|
||||||
+ (x.Affinity.Discriminator != "0000" ? "#" + x.Affinity.Discriminator : ""),
|
|
||||||
ClaimerName =
|
ClaimerName =
|
||||||
x.Claimer == null
|
x.Claimer == null
|
||||||
? null
|
? null
|
||||||
: x.Claimer.Username
|
: x.Claimer.Username,
|
||||||
+ (x.Claimer.Discriminator != "0000" ? "#" + x.Claimer.Discriminator : ""),
|
WaifuName = x.Waifu.Username,
|
||||||
WaifuName = x.Waifu.Username
|
|
||||||
+ (x.Waifu.Discriminator != "0000" ? "#" + x.Waifu.Discriminator : ""),
|
|
||||||
Price = x.Price
|
Price = x.Price
|
||||||
})
|
})
|
||||||
.ToListAsyncEF();
|
.ToListAsyncEF();
|
||||||
|
@ -62,7 +59,7 @@ public static class WaifuExtensions
|
||||||
public static ulong GetWaifuUserId(this DbSet<WaifuInfo> waifus, ulong ownerId, string name)
|
public static ulong GetWaifuUserId(this DbSet<WaifuInfo> waifus, ulong ownerId, string name)
|
||||||
=> waifus.AsQueryable()
|
=> waifus.AsQueryable()
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Where(x => x.Claimer.UserId == ownerId && x.Waifu.Username + "#" + x.Waifu.Discriminator == name)
|
.Where(x => x.Claimer.UserId == ownerId && x.Waifu.Username == name)
|
||||||
.Select(x => x.Waifu.UserId)
|
.Select(x => x.Waifu.UserId)
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
@ -100,7 +97,7 @@ public static class WaifuExtensions
|
||||||
ctx.Set<DiscordUser>()
|
ctx.Set<DiscordUser>()
|
||||||
.AsQueryable()
|
.AsQueryable()
|
||||||
.Where(u => u.UserId == userId)
|
.Where(u => u.UserId == userId)
|
||||||
.Select(u => u.Username + "#" + u.Discriminator)
|
.Select(u => u.Username)
|
||||||
.FirstOrDefault(),
|
.FirstOrDefault(),
|
||||||
AffinityCount =
|
AffinityCount =
|
||||||
ctx.Set<WaifuUpdate>()
|
ctx.Set<WaifuUpdate>()
|
||||||
|
@ -112,14 +109,14 @@ public static class WaifuExtensions
|
||||||
ctx.Set<DiscordUser>()
|
ctx.Set<DiscordUser>()
|
||||||
.AsQueryable()
|
.AsQueryable()
|
||||||
.Where(u => u.Id == w.AffinityId)
|
.Where(u => u.Id == w.AffinityId)
|
||||||
.Select(u => u.Username + "#" + u.Discriminator)
|
.Select(u => u.Username)
|
||||||
.FirstOrDefault(),
|
.FirstOrDefault(),
|
||||||
ClaimCount = ctx.Set<WaifuInfo>().AsQueryable().Count(x => x.ClaimerId == w.WaifuId),
|
ClaimCount = ctx.Set<WaifuInfo>().AsQueryable().Count(x => x.ClaimerId == w.WaifuId),
|
||||||
ClaimerName =
|
ClaimerName =
|
||||||
ctx.Set<DiscordUser>()
|
ctx.Set<DiscordUser>()
|
||||||
.AsQueryable()
|
.AsQueryable()
|
||||||
.Where(u => u.Id == w.ClaimerId)
|
.Where(u => u.Id == w.ClaimerId)
|
||||||
.Select(u => u.Username + "#" + u.Discriminator)
|
.Select(u => u.Username)
|
||||||
.FirstOrDefault(),
|
.FirstOrDefault(),
|
||||||
DivorceCount =
|
DivorceCount =
|
||||||
ctx.Set<WaifuUpdate>()
|
ctx.Set<WaifuUpdate>()
|
||||||
|
|
|
@ -29,7 +29,7 @@ public partial class Games
|
||||||
if (!await nunchi.Join(ctx.User.Id, ctx.User.ToString()))
|
if (!await nunchi.Join(ctx.User.Id, ctx.User.ToString()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await Response().Error(strs.nunchi_joined(nunchi.ParticipantCount)).SendAsync();
|
await Response().Confirm(strs.nunchi_joined(nunchi.ParticipantCount)).SendAsync();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -122,11 +122,11 @@ public sealed class CurrencyRewardService : IEService, IReadyExecutor
|
||||||
var dollarValue = pledgeCents / 100;
|
var dollarValue = pledgeCents / 100;
|
||||||
percentBonus = dollarValue switch
|
percentBonus = dollarValue switch
|
||||||
{
|
{
|
||||||
>= 100 => 100,
|
>= 100 => 20,
|
||||||
>= 50 => 50,
|
>= 50 => 10,
|
||||||
>= 20 => 20,
|
>= 20 => 5,
|
||||||
>= 10 => 10,
|
>= 10 => 3,
|
||||||
>= 5 => 5,
|
>= 5 => 1,
|
||||||
_ => 0
|
_ => 0
|
||||||
};
|
};
|
||||||
return (long)(modifiedAmount * (1 + (percentBonus / 100.0f)));
|
return (long)(modifiedAmount * (1 + (percentBonus / 100.0f)));
|
||||||
|
|
191
src/EllieBot/Modules/Searches/Translate/FlagTranslateService.cs
Normal file
191
src/EllieBot/Modules/Searches/Translate/FlagTranslateService.cs
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
#nullable disable
|
||||||
|
using LinqToDB;
|
||||||
|
using LinqToDB.EntityFrameworkCore;
|
||||||
|
using EllieBot.Common.ModuleBehaviors;
|
||||||
|
using EllieBot.Db.Models;
|
||||||
|
using System.Collections.Frozen;
|
||||||
|
|
||||||
|
namespace EllieBot.Modules.Searches;
|
||||||
|
|
||||||
|
public sealed partial class FlagTranslateService : IReadyExecutor, IEService
|
||||||
|
{
|
||||||
|
private readonly IBotCreds _creds;
|
||||||
|
private readonly DiscordSocketClient _client;
|
||||||
|
private readonly TranslateService _ts;
|
||||||
|
private readonly IMessageSenderService _sender;
|
||||||
|
private IReadOnlyDictionary<string, string> _supportedFlags;
|
||||||
|
private readonly DbService _db;
|
||||||
|
private ConcurrentHashSet<ulong> _enabledChannels;
|
||||||
|
private readonly IBotCache _cache;
|
||||||
|
|
||||||
|
// disallow same message being translated multiple times to the same language
|
||||||
|
private readonly ConcurrentHashSet<(ulong, string)> _msgLangs = new();
|
||||||
|
|
||||||
|
public FlagTranslateService(
|
||||||
|
IBotCreds creds,
|
||||||
|
DiscordSocketClient client,
|
||||||
|
TranslateService ts,
|
||||||
|
IMessageSenderService sender,
|
||||||
|
DbService db,
|
||||||
|
IBotCache cache)
|
||||||
|
{
|
||||||
|
_creds = creds;
|
||||||
|
_client = client;
|
||||||
|
_ts = ts;
|
||||||
|
_sender = sender;
|
||||||
|
_db = db;
|
||||||
|
_cache = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task OnReadyAsync()
|
||||||
|
{
|
||||||
|
_supportedFlags = COUNTRIES
|
||||||
|
.Split('\n')
|
||||||
|
.Select(x => x.Split(' '))
|
||||||
|
.ToDictionary(x => x[0], x => x[1].TrimEnd())
|
||||||
|
.ToFrozenDictionary();
|
||||||
|
|
||||||
|
await using (var uow = _db.GetDbContext())
|
||||||
|
{
|
||||||
|
_enabledChannels = (await uow.GetTable<FlagTranslateChannel>()
|
||||||
|
.Where(x => Linq2DbExpressions.GuildOnShard(x.GuildId,
|
||||||
|
_creds.TotalShards,
|
||||||
|
_client.ShardId))
|
||||||
|
.Select(x => new
|
||||||
|
{
|
||||||
|
x.ChannelId,
|
||||||
|
x.GuildId
|
||||||
|
})
|
||||||
|
.ToListAsyncLinqToDB())
|
||||||
|
.Select(x => x.ChannelId)
|
||||||
|
.ToHashSet()
|
||||||
|
.ToConcurrentSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
_client.ReactionAdded += OnReactionAdded;
|
||||||
|
|
||||||
|
var periodicCleanup = new PeriodicTimer(TimeSpan.FromHours(24));
|
||||||
|
|
||||||
|
while (await periodicCleanup.WaitForNextTickAsync())
|
||||||
|
{
|
||||||
|
_msgLangs.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private const int FLAG_START = 127462;
|
||||||
|
|
||||||
|
private static TypedKey<bool> CdKey(ulong userId)
|
||||||
|
=> new($"flagtranslate:{userId}");
|
||||||
|
|
||||||
|
private Task OnReactionAdded(
|
||||||
|
Cacheable<IUserMessage, ulong> arg1,
|
||||||
|
Cacheable<IMessageChannel, ulong> arg2,
|
||||||
|
SocketReaction reaction)
|
||||||
|
{
|
||||||
|
if (!_enabledChannels.Contains(reaction.Channel.Id))
|
||||||
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
var runes = reaction.Emote.Name.EnumerateRunes();
|
||||||
|
if (!runes.MoveNext()
|
||||||
|
|| runes.Current is not { Value: >= 127462 and <= 127487 } l1
|
||||||
|
|| !runes.MoveNext()
|
||||||
|
|| runes.Current is not { Value: >= 127462 and <= 127487 } l2)
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
if (reaction.Channel is not SocketTextChannel tc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var user = await ((IGuild)tc.Guild).GetUserAsync(reaction.UserId);
|
||||||
|
|
||||||
|
if (user is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!user.GetPermissions(tc).SendMessages)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!tc.Guild.CurrentUser.GetPermissions(tc).SendMessages
|
||||||
|
|| !tc.Guild.CurrentUser.GetPermissions(tc).EmbedLinks)
|
||||||
|
{
|
||||||
|
await Disable(tc.Guild.Id, tc.Id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var c1 = (char)(l1.Value - FLAG_START + 65);
|
||||||
|
var c2 = (char)(l2.Value - FLAG_START + 65);
|
||||||
|
|
||||||
|
var code = $"{c1}{c2}".ToUpper();
|
||||||
|
|
||||||
|
if (!_supportedFlags.TryGetValue(code, out var lang))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!_msgLangs.Add((reaction.MessageId, lang)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var result = await _cache.GetAsync(CdKey(reaction.UserId));
|
||||||
|
if (result.TryPickT0(out _, out _))
|
||||||
|
return;
|
||||||
|
|
||||||
|
await _cache.AddAsync(CdKey(reaction.UserId), true, TimeSpan.FromSeconds(5));
|
||||||
|
|
||||||
|
var msg = await arg1.GetOrDownloadAsync();
|
||||||
|
|
||||||
|
var response = await _ts.Translate("", lang, msg.Content).ConfigureAwait(false);
|
||||||
|
|
||||||
|
await msg.ReplyAsync(embed: _sender.CreateEmbed()
|
||||||
|
.WithOkColor()
|
||||||
|
.WithFooter(user.ToString() ?? reaction.UserId.ToString(),
|
||||||
|
user.RealAvatarUrl().ToString())
|
||||||
|
.WithDescription(response)
|
||||||
|
.WithAuthor(reaction.Emote.ToString())
|
||||||
|
.Build(),
|
||||||
|
allowedMentions: AllowedMentions.None
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Disable(ulong guildId, ulong tcId)
|
||||||
|
{
|
||||||
|
if (!_enabledChannels.TryRemove(tcId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
await using var uow = _db.GetDbContext();
|
||||||
|
await uow.GetTable<FlagTranslateChannel>()
|
||||||
|
.Where(x => x.GuildId == guildId
|
||||||
|
&& x.ChannelId == tcId)
|
||||||
|
.DeleteAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> Toggle(ulong guildId, ulong tcId)
|
||||||
|
{
|
||||||
|
if (_enabledChannels.Contains(tcId))
|
||||||
|
{
|
||||||
|
await Disable(guildId, tcId);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Enable(guildId, tcId);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Enable(ulong guildId, ulong tcId)
|
||||||
|
{
|
||||||
|
if (!_enabledChannels.Add(tcId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
await using var uow = _db.GetDbContext();
|
||||||
|
await uow.GetTable<FlagTranslateChannel>()
|
||||||
|
.InsertAsync(() => new FlagTranslateChannel
|
||||||
|
{
|
||||||
|
GuildId = guildId,
|
||||||
|
ChannelId = tcId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
namespace EllieBot.Modules.Searches;
|
||||||
|
|
||||||
|
public partial class FlagTranslateService
|
||||||
|
{
|
||||||
|
private const string COUNTRIES = """
|
||||||
|
CN zh
|
||||||
|
IN hi
|
||||||
|
US en
|
||||||
|
ID id
|
||||||
|
PK ur
|
||||||
|
BR pt
|
||||||
|
NG ha
|
||||||
|
BD bn
|
||||||
|
RU ru
|
||||||
|
JP ja
|
||||||
|
MX es
|
||||||
|
PH tl
|
||||||
|
VN vi
|
||||||
|
EG ar
|
||||||
|
ET am
|
||||||
|
DE de
|
||||||
|
IR fa
|
||||||
|
TR tr
|
||||||
|
TH th
|
||||||
|
FR fr
|
||||||
|
CD fr
|
||||||
|
MM my
|
||||||
|
UG en
|
||||||
|
MZ pt
|
||||||
|
ZA zu
|
||||||
|
CO es
|
||||||
|
BG bg
|
||||||
|
HR hr
|
||||||
|
MY ms
|
||||||
|
NL nl
|
||||||
|
RO ro
|
||||||
|
CZ cs
|
||||||
|
GR el
|
||||||
|
SK sk
|
||||||
|
PT pt
|
||||||
|
KR ko
|
||||||
|
IT it
|
||||||
|
ES es
|
||||||
|
RS sr
|
||||||
|
TN ar
|
||||||
|
PL pl
|
||||||
|
SD ar
|
||||||
|
CM fr
|
||||||
|
SN fr
|
||||||
|
ML fr
|
||||||
|
NE ha
|
||||||
|
BI fr
|
||||||
|
AO pt
|
||||||
|
AF ps
|
||||||
|
MA ar
|
||||||
|
DZ ar
|
||||||
|
GB en
|
||||||
|
AR es
|
||||||
|
ZW ny
|
||||||
|
KE sw
|
||||||
|
GH en
|
||||||
|
SA ar
|
||||||
|
IL he
|
||||||
|
IQ ar
|
||||||
|
UA ua
|
||||||
|
LY ar
|
||||||
|
KW ar
|
||||||
|
OM ar
|
||||||
|
YE ar
|
||||||
|
AL sq
|
||||||
|
AE ar
|
||||||
|
""";
|
||||||
|
}
|
|
@ -44,12 +44,10 @@ public sealed class TranslateService : ITranslateService, IExecNoCommand, IReady
|
||||||
foreach (var c in cs)
|
foreach (var c in cs)
|
||||||
{
|
{
|
||||||
_atcs[c.ChannelId] = c.AutoDelete;
|
_atcs[c.ChannelId] = c.AutoDelete;
|
||||||
_users[c.ChannelId] =
|
_users[c.ChannelId] = new(c.Users.ToDictionary(x => x.UserId, x => (x.Source.ToLower(), x.Target.ToLower())));
|
||||||
new(c.Users.ToDictionary(x => x.UserId, x => (x.Source.ToLower(), x.Target.ToLower())));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task ExecOnNoCommandAsync(IGuild guild, IUserMessage msg)
|
public async Task ExecOnNoCommandAsync(IGuild guild, IUserMessage msg)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(msg.Content))
|
if (string.IsNullOrWhiteSpace(msg.Content))
|
||||||
|
@ -95,7 +93,7 @@ public sealed class TranslateService : ITranslateService, IExecNoCommand, IReady
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> Translate(string source, string target, string text = null)
|
public async Task<string> Translate(string source, string target, string text)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(text))
|
if (string.IsNullOrWhiteSpace(text))
|
||||||
throw new ArgumentException("Text is empty or null", nameof(text));
|
throw new ArgumentException("Text is empty or null", nameof(text));
|
||||||
|
|
|
@ -6,6 +6,14 @@ public partial class Searches
|
||||||
[Group]
|
[Group]
|
||||||
public partial class TranslateCommands : EllieModule<ITranslateService>
|
public partial class TranslateCommands : EllieModule<ITranslateService>
|
||||||
{
|
{
|
||||||
|
private readonly FlagTranslateService _flagSvc;
|
||||||
|
|
||||||
|
public TranslateCommands(FlagTranslateService flagSvc)
|
||||||
|
{
|
||||||
|
_flagSvc = flagSvc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public enum AutoDeleteAutoTranslate
|
public enum AutoDeleteAutoTranslate
|
||||||
{
|
{
|
||||||
Del,
|
Del,
|
||||||
|
@ -91,5 +99,18 @@ public partial class Searches
|
||||||
|
|
||||||
await Response().Embed(eb).SendAsync();
|
await Response().Embed(eb).SendAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[UserPerm(ChannelPermission.ManageChannels)]
|
||||||
|
[BotPerm(ChannelPermission.SendMessages | ChannelPermission.EmbedLinks)]
|
||||||
|
public async Task TranslateFlags()
|
||||||
|
{
|
||||||
|
var enabled = await _flagSvc.Toggle(ctx.Guild.Id, ctx.Channel.Id);
|
||||||
|
if (enabled)
|
||||||
|
await Response().Confirm(strs.trfl_enabled).SendAsync();
|
||||||
|
else
|
||||||
|
await Response().Confirm(strs.trfl_disabled).SendAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -28,6 +28,8 @@ public class XpSvc : GrpcXp.GrpcXpBase, IGrpcSvc, IEService
|
||||||
GetXpSettingsRequest request,
|
GetXpSettingsRequest request,
|
||||||
ServerCallContext context)
|
ServerCallContext context)
|
||||||
{
|
{
|
||||||
|
await Task.Yield();
|
||||||
|
|
||||||
var guild = _client.GetGuild(request.GuildId);
|
var guild = _client.GetGuild(request.GuildId);
|
||||||
|
|
||||||
if (guild is null)
|
if (guild is null)
|
||||||
|
@ -54,6 +56,26 @@ public class XpSvc : GrpcXp.GrpcXpBase, IGrpcSvc, IEService
|
||||||
Name = guild.GetRole(x)?.Name ?? "????"
|
Name = guild.GetRole(x)?.Name ?? "????"
|
||||||
})));
|
})));
|
||||||
|
|
||||||
|
var curRews = _xp.GetCurrencyRewards(request.GuildId);
|
||||||
|
var roleRews = _xp.GetRoleRewards(request.GuildId);
|
||||||
|
|
||||||
|
var rews = curRews.Select(x => new RewItemReply()
|
||||||
|
{
|
||||||
|
Level = x.Level,
|
||||||
|
Type = "Currency",
|
||||||
|
Value = x.Amount.ToString()
|
||||||
|
});
|
||||||
|
|
||||||
|
rews = rews.Concat(roleRews.Select(x => new RewItemReply()
|
||||||
|
{
|
||||||
|
Level = x.Level,
|
||||||
|
Type = "Role",
|
||||||
|
Value = guild.GetRole(x.RoleId)?.ToString() ?? x.RoleId.ToString()
|
||||||
|
}))
|
||||||
|
.OrderBy(x => x.Level);
|
||||||
|
|
||||||
|
reply.Rewards.AddRange(rews);
|
||||||
|
|
||||||
reply.ServerExcluded = isServerExcluded;
|
reply.ServerExcluded = isServerExcluded;
|
||||||
|
|
||||||
return reply;
|
return reply;
|
||||||
|
|
|
@ -201,9 +201,12 @@ public sealed partial class GoogleApiService : IGoogleApiService, IEService
|
||||||
{
|
{
|
||||||
string text;
|
string text;
|
||||||
|
|
||||||
if (!Languages.ContainsKey(sourceLanguage) || !Languages.ContainsKey(targetLanguage))
|
if (!Languages.ContainsKey(targetLanguage))
|
||||||
throw new ArgumentException(nameof(sourceLanguage) + "/" + nameof(targetLanguage));
|
throw new ArgumentException(nameof(sourceLanguage) + "/" + nameof(targetLanguage));
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(sourceLanguage) || !Languages.ContainsKey(sourceLanguage))
|
||||||
|
sourceLanguage = "auto";
|
||||||
|
|
||||||
|
|
||||||
var url = new Uri(string.Format(
|
var url = new Uri(string.Format(
|
||||||
"https://translate.googleapis.com/translate_a/single?client=gtx&sl={0}&tl={1}&dt=t&q={2}",
|
"https://translate.googleapis.com/translate_a/single?client=gtx&sl={0}&tl={1}&dt=t&q={2}",
|
||||||
|
@ -223,7 +226,7 @@ public sealed partial class GoogleApiService : IGoogleApiService, IEService
|
||||||
private string ConvertToLanguageCode(string language)
|
private string ConvertToLanguageCode(string language)
|
||||||
{
|
{
|
||||||
Languages.TryGetValue(language, out var mode);
|
Languages.TryGetValue(language, out var mode);
|
||||||
return mode;
|
return string.IsNullOrWhiteSpace(mode) ? language : mode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,7 +154,6 @@ public sealed partial class GoogleApiService
|
||||||
}
|
}
|
||||||
|
|
||||||
Languages = langs;
|
Languages = langs;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -77,8 +77,7 @@ public class DefaultWallet : IWallet
|
||||||
.InsertOrUpdateAsync(() => new()
|
.InsertOrUpdateAsync(() => new()
|
||||||
{
|
{
|
||||||
UserId = userId,
|
UserId = userId,
|
||||||
Username = "Unknown",
|
Username = "??Unknown",
|
||||||
Discriminator = "????",
|
|
||||||
CurrencyAmount = amount,
|
CurrencyAmount = amount,
|
||||||
},
|
},
|
||||||
(old) => new()
|
(old) => new()
|
||||||
|
|
|
@ -193,7 +193,7 @@ public sealed class StatsService : IStatsService, IReadyExecutor, IEService
|
||||||
Id = g.Id,
|
Id = g.Id,
|
||||||
IconUrl = g.IconUrl,
|
IconUrl = g.IconUrl,
|
||||||
Name = g.Name,
|
Name = g.Name,
|
||||||
Owner = (await ig.GetUserAsync(g.OwnerId))?.Username ?? "Unknown",
|
Owner = (await ig.GetUserAsync(g.OwnerId))?.Username ?? "??Unknown",
|
||||||
OwnerId = g.OwnerId,
|
OwnerId = g.OwnerId,
|
||||||
CreatedAt = g.CreatedAt.UtcDateTime,
|
CreatedAt = g.CreatedAt.UtcDateTime,
|
||||||
VoiceChannels = g.VoiceChannels.Count,
|
VoiceChannels = g.VoiceChannels.Count,
|
||||||
|
|
|
@ -1445,3 +1445,8 @@ ncpixel:
|
||||||
- ncgp
|
- ncgp
|
||||||
ncreset:
|
ncreset:
|
||||||
- ncreset
|
- ncreset
|
||||||
|
translateflags:
|
||||||
|
- translateflags
|
||||||
|
- trfl
|
||||||
|
- fltr
|
||||||
|
- transflags
|
|
@ -4634,3 +4634,11 @@ ncreset:
|
||||||
- ''
|
- ''
|
||||||
params:
|
params:
|
||||||
- { }
|
- { }
|
||||||
|
translateflags:
|
||||||
|
desc: |-
|
||||||
|
Toggles translate flags on the current channel.
|
||||||
|
Reacting with a country flag will translate the message to that country's language.
|
||||||
|
ex:
|
||||||
|
- ''
|
||||||
|
params:
|
||||||
|
- { }
|
|
@ -1111,5 +1111,7 @@
|
||||||
"nc_hint": "Use `{0}nczoom x y` command to zoom in. Image is {1}x{2} pixels.",
|
"nc_hint": "Use `{0}nczoom x y` command to zoom in. Image is {1}x{2} pixels.",
|
||||||
"nc_insuff_payment": "Invalid payment.",
|
"nc_insuff_payment": "Invalid payment.",
|
||||||
"invalid_img_size": "Image must to be {0}x{1} pixels.",
|
"invalid_img_size": "Image must to be {0}x{1} pixels.",
|
||||||
"no_attach_found": "No attachment found. Please send the image along with this command."
|
"no_attach_found": "No attachment found. Please send the image along with this command.",
|
||||||
|
"trfl_enabled": "Flag translation enabled on this channel. Reacting to a message with a flag will translate it to that language.",
|
||||||
|
"trfl_disabled": "Flag translation disabled."
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue