From 4b12e4e923c73178000a5ba594163373f5c0f44a Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sat, 2 Nov 2024 16:23:58 +0000 Subject: [PATCH] dev: Removed discrim from the database add: .translateflags command add: captcha to timely, configurable in .conf gambling change: change bonuses for patreon rewards fix: nunchi message color fix --- CHANGELOG.md | 703 +-- .../Db/Extensions/DiscordUserExtensions.cs | 5 +- src/NadekoBot/Db/Models/DiscordUser.cs | 7 +- .../Db/Models/FlagTranslateChannel.cs | 8 + src/NadekoBot/Db/NadekoContext.cs | 8 + src/NadekoBot/Migrations/MigrationQueries.cs | 5 + ..._no-discrim-and-flag-translate.Designer.cs | 3851 +++++++++++++++++ ...102022956_no-discrim-and-flag-translate.cs | 56 + .../PostgreSqlContextModelSnapshot.cs | 35 +- ..._no-discrim-and-flag-translate.Designer.cs | 2973 +++++++++++++ ...102022949_no-discrim-and-flag-translate.cs | 55 + .../NadekoSqliteContextModelSnapshot.cs | 26 +- .../Administration/Self/SelfService.cs | 5 +- .../Modules/Gambling/Waifus/WaifuService.cs | 4 +- .../Gambling/Waifus/db/WaifuExtensions.cs | 17 +- .../Modules/Games/Nunchi/NunchiCommands.cs | 2 +- .../Patronage/CurrencyRewardService.cs | 10 +- .../Translate/FlagTranslateService.cs | 191 + .../FlagTranslateService_SupportedFlags.cs | 73 + .../Searches/Translate/TranslateService.cs | 6 +- .../Searches/Translate/TranslatorCommands.cs | 21 + src/NadekoBot/Services/GrpcApi/XpSvc.cs | 22 + .../_common/Impl/GoogleApiService.cs | 7 +- .../GoogleApiService_SupportedLanguages.cs | 1 - .../Services/Currency/DefaultWallet.cs | 3 +- .../_common/Services/Impl/StatsService.cs | 2 +- src/NadekoBot/data/aliases.yml | 7 +- .../data/strings/commands/commands.en-US.yml | 8 + .../strings/responses/responses.en-US.json | 4 +- 29 files changed, 7782 insertions(+), 333 deletions(-) create mode 100644 src/NadekoBot/Db/Models/FlagTranslateChannel.cs create mode 100644 src/NadekoBot/Migrations/PostgreSql/20241102022956_no-discrim-and-flag-translate.Designer.cs create mode 100644 src/NadekoBot/Migrations/PostgreSql/20241102022956_no-discrim-and-flag-translate.cs create mode 100644 src/NadekoBot/Migrations/Sqlite/20241102022949_no-discrim-and-flag-translate.Designer.cs create mode 100644 src/NadekoBot/Migrations/Sqlite/20241102022949_no-discrim-and-flag-translate.cs create mode 100644 src/NadekoBot/Modules/Searches/Translate/FlagTranslateService.cs create mode 100644 src/NadekoBot/Modules/Searches/Translate/FlagTranslateService_SupportedFlags.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index 58818c32c..805081c08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,27 +2,56 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except date format. a-c-f-r-o +## [5.1.18] - 02.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 ` or `.ncz x y` - - set pixel: `.ncsp ` - - get pixel: `.ncp ` - - 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 ` or `.ncz x y` + - set pixel: `.ncsp ` + - get pixel: `.ncp ` + - 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 ## Added - Added -c option for `.xpglb` -- +- ## Change @@ -31,7 +60,7 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da ## Fixed -- Fixed a big issue which caused several features to not get loaded on bot restart +- Fixed a big issue which caused several features to not get loaded on bot restart - Alias collision fix `.qse` is now quotesearch, `.qs` will stay `.queuesearch` - Fixed some migrations which would prevent users from updating from ancient versions - Waifulb will no longer show #0000 discrims @@ -70,10 +99,11 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.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 - Fixed a bug which caused `.bye` and `.greet` messages to be randomly disabled @@ -82,9 +112,9 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.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,29 +133,33 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.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 medusa 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] - 19.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. +- 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. - `.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` 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` 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 +- `.setgame` renamed to`.setactivity` and now supports custom text activity. You don't have to specify playing, + listening etc before the activity - Clarified and added some embed / placeholder links to command help where needed - dev: A lot of code cleanup and internal improvements @@ -142,7 +176,7 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.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] - 08.08.2024 @@ -166,15 +200,16 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.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?) + +- 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?) - 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 +217,9 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da ### Added - Added: Added a `.afk ?` 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,14 +227,16 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da - Updated some bet descriptions to include 'all' 'half' usage instructions - Updated some command strings - dev: Vastly simplified medusa 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 -- .coins will no longer show double minus sign for negative changes +- .coins will no longer show double minus sign for negative changes - You can once again disable cleverbot responses using fake 'cleverbot:response' module name in permission commands ### Removed + - Removed .rip command ## [5.1.4] - 13.07.2024 @@ -208,12 +245,14 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da - Added `.coins` command which lists top 10 cryptos ordered by marketcap - 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 `x`, no spaces +- 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 `x`, 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. +- 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 @@ -235,7 +274,8 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da ### Changed -- Replying to the bot's message in the channel where chatterbot is enabled will also trigger the ai response, as if you pinged the bot. This only works for chatterbot, but not for nadeko ai command prompts +- Replying to the bot's message in the channel where chatterbot is enabled will also trigger the ai response, as if you + pinged the bot. This only works for chatterbot, but not for nadeko ai command prompts ### Fixed @@ -254,9 +294,9 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.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 @@ -268,28 +308,33 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da ### Added - Added `.prompt` command, Nadeko Ai Assistant - - You can send natural language questions, queries or execute commands. For example "@Nadeko how's the weather in paris" and it will return `.we Paris` and run it for you. - - In case the bot can't execute a command using your query, It will fall back to your chatter bot, in case you have it enabled in data/games.yml. (Cleverbot or chatgpt) - - (It's far from perfect so please don't ask the bot to do dangerous things like banning or pruning) - - Requires Patreon subscription, after which you'll be able to run it on global @Nadeko bot. - - Selfhosters: If you're selfhosting, you also will need to acquire the api key from after pledging on patreon and put it in nadekoAiToken in creds.yml + - You can send natural language questions, queries or execute commands. For example "@Nadeko how's the weather in + paris" and it will return `.we Paris` and run it for you. + - In case the bot can't execute a command using your query, It will fall back to your chatter bot, in case you have + it enabled in data/games.yml. (Cleverbot or chatgpt) + - (It's far from perfect so please don't ask the bot to do dangerous things like banning or pruning) + - Requires Patreon subscription, after which you'll be able to run it on global @Nadeko bot. + - Selfhosters: If you're selfhosting, you also will need to acquire the api key + from after pledging on patreon and put it in nadekoAiToken in creds.yml - Added support for `gpt-4o` in `data/games.yml` - ### Changed - Remind will now show a timestamp tag for durations - Only `Gpt35Turbo` and `Gpt4o` are valid inputs in games.yml now -- `data/patron.yml` changed. It now has limits. The entire feature limit system has been reworked. Your previous settings will be reset +- `data/patron.yml` changed. It now has limits. The entire feature limit system has been reworked. Your previous + settings will be reset - A lot of updates to bot strings (thanks Ene) -- Improved cleanup command to delete a lot more data once cleanup is ran, not only guild configs (please don't use this command unless you have your database bakced up and you know 100% what you're doing) +- Improved cleanup command to delete a lot more data once cleanup is ran, not only guild configs (please don't use this + command unless you have your database bakced up and you know 100% what you're doing) ### Fixed - 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. +- `.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 (thx cata) ### Removed @@ -303,10 +348,12 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da - Added `.setserverbanner` and `.setservericon` commands (thx cata) - 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 +- 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 @@ -323,14 +370,15 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da ### Fixed -- `.streammessage` will once again be able to mention anyone (as long as the user setting the message has the permission to mention everyone) +- `.streammessage` will once again be able to mention anyone (as long as the user setting the message has the permission + to mention everyone) - `.streammsgall` fixed - `.xplb` and `.xpglb` pagination fixed - Fixed page number when the total number of elements is unknown ## [5.0.6] - 14.05.2024 -### Changed +### Changed - `.greet` and `.bye` will now be automatically disabled if the bot losses permissions to post in the specified channel - Removed response replies from `.blackjack` and `.pick` as the original message will always be deleted @@ -338,7 +386,7 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da ### Fixed - Fixed `.blackjack` response string as it contained no user name -- Fixed `.ttt` and `.gift` strings not mentioning the user +- Fixed `.ttt` and `.gift` strings not mentioning the user ## [5.0.5] - 11.05.2024 @@ -352,45 +400,52 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da ### Added -- Added `.shopadd command` You can now sell commands in the shop. The command will execute as if you were the one running it when someone buys it - - type `.h .shopadd` for more info -- Added `.stickyroles` Users leaving the server will have their roles saved to the database and reapplied if they rejoin within 30 days. +- Added `.shopadd command` You can now sell commands in the shop. The command will execute as if you were the one + running it when someone buys it + - type `.h .shopadd` for more info +- Added `.stickyroles` Users leaving the server will have their roles saved to the database and reapplied if they rejoin + within 30 days. - Giveaway commands - - `.ga start ` starts the giveway with the specified duration and message (prize). You may have up to 5 giveaways on the server at once - - `.ga end ` prematurely ends the giveaway and selects a winner - - `.ga cancel ` cancels the giveaway and doesn't select a winner - - `.ga list` lists active giveaways on the current server - - `.ga reroll ` rerolls the winner on the completed giveaway. This only works for 24 hours after the giveaway has ended, or until the bot restarts. - - Users can join the giveaway by adding a :tada: reaction + - `.ga start ` starts the giveway with the specified duration and message (prize). You may have up + to 5 giveaways on the server at once + - `.ga end ` prematurely ends the giveaway and selects a winner + - `.ga cancel ` cancels the giveaway and doesn't select a winner + - `.ga list` lists active giveaways on the current server + - `.ga reroll ` rerolls the winner on the completed giveaway. This only works for 24 hours after the giveaway + has ended, or until the bot restarts. + - Users can join the giveaway by adding a :tada: reaction - Added Todo Commands - - `.todo add ` - adds a new todo - - `.todo delete ` - deletes a todo item - - `.todo done ` - completes a todo (marks it with a checkmark) - - `.todo list` - lists all todos - - `.todo edit ` - edits a todo item message - - `.todo show ` - Shows the text of the specified todo item - - In addition to that, there are also Todo archive commands - - `.todo archive add ` - adds all current todos (completed and not completed) to the archived list, your current todo list will become cleared - - `.todo archive list` - lists all your archived todo lists - - `.todo archive show ` - shows the todo items from one of your archived lists - - `.todo archive delete ` - deletes and archived todo list + - `.todo add ` - adds a new todo + - `.todo delete ` - deletes a todo item + - `.todo done ` - completes a todo (marks it with a checkmark) + - `.todo list` - lists all todos + - `.todo edit ` - edits a todo item message + - `.todo show ` - Shows the text of the specified todo item + - In addition to that, there are also Todo archive commands + - `.todo archive add ` - adds all current todos (completed and not completed) to the archived list, your + current todo list will become cleared + - `.todo archive list` - lists all your archived todo lists + - `.todo archive show ` - shows the todo items from one of your archived lists + - `.todo archive delete ` - deletes and archived todo list - Added `.queufairplay` / `.qfp` (music feature) re-added but it works differently - - Once you run it, it will reorganize currently queued songs so that they're in a fair order. + - Once you run it, it will reorganize currently queued songs so that they're in a fair order. - Added `.clubrename` command to uh rename your club - For self-hosters: - - Added `.sqlselectcsv` which will return results in a csv file instead of an embed. - - You can set whether nadeko ignores other bots in `bot.yml` - - You can set shop sale cut in `gambling.yml` + - Added `.sqlselectcsv` which will return results in a csv file instead of an embed. + - You can set whether nadeko ignores other bots in `bot.yml` + - You can set shop sale cut in `gambling.yml` - Added a page parameter to `.feedlist` - Added seconds/sec/s to `.convert` command - Added `.prunecancel` to cancel an active prune -- Added progress reporting when using `.prune`. +- Added progress reporting when using `.prune`. - Added audit log reason for `.setrole` and some other features ### Changed -- Users who have manage messages perm in the channel will now be excluded from link and invite filtering (`.sfi` and `.sfl`) -- `.send` command should work consistently and correctly now. You can have targets from other shards too. The usage has been changed. refer to `.h .send` for more info +- Users who have manage messages perm in the channel will now be excluded from link and invite filtering (`.sfi` + and `.sfl`) +- `.send` command should work consistently and correctly now. You can have targets from other shards too. The usage has + been changed. refer to `.h .send` for more info - `.serverinfo` no longer takes a server name. It only takes an id or no arguments - You can now target a different channel with .repeat - `.cmds `, `.cmds 1 considered wins + - Better than .slottest + - Counts win/loss streaks too + - Doesn't count 1x returns as neither wins nor losses + - multipliers < 1 are considered losses, > 1 considered wins - Added `.betdraw` command which lets you guess red/black and/or high/low for a random card - - They payouts are very good, but seven always loses -- Added `.lula` command. Plays the same as `.wof` but looks much nicer, and is easily customizable from gambling.yml without any changes to the sourcecode needed. + - They payouts are very good, but seven always loses +- Added `.lula` command. Plays the same as `.wof` but looks much nicer, and is easily customizable from gambling.yml + without any changes to the sourcecode needed. - Added `.repeatskip` command which makes the next repeat trigger not post anything - Added `.linkonly` which will make the bot only allow link posts in the channel. Exclusive with `.imageonly` -- Added release notifications. Bot owners will now receive new release notifications in dms if they have `checkForUpdates` set to `true` in data/bot.yml - - You can also configure it via `.conf bot checkfor - - updates ` +- Added release notifications. Bot owners will now receive new release notifications in dms if they + have `checkForUpdates` set to `true` in data/bot.yml + - You can also configure it via `.conf bot checkfor + - updates ` - Added `.xpshop` which lets bot owners add xp backgrounds and xp frames for sale by configuring `data/xp.yml` - - You can also toggle xpshop feature via `.conf xp shop.is_enabled` + - You can also toggle xpshop feature via `.conf xp shop.is_enabled` ### Changed @@ -752,23 +824,23 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da - `.xpadd` will now work on roles too. It will add the specified xp to each user (visible to the bot) in the role - Improved / cleaned up / modernized how most gambling commands look - - `.roll` - - `.rolluo` - - `.draw` - - `.flip` - - `.slot` - - `.betroll` - - `.betflip` - - Try them out! + - `.roll` + - `.rolluo` + - `.draw` + - `.flip` + - `.slot` + - `.betroll` + - `.betflip` + - Try them out! - `.draw`, `.betdraw` and some other card commands (not all) will use the new, rewritten deck system - Error will be printed to the console if there's a problem in `.plant` - [dev] Split Nadeko.Common into a separate project - - [dev] It will contain classes/utilities which can be shared across different nadeko related projects + - [dev] It will contain classes/utilities which can be shared across different nadeko related projects - [dev] Split Nadeko.Econ into a separate project - - [dev] It should be home for the backend any gambling/currency/economy feature - - [dev] It will contain most gambling games and any shared logic + - [dev] It should be home for the backend any gambling/currency/economy feature + - [dev] It will contain most gambling games and any shared logic - [dev] Compliation should take less time and RAM - - [dev] No longer using generator and partial methods for commands + - [dev] No longer using generator and partial methods for commands ### Fixed @@ -808,7 +880,8 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da ### Fixed -- Fixed elipsis character issue with aliases/quotes. You should now be able to set an elipsis to be an alias of `.quoteprint` +- Fixed elipsis character issue with aliases/quotes. You should now be able to set an elipsis to be an alias + of `.quoteprint` ## [4.2.13] - 30.06.2022 @@ -849,11 +922,11 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da ### Changed - New cache abstraction added - - 2 implemenations: redis and memory - - All current bots will stay on redis cache, all new bots will use **in-process memory cache by default** - - This change removes bot's hard dependency on redis - - Configurable in `creds.yml` (please read the comments) - - You **MUST** use 'redis' if your bot runs on more than 1 shard (2000+ servers) + - 2 implemenations: redis and memory + - All current bots will stay on redis cache, all new bots will use **in-process memory cache by default** + - This change removes bot's hard dependency on redis + - Configurable in `creds.yml` (please read the comments) + - You **MUST** use 'redis' if your bot runs on more than 1 shard (2000+ servers) - [dev] Using new non-locking ConcurrentDictionary ### Fixed @@ -874,7 +947,8 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da ### Fixed -- Fixed `.crypto`, you will still need coinmarketcapApiKey in `creds.yml` in order to make it run consistently as the key is shared +- Fixed `.crypto`, you will still need coinmarketcapApiKey in `creds.yml` in order to make it run consistently as the + key is shared ## [4.2.3] - 17.06.2022 @@ -927,7 +1001,8 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da invidiousInstances: [] ``` - Added new properties to `creds.yml`. google -> searchId and google -> searchImageId. -- These properties are used as `cx` (google api query parameter) in case you've setup your `data/searches.yml` to use the official google api. +- These properties are used as `cx` (google api query parameter) in case you've setup your `data/searches.yml` to use + the official google api. `searchId` is used for web search `searchimageId` is used for image search ```yml @@ -938,74 +1013,89 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da - Check `creds_example.yml` for comments explaining how to obtain them. #### Patronage system added + - Added `data/patron.yml` for configuration - Implemented only for patreon so far - Patreon subscription code completely rewritten - Users who pledge on patreon get benefits based on the amount they pledged -- Public nadeko only. But selfhosters can adapt it to their own patreon pages by configuring their patreon credentials in `creds.yml` and enabling the system in `data/patron.yml` file. - - Most of the patronage system strings are hardcoded atm, so if you wish to use this system on selfhosts, you will have to modify the source +- Public nadeko only. But selfhosters can adapt it to their own patreon pages by configuring their patreon credentials + in `creds.yml` and enabling the system in `data/patron.yml` file. + - Most of the patronage system strings are hardcoded atm, so if you wish to use this system on selfhosts, you will + have to modify the source - Pledge amounts are split into tiers. This is not configurable atm. - - Tier I - 1$ - 4.99$ a month - - Tier V - 5$ - 9.99$ a month - - Tier X - 10$ - 19.99$ a month - - Tier XX - 20$ - 49.99$ a month - - Tier L - 50$ - 99.99$ a month - - Tier C - 100$+ a month + - Tier I - 1$ - 4.99$ a month + - Tier V - 5$ - 9.99$ a month + - Tier X - 10$ - 19.99$ a month + - Tier XX - 20$ - 49.99$ a month + - Tier L - 50$ - 99.99$ a month + - Tier C - 100$+ a month - Rewards and command quotas for each of the tiers are configurable - Limitations to certain features are also configurable. ex: + ```yml quotas: - features: - "rero:max_count": - x: 50 + features: + "rero:max_count": + x: 50 ``` + - ^ this setting would set the maximum number of reaction roles to be 50 for a user who is in Patron Tier X - Read the comments in the .yml file for (much) more info - Quota system allows the owner to set up hourly, daily and monthly quota usage for each tier - Quota system applies to entire server owner by a patron - - Patron spends own quota by using the commands on any server - - Any user on *any* server owned by a patron spends that patron's quota + - Patron spends own quota by using the commands on any server + - Any user on *any* server owned by a patron spends that patron's quota - When users subscribe to patreon they will receive a welcome message - - If you're enabling patron system for a selfhost, you will want to edit it + - If you're enabling patron system for a selfhost, you will want to edit it Added `.patron` and `.patronmessage` commands + - `.patron` checks your patronage status, and quotas. Requires patron system to be enabled. - `.patronmessage` (owner only) sends message to all patrons with the specified tier or higher. Supports embeds -- Added a fake `.cmdcd` command `cleverbot:response` which can be used to limit how often users can talk to the cleverbot. +- Added a fake `.cmdcd` command `cleverbot:response` which can be used to limit how often users can talk to the + cleverbot. ### Changed - CurrencyReward now support adding additional flowers to patrons. - `.donate` command completely reworked. - - Works only on public bot (OnlyPublicBotAttribute) - - Guides user on how to donate to support the project - - Added interaction explaining selfhosting + - Works only on public bot (OnlyPublicBotAttribute) + - Guides user on how to donate to support the project + - Added interaction explaining selfhosting - `.google` reimplemented. It now has 2 modes configurable in `data/searches.yml` under the `webSearchengine` property - - If set to `google`, official custom search api will be used. You will need to set googleapikey and google.searchId in `creds.yml` - - if set to `searx` one of the instances specified in the `searxInstances:` property will be randomly chosen for each request - - instances must have `format=json` allowed (public ones usually don't allow it) - - instances are specified as a fully qualified url, example: `https://my.cool.searx.instance.io` -- `.image` reimplemented. Same as `.google` - it uses either `google` official api (in which case it uses `google.searchImageId` from `creds.yml`) or `searx` + - If set to `google`, official custom search api will be used. You will need to set googleapikey and google.searchId + in `creds.yml` + - if set to `searx` one of the instances specified in the `searxInstances:` property will be randomly chosen for + each request + - instances must have `format=json` allowed (public ones usually don't allow it) + - instances are specified as a fully qualified url, example: `https://my.cool.searx.instance.io` +- `.image` reimplemented. Same as `.google` - it uses either `google` official api (in which case it + uses `google.searchImageId` from `creds.yml`) or `searx` -- `.youtube` reimplemented. It will use a `ytProvider:` property from `data/searches.yml` to determine how to retrieve results - - `ytdataapi` will use the official google api (requires `GoogleApiKey` specified in `creds.yml`) and YoutubeDataApi enabled in the dev console - - `ytdl` will use `youtube-dl` program from the host machine. It must be downloaded and it's location must be added to path env variable. - - `ytdlp` will use `yt-dlp` program from the host machine. Same as `youtube-dl` - must be in path env variable. - - `invidious` will use one of invidious instances specified in the `invidiousInstances` property. Very good. +- `.youtube` reimplemented. It will use a `ytProvider:` property from `data/searches.yml` to determine how to retrieve + results + - `ytdataapi` will use the official google api (requires `GoogleApiKey` specified in `creds.yml`) and YoutubeDataApi + enabled in the dev console + - `ytdl` will use `youtube-dl` program from the host machine. It must be downloaded and it's location must be added + to path env variable. + - `ytdlp` will use `yt-dlp` program from the host machine. Same as `youtube-dl` - must be in path env variable. + - `invidious` will use one of invidious instances specified in the `invidiousInstances` property. Very good. - `.google`, `.youtube` and `.image` moved to the new Search group Note: Results of each `.youtube` query will be cached for 1 hour to improve perfomance + - Removed 30 second `.ping` ratelimit on public nadeko - xp image generation changes - - In case you have default settings, your xp image will look slightly different - - If you've modified xp_template.json, your xp image might look broken. Your old template will be saved in xp_template.json.old - - Xp number outline is now slightly thicker - - Xp number will now have Center vertical and horizontal alignment - - LastLevelUp no longer supported + - In case you have default settings, your xp image will look slightly different + - If you've modified xp_template.json, your xp image might look broken. Your old template will be saved in + xp_template.json.old + - Xp number outline is now slightly thicker + - Xp number will now have Center vertical and horizontal alignment + - LastLevelUp no longer supported - Some commands will now use timestamp tags for better user experience - `.prune` was slightly slowed down to avoid ratelimits @@ -1061,38 +1151,38 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf ### Added - Added support for embed arrays in commands such as .say, .greet, .bye, etc... - - Website to create them is live at eb.nadeko.bot (old one is moved to oldeb.nadeko.bot) - - Embed arrays don't have a plainText property (it's renamed to 'content') - - Embed arrays use color hex values instead of an integer - - Old embed format will still work - - There shouldn't be any breaking changes -- Added `.stondel` command which, when toggled, will make the bot delete online stream messages on the server when the stream goes offline + - Website to create them is live at eb.nadeko.bot (old one is moved to oldeb.nadeko.bot) + - Embed arrays don't have a plainText property (it's renamed to 'content') + - Embed arrays use color hex values instead of an integer + - Old embed format will still work + - There shouldn't be any breaking changes +- Added `.stondel` command which, when toggled, will make the bot delete online stream messages on the server when the + stream goes offline - Added a simple bank system. - - Users can deposit, withdraw and check the balance of their currency in the bank. - - Users can't check other user's bank balances. + - Users can deposit, withdraw and check the balance of their currency in the bank. + - Users can't check other user's bank balances. - Added a button on a .$ command which, when clicked, sends you a message with your bank balance that only you can see. - Added `.h ` - - Using this command will list all commands in the specified group - - Atm only .bank is a proper group (`.h bank`) + - Using this command will list all commands in the specified group + - Atm only .bank is a proper group (`.h bank`) - Added "Bank Accounts" entry to `.economy` ### Changed - Reaction roles rewritten completely - - Supports multiple exclusivity groups per message - - Supports level requirements - - However they can only be added one by one - - Use the following commands for more information - - `.h .reroa` - - `.h .reroli` - - `.h .rerot` - - `.h .rerorm` - - `.h .rerodela` + - Supports multiple exclusivity groups per message + - Supports level requirements + - However they can only be added one by one + - Use the following commands for more information + - `.h .reroa` + - `.h .reroli` + - `.h .rerot` + - `.h .rerorm` + - `.h .rerodela` - Pagination is now using buttons instead of reactions - Bot will now support much higher XP values for global and server levels - [dev] Small change and generation perf improvement for the localized response strings - ### Fixed - Fixed `.deletexp` command @@ -1110,24 +1200,27 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf ### Added - NadekoBot now supports mysql, postgresql and sqlite - - To change the db nadeko will use, simply change the `db type` in `creds.yml` - - There is no migration code right now, which means that if you want to switch to another system you'll either have to manually export/import your database or start fresh + - To change the db nadeko will use, simply change the `db type` in `creds.yml` + - There is no migration code right now, which means that if you want to switch to another system you'll either have + to manually export/import your database or start fresh - Medusa system - - A massive new feature which allows developers to create custom modules/plugins/cogs - - They can be load/unloaded/updated at runtime without restarting the bot + - A massive new feature which allows developers to create custom modules/plugins/cogs + - They can be load/unloaded/updated at runtime without restarting the bot ### Changed - Minor club rework - - Clubs names are now case sensitive (owo and OwO can be 2 different clubs) - - Removed discriminators - - Current discriminators which are greater than 1 are appended to clubnames to avoid duplicates, you can rename your club with `.clubrename` to remove it - - Most of the clubs with #1 discriminator no longer have it (For example MyClub#1 will now just be MyClub) -- [dev] A lot of refactoring and slight functionality changes within Nadeko's behavior system and command handler which were required in order to support the medusa system + - Clubs names are now case sensitive (owo and OwO can be 2 different clubs) + - Removed discriminators + - Current discriminators which are greater than 1 are appended to clubnames to avoid duplicates, you can rename + your club with `.clubrename` to remove it + - Most of the clubs with #1 discriminator no longer have it (For example MyClub#1 will now just be MyClub) +- [dev] A lot of refactoring and slight functionality changes within Nadeko's behavior system and command handler which + were required in order to support the medusa system ### Removed - - Removed `.clublevelreq` command as it doesn't serve much purpose +- Removed `.clublevelreq` command as it doesn't serve much purpose ## [4.0.6] - 21.03.2022 @@ -1173,43 +1266,51 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf ## [4.0.0] - 02.03.2022 ### Added + - Added `.deleteemptyservers` command - Added `.curtr ` which lets you see full information about one of your own transactions with the specified id - Added trovo.live support for stream notifications (`.stadd`) - Added unclaimed waifu decay functionality - - Added 3 new settings to `data/gambling.yml` to control it: - - waifu.decay.percent - How much % to subtract from unclaimed waifu - - waifu.decay.hourInterval - How often to decay the price - - waifu.decay.minPrice - Unclaimed waifus with price lower than the one specified here will not be affected by the decay -- Added `currency.transactionsLifetime` to `data/gambling.yml` Any transaction older than the number of days specified will be automatically deleted + - Added 3 new settings to `data/gambling.yml` to control it: + - waifu.decay.percent - How much % to subtract from unclaimed waifu + - waifu.decay.hourInterval - How often to decay the price + - waifu.decay.minPrice - Unclaimed waifus with price lower than the one specified here will not be affected by + the decay +- Added `currency.transactionsLifetime` to `data/gambling.yml` Any transaction older than the number of days specified + will be automatically deleted - Added `.stock` command to check stock prices and charts - Re-added `.qap / .queueautoplay` ### Changed + - CustomReactions module (and customreactions db table) has been renamed to Expressions. - - This was done to remove confusion about how it relates to discord Reactions (it doesn't, it was created and named before discord reactions existed) - - Expression command now start with ex/expr and end with the name of the action or setting. - - For example `.exd` (`.dcr`) is expression delete, `.exa` (`.acr`) - - Permissions (`.lp`) be automatically updated with "ACTUALEXPRESSIONS", "EXPRESSIONS" instead of "ACTUALCUSTOMREACTIONS" and "CUSTOMREACTIONS" - - Permissions for `.ecr` (now `.exe`), `.scr` (now `.exs`), `.dcr` (now `.exd`), `.acr` (now `.exa`), `.lcr` (now `.exl`) will be automatically updated - - If you have custom permissions for other CustomReaction commands - - Some of the old aliases like `.acr` `.dcr` `.lcr` and a few others have been kept + - This was done to remove confusion about how it relates to discord Reactions (it doesn't, it was created and named + before discord reactions existed) + - Expression command now start with ex/expr and end with the name of the action or setting. + - For example `.exd` (`.dcr`) is expression delete, `.exa` (`.acr`) + - Permissions (`.lp`) be automatically updated with "ACTUALEXPRESSIONS", "EXPRESSIONS" instead of " + ACTUALCUSTOMREACTIONS" and "CUSTOMREACTIONS" + - Permissions for `.ecr` (now `.exe`), `.scr` (now `.exs`), `.dcr` (now `.exd`), `.acr` (now `.exa`), `.lcr` ( + now `.exl`) will be automatically updated + - If you have custom permissions for other CustomReaction commands + - Some of the old aliases like `.acr` `.dcr` `.lcr` and a few others have been kept - Currency output format improvement (will use guild locale now for some commands) - `.crypto` will now also show CoinMarketCap rank - Waifus can now be claimed for much higher prices (int -> long) - Several strings and commands related to music have been changed - - Changed `.ms / .movesong` to `.tm / .trackmove` but kept old aliases - - Changed ~~song~~ -> `track` throughout music module strings + - Changed `.ms / .movesong` to `.tm / .trackmove` but kept old aliases + - Changed ~~song~~ -> `track` throughout music module strings - Improved .curtrs (It will now have a lot more useful data in the database, show Tx ids, and be partially localized) - - [dev] Reason renamed to Note - - [dev] Added Type, Extra, OtherId fields to the database + - [dev] Reason renamed to Note + - [dev] Added Type, Extra, OtherId fields to the database - [dev] CommandStrings will now use methodname as the key, and **not** the command name (first entry in aliases.yml) - - In other words aliases.yml and commands.en-US.yml will use the same keys (once again) + - In other words aliases.yml and commands.en-US.yml will use the same keys (once again) - [dev] Reorganized module and submodule folders - [dev] Permissionv2 db table renamed to Permissions - [dev] Moved FilterWordsChannelId to a separate table ### Fixed + - Fixed twitch stream notifications (rewrote it to use the new api) - Fixed an extra whitespace in usage part of command help if the command has no arguments - Possible small fix for `.prune` ratelimiting @@ -1221,8 +1322,10 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf - Fixed embed color when disabling `.antialt` ### Removed + - Removed `.bce` - use `.config` or `.config bot` specifically for bot config -- Removed obsolete placeholders: %users% %servers% %userfull% %username% %userdiscrim% %useravatar% %id% %uid% %chname% %cid% %sid% %members% %server_time% %shardid% %time% %mention% +- Removed obsolete placeholders: %users% %servers% %userfull% %username% %userdiscrim% %useravatar% %id% %uid% %chname% + %cid% %sid% %members% %server_time% %shardid% %time% %mention% - Removed some obsolete commands and strings - Removed code which migrated 2.x to v3 credentials, settings, etc... @@ -1236,6 +1339,7 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf ## [3.0.12] - 06.01.2022 ### Fixed + - `.smch` Fixed - `.trans` command will now work properly with capitilized language names - Ban message color with plain text fixed @@ -1247,88 +1351,106 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf ## [3.0.11] - 17.12.2021 ### Added -- `.remindl` and `.remindrm` commands now supports optional 'server' parameter for Administrators which allows them to delete any reminder created on the server + +- `.remindl` and `.remindrm` commands now supports optional 'server' parameter for Administrators which allows them to + delete any reminder created on the server - Added slots.currencyFontColor to gambling.yml - Added `.qexport` and `.qimport` commands which allow you to export and import quotes just like `.crsexport` - Added `.showembed ` and `.showembed #channel ` which will show you embed json from the specified message ### Changed + - `.at` and `.atl` commands reworked - - Persist restarts - - Will now only translate non-commands - - You can switch between `.at del` and `.at` without clearing the user language registrations - - Disabling `.at` will clear all user language registrations on that channel - - Users can't register languages if the `.at` is not enabled - - Looks much nicer - - Bot will now reply to user messages with a translation if `del` is disabled - - Bot will make an embed with original and translated text with user avatar and name if `del` is enabled - - If the bot is unable to delete messages while having `del` enabled, it will reset back to the no-del behavior for the current session + - Persist restarts + - Will now only translate non-commands + - You can switch between `.at del` and `.at` without clearing the user language registrations + - Disabling `.at` will clear all user language registrations on that channel + - Users can't register languages if the `.at` is not enabled + - Looks much nicer + - Bot will now reply to user messages with a translation if `del` is disabled + - Bot will make an embed with original and translated text with user avatar and name if `del` is enabled + - If the bot is unable to delete messages while having `del` enabled, it will reset back to the no-del behavior for + the current session ### Fixed + - `.crypto` now supports top 5000 coins ## [3.0.10] - 01.12.2021 ### Changed + - `.warn` now supports weighted warnings - `.warnlog` will now show current amount and total amount of warnings ### Fixed + - `.xprewsreset` now has correct permissions ### Removed + - Removed slot.numbers from `images.yml` as they're no longer used ## [3.0.9] - 21.11.2021 ### Changed + - `.ea` will now use an image attachments if you omit imageUrl ### Added + - Added `.emojiadd` with 3 overloads - - `.ea :customEmoji:` which copies another server's emoji - - `.ea newName :customEmoji:` which copies emoji under a different name - - `.ea emojiName ` which creates a new emoji from the specified image -- Patreon Access and Refresh Tokens should now be automatically updated once a month as long as the user has provided the necessary credentials in creds.yml file: - - `Patreon.ClientId` - - `Patreon.RefreshToken` (will also get updated once a month but needs an initial value) - - `Patreon.ClientSecret` - - `Patreon.CampaignId` + - `.ea :customEmoji:` which copies another server's emoji + - `.ea newName :customEmoji:` which copies emoji under a different name + - `.ea emojiName ` which creates a new emoji from the specified image +- Patreon Access and Refresh Tokens should now be automatically updated once a month as long as the user has provided + the necessary credentials in creds.yml file: + - `Patreon.ClientId` + - `Patreon.RefreshToken` (will also get updated once a month but needs an initial value) + - `Patreon.ClientSecret` + - `Patreon.CampaignId` ### Fixed + - Fixed an error that would show up in the console when a club image couldn't be drawn in certain circumstances ## [3.0.8] - 03.11.2021 ### Added + - Created VotesApi project nad re-worked vote rewards handling - - Updated votes entries in creds.yml with explanations on how to set up vote links + - Updated votes entries in creds.yml with explanations on how to set up vote links ### Fixed + - Fixed adding currency to users who don't exist in the database - Memory used by the bot is now correct (thanks to kotz) - Ban/kick will no longer fail due to too long reasons - Fixed some fields not preserving inline after string replacements ### Changed + - `images.json` moved to `images.yml` - - Links will use the new cdn url - - Heads and Tails images will be updated if you haven't changed them already + - Links will use the new cdn url + - Heads and Tails images will be updated if you haven't changed them already - `.slot` redesigned (and updated entries in `images.yml`) - Reduced required permissions for .qdel (thanks to tbodt) ## [3.0.7] - 05.10.2021 ### Added + - `.streamsclear` re-added. It will remove all followed streams on the server. - `.gifts` now have 3 new ✂️ Haircut 🧻 ToiletPaper and 🥀 WiltedRose which **reduce** waifu's value - - They are called negative gifts - - They show up at the end of the `.gifts` page and are marked with a broken heart - - They have a separate multiplier (`waifu.multi.negative_gift_effect` default 0.5, changeable via `.config gambling` or `data/gambling.yml`) - - When gifted, the waifu's price will be reduced by the `price * multiplier` - - Negative gifts don't show up in `.waifuinfo` nor is the record of them kept in the database + - They are called negative gifts + - They show up at the end of the `.gifts` page and are marked with a broken heart + - They have a separate multiplier (`waifu.multi.negative_gift_effect` default 0.5, changeable via `.config gambling` + or `data/gambling.yml`) + - When gifted, the waifu's price will be reduced by the `price * multiplier` + - Negative gifts don't show up in `.waifuinfo` nor is the record of them kept in the database ### Fixed + - Fixed `%users%` and `%shard.usercount%` placeholders not showing correct values ## [3.0.6] - 27.09.2021 @@ -1340,7 +1462,7 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf ### Changed - Hangman rewrite - - Hangman categories are now held in separate .yml files in data/hangman/XYZ.yml where XYZ is the category name + - Hangman categories are now held in separate .yml files in data/hangman/XYZ.yml where XYZ is the category name ### Fixed @@ -1361,15 +1483,15 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf - Fully translated to Brazilian Portuguese 🎉 - Added `%server.boosters%` and `%server.boost_level%` placeholders - Added `DmHelpTextKeywords` to `data/bot.yml` - - Bot now sends dm help text ONLY if the message contains one of the keywords specified - - If no keywords are specified, bot will reply to every DM (like before) + - Bot now sends dm help text ONLY if the message contains one of the keywords specified + - If no keywords are specified, bot will reply to every DM (like before) ### Fixed - Possible fix for `.repeat` bug - - Slight adjustment for repeater logic - - Timer should no longer increase on some repeaters - - Repeaters should no longer have periods when they're missing from the list + - Slight adjustment for repeater logic + - Timer should no longer increase on some repeaters + - Repeaters should no longer have periods when they're missing from the list - Fixed several commands which used error color for success confirmation messages ## [3.0.3] - 15.09.2021 @@ -1380,7 +1502,7 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf - Added `.youtubeuploadnotif` / `.yun` as a shortcut for subscribing to a youtube channel's rss feed - Added `.imageonlychannel` / `.imageonly` to prevent users from posting anything but images in the channel - Added `.config games hangman.currency_reward` and a property with the same name in games.yml - - If set, users will gain the specified amount of currency for each hangman win + - If set, users will gain the specified amount of currency for each hangman win - Fully translated to Spanish, Russian and Ukrainian 🎉 ### Changed @@ -1397,7 +1519,8 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf - `.rero` now optionally takes a message id to which to attach the reaction roles - Fully translated to German 🎉 -- Added `.boost`, `.boostmsg` and `.boostdel` commands which allow you to have customizable messages when someone boosts your server, with auto-deletion support +- Added `.boost`, `.boostmsg` and `.boostdel` commands which allow you to have customizable messages when someone boosts + your server, with auto-deletion support ### Changed @@ -1426,19 +1549,21 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf ### Changed - Renamed `credentials.json` to `creds.yml` (example in `creds_example.yml`) - - Most of the credentials from 2.x will be automatically migrated - - Explanations on how to get the keys are added as the comments + - Most of the credentials from 2.x will be automatically migrated + - Explanations on how to get the keys are added as the comments - Code cleanup - - Command attributes cleaned up - - Removed dummy Remarks and Usages attributes as hey were unused for a few patches but stayed in the code to avoid big git diffsmigration code has ran and it can be safely removed - - There are 2 projects: NadekoBot and NadekoBot.Coordinator - - You can directly run NadekoBot as the regular bot with one shard - - Run NadekoBot.Coordinator if you want more control over your shards and a grpc api for coordinator with which you can start, restart, kill and see status of shards - - Small performance improvements - - Db Migrations squashed - - A lot of cleanup all around + - Command attributes cleaned up + - Removed dummy Remarks and Usages attributes as hey were unused for a few patches but stayed in the code to + avoid big git diffsmigration code has ran and it can be safely removed + - There are 2 projects: NadekoBot and NadekoBot.Coordinator + - You can directly run NadekoBot as the regular bot with one shard + - Run NadekoBot.Coordinator if you want more control over your shards and a grpc api for coordinator with which + you can start, restart, kill and see status of shards + - Small performance improvements + - Db Migrations squashed + - A lot of cleanup all around - Many guides reworked - - Guides now instruct users to set build output to nadekobot/output instead of running from nadekobot/src/NadekoBot + - Guides now instruct users to set build output to nadekobot/output instead of running from nadekobot/src/NadekoBot ### Fixed @@ -1447,7 +1572,8 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf ### Removed - Removed All database migrations and data (json file) migrations - - As updating to the latest 2.x version before switching over to v3 is mandated (or fresh v3 install), that means all + - As updating to the latest 2.x version before switching over to v3 is mandated (or fresh v3 install), that means + all ## [2.46.2] - 14.07.2021 @@ -1473,13 +1599,15 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf ### Changed - `.aar` reworked. Now supports multiple roles, up to 3. - - Toggle roles that are added to newly joined users with `.aar RoleName` - - Use `.aar` to list roles which will be added - - Roles which are deleted are automatically cleaned up from `.aar` + - Toggle roles that are added to newly joined users with `.aar RoleName` + - Use `.aar` to list roles which will be added + - Roles which are deleted are automatically cleaned up from `.aar` - `.inrole` now also shows user ids -- Blacklist commands (owner only) `.ubl` `.sbl` and `.cbl` will now list blacklisted items when no argument (or a page number) is provided +- Blacklist commands (owner only) `.ubl` `.sbl` and `.cbl` will now list blacklisted items when no argument (or a page + number) is provided - `.cmdcd` now works with customreactions too -- `.xprr` usage changed. It now takes add/rm parameter to add/remove a role ex. You can only take or remove a single role, adding and removing a role at the same level doesn't work (yet?) +- `.xprr` usage changed. It now takes add/rm parameter to add/remove a role ex. You can only take or remove a single + role, adding and removing a role at the same level doesn't work (yet?) - example: `.xprr 5 add Member` or `.xprr 1 rm Newbie` ## [2.45.2] - 14.06.2021 @@ -1500,16 +1628,19 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf ### Added -- Added many new aliases to custom reaction commands in the format ex + "action" to prepare for the future rename from CustomReactions to Expressions +- Added many new aliases to custom reaction commands in the format ex + "action" to prepare for the future rename from + CustomReactions to Expressions - You can now `.divorce` via username#discrim even if the user no longer exists ### Changed - DmHelpText should now have %prefix% and %bot.prefix% placeholders available - Added squares which show enabled features for each cr in `.lcr` -- Changed CustomReactions' IDs to show, and accept base 32 unambigous characters instead of the normal database IDs (this will result in much shorter cr IDs in case you have a lot of them) +- Changed CustomReactions' IDs to show, and accept base 32 unambigous characters instead of the normal database IDs ( + this will result in much shorter cr IDs in case you have a lot of them) - Improved `.lcr` helptext to explain what's shown in the output -- `.rolecolor ` changed to take color, then the role, to make it easier to set color for roles with multiple words without mentioning the role +- `.rolecolor ` changed to take color, then the role, to make it easier to set color for roles with + multiple words without mentioning the role - `.acmdcds` alias chanaged to `.cmdcds` - `.8ball` will now cache results for a day - `.chatmute` and `.voicemute` now support timed mutes @@ -1523,13 +1654,16 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf ### Added - Added `.crsexport` and `.crsimport` - - Allows for quick export/import of server or global custom reactions - - Requires admin permissions for server crs, and owner for global crs - - Explanation of the fields is in the comment at the top of the `.crsexport` .yml file -- Added `.mquality` / `.musicquality` - Set encoding quality. Has 4 presets - Low, Medium, High, Highest. Default is Highest + - Allows for quick export/import of server or global custom reactions + - Requires admin permissions for server crs, and owner for global crs + - Explanation of the fields is in the comment at the top of the `.crsexport` .yml file +- Added `.mquality` / `.musicquality` - Set encoding quality. Has 4 presets - Low, Medium, High, Highest. Default is + Highest - Added `.xprewsreset` which resets all currently set xp level up rewards -- Added `.purgeuser @User` which will remove the specified from the database completely. Removed settings include: Xp, clubs, waifu, currency, etc... -- Added `.config xp txt.per_image` and xpFromImage to xp.yml - Change this config to allow xp gain from posting images. Images must be 128x128 or greater in size +- Added `.purgeuser @User` which will remove the specified from the database completely. Removed settings include: Xp, + clubs, waifu, currency, etc... +- Added `.config xp txt.per_image` and xpFromImage to xp.yml - Change this config to allow xp gain from posting images. + Images must be 128x128 or greater in size - Added `.take ` to complement `.award role` - Added **Fans** list to `.waifuinfo` which shows how many people have their affinity set to you - Added `.antialt` which will punish any user whose account is younger than specified threshold @@ -1543,7 +1677,8 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf - Re-created GuildRepeaters table and renamed to Repeaters - confirmation prompts will now use pending color from bot config, instead of okcolor - `.mute` can now have up to 49 days mute to match .warnp -- `.warnlog` now has proper pagination (with reactions) and checking your own warnings past page 1 works correctly now with `.warnlog 2` +- `.warnlog` now has proper pagination (with reactions) and checking your own warnings past page 1 works correctly now + with `.warnlog 2` ### Fixed @@ -1556,7 +1691,7 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf - Re-added `%music.playing%` and `%music.queued%` (#290) - Added `%music.servers%` which shows how many servers have a song queued up to play -ℹ️ ^ Only available to `.ropl` / `.adpl` feature atm + ℹ️ ^ Only available to `.ropl` / `.adpl` feature atm - `.autodc` re-added - `.qrp`, `.vol`, `.smch` `.autodc` will now persist @@ -1607,7 +1742,8 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf - Higher quality audio (no stuttering too!) - Local tracks will now have durations if you have ffprobe installed (comes with ffmpeg) - Bot supports joining a different vc without skipping the song if you use `.j` - - ⚠️ **DO NOT DRAG THE BOT** to another vc, as it's not properly supported atm, and you will have to do `.play` after dragging it) + - ⚠️ **DO NOT DRAG THE BOT** to another vc, as it's not properly supported atm, and you will have to do `.play` + after dragging it) - `.j` makes the bot join your voice channel - `.p` is now alias of play, pause is `.pause` - `.qs` should work without google api key now for most users as it is using a custom loader @@ -1630,4 +1766,5 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf ### Removed - Removed admin requirement on `.scrm` as it didn't make sense -- Some Music commands are removed because of the complexity they bring in with little value (if you *really* want them back, you can open an issue and specify your *good* reason) +- Some Music commands are removed because of the complexity they bring in with little value (if you *really* want them + back, you can open an issue and specify your *good* reason) diff --git a/src/NadekoBot/Db/Extensions/DiscordUserExtensions.cs b/src/NadekoBot/Db/Extensions/DiscordUserExtensions.cs index b7dbbdd4b..a18894a69 100644 --- a/src/NadekoBot/Db/Extensions/DiscordUserExtensions.cs +++ b/src/NadekoBot/Db/Extensions/DiscordUserExtensions.cs @@ -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 diff --git a/src/NadekoBot/Db/Models/DiscordUser.cs b/src/NadekoBot/Db/Models/DiscordUser.cs index 13230aee0..f9a168b68 100644 --- a/src/NadekoBot/Db/Models/DiscordUser.cs +++ b/src/NadekoBot/Db/Models/DiscordUser.cs @@ -7,7 +7,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; } @@ -27,9 +27,6 @@ public class DiscordUser : DbEntity public override string ToString() { - if (string.IsNullOrWhiteSpace(Discriminator) || Discriminator == "0000") - return Username; - - return Username + "#" + Discriminator; + return Username; } } \ No newline at end of file diff --git a/src/NadekoBot/Db/Models/FlagTranslateChannel.cs b/src/NadekoBot/Db/Models/FlagTranslateChannel.cs new file mode 100644 index 000000000..e34229776 --- /dev/null +++ b/src/NadekoBot/Db/Models/FlagTranslateChannel.cs @@ -0,0 +1,8 @@ +#nullable disable +namespace NadekoBot.Db.Models; + +public class FlagTranslateChannel : DbEntity +{ + public ulong GuildId { get; set; } + public ulong ChannelId { get; set; } +} \ No newline at end of file diff --git a/src/NadekoBot/Db/NadekoContext.cs b/src/NadekoBot/Db/NadekoContext.cs index e3ef94fb1..19dcb649c 100644 --- a/src/NadekoBot/Db/NadekoContext.cs +++ b/src/NadekoBot/Db/NadekoContext.cs @@ -73,6 +73,14 @@ public abstract class NadekoContext : DbContext protected override void OnModelCreating(ModelBuilder modelBuilder) { + #region Flag Translate + + modelBuilder.Entity() + .HasIndex(x => new { x.GuildId, x.ChannelId }) + .IsUnique(); + + #endregion + #region NCanvas modelBuilder.Entity() diff --git a/src/NadekoBot/Migrations/MigrationQueries.cs b/src/NadekoBot/Migrations/MigrationQueries.cs index b14ac1e5a..4052f70a5 100644 --- a/src/NadekoBot/Migrations/MigrationQueries.cs +++ b/src/NadekoBot/Migrations/MigrationQueries.cs @@ -5,6 +5,11 @@ namespace NadekoBot.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()) diff --git a/src/NadekoBot/Migrations/PostgreSql/20241102022956_no-discrim-and-flag-translate.Designer.cs b/src/NadekoBot/Migrations/PostgreSql/20241102022956_no-discrim-and-flag-translate.Designer.cs new file mode 100644 index 000000000..fc96d911a --- /dev/null +++ b/src/NadekoBot/Migrations/PostgreSql/20241102022956_no-discrim-and-flag-translate.Designer.cs @@ -0,0 +1,3851 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NadekoBot.Db; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace NadekoBot.Migrations.PostgreSql +{ + [DbContext(typeof(PostgreSqlContext))] + [Migration("20241102022956_no-discrim-and-flag-translate")] + partial class nodiscrimandflagtranslate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("NadekoBot.Db.Models.AntiAltSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer") + .HasColumnName("action"); + + b.Property("ActionDurationMinutes") + .HasColumnType("integer") + .HasColumnName("actiondurationminutes"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("MinAge") + .HasColumnType("interval") + .HasColumnName("minage"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_antialtsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antialtsetting_guildconfigid"); + + b.ToTable("antialtsetting", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AntiRaidSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer") + .HasColumnName("action"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("PunishDuration") + .HasColumnType("integer") + .HasColumnName("punishduration"); + + b.Property("Seconds") + .HasColumnType("integer") + .HasColumnName("seconds"); + + b.Property("UserThreshold") + .HasColumnType("integer") + .HasColumnName("userthreshold"); + + b.HasKey("Id") + .HasName("pk_antiraidsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antiraidsetting_guildconfigid"); + + b.ToTable("antiraidsetting", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AntiSpamIgnore", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AntiSpamSettingId") + .HasColumnType("integer") + .HasColumnName("antispamsettingid"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.HasKey("Id") + .HasName("pk_antispamignore"); + + b.HasIndex("AntiSpamSettingId") + .HasDatabaseName("ix_antispamignore_antispamsettingid"); + + b.ToTable("antispamignore", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AntiSpamSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer") + .HasColumnName("action"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("MessageThreshold") + .HasColumnType("integer") + .HasColumnName("messagethreshold"); + + b.Property("MuteTime") + .HasColumnType("integer") + .HasColumnName("mutetime"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_antispamsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antispamsetting_guildconfigid"); + + b.ToTable("antispamsetting", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ArchivedTodoListModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_todosarchive"); + + b.ToTable("todosarchive", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AutoCommand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("ChannelName") + .HasColumnType("text") + .HasColumnName("channelname"); + + b.Property("CommandText") + .HasColumnType("text") + .HasColumnName("commandtext"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("GuildName") + .HasColumnType("text") + .HasColumnName("guildname"); + + b.Property("Interval") + .HasColumnType("integer") + .HasColumnName("interval"); + + b.Property("VoiceChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("voicechannelid"); + + b.Property("VoiceChannelName") + .HasColumnType("text") + .HasColumnName("voicechannelname"); + + b.HasKey("Id") + .HasName("pk_autocommands"); + + b.ToTable("autocommands", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AutoPublishChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.HasKey("Id") + .HasName("pk_autopublishchannel"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_autopublishchannel_guildid"); + + b.ToTable("autopublishchannel", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AutoTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoDelete") + .HasColumnType("boolean") + .HasColumnName("autodelete"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.HasKey("Id") + .HasName("pk_autotranslatechannels"); + + b.HasIndex("ChannelId") + .IsUnique() + .HasDatabaseName("ix_autotranslatechannels_channelid"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_autotranslatechannels_guildid"); + + b.ToTable("autotranslatechannels", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AutoTranslateUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("integer") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Source") + .HasColumnType("text") + .HasColumnName("source"); + + b.Property("Target") + .HasColumnType("text") + .HasColumnName("target"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_autotranslateusers"); + + b.HasAlternateKey("ChannelId", "UserId") + .HasName("ak_autotranslateusers_channelid_userid"); + + b.ToTable("autotranslateusers", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("PruneDays") + .HasColumnType("integer") + .HasColumnName("prunedays"); + + b.Property("Text") + .HasColumnType("text") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_bantemplates"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_bantemplates_guildid"); + + b.ToTable("bantemplates", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.BankUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Balance") + .HasColumnType("bigint") + .HasColumnName("balance"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_bankusers"); + + b.HasIndex("UserId") + .IsUnique() + .HasDatabaseName("ix_bankusers_userid"); + + b.ToTable("bankusers", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.BlacklistEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("ItemId") + .HasColumnType("numeric(20,0)") + .HasColumnName("itemid"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b => + { + b.Property("ClubId") + .HasColumnType("integer") + .HasColumnName("clubid"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("userid"); + + b.HasKey("ClubId", "UserId") + .HasName("pk_clubapplicants"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_clubapplicants_userid"); + + b.ToTable("clubapplicants", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b => + { + b.Property("ClubId") + .HasColumnType("integer") + .HasColumnName("clubid"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("userid"); + + b.HasKey("ClubId", "UserId") + .HasName("pk_clubbans"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_clubbans_userid"); + + b.ToTable("clubbans", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("ImageUrl") + .HasColumnType("text") + .HasColumnName("imageurl"); + + b.Property("Name") + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasColumnName("name"); + + b.Property("OwnerId") + .HasColumnType("integer") + .HasColumnName("ownerid"); + + b.Property("Xp") + .HasColumnType("integer") + .HasColumnName("xp"); + + b.HasKey("Id") + .HasName("pk_clubs"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("ix_clubs_name"); + + b.HasIndex("OwnerId") + .IsUnique() + .HasDatabaseName("ix_clubs_ownerid"); + + b.ToTable("clubs", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.CommandAlias", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Mapping") + .HasColumnType("text") + .HasColumnName("mapping"); + + b.Property("Trigger") + .HasColumnType("text") + .HasColumnName("trigger"); + + b.HasKey("Id") + .HasName("pk_commandalias"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_commandalias_guildconfigid"); + + b.ToTable("commandalias", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.CommandCooldown", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CommandName") + .HasColumnType("text") + .HasColumnName("commandname"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Seconds") + .HasColumnType("integer") + .HasColumnName("seconds"); + + b.HasKey("Id") + .HasName("pk_commandcooldown"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_commandcooldown_guildconfigid"); + + b.ToTable("commandcooldown", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.CurrencyTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Amount") + .HasColumnType("bigint") + .HasColumnName("amount"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Extra") + .IsRequired() + .HasColumnType("text") + .HasColumnName("extra"); + + b.Property("Note") + .HasColumnType("text") + .HasColumnName("note"); + + b.Property("OtherId") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)") + .HasColumnName("otherid") + .HasDefaultValueSql("NULL"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text") + .HasColumnName("type"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_currencytransactions"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_currencytransactions_userid"); + + b.ToTable("currencytransactions", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DelMsgOnCmdChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("State") + .HasColumnType("boolean") + .HasColumnName("state"); + + b.HasKey("Id") + .HasName("pk_delmsgoncmdchannel"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_delmsgoncmdchannel_guildconfigid"); + + b.ToTable("delmsgoncmdchannel", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DiscordPermOverride", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Command") + .HasColumnType("text") + .HasColumnName("command"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Perm") + .HasColumnType("numeric(20,0)") + .HasColumnName("perm"); + + b.HasKey("Id") + .HasName("pk_discordpermoverrides"); + + b.HasIndex("GuildId", "Command") + .IsUnique() + .HasDatabaseName("ix_discordpermoverrides_guildid_command"); + + b.ToTable("discordpermoverrides", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AvatarId") + .HasColumnType("text") + .HasColumnName("avatarid"); + + b.Property("ClubId") + .HasColumnType("integer") + .HasColumnName("clubid"); + + b.Property("CurrencyAmount") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(0L) + .HasColumnName("currencyamount"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("IsClubAdmin") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("isclubadmin"); + + b.Property("NotifyOnLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("notifyonlevelup"); + + b.Property("TotalXp") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(0L) + .HasColumnName("totalxp"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("text") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_discorduser"); + + b.HasAlternateKey("UserId") + .HasName("ak_discorduser_userid"); + + b.HasIndex("ClubId") + .HasDatabaseName("ix_discorduser_clubid"); + + b.HasIndex("CurrencyAmount") + .HasDatabaseName("ix_discorduser_currencyamount"); + + b.HasIndex("TotalXp") + .HasDatabaseName("ix_discorduser_totalxp"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_discorduser_userid"); + + b.HasIndex("Username") + .HasDatabaseName("ix_discorduser_username"); + + b.ToTable("discorduser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ExcludedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("ItemId") + .HasColumnType("numeric(20,0)") + .HasColumnName("itemid"); + + b.Property("ItemType") + .HasColumnType("integer") + .HasColumnName("itemtype"); + + b.Property("XpSettingsId") + .HasColumnType("integer") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_excludeditem"); + + b.HasIndex("XpSettingsId") + .HasDatabaseName("ix_excludeditem_xpsettingsid"); + + b.ToTable("excludeditem", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FeedSub", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("Url") + .IsRequired() + .HasColumnType("text") + .HasColumnName("url"); + + b.HasKey("Id") + .HasName("pk_feedsub"); + + b.HasAlternateKey("GuildConfigId", "Url") + .HasName("ak_feedsub_guildconfigid_url"); + + b.ToTable("feedsub", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FilterChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterchannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterchannelid_guildconfigid"); + + b.ToTable("filterchannelid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FilterLinksChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterlinkschannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterlinkschannelid_guildconfigid"); + + b.ToTable("filterlinkschannelid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FilterWordsChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterwordschannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterwordschannelid_guildconfigid"); + + b.ToTable("filterwordschannelid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FilteredWord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Word") + .HasColumnType("text") + .HasColumnName("word"); + + b.HasKey("Id") + .HasName("pk_filteredword"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filteredword_guildconfigid"); + + b.ToTable("filteredword", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FlagTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.HasKey("Id") + .HasName("pk_flagtranslatechannel"); + + b.HasIndex("GuildId", "ChannelId") + .IsUnique() + .HasDatabaseName("ix_flagtranslatechannel_guildid_channelid"); + + b.ToTable("flagtranslatechannel", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("Username") + .HasColumnType("text") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_followedstream"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_followedstream_guildconfigid"); + + b.ToTable("followedstream", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GCChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_gcchannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_gcchannelid_guildconfigid"); + + b.ToTable("gcchannelid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GamblingStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Bet") + .HasColumnType("numeric") + .HasColumnName("bet"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Feature") + .HasColumnType("text") + .HasColumnName("feature"); + + b.Property("PaidOut") + .HasColumnType("numeric") + .HasColumnName("paidout"); + + b.HasKey("Id") + .HasName("pk_gamblingstats"); + + b.HasIndex("Feature") + .IsUnique() + .HasDatabaseName("ix_gamblingstats_feature"); + + b.ToTable("gamblingstats", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GiveawayModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("EndsAt") + .HasColumnType("timestamp without time zone") + .HasColumnName("endsat"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageid"); + + b.HasKey("Id") + .HasName("pk_giveawaymodel"); + + b.ToTable("giveawaymodel", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GiveawayUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("GiveawayId") + .HasColumnType("integer") + .HasColumnName("giveawayid"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_giveawayuser"); + + b.HasIndex("GiveawayId", "UserId") + .IsUnique() + .HasDatabaseName("ix_giveawayuser_giveawayid_userid"); + + b.ToTable("giveawayuser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GroupName", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Number") + .HasColumnType("integer") + .HasColumnName("number"); + + b.HasKey("Id") + .HasName("pk_groupname"); + + b.HasIndex("GuildConfigId", "Number") + .IsUnique() + .HasDatabaseName("ix_groupname_guildconfigid_number"); + + b.ToTable("groupname", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GuildConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoAssignRoleIds") + .HasColumnType("text") + .HasColumnName("autoassignroleids"); + + b.Property("AutoDeleteSelfAssignedRoleMessages") + .HasColumnType("boolean") + .HasColumnName("autodeleteselfassignedrolemessages"); + + b.Property("CleverbotEnabled") + .HasColumnType("boolean") + .HasColumnName("cleverbotenabled"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("DeleteMessageOnCommand") + .HasColumnType("boolean") + .HasColumnName("deletemessageoncommand"); + + b.Property("DeleteStreamOnlineMessage") + .HasColumnType("boolean") + .HasColumnName("deletestreamonlinemessage"); + + b.Property("DisableGlobalExpressions") + .HasColumnType("boolean") + .HasColumnName("disableglobalexpressions"); + + b.Property("ExclusiveSelfAssignedRoles") + .HasColumnType("boolean") + .HasColumnName("exclusiveselfassignedroles"); + + b.Property("FilterInvites") + .HasColumnType("boolean") + .HasColumnName("filterinvites"); + + b.Property("FilterLinks") + .HasColumnType("boolean") + .HasColumnName("filterlinks"); + + b.Property("FilterWords") + .HasColumnType("boolean") + .HasColumnName("filterwords"); + + b.Property("GameVoiceChannel") + .HasColumnType("numeric(20,0)") + .HasColumnName("gamevoicechannel"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Locale") + .HasColumnType("text") + .HasColumnName("locale"); + + b.Property("MuteRoleName") + .HasColumnType("text") + .HasColumnName("muterolename"); + + b.Property("NotifyStreamOffline") + .HasColumnType("boolean") + .HasColumnName("notifystreamoffline"); + + b.Property("PermissionRole") + .HasColumnType("text") + .HasColumnName("permissionrole"); + + b.Property("Prefix") + .HasColumnType("text") + .HasColumnName("prefix"); + + b.Property("StickyRoles") + .HasColumnType("boolean") + .HasColumnName("stickyroles"); + + b.Property("TimeZoneId") + .HasColumnType("text") + .HasColumnName("timezoneid"); + + b.Property("VerboseErrors") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("verboseerrors"); + + b.Property("VerbosePermissions") + .HasColumnType("boolean") + .HasColumnName("verbosepermissions"); + + b.Property("WarnExpireAction") + .HasColumnType("integer") + .HasColumnName("warnexpireaction"); + + b.Property("WarnExpireHours") + .HasColumnType("integer") + .HasColumnName("warnexpirehours"); + + b.Property("WarningsInitialized") + .HasColumnType("boolean") + .HasColumnName("warningsinitialized"); + + b.HasKey("Id") + .HasName("pk_guildconfigs"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_guildconfigs_guildid"); + + b.HasIndex("WarnExpireHours") + .HasDatabaseName("ix_guildconfigs_warnexpirehours"); + + b.ToTable("guildconfigs", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.HoneypotChannel", b => + { + b.Property("GuildId") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.HasKey("GuildId") + .HasName("pk_honeypotchannels"); + + b.ToTable("honeypotchannels", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.IgnoredLogItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("ItemType") + .HasColumnType("integer") + .HasColumnName("itemtype"); + + b.Property("LogItemId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logitemid"); + + b.Property("LogSettingId") + .HasColumnType("integer") + .HasColumnName("logsettingid"); + + b.HasKey("Id") + .HasName("pk_ignoredlogchannels"); + + b.HasIndex("LogSettingId", "LogItemId", "ItemType") + .IsUnique() + .HasDatabaseName("ix_ignoredlogchannels_logsettingid_logitemid_itemtype"); + + b.ToTable("ignoredlogchannels", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ImageOnlyChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_imageonlychannels"); + + b.HasIndex("ChannelId") + .IsUnique() + .HasDatabaseName("ix_imageonlychannels_channelid"); + + b.ToTable("imageonlychannels", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.LogSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelCreatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelcreatedid"); + + b.Property("ChannelDestroyedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channeldestroyedid"); + + b.Property("ChannelUpdatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelupdatedid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("LogOtherId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logotherid"); + + b.Property("LogUserPresenceId") + .HasColumnType("numeric(20,0)") + .HasColumnName("loguserpresenceid"); + + b.Property("LogVoicePresenceId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logvoicepresenceid"); + + b.Property("LogVoicePresenceTTSId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logvoicepresencettsid"); + + b.Property("LogWarnsId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logwarnsid"); + + b.Property("MessageDeletedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messagedeletedid"); + + b.Property("MessageUpdatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageupdatedid"); + + b.Property("ThreadCreatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("threadcreatedid"); + + b.Property("ThreadDeletedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("threaddeletedid"); + + b.Property("UserBannedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userbannedid"); + + b.Property("UserJoinedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userjoinedid"); + + b.Property("UserLeftId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userleftid"); + + b.Property("UserMutedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("usermutedid"); + + b.Property("UserUnbannedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userunbannedid"); + + b.Property("UserUpdatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userupdatedid"); + + b.HasKey("Id") + .HasName("pk_logsettings"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_logsettings_guildid"); + + b.ToTable("logsettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.MusicPlayerSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoDisconnect") + .HasColumnType("boolean") + .HasColumnName("autodisconnect"); + + b.Property("AutoPlay") + .HasColumnType("boolean") + .HasColumnName("autoplay"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("MusicChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("musicchannelid"); + + b.Property("PlayerRepeat") + .HasColumnType("integer") + .HasColumnName("playerrepeat"); + + b.Property("QualityPreset") + .HasColumnType("integer") + .HasColumnName("qualitypreset"); + + b.Property("Volume") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(100) + .HasColumnName("volume"); + + b.HasKey("Id") + .HasName("pk_musicplayersettings"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_musicplayersettings_guildid"); + + b.ToTable("musicplayersettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.MusicPlaylist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Author") + .HasColumnType("text") + .HasColumnName("author"); + + b.Property("AuthorId") + .HasColumnType("numeric(20,0)") + .HasColumnName("authorid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("pk_musicplaylists"); + + b.ToTable("musicplaylists", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.MutedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_muteduserid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_muteduserid_guildconfigid"); + + b.ToTable("muteduserid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.NCPixel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Color") + .HasColumnType("bigint") + .HasColumnName("color"); + + b.Property("OwnerId") + .HasColumnType("numeric(20,0)") + .HasColumnName("ownerid"); + + b.Property("Position") + .HasColumnType("integer") + .HasColumnName("position"); + + b.Property("Price") + .HasColumnType("bigint") + .HasColumnName("price"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_ncpixel"); + + b.HasAlternateKey("Position") + .HasName("ak_ncpixel_position"); + + b.HasIndex("OwnerId") + .HasDatabaseName("ix_ncpixel_ownerid"); + + b.ToTable("ncpixel", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.NadekoExpression", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AllowTarget") + .HasColumnType("boolean") + .HasColumnName("allowtarget"); + + b.Property("AutoDeleteTrigger") + .HasColumnType("boolean") + .HasColumnName("autodeletetrigger"); + + b.Property("ContainsAnywhere") + .HasColumnType("boolean") + .HasColumnName("containsanywhere"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("DmResponse") + .HasColumnType("boolean") + .HasColumnName("dmresponse"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Reactions") + .HasColumnType("text") + .HasColumnName("reactions"); + + b.Property("Response") + .HasColumnType("text") + .HasColumnName("response"); + + b.Property("Trigger") + .HasColumnType("text") + .HasColumnName("trigger"); + + b.HasKey("Id") + .HasName("pk_expressions"); + + b.ToTable("expressions", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.PatronUser", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("AmountCents") + .HasColumnType("integer") + .HasColumnName("amountcents"); + + b.Property("LastCharge") + .HasColumnType("timestamp without time zone") + .HasColumnName("lastcharge"); + + b.Property("UniquePlatformUserId") + .HasColumnType("text") + .HasColumnName("uniqueplatformuserid"); + + b.Property("ValidThru") + .HasColumnType("timestamp without time zone") + .HasColumnName("validthru"); + + b.HasKey("UserId") + .HasName("pk_patrons"); + + b.HasIndex("UniquePlatformUserId") + .IsUnique() + .HasDatabaseName("ix_patrons_uniqueplatformuserid"); + + b.ToTable("patrons", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.Permissionv2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Index") + .HasColumnType("integer") + .HasColumnName("index"); + + b.Property("IsCustomCommand") + .HasColumnType("boolean") + .HasColumnName("iscustomcommand"); + + b.Property("PrimaryTarget") + .HasColumnType("integer") + .HasColumnName("primarytarget"); + + b.Property("PrimaryTargetId") + .HasColumnType("numeric(20,0)") + .HasColumnName("primarytargetid"); + + b.Property("SecondaryTarget") + .HasColumnType("integer") + .HasColumnName("secondarytarget"); + + b.Property("SecondaryTargetName") + .HasColumnType("text") + .HasColumnName("secondarytargetname"); + + b.Property("State") + .HasColumnType("boolean") + .HasColumnName("state"); + + b.HasKey("Id") + .HasName("pk_permissions"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_permissions_guildconfigid"); + + b.ToTable("permissions", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.PlantedCurrency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Amount") + .HasColumnType("bigint") + .HasColumnName("amount"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageid"); + + b.Property("Password") + .HasColumnType("text") + .HasColumnName("password"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_plantedcurrency"); + + b.HasIndex("ChannelId") + .HasDatabaseName("ix_plantedcurrency_channelid"); + + b.HasIndex("MessageId") + .IsUnique() + .HasDatabaseName("ix_plantedcurrency_messageid"); + + b.ToTable("plantedcurrency", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.PlaylistSong", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("MusicPlaylistId") + .HasColumnType("integer") + .HasColumnName("musicplaylistid"); + + b.Property("Provider") + .HasColumnType("text") + .HasColumnName("provider"); + + b.Property("ProviderType") + .HasColumnType("integer") + .HasColumnName("providertype"); + + b.Property("Query") + .HasColumnType("text") + .HasColumnName("query"); + + b.Property("Title") + .HasColumnType("text") + .HasColumnName("title"); + + b.Property("Uri") + .HasColumnType("text") + .HasColumnName("uri"); + + b.HasKey("Id") + .HasName("pk_playlistsong"); + + b.HasIndex("MusicPlaylistId") + .HasDatabaseName("ix_playlistsong_musicplaylistid"); + + b.ToTable("playlistsong", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.Quote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .HasColumnType("numeric(20,0)") + .HasColumnName("authorid"); + + b.Property("AuthorName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("authorname"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Keyword") + .IsRequired() + .HasColumnType("text") + .HasColumnName("keyword"); + + b.Property("Text") + .IsRequired() + .HasColumnType("text") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_quotes"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_quotes_guildid"); + + b.HasIndex("Keyword") + .HasDatabaseName("ix_quotes_keyword"); + + b.ToTable("quotes", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ReactionRoleV2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Emote") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("emote"); + + b.Property("Group") + .HasColumnType("integer") + .HasColumnName("group"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("LevelReq") + .HasColumnType("integer") + .HasColumnName("levelreq"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_reactionroles"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_reactionroles_guildid"); + + b.HasIndex("MessageId", "Emote") + .IsUnique() + .HasDatabaseName("ix_reactionroles_messageid_emote"); + + b.ToTable("reactionroles", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("IsPrivate") + .HasColumnType("boolean") + .HasColumnName("isprivate"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("ServerId") + .HasColumnType("numeric(20,0)") + .HasColumnName("serverid"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("When") + .HasColumnType("timestamp without time zone") + .HasColumnName("when"); + + b.HasKey("Id") + .HasName("pk_reminders"); + + b.HasIndex("When") + .HasDatabaseName("ix_reminders_when"); + + b.ToTable("reminders", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.Repeater", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Interval") + .HasColumnType("interval") + .HasColumnName("interval"); + + b.Property("LastMessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("lastmessageid"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("NoRedundant") + .HasColumnType("boolean") + .HasColumnName("noredundant"); + + b.Property("StartTimeOfDay") + .HasColumnType("interval") + .HasColumnName("starttimeofday"); + + b.HasKey("Id") + .HasName("pk_repeaters"); + + b.ToTable("repeaters", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.RewardedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AmountRewardedThisMonth") + .HasColumnType("bigint") + .HasColumnName("amountrewardedthismonth"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("LastReward") + .HasColumnType("timestamp without time zone") + .HasColumnName("lastreward"); + + b.Property("PlatformUserId") + .HasColumnType("text") + .HasColumnName("platformuserid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_rewardedusers"); + + b.HasIndex("PlatformUserId") + .IsUnique() + .HasDatabaseName("ix_rewardedusers_platformuserid"); + + b.ToTable("rewardedusers", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.RotatingPlayingStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Status") + .HasColumnType("text") + .HasColumnName("status"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_rotatingstatus"); + + b.ToTable("rotatingstatus", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.SelfAssignedRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Group") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("group"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("LevelRequirement") + .HasColumnType("integer") + .HasColumnName("levelrequirement"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_selfassignableroles"); + + b.HasIndex("GuildId", "RoleId") + .IsUnique() + .HasDatabaseName("ix_selfassignableroles_guildid_roleid"); + + b.ToTable("selfassignableroles", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ShopEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .HasColumnType("numeric(20,0)") + .HasColumnName("authorid"); + + b.Property("Command") + .HasColumnType("text") + .HasColumnName("command"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Index") + .HasColumnType("integer") + .HasColumnName("index"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Price") + .HasColumnType("integer") + .HasColumnName("price"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("RoleName") + .HasColumnType("text") + .HasColumnName("rolename"); + + b.Property("RoleRequirement") + .HasColumnType("numeric(20,0)") + .HasColumnName("rolerequirement"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_shopentry"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_shopentry_guildconfigid"); + + b.ToTable("shopentry", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ShopEntryItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("ShopEntryId") + .HasColumnType("integer") + .HasColumnName("shopentryid"); + + b.Property("Text") + .HasColumnType("text") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_shopentryitem"); + + b.HasIndex("ShopEntryId") + .HasDatabaseName("ix_shopentryitem_shopentryid"); + + b.ToTable("shopentryitem", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.SlowmodeIgnoredRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_slowmodeignoredrole"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_slowmodeignoredrole_guildconfigid"); + + b.ToTable("slowmodeignoredrole", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.SlowmodeIgnoredUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_slowmodeignoreduser"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_slowmodeignoreduser_guildconfigid"); + + b.ToTable("slowmodeignoreduser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StickyRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("RoleIds") + .HasColumnType("text") + .HasColumnName("roleids"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_stickyroles"); + + b.HasIndex("GuildId", "UserId") + .IsUnique() + .HasDatabaseName("ix_stickyroles_guildid_userid"); + + b.ToTable("stickyroles", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamOnlineMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageid"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_streamonlinemessages"); + + b.ToTable("streamonlinemessages", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamRoleBlacklistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("integer") + .HasColumnName("streamrolesettingsid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("text") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_streamroleblacklisteduser"); + + b.HasIndex("StreamRoleSettingsId") + .HasDatabaseName("ix_streamroleblacklisteduser_streamrolesettingsid"); + + b.ToTable("streamroleblacklisteduser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamRoleSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AddRoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("addroleid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Enabled") + .HasColumnType("boolean") + .HasColumnName("enabled"); + + b.Property("FromRoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("fromroleid"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Keyword") + .HasColumnType("text") + .HasColumnName("keyword"); + + b.HasKey("Id") + .HasName("pk_streamrolesettings"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_streamrolesettings_guildconfigid"); + + b.ToTable("streamrolesettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamRoleWhitelistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("integer") + .HasColumnName("streamrolesettingsid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("text") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_streamrolewhitelisteduser"); + + b.HasIndex("StreamRoleSettingsId") + .HasDatabaseName("ix_streamrolewhitelisteduser_streamrolesettingsid"); + + b.ToTable("streamrolewhitelisteduser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.TodoModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ArchiveId") + .HasColumnType("integer") + .HasColumnName("archiveid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("IsDone") + .HasColumnType("boolean") + .HasColumnName("isdone"); + + b.Property("Todo") + .HasColumnType("text") + .HasColumnName("todo"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_todos"); + + b.HasIndex("ArchiveId") + .HasDatabaseName("ix_todos_archiveid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_todos_userid"); + + b.ToTable("todos", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.UnbanTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("UnbanAt") + .HasColumnType("timestamp without time zone") + .HasColumnName("unbanat"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unbantimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unbantimer_guildconfigid"); + + b.ToTable("unbantimer", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.UnmuteTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("UnmuteAt") + .HasColumnType("timestamp without time zone") + .HasColumnName("unmuteat"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unmutetimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unmutetimer_guildconfigid"); + + b.ToTable("unmutetimer", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.UnroleTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("UnbanAt") + .HasColumnType("timestamp without time zone") + .HasColumnName("unbanat"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unroletimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unroletimer_guildconfigid"); + + b.ToTable("unroletimer", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.UserXpStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AwardedXp") + .HasColumnType("bigint") + .HasColumnName("awardedxp"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("NotifyOnLevelUp") + .HasColumnType("integer") + .HasColumnName("notifyonlevelup"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Xp") + .HasColumnType("bigint") + .HasColumnName("xp"); + + b.HasKey("Id") + .HasName("pk_userxpstats"); + + b.HasIndex("AwardedXp") + .HasDatabaseName("ix_userxpstats_awardedxp"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_userxpstats_guildid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_userxpstats_userid"); + + b.HasIndex("Xp") + .HasDatabaseName("ix_userxpstats_xp"); + + b.HasIndex("UserId", "GuildId") + .IsUnique() + .HasDatabaseName("ix_userxpstats_userid_guildid"); + + b.ToTable("userxpstats", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.VcRoleInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("VoiceChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("voicechannelid"); + + b.HasKey("Id") + .HasName("pk_vcroleinfo"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_vcroleinfo_guildconfigid"); + + b.ToTable("vcroleinfo", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.WaifuInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AffinityId") + .HasColumnType("integer") + .HasColumnName("affinityid"); + + b.Property("ClaimerId") + .HasColumnType("integer") + .HasColumnName("claimerid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Price") + .HasColumnType("bigint") + .HasColumnName("price"); + + b.Property("WaifuId") + .HasColumnType("integer") + .HasColumnName("waifuid"); + + b.HasKey("Id") + .HasName("pk_waifuinfo"); + + b.HasIndex("AffinityId") + .HasDatabaseName("ix_waifuinfo_affinityid"); + + b.HasIndex("ClaimerId") + .HasDatabaseName("ix_waifuinfo_claimerid"); + + b.HasIndex("Price") + .HasDatabaseName("ix_waifuinfo_price"); + + b.HasIndex("WaifuId") + .IsUnique() + .HasDatabaseName("ix_waifuinfo_waifuid"); + + b.ToTable("waifuinfo", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.WaifuItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("ItemEmoji") + .HasColumnType("text") + .HasColumnName("itememoji"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("WaifuInfoId") + .HasColumnType("integer") + .HasColumnName("waifuinfoid"); + + b.HasKey("Id") + .HasName("pk_waifuitem"); + + b.HasIndex("WaifuInfoId") + .HasDatabaseName("ix_waifuitem_waifuinfoid"); + + b.ToTable("waifuitem", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.WaifuUpdate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("NewId") + .HasColumnType("integer") + .HasColumnName("newid"); + + b.Property("OldId") + .HasColumnType("integer") + .HasColumnName("oldid"); + + b.Property("UpdateType") + .HasColumnType("integer") + .HasColumnName("updatetype"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_waifuupdates"); + + b.HasIndex("NewId") + .HasDatabaseName("ix_waifuupdates_newid"); + + b.HasIndex("OldId") + .HasDatabaseName("ix_waifuupdates_oldid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_waifuupdates_userid"); + + b.ToTable("waifuupdates", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.Warning", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Forgiven") + .HasColumnType("boolean") + .HasColumnName("forgiven"); + + b.Property("ForgivenBy") + .HasColumnType("text") + .HasColumnName("forgivenby"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Moderator") + .HasColumnType("text") + .HasColumnName("moderator"); + + b.Property("Reason") + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Weight") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(1L) + .HasColumnName("weight"); + + b.HasKey("Id") + .HasName("pk_warnings"); + + b.HasIndex("DateAdded") + .HasDatabaseName("ix_warnings_dateadded"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_warnings_guildid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_warnings_userid"); + + b.ToTable("warnings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.WarningPunishment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Count") + .HasColumnType("integer") + .HasColumnName("count"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Punishment") + .HasColumnType("integer") + .HasColumnName("punishment"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("Time") + .HasColumnType("integer") + .HasColumnName("time"); + + b.HasKey("Id") + .HasName("pk_warningpunishment"); + + b.HasAlternateKey("GuildId", "Count") + .HasName("ak_warningpunishment_guildid_count"); + + b.ToTable("warningpunishment", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpCurrencyReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Amount") + .HasColumnType("integer") + .HasColumnName("amount"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Level") + .HasColumnType("integer") + .HasColumnName("level"); + + b.Property("XpSettingsId") + .HasColumnType("integer") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_xpcurrencyreward"); + + b.HasIndex("XpSettingsId") + .HasDatabaseName("ix_xpcurrencyreward_xpsettingsid"); + + b.ToTable("xpcurrencyreward", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpRoleReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Level") + .HasColumnType("integer") + .HasColumnName("level"); + + b.Property("Remove") + .HasColumnType("boolean") + .HasColumnName("remove"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("XpSettingsId") + .HasColumnType("integer") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_xprolereward"); + + b.HasIndex("XpSettingsId", "Level") + .IsUnique() + .HasDatabaseName("ix_xprolereward_xpsettingsid_level"); + + b.ToTable("xprolereward", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("ServerExcluded") + .HasColumnType("boolean") + .HasColumnName("serverexcluded"); + + b.HasKey("Id") + .HasName("pk_xpsettings"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_xpsettings_guildconfigid"); + + b.ToTable("xpsettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpShopOwnedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("IsUsing") + .HasColumnType("boolean") + .HasColumnName("isusing"); + + b.Property("ItemKey") + .IsRequired() + .HasColumnType("text") + .HasColumnName("itemkey"); + + b.Property("ItemType") + .HasColumnType("integer") + .HasColumnName("itemtype"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_xpshopowneditem"); + + b.HasIndex("UserId", "ItemType", "ItemKey") + .IsUnique() + .HasDatabaseName("ix_xpshopowneditem_userid_itemtype_itemkey"); + + b.ToTable("xpshopowneditem", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.GreetSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoDeleteTimer") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("autodeletetimer"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("GreetType") + .HasColumnType("integer") + .HasColumnName("greettype"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("IsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("isenabled"); + + b.Property("MessageText") + .HasColumnType("text") + .HasColumnName("messagetext"); + + b.HasKey("Id") + .HasName("pk_greetsettings"); + + b.HasIndex("GuildId", "GreetType") + .IsUnique() + .HasDatabaseName("ix_greetsettings_guildid_greettype"); + + b.ToTable("greetsettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AntiAltSetting", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithOne("AntiAltSetting") + .HasForeignKey("NadekoBot.Db.Models.AntiAltSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antialtsetting_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AntiRaidSetting", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithOne("AntiRaidSetting") + .HasForeignKey("NadekoBot.Db.Models.AntiRaidSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antiraidsetting_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AntiSpamIgnore", b => + { + b.HasOne("NadekoBot.Db.Models.AntiSpamSetting", null) + .WithMany("IgnoredChannels") + .HasForeignKey("AntiSpamSettingId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_antispamignore_antispamsetting_antispamsettingid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AntiSpamSetting", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithOne("AntiSpamSetting") + .HasForeignKey("NadekoBot.Db.Models.AntiSpamSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antispamsetting_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AutoTranslateUser", b => + { + b.HasOne("NadekoBot.Db.Models.AutoTranslateChannel", "Channel") + .WithMany("Users") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_autotranslateusers_autotranslatechannels_channelid"); + + b.Navigation("Channel"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Applicants") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubapplicants_clubs_clubid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubapplicants_discorduser_userid"); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Bans") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubbans_clubs_clubid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubbans_discorduser_userid"); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Owner") + .WithOne() + .HasForeignKey("NadekoBot.Db.Models.ClubInfo", "OwnerId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("fk_clubs_discorduser_ownerid"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.CommandAlias", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("CommandAliases") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_commandalias_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.CommandCooldown", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("CommandCooldowns") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_commandcooldown_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DelMsgOnCmdChannel", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("DelMsgOnCmdChannels") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_delmsgoncmdchannel_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Members") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.NoAction) + .HasConstraintName("fk_discorduser_clubs_clubid"); + + b.Navigation("Club"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ExcludedItem", b => + { + b.HasOne("NadekoBot.Db.Models.XpSettings", "XpSettings") + .WithMany("ExclusionList") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_excludeditem_xpsettings_xpsettingsid"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FeedSub", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", "GuildConfig") + .WithMany("FeedSubs") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_feedsub_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FilterChannelId", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("FilterInvitesChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_filterchannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FilterLinksChannelId", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("FilterLinksChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_filterlinkschannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FilterWordsChannelId", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("FilterWordsChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_filterwordschannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FilteredWord", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("FilteredWords") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_filteredword_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("FollowedStreams") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_followedstream_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GCChannelId", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", "GuildConfig") + .WithMany("GenerateCurrencyChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_gcchannelid_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GiveawayUser", b => + { + b.HasOne("NadekoBot.Db.Models.GiveawayModel", null) + .WithMany("Participants") + .HasForeignKey("GiveawayId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_giveawayuser_giveawaymodel_giveawayid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GroupName", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", "GuildConfig") + .WithMany("SelfAssignableRoleGroupNames") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_groupname_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.IgnoredLogItem", b => + { + b.HasOne("NadekoBot.Db.Models.LogSetting", "LogSetting") + .WithMany("LogIgnores") + .HasForeignKey("LogSettingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_ignoredlogchannels_logsettings_logsettingid"); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.MutedUserId", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("MutedUsers") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_muteduserid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.Permissionv2", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("Permissions") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_permissions_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.PlaylistSong", b => + { + b.HasOne("NadekoBot.Db.Models.MusicPlaylist", null) + .WithMany("Songs") + .HasForeignKey("MusicPlaylistId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_playlistsong_musicplaylists_musicplaylistid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ShopEntry", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("ShopEntries") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_shopentry_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ShopEntryItem", b => + { + b.HasOne("NadekoBot.Db.Models.ShopEntry", null) + .WithMany("Items") + .HasForeignKey("ShopEntryId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_shopentryitem_shopentry_shopentryid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.SlowmodeIgnoredRole", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredRoles") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_slowmodeignoredrole_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.SlowmodeIgnoredUser", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredUsers") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_slowmodeignoreduser_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamRoleBlacklistedUser", b => + { + b.HasOne("NadekoBot.Db.Models.StreamRoleSettings", "StreamRoleSettings") + .WithMany("Blacklist") + .HasForeignKey("StreamRoleSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_streamroleblacklisteduser_streamrolesettings_streamrolesett~"); + + b.Navigation("StreamRoleSettings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamRoleSettings", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", "GuildConfig") + .WithOne("StreamRole") + .HasForeignKey("NadekoBot.Db.Models.StreamRoleSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_streamrolesettings_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamRoleWhitelistedUser", b => + { + b.HasOne("NadekoBot.Db.Models.StreamRoleSettings", "StreamRoleSettings") + .WithMany("Whitelist") + .HasForeignKey("StreamRoleSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_streamrolewhitelisteduser_streamrolesettings_streamrolesett~"); + + b.Navigation("StreamRoleSettings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.TodoModel", b => + { + b.HasOne("NadekoBot.Db.Models.ArchivedTodoListModel", null) + .WithMany("Items") + .HasForeignKey("ArchiveId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_todos_todosarchive_archiveid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.UnbanTimer", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("UnbanTimer") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_unbantimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.UnmuteTimer", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("UnmuteTimers") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_unmutetimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.UnroleTimer", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("UnroleTimer") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_unroletimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.VcRoleInfo", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("VcRoleInfos") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_vcroleinfo_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.WaifuInfo", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Affinity") + .WithMany() + .HasForeignKey("AffinityId") + .HasConstraintName("fk_waifuinfo_discorduser_affinityid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Claimer") + .WithMany() + .HasForeignKey("ClaimerId") + .HasConstraintName("fk_waifuinfo_discorduser_claimerid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Waifu") + .WithOne() + .HasForeignKey("NadekoBot.Db.Models.WaifuInfo", "WaifuId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_waifuinfo_discorduser_waifuid"); + + b.Navigation("Affinity"); + + b.Navigation("Claimer"); + + b.Navigation("Waifu"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.WaifuItem", b => + { + b.HasOne("NadekoBot.Db.Models.WaifuInfo", "WaifuInfo") + .WithMany("Items") + .HasForeignKey("WaifuInfoId") + .HasConstraintName("fk_waifuitem_waifuinfo_waifuinfoid"); + + b.Navigation("WaifuInfo"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.WaifuUpdate", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "New") + .WithMany() + .HasForeignKey("NewId") + .HasConstraintName("fk_waifuupdates_discorduser_newid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Old") + .WithMany() + .HasForeignKey("OldId") + .HasConstraintName("fk_waifuupdates_discorduser_oldid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_waifuupdates_discorduser_userid"); + + b.Navigation("New"); + + b.Navigation("Old"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpCurrencyReward", b => + { + b.HasOne("NadekoBot.Db.Models.XpSettings", "XpSettings") + .WithMany("CurrencyRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xpcurrencyreward_xpsettings_xpsettingsid"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpRoleReward", b => + { + b.HasOne("NadekoBot.Db.Models.XpSettings", "XpSettings") + .WithMany("RoleRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xprolereward_xpsettings_xpsettingsid"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpSettings", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", "GuildConfig") + .WithOne("XpSettings") + .HasForeignKey("NadekoBot.Db.Models.XpSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xpsettings_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AntiSpamSetting", b => + { + b.Navigation("IgnoredChannels"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ArchivedTodoListModel", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AutoTranslateChannel", b => + { + b.Navigation("Users"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.Navigation("Applicants"); + + b.Navigation("Bans"); + + b.Navigation("Members"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GiveawayModel", b => + { + b.Navigation("Participants"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GuildConfig", b => + { + b.Navigation("AntiAltSetting"); + + b.Navigation("AntiRaidSetting"); + + b.Navigation("AntiSpamSetting"); + + b.Navigation("CommandAliases"); + + b.Navigation("CommandCooldowns"); + + b.Navigation("DelMsgOnCmdChannels"); + + b.Navigation("FeedSubs"); + + b.Navigation("FilterInvitesChannelIds"); + + b.Navigation("FilterLinksChannelIds"); + + b.Navigation("FilterWordsChannelIds"); + + b.Navigation("FilteredWords"); + + b.Navigation("FollowedStreams"); + + b.Navigation("GenerateCurrencyChannelIds"); + + b.Navigation("MutedUsers"); + + b.Navigation("Permissions"); + + b.Navigation("SelfAssignableRoleGroupNames"); + + b.Navigation("ShopEntries"); + + b.Navigation("SlowmodeIgnoredRoles"); + + b.Navigation("SlowmodeIgnoredUsers"); + + b.Navigation("StreamRole"); + + b.Navigation("UnbanTimer"); + + b.Navigation("UnmuteTimers"); + + b.Navigation("UnroleTimer"); + + b.Navigation("VcRoleInfos"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.LogSetting", b => + { + b.Navigation("LogIgnores"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.MusicPlaylist", b => + { + b.Navigation("Songs"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ShopEntry", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamRoleSettings", b => + { + b.Navigation("Blacklist"); + + b.Navigation("Whitelist"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.WaifuInfo", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpSettings", b => + { + b.Navigation("CurrencyRewards"); + + b.Navigation("ExclusionList"); + + b.Navigation("RoleRewards"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/NadekoBot/Migrations/PostgreSql/20241102022956_no-discrim-and-flag-translate.cs b/src/NadekoBot/Migrations/PostgreSql/20241102022956_no-discrim-and-flag-translate.cs new file mode 100644 index 000000000..a8dbd5cce --- /dev/null +++ b/src/NadekoBot/Migrations/PostgreSql/20241102022956_no-discrim-and-flag-translate.cs @@ -0,0 +1,56 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace NadekoBot.Migrations.PostgreSql +{ + /// + public partial class nodiscrimandflagtranslate : Migration + { + /// + 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(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + guildid = table.Column(type: "numeric(20,0)", nullable: false), + channelid = table.Column(type: "numeric(20,0)", nullable: false), + dateadded = table.Column(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); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "flagtranslatechannel"); + + migrationBuilder.AddColumn( + name: "discriminator", + table: "discorduser", + type: "text", + nullable: true); + } + } +} diff --git a/src/NadekoBot/Migrations/PostgreSql/PostgreSqlContextModelSnapshot.cs b/src/NadekoBot/Migrations/PostgreSql/PostgreSqlContextModelSnapshot.cs index f37398328..bfcd09274 100644 --- a/src/NadekoBot/Migrations/PostgreSql/PostgreSqlContextModelSnapshot.cs +++ b/src/NadekoBot/Migrations/PostgreSql/PostgreSqlContextModelSnapshot.cs @@ -751,10 +751,6 @@ namespace NadekoBot.Migrations.PostgreSql .HasColumnType("timestamp without time zone") .HasColumnName("dateadded"); - b.Property("Discriminator") - .HasColumnType("text") - .HasColumnName("discriminator"); - b.Property("IsClubAdmin") .ValueGeneratedOnAdd() .HasColumnType("boolean") @@ -998,6 +994,37 @@ namespace NadekoBot.Migrations.PostgreSql b.ToTable("filteredword", (string)null); }); + modelBuilder.Entity("NadekoBot.Db.Models.FlagTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.HasKey("Id") + .HasName("pk_flagtranslatechannel"); + + b.HasIndex("GuildId", "ChannelId") + .IsUnique() + .HasDatabaseName("ix_flagtranslatechannel_guildid_channelid"); + + b.ToTable("flagtranslatechannel", (string)null); + }); + modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b => { b.Property("Id") diff --git a/src/NadekoBot/Migrations/Sqlite/20241102022949_no-discrim-and-flag-translate.Designer.cs b/src/NadekoBot/Migrations/Sqlite/20241102022949_no-discrim-and-flag-translate.Designer.cs new file mode 100644 index 000000000..549a2f0d0 --- /dev/null +++ b/src/NadekoBot/Migrations/Sqlite/20241102022949_no-discrim-and-flag-translate.Designer.cs @@ -0,0 +1,2973 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NadekoBot.Db; + +#nullable disable + +namespace NadekoBot.Migrations +{ + [DbContext(typeof(SqliteContext))] + [Migration("20241102022949_no-discrim-and-flag-translate")] + partial class nodiscrimandflagtranslate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.8"); + + modelBuilder.Entity("NadekoBot.Db.Models.AntiAltSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .HasColumnType("INTEGER"); + + b.Property("ActionDurationMinutes") + .HasColumnType("INTEGER"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("MinAge") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("AntiAltSetting"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AntiRaidSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("PunishDuration") + .HasColumnType("INTEGER"); + + b.Property("Seconds") + .HasColumnType("INTEGER"); + + b.Property("UserThreshold") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("AntiRaidSetting"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AntiSpamIgnore", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AntiSpamSettingId") + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("AntiSpamSettingId"); + + b.ToTable("AntiSpamIgnore"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AntiSpamSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("MessageThreshold") + .HasColumnType("INTEGER"); + + b.Property("MuteTime") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("AntiSpamSetting"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ArchivedTodoListModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("TodosArchive"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AutoCommand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("ChannelName") + .HasColumnType("TEXT"); + + b.Property("CommandText") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("GuildName") + .HasColumnType("TEXT"); + + b.Property("Interval") + .HasColumnType("INTEGER"); + + b.Property("VoiceChannelId") + .HasColumnType("INTEGER"); + + b.Property("VoiceChannelName") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("AutoCommands"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AutoPublishChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("AutoPublishChannel"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AutoTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoDelete") + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId") + .IsUnique(); + + b.HasIndex("GuildId"); + + b.ToTable("AutoTranslateChannels"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AutoTranslateUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Source") + .HasColumnType("TEXT"); + + b.Property("Target") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasAlternateKey("ChannelId", "UserId"); + + b.ToTable("AutoTranslateUsers"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("PruneDays") + .HasColumnType("INTEGER"); + + b.Property("Text") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("BanTemplates"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.BankUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Balance") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("BankUsers"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.BlacklistEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Blacklist"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b => + { + b.Property("ClubId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("ClubId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ClubApplicants"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b => + { + b.Property("ClubId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("ClubId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ClubBans"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("ImageUrl") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("OwnerId") + .HasColumnType("INTEGER"); + + b.Property("Xp") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("OwnerId") + .IsUnique(); + + b.ToTable("Clubs"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.CommandAlias", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Mapping") + .HasColumnType("TEXT"); + + b.Property("Trigger") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("CommandAlias"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.CommandCooldown", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CommandName") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Seconds") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("CommandCooldown"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.CurrencyTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Extra") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("OtherId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValueSql("NULL"); + + b.Property("Type") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("CurrencyTransactions"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DelMsgOnCmdChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("State") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("DelMsgOnCmdChannel"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DiscordPermOverride", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Command") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Perm") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "Command") + .IsUnique(); + + b.ToTable("DiscordPermOverrides"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AvatarId") + .HasColumnType("TEXT"); + + b.Property("ClubId") + .HasColumnType("INTEGER"); + + b.Property("CurrencyAmount") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0L); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IsClubAdmin") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(false); + + b.Property("NotifyOnLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0); + + b.Property("TotalXp") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0L); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasAlternateKey("UserId"); + + b.HasIndex("ClubId"); + + b.HasIndex("CurrencyAmount"); + + b.HasIndex("TotalXp"); + + b.HasIndex("UserId"); + + b.HasIndex("Username"); + + b.ToTable("DiscordUser"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ExcludedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("INTEGER"); + + b.Property("ItemType") + .HasColumnType("INTEGER"); + + b.Property("XpSettingsId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId"); + + b.ToTable("ExcludedItem"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FeedSub", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("Url") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasAlternateKey("GuildConfigId", "Url"); + + b.ToTable("FeedSub"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FilterChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilterChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FilterLinksChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilterLinksChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FilterWordsChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilterWordsChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FilteredWord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Word") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilteredWord"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FlagTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "ChannelId") + .IsUnique(); + + b.ToTable("FlagTranslateChannel"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FollowedStream"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GCChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("GCChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GamblingStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Bet") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Feature") + .HasColumnType("TEXT"); + + b.Property("PaidOut") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Feature") + .IsUnique(); + + b.ToTable("GamblingStats"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GiveawayModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("EndsAt") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("GiveawayModel"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GiveawayUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("GiveawayId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GiveawayId", "UserId") + .IsUnique(); + + b.ToTable("GiveawayUser"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GroupName", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Number") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId", "Number") + .IsUnique(); + + b.ToTable("GroupName"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GuildConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoAssignRoleIds") + .HasColumnType("TEXT"); + + b.Property("AutoDeleteSelfAssignedRoleMessages") + .HasColumnType("INTEGER"); + + b.Property("CleverbotEnabled") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DeleteMessageOnCommand") + .HasColumnType("INTEGER"); + + b.Property("DeleteStreamOnlineMessage") + .HasColumnType("INTEGER"); + + b.Property("DisableGlobalExpressions") + .HasColumnType("INTEGER"); + + b.Property("ExclusiveSelfAssignedRoles") + .HasColumnType("INTEGER"); + + b.Property("FilterInvites") + .HasColumnType("INTEGER"); + + b.Property("FilterLinks") + .HasColumnType("INTEGER"); + + b.Property("FilterWords") + .HasColumnType("INTEGER"); + + b.Property("GameVoiceChannel") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Locale") + .HasColumnType("TEXT"); + + b.Property("MuteRoleName") + .HasColumnType("TEXT"); + + b.Property("NotifyStreamOffline") + .HasColumnType("INTEGER"); + + b.Property("PermissionRole") + .HasColumnType("TEXT"); + + b.Property("Prefix") + .HasColumnType("TEXT"); + + b.Property("StickyRoles") + .HasColumnType("INTEGER"); + + b.Property("TimeZoneId") + .HasColumnType("TEXT"); + + b.Property("VerboseErrors") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(true); + + b.Property("VerbosePermissions") + .HasColumnType("INTEGER"); + + b.Property("WarnExpireAction") + .HasColumnType("INTEGER"); + + b.Property("WarnExpireHours") + .HasColumnType("INTEGER"); + + b.Property("WarningsInitialized") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.HasIndex("WarnExpireHours"); + + b.ToTable("GuildConfigs"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.HoneypotChannel", b => + { + b.Property("GuildId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.HasKey("GuildId"); + + b.ToTable("HoneyPotChannels"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.IgnoredLogItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemType") + .HasColumnType("INTEGER"); + + b.Property("LogItemId") + .HasColumnType("INTEGER"); + + b.Property("LogSettingId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("LogSettingId", "LogItemId", "ItemType") + .IsUnique(); + + b.ToTable("IgnoredLogChannels"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ImageOnlyChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId") + .IsUnique(); + + b.ToTable("ImageOnlyChannels"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.LogSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelCreatedId") + .HasColumnType("INTEGER"); + + b.Property("ChannelDestroyedId") + .HasColumnType("INTEGER"); + + b.Property("ChannelUpdatedId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LogOtherId") + .HasColumnType("INTEGER"); + + b.Property("LogUserPresenceId") + .HasColumnType("INTEGER"); + + b.Property("LogVoicePresenceId") + .HasColumnType("INTEGER"); + + b.Property("LogVoicePresenceTTSId") + .HasColumnType("INTEGER"); + + b.Property("LogWarnsId") + .HasColumnType("INTEGER"); + + b.Property("MessageDeletedId") + .HasColumnType("INTEGER"); + + b.Property("MessageUpdatedId") + .HasColumnType("INTEGER"); + + b.Property("ThreadCreatedId") + .HasColumnType("INTEGER"); + + b.Property("ThreadDeletedId") + .HasColumnType("INTEGER"); + + b.Property("UserBannedId") + .HasColumnType("INTEGER"); + + b.Property("UserJoinedId") + .HasColumnType("INTEGER"); + + b.Property("UserLeftId") + .HasColumnType("INTEGER"); + + b.Property("UserMutedId") + .HasColumnType("INTEGER"); + + b.Property("UserUnbannedId") + .HasColumnType("INTEGER"); + + b.Property("UserUpdatedId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("LogSettings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.MusicPlayerSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoDisconnect") + .HasColumnType("INTEGER"); + + b.Property("AutoPlay") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("MusicChannelId") + .HasColumnType("INTEGER"); + + b.Property("PlayerRepeat") + .HasColumnType("INTEGER"); + + b.Property("QualityPreset") + .HasColumnType("INTEGER"); + + b.Property("Volume") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(100); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("MusicPlayerSettings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.MusicPlaylist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Author") + .HasColumnType("TEXT"); + + b.Property("AuthorId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("MusicPlaylists"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.MutedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("MutedUserId"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.NCPixel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Color") + .HasColumnType("INTEGER"); + + b.Property("OwnerId") + .HasColumnType("INTEGER"); + + b.Property("Position") + .HasColumnType("INTEGER"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasAlternateKey("Position"); + + b.HasIndex("OwnerId"); + + b.ToTable("NCPixel"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.NadekoExpression", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AllowTarget") + .HasColumnType("INTEGER"); + + b.Property("AutoDeleteTrigger") + .HasColumnType("INTEGER"); + + b.Property("ContainsAnywhere") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DmResponse") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Reactions") + .HasColumnType("TEXT"); + + b.Property("Response") + .HasColumnType("TEXT"); + + b.Property("Trigger") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Expressions"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.PatronUser", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AmountCents") + .HasColumnType("INTEGER"); + + b.Property("LastCharge") + .HasColumnType("TEXT"); + + b.Property("UniquePlatformUserId") + .HasColumnType("TEXT"); + + b.Property("ValidThru") + .HasColumnType("TEXT"); + + b.HasKey("UserId"); + + b.HasIndex("UniquePlatformUserId") + .IsUnique(); + + b.ToTable("Patrons"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.Permissionv2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("IsCustomCommand") + .HasColumnType("INTEGER"); + + b.Property("PrimaryTarget") + .HasColumnType("INTEGER"); + + b.Property("PrimaryTargetId") + .HasColumnType("INTEGER"); + + b.Property("SecondaryTarget") + .HasColumnType("INTEGER"); + + b.Property("SecondaryTargetName") + .HasColumnType("TEXT"); + + b.Property("State") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.PlantedCurrency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId"); + + b.HasIndex("MessageId") + .IsUnique(); + + b.ToTable("PlantedCurrency"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.PlaylistSong", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("MusicPlaylistId") + .HasColumnType("INTEGER"); + + b.Property("Provider") + .HasColumnType("TEXT"); + + b.Property("ProviderType") + .HasColumnType("INTEGER"); + + b.Property("Query") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Uri") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("MusicPlaylistId"); + + b.ToTable("PlaylistSong"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.Quote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuthorId") + .HasColumnType("INTEGER"); + + b.Property("AuthorName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Keyword") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Text") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.HasIndex("Keyword"); + + b.ToTable("Quotes"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ReactionRoleV2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Emote") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Group") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LevelReq") + .HasColumnType("INTEGER"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.HasIndex("MessageId", "Emote") + .IsUnique(); + + b.ToTable("ReactionRoles"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IsPrivate") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("When"); + + b.ToTable("Reminders"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.Repeater", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Interval") + .HasColumnType("TEXT"); + + b.Property("LastMessageId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NoRedundant") + .HasColumnType("INTEGER"); + + b.Property("StartTimeOfDay") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Repeaters"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.RewardedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AmountRewardedThisMonth") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("LastReward") + .HasColumnType("TEXT"); + + b.Property("PlatformUserId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PlatformUserId") + .IsUnique(); + + b.ToTable("RewardedUsers"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.RotatingPlayingStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RotatingStatus"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.SelfAssignedRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Group") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LevelRequirement") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "RoleId") + .IsUnique(); + + b.ToTable("SelfAssignableRoles"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ShopEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuthorId") + .HasColumnType("INTEGER"); + + b.Property("Command") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("RoleName") + .HasColumnType("TEXT"); + + b.Property("RoleRequirement") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("ShopEntry"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ShopEntryItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ShopEntryId") + .HasColumnType("INTEGER"); + + b.Property("Text") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ShopEntryId"); + + b.ToTable("ShopEntryItem"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.SlowmodeIgnoredRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("SlowmodeIgnoredRole"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.SlowmodeIgnoredUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("SlowmodeIgnoredUser"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StickyRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("RoleIds") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "UserId") + .IsUnique(); + + b.ToTable("StickyRoles"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamOnlineMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("StreamOnlineMessages"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamRoleBlacklistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("StreamRoleSettingsId"); + + b.ToTable("StreamRoleBlacklistedUser"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamRoleSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddRoleId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("FromRoleId") + .HasColumnType("INTEGER"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Keyword") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("StreamRoleSettings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamRoleWhitelistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("StreamRoleSettingsId"); + + b.ToTable("StreamRoleWhitelistedUser"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.TodoModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArchiveId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IsDone") + .HasColumnType("INTEGER"); + + b.Property("Todo") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ArchiveId"); + + b.HasIndex("UserId"); + + b.ToTable("Todos"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.UnbanTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UnbanAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnbanTimer"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.UnmuteTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UnmuteAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnmuteTimer"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.UnroleTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("UnbanAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnroleTimer"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.UserXpStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AwardedXp") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("NotifyOnLevelUp") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Xp") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("AwardedXp"); + + b.HasIndex("GuildId"); + + b.HasIndex("UserId"); + + b.HasIndex("Xp"); + + b.HasIndex("UserId", "GuildId") + .IsUnique(); + + b.ToTable("UserXpStats"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.VcRoleInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("VoiceChannelId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("VcRoleInfo"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.WaifuInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AffinityId") + .HasColumnType("INTEGER"); + + b.Property("ClaimerId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("WaifuId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("AffinityId"); + + b.HasIndex("ClaimerId"); + + b.HasIndex("Price"); + + b.HasIndex("WaifuId") + .IsUnique(); + + b.ToTable("WaifuInfo"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.WaifuItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemEmoji") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("WaifuInfoId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("WaifuInfoId"); + + b.ToTable("WaifuItem"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.WaifuUpdate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("NewId") + .HasColumnType("INTEGER"); + + b.Property("OldId") + .HasColumnType("INTEGER"); + + b.Property("UpdateType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NewId"); + + b.HasIndex("OldId"); + + b.HasIndex("UserId"); + + b.ToTable("WaifuUpdates"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.Warning", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Forgiven") + .HasColumnType("INTEGER"); + + b.Property("ForgivenBy") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Moderator") + .HasColumnType("TEXT"); + + b.Property("Reason") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Weight") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(1L); + + b.HasKey("Id"); + + b.HasIndex("DateAdded"); + + b.HasIndex("GuildId"); + + b.HasIndex("UserId"); + + b.ToTable("Warnings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.WarningPunishment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Count") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Punishment") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("Time") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasAlternateKey("GuildId", "Count"); + + b.ToTable("WarningPunishment"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpCurrencyReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("XpSettingsId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId"); + + b.ToTable("XpCurrencyReward"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpRoleReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Remove") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("XpSettingsId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId", "Level") + .IsUnique(); + + b.ToTable("XpRoleReward"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("ServerExcluded") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpShopOwnedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IsUsing") + .HasColumnType("INTEGER"); + + b.Property("ItemKey") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ItemType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "ItemType", "ItemKey") + .IsUnique(); + + b.ToTable("XpShopOwnedItem"); + }); + + modelBuilder.Entity("NadekoBot.Services.GreetSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoDeleteTimer") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("GreetType") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("IsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(false); + + b.Property("MessageText") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "GreetType") + .IsUnique(); + + b.ToTable("GreetSettings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AntiAltSetting", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithOne("AntiAltSetting") + .HasForeignKey("NadekoBot.Db.Models.AntiAltSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AntiRaidSetting", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithOne("AntiRaidSetting") + .HasForeignKey("NadekoBot.Db.Models.AntiRaidSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AntiSpamIgnore", b => + { + b.HasOne("NadekoBot.Db.Models.AntiSpamSetting", null) + .WithMany("IgnoredChannels") + .HasForeignKey("AntiSpamSettingId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AntiSpamSetting", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithOne("AntiSpamSetting") + .HasForeignKey("NadekoBot.Db.Models.AntiSpamSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AutoTranslateUser", b => + { + b.HasOne("NadekoBot.Db.Models.AutoTranslateChannel", "Channel") + .WithMany("Users") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Channel"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Applicants") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Bans") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Owner") + .WithOne() + .HasForeignKey("NadekoBot.Db.Models.ClubInfo", "OwnerId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.CommandAlias", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("CommandAliases") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.CommandCooldown", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("CommandCooldowns") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DelMsgOnCmdChannel", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("DelMsgOnCmdChannels") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Members") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.NoAction); + + b.Navigation("Club"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ExcludedItem", b => + { + b.HasOne("NadekoBot.Db.Models.XpSettings", "XpSettings") + .WithMany("ExclusionList") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FeedSub", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", "GuildConfig") + .WithMany("FeedSubs") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FilterChannelId", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("FilterInvitesChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FilterLinksChannelId", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("FilterLinksChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FilterWordsChannelId", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("FilterWordsChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FilteredWord", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("FilteredWords") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("FollowedStreams") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GCChannelId", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", "GuildConfig") + .WithMany("GenerateCurrencyChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GiveawayUser", b => + { + b.HasOne("NadekoBot.Db.Models.GiveawayModel", null) + .WithMany("Participants") + .HasForeignKey("GiveawayId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GroupName", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", "GuildConfig") + .WithMany("SelfAssignableRoleGroupNames") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.IgnoredLogItem", b => + { + b.HasOne("NadekoBot.Db.Models.LogSetting", "LogSetting") + .WithMany("LogIgnores") + .HasForeignKey("LogSettingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.MutedUserId", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("MutedUsers") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.Permissionv2", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("Permissions") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.PlaylistSong", b => + { + b.HasOne("NadekoBot.Db.Models.MusicPlaylist", null) + .WithMany("Songs") + .HasForeignKey("MusicPlaylistId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ShopEntry", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("ShopEntries") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ShopEntryItem", b => + { + b.HasOne("NadekoBot.Db.Models.ShopEntry", null) + .WithMany("Items") + .HasForeignKey("ShopEntryId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.SlowmodeIgnoredRole", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredRoles") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.SlowmodeIgnoredUser", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredUsers") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamRoleBlacklistedUser", b => + { + b.HasOne("NadekoBot.Db.Models.StreamRoleSettings", "StreamRoleSettings") + .WithMany("Blacklist") + .HasForeignKey("StreamRoleSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("StreamRoleSettings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamRoleSettings", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", "GuildConfig") + .WithOne("StreamRole") + .HasForeignKey("NadekoBot.Db.Models.StreamRoleSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamRoleWhitelistedUser", b => + { + b.HasOne("NadekoBot.Db.Models.StreamRoleSettings", "StreamRoleSettings") + .WithMany("Whitelist") + .HasForeignKey("StreamRoleSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("StreamRoleSettings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.TodoModel", b => + { + b.HasOne("NadekoBot.Db.Models.ArchivedTodoListModel", null) + .WithMany("Items") + .HasForeignKey("ArchiveId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.UnbanTimer", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("UnbanTimer") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.UnmuteTimer", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("UnmuteTimers") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.UnroleTimer", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("UnroleTimer") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.VcRoleInfo", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", null) + .WithMany("VcRoleInfos") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.WaifuInfo", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Affinity") + .WithMany() + .HasForeignKey("AffinityId"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Claimer") + .WithMany() + .HasForeignKey("ClaimerId"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Waifu") + .WithOne() + .HasForeignKey("NadekoBot.Db.Models.WaifuInfo", "WaifuId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Affinity"); + + b.Navigation("Claimer"); + + b.Navigation("Waifu"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.WaifuItem", b => + { + b.HasOne("NadekoBot.Db.Models.WaifuInfo", "WaifuInfo") + .WithMany("Items") + .HasForeignKey("WaifuInfoId"); + + b.Navigation("WaifuInfo"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.WaifuUpdate", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "New") + .WithMany() + .HasForeignKey("NewId"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Old") + .WithMany() + .HasForeignKey("OldId"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("New"); + + b.Navigation("Old"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpCurrencyReward", b => + { + b.HasOne("NadekoBot.Db.Models.XpSettings", "XpSettings") + .WithMany("CurrencyRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpRoleReward", b => + { + b.HasOne("NadekoBot.Db.Models.XpSettings", "XpSettings") + .WithMany("RoleRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpSettings", b => + { + b.HasOne("NadekoBot.Db.Models.GuildConfig", "GuildConfig") + .WithOne("XpSettings") + .HasForeignKey("NadekoBot.Db.Models.XpSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AntiSpamSetting", b => + { + b.Navigation("IgnoredChannels"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ArchivedTodoListModel", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.AutoTranslateChannel", b => + { + b.Navigation("Users"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.Navigation("Applicants"); + + b.Navigation("Bans"); + + b.Navigation("Members"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GiveawayModel", b => + { + b.Navigation("Participants"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.GuildConfig", b => + { + b.Navigation("AntiAltSetting"); + + b.Navigation("AntiRaidSetting"); + + b.Navigation("AntiSpamSetting"); + + b.Navigation("CommandAliases"); + + b.Navigation("CommandCooldowns"); + + b.Navigation("DelMsgOnCmdChannels"); + + b.Navigation("FeedSubs"); + + b.Navigation("FilterInvitesChannelIds"); + + b.Navigation("FilterLinksChannelIds"); + + b.Navigation("FilterWordsChannelIds"); + + b.Navigation("FilteredWords"); + + b.Navigation("FollowedStreams"); + + b.Navigation("GenerateCurrencyChannelIds"); + + b.Navigation("MutedUsers"); + + b.Navigation("Permissions"); + + b.Navigation("SelfAssignableRoleGroupNames"); + + b.Navigation("ShopEntries"); + + b.Navigation("SlowmodeIgnoredRoles"); + + b.Navigation("SlowmodeIgnoredUsers"); + + b.Navigation("StreamRole"); + + b.Navigation("UnbanTimer"); + + b.Navigation("UnmuteTimers"); + + b.Navigation("UnroleTimer"); + + b.Navigation("VcRoleInfos"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.LogSetting", b => + { + b.Navigation("LogIgnores"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.MusicPlaylist", b => + { + b.Navigation("Songs"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ShopEntry", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamRoleSettings", b => + { + b.Navigation("Blacklist"); + + b.Navigation("Whitelist"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.WaifuInfo", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpSettings", b => + { + b.Navigation("CurrencyRewards"); + + b.Navigation("ExclusionList"); + + b.Navigation("RoleRewards"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/NadekoBot/Migrations/Sqlite/20241102022949_no-discrim-and-flag-translate.cs b/src/NadekoBot/Migrations/Sqlite/20241102022949_no-discrim-and-flag-translate.cs new file mode 100644 index 000000000..b685c874a --- /dev/null +++ b/src/NadekoBot/Migrations/Sqlite/20241102022949_no-discrim-and-flag-translate.cs @@ -0,0 +1,55 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace NadekoBot.Migrations +{ + /// + public partial class nodiscrimandflagtranslate : Migration + { + /// + 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(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + GuildId = table.Column(type: "INTEGER", nullable: false), + ChannelId = table.Column(type: "INTEGER", nullable: false), + DateAdded = table.Column(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); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "FlagTranslateChannel"); + + migrationBuilder.AddColumn( + name: "Discriminator", + table: "DiscordUser", + type: "TEXT", + nullable: true); + } + } +} diff --git a/src/NadekoBot/Migrations/Sqlite/NadekoSqliteContextModelSnapshot.cs b/src/NadekoBot/Migrations/Sqlite/NadekoSqliteContextModelSnapshot.cs index fb997ff86..bdd43bea1 100644 --- a/src/NadekoBot/Migrations/Sqlite/NadekoSqliteContextModelSnapshot.cs +++ b/src/NadekoBot/Migrations/Sqlite/NadekoSqliteContextModelSnapshot.cs @@ -560,9 +560,6 @@ namespace NadekoBot.Migrations b.Property("DateAdded") .HasColumnType("TEXT"); - b.Property("Discriminator") - .HasColumnType("TEXT"); - b.Property("IsClubAdmin") .ValueGeneratedOnAdd() .HasColumnType("INTEGER") @@ -743,6 +740,29 @@ namespace NadekoBot.Migrations b.ToTable("FilteredWord"); }); + modelBuilder.Entity("NadekoBot.Db.Models.FlagTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "ChannelId") + .IsUnique(); + + b.ToTable("FlagTranslateChannel"); + }); + modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b => { b.Property("Id") diff --git a/src/NadekoBot/Modules/Administration/Self/SelfService.cs b/src/NadekoBot/Modules/Administration/Self/SelfService.cs index 0a7214494..af33c1e0f 100644 --- a/src/NadekoBot/Modules/Administration/Self/SelfService.cs +++ b/src/NadekoBot/Modules/Administration/Self/SelfService.cs @@ -453,7 +453,6 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, INService { 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, INService 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, INService .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, diff --git a/src/NadekoBot/Modules/Gambling/Waifus/WaifuService.cs b/src/NadekoBot/Modules/Gambling/Waifus/WaifuService.cs index 87e871fe6..b321254b6 100644 --- a/src/NadekoBot/Modules/Gambling/Waifus/WaifuService.cs +++ b/src/NadekoBot/Modules/Gambling/Waifus/WaifuService.cs @@ -603,7 +603,7 @@ public class WaifuService : INService, 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 : INService, IReadyExecutor .Where(wi => wi.AffinityId == waifuId) .Select(wi => wi.WaifuId) .Contains(x.Id)) - .Select(x => $"{x.Username}#{x.Discriminator}") + .Select(x => x.Username) .ToListAsyncEF(); } diff --git a/src/NadekoBot/Modules/Gambling/Waifus/db/WaifuExtensions.cs b/src/NadekoBot/Modules/Gambling/Waifus/db/WaifuExtensions.cs index 1e141ab85..4337ffbe7 100644 --- a/src/NadekoBot/Modules/Gambling/Waifus/db/WaifuExtensions.cs +++ b/src/NadekoBot/Modules/Gambling/Waifus/db/WaifuExtensions.cs @@ -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 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() .AsQueryable() .Where(u => u.UserId == userId) - .Select(u => u.Username + "#" + u.Discriminator) + .Select(u => u.Username) .FirstOrDefault(), AffinityCount = ctx.Set() @@ -112,14 +109,14 @@ public static class WaifuExtensions ctx.Set() .AsQueryable() .Where(u => u.Id == w.AffinityId) - .Select(u => u.Username + "#" + u.Discriminator) + .Select(u => u.Username) .FirstOrDefault(), ClaimCount = ctx.Set().AsQueryable().Count(x => x.ClaimerId == w.WaifuId), ClaimerName = ctx.Set() .AsQueryable() .Where(u => u.Id == w.ClaimerId) - .Select(u => u.Username + "#" + u.Discriminator) + .Select(u => u.Username) .FirstOrDefault(), DivorceCount = ctx.Set() diff --git a/src/NadekoBot/Modules/Games/Nunchi/NunchiCommands.cs b/src/NadekoBot/Modules/Games/Nunchi/NunchiCommands.cs index 329cff5fa..8631489ea 100644 --- a/src/NadekoBot/Modules/Games/Nunchi/NunchiCommands.cs +++ b/src/NadekoBot/Modules/Games/Nunchi/NunchiCommands.cs @@ -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; } diff --git a/src/NadekoBot/Modules/Patronage/CurrencyRewardService.cs b/src/NadekoBot/Modules/Patronage/CurrencyRewardService.cs index b22d9d108..ccd1d2a62 100644 --- a/src/NadekoBot/Modules/Patronage/CurrencyRewardService.cs +++ b/src/NadekoBot/Modules/Patronage/CurrencyRewardService.cs @@ -122,11 +122,11 @@ public sealed class CurrencyRewardService : INService, 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))); diff --git a/src/NadekoBot/Modules/Searches/Translate/FlagTranslateService.cs b/src/NadekoBot/Modules/Searches/Translate/FlagTranslateService.cs new file mode 100644 index 000000000..2a82b847a --- /dev/null +++ b/src/NadekoBot/Modules/Searches/Translate/FlagTranslateService.cs @@ -0,0 +1,191 @@ +#nullable disable +using LinqToDB; +using LinqToDB.EntityFrameworkCore; +using NadekoBot.Common.ModuleBehaviors; +using NadekoBot.Db.Models; +using System.Collections.Frozen; + +namespace NadekoBot.Modules.Searches; + +public sealed partial class FlagTranslateService : IReadyExecutor, INService +{ + private readonly IBotCreds _creds; + private readonly DiscordSocketClient _client; + private readonly TranslateService _ts; + private readonly IMessageSenderService _sender; + private IReadOnlyDictionary _supportedFlags; + private readonly DbService _db; + private ConcurrentHashSet _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() + .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 CdKey(ulong userId) + => new($"flagtranslate:{userId}"); + + private Task OnReactionAdded( + Cacheable arg1, + Cacheable 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() + .Where(x => x.GuildId == guildId + && x.ChannelId == tcId) + .DeleteAsync(); + } + + public async Task 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() + .InsertAsync(() => new FlagTranslateChannel + { + GuildId = guildId, + ChannelId = tcId + }); + } +} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Searches/Translate/FlagTranslateService_SupportedFlags.cs b/src/NadekoBot/Modules/Searches/Translate/FlagTranslateService_SupportedFlags.cs new file mode 100644 index 000000000..27210e84a --- /dev/null +++ b/src/NadekoBot/Modules/Searches/Translate/FlagTranslateService_SupportedFlags.cs @@ -0,0 +1,73 @@ +namespace NadekoBot.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 + """; +} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Searches/Translate/TranslateService.cs b/src/NadekoBot/Modules/Searches/Translate/TranslateService.cs index 107cf7d26..090c265d1 100644 --- a/src/NadekoBot/Modules/Searches/Translate/TranslateService.cs +++ b/src/NadekoBot/Modules/Searches/Translate/TranslateService.cs @@ -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 Translate(string source, string target, string text = null) + public async Task Translate(string source, string target, string text) { if (string.IsNullOrWhiteSpace(text)) throw new ArgumentException("Text is empty or null", nameof(text)); diff --git a/src/NadekoBot/Modules/Searches/Translate/TranslatorCommands.cs b/src/NadekoBot/Modules/Searches/Translate/TranslatorCommands.cs index ca457ccc5..345556ecd 100644 --- a/src/NadekoBot/Modules/Searches/Translate/TranslatorCommands.cs +++ b/src/NadekoBot/Modules/Searches/Translate/TranslatorCommands.cs @@ -6,6 +6,14 @@ public partial class Searches [Group] public partial class TranslateCommands : NadekoModule { + 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(); + } } } \ No newline at end of file diff --git a/src/NadekoBot/Services/GrpcApi/XpSvc.cs b/src/NadekoBot/Services/GrpcApi/XpSvc.cs index 8e64256a9..445ecfd67 100644 --- a/src/NadekoBot/Services/GrpcApi/XpSvc.cs +++ b/src/NadekoBot/Services/GrpcApi/XpSvc.cs @@ -28,6 +28,8 @@ public class XpSvc : GrpcXp.GrpcXpBase, IGrpcSvc, INService 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, INService 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; diff --git a/src/NadekoBot/_common/Impl/GoogleApiService.cs b/src/NadekoBot/_common/Impl/GoogleApiService.cs index b1da4d7ac..55b84d113 100644 --- a/src/NadekoBot/_common/Impl/GoogleApiService.cs +++ b/src/NadekoBot/_common/Impl/GoogleApiService.cs @@ -201,9 +201,12 @@ public sealed partial class GoogleApiService : IGoogleApiService, INService { 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, INService private string ConvertToLanguageCode(string language) { Languages.TryGetValue(language, out var mode); - return mode; + return string.IsNullOrWhiteSpace(mode) ? language : mode; } } diff --git a/src/NadekoBot/_common/Impl/GoogleApiService_SupportedLanguages.cs b/src/NadekoBot/_common/Impl/GoogleApiService_SupportedLanguages.cs index 365d4f5f4..42694beb5 100644 --- a/src/NadekoBot/_common/Impl/GoogleApiService_SupportedLanguages.cs +++ b/src/NadekoBot/_common/Impl/GoogleApiService_SupportedLanguages.cs @@ -154,7 +154,6 @@ public sealed partial class GoogleApiService } Languages = langs; - } } \ No newline at end of file diff --git a/src/NadekoBot/_common/Services/Currency/DefaultWallet.cs b/src/NadekoBot/_common/Services/Currency/DefaultWallet.cs index e30206d7c..0371becd9 100644 --- a/src/NadekoBot/_common/Services/Currency/DefaultWallet.cs +++ b/src/NadekoBot/_common/Services/Currency/DefaultWallet.cs @@ -77,8 +77,7 @@ public class DefaultWallet : IWallet .InsertOrUpdateAsync(() => new() { UserId = userId, - Username = "Unknown", - Discriminator = "????", + Username = "??Unknown", CurrencyAmount = amount, }, (old) => new() diff --git a/src/NadekoBot/_common/Services/Impl/StatsService.cs b/src/NadekoBot/_common/Services/Impl/StatsService.cs index 03deab65e..a45c74061 100644 --- a/src/NadekoBot/_common/Services/Impl/StatsService.cs +++ b/src/NadekoBot/_common/Services/Impl/StatsService.cs @@ -193,7 +193,7 @@ public sealed class StatsService : IStatsService, IReadyExecutor, INService 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, diff --git a/src/NadekoBot/data/aliases.yml b/src/NadekoBot/data/aliases.yml index fa89b63bc..3588969c1 100644 --- a/src/NadekoBot/data/aliases.yml +++ b/src/NadekoBot/data/aliases.yml @@ -1444,4 +1444,9 @@ ncpixel: - ncp - ncgp ncreset: - - ncreset \ No newline at end of file + - ncreset +translateflags: + - translateflags + - trfl + - fltr + - transflags \ No newline at end of file diff --git a/src/NadekoBot/data/strings/commands/commands.en-US.yml b/src/NadekoBot/data/strings/commands/commands.en-US.yml index ffe822aa7..108d68835 100644 --- a/src/NadekoBot/data/strings/commands/commands.en-US.yml +++ b/src/NadekoBot/data/strings/commands/commands.en-US.yml @@ -4632,5 +4632,13 @@ ncreset: This command is dangerous and irreversible. ex: - '' + 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: - { } \ No newline at end of file diff --git a/src/NadekoBot/data/strings/responses/responses.en-US.json b/src/NadekoBot/data/strings/responses/responses.en-US.json index e42b454c2..9b4132262 100644 --- a/src/NadekoBot/data/strings/responses/responses.en-US.json +++ b/src/NadekoBot/data/strings/responses/responses.en-US.json @@ -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." }