mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-11 01:38:27 -04:00
Compare commits
104 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
32fc8b6e03 | ||
|
297e2fde0e | ||
|
729f26caab | ||
|
4b12e4e923 | ||
|
12f4ce7f2a | ||
|
00944e08c3 | ||
|
569abd7194 | ||
|
474a1db41d | ||
|
0f6255947e | ||
|
f68f219a25 | ||
|
8f16b11d02 | ||
|
df5eced904 | ||
|
1dcd158f43 | ||
|
757c9b564d | ||
|
07cef3eb5e | ||
|
85c525e19b | ||
|
477581f616 | ||
|
ff30105816 | ||
|
49f04a594b | ||
|
716090a132 | ||
|
c835514c7b | ||
|
b136e7ff0e | ||
|
9dd2997b0f | ||
|
fde5309ea4 | ||
|
a8e4173e9b | ||
|
74b4c4b64d | ||
|
6cc5a160a2 | ||
|
ca8e022db6 | ||
|
cd8c14c607 | ||
|
1340533c21 | ||
|
14d86b9042 | ||
|
3a504a954f | ||
|
822ce0b8de | ||
|
40490a4656 | ||
|
0cf7909fef | ||
|
de8d4b7d9e | ||
|
0123892038 | ||
|
d00e59567a | ||
|
0aba2fdcaf | ||
|
bb910a8188 | ||
|
bdad9cc17a | ||
|
5d76a15dc0 | ||
|
a7be56a562 | ||
|
3c108e531e | ||
|
c473669cbc | ||
|
b97c486b80 | ||
|
716e092fd0 | ||
|
a362ee90fc | ||
|
1de6cdb8dc | ||
|
f473014fe9 | ||
|
2c3e5fe507 | ||
|
ecc192c6a9 | ||
|
f7bd181034 | ||
|
664a4b3604 | ||
|
0326e88910 | ||
|
e4202b33f5 | ||
|
021e7978da | ||
|
28ad6db2de | ||
|
fb62df7aa2 | ||
|
33663d7efc | ||
|
6d1edc07cb | ||
|
c36ab34c4f | ||
|
e85e7c49cb | ||
|
e56190e9da | ||
|
2d16ecf6de | ||
|
2b12269917 | ||
|
79c2dfec2d | ||
|
73356b6beb | ||
|
bc22987330 | ||
|
c033c0e3c8 | ||
|
c9ed2cf4b5 | ||
|
52b87c7776 | ||
|
8b2ed0dbdc | ||
|
9424d4d5f9 | ||
|
67b186a1a5 | ||
|
436f9ed074 | ||
|
c1e51329be | ||
|
ae1193c1c5 | ||
|
9601a4d1a9 | ||
|
bdfde1205a | ||
|
5992628f80 | ||
|
d24e6fd8e7 | ||
|
c31c2e8d8e | ||
|
9aaf062d78 | ||
|
0b9e812d59 | ||
|
dc63e46852 | ||
|
e314686a03 | ||
|
f764a650da | ||
|
67616deb79 | ||
|
d0aa80a004 | ||
|
f66c105cc0 | ||
|
2a528cb3d6 | ||
|
8b40f97a3d | ||
|
fa9263ed32 | ||
|
88c42b74c7 | ||
|
f7406ec90b | ||
|
e446c8ee8b | ||
|
5839e944e1 | ||
|
15e41c10db | ||
|
99a8ea18bb | ||
|
5453f8acfa | ||
|
c95d1421c6 | ||
|
f631f16690 | ||
|
d397c2dce8 |
442
CHANGELOG.md
442
CHANGELOG.md
@@ -2,6 +2,189 @@
|
||||
|
||||
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 button. Togglable via `.conf gambling` it's called pass because previously it was a captcha, but captchas are too annoying
|
||||
|
||||
## 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
|
||||
- Flower currency generation will now have a strikeout to try combat the pickbots. This is the weakest but easiest protection to implement. There may be more options in the future
|
||||
|
||||
## Fixed
|
||||
|
||||
- nunchi join game message is now ok color instead of error color
|
||||
|
||||
## [5.1.17] - 29.10.2024
|
||||
|
||||
### Fixed
|
||||
|
||||
- fix: Bot will now not accept .aar Role if that Role is higher than or equal to bot's role. Previously bot would just
|
||||
fail silently, now there is a proper error message.
|
||||
|
||||
## [5.1.16] - 28.10.2024
|
||||
|
||||
## Added
|
||||
|
||||
- Added .ncanvas and related commands.
|
||||
- You can set pixel colors (and text) on a 500x350 canvas, pepega version of r/place
|
||||
- You use currency to set pixels.
|
||||
- Commands:
|
||||
- see the entire canvas: `.nc`
|
||||
- zoom: `.ncz <pos>` or `.ncz x y`
|
||||
- set pixel: `.ncsp <pos> <color> <text?>`
|
||||
- get pixel: `.ncp <pos>`
|
||||
- Owners can use .ncsetimg to set a starting image, use `.h .setimg` for instructions
|
||||
- Owners can reset the whole canvas via `.ncreset`
|
||||
|
||||
## [5.1.15] - 21.10.2024
|
||||
|
||||
## Added
|
||||
|
||||
- Added -c option for `.xpglb`
|
||||
-
|
||||
|
||||
## Change
|
||||
|
||||
- Leaderboards will now show 10 users per page
|
||||
- A lot of internal changes and improvements
|
||||
|
||||
## Fixed
|
||||
|
||||
- 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
|
||||
- More `.greet` command fixes
|
||||
- Author name will now be counted as content in embeds. Embeds can now only have author fields and still be valid
|
||||
- Grpc api fixes, and additions
|
||||
|
||||
## [5.1.14] - 03.10.2024
|
||||
|
||||
## Changed
|
||||
|
||||
- Improved `.xplb -c`, it will now correctly only show users who are still in the server with no count limit
|
||||
|
||||
## Fixed
|
||||
|
||||
- Fixed medusa load error on startup
|
||||
|
||||
## [5.1.13] - 03.10.2024
|
||||
|
||||
### Fixed
|
||||
|
||||
- Grpc api server will no longer start unless enabled in creds
|
||||
- Seq comment in creds fixed
|
||||
|
||||
## [5.1.12] - 03.10.2024
|
||||
|
||||
### Added
|
||||
|
||||
- Added support for `seq` for logging. If you fill in seq url and apiKey in creds.yml, bot will sends logs to it
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed another bug in `.greet` / `.bye` system, which caused it to show wrong message on a wrong server occasionally
|
||||
|
||||
## [5.1.11] - 03.10.2024
|
||||
|
||||
### 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 initial version of grpc api. Beta
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed a bug which caused `.bye` and `.greet` messages to be randomly disabled
|
||||
- Fixed `.lb -c` breaking sometimes, and fixed pagination
|
||||
|
||||
### 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.
|
||||
- ytProvider in data/searches.yml now also controls where you're getting your song streams from.
|
||||
- (Invidious support added for .q)
|
||||
|
||||
## [5.1.10] - 24.09.2024
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed claimed waifu decay in `games.yml`
|
||||
|
||||
### Changed
|
||||
|
||||
- Added some logs for greet service in case there are unforeseen issues, for easier debugging
|
||||
|
||||
## [5.1.9] - 21.09.2024
|
||||
|
||||
### Fixed
|
||||
|
||||
- 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
|
||||
- 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.
|
||||
|
||||
## [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.
|
||||
- `.adpl` now supports custom statuses (you no longer need to specify Playing, Watching, etc...)
|
||||
|
||||
### Changed
|
||||
|
||||
- `.quote` commands cleaned up and improved
|
||||
- All quote commands now start with `.q<whatever>` and follow the same naming pattern as Expression commands
|
||||
- `.liqu` renamed to `.qli`
|
||||
- `.quotesearch` / `.qse` is now paginated for easier searching
|
||||
- `.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
|
||||
- Clarified and added some embed / placeholder links to command help where needed
|
||||
- dev: A lot of code cleanup and internal improvements
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed `.xpcurrew` breaking xp gain if user gains 0 xp from being in a voice channel
|
||||
- Fixed a bug in `.gatari` command
|
||||
- Fixed some waifu related strings
|
||||
- Fixed `.quoteshow` and `.quoteid` commands
|
||||
- Fixed some placeholders not working in `.greetdm`
|
||||
- Fixed postgres support
|
||||
- Fixed and clarified some command strings/parameter descriptions
|
||||
|
||||
### Removed
|
||||
|
||||
- Removed mysql support as it didn't work for a while, and requires some special handling/maintenance
|
||||
- Sqlite and Postgres support stays
|
||||
|
||||
## [5.1.7] - 08.08.2024
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed some command groups incorrectly showing up as modules
|
||||
|
||||
## [5.1.6] - 07.08.2024
|
||||
|
||||
### Added
|
||||
@@ -14,10 +197,11 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da
|
||||
|
||||
### Fixed
|
||||
|
||||
- `.afk` messages can no longer ping, and the response is moved to DMs to avoid
|
||||
- `.afk` messages can no longer ping, and the response is moved to DMs to avoid abuse
|
||||
- Possible fix for `.remind` timestamp
|
||||
|
||||
### Removed
|
||||
|
||||
- Removed old bloat / semi broken / dumb commands
|
||||
- `.memelist` / `.memegen` (too inconvenient to use)
|
||||
- `.activity` (useless owner-only command)
|
||||
@@ -44,7 +228,8 @@ 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
|
||||
|
||||
@@ -52,6 +237,7 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da
|
||||
- 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
|
||||
@@ -60,8 +246,10 @@ 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
|
||||
- Bot owners can now check other people's bank balance (Not server owners, only bot owner, the person who is hosting the
|
||||
bot)
|
||||
- You can now send multiple waifu gifts at once to waifus. For example `.waifugift 3xRose @user` will give that user 3
|
||||
roses
|
||||
- The format is `<NUMBER>x<ITEM>`, no spaces
|
||||
- Added `.boosttest` command
|
||||
- Added support for any openai compatible api for the chatterbot feature change:
|
||||
@@ -87,7 +275,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
|
||||
|
||||
@@ -120,28 +309,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)
|
||||
- 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 <https://dashy.nadeko.bot/me> after pledging on patreon and put it in nadekoAiToken in creds.yml
|
||||
- Selfhosters: If you're selfhosting, you also will need to acquire the api key
|
||||
from <https://dashy.nadeko.bot/me> 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
|
||||
@@ -155,8 +349,10 @@ 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
|
||||
|
||||
@@ -175,7 +371,8 @@ 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
|
||||
@@ -204,15 +401,19 @@ 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
|
||||
- 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 `.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 <duration> <text>` starts the giveway with the specified duration and message (prize). You may have up to 5 giveaways on the server at once
|
||||
- `.ga start <duration> <text>` starts the giveway with the specified duration and message (prize). You may have up
|
||||
to 5 giveaways on the server at once
|
||||
- `.ga end <id>` prematurely ends the giveaway and selects a winner
|
||||
- `.ga cancel <id>` cancels the giveaway and doesn't select a winner
|
||||
- `.ga list` lists active giveaways on the current server
|
||||
- `.ga reroll <id>` rerolls the winner on the completed giveaway. This only works for 24 hours after the giveaway has ended, or until the bot restarts.
|
||||
- `.ga reroll <id>` 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 <name>` - adds a new todo
|
||||
@@ -222,7 +423,8 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da
|
||||
- `.todo edit <id> <new message>` - edits a todo item message
|
||||
- `.todo show <id>` - Shows the text of the specified todo item
|
||||
- In addition to that, there are also Todo archive commands
|
||||
- `.todo archive add <name>` - adds all current todos (completed and not completed) to the archived list, your current todo list will become cleared
|
||||
- `.todo archive add <name>` - 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 <id>` - shows the todo items from one of your archived lists
|
||||
- `.todo archive delete <id>` - deletes and archived todo list
|
||||
@@ -241,8 +443,10 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da
|
||||
|
||||
### 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 <module name>`, `.cmds <group name` and `.mdls` looks better
|
||||
@@ -254,7 +458,8 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da
|
||||
### Fixed
|
||||
|
||||
- `.feed` should now correctly accept (and show) the message which can be passed as the third parameter
|
||||
- `.say` will now correctly report errors if the user or the bot don't have sufficent perms to send a message in the targeted channel
|
||||
- `.say` will now correctly report errors if the user or the bot don't have sufficent perms to send a message in the
|
||||
targeted channel
|
||||
- Fixed `.invitelist` not paginating correctly
|
||||
- `.serverinfo` will now correctly work for other shards
|
||||
- `.send` will now correctly work for other shards
|
||||
@@ -272,15 +477,17 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da
|
||||
## [4.3.22] - 23.04.2024
|
||||
|
||||
### Added
|
||||
|
||||
- Added `.setbanner` command (thx cata)
|
||||
|
||||
### Fixed
|
||||
- Fixed pagination error due to a missing emoji
|
||||
|
||||
- Fixed pagination error due to a missing emoji
|
||||
|
||||
## [4.3.21] - 19.04.2024
|
||||
|
||||
### Fixed
|
||||
|
||||
- Possible fix for a duplicate in `.h bank`
|
||||
- Fixed `.stock` command
|
||||
- Fixed `.clubapply` and `.clubaccept`
|
||||
@@ -289,14 +496,17 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da
|
||||
## [4.3.20] - 20.01.2024
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed `.config searches followedStreams.maxCount` not working
|
||||
|
||||
## [4.3.19] - 20.01.2024
|
||||
|
||||
### Added
|
||||
|
||||
- Added `followedStreams.maxCount` to `searches.yml` which lets bot owners change the default of 10 per server
|
||||
|
||||
### Changed
|
||||
|
||||
- Improvements to GPT ChatterBot (thx alexandra)
|
||||
- Add a personality prompt to tweak the way chatgpt bot behaves
|
||||
- Added Chat history support to chatgpt ChatterBot
|
||||
@@ -319,7 +529,8 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da
|
||||
- Fixed `icon_url` when using `.showembed`
|
||||
- Fixed `.quoteshow` not showing sometimes (thx Cata)
|
||||
- Notifications will no longer be sent if dms are off when using `.give`
|
||||
- Users should no longer be able to apply to clubs while in a club already (especially not to the same club they're already in)
|
||||
- Users should no longer be able to apply to clubs while in a club already (especially not to the same club they're
|
||||
already in)
|
||||
|
||||
### Removed
|
||||
|
||||
@@ -418,10 +629,12 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da
|
||||
|
||||
### Changed
|
||||
|
||||
- .meload and .meunload are now case sensitive. Previously loaded medusae may need to be reloaded or data/medusae/medusa.yml may need to be edited manually
|
||||
- .meload and .meunload are now case sensitive. Previously loaded medusae may need to be reloaded or
|
||||
data/medusae/medusa.yml may need to be edited manually
|
||||
- Several club related command have their error messages improved
|
||||
- Updated help text for .antispam and .antiraid
|
||||
- You can now specify time and date (time is optional) in `.remind` command instead of relative time, in the format `HH:mm dd.MM.YYYY`
|
||||
- You can now specify time and date (time is optional) in `.remind` command instead of relative time, in the
|
||||
format `HH:mm dd.MM.YYYY`
|
||||
- OwnerId will be automatically added to `creds.yml` at bot startup if it's missing
|
||||
|
||||
### Fixed
|
||||
@@ -481,13 +694,15 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da
|
||||
|
||||
### Added
|
||||
|
||||
- Added `.exprdelserv` (.exds) to completement .exas. Deletes an expression on the current server and is susceptible to .dpo, unlike .exd
|
||||
- Added `.exprdelserv` (.exds) to completement .exas. Deletes an expression on the current server and is susceptible to
|
||||
.dpo, unlike .exd
|
||||
- Added `.shopreq` which lets you set role requirement for specific shop items
|
||||
- Added `.shopbuy` alias to `.buy`
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed `.convertlist` showing currencies twice (this may not apply to existing users and it may require you to manually remove all currencies from units.json)
|
||||
- Fixed `.convertlist` showing currencies twice (this may not apply to existing users and it may require you to manually
|
||||
remove all currencies from units.json)
|
||||
|
||||
### Removed
|
||||
|
||||
@@ -497,9 +712,12 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da
|
||||
|
||||
### Added
|
||||
|
||||
- Added `.expraddserver` (.exas) which will server as a server-only alternative to '.exa' in case users want to override default Admin permissions with .dpo
|
||||
- Added .banprune command which sets how many days worth of messages will be pruned when bot (soft)bans a person either through a command or another punishment feature.
|
||||
- Added .qdelauth - Delete all quotes by the specified author on this server. If you target yourself - no permission required
|
||||
- Added `.expraddserver` (.exas) which will server as a server-only alternative to '.exa' in case users want to override
|
||||
default Admin permissions with .dpo
|
||||
- Added .banprune command which sets how many days worth of messages will be pruned when bot (soft)bans a person either
|
||||
through a command or another punishment feature.
|
||||
- Added .qdelauth - Delete all quotes by the specified author on this server. If you target yourself - no permission
|
||||
required
|
||||
- Added `.timeout` command
|
||||
- Added an option to award currency based on received xp
|
||||
|
||||
@@ -557,7 +775,8 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da
|
||||
- Possibly fixed .trivia not stopping bug
|
||||
- Fixed very low payout rate on `.betroll`
|
||||
- Fixed an issue with youtube song resolver which caused invalid data to be cached
|
||||
- Added client id to the cache key as a potential fix for VoiceXp 'bug'. The solution may be to use different redis instances for each bot, or to switch from botCache: from 'redis' to 'memory' in creds.yml
|
||||
- Added client id to the cache key as a potential fix for VoiceXp 'bug'. The solution may be to use different redis
|
||||
instances for each bot, or to switch from botCache: from 'redis' to 'memory' in creds.yml
|
||||
- Bot owner should now be able to buy items from the xpshop when patron requirement is set
|
||||
- Fixed youtube-dl caching invalid data. Please use yt-dlp instead
|
||||
|
||||
@@ -589,10 +808,12 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da
|
||||
- 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.
|
||||
- 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
|
||||
- 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 <true/false>`
|
||||
- Added `.xpshop` which lets bot owners add xp backgrounds and xp frames for sale by configuring `data/xp.yml`
|
||||
@@ -660,7 +881,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
|
||||
|
||||
@@ -726,7 +948,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
|
||||
|
||||
@@ -779,7 +1002,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
|
||||
@@ -790,12 +1014,15 @@ 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
|
||||
@@ -805,12 +1032,14 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except da
|
||||
- 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
|
||||
```
|
||||
|
||||
- ^ 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
|
||||
@@ -821,10 +1050,12 @@ quotas:
|
||||
- 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
|
||||
|
||||
@@ -835,26 +1066,34 @@ Added `.patron` and `.patronmessage` commands
|
||||
- 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
|
||||
- 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`
|
||||
- `.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.
|
||||
- `.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
|
||||
- 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
|
||||
@@ -918,7 +1157,8 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf
|
||||
- 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 `.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.
|
||||
@@ -944,7 +1184,6 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf
|
||||
- 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
|
||||
@@ -963,7 +1202,8 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf
|
||||
|
||||
- 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
|
||||
- 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
|
||||
@@ -973,9 +1213,11 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf
|
||||
- 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
|
||||
- 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
|
||||
- [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
|
||||
|
||||
@@ -1025,6 +1267,7 @@ 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 <id>` which lets you see full information about one of your own transactions with the specified id
|
||||
- Added trovo.live support for stream notifications (`.stadd`)
|
||||
@@ -1032,18 +1275,24 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf
|
||||
- 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
|
||||
- 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)
|
||||
- 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
|
||||
- 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)
|
||||
@@ -1062,6 +1311,7 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf
|
||||
- [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
|
||||
@@ -1073,8 +1323,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...
|
||||
|
||||
@@ -1088,6 +1340,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
|
||||
@@ -1099,12 +1352,15 @@ 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 <msgid>` and `.showembed #channel <msgid>` which will show you embed json from the specified message
|
||||
|
||||
### Changed
|
||||
|
||||
- `.at` and `.atl` commands reworked
|
||||
- Persist restarts
|
||||
- Will now only translate non-commands
|
||||
@@ -1114,55 +1370,67 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf
|
||||
- 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
|
||||
- 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 <imagelink.png>` 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 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
|
||||
|
||||
### 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
|
||||
@@ -1172,15 +1440,18 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf
|
||||
## [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`)
|
||||
- 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
|
||||
@@ -1249,7 +1520,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
|
||||
|
||||
@@ -1282,10 +1554,12 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf
|
||||
- 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
|
||||
- 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
|
||||
- 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
|
||||
@@ -1299,7 +1573,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
|
||||
|
||||
@@ -1329,9 +1604,11 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf
|
||||
- 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
|
||||
@@ -1352,16 +1629,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 <color> <role>` changed to take color, then the role, to make it easier to set color for roles with multiple words without mentioning the role
|
||||
- `.rolecolor <color> <role>` 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
|
||||
@@ -1378,10 +1658,13 @@ Note: Results of each `.youtube` query will be cached for 1 hour to improve perf
|
||||
- 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 `.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 <amount> <role>` to complement `.award <amount> 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
|
||||
@@ -1395,7 +1678,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
|
||||
|
||||
@@ -1459,7 +1743,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
|
||||
@@ -1482,4 +1767,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)
|
||||
|
@@ -30,6 +30,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nadeko.Medusa", "src\Nadeko
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NadekoBot.Generators", "src\NadekoBot.Generators\NadekoBot.Generators.csproj", "{92770AF3-83EE-49F1-A0BB-79124D19A13D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NadekoBot.GrpcApiBase", "src\NadekoBot.GrpcApiBase\NadekoBot.GrpcApiBase.csproj", "{FB74B9EA-10B9-4542-ACB1-35523A95A587}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -79,6 +81,12 @@ Global
|
||||
{92770AF3-83EE-49F1-A0BB-79124D19A13D}.GlobalNadeko|Any CPU.Build.0 = Debug|Any CPU
|
||||
{92770AF3-83EE-49F1-A0BB-79124D19A13D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{92770AF3-83EE-49F1-A0BB-79124D19A13D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FB74B9EA-10B9-4542-ACB1-35523A95A587}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FB74B9EA-10B9-4542-ACB1-35523A95A587}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FB74B9EA-10B9-4542-ACB1-35523A95A587}.GlobalNadeko|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FB74B9EA-10B9-4542-ACB1-35523A95A587}.GlobalNadeko|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FB74B9EA-10B9-4542-ACB1-35523A95A587}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FB74B9EA-10B9-4542-ACB1-35523A95A587}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -91,6 +99,7 @@ Global
|
||||
{E685977E-31A4-46F4-A5D7-4E3E39E82E43} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}
|
||||
{92770AF3-83EE-49F1-A0BB-79124D19A13D} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}
|
||||
{2F4CF6D6-0C2F-4944-B204-9508CDA53195} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}
|
||||
{FB74B9EA-10B9-4542-ACB1-35523A95A587} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {5F3F555C-855F-4BE8-B526-D062D3E8ACA4}
|
||||
|
@@ -5,6 +5,5 @@ else {
|
||||
$migrationName = $args[0]
|
||||
dotnet ef migrations add $migrationName -c SqliteContext -p src/NadekoBot/NadekoBot.csproj
|
||||
dotnet ef migrations add $migrationName -c PostgreSqlContext -p src/NadekoBot/NadekoBot.csproj
|
||||
dotnet ef migrations add $migrationName -c MysqlContext -p src/NadekoBot/NadekoBot.csproj
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,3 @@
|
||||
dotnet ef migrations remove -c SqliteContext -f -p src/NadekoBot/NadekoBot.csproj
|
||||
dotnet ef migrations remove -c PostgreSqlContext -f -p src/NadekoBot/NadekoBot.csproj
|
||||
dotnet ef migrations remove -c MysqlContext -f -p src/NadekoBot/NadekoBot.csproj
|
||||
|
||||
|
184
src/NadekoBot.Generators/GrpcApiPermGenerator.cs
Normal file
184
src/NadekoBot.Generators/GrpcApiPermGenerator.cs
Normal file
@@ -0,0 +1,184 @@
|
||||
#nullable enable
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace NadekoBot.Generators
|
||||
{
|
||||
public readonly record struct MethodPermData
|
||||
{
|
||||
public readonly ImmutableArray<(string Name, string Value)> MethodPerms;
|
||||
public readonly ImmutableArray<string> NoAuthRequired;
|
||||
|
||||
public MethodPermData(ImmutableArray<(string Name, string Value)> methodPerms,
|
||||
ImmutableArray<string> noAuthRequired)
|
||||
{
|
||||
MethodPerms = methodPerms;
|
||||
NoAuthRequired = noAuthRequired;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Generator]
|
||||
public class GrpcApiPermGenerator : IIncrementalGenerator
|
||||
{
|
||||
public const string GRPC_API_PERM_ATTRIBUTE =
|
||||
"""
|
||||
namespace NadekoBot.GrpcApi;
|
||||
|
||||
[System.AttributeUsage(System.AttributeTargets.Method)]
|
||||
public class GrpcApiPermAttribute : System.Attribute
|
||||
{
|
||||
public GuildPerm Value { get; }
|
||||
public GrpcApiPermAttribute(GuildPerm value) => Value = value;
|
||||
}
|
||||
""";
|
||||
|
||||
public const string GRPC_NO_AUTH_REQUIRED_ATTRIBUTE =
|
||||
"""
|
||||
namespace NadekoBot.GrpcApi;
|
||||
|
||||
[System.AttributeUsage(System.AttributeTargets.Method)]
|
||||
public class GrpcNoAuthRequiredAttribute : System.Attribute
|
||||
{
|
||||
}
|
||||
""";
|
||||
|
||||
public void Initialize(IncrementalGeneratorInitializationContext context)
|
||||
{
|
||||
context.RegisterPostInitializationOutput(ctx => ctx.AddSource("GrpcApiPermAttribute.cs",
|
||||
SourceText.From(GRPC_API_PERM_ATTRIBUTE, Encoding.UTF8)));
|
||||
|
||||
context.RegisterPostInitializationOutput(ctx => ctx.AddSource("GrpcNoAuthRequiredAttribute.cs",
|
||||
SourceText.From(GRPC_NO_AUTH_REQUIRED_ATTRIBUTE, Encoding.UTF8)));
|
||||
|
||||
var perms = context.SyntaxProvider
|
||||
.ForAttributeWithMetadataName(
|
||||
"NadekoBot.GrpcApi.GrpcApiPermAttribute",
|
||||
predicate: static (s, _) => s is MethodDeclarationSyntax,
|
||||
transform: static (ctx, _) => GetMethodSemanticTargets(ctx.SemanticModel, ctx.TargetNode))
|
||||
.Where(static m => m is not null)
|
||||
.Select(static (x, _) => x!.Value)
|
||||
.Collect();
|
||||
|
||||
|
||||
var all = context.SyntaxProvider
|
||||
.ForAttributeWithMetadataName(
|
||||
"NadekoBot.GrpcApi.GrpcNoAuthRequiredAttribute",
|
||||
predicate: static (s, _) => s is MethodDeclarationSyntax,
|
||||
transform: static (ctx, _) => GetNoAuthMethodName(ctx.SemanticModel, ctx.TargetNode))
|
||||
.Collect()
|
||||
.Combine(perms)
|
||||
.Select((x, _) => new MethodPermData(x.Right, x.Left));
|
||||
|
||||
context.RegisterSourceOutput(all,
|
||||
static (spc, source) => Execute(source, spc));
|
||||
}
|
||||
|
||||
private static string GetNoAuthMethodName(SemanticModel model, SyntaxNode node)
|
||||
=> ((MethodDeclarationSyntax)node).Identifier.Text;
|
||||
|
||||
private static (string Name, string Value)? GetMethodSemanticTargets(SemanticModel model, SyntaxNode node)
|
||||
{
|
||||
var method = (MethodDeclarationSyntax)node;
|
||||
|
||||
var name = method.Identifier.Text;
|
||||
var attr = method.AttributeLists
|
||||
.SelectMany(x => x.Attributes)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (attr is null)
|
||||
return null;
|
||||
|
||||
return (name, attr.ArgumentList?.Arguments[0].ToString() ?? "__missing_perm__");
|
||||
}
|
||||
|
||||
private static void Execute(MethodPermData data, SourceProductionContext ctx)
|
||||
{
|
||||
using (var stringWriter = new StringWriter())
|
||||
using (var sw = new IndentedTextWriter(stringWriter))
|
||||
{
|
||||
sw.WriteLine("using System.Collections.Frozen;");
|
||||
sw.WriteLine();
|
||||
sw.WriteLine("namespace NadekoBot.GrpcApi;");
|
||||
sw.WriteLine();
|
||||
|
||||
sw.WriteLine("public partial class GrpcApiPermsInterceptor");
|
||||
sw.WriteLine("{");
|
||||
|
||||
sw.Indent++;
|
||||
|
||||
sw.WriteLine(
|
||||
"private static FrozenDictionary<string, GuildPerm> _perms = new Dictionary<string, GuildPerm>()");
|
||||
sw.WriteLine("{");
|
||||
|
||||
sw.Indent++;
|
||||
foreach (var field in data.MethodPerms)
|
||||
{
|
||||
sw.WriteLine("{{ \"{0}\", {1} }},", field.Name, field.Value);
|
||||
}
|
||||
|
||||
sw.Indent--;
|
||||
sw.WriteLine("}.ToFrozenDictionary();");
|
||||
|
||||
sw.WriteLine();
|
||||
sw.WriteLine("private static FrozenSet<string> _noAuthRequired = new HashSet<string>()");
|
||||
sw.WriteLine("{");
|
||||
|
||||
sw.Indent++;
|
||||
foreach (var noauth in data.NoAuthRequired)
|
||||
{
|
||||
sw.WriteLine("{{ \"{0}\" }},", noauth);
|
||||
}
|
||||
|
||||
sw.WriteLine("");
|
||||
|
||||
sw.Indent--;
|
||||
sw.WriteLine("}.ToFrozenSet();");
|
||||
|
||||
sw.Indent--;
|
||||
sw.WriteLine("}");
|
||||
|
||||
sw.Flush();
|
||||
ctx.AddSource("GrpcApiInterceptor.g.cs", stringWriter.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private List<TranslationPair> GetFields(string? dataText)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dataText))
|
||||
return new();
|
||||
|
||||
Dictionary<string, string> data;
|
||||
try
|
||||
{
|
||||
var output = JsonConvert.DeserializeObject<Dictionary<string, string>>(dataText!);
|
||||
if (output is null)
|
||||
return new();
|
||||
|
||||
data = output;
|
||||
}
|
||||
catch
|
||||
{
|
||||
Debug.WriteLine("Failed parsing responses file.");
|
||||
return new();
|
||||
}
|
||||
|
||||
var list = new List<TranslationPair>();
|
||||
foreach (var entry in data)
|
||||
{
|
||||
list.Add(new(
|
||||
entry.Key,
|
||||
entry.Value
|
||||
));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
@@ -9,7 +9,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.0.1" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" PrivateAssets="all" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" PrivateAssets="all" GeneratePathProperty="true" />
|
||||
</ItemGroup>
|
||||
|
21
src/NadekoBot.GrpcApiBase/NadekoBot.GrpcApiBase.csproj
Normal file
21
src/NadekoBot.GrpcApiBase/NadekoBot.GrpcApiBase.csproj
Normal file
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Google.Protobuf" Version="3.28.2" />
|
||||
<PackageReference Include="Grpc" Version="2.46.6" />
|
||||
<PackageReference Include="Grpc.Tools" Version="2.66.0" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Protobuf Include="protos/*.proto">
|
||||
<GrpcServices>Server</GrpcServices>
|
||||
</Protobuf>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
47
src/NadekoBot.GrpcApiBase/protos/canvas.proto
Normal file
47
src/NadekoBot.GrpcApiBase/protos/canvas.proto
Normal file
@@ -0,0 +1,47 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option csharp_namespace = "NadekoBot.GrpcApi";
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
|
||||
package ncanvas;
|
||||
|
||||
service GrpcNCanvas {
|
||||
rpc GetCanvas(google.protobuf.Empty) returns (CanvasReply);
|
||||
rpc GetPixel(GetPixelRequest) returns (GetPixelReply);
|
||||
rpc SetPixel(SetPixelRequest) returns (SetPixelReply);
|
||||
}
|
||||
|
||||
message CanvasReply {
|
||||
repeated uint32 pixels = 1;
|
||||
int32 width = 2;
|
||||
int32 height = 3;
|
||||
}
|
||||
|
||||
message GetPixelRequest {
|
||||
int32 x = 1;
|
||||
int32 y = 2;
|
||||
}
|
||||
|
||||
message GetPixelReply {
|
||||
string color = 1;
|
||||
uint32 packedColor = 2;
|
||||
int32 positionX = 3;
|
||||
int32 positionY = 4;
|
||||
int64 price = 5;
|
||||
string text = 6;
|
||||
string position = 7;
|
||||
}
|
||||
|
||||
message SetPixelRequest {
|
||||
string position = 1;
|
||||
string color = 2;
|
||||
string text = 3;
|
||||
int64 price = 4;
|
||||
}
|
||||
|
||||
message SetPixelReply {
|
||||
string error = 1;
|
||||
bool success = 2;
|
||||
optional GetPixelReply pixel = 3;
|
||||
}
|
89
src/NadekoBot.GrpcApiBase/protos/exprs.proto
Normal file
89
src/NadekoBot.GrpcApiBase/protos/exprs.proto
Normal file
@@ -0,0 +1,89 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option csharp_namespace = "NadekoBot.GrpcApi";
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
|
||||
package exprs;
|
||||
|
||||
service GrpcExprs {
|
||||
rpc GetExprs(GetExprsRequest) returns (GetExprsReply);
|
||||
rpc AddExpr(AddExprRequest) returns (AddExprReply);
|
||||
rpc DeleteExpr(DeleteExprRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc GetQuotes(GetQuotesRequest) returns (GetQuotesReply);
|
||||
rpc AddQuote(AddQuoteRequest) returns (AddQuoteReply);
|
||||
rpc DeleteQuote(DeleteQuoteRequest) returns (google.protobuf.Empty);
|
||||
}
|
||||
|
||||
message DeleteExprRequest {
|
||||
string id = 1;
|
||||
uint64 guildId = 2;
|
||||
}
|
||||
|
||||
message GetExprsRequest {
|
||||
uint64 guildId = 1;
|
||||
string query = 2;
|
||||
int32 page = 3;
|
||||
}
|
||||
|
||||
message GetExprsReply {
|
||||
repeated ExprDto expressions = 1;
|
||||
int32 totalCount = 2;
|
||||
}
|
||||
|
||||
message ExprDto {
|
||||
string id = 1;
|
||||
string trigger = 2;
|
||||
string response = 3;
|
||||
|
||||
bool ca = 4;
|
||||
bool ad = 5;
|
||||
bool dm = 6;
|
||||
bool at = 7;
|
||||
}
|
||||
|
||||
message AddExprRequest {
|
||||
uint64 guildId = 1;
|
||||
ExprDto expr = 2;
|
||||
}
|
||||
|
||||
message AddExprReply {
|
||||
string id = 1;
|
||||
bool success = 2;
|
||||
}
|
||||
|
||||
message GetQuotesRequest {
|
||||
uint64 guildId = 1;
|
||||
string query = 2;
|
||||
int32 page = 3;
|
||||
}
|
||||
|
||||
message GetQuotesReply {
|
||||
repeated QuoteDto quotes = 1;
|
||||
int32 totalCount = 2;
|
||||
}
|
||||
|
||||
message QuoteDto {
|
||||
string id = 1;
|
||||
string trigger = 2;
|
||||
string response = 3;
|
||||
|
||||
uint64 authorId = 4;
|
||||
string authorName = 5;
|
||||
}
|
||||
|
||||
message AddQuoteRequest {
|
||||
uint64 guildId = 1;
|
||||
QuoteDto quote = 2;
|
||||
}
|
||||
|
||||
message AddQuoteReply {
|
||||
string id = 1;
|
||||
bool success = 2;
|
||||
}
|
||||
|
||||
message DeleteQuoteRequest {
|
||||
string id = 1;
|
||||
uint64 guildId = 2;
|
||||
}
|
60
src/NadekoBot.GrpcApiBase/protos/fin.proto
Normal file
60
src/NadekoBot.GrpcApiBase/protos/fin.proto
Normal file
@@ -0,0 +1,60 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option csharp_namespace = "NadekoBot.GrpcApi";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
package fin;
|
||||
|
||||
service GrpcFin {
|
||||
rpc GetTransactions(GetTransactionsRequest) returns (GetTransactionsReply);
|
||||
rpc GetHoldings(GetHoldingsRequest) returns (GetHoldingsReply);
|
||||
rpc Withdraw(WithdrawRequest) returns (WithdrawReply);
|
||||
rpc Deposit(DepositRequest) returns (DepositReply);
|
||||
}
|
||||
|
||||
message GetTransactionsRequest {
|
||||
int32 page = 1;
|
||||
uint64 userId = 2;
|
||||
}
|
||||
|
||||
message GetTransactionsReply {
|
||||
repeated TransactionReply transactions = 1;
|
||||
int32 total = 2;
|
||||
}
|
||||
|
||||
message TransactionReply {
|
||||
int64 amount = 1;
|
||||
string note = 2;
|
||||
string type = 3;
|
||||
string extra = 4;
|
||||
google.protobuf.Timestamp timestamp = 5;
|
||||
string id = 6;
|
||||
}
|
||||
|
||||
message GetHoldingsRequest {
|
||||
uint64 userId = 1;
|
||||
}
|
||||
|
||||
message GetHoldingsReply {
|
||||
int64 cash = 1;
|
||||
int64 bank = 2;
|
||||
}
|
||||
|
||||
message WithdrawRequest {
|
||||
uint64 userId = 1;
|
||||
int64 amount = 2;
|
||||
}
|
||||
|
||||
message WithdrawReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message DepositRequest {
|
||||
uint64 userId = 1;
|
||||
int64 amount = 2;
|
||||
}
|
||||
|
||||
message DepositReply {
|
||||
bool success = 1;
|
||||
}
|
51
src/NadekoBot.GrpcApiBase/protos/greet.proto
Normal file
51
src/NadekoBot.GrpcApiBase/protos/greet.proto
Normal file
@@ -0,0 +1,51 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option csharp_namespace = "NadekoBot.GrpcApi";
|
||||
|
||||
package greet;
|
||||
|
||||
service GrpcGreet {
|
||||
rpc GetGreetSettings (GetGreetRequest) returns (GrpcGreetSettings);
|
||||
rpc UpdateGreet (UpdateGreetRequest) returns (UpdateGreetReply);
|
||||
rpc TestGreet (TestGreetRequest) returns (TestGreetReply);
|
||||
}
|
||||
|
||||
message GrpcGreetSettings {
|
||||
string channelId = 1;
|
||||
string message = 2;
|
||||
bool isEnabled = 3;
|
||||
GrpcGreetType type = 4;
|
||||
}
|
||||
|
||||
message GetGreetRequest {
|
||||
uint64 guildId = 1;
|
||||
GrpcGreetType type = 2;
|
||||
}
|
||||
|
||||
message UpdateGreetRequest {
|
||||
uint64 guildId = 1;
|
||||
GrpcGreetSettings settings = 2;
|
||||
}
|
||||
|
||||
enum GrpcGreetType {
|
||||
Greet = 0;
|
||||
GreetDm = 1;
|
||||
Bye = 2;
|
||||
Boost = 3;
|
||||
}
|
||||
|
||||
message UpdateGreetReply {
|
||||
bool Success = 1;
|
||||
}
|
||||
|
||||
message TestGreetRequest {
|
||||
uint64 guildId = 1;
|
||||
uint64 channelId = 2;
|
||||
uint64 userId = 3;
|
||||
GrpcGreetType type = 4;
|
||||
}
|
||||
|
||||
message TestGreetReply {
|
||||
bool success = 1;
|
||||
string error = 2;
|
||||
}
|
144
src/NadekoBot.GrpcApiBase/protos/other.proto
Normal file
144
src/NadekoBot.GrpcApiBase/protos/other.proto
Normal file
@@ -0,0 +1,144 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option csharp_namespace = "NadekoBot.GrpcApi";
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
|
||||
package other;
|
||||
|
||||
service GrpcOther {
|
||||
rpc BotOnGuild(BotOnGuildRequest) returns (BotOnGuildReply);
|
||||
rpc GetTextChannels(GetTextChannelsRequest) returns (GetTextChannelsReply);
|
||||
rpc GetRoles(GetRolesRequest) returns (GetRolesReply);
|
||||
|
||||
rpc GetCurrencyLb(GetLbRequest) returns (CurrencyLbReply);
|
||||
rpc GetXpLb(GetLbRequest) returns (XpLbReply);
|
||||
rpc GetWaifuLb(GetLbRequest) returns (WaifuLbReply);
|
||||
|
||||
rpc GetShardStats(google.protobuf.Empty) returns (stream ShardStatsReply);
|
||||
rpc GetCommandFeed(google.protobuf.Empty) returns (stream CommandFeedEntry);
|
||||
rpc GetServerInfo(ServerInfoRequest) returns (GetServerInfoReply);
|
||||
}
|
||||
|
||||
message CommandFeedEntry {
|
||||
string command = 1;
|
||||
}
|
||||
|
||||
message GetRolesRequest {
|
||||
uint64 guildId = 1;
|
||||
}
|
||||
|
||||
message GetRolesReply {
|
||||
repeated RoleReply roles = 1;
|
||||
}
|
||||
|
||||
message BotOnGuildRequest {
|
||||
uint64 guildId = 1;
|
||||
}
|
||||
|
||||
message BotOnGuildReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message ShardStatsReply {
|
||||
int32 id = 1;
|
||||
string status = 2;
|
||||
|
||||
int32 guildCount = 3;
|
||||
string uptime = 4;
|
||||
int64 commands = 5;
|
||||
}
|
||||
|
||||
message GetTextChannelsRequest{
|
||||
uint64 guildId = 1;
|
||||
}
|
||||
|
||||
message GetTextChannelsReply {
|
||||
repeated TextChannelReply textChannels = 1;
|
||||
}
|
||||
|
||||
message TextChannelReply {
|
||||
uint64 id = 1;
|
||||
string name = 2;
|
||||
}
|
||||
|
||||
message CurrencyLbReply {
|
||||
repeated CurrencyLbEntryReply entries = 1;
|
||||
}
|
||||
|
||||
message CurrencyLbEntryReply {
|
||||
string user = 1;
|
||||
uint64 userId = 2;
|
||||
int64 amount = 3;
|
||||
string avatar = 4;
|
||||
}
|
||||
|
||||
message GetLbRequest {
|
||||
int32 page = 1;
|
||||
int32 perPage = 2;
|
||||
}
|
||||
|
||||
message XpLbReply {
|
||||
repeated XpLbEntryReply entries = 1;
|
||||
}
|
||||
|
||||
message XpLbEntryReply {
|
||||
string user = 1;
|
||||
uint64 userId = 2;
|
||||
int64 totalXp = 3;
|
||||
int64 level = 4;
|
||||
}
|
||||
|
||||
message WaifuLbReply {
|
||||
repeated WaifuLbEntry entries = 1;
|
||||
}
|
||||
|
||||
message WaifuLbEntry {
|
||||
string user = 1;
|
||||
string claimedBy = 2;
|
||||
int64 value = 3;
|
||||
bool isMutual = 4;
|
||||
}
|
||||
|
||||
message ServerInfoRequest {
|
||||
uint64 guildId = 1;
|
||||
}
|
||||
|
||||
message GetServerInfoReply {
|
||||
uint64 id = 1;
|
||||
string name = 2;
|
||||
string iconUrl = 3;
|
||||
uint64 ownerId = 4;
|
||||
string ownerName = 5;
|
||||
repeated RoleReply roles = 6;
|
||||
repeated EmojiReply emojis = 7;
|
||||
repeated string features = 8;
|
||||
int32 textChannels = 9;
|
||||
int32 voiceChannels = 10;
|
||||
int32 memberCount = 11;
|
||||
int64 createdAt = 12;
|
||||
}
|
||||
|
||||
message RoleReply {
|
||||
uint64 id = 1;
|
||||
string name = 2;
|
||||
string iconUrl = 3;
|
||||
string color = 4;
|
||||
}
|
||||
|
||||
message EmojiReply {
|
||||
string name = 1;
|
||||
string url = 2;
|
||||
string code = 3;
|
||||
}
|
||||
|
||||
message ChannelReply {
|
||||
uint64 id = 1;
|
||||
string name = 2;
|
||||
ChannelType type = 3;
|
||||
}
|
||||
|
||||
enum ChannelType {
|
||||
Text = 0;
|
||||
Voice = 1;
|
||||
}
|
107
src/NadekoBot.GrpcApiBase/protos/warn.proto
Normal file
107
src/NadekoBot.GrpcApiBase/protos/warn.proto
Normal file
@@ -0,0 +1,107 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option csharp_namespace = "NadekoBot.GrpcApi";
|
||||
|
||||
package warn;
|
||||
|
||||
service GrpcWarn {
|
||||
rpc GetWarnSettings (WarnSettingsRequest) returns (WarnSettingsReply);
|
||||
|
||||
rpc SetWarnExpiry(SetWarnExpiryRequest) returns (SetWarnExpiryReply);
|
||||
rpc AddWarnp (AddWarnpRequest) returns (AddWarnpReply);
|
||||
rpc DeleteWarnp (DeleteWarnpRequest) returns (DeleteWarnpReply);
|
||||
|
||||
rpc GetLatestWarnings(GetLatestWarningsRequest) returns (GetLatestWarningsReply);
|
||||
rpc GetUserWarnings(GetUserWarningsRequest) returns (GetUserWarningsReply);
|
||||
|
||||
rpc ForgiveWarning(ForgiveWarningRequest) returns (ForgiveWarningReply);
|
||||
rpc DeleteWarning(ForgiveWarningRequest) returns (ForgiveWarningReply);
|
||||
|
||||
}
|
||||
message WarnSettingsRequest {
|
||||
uint64 guildId = 1;
|
||||
}
|
||||
|
||||
message WarnPunishment {
|
||||
int32 threshold = 1;
|
||||
string action = 2;
|
||||
int32 duration = 3;
|
||||
string role = 4;
|
||||
}
|
||||
|
||||
message WarnSettingsReply {
|
||||
repeated WarnPunishment punishments = 1;
|
||||
int32 expiryDays = 2;
|
||||
bool deleteOnExpire = 3;
|
||||
}
|
||||
|
||||
message AddWarnpRequest {
|
||||
uint64 guildId = 1;
|
||||
WarnPunishment punishment = 2;
|
||||
}
|
||||
|
||||
message AddWarnpReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message DeleteWarnpRequest {
|
||||
uint64 guildId = 1;
|
||||
int32 threshold = 2;
|
||||
}
|
||||
|
||||
message DeleteWarnpReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message GetUserWarningsRequest {
|
||||
uint64 guildId = 1;
|
||||
string user = 2;
|
||||
int32 page = 3;
|
||||
}
|
||||
|
||||
message GetUserWarningsReply {
|
||||
repeated Warning warnings = 1;
|
||||
int32 totalCount = 2;
|
||||
}
|
||||
|
||||
message Warning {
|
||||
string id = 1;
|
||||
string reason = 2;
|
||||
int64 timestamp = 3;
|
||||
int64 weight = 4;
|
||||
bool forgiven = 5;
|
||||
string forgivenBy = 6;
|
||||
string user = 7;
|
||||
uint64 userId = 8;
|
||||
string moderator = 9;
|
||||
}
|
||||
|
||||
message ForgiveWarningRequest {
|
||||
uint64 guildId = 1;
|
||||
string warnId = 2;
|
||||
string modName = 3;
|
||||
}
|
||||
|
||||
message ForgiveWarningReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message SetWarnExpiryRequest {
|
||||
uint64 guildId = 1;
|
||||
int32 expiryDays = 2;
|
||||
bool deleteOnExpire = 3;
|
||||
}
|
||||
|
||||
message SetWarnExpiryReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message GetLatestWarningsRequest {
|
||||
uint64 guildId = 1;
|
||||
int32 page = 2;
|
||||
}
|
||||
|
||||
message GetLatestWarningsReply {
|
||||
repeated Warning warnings = 1;
|
||||
int32 totalCount = 2;
|
||||
}
|
108
src/NadekoBot.GrpcApiBase/protos/xp.proto
Normal file
108
src/NadekoBot.GrpcApiBase/protos/xp.proto
Normal file
@@ -0,0 +1,108 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option csharp_namespace = "NadekoBot.GrpcApi";
|
||||
|
||||
package xp;
|
||||
|
||||
service GrpcXp {
|
||||
rpc GetXpLb(GetXpLbRequest) returns (GetXpLbReply);
|
||||
rpc ResetUserXp(ResetUserXpRequest) returns (ResetUserXpReply);
|
||||
|
||||
rpc GetXpSettings(GetXpSettingsRequest) returns (GetXpSettingsReply);
|
||||
|
||||
rpc AddExclusion(AddExclusionRequest) returns (AddExclusionReply);
|
||||
rpc DeleteExclusion(DeleteExclusionRequest) returns (DeleteExclusionReply);
|
||||
|
||||
rpc AddReward(AddRewardRequest) returns (AddRewardReply);
|
||||
rpc DeleteReward(DeleteRewardRequest) returns (DeleteRewardReply);
|
||||
}
|
||||
|
||||
message GetXpLbRequest {
|
||||
uint64 guildId = 1;
|
||||
int32 page = 2;
|
||||
}
|
||||
|
||||
message GetXpLbReply {
|
||||
repeated XpLbUserReply users = 1;
|
||||
int32 total = 2;
|
||||
}
|
||||
|
||||
message XpLbUserReply {
|
||||
uint64 userId = 1;
|
||||
string username = 2;
|
||||
int64 xp = 3;
|
||||
int64 level = 4;
|
||||
string avatar = 5;
|
||||
}
|
||||
|
||||
message ResetUserXpRequest {
|
||||
uint64 guildId = 1;
|
||||
uint64 userId = 2;
|
||||
}
|
||||
|
||||
message ResetUserXpReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message GetXpSettingsReply {
|
||||
repeated ExclItemReply exclusions = 1;
|
||||
repeated RewItemReply rewards = 2;
|
||||
bool serverExcluded = 3;
|
||||
}
|
||||
|
||||
message GetXpSettingsRequest {
|
||||
uint64 guildId = 1;
|
||||
}
|
||||
|
||||
message ExclItemReply {
|
||||
string type = 1;
|
||||
uint64 id = 2;
|
||||
string name = 3;
|
||||
}
|
||||
|
||||
message RewItemReply {
|
||||
int32 level = 1;
|
||||
string type = 2;
|
||||
string value = 3;
|
||||
}
|
||||
|
||||
message AddExclusionRequest {
|
||||
uint64 guildId = 1;
|
||||
string type = 2;
|
||||
uint64 id = 3;
|
||||
}
|
||||
|
||||
message AddExclusionReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message DeleteExclusionRequest {
|
||||
uint64 guildId = 1;
|
||||
string type = 2;
|
||||
uint64 id = 3;
|
||||
}
|
||||
|
||||
message DeleteExclusionReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message AddRewardRequest {
|
||||
uint64 guildId = 1;
|
||||
int32 level = 2;
|
||||
string type = 3;
|
||||
string value = 4;
|
||||
}
|
||||
|
||||
message AddRewardReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message DeleteRewardRequest {
|
||||
uint64 guildId = 1;
|
||||
int32 level = 2;
|
||||
string type = 3;
|
||||
}
|
||||
|
||||
message DeleteRewardReply {
|
||||
bool success = 1;
|
||||
}
|
@@ -1,76 +0,0 @@
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Nadeko.Common;
|
||||
using NadekoBot.Services;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace NadekoBot.Tests
|
||||
{
|
||||
public class GroupGreetTests
|
||||
{
|
||||
private GreetGrouper<int> _grouper;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
=> _grouper = new GreetGrouper<int>();
|
||||
|
||||
[Test]
|
||||
public void CreateTest()
|
||||
{
|
||||
var created = _grouper.CreateOrAdd(0, 5);
|
||||
|
||||
Assert.True(created);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateClearTest()
|
||||
{
|
||||
_grouper.CreateOrAdd(0, 5);
|
||||
_grouper.ClearGroup(0, 5, out var items);
|
||||
|
||||
Assert.AreEqual(0, items.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NotCreatedTest()
|
||||
{
|
||||
_grouper.CreateOrAdd(0, 5);
|
||||
var created = _grouper.CreateOrAdd(0, 4);
|
||||
|
||||
Assert.False(created);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ClearAddedTest()
|
||||
{
|
||||
_grouper.CreateOrAdd(0, 5);
|
||||
_grouper.CreateOrAdd(0, 4);
|
||||
_grouper.ClearGroup(0, 5, out var items);
|
||||
|
||||
var list = items.ToList();
|
||||
|
||||
Assert.AreEqual(1, list.Count, $"Count was {list.Count}");
|
||||
Assert.AreEqual(4, list[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ClearManyTest()
|
||||
{
|
||||
_grouper.CreateOrAdd(0, 5);
|
||||
|
||||
// add 15 items
|
||||
await Enumerable.Range(10, 15)
|
||||
.Select(x => Task.Run(() => _grouper.CreateOrAdd(0, x))).WhenAll();
|
||||
|
||||
// get 5 at most
|
||||
_grouper.ClearGroup(0, 5, out var items);
|
||||
var list = items.ToList();
|
||||
Assert.AreEqual(5, list.Count, $"Count was {list.Count}");
|
||||
|
||||
// try to get 15, but there should be 10 left
|
||||
_grouper.ClearGroup(0, 15, out items);
|
||||
list = items.ToList();
|
||||
Assert.AreEqual(10, list.Count, $"Count was {list.Count}");
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
#nullable disable
|
||||
using DryIoc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NadekoBot.Common.Configs;
|
||||
@@ -24,7 +25,7 @@ public sealed class Bot : IBot
|
||||
public bool IsReady { get; private set; }
|
||||
public int ShardId { get; set; }
|
||||
|
||||
private readonly IBotCredentials _creds;
|
||||
private readonly IBotCreds _creds;
|
||||
private readonly CommandService _commandService;
|
||||
private readonly DbService _db;
|
||||
|
||||
@@ -41,6 +42,9 @@ public sealed class Bot : IBot
|
||||
_credsProvider = new BotCredsProvider(totalShards, credPath);
|
||||
_creds = _credsProvider.GetCreds();
|
||||
|
||||
LogSetup.SetupLogger(shardId, _creds);
|
||||
Log.Information("Pid: {ProcessId}", Environment.ProcessId);
|
||||
|
||||
_db = new NadekoDbService(_credsProvider);
|
||||
|
||||
var messageCacheSize =
|
||||
@@ -88,18 +92,18 @@ public sealed class Bot : IBot
|
||||
|
||||
|
||||
public IReadOnlyList<ulong> GetCurrentGuildIds()
|
||||
=> Client.Guilds.Select(x => x.Id).ToList().ToList();
|
||||
=> Client.Guilds.Select(x => x.Id).ToList().AsReadOnly();
|
||||
|
||||
private void AddServices()
|
||||
private async Task AddServices()
|
||||
{
|
||||
var startingGuildIdList = GetCurrentGuildIds();
|
||||
var startingGuildIdList = GetCurrentGuildIds().ToList();
|
||||
var startTime = Stopwatch.GetTimestamp();
|
||||
var bot = Client.CurrentUser;
|
||||
|
||||
using (var uow = _db.GetDbContext())
|
||||
await using (var uow = _db.GetDbContext())
|
||||
{
|
||||
AllGuildConfigs = await uow.GuildConfigs.GetAllGuildConfigs(startingGuildIdList);
|
||||
uow.EnsureUserCreated(bot.Id, bot.Username, bot.Discriminator, bot.AvatarId);
|
||||
AllGuildConfigs = uow.Set<GuildConfig>().GetAllGuildConfigs(startingGuildIdList).ToImmutableArray();
|
||||
}
|
||||
|
||||
// var svcs = new StandardKernel(new NinjectSettings()
|
||||
@@ -114,7 +118,7 @@ public sealed class Bot : IBot
|
||||
// svcs.Components.Remove<IPlanner, Planner>();
|
||||
// svcs.Components.Add<IPlanner, RemovablePlanner>();
|
||||
|
||||
svcs.AddSingleton<IBotCredentials>(_ => _credsProvider.GetCreds());
|
||||
svcs.AddSingleton<IBotCreds>(_ => _credsProvider.GetCreds());
|
||||
svcs.AddSingleton<DbService, DbService>(_db);
|
||||
svcs.AddSingleton<IBotCredsProvider>(_credsProvider);
|
||||
svcs.AddSingleton<DiscordSocketClient>(Client);
|
||||
@@ -161,7 +165,8 @@ public sealed class Bot : IBot
|
||||
LoadTypeReaders(a);
|
||||
}
|
||||
|
||||
Log.Information("All services loaded in {ServiceLoadTime:F2}s", Stopwatch.GetElapsedTime(startTime) .TotalSeconds);
|
||||
Log.Information("All services loaded in {ServiceLoadTime:F2}s",
|
||||
Stopwatch.GetElapsedTime(startTime).TotalSeconds);
|
||||
}
|
||||
|
||||
private void LoadTypeReaders(Assembly assembly)
|
||||
@@ -265,7 +270,7 @@ public sealed class Bot : IBot
|
||||
Log.Information("Shard {ShardId} loading services...", Client.ShardId);
|
||||
try
|
||||
{
|
||||
AddServices();
|
||||
await AddServices();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -273,7 +278,9 @@ public sealed class Bot : IBot
|
||||
Helpers.ReadErrorAndExit(9);
|
||||
}
|
||||
|
||||
Log.Information("Shard {ShardId} connected in {Elapsed:F2}s", Client.ShardId, Stopwatch.GetElapsedTime(startTime).TotalSeconds);
|
||||
Log.Information("Shard {ShardId} connected in {Elapsed:F2}s",
|
||||
Client.ShardId,
|
||||
Stopwatch.GetElapsedTime(startTime).TotalSeconds);
|
||||
var commandHandler = Services.GetRequiredService<CommandHandler>();
|
||||
|
||||
// start handling messages received in commandhandler
|
||||
|
@@ -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
|
||||
@@ -88,13 +85,6 @@ public static class DiscordUserExtensions
|
||||
.Count()
|
||||
+ 1;
|
||||
|
||||
public static async Task<IReadOnlyCollection<DiscordUser>> GetUsersXpLeaderboardFor(this DbSet<DiscordUser> users, int page, int perPage)
|
||||
=> await users.ToLinqToDBTable()
|
||||
.OrderByDescending(x => x.TotalXp)
|
||||
.Skip(page * perPage)
|
||||
.Take(perPage)
|
||||
.ToArrayAsyncLinqToDB();
|
||||
|
||||
public static Task<List<DiscordUser>> GetTopRichest(
|
||||
this DbSet<DiscordUser> users,
|
||||
ulong botId,
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#nullable disable
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Db.Models;
|
||||
|
||||
@@ -42,19 +43,27 @@ public static class GuildConfigExtensions
|
||||
}
|
||||
|
||||
private static IQueryable<GuildConfig> IncludeEverything(this DbSet<GuildConfig> configs)
|
||||
=> configs.AsQueryable()
|
||||
=> configs
|
||||
.AsSplitQuery()
|
||||
.Include(gc => gc.CommandCooldowns)
|
||||
.Include(gc => gc.FollowedStreams)
|
||||
.Include(gc => gc.StreamRole)
|
||||
.Include(gc => gc.DelMsgOnCmdChannels)
|
||||
.Include(gc => gc.XpSettings)
|
||||
.ThenInclude(x => x.ExclusionList)
|
||||
.Include(gc => gc.DelMsgOnCmdChannels);
|
||||
.ThenInclude(x => x.ExclusionList);
|
||||
|
||||
public static IEnumerable<GuildConfig> GetAllGuildConfigs(
|
||||
public static async Task<GuildConfig[]> GetAllGuildConfigs(
|
||||
this DbSet<GuildConfig> configs,
|
||||
IReadOnlyList<ulong> availableGuilds)
|
||||
=> configs.IncludeEverything().AsNoTracking().Where(x => availableGuilds.Contains(x.GuildId)).ToList();
|
||||
List<ulong> availableGuilds)
|
||||
{
|
||||
var result = await configs
|
||||
.IncludeEverything()
|
||||
.Where(x => availableGuilds.Contains(x.GuildId))
|
||||
.AsNoTracking()
|
||||
.ToArrayAsync();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and creates if it doesn't exist a config for a guild.
|
||||
@@ -80,12 +89,12 @@ public static class GuildConfigExtensions
|
||||
|
||||
if (config is null)
|
||||
{
|
||||
ctx.Set<GuildConfig>().Add(config = new()
|
||||
ctx.Set<GuildConfig>()
|
||||
.Add(config = new()
|
||||
{
|
||||
GuildId = guildId,
|
||||
Permissions = Permissionv2.GetDefaultPermlist,
|
||||
WarningsInitialized = true,
|
||||
WarnPunishments = DefaultWarnPunishments
|
||||
});
|
||||
ctx.SaveChanges();
|
||||
}
|
||||
@@ -93,7 +102,6 @@ public static class GuildConfigExtensions
|
||||
if (!config.WarningsInitialized)
|
||||
{
|
||||
config.WarningsInitialized = true;
|
||||
config.WarnPunishments = DefaultWarnPunishments;
|
||||
}
|
||||
|
||||
return config;
|
||||
@@ -149,14 +157,16 @@ public static class GuildConfigExtensions
|
||||
|
||||
public static GuildConfig GcWithPermissionsFor(this DbContext ctx, ulong guildId)
|
||||
{
|
||||
var config = ctx.Set<GuildConfig>().AsQueryable()
|
||||
var config = ctx.Set<GuildConfig>()
|
||||
.AsQueryable()
|
||||
.Where(gc => gc.GuildId == guildId)
|
||||
.Include(gc => gc.Permissions)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (config is null) // if there is no guildconfig, create new one
|
||||
{
|
||||
ctx.Set<GuildConfig>().Add(config = new()
|
||||
ctx.Set<GuildConfig>()
|
||||
.Add(config = new()
|
||||
{
|
||||
GuildId = guildId,
|
||||
Permissions = Permissionv2.GetDefaultPermlist
|
||||
|
@@ -1,53 +0,0 @@
|
||||
#nullable disable
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Db.Models;
|
||||
|
||||
namespace NadekoBot.Db;
|
||||
|
||||
public static class QuoteExtensions
|
||||
{
|
||||
public static IEnumerable<Quote> GetForGuild(this DbSet<Quote> quotes, ulong guildId)
|
||||
=> quotes.AsQueryable().Where(x => x.GuildId == guildId);
|
||||
|
||||
public static IReadOnlyCollection<Quote> GetGroup(
|
||||
this DbSet<Quote> quotes,
|
||||
ulong guildId,
|
||||
int page,
|
||||
OrderType order)
|
||||
{
|
||||
var q = quotes.AsQueryable().Where(x => x.GuildId == guildId);
|
||||
if (order == OrderType.Keyword)
|
||||
q = q.OrderBy(x => x.Keyword);
|
||||
else
|
||||
q = q.OrderBy(x => x.Id);
|
||||
|
||||
return q.Skip(15 * page).Take(15).ToArray();
|
||||
}
|
||||
|
||||
public static async Task<Quote> GetRandomQuoteByKeywordAsync(
|
||||
this DbSet<Quote> quotes,
|
||||
ulong guildId,
|
||||
string keyword)
|
||||
{
|
||||
return (await quotes.AsQueryable().Where(q => q.GuildId == guildId && q.Keyword == keyword).ToArrayAsync())
|
||||
.RandomOrDefault();
|
||||
}
|
||||
|
||||
public static async Task<Quote> SearchQuoteKeywordTextAsync(
|
||||
this DbSet<Quote> quotes,
|
||||
ulong guildId,
|
||||
string keyword,
|
||||
string text)
|
||||
{
|
||||
return (await quotes.AsQueryable()
|
||||
.Where(q => q.GuildId == guildId
|
||||
&& (keyword == null || q.Keyword == keyword)
|
||||
&& (EF.Functions.Like(q.Text.ToUpper(), $"%{text.ToUpper()}%")
|
||||
|| EF.Functions.Like(q.AuthorName, text)))
|
||||
.ToArrayAsync())
|
||||
.RandomOrDefault();
|
||||
}
|
||||
|
||||
public static void RemoveAllByKeyword(this DbSet<Quote> quotes, ulong guildId, string keyword)
|
||||
=> quotes.RemoveRange(quotes.AsQueryable().Where(x => x.GuildId == guildId && x.Keyword.ToUpper() == keyword));
|
||||
}
|
@@ -26,17 +26,6 @@ public static class UserXpExtensions
|
||||
return usr;
|
||||
}
|
||||
|
||||
public static async Task<IReadOnlyCollection<UserXpStats>> GetUsersFor(
|
||||
this DbSet<UserXpStats> xps,
|
||||
ulong guildId,
|
||||
int page)
|
||||
=> await xps.ToLinqToDBTable()
|
||||
.Where(x => x.GuildId == guildId)
|
||||
.OrderByDescending(x => x.Xp + x.AwardedXp)
|
||||
.Skip(page * 9)
|
||||
.Take(9)
|
||||
.ToArrayAsyncLinqToDB();
|
||||
|
||||
public static async Task<List<UserXpStats>> GetTopUserXps(this DbSet<UserXpStats> xps, ulong guildId, int count)
|
||||
=> await xps.ToLinqToDBTable()
|
||||
.Where(x => x.GuildId == guildId)
|
||||
@@ -55,9 +44,6 @@ public static class UserXpExtensions
|
||||
.CountAsyncLinqToDB()
|
||||
+ 1;
|
||||
|
||||
public static void ResetGuildUserXp(this DbSet<UserXpStats> xps, ulong userId, ulong guildId)
|
||||
=> xps.Delete(x => x.UserId == userId && x.GuildId == guildId);
|
||||
|
||||
public static void ResetGuildXp(this DbSet<UserXpStats> xps, ulong guildId)
|
||||
=> xps.Delete(x => x.GuildId == guildId);
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
8
src/NadekoBot/Db/Models/FlagTranslateChannel.cs
Normal file
8
src/NadekoBot/Db/Models/FlagTranslateChannel.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Db.Models;
|
||||
|
||||
public class FlagTranslateChannel : DbEntity
|
||||
{
|
||||
public ulong GuildId { get; set; }
|
||||
public ulong ChannelId { get; set; }
|
||||
}
|
@@ -13,21 +13,23 @@ public class GuildConfig : DbEntity
|
||||
|
||||
public string AutoAssignRoleIds { get; set; }
|
||||
|
||||
//greet stuff
|
||||
public int AutoDeleteGreetMessagesTimer { get; set; } = 30;
|
||||
public int AutoDeleteByeMessagesTimer { get; set; } = 30;
|
||||
|
||||
public ulong GreetMessageChannelId { get; set; }
|
||||
public ulong ByeMessageChannelId { get; set; }
|
||||
|
||||
public bool SendDmGreetMessage { get; set; }
|
||||
public string DmGreetMessageText { get; set; } = "Welcome to the %server% server, %user%!";
|
||||
|
||||
public bool SendChannelGreetMessage { get; set; }
|
||||
public string ChannelGreetMessageText { get; set; } = "Welcome to the %server% server, %user%!";
|
||||
|
||||
public bool SendChannelByeMessage { get; set; }
|
||||
public string ChannelByeMessageText { get; set; } = "%user% has left!";
|
||||
// //greet stuff
|
||||
// public int AutoDeleteGreetMessagesTimer { get; set; } = 30;
|
||||
// public int AutoDeleteByeMessagesTimer { get; set; } = 30;
|
||||
//
|
||||
// public ulong GreetMessageChannelId { get; set; }
|
||||
// public ulong ByeMessageChannelId { get; set; }
|
||||
//
|
||||
// public bool SendDmGreetMessage { get; set; }
|
||||
// public string DmGreetMessageText { get; set; } = "Welcome to the %server% server, %user%!";
|
||||
//
|
||||
// public bool SendChannelGreetMessage { get; set; }
|
||||
// public string ChannelGreetMessageText { get; set; } = "Welcome to the %server% server, %user%!";
|
||||
//
|
||||
// public bool SendChannelByeMessage { get; set; }
|
||||
// public string ChannelByeMessageText { get; set; } = "%user% has left!";
|
||||
// public bool SendBoostMessage { get; set; }
|
||||
// pulic int BoostMessageDeleteAfter { get; set; }
|
||||
|
||||
//self assignable roles
|
||||
public bool ExclusiveSelfAssignedRoles { get; set; }
|
||||
@@ -75,7 +77,6 @@ public class GuildConfig : DbEntity
|
||||
public HashSet<UnroleTimer> UnroleTimer { get; set; } = new();
|
||||
public HashSet<VcRoleInfo> VcRoleInfos { get; set; }
|
||||
public HashSet<CommandAlias> CommandAliases { get; set; } = new();
|
||||
public List<WarningPunishment> WarnPunishments { get; set; } = new();
|
||||
public bool WarningsInitialized { get; set; }
|
||||
public HashSet<SlowmodeIgnoredUser> SlowmodeIgnoredUsers { get; set; }
|
||||
public HashSet<SlowmodeIgnoredRole> SlowmodeIgnoredRoles { get; set; }
|
||||
@@ -98,10 +99,6 @@ public class GuildConfig : DbEntity
|
||||
|
||||
#region Boost Message
|
||||
|
||||
public bool SendBoostMessage { get; set; }
|
||||
public string BoostMessage { get; set; } = "%user% just boosted this server!";
|
||||
public ulong BoostMessageChannelId { get; set; }
|
||||
public int BoostMessageDeleteAfter { get; set; }
|
||||
public bool StickyRoles { get; set; }
|
||||
|
||||
#endregion
|
||||
|
19
src/NadekoBot/Db/Models/NCanvas/NCanvas.cs
Normal file
19
src/NadekoBot/Db/Models/NCanvas/NCanvas.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace NadekoBot.Db.Models;
|
||||
|
||||
public class NCPixel
|
||||
{
|
||||
[Key]
|
||||
public int Id { get; set; }
|
||||
|
||||
public required int Position { get; init; }
|
||||
|
||||
public required long Price { get; init; }
|
||||
|
||||
public required ulong OwnerId { get; init; }
|
||||
public required uint Color { get; init; }
|
||||
|
||||
[MaxLength(256)]
|
||||
public required string Text { get; init; }
|
||||
}
|
@@ -3,6 +3,7 @@ namespace NadekoBot.Db.Models;
|
||||
|
||||
public class WarningPunishment : DbEntity
|
||||
{
|
||||
public ulong GuildId { get; set; }
|
||||
public int Count { get; set; }
|
||||
public PunishmentAction Punishment { get; set; }
|
||||
public int Time { get; set; }
|
||||
|
@@ -9,5 +9,3 @@ public class UserXpStats : DbEntity
|
||||
public long AwardedXp { get; set; }
|
||||
public XpNotificationLocation NotifyOnLevelUp { get; set; }
|
||||
}
|
||||
|
||||
public enum XpNotificationLocation { None, Dm, Channel }
|
8
src/NadekoBot/Db/Models/xp/XpNotificationLocation.cs
Normal file
8
src/NadekoBot/Db/Models/xp/XpNotificationLocation.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace NadekoBot.Db.Models;
|
||||
|
||||
public enum XpNotificationLocation
|
||||
{
|
||||
None,
|
||||
Dm,
|
||||
Channel
|
||||
}
|
@@ -1,38 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Db.Models;
|
||||
|
||||
namespace NadekoBot.Db;
|
||||
|
||||
public sealed class MysqlContext : NadekoContext
|
||||
{
|
||||
private readonly string _connStr;
|
||||
private readonly string _version;
|
||||
|
||||
protected override string CurrencyTransactionOtherIdDefaultValue
|
||||
=> "NULL";
|
||||
|
||||
public MysqlContext(string connStr = "Server=localhost", string version = "8.0")
|
||||
{
|
||||
_connStr = connStr;
|
||||
_version = version;
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
base.OnConfiguring(optionsBuilder);
|
||||
optionsBuilder
|
||||
.UseLowerCaseNamingConvention()
|
||||
.UseMySql(_connStr, ServerVersion.Parse(_version));
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
// mysql is case insensitive by default
|
||||
// we can set binary collation to change that
|
||||
modelBuilder.Entity<ClubInfo>()
|
||||
.Property(x => x.Name)
|
||||
.UseCollation("utf8mb4_bin");
|
||||
}
|
||||
}
|
@@ -10,6 +10,7 @@ namespace NadekoBot.Db;
|
||||
public abstract class NadekoContext : DbContext
|
||||
{
|
||||
public DbSet<GuildConfig> GuildConfigs { get; set; }
|
||||
public DbSet<GreetSettings> GreetSettings { get; set; }
|
||||
|
||||
public DbSet<Quote> Quotes { get; set; }
|
||||
public DbSet<Reminder> Reminders { get; set; }
|
||||
@@ -61,7 +62,6 @@ public abstract class NadekoContext : DbContext
|
||||
public DbSet<ArchivedTodoListModel> TodosArchive { get; set; }
|
||||
public DbSet<HoneypotChannel> HoneyPotChannels { get; set; }
|
||||
|
||||
// todo add guild colors
|
||||
// public DbSet<GuildColors> GuildColors { get; set; }
|
||||
|
||||
|
||||
@@ -73,6 +73,24 @@ public abstract class NadekoContext : DbContext
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
#region Flag Translate
|
||||
|
||||
modelBuilder.Entity<FlagTranslateChannel>()
|
||||
.HasIndex(x => new { x.GuildId, x.ChannelId })
|
||||
.IsUnique();
|
||||
|
||||
#endregion
|
||||
|
||||
#region NCanvas
|
||||
|
||||
modelBuilder.Entity<NCPixel>()
|
||||
.HasAlternateKey(x => x.Position);
|
||||
|
||||
modelBuilder.Entity<NCPixel>()
|
||||
.HasIndex(x => x.OwnerId);
|
||||
|
||||
#endregion
|
||||
|
||||
#region QUOTES
|
||||
|
||||
var quoteEntity = modelBuilder.Entity<Quote>();
|
||||
@@ -194,11 +212,6 @@ public abstract class NadekoContext : DbContext
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.WarnPunishments)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.SlowmodeIgnoredRoles)
|
||||
.WithOne()
|
||||
@@ -276,6 +289,18 @@ public abstract class NadekoContext : DbContext
|
||||
|
||||
#endregion
|
||||
|
||||
#region WarningPunishments
|
||||
|
||||
var warnpunishmentEntity = modelBuilder.Entity<WarningPunishment>(b =>
|
||||
{
|
||||
b.HasAlternateKey(x => new
|
||||
{
|
||||
x.GuildId,
|
||||
x.Count
|
||||
});
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
#region Self Assignable Roles
|
||||
|
||||
@@ -338,6 +363,7 @@ public abstract class NadekoContext : DbContext
|
||||
du.HasIndex(x => x.TotalXp);
|
||||
du.HasIndex(x => x.CurrencyAmount);
|
||||
du.HasIndex(x => x.UserId);
|
||||
du.HasIndex(x => x.Username);
|
||||
});
|
||||
|
||||
#endregion
|
||||
@@ -678,6 +704,29 @@ public abstract class NadekoContext : DbContext
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
#endregion
|
||||
|
||||
#region GreetSettings
|
||||
|
||||
modelBuilder
|
||||
.Entity<GreetSettings>(gs => gs.HasIndex(x => new
|
||||
{
|
||||
x.GuildId,
|
||||
x.GreetType
|
||||
})
|
||||
.IsUnique());
|
||||
|
||||
modelBuilder.Entity<GreetSettings>(gs =>
|
||||
{
|
||||
gs
|
||||
.Property(x => x.IsEnabled)
|
||||
.HasDefaultValue(false);
|
||||
|
||||
gs
|
||||
.Property(x => x.AutoDeleteTimer)
|
||||
.HasDefaultValue(0);
|
||||
});
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
@@ -44,8 +44,6 @@ public sealed class NadekoDbService : DbService
|
||||
case "postgres":
|
||||
case "pgsql":
|
||||
return new PostgreSqlContext(connString);
|
||||
case "mysql":
|
||||
return new MysqlContext(connString);
|
||||
case "sqlite":
|
||||
return new SqliteContext(connString);
|
||||
default:
|
||||
|
@@ -5,18 +5,14 @@ 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.IsMySql())
|
||||
{
|
||||
migrationBuilder.Sql(
|
||||
@"INSERT IGNORE into reactionroles(guildid, channelid, messageid, emote, roleid, `group`, levelreq, dateadded)
|
||||
select guildid, channelid, messageid, emotename, roleid, exclusive, 0, reactionrolemessage.dateadded
|
||||
from reactionrole
|
||||
left join reactionrolemessage on reactionrolemessage.id = reactionrole.reactionrolemessageid
|
||||
left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id;");
|
||||
}
|
||||
else if (migrationBuilder.IsSqlite())
|
||||
if (migrationBuilder.IsSqlite())
|
||||
{
|
||||
migrationBuilder.Sql(
|
||||
@"insert or ignore into reactionroles(guildid, channelid, messageid, emote, roleid, 'group', levelreq, dateadded)
|
||||
@@ -27,7 +23,8 @@ left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id;")
|
||||
}
|
||||
else if (migrationBuilder.IsNpgsql())
|
||||
{
|
||||
migrationBuilder.Sql(@"insert into reactionroles(guildid, channelid, messageid, emote, roleid, ""group"", levelreq, dateadded)
|
||||
migrationBuilder.Sql(
|
||||
@"insert into reactionroles(guildid, channelid, messageid, emote, roleid, ""group"", levelreq, dateadded)
|
||||
select guildid, channelid, messageid, emotename, roleid, exclusive::int, 0, reactionrolemessage.dateadded
|
||||
from reactionrole
|
||||
left join reactionrolemessage on reactionrolemessage.id = reactionrole.reactionrolemessageid
|
||||
@@ -42,12 +39,52 @@ left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id;")
|
||||
|
||||
public static void GuildConfigCleanup(MigrationBuilder builder)
|
||||
{
|
||||
builder.Sql($"""
|
||||
DELETE FROM "StreamRoleBlacklistedUser" WHERE "StreamRoleSettingsId" is NULL;
|
||||
""");
|
||||
|
||||
builder.Sql($"""
|
||||
DELETE FROM "DelMsgOnCmdChannel" WHERE "GuildConfigId" is NULL;
|
||||
DELETE FROM "WarningPunishment" WHERE "GuildConfigId" NOT IN (SELECT "Id" from "GuildConfigs");
|
||||
DELETE FROM "StreamRoleBlacklistedUser" WHERE "StreamRoleSettingsId" is NULL;
|
||||
DELETE FROM "Permissions" WHERE "GuildConfigId" NOT IN (SELECT "Id" from "GuildConfigs");
|
||||
""");
|
||||
}
|
||||
|
||||
public static void GreetSettingsCopy(MigrationBuilder builder)
|
||||
{
|
||||
builder.Sql("""
|
||||
INSERT INTO GreetSettings (GuildId, GreetType, MessageText, IsEnabled, ChannelId, AutoDeleteTimer)
|
||||
SELECT GuildId, 0, ChannelGreetMessageText, SendChannelGreetMessage, GreetMessageChannelId, AutoDeleteGreetMessagesTimer
|
||||
FROM GuildConfigs
|
||||
WHERE SendChannelGreetMessage = TRUE;
|
||||
|
||||
INSERT INTO GreetSettings (GuildId, GreetType, MessageText, IsEnabled, ChannelId, AutoDeleteTimer)
|
||||
SELECT GuildId, 1, DmGreetMessageText, SendDmGreetMessage, GreetMessageChannelId, 0
|
||||
FROM GuildConfigs
|
||||
WHERE SendDmGreetMessage = TRUE;
|
||||
|
||||
INSERT INTO GreetSettings (GuildId, GreetType, MessageText, IsEnabled, ChannelId, AutoDeleteTimer)
|
||||
SELECT GuildId, 2, ChannelByeMessageText, SendChannelByeMessage, ByeMessageChannelId, AutoDeleteByeMessagesTimer
|
||||
FROM GuildConfigs
|
||||
WHERE SendChannelByeMessage = TRUE;
|
||||
|
||||
INSERT INTO GreetSettings (GuildId, GreetType, MessageText, IsEnabled, ChannelId, AutoDeleteTimer)
|
||||
SELECT GuildId, 3, BoostMessage, SendBoostMessage, BoostMessageChannelId, BoostMessageDeleteAfter
|
||||
FROM GuildConfigs
|
||||
WHERE SendBoostMessage = TRUE;
|
||||
""");
|
||||
}
|
||||
|
||||
public static void AddGuildIdsToWarningPunishment(MigrationBuilder builder)
|
||||
{
|
||||
builder.Sql("""
|
||||
DELETE FROM WarningPunishment WHERE GuildConfigId IS NULL OR GuildConfigId NOT IN (SELECT Id FROM GuildConfigs);
|
||||
UPDATE WarningPunishment
|
||||
SET GuildId = (SELECT GuildId FROM GuildConfigs WHERE Id = GuildConfigId);
|
||||
|
||||
DELETE FROM WarningPunishment as wp
|
||||
WHERE (wp.Count, wp.GuildConfigId) in (
|
||||
SELECT wp2.Count, wp2.GuildConfigId FROM WarningPunishment as wp2
|
||||
GROUP BY wp2.Count, wp2.GuildConfigId
|
||||
HAVING COUNT(id) > 1
|
||||
);
|
||||
""");
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,26 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class stondel : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "deletestreamonlinemessage",
|
||||
table: "guildconfigs",
|
||||
type: "tinyint(1)",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "deletestreamonlinemessage",
|
||||
table: "guildconfigs");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,41 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class bank : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "bankusers",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
userid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
balance = table.Column<long>(type: "bigint", nullable: false),
|
||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_bankusers", x => x.id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_bankusers_userid",
|
||||
table: "bankusers",
|
||||
column: "userid",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "bankusers");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,120 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class newrero : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "reactionroles",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
guildid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
channelid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
messageid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
emote = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
roleid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
group = table.Column<int>(type: "int", nullable: false),
|
||||
levelreq = table.Column<int>(type: "int", nullable: false),
|
||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_reactionroles", x => x.id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_reactionroles_guildid",
|
||||
table: "reactionroles",
|
||||
column: "guildid");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_reactionroles_messageid_emote",
|
||||
table: "reactionroles",
|
||||
columns: new[] { "messageid", "emote" },
|
||||
unique: true);
|
||||
|
||||
MigrationQueries.MigrateRero(migrationBuilder);
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "reactionrole");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "reactionrolemessage");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "reactionroles");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "reactionrolemessage",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
guildconfigid = table.Column<int>(type: "int", nullable: false),
|
||||
channelid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true),
|
||||
exclusive = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
index = table.Column<int>(type: "int", nullable: false),
|
||||
messageid = table.Column<ulong>(type: "bigint unsigned", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_reactionrolemessage", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "fk_reactionrolemessage_guildconfigs_guildconfigid",
|
||||
column: x => x.guildconfigid,
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "reactionrole",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true),
|
||||
emotename = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
reactionrolemessageid = table.Column<int>(type: "int", nullable: true),
|
||||
roleid = table.Column<ulong>(type: "bigint unsigned", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_reactionrole", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "fk_reactionrole_reactionrolemessage_reactionrolemessageid",
|
||||
column: x => x.reactionrolemessageid,
|
||||
principalTable: "reactionrolemessage",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_reactionrole_reactionrolemessageid",
|
||||
table: "reactionrole",
|
||||
column: "reactionrolemessageid");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_reactionrolemessage_guildconfigid",
|
||||
table: "reactionrolemessage",
|
||||
column: "guildconfigid");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,175 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class patronagesystem : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "patreonuserid",
|
||||
table: "rewardedusers",
|
||||
newName: "platformuserid");
|
||||
|
||||
migrationBuilder.RenameIndex(
|
||||
name: "ix_rewardedusers_patreonuserid",
|
||||
table: "rewardedusers",
|
||||
newName: "ix_rewardedusers_platformuserid");
|
||||
|
||||
migrationBuilder.AlterColumn<long>(
|
||||
name: "xp",
|
||||
table: "userxpstats",
|
||||
type: "bigint",
|
||||
nullable: false,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int");
|
||||
|
||||
migrationBuilder.AlterColumn<long>(
|
||||
name: "awardedxp",
|
||||
table: "userxpstats",
|
||||
type: "bigint",
|
||||
nullable: false,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int");
|
||||
|
||||
migrationBuilder.AlterColumn<long>(
|
||||
name: "amountrewardedthismonth",
|
||||
table: "rewardedusers",
|
||||
type: "bigint",
|
||||
nullable: false,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int");
|
||||
|
||||
migrationBuilder.AlterColumn<bool>(
|
||||
name: "verboseerrors",
|
||||
table: "guildconfigs",
|
||||
type: "tinyint(1)",
|
||||
nullable: false,
|
||||
defaultValue: true,
|
||||
oldClrType: typeof(bool),
|
||||
oldType: "tinyint(1)");
|
||||
|
||||
migrationBuilder.AlterColumn<long>(
|
||||
name: "totalxp",
|
||||
table: "discorduser",
|
||||
type: "bigint",
|
||||
nullable: false,
|
||||
defaultValue: 0L,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int",
|
||||
oldDefaultValue: 0);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "patronquotas",
|
||||
columns: table => new
|
||||
{
|
||||
userid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
featuretype = table.Column<int>(type: "int", nullable: false),
|
||||
feature = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
hourlycount = table.Column<uint>(type: "int unsigned", nullable: false),
|
||||
dailycount = table.Column<uint>(type: "int unsigned", nullable: false),
|
||||
monthlycount = table.Column<uint>(type: "int unsigned", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_patronquotas", x => new { x.userid, x.featuretype, x.feature });
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "patrons",
|
||||
columns: table => new
|
||||
{
|
||||
userid = table.Column<ulong>(type: "bigint unsigned", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
uniqueplatformuserid = table.Column<string>(type: "varchar(255)", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
amountcents = table.Column<int>(type: "int", nullable: false),
|
||||
lastcharge = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
validthru = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_patrons", x => x.userid);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_patronquotas_userid",
|
||||
table: "patronquotas",
|
||||
column: "userid");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_patrons_uniqueplatformuserid",
|
||||
table: "patrons",
|
||||
column: "uniqueplatformuserid",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "patronquotas");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "patrons");
|
||||
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "platformuserid",
|
||||
table: "rewardedusers",
|
||||
newName: "patreonuserid");
|
||||
|
||||
migrationBuilder.RenameIndex(
|
||||
name: "ix_rewardedusers_platformuserid",
|
||||
table: "rewardedusers",
|
||||
newName: "ix_rewardedusers_patreonuserid");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "xp",
|
||||
table: "userxpstats",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
oldClrType: typeof(long),
|
||||
oldType: "bigint");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "awardedxp",
|
||||
table: "userxpstats",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
oldClrType: typeof(long),
|
||||
oldType: "bigint");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "amountrewardedthismonth",
|
||||
table: "rewardedusers",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
oldClrType: typeof(long),
|
||||
oldType: "bigint");
|
||||
|
||||
migrationBuilder.AlterColumn<bool>(
|
||||
name: "verboseerrors",
|
||||
table: "guildconfigs",
|
||||
type: "tinyint(1)",
|
||||
nullable: false,
|
||||
oldClrType: typeof(bool),
|
||||
oldType: "tinyint(1)",
|
||||
oldDefaultValue: true);
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "totalxp",
|
||||
table: "discorduser",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0,
|
||||
oldClrType: typeof(long),
|
||||
oldType: "bigint",
|
||||
oldDefaultValue: 0L);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,38 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class stondeldbcache : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "streamonlinemessages",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
channelid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
messageid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
type = table.Column<int>(type: "int", nullable: false),
|
||||
name = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_streamonlinemessages", x => x.id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "streamonlinemessages");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,25 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class logwarns : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<ulong>(
|
||||
name: "logwarnsid",
|
||||
table: "logsettings",
|
||||
type: "bigint unsigned",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "logwarnsid",
|
||||
table: "logsettings");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,44 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class xpitemshop : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "xpshopowneditem",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
userid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
itemtype = table.Column<int>(type: "int", nullable: false),
|
||||
isusing = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
itemkey = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_xpshopowneditem", x => x.id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_xpshopowneditem_userid_itemtype_itemkey",
|
||||
table: "xpshopowneditem",
|
||||
columns: new[] { "userid", "itemtype", "itemkey" },
|
||||
unique: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "xpshopowneditem");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,26 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class linkonlychannels : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "type",
|
||||
table: "imageonlychannels",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "type",
|
||||
table: "imageonlychannels");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,48 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class removeobsoletexpcolumns : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "lastlevelup",
|
||||
table: "userxpstats");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "lastlevelup",
|
||||
table: "discorduser");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "lastxpgain",
|
||||
table: "discorduser");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "lastlevelup",
|
||||
table: "userxpstats",
|
||||
type: "datetime(6)",
|
||||
nullable: false,
|
||||
defaultValueSql: "(UTC_TIMESTAMP)");
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "lastlevelup",
|
||||
table: "discorduser",
|
||||
type: "datetime(6)",
|
||||
nullable: false,
|
||||
defaultValueSql: "(UTC_TIMESTAMP)");
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "lastxpgain",
|
||||
table: "discorduser",
|
||||
type: "datetime(6)",
|
||||
nullable: false,
|
||||
defaultValueSql: "(UTC_TIMESTAMP - INTERVAL 1 year)");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,25 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class banprune : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "prunedays",
|
||||
table: "bantemplates",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "prunedays",
|
||||
table: "bantemplates");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,25 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class shoprolereq : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<ulong>(
|
||||
name: "rolerequirement",
|
||||
table: "shopentry",
|
||||
type: "bigint unsigned",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "rolerequirement",
|
||||
table: "shopentry");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,41 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class autopub : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "autopublishchannel",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
guildid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
channelid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_autopublishchannel", x => x.id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_autopublishchannel_guildid",
|
||||
table: "autopublishchannel",
|
||||
column: "guildid",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "autopublishchannel");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,43 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class gamblingstats : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "gamblingstats",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
feature = table.Column<string>(type: "varchar(255)", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
bet = table.Column<decimal>(type: "decimal(65,30)", nullable: false),
|
||||
paidout = table.Column<decimal>(type: "decimal(65,30)", nullable: false),
|
||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_gamblingstats", x => x.id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_gamblingstats_feature",
|
||||
table: "gamblingstats",
|
||||
column: "feature",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "gamblingstats");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,26 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class toggleglobalexpressions : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "disableglobalexpressions",
|
||||
table: "guildconfigs",
|
||||
type: "tinyint(1)",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "disableglobalexpressions",
|
||||
table: "guildconfigs");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,35 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class logthread : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<ulong>(
|
||||
name: "threadcreatedid",
|
||||
table: "logsettings",
|
||||
type: "bigint unsigned",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<ulong>(
|
||||
name: "threaddeletedid",
|
||||
table: "logsettings",
|
||||
type: "bigint unsigned",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "threadcreatedid",
|
||||
table: "logsettings");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "threaddeletedid",
|
||||
table: "logsettings");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,26 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class feedtext : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "message",
|
||||
table: "feedsub",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "message",
|
||||
table: "feedsub");
|
||||
}
|
||||
}
|
||||
}
|
3830
src/NadekoBot/Migrations/Mysql/20240502233216_v5.Designer.cs
generated
3830
src/NadekoBot/Migrations/Mysql/20240502233216_v5.Designer.cs
generated
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,702 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class guidlconfigcleanup : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_antiraidsetting_guildconfigs_guildconfigid",
|
||||
table: "antiraidsetting");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_antispamignore_antispamsetting_antispamsettingid",
|
||||
table: "antispamignore");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_antispamsetting_guildconfigs_guildconfigid",
|
||||
table: "antispamsetting");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_commandalias_guildconfigs_guildconfigid",
|
||||
table: "commandalias");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_commandcooldown_guildconfigs_guildconfigid",
|
||||
table: "commandcooldown");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_delmsgoncmdchannel_guildconfigs_guildconfigid",
|
||||
table: "delmsgoncmdchannel");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_excludeditem_xpsettings_xpsettingsid",
|
||||
table: "excludeditem");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_filterchannelid_guildconfigs_guildconfigid",
|
||||
table: "filterchannelid");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_filteredword_guildconfigs_guildconfigid",
|
||||
table: "filteredword");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_filterlinkschannelid_guildconfigs_guildconfigid",
|
||||
table: "filterlinkschannelid");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_filterwordschannelid_guildconfigs_guildconfigid",
|
||||
table: "filterwordschannelid");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_followedstream_guildconfigs_guildconfigid",
|
||||
table: "followedstream");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_gcchannelid_guildconfigs_guildconfigid",
|
||||
table: "gcchannelid");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_muteduserid_guildconfigs_guildconfigid",
|
||||
table: "muteduserid");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_permissions_guildconfigs_guildconfigid",
|
||||
table: "permissions");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_shopentry_guildconfigs_guildconfigid",
|
||||
table: "shopentry");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_shopentryitem_shopentry_shopentryid",
|
||||
table: "shopentryitem");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_slowmodeignoredrole_guildconfigs_guildconfigid",
|
||||
table: "slowmodeignoredrole");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_slowmodeignoreduser_guildconfigs_guildconfigid",
|
||||
table: "slowmodeignoreduser");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_streamroleblacklisteduser_streamrolesettings_streamrolesetti~",
|
||||
table: "streamroleblacklisteduser");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_streamrolewhitelisteduser_streamrolesettings_streamrolesetti~",
|
||||
table: "streamrolewhitelisteduser");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_unbantimer_guildconfigs_guildconfigid",
|
||||
table: "unbantimer");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_unmutetimer_guildconfigs_guildconfigid",
|
||||
table: "unmutetimer");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_unroletimer_guildconfigs_guildconfigid",
|
||||
table: "unroletimer");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_vcroleinfo_guildconfigs_guildconfigid",
|
||||
table: "vcroleinfo");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_warningpunishment_guildconfigs_guildconfigid",
|
||||
table: "warningpunishment");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "ignoredvoicepresencechannels");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "streamrolesettingsid",
|
||||
table: "streamrolewhitelisteduser",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "streamrolesettingsid",
|
||||
table: "streamroleblacklisteduser",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "guildconfigid",
|
||||
table: "delmsgoncmdchannel",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_antiraidsetting_guildconfigs_guildconfigid",
|
||||
table: "antiraidsetting",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_antispamignore_antispamsetting_antispamsettingid",
|
||||
table: "antispamignore",
|
||||
column: "antispamsettingid",
|
||||
principalTable: "antispamsetting",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_antispamsetting_guildconfigs_guildconfigid",
|
||||
table: "antispamsetting",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_commandalias_guildconfigs_guildconfigid",
|
||||
table: "commandalias",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_commandcooldown_guildconfigs_guildconfigid",
|
||||
table: "commandcooldown",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_delmsgoncmdchannel_guildconfigs_guildconfigid",
|
||||
table: "delmsgoncmdchannel",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_excludeditem_xpsettings_xpsettingsid",
|
||||
table: "excludeditem",
|
||||
column: "xpsettingsid",
|
||||
principalTable: "xpsettings",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_filterchannelid_guildconfigs_guildconfigid",
|
||||
table: "filterchannelid",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_filteredword_guildconfigs_guildconfigid",
|
||||
table: "filteredword",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_filterlinkschannelid_guildconfigs_guildconfigid",
|
||||
table: "filterlinkschannelid",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_filterwordschannelid_guildconfigs_guildconfigid",
|
||||
table: "filterwordschannelid",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_followedstream_guildconfigs_guildconfigid",
|
||||
table: "followedstream",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_gcchannelid_guildconfigs_guildconfigid",
|
||||
table: "gcchannelid",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_muteduserid_guildconfigs_guildconfigid",
|
||||
table: "muteduserid",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_permissions_guildconfigs_guildconfigid",
|
||||
table: "permissions",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_shopentry_guildconfigs_guildconfigid",
|
||||
table: "shopentry",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_shopentryitem_shopentry_shopentryid",
|
||||
table: "shopentryitem",
|
||||
column: "shopentryid",
|
||||
principalTable: "shopentry",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_slowmodeignoredrole_guildconfigs_guildconfigid",
|
||||
table: "slowmodeignoredrole",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_slowmodeignoreduser_guildconfigs_guildconfigid",
|
||||
table: "slowmodeignoreduser",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_streamroleblacklisteduser_streamrolesettings_streamrolesetti~",
|
||||
table: "streamroleblacklisteduser",
|
||||
column: "streamrolesettingsid",
|
||||
principalTable: "streamrolesettings",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_streamrolewhitelisteduser_streamrolesettings_streamrolesetti~",
|
||||
table: "streamrolewhitelisteduser",
|
||||
column: "streamrolesettingsid",
|
||||
principalTable: "streamrolesettings",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_unbantimer_guildconfigs_guildconfigid",
|
||||
table: "unbantimer",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_unmutetimer_guildconfigs_guildconfigid",
|
||||
table: "unmutetimer",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_unroletimer_guildconfigs_guildconfigid",
|
||||
table: "unroletimer",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_vcroleinfo_guildconfigs_guildconfigid",
|
||||
table: "vcroleinfo",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_warningpunishment_guildconfigs_guildconfigid",
|
||||
table: "warningpunishment",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_antiraidsetting_guildconfigs_guildconfigid",
|
||||
table: "antiraidsetting");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_antispamignore_antispamsetting_antispamsettingid",
|
||||
table: "antispamignore");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_antispamsetting_guildconfigs_guildconfigid",
|
||||
table: "antispamsetting");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_commandalias_guildconfigs_guildconfigid",
|
||||
table: "commandalias");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_commandcooldown_guildconfigs_guildconfigid",
|
||||
table: "commandcooldown");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_delmsgoncmdchannel_guildconfigs_guildconfigid",
|
||||
table: "delmsgoncmdchannel");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_excludeditem_xpsettings_xpsettingsid",
|
||||
table: "excludeditem");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_filterchannelid_guildconfigs_guildconfigid",
|
||||
table: "filterchannelid");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_filteredword_guildconfigs_guildconfigid",
|
||||
table: "filteredword");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_filterlinkschannelid_guildconfigs_guildconfigid",
|
||||
table: "filterlinkschannelid");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_filterwordschannelid_guildconfigs_guildconfigid",
|
||||
table: "filterwordschannelid");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_followedstream_guildconfigs_guildconfigid",
|
||||
table: "followedstream");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_gcchannelid_guildconfigs_guildconfigid",
|
||||
table: "gcchannelid");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_muteduserid_guildconfigs_guildconfigid",
|
||||
table: "muteduserid");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_permissions_guildconfigs_guildconfigid",
|
||||
table: "permissions");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_shopentry_guildconfigs_guildconfigid",
|
||||
table: "shopentry");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_shopentryitem_shopentry_shopentryid",
|
||||
table: "shopentryitem");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_slowmodeignoredrole_guildconfigs_guildconfigid",
|
||||
table: "slowmodeignoredrole");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_slowmodeignoreduser_guildconfigs_guildconfigid",
|
||||
table: "slowmodeignoreduser");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_streamroleblacklisteduser_streamrolesettings_streamrolesetti~",
|
||||
table: "streamroleblacklisteduser");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_streamrolewhitelisteduser_streamrolesettings_streamrolesetti~",
|
||||
table: "streamrolewhitelisteduser");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_unbantimer_guildconfigs_guildconfigid",
|
||||
table: "unbantimer");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_unmutetimer_guildconfigs_guildconfigid",
|
||||
table: "unmutetimer");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_unroletimer_guildconfigs_guildconfigid",
|
||||
table: "unroletimer");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_vcroleinfo_guildconfigs_guildconfigid",
|
||||
table: "vcroleinfo");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_warningpunishment_guildconfigs_guildconfigid",
|
||||
table: "warningpunishment");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "streamrolesettingsid",
|
||||
table: "streamrolewhitelisteduser",
|
||||
type: "int",
|
||||
nullable: true,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "streamrolesettingsid",
|
||||
table: "streamroleblacklisteduser",
|
||||
type: "int",
|
||||
nullable: true,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "guildconfigid",
|
||||
table: "delmsgoncmdchannel",
|
||||
type: "int",
|
||||
nullable: true,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ignoredvoicepresencechannels",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
logsettingid = table.Column<int>(type: "int", nullable: true),
|
||||
channelid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_ignoredvoicepresencechannels", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "fk_ignoredvoicepresencechannels_logsettings_logsettingid",
|
||||
column: x => x.logsettingid,
|
||||
principalTable: "logsettings",
|
||||
principalColumn: "id");
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_ignoredvoicepresencechannels_logsettingid",
|
||||
table: "ignoredvoicepresencechannels",
|
||||
column: "logsettingid");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_antiraidsetting_guildconfigs_guildconfigid",
|
||||
table: "antiraidsetting",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_antispamignore_antispamsetting_antispamsettingid",
|
||||
table: "antispamignore",
|
||||
column: "antispamsettingid",
|
||||
principalTable: "antispamsetting",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_antispamsetting_guildconfigs_guildconfigid",
|
||||
table: "antispamsetting",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_commandalias_guildconfigs_guildconfigid",
|
||||
table: "commandalias",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_commandcooldown_guildconfigs_guildconfigid",
|
||||
table: "commandcooldown",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_delmsgoncmdchannel_guildconfigs_guildconfigid",
|
||||
table: "delmsgoncmdchannel",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_excludeditem_xpsettings_xpsettingsid",
|
||||
table: "excludeditem",
|
||||
column: "xpsettingsid",
|
||||
principalTable: "xpsettings",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_filterchannelid_guildconfigs_guildconfigid",
|
||||
table: "filterchannelid",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_filteredword_guildconfigs_guildconfigid",
|
||||
table: "filteredword",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_filterlinkschannelid_guildconfigs_guildconfigid",
|
||||
table: "filterlinkschannelid",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_filterwordschannelid_guildconfigs_guildconfigid",
|
||||
table: "filterwordschannelid",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_followedstream_guildconfigs_guildconfigid",
|
||||
table: "followedstream",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_gcchannelid_guildconfigs_guildconfigid",
|
||||
table: "gcchannelid",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_muteduserid_guildconfigs_guildconfigid",
|
||||
table: "muteduserid",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_permissions_guildconfigs_guildconfigid",
|
||||
table: "permissions",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_shopentry_guildconfigs_guildconfigid",
|
||||
table: "shopentry",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_shopentryitem_shopentry_shopentryid",
|
||||
table: "shopentryitem",
|
||||
column: "shopentryid",
|
||||
principalTable: "shopentry",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_slowmodeignoredrole_guildconfigs_guildconfigid",
|
||||
table: "slowmodeignoredrole",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_slowmodeignoreduser_guildconfigs_guildconfigid",
|
||||
table: "slowmodeignoreduser",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_streamroleblacklisteduser_streamrolesettings_streamrolesetti~",
|
||||
table: "streamroleblacklisteduser",
|
||||
column: "streamrolesettingsid",
|
||||
principalTable: "streamrolesettings",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_streamrolewhitelisteduser_streamrolesettings_streamrolesetti~",
|
||||
table: "streamrolewhitelisteduser",
|
||||
column: "streamrolesettingsid",
|
||||
principalTable: "streamrolesettings",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_unbantimer_guildconfigs_guildconfigid",
|
||||
table: "unbantimer",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_unmutetimer_guildconfigs_guildconfigid",
|
||||
table: "unmutetimer",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_unroletimer_guildconfigs_guildconfigid",
|
||||
table: "unroletimer",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_vcroleinfo_guildconfigs_guildconfigid",
|
||||
table: "vcroleinfo",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_warningpunishment_guildconfigs_guildconfigid",
|
||||
table: "warningpunishment",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id");
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,44 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class removepatronlimits : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "patronquotas");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "patronquotas",
|
||||
columns: table => new
|
||||
{
|
||||
userid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
featuretype = table.Column<int>(type: "int", nullable: false),
|
||||
feature = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
dailycount = table.Column<uint>(type: "int unsigned", nullable: false),
|
||||
hourlycount = table.Column<uint>(type: "int unsigned", nullable: false),
|
||||
monthlycount = table.Column<uint>(type: "int unsigned", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_patronquotas", x => new { x.userid, x.featuretype, x.feature });
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_patronquotas_userid",
|
||||
table: "patronquotas",
|
||||
column: "userid");
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class honeypot : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "honeypotchannels",
|
||||
columns: table => new
|
||||
{
|
||||
guildid = table.Column<ulong>(type: "bigint unsigned", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
channelid = table.Column<ulong>(type: "bigint unsigned", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_honeypotchannels", x => x.guildid);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "honeypotchannels");
|
||||
}
|
||||
}
|
||||
}
|
@@ -9,12 +9,6 @@ namespace NadekoBot.Migrations.PostgreSql
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<decimal>(
|
||||
name: "rolerequirement",
|
||||
table: "shopentry",
|
||||
type: "numeric(20,0)",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "autopublishchannel",
|
||||
columns: table => new
|
||||
@@ -41,10 +35,6 @@ namespace NadekoBot.Migrations.PostgreSql
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "autopublishchannel");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "rolerequirement",
|
||||
table: "shopentry");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,199 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.PostgreSql
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class greetsettings : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "greetsettings",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy",
|
||||
NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
guildid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||
greettype = table.Column<int>(type: "integer", nullable: false),
|
||||
messagetext = table.Column<string>(type: "text", nullable: true),
|
||||
isenabled = table.Column<bool>(type: "boolean", nullable: false, defaultValue: false),
|
||||
channelid = table.Column<decimal>(type: "numeric(20,0)", nullable: true),
|
||||
autodeletetimer = table.Column<int>(type: "integer", nullable: false, defaultValue: 0)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_greetsettings", x => x.id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_greetsettings_guildid_greettype",
|
||||
table: "greetsettings",
|
||||
columns: new[] { "guildid", "greettype" },
|
||||
unique: true);
|
||||
|
||||
MigrationQueries.GreetSettingsCopy(migrationBuilder);
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "autodeletebyemessagestimer",
|
||||
table: "guildconfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "autodeletegreetmessagestimer",
|
||||
table: "guildconfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "boostmessage",
|
||||
table: "guildconfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "boostmessagechannelid",
|
||||
table: "guildconfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "boostmessagedeleteafter",
|
||||
table: "guildconfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "byemessagechannelid",
|
||||
table: "guildconfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "channelbyemessagetext",
|
||||
table: "guildconfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "channelgreetmessagetext",
|
||||
table: "guildconfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "dmgreetmessagetext",
|
||||
table: "guildconfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "greetmessagechannelid",
|
||||
table: "guildconfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "sendboostmessage",
|
||||
table: "guildconfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "sendchannelbyemessage",
|
||||
table: "guildconfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "sendchannelgreetmessage",
|
||||
table: "guildconfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "senddmgreetmessage",
|
||||
table: "guildconfigs");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "greetsettings");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "autodeletebyemessagestimer",
|
||||
table: "guildconfigs",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "autodeletegreetmessagestimer",
|
||||
table: "guildconfigs",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "boostmessage",
|
||||
table: "guildconfigs",
|
||||
type: "text",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<decimal>(
|
||||
name: "boostmessagechannelid",
|
||||
table: "guildconfigs",
|
||||
type: "numeric(20,0)",
|
||||
nullable: false,
|
||||
defaultValue: 0m);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "boostmessagedeleteafter",
|
||||
table: "guildconfigs",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<decimal>(
|
||||
name: "byemessagechannelid",
|
||||
table: "guildconfigs",
|
||||
type: "numeric(20,0)",
|
||||
nullable: false,
|
||||
defaultValue: 0m);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "channelbyemessagetext",
|
||||
table: "guildconfigs",
|
||||
type: "text",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "channelgreetmessagetext",
|
||||
table: "guildconfigs",
|
||||
type: "text",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "dmgreetmessagetext",
|
||||
table: "guildconfigs",
|
||||
type: "text",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<decimal>(
|
||||
name: "greetmessagechannelid",
|
||||
table: "guildconfigs",
|
||||
type: "numeric(20,0)",
|
||||
nullable: false,
|
||||
defaultValue: 0m);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "sendboostmessage",
|
||||
table: "guildconfigs",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "sendchannelbyemessage",
|
||||
table: "guildconfigs",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "sendchannelgreetmessage",
|
||||
table: "guildconfigs",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "senddmgreetmessage",
|
||||
table: "guildconfigs",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,71 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.PostgreSql
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class warnsplit : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<decimal>(
|
||||
name: "guildid",
|
||||
table: "warningpunishment",
|
||||
type: "numeric(20,0)",
|
||||
nullable: false,
|
||||
defaultValue: 0m);
|
||||
|
||||
MigrationQueries.AddGuildIdsToWarningPunishment(migrationBuilder);
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "fk_warningpunishment_guildconfigs_guildconfigid",
|
||||
table: "warningpunishment");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "ix_warningpunishment_guildconfigid",
|
||||
table: "warningpunishment");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "guildconfigid",
|
||||
table: "warningpunishment");
|
||||
|
||||
migrationBuilder.AddUniqueConstraint(
|
||||
name: "ak_warningpunishment_guildid_count",
|
||||
table: "warningpunishment",
|
||||
columns: new[] { "guildid", "count" });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropUniqueConstraint(
|
||||
name: "ak_warningpunishment_guildid_count",
|
||||
table: "warningpunishment");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "guildid",
|
||||
table: "warningpunishment");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "guildconfigid",
|
||||
table: "warningpunishment",
|
||||
type: "integer",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_warningpunishment_guildconfigid",
|
||||
table: "warningpunishment",
|
||||
column: "guildconfigid");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "fk_warningpunishment_guildconfigs_guildconfigid",
|
||||
table: "warningpunishment",
|
||||
column: "guildconfigid",
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,54 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.PostgreSql
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class ncanvas : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ncpixel",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
position = table.Column<int>(type: "integer", nullable: false),
|
||||
price = table.Column<long>(type: "bigint", nullable: false),
|
||||
ownerid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||
color = table.Column<long>(type: "bigint", nullable: false),
|
||||
text = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_ncpixel", x => x.id);
|
||||
table.UniqueConstraint("ak_ncpixel_position", x => x.position);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_discorduser_username",
|
||||
table: "discorduser",
|
||||
column: "username");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_ncpixel_ownerid",
|
||||
table: "ncpixel",
|
||||
column: "ownerid");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "ncpixel");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "ix_discorduser_username",
|
||||
table: "discorduser");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.PostgreSql
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class nodiscrimandflagtranslate : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
MigrationQueries.UpdateUsernames(migrationBuilder);
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "discriminator",
|
||||
table: "discorduser");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "flagtranslatechannel",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
guildid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||
channelid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||
dateadded = table.Column<DateTime>(type: "timestamp without time zone", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_flagtranslatechannel", x => x.id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_flagtranslatechannel_guildid_channelid",
|
||||
table: "flagtranslatechannel",
|
||||
columns: new[] { "guildid", "channelid" },
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "flagtranslatechannel");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "discriminator",
|
||||
table: "discorduser",
|
||||
type: "text",
|
||||
nullable: true);
|
||||
}
|
||||
}
|
||||
}
|
@@ -17,7 +17,7 @@ namespace NadekoBot.Migrations.PostgreSql
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "8.0.4")
|
||||
.HasAnnotation("ProductVersion", "8.0.8")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
@@ -751,10 +751,6 @@ namespace NadekoBot.Migrations.PostgreSql
|
||||
.HasColumnType("timestamp without time zone")
|
||||
.HasColumnName("dateadded");
|
||||
|
||||
b.Property<string>("Discriminator")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("discriminator");
|
||||
|
||||
b.Property<bool>("IsClubAdmin")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
@@ -799,6 +795,9 @@ namespace NadekoBot.Migrations.PostgreSql
|
||||
b.HasIndex("UserId")
|
||||
.HasDatabaseName("ix_discorduser_userid");
|
||||
|
||||
b.HasIndex("Username")
|
||||
.HasDatabaseName("ix_discorduser_username");
|
||||
|
||||
b.ToTable("discorduser", (string)null);
|
||||
});
|
||||
|
||||
@@ -995,6 +994,37 @@ namespace NadekoBot.Migrations.PostgreSql
|
||||
b.ToTable("filteredword", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Db.Models.FlagTranslateChannel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<decimal>("ChannelId")
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("channelid");
|
||||
|
||||
b.Property<DateTime?>("DateAdded")
|
||||
.HasColumnType("timestamp without time zone")
|
||||
.HasColumnName("dateadded");
|
||||
|
||||
b.Property<decimal>("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<int>("Id")
|
||||
@@ -1220,42 +1250,10 @@ namespace NadekoBot.Migrations.PostgreSql
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("autoassignroleids");
|
||||
|
||||
b.Property<int>("AutoDeleteByeMessagesTimer")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("autodeletebyemessagestimer");
|
||||
|
||||
b.Property<int>("AutoDeleteGreetMessagesTimer")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("autodeletegreetmessagestimer");
|
||||
|
||||
b.Property<bool>("AutoDeleteSelfAssignedRoleMessages")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("autodeleteselfassignedrolemessages");
|
||||
|
||||
b.Property<string>("BoostMessage")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("boostmessage");
|
||||
|
||||
b.Property<decimal>("BoostMessageChannelId")
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("boostmessagechannelid");
|
||||
|
||||
b.Property<int>("BoostMessageDeleteAfter")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("boostmessagedeleteafter");
|
||||
|
||||
b.Property<decimal>("ByeMessageChannelId")
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("byemessagechannelid");
|
||||
|
||||
b.Property<string>("ChannelByeMessageText")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("channelbyemessagetext");
|
||||
|
||||
b.Property<string>("ChannelGreetMessageText")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("channelgreetmessagetext");
|
||||
|
||||
b.Property<bool>("CleverbotEnabled")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("cleverbotenabled");
|
||||
@@ -1276,10 +1274,6 @@ namespace NadekoBot.Migrations.PostgreSql
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("disableglobalexpressions");
|
||||
|
||||
b.Property<string>("DmGreetMessageText")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("dmgreetmessagetext");
|
||||
|
||||
b.Property<bool>("ExclusiveSelfAssignedRoles")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("exclusiveselfassignedroles");
|
||||
@@ -1300,10 +1294,6 @@ namespace NadekoBot.Migrations.PostgreSql
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("gamevoicechannel");
|
||||
|
||||
b.Property<decimal>("GreetMessageChannelId")
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("greetmessagechannelid");
|
||||
|
||||
b.Property<decimal>("GuildId")
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("guildid");
|
||||
@@ -1328,22 +1318,6 @@ namespace NadekoBot.Migrations.PostgreSql
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("prefix");
|
||||
|
||||
b.Property<bool>("SendBoostMessage")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("sendboostmessage");
|
||||
|
||||
b.Property<bool>("SendChannelByeMessage")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("sendchannelbyemessage");
|
||||
|
||||
b.Property<bool>("SendChannelGreetMessage")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("sendchannelgreetmessage");
|
||||
|
||||
b.Property<bool>("SendDmGreetMessage")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("senddmgreetmessage");
|
||||
|
||||
b.Property<bool>("StickyRoles")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("stickyroles");
|
||||
@@ -1683,6 +1657,49 @@ namespace NadekoBot.Migrations.PostgreSql
|
||||
b.ToTable("muteduserid", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Db.Models.NCPixel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<long>("Color")
|
||||
.HasColumnType("bigint")
|
||||
.HasColumnName("color");
|
||||
|
||||
b.Property<decimal>("OwnerId")
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("ownerid");
|
||||
|
||||
b.Property<int>("Position")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("position");
|
||||
|
||||
b.Property<long>("Price")
|
||||
.HasColumnType("bigint")
|
||||
.HasColumnName("price");
|
||||
|
||||
b.Property<string>("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<int>("Id")
|
||||
@@ -2994,9 +3011,9 @@ namespace NadekoBot.Migrations.PostgreSql
|
||||
.HasColumnType("timestamp without time zone")
|
||||
.HasColumnName("dateadded");
|
||||
|
||||
b.Property<int?>("GuildConfigId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("guildconfigid");
|
||||
b.Property<decimal>("GuildId")
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("guildid");
|
||||
|
||||
b.Property<int>("Punishment")
|
||||
.HasColumnType("integer")
|
||||
@@ -3013,8 +3030,8 @@ namespace NadekoBot.Migrations.PostgreSql
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_warningpunishment");
|
||||
|
||||
b.HasIndex("GuildConfigId")
|
||||
.HasDatabaseName("ix_warningpunishment_guildconfigid");
|
||||
b.HasAlternateKey("GuildId", "Count")
|
||||
.HasName("ak_warningpunishment_guildid_count");
|
||||
|
||||
b.ToTable("warningpunishment", (string)null);
|
||||
});
|
||||
@@ -3163,6 +3180,53 @@ namespace NadekoBot.Migrations.PostgreSql
|
||||
b.ToTable("xpshopowneditem", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.GreetSettings", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("AutoDeleteTimer")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasDefaultValue(0)
|
||||
.HasColumnName("autodeletetimer");
|
||||
|
||||
b.Property<decimal?>("ChannelId")
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("channelid");
|
||||
|
||||
b.Property<int>("GreetType")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("greettype");
|
||||
|
||||
b.Property<decimal>("GuildId")
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("guildid");
|
||||
|
||||
b.Property<bool>("IsEnabled")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("isenabled");
|
||||
|
||||
b.Property<string>("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)
|
||||
@@ -3625,15 +3689,6 @@ namespace NadekoBot.Migrations.PostgreSql
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Db.Models.WarningPunishment", b =>
|
||||
{
|
||||
b.HasOne("NadekoBot.Db.Models.GuildConfig", null)
|
||||
.WithMany("WarnPunishments")
|
||||
.HasForeignKey("GuildConfigId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.HasConstraintName("fk_warningpunishment_guildconfigs_guildconfigid");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Db.Models.XpCurrencyReward", b =>
|
||||
{
|
||||
b.HasOne("NadekoBot.Db.Models.XpSettings", "XpSettings")
|
||||
@@ -3749,8 +3804,6 @@ namespace NadekoBot.Migrations.PostgreSql
|
||||
|
||||
b.Navigation("VcRoleInfos");
|
||||
|
||||
b.Navigation("WarnPunishments");
|
||||
|
||||
b.Navigation("XpSettings");
|
||||
});
|
||||
|
||||
|
2929
src/NadekoBot/Migrations/Sqlite/20240912124710_greet-settings.Designer.cs
generated
Normal file
2929
src/NadekoBot/Migrations/Sqlite/20240912124710_greet-settings.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
197
src/NadekoBot/Migrations/Sqlite/20240912124710_greet-settings.cs
Normal file
197
src/NadekoBot/Migrations/Sqlite/20240912124710_greet-settings.cs
Normal file
@@ -0,0 +1,197 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class greetsettings : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "GreetSettings",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
GuildId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||
GreetType = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
MessageText = table.Column<string>(type: "TEXT", nullable: true),
|
||||
IsEnabled = table.Column<bool>(type: "INTEGER", nullable: false, defaultValue: false),
|
||||
ChannelId = table.Column<ulong>(type: "INTEGER", nullable: true),
|
||||
AutoDeleteTimer = table.Column<int>(type: "INTEGER", nullable: false, defaultValue: 0)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_GreetSettings", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_GreetSettings_GuildId_GreetType",
|
||||
table: "GreetSettings",
|
||||
columns: new[] { "GuildId", "GreetType" },
|
||||
unique: true);
|
||||
|
||||
MigrationQueries.GreetSettingsCopy(migrationBuilder);
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "AutoDeleteByeMessagesTimer",
|
||||
table: "GuildConfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "AutoDeleteGreetMessagesTimer",
|
||||
table: "GuildConfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "BoostMessage",
|
||||
table: "GuildConfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "BoostMessageChannelId",
|
||||
table: "GuildConfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "BoostMessageDeleteAfter",
|
||||
table: "GuildConfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ByeMessageChannelId",
|
||||
table: "GuildConfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ChannelByeMessageText",
|
||||
table: "GuildConfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ChannelGreetMessageText",
|
||||
table: "GuildConfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DmGreetMessageText",
|
||||
table: "GuildConfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "GreetMessageChannelId",
|
||||
table: "GuildConfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SendBoostMessage",
|
||||
table: "GuildConfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SendChannelByeMessage",
|
||||
table: "GuildConfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SendChannelGreetMessage",
|
||||
table: "GuildConfigs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SendDmGreetMessage",
|
||||
table: "GuildConfigs");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "GreetSettings");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "AutoDeleteByeMessagesTimer",
|
||||
table: "GuildConfigs",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "AutoDeleteGreetMessagesTimer",
|
||||
table: "GuildConfigs",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "BoostMessage",
|
||||
table: "GuildConfigs",
|
||||
type: "TEXT",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<ulong>(
|
||||
name: "BoostMessageChannelId",
|
||||
table: "GuildConfigs",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0ul);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "BoostMessageDeleteAfter",
|
||||
table: "GuildConfigs",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<ulong>(
|
||||
name: "ByeMessageChannelId",
|
||||
table: "GuildConfigs",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0ul);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "ChannelByeMessageText",
|
||||
table: "GuildConfigs",
|
||||
type: "TEXT",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "ChannelGreetMessageText",
|
||||
table: "GuildConfigs",
|
||||
type: "TEXT",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "DmGreetMessageText",
|
||||
table: "GuildConfigs",
|
||||
type: "TEXT",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<ulong>(
|
||||
name: "GreetMessageChannelId",
|
||||
table: "GuildConfigs",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0ul);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "SendBoostMessage",
|
||||
table: "GuildConfigs",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "SendChannelByeMessage",
|
||||
table: "GuildConfigs",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "SendChannelGreetMessage",
|
||||
table: "GuildConfigs",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "SendDmGreetMessage",
|
||||
table: "GuildConfigs",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
}
|
||||
}
|
2919
src/NadekoBot/Migrations/Sqlite/20241018004612_warn-split.Designer.cs
generated
Normal file
2919
src/NadekoBot/Migrations/Sqlite/20241018004612_warn-split.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
72
src/NadekoBot/Migrations/Sqlite/20241018004612_warn-split.cs
Normal file
72
src/NadekoBot/Migrations/Sqlite/20241018004612_warn-split.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class warnsplit : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<ulong>(
|
||||
name: "GuildId",
|
||||
table: "WarningPunishment",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0ul);
|
||||
|
||||
MigrationQueries.AddGuildIdsToWarningPunishment(migrationBuilder);
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_WarningPunishment_GuildConfigs_GuildConfigId",
|
||||
table: "WarningPunishment");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_WarningPunishment_GuildConfigId",
|
||||
table: "WarningPunishment");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "GuildConfigId",
|
||||
table: "WarningPunishment");
|
||||
|
||||
migrationBuilder.AddUniqueConstraint(
|
||||
name: "AK_WarningPunishment_GuildId_Count",
|
||||
table: "WarningPunishment",
|
||||
columns: new[] { "GuildId", "Count" });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropUniqueConstraint(
|
||||
name: "AK_WarningPunishment_GuildId_Count",
|
||||
table: "WarningPunishment");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "GuildId",
|
||||
table: "WarningPunishment");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "GuildConfigId",
|
||||
table: "WarningPunishment",
|
||||
type: "INTEGER",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_WarningPunishment_GuildConfigId",
|
||||
table: "WarningPunishment",
|
||||
column: "GuildConfigId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_WarningPunishment_GuildConfigs_GuildConfigId",
|
||||
table: "WarningPunishment",
|
||||
column: "GuildConfigId",
|
||||
principalTable: "GuildConfigs",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
}
|
||||
}
|
2953
src/NadekoBot/Migrations/Sqlite/20241028033656_ncanvas.Designer.cs
generated
Normal file
2953
src/NadekoBot/Migrations/Sqlite/20241028033656_ncanvas.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
53
src/NadekoBot/Migrations/Sqlite/20241028033656_ncanvas.cs
Normal file
53
src/NadekoBot/Migrations/Sqlite/20241028033656_ncanvas.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class ncanvas : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "NCPixel",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Position = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
Price = table.Column<long>(type: "INTEGER", nullable: false),
|
||||
OwnerId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||
Color = table.Column<uint>(type: "INTEGER", nullable: false),
|
||||
Text = table.Column<string>(type: "TEXT", maxLength: 256, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_NCPixel", x => x.Id);
|
||||
table.UniqueConstraint("AK_NCPixel_Position", x => x.Position);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_DiscordUser_Username",
|
||||
table: "DiscordUser",
|
||||
column: "Username");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_NCPixel_OwnerId",
|
||||
table: "NCPixel",
|
||||
column: "OwnerId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "NCPixel");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_DiscordUser_Username",
|
||||
table: "DiscordUser");
|
||||
}
|
||||
}
|
||||
}
|
2973
src/NadekoBot/Migrations/Sqlite/20241102022949_no-discrim-and-flag-translate.Designer.cs
generated
Normal file
2973
src/NadekoBot/Migrations/Sqlite/20241102022949_no-discrim-and-flag-translate.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class nodiscrimandflagtranslate : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
MigrationQueries.UpdateUsernames(migrationBuilder);
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Discriminator",
|
||||
table: "DiscordUser");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "FlagTranslateChannel",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
GuildId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||
ChannelId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||
DateAdded = table.Column<DateTime>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_FlagTranslateChannel", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_FlagTranslateChannel_GuildId_ChannelId",
|
||||
table: "FlagTranslateChannel",
|
||||
columns: new[] { "GuildId", "ChannelId" },
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "FlagTranslateChannel");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Discriminator",
|
||||
table: "DiscordUser",
|
||||
type: "TEXT",
|
||||
nullable: true);
|
||||
}
|
||||
}
|
||||
}
|
@@ -15,7 +15,7 @@ namespace NadekoBot.Migrations
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "8.0.4");
|
||||
modelBuilder.HasAnnotation("ProductVersion", "8.0.8");
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Db.Models.AntiAltSetting", b =>
|
||||
{
|
||||
@@ -560,9 +560,6 @@ namespace NadekoBot.Migrations
|
||||
b.Property<DateTime?>("DateAdded")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Discriminator")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("IsClubAdmin")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
@@ -596,6 +593,8 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.HasIndex("Username");
|
||||
|
||||
b.ToTable("DiscordUser");
|
||||
});
|
||||
|
||||
@@ -741,6 +740,29 @@ namespace NadekoBot.Migrations
|
||||
b.ToTable("FilteredWord");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Db.Models.FlagTranslateChannel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<ulong>("ChannelId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime?>("DateAdded")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<ulong>("GuildId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GuildId", "ChannelId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("FlagTranslateChannel");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -907,33 +929,9 @@ namespace NadekoBot.Migrations
|
||||
b.Property<string>("AutoAssignRoleIds")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("AutoDeleteByeMessagesTimer")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AutoDeleteGreetMessagesTimer")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("AutoDeleteSelfAssignedRoleMessages")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("BoostMessage")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<ulong>("BoostMessageChannelId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("BoostMessageDeleteAfter")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<ulong>("ByeMessageChannelId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ChannelByeMessageText")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ChannelGreetMessageText")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("CleverbotEnabled")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
@@ -949,9 +947,6 @@ namespace NadekoBot.Migrations
|
||||
b.Property<bool>("DisableGlobalExpressions")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("DmGreetMessageText")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("ExclusiveSelfAssignedRoles")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
@@ -967,9 +962,6 @@ namespace NadekoBot.Migrations
|
||||
b.Property<ulong?>("GameVoiceChannel")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<ulong>("GreetMessageChannelId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<ulong>("GuildId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
@@ -988,18 +980,6 @@ namespace NadekoBot.Migrations
|
||||
b.Property<string>("Prefix")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("SendBoostMessage")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("SendChannelByeMessage")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("SendChannelGreetMessage")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("SendDmGreetMessage")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("StickyRoles")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
@@ -1255,6 +1235,38 @@ namespace NadekoBot.Migrations
|
||||
b.ToTable("MutedUserId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Db.Models.NCPixel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("Color")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<ulong>("OwnerId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Position")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<long>("Price")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("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<int>("Id")
|
||||
@@ -2225,7 +2237,7 @@ namespace NadekoBot.Migrations
|
||||
b.Property<DateTime?>("DateAdded")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("GuildConfigId")
|
||||
b.Property<ulong>("GuildId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Punishment")
|
||||
@@ -2239,7 +2251,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
b.HasAlternateKey("GuildId", "Count");
|
||||
|
||||
b.ToTable("WarningPunishment");
|
||||
});
|
||||
@@ -2351,6 +2363,42 @@ namespace NadekoBot.Migrations
|
||||
b.ToTable("XpShopOwnedItem");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.GreetSettings", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AutoDeleteTimer")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasDefaultValue(0);
|
||||
|
||||
b.Property<ulong?>("ChannelId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("GreetType")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<ulong>("GuildId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("IsEnabled")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasDefaultValue(false);
|
||||
|
||||
b.Property<string>("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)
|
||||
@@ -2766,14 +2814,6 @@ namespace NadekoBot.Migrations
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Db.Models.WarningPunishment", b =>
|
||||
{
|
||||
b.HasOne("NadekoBot.Db.Models.GuildConfig", null)
|
||||
.WithMany("WarnPunishments")
|
||||
.HasForeignKey("GuildConfigId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Db.Models.XpCurrencyReward", b =>
|
||||
{
|
||||
b.HasOne("NadekoBot.Db.Models.XpSettings", "XpSettings")
|
||||
@@ -2886,8 +2926,6 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.Navigation("VcRoleInfos");
|
||||
|
||||
b.Navigation("WarnPunishments");
|
||||
|
||||
b.Navigation("XpSettings");
|
||||
});
|
||||
|
||||
|
@@ -25,6 +25,13 @@ public partial class Administration
|
||||
return;
|
||||
}
|
||||
|
||||
// the user can't aar the role which is greater or equal to the bot's highest role
|
||||
if (role.Position >= ((SocketGuild)ctx.Guild).CurrentUser.GetRoles().Max(x => x.Position))
|
||||
{
|
||||
await Response().Error(strs.hierarchy).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
var roles = await _service.ToggleAarAsync(ctx.Guild.Id, role.Id);
|
||||
if (roles.Count == 0)
|
||||
await Response().Confirm(strs.aar_disabled).SendAsync();
|
||||
|
@@ -1,4 +1,3 @@
|
||||
#nullable disable
|
||||
using LinqToDB;
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using NadekoBot.Common.ModuleBehaviors;
|
||||
@@ -11,7 +10,7 @@ public class AutoPublishService : IExecNoCommand, IReadyExecutor, INService
|
||||
private readonly DbService _db;
|
||||
private readonly DiscordSocketClient _client;
|
||||
private readonly IBotCredsProvider _creds;
|
||||
private ConcurrentDictionary<ulong, ulong> _enabled;
|
||||
private ConcurrentDictionary<ulong, ulong> _enabled = new();
|
||||
|
||||
public AutoPublishService(DbService db, DiscordSocketClient client, IBotCredsProvider creds)
|
||||
{
|
||||
@@ -20,7 +19,7 @@ public class AutoPublishService : IExecNoCommand, IReadyExecutor, INService
|
||||
_creds = creds;
|
||||
}
|
||||
|
||||
public async Task ExecOnNoCommandAsync(IGuild guild, IUserMessage msg)
|
||||
public async Task ExecOnNoCommandAsync(IGuild? guild, IUserMessage msg)
|
||||
{
|
||||
if (guild is null)
|
||||
return;
|
||||
@@ -49,6 +48,18 @@ public class AutoPublishService : IExecNoCommand, IReadyExecutor, INService
|
||||
_enabled = items
|
||||
.ToDictionary(x => x.GuildId, x => x.ChannelId)
|
||||
.ToConcurrent();
|
||||
|
||||
_client.LeftGuild += ClientOnLeftGuild;
|
||||
}
|
||||
|
||||
private async Task ClientOnLeftGuild(SocketGuild guild)
|
||||
{
|
||||
await using var ctx = _db.GetDbContext();
|
||||
_enabled.TryRemove(guild.Id, out _);
|
||||
|
||||
await ctx.GetTable<AutoPublishChannel>()
|
||||
.Where(x => x.GuildId == guild.Id)
|
||||
.DeleteAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> ToggleAutoPublish(ulong guildId, ulong channelId)
|
||||
|
@@ -1,14 +1,20 @@
|
||||
namespace NadekoBot.Modules.Administration.DangerousCommands;
|
||||
using NadekoBot.Modules.Administration.DangerousCommands;
|
||||
|
||||
namespace NadekoBot.Modules.Administration;
|
||||
|
||||
public partial class Administration
|
||||
{
|
||||
[Group]
|
||||
public class CleanupCommands : CleanupModuleBase
|
||||
public partial class CleanupCommands : CleanupModuleBase
|
||||
{
|
||||
private readonly ICleanupService _svc;
|
||||
private readonly IBotCredsProvider _creds;
|
||||
|
||||
public CleanupCommands(ICleanupService svc)
|
||||
=> _svc = svc;
|
||||
public CleanupCommands(ICleanupService svc, IBotCredsProvider creds)
|
||||
{
|
||||
_svc = svc;
|
||||
_creds = creds;
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[OwnerOnly]
|
||||
@@ -37,5 +43,32 @@ public partial class Administration
|
||||
|
||||
await Response().Text("This guild's bot data will be saved.").SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[OwnerOnly]
|
||||
public async Task LeaveUnkeptServers(int startShardId, int shardMultiplier = 3000)
|
||||
{
|
||||
var keptGuildCount = await _svc.GetKeptGuildCount();
|
||||
|
||||
var response = await PromptUserConfirmAsync(new EmbedBuilder()
|
||||
.WithDescription($"""
|
||||
Do you want the bot to leave all unkept servers?
|
||||
|
||||
There are currently {keptGuildCount} kept servers.
|
||||
|
||||
**This is a highly destructive and irreversible action.**
|
||||
"""));
|
||||
|
||||
if (!response)
|
||||
return;
|
||||
|
||||
for (var shardId = startShardId; shardId < _creds.GetCreds().TotalShards; shardId++)
|
||||
{
|
||||
await _svc.StartLeavingUnkeptServers(shardId);
|
||||
await Task.Delay(shardMultiplier * 1000);
|
||||
}
|
||||
|
||||
await ctx.OkAsync();
|
||||
}
|
||||
}
|
||||
}
|
@@ -9,9 +9,12 @@ namespace NadekoBot.Modules.Administration.DangerousCommands;
|
||||
|
||||
public sealed class CleanupService : ICleanupService, IReadyExecutor, INService
|
||||
{
|
||||
private TypedKey<KeepReport> _cleanupReportKey = new("cleanup:report");
|
||||
private TypedKey<bool> _cleanupTriggerKey = new("cleanup:trigger");
|
||||
|
||||
private TypedKey<int> _keepTriggerKey = new("keep:trigger");
|
||||
|
||||
private readonly IPubSub _pubSub;
|
||||
private TypedKey<KeepReport> _keepReportKey = new("cleanup:report");
|
||||
private TypedKey<bool> _keepTriggerKey = new("cleanup:trigger");
|
||||
private readonly DiscordSocketClient _client;
|
||||
private ConcurrentDictionary<int, ulong[]> guildIds = new();
|
||||
private readonly IBotCredsProvider _creds;
|
||||
@@ -29,11 +32,90 @@ public sealed class CleanupService : ICleanupService, IReadyExecutor, INService
|
||||
_db = db;
|
||||
}
|
||||
|
||||
public async Task OnReadyAsync()
|
||||
{
|
||||
await _pubSub.Sub(_cleanupTriggerKey, OnCleanupTrigger);
|
||||
await _pubSub.Sub(_keepTriggerKey, InternalTriggerKeep);
|
||||
|
||||
_client.JoinedGuild += ClientOnJoinedGuild;
|
||||
|
||||
if (_client.ShardId == 0)
|
||||
await _pubSub.Sub(_cleanupReportKey, OnKeepReport);
|
||||
}
|
||||
|
||||
private bool keepTriggered = false;
|
||||
|
||||
private async ValueTask InternalTriggerKeep(int shardId)
|
||||
{
|
||||
if (_client.ShardId != shardId)
|
||||
return;
|
||||
|
||||
if (keepTriggered)
|
||||
return;
|
||||
|
||||
keepTriggered = true;
|
||||
try
|
||||
{
|
||||
var allGuildIds = _client.Guilds.Select(x => x.Id).ToArray();
|
||||
|
||||
HashSet<ulong> dontDelete;
|
||||
await using (var db = _db.GetDbContext())
|
||||
{
|
||||
await using var ctx = db.CreateLinqToDBContext();
|
||||
var table = ctx.CreateTable<KeptGuilds>(tableOptions: TableOptions.CheckExistence);
|
||||
|
||||
var dontDeleteList = await table
|
||||
.Where(x => allGuildIds.Contains(x.GuildId))
|
||||
.Select(x => x.GuildId)
|
||||
.ToListAsyncLinqToDB();
|
||||
|
||||
dontDelete = dontDeleteList.ToHashSet();
|
||||
}
|
||||
|
||||
Log.Information("Leaving {RemainingCount} guilds, 1 every second. {DontDeleteCount} will remain",
|
||||
allGuildIds.Length - dontDelete.Count,
|
||||
dontDelete.Count);
|
||||
|
||||
foreach (var guildId in allGuildIds)
|
||||
{
|
||||
if (dontDelete.Contains(guildId))
|
||||
continue;
|
||||
|
||||
await Task.Delay(1016);
|
||||
|
||||
SocketGuild? guild = null;
|
||||
try
|
||||
{
|
||||
guild = _client.GetGuild(guildId);
|
||||
|
||||
if (guild is null)
|
||||
{
|
||||
Log.Warning("Unable to find guild {GuildId}", guildId);
|
||||
continue;
|
||||
}
|
||||
|
||||
await guild.LeaveAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning("Unable to leave guild {GuildName} [{GuildId}]: {ErrorMessage}",
|
||||
guild?.Name,
|
||||
guildId,
|
||||
ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
keepTriggered = false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<KeepResult?> DeleteMissingGuildDataAsync()
|
||||
{
|
||||
guildIds = new();
|
||||
var totalShards = _creds.GetCreds().TotalShards;
|
||||
await _pubSub.Pub(_keepTriggerKey, true);
|
||||
await _pubSub.Pub(_cleanupTriggerKey, true);
|
||||
var counter = 0;
|
||||
while (guildIds.Keys.Count < totalShards)
|
||||
{
|
||||
@@ -125,6 +207,18 @@ public sealed class CleanupService : ICleanupService, IReadyExecutor, INService
|
||||
.Contains(x.GuildId))
|
||||
.DeleteAsync();
|
||||
|
||||
// delete autopublish channels
|
||||
await ctx.GetTable<AutoPublishChannel>()
|
||||
.Where(x => !tempTable.Select(x => x.GuildId)
|
||||
.Contains(x.GuildId))
|
||||
.DeleteAsync();
|
||||
|
||||
// delete greet settings
|
||||
await ctx.GetTable<GreetSettings>()
|
||||
.Where(x => !tempTable.Select(x => x.GuildId)
|
||||
.Contains(x.GuildId))
|
||||
.DeleteAsync();
|
||||
|
||||
return new()
|
||||
{
|
||||
GuildCount = guildIds.Keys.Count,
|
||||
@@ -135,9 +229,7 @@ public sealed class CleanupService : ICleanupService, IReadyExecutor, INService
|
||||
{
|
||||
await using var db = _db.GetDbContext();
|
||||
await using var ctx = db.CreateLinqToDBContext();
|
||||
|
||||
var table = ctx.CreateTable<KeptGuilds>(tableOptions: TableOptions.CheckExistence);
|
||||
|
||||
if (await table.AnyAsyncLinqToDB(x => x.GuildId == guildId))
|
||||
return false;
|
||||
|
||||
@@ -149,30 +241,31 @@ public sealed class CleanupService : ICleanupService, IReadyExecutor, INService
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<int> GetKeptGuildCount()
|
||||
{
|
||||
await using var db = _db.GetDbContext();
|
||||
await using var ctx = db.CreateLinqToDBContext();
|
||||
var table = ctx.CreateTable<KeptGuilds>(tableOptions: TableOptions.CheckExistence);
|
||||
return await table.CountAsync();
|
||||
}
|
||||
|
||||
public async Task StartLeavingUnkeptServers(int shardId)
|
||||
=> await _pubSub.Pub(_keepTriggerKey, shardId);
|
||||
|
||||
private ValueTask OnKeepReport(KeepReport report)
|
||||
{
|
||||
guildIds[report.ShardId] = report.GuildIds;
|
||||
return default;
|
||||
}
|
||||
|
||||
public async Task OnReadyAsync()
|
||||
{
|
||||
await _pubSub.Sub(_keepTriggerKey, OnKeepTrigger);
|
||||
|
||||
_client.JoinedGuild += ClientOnJoinedGuild;
|
||||
|
||||
if (_client.ShardId == 0)
|
||||
await _pubSub.Sub(_keepReportKey, OnKeepReport);
|
||||
}
|
||||
|
||||
private async Task ClientOnJoinedGuild(SocketGuild arg)
|
||||
{
|
||||
await KeepGuild(arg.Id);
|
||||
}
|
||||
|
||||
private ValueTask OnKeepTrigger(bool arg)
|
||||
private ValueTask OnCleanupTrigger(bool arg)
|
||||
{
|
||||
_pubSub.Pub(_keepReportKey,
|
||||
_pubSub.Pub(_cleanupReportKey,
|
||||
new KeepReport()
|
||||
{
|
||||
ShardId = _client.ShardId,
|
||||
|
@@ -139,7 +139,6 @@ public partial class Administration
|
||||
public Task DeleteXp()
|
||||
=> ConfirmActionInternalAsync("Delete Xp", () => _xcs.DeleteXp());
|
||||
|
||||
|
||||
[Cmd]
|
||||
[OwnerOnly]
|
||||
public Task DeleteWaifus()
|
||||
|
@@ -4,4 +4,6 @@ public interface ICleanupService
|
||||
{
|
||||
Task<KeepResult?> DeleteMissingGuildDataAsync();
|
||||
Task<bool> KeepGuild(ulong guildId);
|
||||
Task<int> GetKeptGuildCount();
|
||||
Task StartLeavingUnkeptServers(int shardId);
|
||||
}
|
@@ -8,236 +8,240 @@ public partial class Administration
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public async Task Boost()
|
||||
{
|
||||
var enabled = await _service.ToggleBoost(ctx.Guild.Id, ctx.Channel.Id);
|
||||
|
||||
if (enabled)
|
||||
await Response().Confirm(strs.boost_on).SendAsync();
|
||||
else
|
||||
await Response().Pending(strs.boost_off).SendAsync();
|
||||
}
|
||||
public Task Boost()
|
||||
=> Toggle(GreetType.Boost);
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public async Task BoostDel(int timer = 30)
|
||||
public Task BoostDel(int timer = 30)
|
||||
=> SetDel(GreetType.Boost, timer);
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public Task BoostMsg([Leftover] string? text = null)
|
||||
=> SetMsg(GreetType.Boost, text);
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public Task Greet()
|
||||
=> Toggle(GreetType.Greet);
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public Task GreetDel(int timer = 30)
|
||||
=> SetDel(GreetType.Greet, timer);
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public Task GreetMsg([Leftover] string? text = null)
|
||||
=> SetMsg(GreetType.Greet, text);
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public Task GreetDm()
|
||||
=> Toggle(GreetType.GreetDm);
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public Task GreetDmMsg([Leftover] string? text = null)
|
||||
=> SetMsg(GreetType.GreetDm, text);
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public Task Bye()
|
||||
=> Toggle(GreetType.Bye);
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public Task ByeDel(int timer = 30)
|
||||
=> SetDel(GreetType.Bye, timer);
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public Task ByeMsg([Leftover] string? text = null)
|
||||
=> SetMsg(GreetType.Bye, text);
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public Task GreetTest([Leftover] IGuildUser? user = null)
|
||||
=> Test(GreetType.Greet, user);
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public Task GreetDmTest([Leftover] IGuildUser? user = null)
|
||||
=> Test(GreetType.GreetDm, user);
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
[Ratelimit(5)]
|
||||
public Task ByeTest([Leftover] IGuildUser? user = null)
|
||||
=> Test(GreetType.Bye, user);
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
[Ratelimit(5)]
|
||||
public Task BoostTest([Leftover] IGuildUser? user = null)
|
||||
=> Test(GreetType.Boost, user);
|
||||
|
||||
|
||||
public async Task Toggle(GreetType type)
|
||||
{
|
||||
var enabled = await _service.SetGreet(ctx.Guild.Id, ctx.Channel.Id, type);
|
||||
|
||||
if (enabled)
|
||||
await Response()
|
||||
.Confirm(
|
||||
type switch
|
||||
{
|
||||
GreetType.Boost => strs.boost_on,
|
||||
GreetType.Greet => strs.greet_on,
|
||||
GreetType.Bye => strs.bye_on,
|
||||
GreetType.GreetDm => strs.greetdm_on,
|
||||
_ => strs.error
|
||||
}
|
||||
)
|
||||
.SendAsync();
|
||||
else
|
||||
await Response()
|
||||
.Pending(
|
||||
type switch
|
||||
{
|
||||
GreetType.Boost => strs.boost_off,
|
||||
GreetType.Greet => strs.greet_off,
|
||||
GreetType.Bye => strs.bye_off,
|
||||
GreetType.GreetDm => strs.greetdm_off,
|
||||
_ => strs.error
|
||||
}
|
||||
)
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
|
||||
public async Task SetDel(GreetType type, int timer)
|
||||
{
|
||||
if (timer is < 0 or > 600)
|
||||
return;
|
||||
|
||||
await _service.SetBoostDel(ctx.Guild.Id, timer);
|
||||
await _service.SetDeleteTimer(ctx.Guild.Id, type, timer);
|
||||
|
||||
if (timer > 0)
|
||||
await Response().Confirm(strs.boostdel_on(timer)).SendAsync();
|
||||
await Response()
|
||||
.Confirm(
|
||||
type switch
|
||||
{
|
||||
GreetType.Boost => strs.boostdel_on(timer),
|
||||
GreetType.Greet => strs.greetdel_on(timer),
|
||||
GreetType.Bye => strs.byedel_on(timer),
|
||||
_ => strs.error
|
||||
}
|
||||
)
|
||||
.SendAsync();
|
||||
else
|
||||
await Response().Pending(strs.boostdel_off).SendAsync();
|
||||
await Response()
|
||||
.Pending(
|
||||
type switch
|
||||
{
|
||||
GreetType.Boost => strs.boostdel_off,
|
||||
GreetType.Greet => strs.greetdel_off,
|
||||
GreetType.Bye => strs.byedel_off,
|
||||
_ => strs.error
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public async Task BoostMsg([Leftover] string? text = null)
|
||||
|
||||
public async Task SetMsg(GreetType type, string? text = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
var boostMessage = _service.GetBoostMessage(ctx.Guild.Id);
|
||||
await Response().Confirm(strs.boostmsg_cur(boostMessage?.SanitizeMentions())).SendAsync();
|
||||
var conf = await _service.GetGreetSettingsAsync(ctx.Guild.Id, type);
|
||||
var msg = conf?.MessageText ?? GreetService.GetDefaultGreet(type);
|
||||
await Response()
|
||||
.Confirm(
|
||||
type switch
|
||||
{
|
||||
GreetType.Boost => strs.boostmsg_cur(msg),
|
||||
GreetType.Greet => strs.greetmsg_cur(msg),
|
||||
GreetType.Bye => strs.byemsg_cur(msg),
|
||||
GreetType.GreetDm => strs.greetdmmsg_cur(msg),
|
||||
_ => strs.error
|
||||
})
|
||||
.SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
var sendBoostEnabled = _service.SetBoostMessage(ctx.Guild.Id, ref text);
|
||||
var isEnabled = await _service.SetMessage(ctx.Guild.Id, type, text);
|
||||
|
||||
await Response().Confirm(strs.boostmsg_new).SendAsync();
|
||||
if (!sendBoostEnabled)
|
||||
await Response().Pending(strs.boostmsg_enable($"`{prefix}boost`")).SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public async Task GreetDel(int timer = 30)
|
||||
await Response()
|
||||
.Confirm(type switch
|
||||
{
|
||||
if (timer is < 0 or > 600)
|
||||
return;
|
||||
GreetType.Boost => strs.boostmsg_new,
|
||||
GreetType.Greet => strs.greetmsg_new,
|
||||
GreetType.Bye => strs.byemsg_new,
|
||||
GreetType.GreetDm => strs.greetdmmsg_new,
|
||||
_ => strs.error
|
||||
})
|
||||
.SendAsync();
|
||||
|
||||
await _service.SetGreetDel(ctx.Guild.Id, timer);
|
||||
|
||||
if (timer > 0)
|
||||
await Response().Confirm(strs.greetdel_on(timer)).SendAsync();
|
||||
else
|
||||
await Response().Pending(strs.greetdel_off).SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public async Task Greet()
|
||||
if (!isEnabled)
|
||||
{
|
||||
var enabled = await _service.SetGreet(ctx.Guild.Id, ctx.Channel.Id);
|
||||
|
||||
if (enabled)
|
||||
await Response().Confirm(strs.greet_on).SendAsync();
|
||||
else
|
||||
await Response().Pending(strs.greet_off).SendAsync();
|
||||
await SendGreetEnableHint(type);
|
||||
}
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public async Task GreetMsg([Leftover] string? text = null)
|
||||
private static string GetCmdName(GreetType type)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
var cmdName = type switch
|
||||
{
|
||||
var greetMsg = _service.GetGreetMsg(ctx.Guild.Id);
|
||||
await Response().Confirm(strs.greetmsg_cur(greetMsg?.SanitizeMentions())).SendAsync();
|
||||
return;
|
||||
GreetType.Greet => "greet",
|
||||
GreetType.Bye => "bye",
|
||||
GreetType.Boost => "boost",
|
||||
GreetType.GreetDm => "greetdm",
|
||||
_ => "unknown_command"
|
||||
};
|
||||
return cmdName;
|
||||
}
|
||||
|
||||
var sendGreetEnabled = _service.SetGreetMessage(ctx.Guild.Id, ref text);
|
||||
|
||||
await Response().Confirm(strs.greetmsg_new).SendAsync();
|
||||
|
||||
if (!sendGreetEnabled)
|
||||
await Response().Pending(strs.greetmsg_enable($"`{prefix}greet`")).SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public async Task GreetDm()
|
||||
{
|
||||
var enabled = await _service.SetGreetDm(ctx.Guild.Id);
|
||||
|
||||
if (enabled)
|
||||
await Response().Confirm(strs.greetdm_on).SendAsync();
|
||||
else
|
||||
await Response().Confirm(strs.greetdm_off).SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public async Task GreetDmMsg([Leftover] string? text = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
var dmGreetMsg = _service.GetDmGreetMsg(ctx.Guild.Id);
|
||||
await Response().Confirm(strs.greetdmmsg_cur(dmGreetMsg?.SanitizeMentions())).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
var sendGreetEnabled = _service.SetGreetDmMessage(ctx.Guild.Id, ref text);
|
||||
|
||||
await Response().Confirm(strs.greetdmmsg_new).SendAsync();
|
||||
if (!sendGreetEnabled)
|
||||
await Response().Pending(strs.greetdmmsg_enable($"`{prefix}greetdm`")).SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public async Task Bye()
|
||||
{
|
||||
var enabled = await _service.SetBye(ctx.Guild.Id, ctx.Channel.Id);
|
||||
|
||||
if (enabled)
|
||||
await Response().Confirm(strs.bye_on).SendAsync();
|
||||
else
|
||||
await Response().Confirm(strs.bye_off).SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public async Task ByeMsg([Leftover] string? text = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
var byeMsg = _service.GetByeMessage(ctx.Guild.Id);
|
||||
await Response().Confirm(strs.byemsg_cur(byeMsg?.SanitizeMentions())).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
var sendByeEnabled = _service.SetByeMessage(ctx.Guild.Id, ref text);
|
||||
|
||||
await Response().Confirm(strs.byemsg_new).SendAsync();
|
||||
if (!sendByeEnabled)
|
||||
await Response().Pending(strs.byemsg_enable($"`{prefix}bye`")).SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
public async Task ByeDel(int timer = 30)
|
||||
{
|
||||
await _service.SetByeDel(ctx.Guild.Id, timer);
|
||||
|
||||
if (timer > 0)
|
||||
await Response().Confirm(strs.byedel_on(timer)).SendAsync();
|
||||
else
|
||||
await Response().Pending(strs.byedel_off).SendAsync();
|
||||
}
|
||||
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
[Ratelimit(5)]
|
||||
public async Task ByeTest([Leftover] IGuildUser? user = null)
|
||||
public async Task Test(GreetType type, IGuildUser? user = null)
|
||||
{
|
||||
user ??= (IGuildUser)ctx.User;
|
||||
|
||||
await _service.ByeTest((ITextChannel)ctx.Channel, user);
|
||||
var enabled = _service.GetByeEnabled(ctx.Guild.Id);
|
||||
if (!enabled)
|
||||
await Response().Pending(strs.byemsg_enable($"`{prefix}bye`")).SendAsync();
|
||||
await _service.Test(ctx.Guild.Id, type, (ITextChannel)ctx.Channel, user);
|
||||
var conf = await _service.GetGreetSettingsAsync(ctx.Guild.Id, type);
|
||||
|
||||
if (conf?.IsEnabled is not true)
|
||||
await SendGreetEnableHint(type);
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
[Ratelimit(5)]
|
||||
public async Task GreetTest([Leftover] IGuildUser? user = null)
|
||||
private async Task SendGreetEnableHint(GreetType type)
|
||||
{
|
||||
user ??= (IGuildUser)ctx.User;
|
||||
var cmd = $"`{prefix}{GetCmdName(type)}`";
|
||||
|
||||
await _service.GreetTest((ITextChannel)ctx.Channel, user);
|
||||
var enabled = _service.GetGreetEnabled(ctx.Guild.Id);
|
||||
if (!enabled)
|
||||
await Response().Pending(strs.greetmsg_enable($"`{prefix}greet`")).SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
[Ratelimit(5)]
|
||||
public async Task GreetDmTest([Leftover] IGuildUser? user = null)
|
||||
var str = type switch
|
||||
{
|
||||
user ??= (IGuildUser)ctx.User;
|
||||
GreetType.Greet => strs.greetmsg_enable(cmd),
|
||||
GreetType.Bye => strs.byemsg_enable(cmd),
|
||||
GreetType.Boost => strs.boostmsg_enable(cmd),
|
||||
GreetType.GreetDm => strs.greetdmmsg_enable(cmd),
|
||||
_ => strs.error
|
||||
};
|
||||
|
||||
var success = await _service.GreetDmTest(user);
|
||||
if (success)
|
||||
await ctx.OkAsync();
|
||||
else
|
||||
await ctx.WarningAsync();
|
||||
var enabled = _service.GetGreetDmEnabled(ctx.Guild.Id);
|
||||
if (!enabled)
|
||||
await Response().Pending(strs.greetdmmsg_enable($"`{prefix}greetdm`")).SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageGuild)]
|
||||
[Ratelimit(5)]
|
||||
public async Task BoostTest([Leftover] IGuildUser? user = null)
|
||||
{
|
||||
user ??= (IGuildUser)ctx.User;
|
||||
|
||||
await _service.BoostTest((ITextChannel)ctx.Channel, user);
|
||||
var enabled = _service.GetBoostEnabled(ctx.Guild.Id);
|
||||
if (!enabled)
|
||||
await Response().Pending(strs.boostmsg_enable($"`{prefix}boost`")).SendAsync();
|
||||
await Response().Pending(str).SendAsync();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,71 +0,0 @@
|
||||
namespace NadekoBot.Services;
|
||||
|
||||
public class GreetGrouper<T>
|
||||
{
|
||||
private readonly Dictionary<ulong, HashSet<T>> _group;
|
||||
private readonly object _locker = new();
|
||||
|
||||
public GreetGrouper()
|
||||
=> _group = new();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a group, if group already exists, adds the specified user
|
||||
/// </summary>
|
||||
/// <param name="guildId">Id of the server for which to create group for</param>
|
||||
/// <param name="toAddIfExists">User to add if group already exists</param>
|
||||
/// <returns></returns>
|
||||
public bool CreateOrAdd(ulong guildId, T toAddIfExists)
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
if (_group.TryGetValue(guildId, out var list))
|
||||
{
|
||||
list.Add(toAddIfExists);
|
||||
return false;
|
||||
}
|
||||
|
||||
_group[guildId] = new();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the specified amount of items from the group. If all items are removed, group will be removed.
|
||||
/// </summary>
|
||||
/// <param name="guildId">Id of the group</param>
|
||||
/// <param name="count">Maximum number of items to retrieve</param>
|
||||
/// <param name="items">Items retrieved</param>
|
||||
/// <returns>Whether the group has no more items left and is deleted</returns>
|
||||
public bool ClearGroup(ulong guildId, int count, out IReadOnlyCollection<T> items)
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
if (_group.TryGetValue(guildId, out var set))
|
||||
{
|
||||
// if we want more than there are, return everything
|
||||
if (count >= set.Count)
|
||||
{
|
||||
items = set;
|
||||
_group.Remove(guildId);
|
||||
return true;
|
||||
}
|
||||
|
||||
// if there are more in the group than what's needed
|
||||
// take the requested number, remove them from the set
|
||||
// and return them
|
||||
var toReturn = set.TakeWhile(_ => count-- != 0).ToList();
|
||||
foreach (var item in toReturn)
|
||||
set.Remove(item);
|
||||
|
||||
items = toReturn;
|
||||
// returning falsemeans group is not yet deleted
|
||||
// because there are items left
|
||||
return false;
|
||||
}
|
||||
|
||||
items = Array.Empty<T>();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,63 +1,101 @@
|
||||
using LinqToDB;
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using LinqToDB.Tools;
|
||||
using NadekoBot.Common.ModuleBehaviors;
|
||||
using NadekoBot.Db.Models;
|
||||
using System.Threading.Channels;
|
||||
|
||||
namespace NadekoBot.Services;
|
||||
|
||||
public class GreetService : INService, IReadyExecutor
|
||||
{
|
||||
public bool GroupGreets
|
||||
=> _bss.Data.GroupGreets;
|
||||
|
||||
private readonly DbService _db;
|
||||
|
||||
private readonly ConcurrentDictionary<ulong, GreetSettings> _guildConfigsCache;
|
||||
private ConcurrentDictionary<GreetType, ConcurrentHashSet<ulong>> _enabled = new();
|
||||
|
||||
private readonly DiscordSocketClient _client;
|
||||
|
||||
private readonly GreetGrouper<IGuildUser> _greets = new();
|
||||
private readonly GreetGrouper<IUser> _byes = new();
|
||||
private readonly BotConfigService _bss;
|
||||
private readonly IReplacementService _repSvc;
|
||||
private readonly IBotCache _cache;
|
||||
private readonly IMessageSenderService _sender;
|
||||
|
||||
private readonly Channel<(GreetSettings, IUser, ITextChannel?)> _greetQueue =
|
||||
Channel.CreateBounded<(GreetSettings, IUser, ITextChannel?)>(
|
||||
new BoundedChannelOptions(60)
|
||||
{
|
||||
FullMode = BoundedChannelFullMode.DropOldest
|
||||
});
|
||||
|
||||
public GreetService(
|
||||
DiscordSocketClient client,
|
||||
IBot bot,
|
||||
DbService db,
|
||||
BotConfigService bss,
|
||||
IMessageSenderService sender,
|
||||
IReplacementService repSvc)
|
||||
IReplacementService repSvc,
|
||||
IBotCache cache
|
||||
)
|
||||
{
|
||||
_db = db;
|
||||
_client = client;
|
||||
_bss = bss;
|
||||
_repSvc = repSvc;
|
||||
_cache = cache;
|
||||
_sender = sender;
|
||||
|
||||
_guildConfigsCache = new(bot.AllGuildConfigs.ToDictionary(g => g.GuildId, GreetSettings.Create));
|
||||
|
||||
_client.UserJoined += OnUserJoined;
|
||||
_client.UserLeft += OnUserLeft;
|
||||
|
||||
bot.JoinedGuild += OnBotJoinedGuild;
|
||||
_client.LeftGuild += OnClientLeftGuild;
|
||||
|
||||
_client.GuildMemberUpdated += ClientOnGuildMemberUpdated;
|
||||
foreach (var type in Enum.GetValues<GreetType>())
|
||||
{
|
||||
_enabled[type] = new();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task OnReadyAsync()
|
||||
{
|
||||
// cache all enabled guilds
|
||||
await using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var guilds = _client.Guilds.Select(x => x.Id).ToList();
|
||||
var enabled = await uow.GetTable<GreetSettings>()
|
||||
.Where(x => x.GuildId.In(guilds))
|
||||
.Where(x => x.IsEnabled)
|
||||
.Select(x => new
|
||||
{
|
||||
x.GuildId,
|
||||
x.GreetType
|
||||
})
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var e in enabled)
|
||||
{
|
||||
_enabled[e.GreetType].Add(e.GuildId);
|
||||
}
|
||||
}
|
||||
|
||||
_client.UserJoined += OnUserJoined;
|
||||
_client.UserLeft += OnUserLeft;
|
||||
|
||||
_client.LeftGuild += OnClientLeftGuild;
|
||||
|
||||
_client.GuildMemberUpdated += ClientOnGuildMemberUpdated;
|
||||
|
||||
while (true)
|
||||
{
|
||||
var (conf, user, compl) = await _greetDmQueue.Reader.ReadAsync();
|
||||
var res = await GreetDmUserInternal(conf, user);
|
||||
compl.TrySetResult(res);
|
||||
await Task.Delay(2000);
|
||||
try
|
||||
{
|
||||
var (conf, user, ch) = await _greetQueue.Reader.ReadAsync();
|
||||
await GreetUsers(conf, ch, user);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Greet Loop almost crashed. Please report this!");
|
||||
}
|
||||
|
||||
await Task.Delay(2016);
|
||||
}
|
||||
}
|
||||
|
||||
private Task ClientOnGuildMemberUpdated(Cacheable<SocketGuildUser, ulong> optOldUser, SocketGuildUser newUser)
|
||||
{
|
||||
if (!_enabled[GreetType.Boost].Contains(newUser.Guild.Id))
|
||||
return Task.CompletedTask;
|
||||
|
||||
// if user is a new booster
|
||||
// or boosted again the same server
|
||||
if ((optOldUser.Value is { PremiumSince: null } && newUser is { PremiumSince: not null })
|
||||
@@ -65,60 +103,74 @@ public class GreetService : INService, IReadyExecutor
|
||||
&& newUser.PremiumSince is { } newDate
|
||||
&& newDate > oldDate))
|
||||
{
|
||||
var conf = GetOrAddSettingsForGuild(newUser.Guild.Id);
|
||||
if (!conf.SendBoostMessage)
|
||||
return Task.CompletedTask;
|
||||
|
||||
_ = Task.Run(TriggerBoostMessage(conf, newUser));
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Func<Task> TriggerBoostMessage(GreetSettings conf, SocketGuildUser user)
|
||||
=> async () =>
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
var channel = user.Guild.GetTextChannel(conf.BoostMessageChannelId);
|
||||
var conf = await GetGreetSettingsAsync(newUser.Guild.Id, GreetType.Boost);
|
||||
|
||||
if (conf is null || !conf.IsEnabled)
|
||||
return;
|
||||
|
||||
ITextChannel? channel = null;
|
||||
if (conf.ChannelId is { } cid)
|
||||
channel = newUser.Guild.GetTextChannel(cid);
|
||||
|
||||
if (channel is null)
|
||||
return;
|
||||
|
||||
await SendBoostMessage(conf, user, channel);
|
||||
};
|
||||
|
||||
private async Task<bool> SendBoostMessage(GreetSettings conf, IGuildUser user, ITextChannel channel)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(conf.BoostMessage))
|
||||
return false;
|
||||
|
||||
var toSend = SmartText.CreateFrom(conf.BoostMessage);
|
||||
|
||||
try
|
||||
{
|
||||
var newContent = await _repSvc.ReplaceAsync(toSend,
|
||||
new(client: _client, guild: user.Guild, channel: channel, users: user));
|
||||
var toDelete = await _sender.Response(channel).Text(newContent).Sanitize(false).SendAsync();
|
||||
if (conf.BoostMessageDeleteAfter > 0)
|
||||
toDelete.DeleteAfter(conf.BoostMessageDeleteAfter);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Error sending boost message");
|
||||
await GreetUsers(conf, channel, newUser);
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private Task OnClientLeftGuild(SocketGuild arg)
|
||||
{
|
||||
_guildConfigsCache.TryRemove(arg.Id, out _);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task OnBotJoinedGuild(GuildConfig gc)
|
||||
private async Task OnClientLeftGuild(SocketGuild guild)
|
||||
{
|
||||
_guildConfigsCache[gc.GuildId] = GreetSettings.Create(gc);
|
||||
foreach (var gt in Enum.GetValues<GreetType>())
|
||||
{
|
||||
_enabled[gt].TryRemove(guild.Id);
|
||||
}
|
||||
|
||||
await using var uow = _db.GetDbContext();
|
||||
await uow.GetTable<GreetSettings>()
|
||||
.Where(x => x.GuildId == guild.Id)
|
||||
.DeleteAsync();
|
||||
}
|
||||
|
||||
private Task OnUserJoined(IGuildUser user)
|
||||
{
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_enabled[GreetType.Greet].Contains(user.GuildId))
|
||||
{
|
||||
var conf = await GetGreetSettingsAsync(user.GuildId, GreetType.Greet);
|
||||
if (conf?.ChannelId is ulong cid)
|
||||
{
|
||||
var channel = await user.Guild.GetTextChannelAsync(cid);
|
||||
if (channel is not null)
|
||||
{
|
||||
await _greetQueue.Writer.WriteAsync((conf, user, channel));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (_enabled[GreetType.GreetDm].Contains(user.GuildId))
|
||||
{
|
||||
var confDm = await GetGreetSettingsAsync(user.GuildId, GreetType.GreetDm);
|
||||
if (confDm is not null)
|
||||
{
|
||||
await _greetQueue.Writer.WriteAsync((confDm, user, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Error in GreetService.OnUserJoined. This should not happen. Please report it");
|
||||
}
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -126,37 +178,27 @@ public class GreetService : INService, IReadyExecutor
|
||||
{
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
if (!_enabled[GreetType.Bye].Contains(guild.Id))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
var conf = GetOrAddSettingsForGuild(guild.Id);
|
||||
var conf = await GetGreetSettingsAsync(guild.Id, GreetType.Bye);
|
||||
|
||||
if (!conf.SendChannelByeMessage)
|
||||
if (conf?.ChannelId is not { } cid)
|
||||
return;
|
||||
var channel = guild.TextChannels.FirstOrDefault(c => c.Id == conf.ByeMessageChannelId);
|
||||
|
||||
var channel = guild.GetChannel(cid) as ITextChannel;
|
||||
if (channel is null) //maybe warn the server owner that the channel is missing
|
||||
{
|
||||
Log.Warning("Channel {ChannelId} in {GuildId} was not found. Bye message will be disabled",
|
||||
conf.ChannelId,
|
||||
conf.GuildId);
|
||||
await SetGreet(guild.Id, null, GreetType.Bye, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GroupGreets)
|
||||
{
|
||||
// if group is newly created, greet that user right away,
|
||||
// but any user which joins in the next 5 seconds will
|
||||
// be greeted in a group greet
|
||||
if (_byes.CreateOrAdd(guild.Id, user))
|
||||
{
|
||||
// greet single user
|
||||
await ByeUsers(conf, channel, new[] { user });
|
||||
var groupClear = false;
|
||||
while (!groupClear)
|
||||
{
|
||||
await Task.Delay(5000);
|
||||
groupClear = _byes.ClearGroup(guild.Id, 5, out var toBye);
|
||||
await ByeUsers(conf, channel, toBye);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
await ByeUsers(conf, channel, new[] { user });
|
||||
await _greetQueue.Writer.WriteAsync((conf, user, channel));
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -166,98 +208,63 @@ public class GreetService : INService, IReadyExecutor
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public string? GetDmGreetMsg(ulong id)
|
||||
private TypedKey<GreetSettings?> GreetSettingsKey(ulong gid, GreetType type)
|
||||
=> new($"greet_settings:{gid}:{type}");
|
||||
|
||||
public async Task<GreetSettings?> GetGreetSettingsAsync(ulong gid, GreetType type)
|
||||
=> await _cache.GetOrAddAsync<GreetSettings?>(GreetSettingsKey(gid, type),
|
||||
() => InternalGetGreetSettingsAsync(gid, type),
|
||||
TimeSpan.FromSeconds(3));
|
||||
|
||||
private async Task<GreetSettings?> InternalGetGreetSettingsAsync(ulong gid, GreetType type)
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
return uow.GuildConfigsForId(id, set => set).DmGreetMessageText;
|
||||
await using var uow = _db.GetDbContext();
|
||||
var res = await uow.GetTable<GreetSettings>()
|
||||
.Where(x => x.GuildId == gid && x.GreetType == type)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (res is not null)
|
||||
res.MessageText ??= GetDefaultGreet(type);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public string? GetGreetMsg(ulong gid)
|
||||
private async Task GreetUsers(GreetSettings conf, ITextChannel? channel, IUser user)
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
return uow.GuildConfigsForId(gid, set => set).ChannelGreetMessageText;
|
||||
if (conf.GreetType == GreetType.GreetDm)
|
||||
{
|
||||
if (user is not IGuildUser gu)
|
||||
return;
|
||||
|
||||
await GreetDmUserInternal(conf, gu);
|
||||
return;
|
||||
}
|
||||
|
||||
public string? GetBoostMessage(ulong gid)
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
return uow.GuildConfigsForId(gid, set => set).BoostMessage;
|
||||
}
|
||||
|
||||
public GreetSettings GetGreetSettings(ulong gid)
|
||||
{
|
||||
if (_guildConfigsCache.TryGetValue(gid, out var gs))
|
||||
return gs;
|
||||
|
||||
using var uow = _db.GetDbContext();
|
||||
return GreetSettings.Create(uow.GuildConfigsForId(gid, set => set));
|
||||
}
|
||||
|
||||
private Task ByeUsers(GreetSettings conf, ITextChannel channel, IUser user)
|
||||
=> ByeUsers(conf, channel, new[] { user });
|
||||
|
||||
private async Task ByeUsers(GreetSettings conf, ITextChannel channel, IReadOnlyCollection<IUser> users)
|
||||
{
|
||||
if (!users.Any())
|
||||
if (channel is null)
|
||||
return;
|
||||
|
||||
var repCtx = new ReplacementContext(client: _client,
|
||||
guild: channel.Guild,
|
||||
channel: channel,
|
||||
users: users.ToArray());
|
||||
user: user);
|
||||
|
||||
var text = SmartText.CreateFrom(conf.ChannelByeMessageText);
|
||||
var text = SmartText.CreateFrom(conf.MessageText);
|
||||
text = await _repSvc.ReplaceAsync(text, repCtx);
|
||||
try
|
||||
{
|
||||
var toDelete = await _sender.Response(channel).Text(text).Sanitize(false).SendAsync();
|
||||
if (conf.AutoDeleteByeMessagesTimer > 0)
|
||||
toDelete.DeleteAfter(conf.AutoDeleteByeMessagesTimer);
|
||||
if (conf.AutoDeleteTimer > 0)
|
||||
toDelete.DeleteAfter(conf.AutoDeleteTimer);
|
||||
}
|
||||
catch (HttpException ex) when (ex.DiscordCode == DiscordErrorCode.InsufficientPermissions
|
||||
|| ex.DiscordCode == DiscordErrorCode.MissingPermissions
|
||||
|| ex.DiscordCode == DiscordErrorCode.UnknownChannel)
|
||||
catch (HttpException ex) when (ex.DiscordCode is DiscordErrorCode.InsufficientPermissions
|
||||
or DiscordErrorCode.MissingPermissions
|
||||
or DiscordErrorCode.UnknownChannel)
|
||||
{
|
||||
Log.Warning(ex,
|
||||
"Missing permissions to send a bye message, the bye message will be disabled on server: {GuildId}",
|
||||
"Missing permissions to send a {GreetType} message, it will be disabled on server: {GuildId}",
|
||||
conf.GreetType,
|
||||
channel.GuildId);
|
||||
await SetBye(channel.GuildId, channel.Id, false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning(ex, "Error embeding bye message");
|
||||
}
|
||||
}
|
||||
|
||||
private Task GreetUsers(GreetSettings conf, ITextChannel channel, IGuildUser user)
|
||||
=> GreetUsers(conf, channel, new[] { user });
|
||||
|
||||
private async Task GreetUsers(GreetSettings conf, ITextChannel channel, IReadOnlyCollection<IGuildUser> users)
|
||||
{
|
||||
if (users.Count == 0)
|
||||
return;
|
||||
|
||||
var repCtx = new ReplacementContext(client: _client,
|
||||
guild: channel.Guild,
|
||||
channel: channel,
|
||||
users: users.ToArray());
|
||||
|
||||
var text = SmartText.CreateFrom(conf.ChannelGreetMessageText);
|
||||
text = await _repSvc.ReplaceAsync(text, repCtx);
|
||||
try
|
||||
{
|
||||
var toDelete = await _sender.Response(channel).Text(text).Sanitize(false).SendAsync();
|
||||
if (conf.AutoDeleteGreetMessagesTimer > 0)
|
||||
toDelete.DeleteAfter(conf.AutoDeleteGreetMessagesTimer);
|
||||
}
|
||||
catch (HttpException ex) when (ex.DiscordCode == DiscordErrorCode.InsufficientPermissions
|
||||
|| ex.DiscordCode == DiscordErrorCode.MissingPermissions
|
||||
|| ex.DiscordCode == DiscordErrorCode.UnknownChannel)
|
||||
{
|
||||
Log.Warning(ex,
|
||||
"Missing permissions to send a bye message, the greet message will be disabled on server: {GuildId}",
|
||||
channel.GuildId);
|
||||
await SetGreet(channel.GuildId, channel.Id, false);
|
||||
await SetGreet(channel.GuildId, channel.Id, conf.GreetType, false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -265,33 +272,12 @@ public class GreetService : INService, IReadyExecutor
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Channel<(GreetSettings, IGuildUser, TaskCompletionSource<bool>)> _greetDmQueue =
|
||||
Channel.CreateBounded<(GreetSettings, IGuildUser, TaskCompletionSource<bool>)>(new BoundedChannelOptions(60)
|
||||
{
|
||||
// The limit of 60 users should be only hit when there's a raid. In that case
|
||||
// probably the best thing to do is to drop newest (raiding) users
|
||||
FullMode = BoundedChannelFullMode.DropNewest
|
||||
});
|
||||
|
||||
|
||||
private async Task<bool> GreetDmUser(GreetSettings conf, IGuildUser user)
|
||||
{
|
||||
var completionSource = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
await _greetDmQueue.Writer.WriteAsync((conf, user, completionSource));
|
||||
return await completionSource.Task;
|
||||
}
|
||||
|
||||
private async Task<bool> GreetDmUserInternal(GreetSettings conf, IGuildUser user)
|
||||
{
|
||||
try
|
||||
{
|
||||
// var rep = new ReplacementBuilder()
|
||||
// .WithUser(user)
|
||||
// .WithServer(_client, (SocketGuild)user.Guild)
|
||||
// .Build();
|
||||
|
||||
var repCtx = new ReplacementContext(client: _client, guild: user.Guild, users: user);
|
||||
var smartText = SmartText.CreateFrom(conf.DmGreetMessageText);
|
||||
var repCtx = new ReplacementContext(client: _client, guild: user.Guild, user: user);
|
||||
var smartText = SmartText.CreateFrom(conf.MessageText);
|
||||
smartText = await _repSvc.ReplaceAsync(smartText, repCtx);
|
||||
|
||||
if (smartText is SmartPlainText pt)
|
||||
@@ -351,8 +337,9 @@ public class GreetService : INService, IReadyExecutor
|
||||
|
||||
await _sender.Response(user).Text(smartText).Sanitize(false).SendAsync();
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning(ex, "Unable to send Greet DM. Probably the user has closed DMs");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -366,303 +353,156 @@ public class GreetService : INService, IReadyExecutor
|
||||
IconUrl = user.Guild.IconUrl
|
||||
};
|
||||
|
||||
private Task OnUserJoined(IGuildUser user)
|
||||
{
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var conf = GetOrAddSettingsForGuild(user.GuildId);
|
||||
|
||||
if (conf.SendChannelGreetMessage)
|
||||
public static string GetDefaultGreet(GreetType greetType)
|
||||
=> greetType switch
|
||||
{
|
||||
var channel = await user.Guild.GetTextChannelAsync(conf.GreetMessageChannelId);
|
||||
if (channel is not null)
|
||||
{
|
||||
if (GroupGreets)
|
||||
{
|
||||
// if group is newly created, greet that user right away,
|
||||
// but any user which joins in the next 5 seconds will
|
||||
// be greeted in a group greet
|
||||
if (_greets.CreateOrAdd(user.GuildId, user))
|
||||
{
|
||||
// greet single user
|
||||
await GreetUsers(conf, channel, new[] { user });
|
||||
var groupClear = false;
|
||||
while (!groupClear)
|
||||
{
|
||||
await Task.Delay(5000);
|
||||
groupClear = _greets.ClearGroup(user.GuildId, 5, out var toGreet);
|
||||
await GreetUsers(conf, channel, toGreet);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
await GreetUsers(conf, channel, new[] { user });
|
||||
}
|
||||
}
|
||||
GreetType.Boost => "%user.mention% has boosted the server!",
|
||||
GreetType.Greet => "%user.mention% has joined the server!",
|
||||
GreetType.Bye => "%user.name% has left the server!",
|
||||
GreetType.GreetDm => "Welcome to the server %user.name%",
|
||||
_ => "%user.name% did something new!"
|
||||
};
|
||||
|
||||
if (conf.SendDmGreetMessage)
|
||||
await GreetDmUser(conf, user);
|
||||
}
|
||||
catch
|
||||
public async Task<bool> SetGreet(
|
||||
ulong guildId,
|
||||
ulong? channelId,
|
||||
GreetType greetType,
|
||||
bool? value = null)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
await using var uow = _db.GetDbContext();
|
||||
var q = uow.GetTable<GreetSettings>();
|
||||
|
||||
if (value is null)
|
||||
value = !_enabled[greetType].Contains(guildId);
|
||||
|
||||
if (value is { } v)
|
||||
{
|
||||
await q
|
||||
.InsertOrUpdateAsync(() => new()
|
||||
{
|
||||
GuildId = guildId,
|
||||
GreetType = greetType,
|
||||
IsEnabled = v,
|
||||
ChannelId = channelId,
|
||||
},
|
||||
(old) => new()
|
||||
{
|
||||
IsEnabled = v,
|
||||
ChannelId = channelId,
|
||||
},
|
||||
() => new()
|
||||
{
|
||||
GuildId = guildId,
|
||||
GreetType = greetType,
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public string? GetByeMessage(ulong gid)
|
||||
if (value is true)
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
return uow.GuildConfigsForId(gid, set => set).ChannelByeMessageText;
|
||||
_enabled[greetType].Add(guildId);
|
||||
return true;
|
||||
}
|
||||
|
||||
public GreetSettings GetOrAddSettingsForGuild(ulong guildId)
|
||||
{
|
||||
if (_guildConfigsCache.TryGetValue(guildId, out var settings))
|
||||
return settings;
|
||||
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var gc = uow.GuildConfigsForId(guildId, set => set);
|
||||
settings = GreetSettings.Create(gc);
|
||||
_enabled[greetType].TryRemove(guildId);
|
||||
return false;
|
||||
}
|
||||
|
||||
_guildConfigsCache.TryAdd(guildId, settings);
|
||||
return settings;
|
||||
|
||||
public async Task<bool> SetMessage(ulong guildId, GreetType greetType, string? message)
|
||||
{
|
||||
await using (var uow = _db.GetDbContext())
|
||||
{
|
||||
await uow.GetTable<GreetSettings>()
|
||||
.InsertOrUpdateAsync(() => new()
|
||||
{
|
||||
GuildId = guildId,
|
||||
GreetType = greetType,
|
||||
MessageText = message
|
||||
},
|
||||
x => new()
|
||||
{
|
||||
MessageText = message
|
||||
},
|
||||
() => new()
|
||||
{
|
||||
GuildId = guildId,
|
||||
GreetType = greetType
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<bool> SetGreet(ulong guildId, ulong channelId, bool? value = null)
|
||||
{
|
||||
await using var uow = _db.GetDbContext();
|
||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||
var enabled = conf.SendChannelGreetMessage = value ?? !conf.SendChannelGreetMessage;
|
||||
conf.GreetMessageChannelId = channelId;
|
||||
var conf = await GetGreetSettingsAsync(guildId, greetType);
|
||||
|
||||
var toAdd = GreetSettings.Create(conf);
|
||||
_guildConfigsCache[guildId] = toAdd;
|
||||
|
||||
await uow.SaveChangesAsync();
|
||||
return enabled;
|
||||
return conf?.IsEnabled ?? false;
|
||||
}
|
||||
|
||||
public bool SetGreetMessage(ulong guildId, ref string message)
|
||||
public async Task<bool> SetDeleteTimer(ulong guildId, GreetType greetType, int timer)
|
||||
{
|
||||
message = message.SanitizeMentions();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(message))
|
||||
throw new ArgumentNullException(nameof(message));
|
||||
|
||||
using var uow = _db.GetDbContext();
|
||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||
conf.ChannelGreetMessageText = message;
|
||||
var greetMsgEnabled = conf.SendChannelGreetMessage;
|
||||
|
||||
var toAdd = GreetSettings.Create(conf);
|
||||
_guildConfigsCache.AddOrUpdate(guildId, toAdd, (_, _) => toAdd);
|
||||
|
||||
uow.SaveChanges();
|
||||
return greetMsgEnabled;
|
||||
}
|
||||
|
||||
public async Task<bool> SetGreetDm(ulong guildId, bool? value = null)
|
||||
{
|
||||
await using var uow = _db.GetDbContext();
|
||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||
var enabled = conf.SendDmGreetMessage = value ?? !conf.SendDmGreetMessage;
|
||||
|
||||
var toAdd = GreetSettings.Create(conf);
|
||||
_guildConfigsCache[guildId] = toAdd;
|
||||
|
||||
await uow.SaveChangesAsync();
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public bool SetGreetDmMessage(ulong guildId, ref string? message)
|
||||
{
|
||||
message = message?.SanitizeMentions();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(message))
|
||||
throw new ArgumentNullException(nameof(message));
|
||||
|
||||
using var uow = _db.GetDbContext();
|
||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||
conf.DmGreetMessageText = message;
|
||||
|
||||
var toAdd = GreetSettings.Create(conf);
|
||||
_guildConfigsCache[guildId] = toAdd;
|
||||
|
||||
uow.SaveChanges();
|
||||
return conf.SendDmGreetMessage;
|
||||
}
|
||||
|
||||
public async Task<bool> SetBye(ulong guildId, ulong channelId, bool? value = null)
|
||||
{
|
||||
await using var uow = _db.GetDbContext();
|
||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||
var enabled = conf.SendChannelByeMessage = value ?? !conf.SendChannelByeMessage;
|
||||
conf.ByeMessageChannelId = channelId;
|
||||
|
||||
var toAdd = GreetSettings.Create(conf);
|
||||
_guildConfigsCache[guildId] = toAdd;
|
||||
|
||||
await uow.SaveChangesAsync();
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public bool SetByeMessage(ulong guildId, ref string? message)
|
||||
{
|
||||
message = message?.SanitizeMentions();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(message))
|
||||
throw new ArgumentNullException(nameof(message));
|
||||
|
||||
using var uow = _db.GetDbContext();
|
||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||
conf.ChannelByeMessageText = message;
|
||||
|
||||
var toAdd = GreetSettings.Create(conf);
|
||||
_guildConfigsCache[guildId] = toAdd;
|
||||
|
||||
uow.SaveChanges();
|
||||
return conf.SendChannelByeMessage;
|
||||
}
|
||||
|
||||
public async Task SetByeDel(ulong guildId, int timer)
|
||||
{
|
||||
if (timer is < 0 or > 600)
|
||||
return;
|
||||
|
||||
await using var uow = _db.GetDbContext();
|
||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||
conf.AutoDeleteByeMessagesTimer = timer;
|
||||
|
||||
var toAdd = GreetSettings.Create(conf);
|
||||
_guildConfigsCache[guildId] = toAdd;
|
||||
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task SetGreetDel(ulong guildId, int timer)
|
||||
{
|
||||
if (timer is < 0 or > 600)
|
||||
return;
|
||||
|
||||
await using var uow = _db.GetDbContext();
|
||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||
conf.AutoDeleteGreetMessagesTimer = timer;
|
||||
|
||||
var toAdd = GreetSettings.Create(conf);
|
||||
_guildConfigsCache[guildId] = toAdd;
|
||||
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public bool SetBoostMessage(ulong guildId, ref string message)
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||
conf.BoostMessage = message;
|
||||
|
||||
var toAdd = GreetSettings.Create(conf);
|
||||
_guildConfigsCache[guildId] = toAdd;
|
||||
|
||||
uow.SaveChanges();
|
||||
return conf.SendBoostMessage;
|
||||
}
|
||||
|
||||
public async Task SetBoostDel(ulong guildId, int timer)
|
||||
{
|
||||
if (timer is < 0 or > 600)
|
||||
if (timer < 0 || timer > 3600)
|
||||
throw new ArgumentOutOfRangeException(nameof(timer));
|
||||
|
||||
await using var uow = _db.GetDbContext();
|
||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||
conf.BoostMessageDeleteAfter = timer;
|
||||
|
||||
var toAdd = GreetSettings.Create(conf);
|
||||
_guildConfigsCache[guildId] = toAdd;
|
||||
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> ToggleBoost(ulong guildId, ulong channelId, bool? forceState = null)
|
||||
await using (var uow = _db.GetDbContext())
|
||||
{
|
||||
await using var uow = _db.GetDbContext();
|
||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||
|
||||
if (forceState is not bool fs)
|
||||
conf.SendBoostMessage = !conf.SendBoostMessage;
|
||||
else
|
||||
conf.SendBoostMessage = fs;
|
||||
|
||||
conf.BoostMessageChannelId = channelId;
|
||||
await uow.SaveChangesAsync();
|
||||
|
||||
var toAdd = GreetSettings.Create(conf);
|
||||
_guildConfigsCache[guildId] = toAdd;
|
||||
return conf.SendBoostMessage;
|
||||
}
|
||||
|
||||
#region Get Enabled Status
|
||||
|
||||
public bool GetGreetDmEnabled(ulong guildId)
|
||||
await uow.GetTable<GreetSettings>()
|
||||
.InsertOrUpdateAsync(() => new()
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||
return conf.SendDmGreetMessage;
|
||||
}
|
||||
|
||||
public bool GetGreetEnabled(ulong guildId)
|
||||
GuildId = guildId,
|
||||
GreetType = greetType,
|
||||
AutoDeleteTimer = timer,
|
||||
},
|
||||
x => new()
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||
return conf.SendChannelGreetMessage;
|
||||
}
|
||||
|
||||
public bool GetByeEnabled(ulong guildId)
|
||||
AutoDeleteTimer = timer
|
||||
},
|
||||
() => new()
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||
return conf.SendChannelByeMessage;
|
||||
GuildId = guildId,
|
||||
GreetType = greetType
|
||||
});
|
||||
}
|
||||
|
||||
public bool GetBoostEnabled(ulong guildId)
|
||||
var conf = await GetGreetSettingsAsync(guildId, greetType);
|
||||
|
||||
return conf?.IsEnabled ?? false;
|
||||
}
|
||||
|
||||
|
||||
public async Task<bool> Test(
|
||||
ulong guildId,
|
||||
GreetType type,
|
||||
IMessageChannel channel,
|
||||
IGuildUser user)
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||
return conf.SendBoostMessage;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Test Messages
|
||||
|
||||
public Task ByeTest(ITextChannel channel, IGuildUser user)
|
||||
var conf = await GetGreetSettingsAsync(guildId, type);
|
||||
if (conf is null)
|
||||
{
|
||||
var conf = GetOrAddSettingsForGuild(user.GuildId);
|
||||
return ByeUsers(conf, channel, user);
|
||||
}
|
||||
|
||||
public Task GreetTest(ITextChannel channel, IGuildUser user)
|
||||
conf = new GreetSettings()
|
||||
{
|
||||
var conf = GetOrAddSettingsForGuild(user.GuildId);
|
||||
return GreetUsers(conf, channel, user);
|
||||
ChannelId = channel.Id,
|
||||
GreetType = type,
|
||||
IsEnabled = false,
|
||||
GuildId = guildId,
|
||||
AutoDeleteTimer = 30,
|
||||
MessageText = GetDefaultGreet(type)
|
||||
};
|
||||
}
|
||||
|
||||
public Task<bool> GreetDmTest(IGuildUser user)
|
||||
await SendMessage(conf, channel, user);
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> SendMessage(GreetSettings conf, IMessageChannel channel, IGuildUser user)
|
||||
{
|
||||
var conf = GetOrAddSettingsForGuild(user.GuildId);
|
||||
return GreetDmUser(conf, user);
|
||||
}
|
||||
|
||||
public Task<bool> BoostTest(ITextChannel channel, IGuildUser user)
|
||||
if (conf.GreetType == GreetType.GreetDm)
|
||||
{
|
||||
var conf = GetOrAddSettingsForGuild(user.GuildId);
|
||||
return SendBoostMessage(conf, user, channel);
|
||||
await _greetQueue.Writer.WriteAsync((conf, user, null));
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
if (channel is not ITextChannel ch)
|
||||
return false;
|
||||
|
||||
await GreetUsers(conf, ch, user);
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -1,45 +1,21 @@
|
||||
using NadekoBot.Db.Models;
|
||||
|
||||
namespace NadekoBot.Services;
|
||||
|
||||
public enum GreetType
|
||||
{
|
||||
Greet,
|
||||
GreetDm,
|
||||
Bye,
|
||||
Boost,
|
||||
}
|
||||
|
||||
public class GreetSettings
|
||||
{
|
||||
public int AutoDeleteGreetMessagesTimer { get; set; }
|
||||
public int AutoDeleteByeMessagesTimer { get; set; }
|
||||
public int Id { get; set; }
|
||||
|
||||
public ulong GreetMessageChannelId { get; set; }
|
||||
public ulong ByeMessageChannelId { get; set; }
|
||||
|
||||
public bool SendDmGreetMessage { get; set; }
|
||||
public string? DmGreetMessageText { get; set; }
|
||||
|
||||
public bool SendChannelGreetMessage { get; set; }
|
||||
public string? ChannelGreetMessageText { get; set; }
|
||||
|
||||
public bool SendChannelByeMessage { get; set; }
|
||||
public string? ChannelByeMessageText { get; set; }
|
||||
|
||||
public bool SendBoostMessage { get; set; }
|
||||
public string? BoostMessage { get; set; }
|
||||
public int BoostMessageDeleteAfter { get; set; }
|
||||
public ulong BoostMessageChannelId { get; set; }
|
||||
|
||||
public static GreetSettings Create(GuildConfig g)
|
||||
=> new()
|
||||
{
|
||||
AutoDeleteByeMessagesTimer = g.AutoDeleteByeMessagesTimer,
|
||||
AutoDeleteGreetMessagesTimer = g.AutoDeleteGreetMessagesTimer,
|
||||
GreetMessageChannelId = g.GreetMessageChannelId,
|
||||
ByeMessageChannelId = g.ByeMessageChannelId,
|
||||
SendDmGreetMessage = g.SendDmGreetMessage,
|
||||
DmGreetMessageText = g.DmGreetMessageText,
|
||||
SendChannelGreetMessage = g.SendChannelGreetMessage,
|
||||
ChannelGreetMessageText = g.ChannelGreetMessageText,
|
||||
SendChannelByeMessage = g.SendChannelByeMessage,
|
||||
ChannelByeMessageText = g.ChannelByeMessageText,
|
||||
SendBoostMessage = g.SendBoostMessage,
|
||||
BoostMessage = g.BoostMessage,
|
||||
BoostMessageDeleteAfter = g.BoostMessageDeleteAfter,
|
||||
BoostMessageChannelId = g.BoostMessageChannelId
|
||||
};
|
||||
public ulong GuildId { get; set; }
|
||||
public GreetType GreetType { get; set; }
|
||||
public string? MessageText { get; set; }
|
||||
public bool IsEnabled { get; set; }
|
||||
public ulong? ChannelId { get; set; }
|
||||
public int AutoDeleteTimer { get; set; }
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user