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
|
||||
|
||||
## [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 .ncanvas and related commands.
|
||||
- You can set pixel colors (and text) on a 500x350 canvas, pepega version of r/place
|
||||
- You use currency to set pixels.
|
||||
- Commands:
|
||||
- see the entire canvas: `.nc`
|
||||
- zoom: `.ncz <pos>` or `.ncz x y`
|
||||
- set pixel: `.ncsp <pos> <color> <text?>`
|
||||
- get pixel: `.ncp <pos>`
|
||||
- Owners can use .ncsetimg to set a starting image, use `.h .setimg` for instructions
|
||||
- Owners can reset the whole canvas via `.ncreset`
|
||||
- You can set pixel colors (and text) on a 500x350 canvas, pepega version of r/place
|
||||
- You use currency to set pixels.
|
||||
- Commands:
|
||||
- see the entire canvas: `.nc`
|
||||
- zoom: `.ncz <pos>` or `.ncz x y`
|
||||
- set pixel: `.ncsp <pos> <color> <text?>`
|
||||
- get pixel: `.ncp <pos>`
|
||||
- Owners can use .ncsetimg to set a starting image, use `.h .setimg` for instructions
|
||||
- Owners can reset the whole canvas via `.ncreset`
|
||||
|
||||
## [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 `%user.displayname%` placeholder. It will show users nickname, if there is one, otherwise it will show the username.
|
||||
- Nickname won't be shown in bye messages.
|
||||
- Added `%user.displayname%` placeholder. It will show users nickname, if there is one, otherwise it will show the
|
||||
username.
|
||||
- Nickname won't be shown in bye messages.
|
||||
- Added initial version of grpc api. Beta
|
||||
|
||||
### Fixed
|
||||
|
@ -82,9 +112,9 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
|
|||
### Changed
|
||||
|
||||
- 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.
|
||||
- (Invidious support added for .q)
|
||||
- (Invidious support added for .q)
|
||||
|
||||
## [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 `.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.
|
||||
- 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
|
||||
- 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
|
||||
- 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
|
||||
- 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
|
||||
- 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
|
||||
|
||||
### Added
|
||||
|
||||
- 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...)
|
||||
|
||||
### Changed
|
||||
|
||||
- `.quote` commands cleaned up and improved
|
||||
- All quote commands now start with `.q<whatever>` and follow the same naming pattern as Expression commands
|
||||
- `.liqu` renamed to `.qli`
|
||||
- `.quotesearch` / `.qse` is now paginated for easier searching
|
||||
- All quote commands now start with `.q<whatever>` and follow the same naming pattern as Expression commands
|
||||
- `.liqu` renamed to `.qli`
|
||||
- `.quotesearch` / `.qse` is now paginated for easier searching
|
||||
- `.whosplaying` 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
|
||||
|
@ -142,7 +174,7 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
|
|||
### Removed
|
||||
|
||||
- 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
|
||||
|
||||
|
@ -166,15 +198,16 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
|
|||
- Possible fix for `.remind` timestamp
|
||||
|
||||
### Removed
|
||||
|
||||
- Removed old bloat / semi broken / dumb commands
|
||||
- `.memelist` / `.memegen` (too inconvenient to use)
|
||||
- `.activity` (useless owner-only command)
|
||||
- `.rafflecur` (Just use raffle and then award manually instead)
|
||||
- `.rollduel` (we had this command?)
|
||||
- `.memelist` / `.memegen` (too inconvenient to use)
|
||||
- `.activity` (useless owner-only command)
|
||||
- `.rafflecur` (Just use raffle and then award manually instead)
|
||||
- `.rollduel` (we had this command?)
|
||||
- You can no longer bet on `.connect4`
|
||||
- `.economy` Removed.
|
||||
- Was buggy and didn.t really show the real state of the economy.
|
||||
- It might come back improved in the future
|
||||
- Was buggy and didn't really show the real state of the economy.
|
||||
- It might come back improved in the future
|
||||
- `.mal` Removed. Useless information / semi broken
|
||||
|
||||
## [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 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
|
||||
- The specified message will be prefixed with "The user is afk: "
|
||||
- The afk message will disappear 30 seconds after being triggered
|
||||
- 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 afk message will disappear 30 seconds after being triggered
|
||||
|
||||
### 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 command strings
|
||||
- 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
|
||||
|
||||
|
@ -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`
|
||||
- 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
|
||||
- The format is `<NUMBER>x<ITEM>`, no spaces
|
||||
- The format is `<NUMBER>x<ITEM>`, no spaces
|
||||
- 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
|
||||
|
||||
|
@ -254,9 +289,9 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
|
|||
### Added
|
||||
|
||||
- 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
|
||||
- Users who run commands or expressions won't be softbanned.
|
||||
- Users who have ban member permissions are also excluded.
|
||||
- Useful to auto softban bots who spam every channel upon joining
|
||||
- Users who run commands or expressions won't be softbanned.
|
||||
- Users who have ban member permissions are also excluded.
|
||||
|
||||
### 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 EllieAiToken to `creds.yml`
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- 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 shopbuy %user% placeholders and updated help text
|
||||
- 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.
|
||||
- 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.
|
||||
- Fixed remind not showing correct time
|
||||
|
||||
### Removed
|
||||
|
@ -296,12 +330,14 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
|
|||
|
||||
### Added
|
||||
|
||||
- Added `'setserverbanner` and `'setservericon` commands
|
||||
- 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
|
||||
- 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
|
||||
- Added `.setserverbanner` and `.setservericon` commands
|
||||
- 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
|
||||
- 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:
|
||||
- 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
|
||||
|
||||
|
@ -309,7 +345,7 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
|
|||
|
||||
### Fixed
|
||||
|
||||
- `'verbose` will now be respected for expression errors
|
||||
- Using `'pick` will now correctly show the name of the user who picked the currency
|
||||
- Fixed `'h` not working on some commands
|
||||
- `'langset` and `'langsetd` should no longer allow unsupported languages and nonsense to be typed in
|
||||
- `.verbose` will now be respected for expression errors
|
||||
- Using `.pick` will now correctly show the name of the user who picked the currency
|
||||
- Fixed `.h` not working on some commands
|
||||
- `.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)
|
||||
{
|
||||
#region Flag Translate
|
||||
|
||||
modelBuilder.Entity<FlagTranslateChannel>()
|
||||
.HasIndex(x => new { x.GuildId, x.ChannelId })
|
||||
.IsUnique();
|
||||
|
||||
#endregion
|
||||
|
||||
#region NCanvas
|
||||
|
||||
modelBuilder.Entity<NCPixel>()
|
||||
|
|
|
@ -25,7 +25,6 @@ public static class DiscordUserExtensions
|
|||
{
|
||||
UserId = userId,
|
||||
Username = username,
|
||||
Discriminator = discrim,
|
||||
AvatarId = avatarId,
|
||||
TotalXp = 0,
|
||||
CurrencyAmount = 0
|
||||
|
@ -33,7 +32,6 @@ public static class DiscordUserExtensions
|
|||
old => new()
|
||||
{
|
||||
Username = username,
|
||||
Discriminator = discrim,
|
||||
AvatarId = avatarId
|
||||
},
|
||||
() => new()
|
||||
|
@ -49,8 +47,7 @@ public static class DiscordUserExtensions
|
|||
() => new()
|
||||
{
|
||||
UserId = userId,
|
||||
Username = "Unknown",
|
||||
Discriminator = "????",
|
||||
Username = "??Unknown",
|
||||
AvatarId = string.Empty,
|
||||
TotalXp = 0,
|
||||
CurrencyAmount = 0
|
||||
|
|
|
@ -6,7 +6,7 @@ public class DiscordUser : DbEntity
|
|||
{
|
||||
public ulong UserId { get; set; }
|
||||
public string Username { get; set; }
|
||||
public string Discriminator { get; set; }
|
||||
// public string Discriminator { get; set; }
|
||||
public string AvatarId { get; set; }
|
||||
|
||||
public int? ClubId { get; set; }
|
||||
|
@ -26,9 +26,6 @@ public class DiscordUser : DbEntity
|
|||
|
||||
public override string ToString()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Discriminator) || Discriminator == "0000")
|
||||
return Username;
|
||||
|
||||
return Username + "#" + Discriminator;
|
||||
return Username;
|
||||
}
|
||||
}
|
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 void UpdateUsernames(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.Sql("UPDATE DiscordUser SET Username = '??' + Username WHERE Discriminator = '????';");
|
||||
}
|
||||
|
||||
public static void MigrateRero(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
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.Username,
|
||||
x.Discriminator
|
||||
})
|
||||
.Where(x => users.Select(y => y.Id).Contains(x.UserId))
|
||||
.ToArrayAsyncEF();
|
||||
|
@ -465,12 +464,11 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, IEService
|
|||
UserId = x.Id,
|
||||
AvatarId = x.AvatarId,
|
||||
Username = x.Username,
|
||||
Discriminator = x.Discriminator
|
||||
});
|
||||
|
||||
var added = (await ctx.BulkCopyAsync(usersToAdd)).RowsCopied;
|
||||
var toUpdateUserIds = presentDbUsers
|
||||
.Where(x => x.Username == "Unknown" && x.Discriminator == "????")
|
||||
.Where(x => x.Username.StartsWith("??"))
|
||||
.Select(x => x.UserId)
|
||||
.ToArray();
|
||||
|
||||
|
@ -481,7 +479,6 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, IEService
|
|||
.UpdateAsync(x => new DiscordUser()
|
||||
{
|
||||
Username = user.Username,
|
||||
Discriminator = user.Discriminator,
|
||||
|
||||
// .award tends to set AvatarId and DateAdded to NULL, so account for that.
|
||||
AvatarId = user.AvatarId,
|
||||
|
|
|
@ -603,7 +603,7 @@ public class WaifuService : IEService, IReadyExecutor
|
|||
.Where(wi => wi.ClaimerId == waifuId)
|
||||
.Select(wi => wi.WaifuId)
|
||||
.Contains(x.Id))
|
||||
.Select(x => $"{x.Username}#{x.Discriminator}")
|
||||
.Select(x => x.Username)
|
||||
.ToListAsyncEF();
|
||||
}
|
||||
|
||||
|
@ -615,7 +615,7 @@ public class WaifuService : IEService, IReadyExecutor
|
|||
.Where(wi => wi.AffinityId == waifuId)
|
||||
.Select(wi => wi.WaifuId)
|
||||
.Contains(x.Id))
|
||||
.Select(x => $"{x.Username}#{x.Discriminator}")
|
||||
.Select(x => x.Username)
|
||||
.ToListAsyncEF();
|
||||
}
|
||||
|
||||
|
|
|
@ -42,15 +42,12 @@ public static class WaifuExtensions
|
|||
{
|
||||
Affinity = x.Affinity == null
|
||||
? null
|
||||
: x.Affinity.Username
|
||||
+ (x.Affinity.Discriminator != "0000" ? "#" + x.Affinity.Discriminator : ""),
|
||||
: x.Affinity.Username,
|
||||
ClaimerName =
|
||||
x.Claimer == null
|
||||
? null
|
||||
: x.Claimer.Username
|
||||
+ (x.Claimer.Discriminator != "0000" ? "#" + x.Claimer.Discriminator : ""),
|
||||
WaifuName = x.Waifu.Username
|
||||
+ (x.Waifu.Discriminator != "0000" ? "#" + x.Waifu.Discriminator : ""),
|
||||
: x.Claimer.Username,
|
||||
WaifuName = x.Waifu.Username,
|
||||
Price = x.Price
|
||||
})
|
||||
.ToListAsyncEF();
|
||||
|
@ -62,7 +59,7 @@ public static class WaifuExtensions
|
|||
public static ulong GetWaifuUserId(this DbSet<WaifuInfo> waifus, ulong ownerId, string name)
|
||||
=> waifus.AsQueryable()
|
||||
.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)
|
||||
.FirstOrDefault();
|
||||
|
||||
|
@ -100,7 +97,7 @@ public static class WaifuExtensions
|
|||
ctx.Set<DiscordUser>()
|
||||
.AsQueryable()
|
||||
.Where(u => u.UserId == userId)
|
||||
.Select(u => u.Username + "#" + u.Discriminator)
|
||||
.Select(u => u.Username)
|
||||
.FirstOrDefault(),
|
||||
AffinityCount =
|
||||
ctx.Set<WaifuUpdate>()
|
||||
|
@ -112,14 +109,14 @@ public static class WaifuExtensions
|
|||
ctx.Set<DiscordUser>()
|
||||
.AsQueryable()
|
||||
.Where(u => u.Id == w.AffinityId)
|
||||
.Select(u => u.Username + "#" + u.Discriminator)
|
||||
.Select(u => u.Username)
|
||||
.FirstOrDefault(),
|
||||
ClaimCount = ctx.Set<WaifuInfo>().AsQueryable().Count(x => x.ClaimerId == w.WaifuId),
|
||||
ClaimerName =
|
||||
ctx.Set<DiscordUser>()
|
||||
.AsQueryable()
|
||||
.Where(u => u.Id == w.ClaimerId)
|
||||
.Select(u => u.Username + "#" + u.Discriminator)
|
||||
.Select(u => u.Username)
|
||||
.FirstOrDefault(),
|
||||
DivorceCount =
|
||||
ctx.Set<WaifuUpdate>()
|
||||
|
|
|
@ -29,7 +29,7 @@ public partial class Games
|
|||
if (!await nunchi.Join(ctx.User.Id, ctx.User.ToString()))
|
||||
return;
|
||||
|
||||
await Response().Error(strs.nunchi_joined(nunchi.ParticipantCount)).SendAsync();
|
||||
await Response().Confirm(strs.nunchi_joined(nunchi.ParticipantCount)).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -122,11 +122,11 @@ public sealed class CurrencyRewardService : IEService, IReadyExecutor
|
|||
var dollarValue = pledgeCents / 100;
|
||||
percentBonus = dollarValue switch
|
||||
{
|
||||
>= 100 => 100,
|
||||
>= 50 => 50,
|
||||
>= 20 => 20,
|
||||
>= 10 => 10,
|
||||
>= 5 => 5,
|
||||
>= 100 => 20,
|
||||
>= 50 => 10,
|
||||
>= 20 => 5,
|
||||
>= 10 => 3,
|
||||
>= 5 => 1,
|
||||
_ => 0
|
||||
};
|
||||
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)
|
||||
{
|
||||
_atcs[c.ChannelId] = c.AutoDelete;
|
||||
_users[c.ChannelId] =
|
||||
new(c.Users.ToDictionary(x => x.UserId, x => (x.Source.ToLower(), x.Target.ToLower())));
|
||||
_users[c.ChannelId] = new(c.Users.ToDictionary(x => x.UserId, x => (x.Source.ToLower(), x.Target.ToLower())));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task ExecOnNoCommandAsync(IGuild guild, IUserMessage msg)
|
||||
{
|
||||
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))
|
||||
throw new ArgumentException("Text is empty or null", nameof(text));
|
||||
|
|
|
@ -6,6 +6,14 @@ public partial class Searches
|
|||
[Group]
|
||||
public partial class TranslateCommands : EllieModule<ITranslateService>
|
||||
{
|
||||
private readonly FlagTranslateService _flagSvc;
|
||||
|
||||
public TranslateCommands(FlagTranslateService flagSvc)
|
||||
{
|
||||
_flagSvc = flagSvc;
|
||||
}
|
||||
|
||||
|
||||
public enum AutoDeleteAutoTranslate
|
||||
{
|
||||
Del,
|
||||
|
@ -91,5 +99,18 @@ public partial class Searches
|
|||
|
||||
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,
|
||||
ServerCallContext context)
|
||||
{
|
||||
await Task.Yield();
|
||||
|
||||
var guild = _client.GetGuild(request.GuildId);
|
||||
|
||||
if (guild is null)
|
||||
|
@ -54,6 +56,26 @@ public class XpSvc : GrpcXp.GrpcXpBase, IGrpcSvc, IEService
|
|||
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;
|
||||
|
||||
return reply;
|
||||
|
|
|
@ -201,9 +201,12 @@ public sealed partial class GoogleApiService : IGoogleApiService, IEService
|
|||
{
|
||||
string text;
|
||||
|
||||
if (!Languages.ContainsKey(sourceLanguage) || !Languages.ContainsKey(targetLanguage))
|
||||
if (!Languages.ContainsKey(targetLanguage))
|
||||
throw new ArgumentException(nameof(sourceLanguage) + "/" + nameof(targetLanguage));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(sourceLanguage) || !Languages.ContainsKey(sourceLanguage))
|
||||
sourceLanguage = "auto";
|
||||
|
||||
|
||||
var url = new Uri(string.Format(
|
||||
"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)
|
||||
{
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -77,8 +77,7 @@ public class DefaultWallet : IWallet
|
|||
.InsertOrUpdateAsync(() => new()
|
||||
{
|
||||
UserId = userId,
|
||||
Username = "Unknown",
|
||||
Discriminator = "????",
|
||||
Username = "??Unknown",
|
||||
CurrencyAmount = amount,
|
||||
},
|
||||
(old) => new()
|
||||
|
|
|
@ -193,7 +193,7 @@ public sealed class StatsService : IStatsService, IReadyExecutor, IEService
|
|||
Id = g.Id,
|
||||
IconUrl = g.IconUrl,
|
||||
Name = g.Name,
|
||||
Owner = (await ig.GetUserAsync(g.OwnerId))?.Username ?? "Unknown",
|
||||
Owner = (await ig.GetUserAsync(g.OwnerId))?.Username ?? "??Unknown",
|
||||
OwnerId = g.OwnerId,
|
||||
CreatedAt = g.CreatedAt.UtcDateTime,
|
||||
VoiceChannels = g.VoiceChannels.Count,
|
||||
|
|
|
@ -1445,3 +1445,8 @@ ncpixel:
|
|||
- ncgp
|
||||
ncreset:
|
||||
- ncreset
|
||||
translateflags:
|
||||
- translateflags
|
||||
- trfl
|
||||
- fltr
|
||||
- transflags
|
|
@ -4634,3 +4634,11 @@ ncreset:
|
|||
- ''
|
||||
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_insuff_payment": "Invalid payment.",
|
||||
"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