Compare commits
No commits in common. "1.4" and "music-test" have entirely different histories.
1.4
...
music-test
@ -3,6 +3,7 @@ You can support the project on patreon: <https://patreon.com/nadekobot> or paypa
|
|||||||
##Table of contents
|
##Table of contents
|
||||||
- [Help](#help)
|
- [Help](#help)
|
||||||
- [Administration](#administration)
|
- [Administration](#administration)
|
||||||
|
- [ClashOfClans](#clashofclans)
|
||||||
- [CustomReactions](#customreactions)
|
- [CustomReactions](#customreactions)
|
||||||
- [Gambling](#gambling)
|
- [Gambling](#gambling)
|
||||||
- [Games](#games)
|
- [Games](#games)
|
||||||
@ -12,7 +13,6 @@ You can support the project on patreon: <https://patreon.com/nadekobot> or paypa
|
|||||||
- [Pokemon](#pokemon)
|
- [Pokemon](#pokemon)
|
||||||
- [Searches](#searches)
|
- [Searches](#searches)
|
||||||
- [Utility](#utility)
|
- [Utility](#utility)
|
||||||
- [Xp](#xp)
|
|
||||||
|
|
||||||
|
|
||||||
### Administration
|
### Administration
|
||||||
@ -90,6 +90,7 @@ Commands and aliases | Description | Usage
|
|||||||
`.setgame` | Sets the bots game. **Bot owner only** | `.setgame with snakes`
|
`.setgame` | Sets the bots game. **Bot owner only** | `.setgame with snakes`
|
||||||
`.setstream` | Sets the bots stream. First argument is the twitch link, second argument is stream name. **Bot owner only** | `.setstream TWITCHLINK Hello`
|
`.setstream` | Sets the bots stream. First argument is the twitch link, second argument is stream name. **Bot owner only** | `.setstream TWITCHLINK Hello`
|
||||||
`.send` | Sends a message to someone on a different server through the bot. Separate server and channel/user ids with `|` and prefix the channel id with `c:` and the user id with `u:`. **Bot owner only** | `.send serverid|c:channelid message` or `.send serverid|u:userid message`
|
`.send` | Sends a message to someone on a different server through the bot. Separate server and channel/user ids with `|` and prefix the channel id with `c:` and the user id with `u:`. **Bot owner only** | `.send serverid|c:channelid message` or `.send serverid|u:userid message`
|
||||||
|
`.announce` | Sends a message to all servers' default channel that bot is connected to. **Bot owner only** | `.announce Useless spam`
|
||||||
`.reloadimages` | Reloads images bot is using. Safe to use even when bot is being used heavily. **Bot owner only** | `.reloadimages`
|
`.reloadimages` | Reloads images bot is using. Safe to use even when bot is being used heavily. **Bot owner only** | `.reloadimages`
|
||||||
`.greetdel` `.grdel` | Sets the time it takes (in seconds) for greet messages to be auto-deleted. Set it to 0 to disable automatic deletion. **Requires ManageServer server permission.** | `.greetdel 0` or `.greetdel 30`
|
`.greetdel` `.grdel` | Sets the time it takes (in seconds) for greet messages to be auto-deleted. Set it to 0 to disable automatic deletion. **Requires ManageServer server permission.** | `.greetdel 0` or `.greetdel 30`
|
||||||
`.greet` | Toggles anouncements on the current channel when someone joins the server. **Requires ManageServer server permission.** | `.greet`
|
`.greet` | Toggles anouncements on the current channel when someone joins the server. **Requires ManageServer server permission.** | `.greet`
|
||||||
@ -118,6 +119,21 @@ Commands and aliases | Description | Usage
|
|||||||
|
|
||||||
###### [Back to ToC](#table-of-contents)
|
###### [Back to ToC](#table-of-contents)
|
||||||
|
|
||||||
|
### ClashOfClans
|
||||||
|
Commands and aliases | Description | Usage
|
||||||
|
----------------|--------------|-------
|
||||||
|
`.createwar` `.cw` | Creates a new war by specifying a size (>10 and multiple of 5) and enemy clan name. **Requires ManageMessages server permission.** | `.cw 15 The Enemy Clan`
|
||||||
|
`.startwar` `.sw` | Starts a war with a given number. | `.sw 15`
|
||||||
|
`.listwar` `.lw` | Shows the active war claims by a number. Shows all wars in a short way if no number is specified. | `.lw [war_number]` or `.lw`
|
||||||
|
`.basecall` | Claims a certain base from a certain war. You can supply a name in the third optional argument to claim in someone else's place. | `.basecall [war_number] [base_number] [optional_other_name]`
|
||||||
|
`.callfinish1` `.cf1` | Finish your claim with 1 star if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. | `.cf1 1` or `.cf1 1 5`
|
||||||
|
`.callfinish2` `.cf2` | Finish your claim with 2 stars if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. | `.cf2 1` or `.cf2 1 5`
|
||||||
|
`.callfinish` `.cf` | Finish your claim with 3 stars if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. | `.cf 1` or `.cf 1 5`
|
||||||
|
`.endwar` `.ew` | Ends the war with a given index. | `.ew [war_number]`
|
||||||
|
`.uncall` | Removes your claim from a certain war. Optional second argument denotes a person in whose place to unclaim | `.uc [war_number] [optional_other_name]`
|
||||||
|
|
||||||
|
###### [Back to ToC](#table-of-contents)
|
||||||
|
|
||||||
### CustomReactions
|
### CustomReactions
|
||||||
Commands and aliases | Description | Usage
|
Commands and aliases | Description | Usage
|
||||||
----------------|--------------|-------
|
----------------|--------------|-------
|
||||||
@ -126,7 +142,6 @@ Commands and aliases | Description | Usage
|
|||||||
`.listcustreactg` `.lcrg` | Lists global or server custom reactions (20 commands per page) grouped by trigger, and show a number of responses for each. Running the command in DM will list global custom reactions, while running it in server will list that server's custom reactions. | `.lcrg 1`
|
`.listcustreactg` `.lcrg` | Lists global or server custom reactions (20 commands per page) grouped by trigger, and show a number of responses for each. Running the command in DM will list global custom reactions, while running it in server will list that server's custom reactions. | `.lcrg 1`
|
||||||
`.showcustreact` `.scr` | Shows a custom reaction's response on a given ID. | `.scr 1`
|
`.showcustreact` `.scr` | Shows a custom reaction's response on a given ID. | `.scr 1`
|
||||||
`.delcustreact` `.dcr` | Deletes a custom reaction on a specific index. If ran in DM, it is bot owner only and deletes a global custom reaction. If ran in a server, it requires Administration privileges and removes server custom reaction. | `.dcr 5`
|
`.delcustreact` `.dcr` | Deletes a custom reaction on a specific index. If ran in DM, it is bot owner only and deletes a global custom reaction. If ran in a server, it requires Administration privileges and removes server custom reaction. | `.dcr 5`
|
||||||
`.crca` | Toggles whether the custom reaction will trigger if the triggering message contains the keyword (instead of only starting with it). | `.crca 44`
|
|
||||||
`.crdm` | Toggles whether the response message of the custom reaction will be sent as a direct message. | `.crdm 44`
|
`.crdm` | Toggles whether the response message of the custom reaction will be sent as a direct message. | `.crdm 44`
|
||||||
`.crad` | Toggles whether the message triggering the custom reaction will be automatically deleted. | `.crad 59`
|
`.crad` | Toggles whether the message triggering the custom reaction will be automatically deleted. | `.crad 59`
|
||||||
`.crstatsclear` | Resets the counters on `.crstats`. You can specify a trigger to clear stats only for that trigger. **Bot owner only** | `.crstatsclear` or `.crstatsclear rng`
|
`.crstatsclear` | Resets the counters on `.crstats`. You can specify a trigger to clear stats only for that trigger. **Bot owner only** | `.crstatsclear` or `.crstatsclear rng`
|
||||||
@ -168,27 +183,23 @@ Commands and aliases | Description | Usage
|
|||||||
`.affinity` | Sets your affinity towards someone you want to be claimed by. Setting affinity will reduce their `.claim` on you by 20%. You can leave second argument empty to clear your affinity. 30 minutes cooldown. | `.affinity @MyHusband` or `.affinity`
|
`.affinity` | Sets your affinity towards someone you want to be claimed by. Setting affinity will reduce their `.claim` on you by 20%. You can leave second argument empty to clear your affinity. 30 minutes cooldown. | `.affinity @MyHusband` or `.affinity`
|
||||||
`.waifus` `.waifulb` | Shows top 9 waifus. You can specify another page to show other waifus. | `.waifus` or `.waifulb 3`
|
`.waifus` `.waifulb` | Shows top 9 waifus. You can specify another page to show other waifus. | `.waifus` or `.waifulb 3`
|
||||||
`.waifuinfo` `.waifustats` | Shows waifu stats for a target person. Defaults to you if no user is provided. | `.waifuinfo @MyCrush` or `.waifuinfo`
|
`.waifuinfo` `.waifustats` | Shows waifu stats for a target person. Defaults to you if no user is provided. | `.waifuinfo @MyCrush` or `.waifuinfo`
|
||||||
`.waifugift` `.gift` `.gifts` | Gift an item to someone. This will increase their waifu value by 50% of the gifted item's value if they don't have affinity set towards you, or 100% if they do. Provide no arguments to see a list of items that you can gift. | `.gifts` or `.gift Rose @Himesama`
|
|
||||||
`.wheeloffortune` `.wheel` | Bets a certain amount of currency on the wheel of fortune. Wheel can stop on one of many different multipliers. Won amount is rounded down to the nearest whole number. | `.wheel 10`
|
|
||||||
|
|
||||||
###### [Back to ToC](#table-of-contents)
|
###### [Back to ToC](#table-of-contents)
|
||||||
|
|
||||||
### Games
|
### Games
|
||||||
Commands and aliases | Description | Usage
|
Commands and aliases | Description | Usage
|
||||||
----------------|--------------|-------
|
----------------|--------------|-------
|
||||||
|
`.leet` | Converts a text to leetspeak with 6 (1-6) severity levels | `.leet 3 Hello`
|
||||||
`.choose` | Chooses a thing from a list of things | `.choose Get up;Sleep;Sleep more`
|
`.choose` | Chooses a thing from a list of things | `.choose Get up;Sleep;Sleep more`
|
||||||
`.8ball` | Ask the 8ball a yes/no question. | `.8ball should I do something`
|
`.8ball` | Ask the 8ball a yes/no question. | `.8ball should I do something`
|
||||||
`.rps` | Play a game of Rocket-Paperclip-Scissors with Nadeko. | `.rps scissors`
|
`.rps` | Play a game of Rocket-Paperclip-Scissors with Nadeko. | `.rps scissors`
|
||||||
`.rategirl` | Use the universal hot-crazy wife zone matrix to determine the girl's worth. It is everything young men need to know about women. At any moment in time, any woman you have previously located on this chart can vanish from that location and appear anywhere else on the chart. | `.rategirl @SomeGurl`
|
`.rategirl` | Use the universal hot-crazy wife zone matrix to determine the girl's worth. It is everything young men need to know about women. At any moment in time, any woman you have previously located on this chart can vanish from that location and appear anywhere else on the chart. | `.rategirl @SomeGurl`
|
||||||
`.linux` | Prints a customizable Linux interjection | `.linux Spyware Windows`
|
`.linux` | Prints a customizable Linux interjection | `.linux Spyware Windows`
|
||||||
`.leet` | Converts a text to leetspeak with 6 (1-6) severity levels | `.leet 3 Hello`
|
|
||||||
`.acrophobia` `.acro` | Starts an Acrophobia game. Second argument is optional round length in seconds. (default is 60) | `.acro` or `.acro 30`
|
`.acrophobia` `.acro` | Starts an Acrophobia game. Second argument is optional round length in seconds. (default is 60) | `.acro` or `.acro 30`
|
||||||
`.cleverbot` | Toggles cleverbot session. When enabled, the bot will reply to messages starting with bot mention in the server. Custom reactions starting with %mention% won't work if cleverbot is enabled. **Requires ManageMessages server permission.** | `.cleverbot`
|
`.cleverbot` | Toggles cleverbot session. When enabled, the bot will reply to messages starting with bot mention in the server. Custom reactions starting with %mention% won't work if cleverbot is enabled. **Requires ManageMessages server permission.** | `.cleverbot`
|
||||||
`.connect4` `.con4` | Creates or joins an existing connect4 game. 2 players are required for the game. Objective of the game is to get 4 of your pieces next to each other in a vertical, horizontal or diagonal line. | `.connect4`
|
|
||||||
`.hangmanlist` | Shows a list of hangman term types. | `.hangmanlist`
|
`.hangmanlist` | Shows a list of hangman term types. | `.hangmanlist`
|
||||||
`.hangman` | Starts a game of hangman in the channel. Use `.hangmanlist` to see a list of available term types. Defaults to 'all'. | `.hangman` or `.hangman movies`
|
`.hangman` | Starts a game of hangman in the channel. Use `.hangmanlist` to see a list of available term types. Defaults to 'all'. | `.hangman` or `.hangman movies`
|
||||||
`.hangmanstop` | Stops the active hangman game on this channel if it exists. | `.hangmanstop`
|
`.hangmanstop` | Stops the active hangman game on this channel if it exists. | `.hangmanstop`
|
||||||
`.nunchi` | Creates or joins an existing nunchi game. Users have to count up by 1 from the starting number shown by the bot. If someone makes a mistake (types an incorrent number, or repeats the same number) they are out of the game and a new round starts without them. Minimum 3 users required. | `.nunchi`
|
|
||||||
`.pick` | Picks the currency planted in this channel. 60 seconds cooldown. | `.pick`
|
`.pick` | Picks the currency planted in this channel. 60 seconds cooldown. | `.pick`
|
||||||
`.plant` | Spend an amount of currency to plant it in this channel. Default is 1. (If bot is restarted or crashes, the currency will be lost) | `.plant` or `.plant 5`
|
`.plant` | Spend an amount of currency to plant it in this channel. Default is 1. (If bot is restarted or crashes, the currency will be lost) | `.plant` or `.plant 5`
|
||||||
`.gencurrency` `.gc` | Toggles currency generation on this channel. Every posted message will have chance to spawn currency. Chance is specified by the Bot Owner. (default is 2%) **Requires ManageMessages server permission.** | `.gc`
|
`.gencurrency` `.gc` | Toggles currency generation on this channel. Every posted message will have chance to spawn currency. Chance is specified by the Bot Owner. (default is 2%) **Requires ManageMessages server permission.** | `.gc`
|
||||||
@ -200,7 +211,7 @@ Commands and aliases | Description | Usage
|
|||||||
`.typeadd` | Adds a new article to the typing contest. **Bot owner only** | `.typeadd wordswords`
|
`.typeadd` | Adds a new article to the typing contest. **Bot owner only** | `.typeadd wordswords`
|
||||||
`.typelist` | Lists added typing articles with their IDs. 15 per page. | `.typelist` or `.typelist 3`
|
`.typelist` | Lists added typing articles with their IDs. 15 per page. | `.typelist` or `.typelist 3`
|
||||||
`.typedel` | Deletes a typing article given the ID. **Bot owner only** | `.typedel 3`
|
`.typedel` | Deletes a typing article given the ID. **Bot owner only** | `.typedel 3`
|
||||||
`.tictactoe` `.ttt` | Starts a game of tic tac toe. Another user must run the command in the same channel in order to accept the challenge. Use numbers 1-9 to play. 15 seconds per move. | .ttt
|
`.tictactoe` `.ttt` | Starts a game of tic tac toe. Another user must run the command in the same channel in order to accept the challenge. Use numbers 1-9 to play. 15 seconds per move. | >ttt
|
||||||
`.trivia` `.t` | Starts a game of trivia. You can add `nohint` to prevent hints. First player to get to 10 points wins by default. You can specify a different number. 30 seconds per question. | `.t` or `.t 5 nohint`
|
`.trivia` `.t` | Starts a game of trivia. You can add `nohint` to prevent hints. First player to get to 10 points wins by default. You can specify a different number. 30 seconds per question. | `.t` or `.t 5 nohint`
|
||||||
`.tl` | Shows a current trivia leaderboard. | `.tl`
|
`.tl` | Shows a current trivia leaderboard. | `.tl`
|
||||||
`.tq` | Quits current trivia after current question. | `.tq`
|
`.tq` | Quits current trivia after current question. | `.tq`
|
||||||
@ -224,22 +235,20 @@ Commands and aliases | Description | Usage
|
|||||||
----------------|--------------|-------
|
----------------|--------------|-------
|
||||||
`.play` `.start` | If no arguments are specified, acts as `.next 1` command. If you specify a song number, it will jump to that song. If you specify a search query, acts as a `.q` command | `.play` or `.play 5` or `.play Dream Of Venice`
|
`.play` `.start` | If no arguments are specified, acts as `.next 1` command. If you specify a song number, it will jump to that song. If you specify a search query, acts as a `.q` command | `.play` or `.play 5` or `.play Dream Of Venice`
|
||||||
`.queue` `.q` `.yq` | Queue a song using keywords or a link. Bot will join your voice channel. **You must be in a voice channel**. | `.q Dream Of Venice`
|
`.queue` `.q` `.yq` | Queue a song using keywords or a link. Bot will join your voice channel. **You must be in a voice channel**. | `.q Dream Of Venice`
|
||||||
`.queuenext` `.qn` | Works the same as `.queue` command, except it enqueues the new song after the current one. **You must be in a voice channel**. | `.qn Dream Of Venice`
|
|
||||||
`.queuesearch` `.qs` `.yqs` | Search for top 5 youtube song result using keywords, and type the index of the song to play that song. Bot will join your voice channel. **You must be in a voice channel**. | `.qs Dream Of Venice`
|
`.queuesearch` `.qs` `.yqs` | Search for top 5 youtube song result using keywords, and type the index of the song to play that song. Bot will join your voice channel. **You must be in a voice channel**. | `.qs Dream Of Venice`
|
||||||
`.listqueue` `.lq` | Lists 10 currently queued songs per page. Default page is 1. | `.lq` or `.lq 2`
|
`.listqueue` `.lq` | Lists 15 currently queued songs per page. Default page is 1. | `.lq` or `.lq 2`
|
||||||
`.next` `.n` | Goes to the next song in the queue. You have to be in the same voice channel as the bot. You can skip multiple songs, but in that case songs will not be requeued if .rcs or .rpl is enabled. | `.n` or `.n 5`
|
`.next` `.n` | Goes to the next song in the queue. You have to be in the same voice channel as the bot. You can skip multiple songs, but in that case songs will not be requeued if .rcs or .rpl is enabled. | `.n` or `.n 5`
|
||||||
`.stop` `.s` | Stops the music and preserves the current song index. Stays in the channel. | `.s`
|
`.stop` `.s` | Stops the music and clears the playlist. Stays in the channel. | `.s`
|
||||||
`.destroy` `.d` | Completely stops the music and unbinds the bot from the channel. (may cause weird behaviour) | `.d`
|
`.destroy` `.d` | Completely stops the music and unbinds the bot from the channel. (may cause weird behaviour) | `.d`
|
||||||
`.pause` `.p` | Pauses or Unpauses the song. | `.p`
|
`.pause` `.p` | Pauses or Unpauses the song. | `.p`
|
||||||
`.volume` `.vol` | Sets the music playback volume (0-100%) | `.vol 50`
|
`.volume` `.vol` | Sets the music playback volume (0-100%) | `.vol 50`
|
||||||
`.defvol` `.dv` | Sets the default music volume when music playback is started (0-100). Persists through restarts. | `.dv 80`
|
`.defvol` `.dv` | Sets the default music volume when music playback is started (0-100). Persists through restarts. | `.dv 80`
|
||||||
`.songremove` `.srm` | Remove a song by its # in the queue, or 'all' to remove all songs from the queue and reset the song index. | `.srm 5`
|
`.songremove` `.srm` | Remove a song by its # in the queue, or 'all' to remove all songs from the queue. | `.srm 5`
|
||||||
`.playlists` `.pls` | Lists all playlists. Paginated, 20 per page. Default page is 0. | `.pls 1`
|
`.playlists` `.pls` | Lists all playlists. Paginated, 20 per page. Default page is 0. | `.pls 1`
|
||||||
`.deleteplaylist` `.delpls` | Deletes a saved playlist. Works only if you made it or if you are the bot owner. | `.delpls animu-5`
|
`.deleteplaylist` `.delpls` | Deletes a saved playlist. Works only if you made it or if you are the bot owner. | `.delpls animu-5`
|
||||||
`.save` | Saves a playlist under a certain name. Playlist name must be no longer than 20 characters and must not contain dashes. | `.save classical1`
|
`.save` | Saves a playlist under a certain name. Playlist name must be no longer than 20 characters and must not contain dashes. | `.save classical1`
|
||||||
`.load` | Loads a saved playlist using its ID. Use `.pls` to list all saved playlists and `.save` to save new ones. | `.load 5`
|
`.load` | Loads a saved playlist using its ID. Use `.pls` to list all saved playlists and `.save` to save new ones. | `.load 5`
|
||||||
`.fairplay` `.fp` | Toggles fairplay. While enabled, the bot will prioritize songs from users who didn't have their song recently played instead of the song's position in the queue. | `.fp`
|
`.fairplay` `.fp` | Toggles fairplay. While enabled, the bot will prioritize songs from users who didn't have their song recently played instead of the song's position in the queue. | `.fp`
|
||||||
`.songautodelete` `.sad` | Toggles whether the song should be automatically removed from the music queue when it finishes playing. | `.sad`
|
|
||||||
`.soundcloudqueue` `.sq` | Queue a soundcloud song using keywords. Bot will join your voice channel. **You must be in a voice channel**. | `.sq Dream Of Venice`
|
`.soundcloudqueue` `.sq` | Queue a soundcloud song using keywords. Bot will join your voice channel. **You must be in a voice channel**. | `.sq Dream Of Venice`
|
||||||
`.soundcloudpl` `.scpl` | Queue a Soundcloud playlist using a link. | `.scpl soundcloudseturl`
|
`.soundcloudpl` `.scpl` | Queue a Soundcloud playlist using a link. | `.scpl soundcloudseturl`
|
||||||
`.nowplaying` `.np` | Shows the song that the bot is currently playing. | `.np`
|
`.nowplaying` `.np` | Shows the song that the bot is currently playing. | `.np`
|
||||||
@ -273,8 +282,6 @@ Commands and aliases | Description | Usage
|
|||||||
`.gelbooru` | Shows a random hentai image from gelbooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `.gelbooru yuri+kissing`
|
`.gelbooru` | Shows a random hentai image from gelbooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `.gelbooru yuri+kissing`
|
||||||
`.boobs` | Real adult content. | `.boobs`
|
`.boobs` | Real adult content. | `.boobs`
|
||||||
`.butts` `.ass` `.butt` | Real adult content. | `.butts` or `.ass`
|
`.butts` `.ass` `.butt` | Real adult content. | `.butts` or `.ass`
|
||||||
`.nsfwtagbl` `.nsfwtbl` | Toggles whether the tag is blacklisted or not in nsfw searches. Provide no parameters to see the list of blacklisted tags. | `.nsfwtbl poop`
|
|
||||||
`.nsfwcc` | Clears nsfw cache. **Bot owner only** | `.nsfwcc`
|
|
||||||
|
|
||||||
###### [Back to ToC](#table-of-contents)
|
###### [Back to ToC](#table-of-contents)
|
||||||
|
|
||||||
@ -376,11 +383,11 @@ Commands and aliases | Description | Usage
|
|||||||
`.place` | Shows a placeholder image of a given tag. Use `.placelist` to see all available tags. You can specify the width and height of the image as the last two optional arguments. | `.place Cage` or `.place steven 500 400`
|
`.place` | Shows a placeholder image of a given tag. Use `.placelist` to see all available tags. You can specify the width and height of the image as the last two optional arguments. | `.place Cage` or `.place steven 500 400`
|
||||||
`.pokemon` `.poke` | Searches for a pokemon. | `.poke Sylveon`
|
`.pokemon` `.poke` | Searches for a pokemon. | `.poke Sylveon`
|
||||||
`.pokemonability` `.pokeab` | Searches for a pokemon ability. | `.pokeab overgrow`
|
`.pokemonability` `.pokeab` | Searches for a pokemon ability. | `.pokeab overgrow`
|
||||||
`.smashcast` `.hb` | Notifies this channel when a certain user starts streaming. **Requires ManageMessages server permission.** | `.smashcast SomeStreamer`
|
`.hitbox` `.hb` | Notifies this channel when a certain user starts streaming. **Requires ManageMessages server permission.** | `.hitbox SomeStreamer`
|
||||||
`.twitch` `.tw` | Notifies this channel when a certain user starts streaming. **Requires ManageMessages server permission.** | `.twitch SomeStreamer`
|
`.twitch` `.tw` | Notifies this channel when a certain user starts streaming. **Requires ManageMessages server permission.** | `.twitch SomeStreamer`
|
||||||
`.mixer` `.bm` | Notifies this channel when a certain user starts streaming. **Requires ManageMessages server permission.** | `.mixer SomeStreamer`
|
`.beam` `.bm` | Notifies this channel when a certain user starts streaming. **Requires ManageMessages server permission.** | `.beam SomeStreamer`
|
||||||
`.liststreams` `.ls` | Lists all streams you are following on this server. | `.ls`
|
`.liststreams` `.ls` | Lists all streams you are following on this server. | `.ls`
|
||||||
`.removestream` `.rms` | Removes notifications of a certain streamer from a certain platform on this channel. **Requires ManageMessages server permission.** | `.rms Twitch SomeGuy` or `.rms mixer SomeOtherGuy`
|
`.removestream` `.rms` | Removes notifications of a certain streamer from a certain platform on this channel. **Requires ManageMessages server permission.** | `.rms Twitch SomeGuy` or `.rms Beam SomeOtherGuy`
|
||||||
`.checkstream` `.cs` | Checks if a user is online on a certain streaming platform. | `.cs twitch MyFavStreamer`
|
`.checkstream` `.cs` | Checks if a user is online on a certain streaming platform. | `.cs twitch MyFavStreamer`
|
||||||
`.translate` `.trans` | Translates from>to text. From the given language to the destination language. | `.trans en>fr Hello`
|
`.translate` `.trans` | Translates from>to text. From the given language to the destination language. | `.trans en>fr Hello`
|
||||||
`.autotrans` `.at` | Starts automatic translation of all messages by users who set their `.atl` in this channel. You can set "del" argument to automatically delete all translated user messages. **Requires Administrator server permission.** **Bot owner only** | `.at` or `.at del`
|
`.autotrans` `.at` | Starts automatic translation of all messages by users who set their `.atl` in this channel. You can set "del" argument to automatically delete all translated user messages. **Requires Administrator server permission.** **Bot owner only** | `.at` or `.at del`
|
||||||
@ -393,6 +400,7 @@ Commands and aliases | Description | Usage
|
|||||||
### Utility
|
### Utility
|
||||||
Commands and aliases | Description | Usage
|
Commands and aliases | Description | Usage
|
||||||
----------------|--------------|-------
|
----------------|--------------|-------
|
||||||
|
`.rotaterolecolor` `.rrc` | Rotates a roles color on an interval with a list of supplied colors. First argument is interval in seconds (Minimum 60). Second argument is a role, followed by a space-separated list of colors in hex. Provide a rolename with a 0 interval to disable. **Requires ManageRoles server permission.** **Bot owner only** | `.rrc 60 MyLsdRole #ff0000 #00ff00 #0000ff` or `.rrc 0 MyLsdRole`
|
||||||
`.togethertube` `.totube` | Creates a new room on <https://togethertube.com> and shows the link in the chat. | `.totube`
|
`.togethertube` `.totube` | Creates a new room on <https://togethertube.com> and shows the link in the chat. | `.totube`
|
||||||
`.whosplaying` `.whpl` | Shows a list of users who are playing the specified game. | `.whpl Overwatch`
|
`.whosplaying` `.whpl` | Shows a list of users who are playing the specified game. | `.whpl Overwatch`
|
||||||
`.inrole` | Lists every person from the specified role on this server. You can use role ID, role name. | `.inrole Some Role`
|
`.inrole` | Lists every person from the specified role on this server. You can use role ID, role name. | `.inrole Some Role`
|
||||||
@ -409,12 +417,11 @@ Commands and aliases | Description | Usage
|
|||||||
`.listservers` | Lists servers the bot is on with some basic info. 15 per page. **Bot owner only** | `.listservers 3`
|
`.listservers` | Lists servers the bot is on with some basic info. 15 per page. **Bot owner only** | `.listservers 3`
|
||||||
`.savechat` | Saves a number of messages to a text file and sends it to you. **Bot owner only** | `.savechat 150`
|
`.savechat` | Saves a number of messages to a text file and sends it to you. **Bot owner only** | `.savechat 150`
|
||||||
`.ping` | Ping the bot to see if there are latency issues. | `.ping`
|
`.ping` | Ping the bot to see if there are latency issues. | `.ping`
|
||||||
`.botconfigedit` `.bce` | Sets one of available bot config settings to a specified value. Use the command without any parameters to get a list of available settings. **Bot owner only** | `.bce CurrencyName b1nzy` or `.bce`
|
|
||||||
`.calculate` `.calc` | Evaluate a mathematical expression. | `.calc 1+1`
|
`.calculate` `.calc` | Evaluate a mathematical expression. | `.calc 1+1`
|
||||||
`.calcops` | Shows all available operations in the `.calc` command | `.calcops`
|
`.calcops` | Shows all available operations in the `.calc` command | `.calcops`
|
||||||
`.alias` `.cmdmap` | Create a custom alias for a certain Nadeko command. Provide no alias to remove the existing one. **Requires Administrator server permission.** | `.alias allin $bf 100 h` or `.alias "linux thingy" >loonix Spyware Windows`
|
`.alias` `.cmdmap` | Create a custom alias for a certain Nadeko command. Provide no alias to remove the existing one. **Requires Administrator server permission.** | `.alias allin $bf 100 h` or `.alias "linux thingy" >loonix Spyware Windows`
|
||||||
`.aliaslist` `.cmdmaplist` `.aliases` | Shows the list of currently set aliases. Paginated. | `.aliaslist` or `.aliaslist 3`
|
`.aliaslist` `.cmdmaplist` `.aliases` | Shows the list of currently set aliases. Paginated. | `.aliaslist` or `.aliaslist 3`
|
||||||
`.serverinfo` `.sinfo` | Shows info about the server the bot is on. If no server is supplied, it defaults to current one. | `.sinfo Some Server`
|
`.serverinfo` `.sinfo` | Shows info about the server the bot is on. If no channel is supplied, it defaults to current one. | `.sinfo Some Server`
|
||||||
`.channelinfo` `.cinfo` | Shows info about the channel. If no channel is supplied, it defaults to current one. | `.cinfo #some-channel`
|
`.channelinfo` `.cinfo` | Shows info about the channel. If no channel is supplied, it defaults to current one. | `.cinfo #some-channel`
|
||||||
`.userinfo` `.uinfo` | Shows info about the user. If no user is supplied, it defaults a user running the command. | `.uinfo @SomeUser`
|
`.userinfo` `.uinfo` | Shows info about the user. If no user is supplied, it defaults a user running the command. | `.uinfo @SomeUser`
|
||||||
`.activity` | Checks for spammers. **Bot owner only** | `.activity`
|
`.activity` | Checks for spammers. **Bot owner only** | `.activity`
|
||||||
@ -433,39 +440,6 @@ Commands and aliases | Description | Usage
|
|||||||
`.repeatremove` `.reprm` | Removes a repeating message on a specified index. Use `.repeatlist` to see indexes. **Requires ManageMessages server permission.** | `.reprm 2`
|
`.repeatremove` `.reprm` | Removes a repeating message on a specified index. Use `.repeatlist` to see indexes. **Requires ManageMessages server permission.** | `.reprm 2`
|
||||||
`.repeat` | Repeat a message every `X` minutes in the current channel. You can instead specify time of day for the message to be repeated at daily (make sure you've set your server's timezone). You can have up to 5 repeating messages on the server in total. **Requires ManageMessages server permission.** | `.repeat 5 Hello there` or `.repeat 17:30 tea time`
|
`.repeat` | Repeat a message every `X` minutes in the current channel. You can instead specify time of day for the message to be repeated at daily (make sure you've set your server's timezone). You can have up to 5 repeating messages on the server in total. **Requires ManageMessages server permission.** | `.repeat 5 Hello there` or `.repeat 17:30 tea time`
|
||||||
`.repeatlist` `.replst` | Shows currently repeating messages and their indexes. **Requires ManageMessages server permission.** | `.repeatlist`
|
`.repeatlist` `.replst` | Shows currently repeating messages and their indexes. **Requires ManageMessages server permission.** | `.repeatlist`
|
||||||
`.streamrole` | Sets a role which is monitored for streamers (FromRole), and a role to add if a user from 'FromRole' is streaming (AddRole). When a user from 'FromRole' starts streaming, they will receive an 'AddRole'. Provide no arguments to disable **Requires ManageRoles server permission.** | `.streamrole "Eligible Streamers" "Featured Streams"`
|
|
||||||
`.streamrolekw` `.srkw` | Sets keyword which is required in the stream's title in order for the streamrole to apply. Provide no keyword in order to reset. **Requires ManageRoles server permission.** | `.srkw` or `.srkw PUBG`
|
|
||||||
`.streamrolebl` `.srbl` | Adds or removes a blacklisted user. Blacklisted users will never receive the stream role. **Requires ManageRoles server permission.** | `.srbl add @b1nzy#1234` or `.srbl rem @b1nzy#1234`
|
|
||||||
`.streamrolewl` `.srwl` | Adds or removes a whitelisted user. Whitelisted users will receive the stream role even if they don't have the specified keyword in their stream title. **Requires ManageRoles server permission.** | `.srwl add @b1nzy#1234` or `.srwl rem @b1nzy#1234`
|
|
||||||
`.convertlist` | List of the convertible dimensions and currencies. | `.convertlist`
|
`.convertlist` | List of the convertible dimensions and currencies. | `.convertlist`
|
||||||
`.convert` | Convert quantities. Use `.convertlist` to see supported dimensions and currencies. | `.convert m km 1000`
|
`.convert` | Convert quantities. Use `.convertlist` to see supported dimensions and currencies. | `.convert m km 1000`
|
||||||
`.verboseerror` `.ve` | Toggles whether the bot should print command errors when a command is incorrectly used. **Requires ManageMessages server permission.** | `.ve`
|
`.verboseerror` `.ve` | Toggles whether the bot should print command errors when a command is incorrectly used. **Requires ManageMessages server permission.** | `.ve`
|
||||||
|
|
||||||
###### [Back to ToC](#table-of-contents)
|
|
||||||
|
|
||||||
### Xp
|
|
||||||
Commands and aliases | Description | Usage
|
|
||||||
----------------|--------------|-------
|
|
||||||
`.experience` `.xp` | Shows your xp stats. Specify the user to show that user's stats instead. | `.xp`
|
|
||||||
`.xprolerewards` `.xprrs` | Shows currently set role rewards. | `.xprrs`
|
|
||||||
`.xprolereward` `.xprr` | Sets a role reward on a specified level. Provide no role name in order to remove the role reward. **Requires ManageRoles server permission.** | `.xprr 3 Social`
|
|
||||||
`.xpnotify` `.xpn` | Sets how the bot should notify you when you get a `server` or `global` level. You can set `dm` (for the bot to send a direct message), `channel` (to get notified in the channel you sent the last message in) or `none` to disable. | `.xpn global dm` `.xpn server channel`
|
|
||||||
`.xpexclude` `.xpex` | Exclude a user or a role from the xp system, or whole current server. **Requires Administrator server permission.** | `.xpex Role Excluded-Role` `.xpex Server`
|
|
||||||
`.xpexclusionlist` `.xpexl` | Shows the roles and channels excluded from the XP system on this server, as well as whether the whole server is excluded. | `.xpexl`
|
|
||||||
`.xpleaderboard` `.xplb` | Shows current server's xp leaderboard. | `.xplb`
|
|
||||||
`.xpgleaderboard` `.xpglb` | Shows the global xp leaderboard. | `.xpglb`
|
|
||||||
`.xpadd` | Adds xp to a user on the server. This does not affect their global ranking. You can use negative values. **Requires Administrator server permission.** | `.xpadd 100 @b1nzy`
|
|
||||||
`.clubcreate` | Creates a club. You must be atleast level 5 and not be in the club already. | `.clubcreate b1nzy's friends`
|
|
||||||
`.clubicon` | Sets the club icon. | `.clubicon https://i.imgur.com/htfDMfU.png`
|
|
||||||
`.clubinfo` | Shows information about the club. | `.clubinfo b1nzy's friends#123`
|
|
||||||
`.clubbans` | Shows the list of users who have banned from your club. Paginated. You must be club owner to use this command. | `.clubbans 2`
|
|
||||||
`.clubapps` | Shows the list of users who have applied to your club. Paginated. You must be club owner to use this command. | `.clubapps 2`
|
|
||||||
`.clubapply` | Apply to join a club. You must meet that club's minimum level requirement, and not be on its ban list. | `.clubapply b1nzy's friends#123`
|
|
||||||
`.clubaccept` | Accept a user who applied to your club. | `.clubaccept b1nzy#1337`
|
|
||||||
`.clubleave` | Leaves the club you're currently in. | `.clubleave`
|
|
||||||
`.clubkick` | Kicks the user from the club. You must be the club owner. They will be able to apply again. | `.clubkick b1nzy#1337`
|
|
||||||
`.clubban` | Bans the user from the club. You must be the club owner. They will not be able to apply again. | `.clubban b1nzy#1337`
|
|
||||||
`.clubunban` | Unbans the previously banned user from the club. You must be the club owner. | `.clubunban b1nzy#1337`
|
|
||||||
`.clublevelreq` | Sets the club required level to apply to join the club. You must be club owner. You can't set this number below 5. | `.clublevelreq 7`
|
|
||||||
`.clubdisband` | Disbands the club you're the owner of. This action is irreversible. | `.clubdisband`
|
|
||||||
`.clublb` | Shows club rankings on the specified page. | `.clublb 2`
|
|
||||||
|
@ -56,13 +56,13 @@ Follow this Detailed [Guide](http://discord.kongslien.net/guide.html).
|
|||||||
|
|
||||||
###Question 12: I'm building NadekoBot from source, but I get hundreds of (namespace) errors without changing anything!?
|
###Question 12: I'm building NadekoBot from source, but I get hundreds of (namespace) errors without changing anything!?
|
||||||
-----
|
-----
|
||||||
**Answer:** Using Visual Studio, you can solve these errors by going to `Tools` -> `NuGet Package Manager` -> `Manage NuGet Packages for Solution`. Go to the Installed tab, select the Packages that were missing (usually `Newtonsoft.json` and `RestSharp`) and install them for all projects.
|
**Answer:** Using Visual Studio, you can solve these errors by going to `Tools` -> `NuGet Package Manager` -> `Manage NuGet Packages for Solution`. Go to the Installed tab, select the Packages that were missing (usually `Newtonsoft.json` and `RestSharp`) and install them for all projects
|
||||||
|
|
||||||
###Question 13: My bot has all permissions but it's still saying, "Failed to add roles. Bot has insufficient permissions". How do I fix this?
|
###Question 13: My bot has all permissions but it's still saying, "Failed to add roles. Bot has insufficient permissions". How do I fix this?
|
||||||
----------
|
----------
|
||||||
**Answer:** Discord has added a few new features and the roles now follow the role hierarchy, which means you need to place your bot's role above every other role on your server to fix the issue. [Here's](https://support.discordapp.com/hc/en-us/articles/214836687-Role-Management-101) a link to Discord's role management 101.
|
**Answer:** Discord has added few new features and the roles now follows the role hierarchy which means you need to place your bot's role above every-other role your server has to fix the role hierarchy issue. [Here's](https://support.discordapp.com/hc/en-us/articles/214836687-Role-Management-101) a link to Discords role management 101.
|
||||||
|
|
||||||
**Please Note:** *The bot can only set/add all roles below its own highest role. It cannot assign its "highest role" to anyone else.*
|
**Please Note:** *The bot can only set/add all roles below its own highest role. It can not assign it's "highest role" to anyone else.*
|
||||||
|
|
||||||
###Question 14: I've broken permissions and am stuck, can I reset permissions?
|
###Question 14: I've broken permissions and am stuck, can I reset permissions?
|
||||||
----------
|
----------
|
||||||
|
@ -16,7 +16,6 @@ If you do not see `credentials.json` you will need to rename `credentials_exampl
|
|||||||
"GoogleApiKey": "AIzaSyDSci1sdlWQOWNVj1vlXxxxxxbk0oWMEzM",
|
"GoogleApiKey": "AIzaSyDSci1sdlWQOWNVj1vlXxxxxxbk0oWMEzM",
|
||||||
"MashapeKey": "4UrKpcWXc2mshS8RKi00000y8Kf5p1Q8kI6jsn32bmd8oVWiY7",
|
"MashapeKey": "4UrKpcWXc2mshS8RKi00000y8Kf5p1Q8kI6jsn32bmd8oVWiY7",
|
||||||
"OsuApiKey": "4c8c8fdff8e1234581725db27fd140a7d93320d6",
|
"OsuApiKey": "4c8c8fdff8e1234581725db27fd140a7d93320d6",
|
||||||
"CleverbotApiKey": "",
|
|
||||||
"PatreonAccessToken": "",
|
"PatreonAccessToken": "",
|
||||||
"PatreonCampaignId": "334038",
|
"PatreonCampaignId": "334038",
|
||||||
"Db": null,
|
"Db": null,
|
||||||
@ -48,7 +47,7 @@ If you do not see `credentials.json` you will need to rename `credentials_exampl
|
|||||||
- Replace the **`12345678`** in this link:
|
- Replace the **`12345678`** in this link:
|
||||||
`https://discordapp.com/oauth2/authorize?client_id=`**`12345678`**`&scope=bot&permissions=66186303` with your `Client ID`.
|
`https://discordapp.com/oauth2/authorize?client_id=`**`12345678`**`&scope=bot&permissions=66186303` with your `Client ID`.
|
||||||
- The link should now look like this:
|
- The link should now look like this:
|
||||||
`https://discordapp.com/oauth2/authorize?client_id=`**`YOUR_CLIENT_ID_HERE`**`&scope=bot&permissions=66186303`
|
`https://discordapp.com/oauth2/authorize?client_id=`**`YOUR_CLENT_ID_HERE`**`&scope=bot&permissions=66186303`
|
||||||
- Go to the newly created link and pick the server we created, and click `Authorize`.
|
- Go to the newly created link and pick the server we created, and click `Authorize`.
|
||||||
- The bot should have been added to your server.
|
- The bot should have been added to your server.
|
||||||
|
|
||||||
@ -149,15 +148,12 @@ It should look like:
|
|||||||
- Required for Urban Disctionary, Hashtag search, and Hearthstone cards.
|
- Required for Urban Disctionary, Hashtag search, and Hearthstone cards.
|
||||||
- You need to create an account on their [api marketplace](https://market.mashape.com/), after that go to `market.mashape.com/YOURNAMEHERE/applications/default-application` and press **Get the keys** in the top right corner.
|
- You need to create an account on their [api marketplace](https://market.mashape.com/), after that go to `market.mashape.com/YOURNAMEHERE/applications/default-application` and press **Get the keys** in the top right corner.
|
||||||
- Copy the key and paste it into `credentials.json`
|
- Copy the key and paste it into `credentials.json`
|
||||||
- **LoLApiKey**
|
- **LOLAPIKey**
|
||||||
- Required for all League of Legends commands.
|
- Required for all League of Legends commands.
|
||||||
- You can get this key [here.](http://api.champion.gg/)
|
- You can get this key [here](http://api.champion.gg/)
|
||||||
- **OsuApiKey**
|
- **OsuAPIKey**
|
||||||
- Required for Osu commands
|
- Required for Osu commands
|
||||||
- You can get this key [here.](https://osu.ppy.sh/p/api)
|
- You can get this key [here.](https://osu.ppy.sh/p/api)
|
||||||
- **CleverbotApiKey**
|
|
||||||
- Required if you want to use official cleverobot, instead of program-o
|
|
||||||
- you can get this key [here.](http://www.cleverbot.com/api/)
|
|
||||||
- **PatreonAccessToken**
|
- **PatreonAccessToken**
|
||||||
- For Patreon creators only.
|
- For Patreon creators only.
|
||||||
- **PatreonCampaignId**
|
- **PatreonCampaignId**
|
||||||
@ -189,8 +185,6 @@ in order to open the database file you will need [DB Browser for SQLite](http://
|
|||||||
- click on **Apply**
|
- click on **Apply**
|
||||||
- click on **Write Changes**
|
- click on **Write Changes**
|
||||||
|
|
||||||
![nadekodb](https://cdn.discordapp.com/attachments/251504306010849280/254067055240806400/nadekodb.gif)
|
|
||||||
|
|
||||||
and that will save all the changes.
|
and that will save all the changes.
|
||||||
|
|
||||||
## Sharding your bot
|
## Sharding your bot
|
||||||
@ -211,6 +205,7 @@ and that will save all the changes.
|
|||||||
- Bot uses a random UDP port in [5000, 6000) range for communication between shards
|
- Bot uses a random UDP port in [5000, 6000) range for communication between shards
|
||||||
|
|
||||||
|
|
||||||
|
![nadekodb](https://cdn.discordapp.com/attachments/251504306010849280/254067055240806400/nadekodb.gif)
|
||||||
|
|
||||||
[Google Console]: https://console.developers.google.com
|
[Google Console]: https://console.developers.google.com
|
||||||
[DiscordApp]: https://discordapp.com/developers/applications/me
|
[DiscordApp]: https://discordapp.com/developers/applications/me
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
Permissions Overview
|
Permissions Overview
|
||||||
===================
|
===================
|
||||||
Have you ever felt confused or even overwhelmed when trying to set Nadeko's permissions? In this guide we will be explaining how to use the
|
Have you ever felt confused or even overwhelmed when trying to set Nadeko's permissions? In this guide we will be explaining how to use the
|
||||||
permission commands correctly and even cover a few common questions! Every command we discuss here can be found in the [Commands List](http://nadekobot.readthedocs.io/en/latest/Commands%20List/#permissions).
|
permission commands correctly and even cover a few common questions! Every command we discuss here can be found in the [Commands List](http://nadekobot.readthedocs.io/en/1.0/Commands%20List/#permissions).
|
||||||
|
|
||||||
**To see the guide, [click here](http://nadekobot.readthedocs.io/en/latest/Permissions%20System/)**
|
**To see the old guide for versions 0.9 and below, see [here](http://nadekobot.readthedocs.io/en/latest/Permissions%20System/)**
|
||||||
|
|
||||||
Why do we use the Permissions Commands?
|
Why do we use the Permissions Commands?
|
||||||
------------------------------
|
------------------------------
|
||||||
@ -15,14 +15,11 @@ With the permissions system it possible to restrict who can skip the current son
|
|||||||
|
|
||||||
First Time Setup
|
First Time Setup
|
||||||
------------------
|
------------------
|
||||||
To change permissions you **must** meet the following requirements:
|
To change permissions you **must** meet the following requirement:
|
||||||
|
|
||||||
**Be the owner of the server**
|
**Have the role specified by `.permrole` (By default, this is Nadeko)**
|
||||||
|
|
||||||
**If you are NOT the server owner, get the role specified by `.permrole` (By default, this is Nadeko)**
|
|
||||||
|
|
||||||
If you have an existing role called `Nadeko` but can't assign it to yourself, create a new role called `Nadeko` and assign that to yourself.
|
If you have an existing role called `Nadeko` but can't assign it to yourself, create a new role called `Nadeko` and assign that to yourself.
|
||||||
![img0](https://i.imgur.com/5QKZqqy.gif)
|
|
||||||
|
|
||||||
If you would like to set a different role, such as `Admins`, to be the role required to edit permissions, do `.permrole Admins` (you must have the current permission role to be able to do this).
|
If you would like to set a different role, such as `Admins`, to be the role required to edit permissions, do `.permrole Admins` (you must have the current permission role to be able to do this).
|
||||||
|
|
||||||
@ -38,7 +35,7 @@ To view this permissions chain, do `.listperms`, with the top of the chain being
|
|||||||
If you want to remove a permission from the chain of permissions, do `.removeperm X` to remove rule number X and similarly, do `.moveperm X Y` to move rule number X to number Y (moving, not swapping!).
|
If you want to remove a permission from the chain of permissions, do `.removeperm X` to remove rule number X and similarly, do `.moveperm X Y` to move rule number X to number Y (moving, not swapping!).
|
||||||
|
|
||||||
As an example, if you wanted to enable NSFW for a certain role, say "Lewd", you could do `.rolemdl NSFW enable Lewd`.
|
As an example, if you wanted to enable NSFW for a certain role, say "Lewd", you could do `.rolemdl NSFW enable Lewd`.
|
||||||
This adds the rule to the top of the permissions chain so even if the default `.sm NSFW disable` rule exists, the "Lewd" role will be able to use the NSFW module.
|
This adds the rule to the top of the permissions chain so even if the default `.sm NSFW disabled` rule exists, the "Lewd" role will be able to use the NSFW module.
|
||||||
|
|
||||||
If you want the bot to notify users why they can't use a command or module, use `.verbose true` and Nadeko will tell you what rule is preventing the command.
|
If you want the bot to notify users why they can't use a command or module, use `.verbose true` and Nadeko will tell you what rule is preventing the command.
|
||||||
|
|
||||||
@ -52,11 +49,11 @@ To allow users to only see the current song and have a DJ role for queuing follo
|
|||||||
|
|
||||||
* Disables music commands for everybody
|
* Disables music commands for everybody
|
||||||
|
|
||||||
2. `.sc .nowplaying enable`
|
2. `.sc !!nowplaying enable`
|
||||||
|
|
||||||
* Enables the "nowplaying" command for everyone
|
* Enables the "nowplaying" command for everyone
|
||||||
|
|
||||||
3. `.sc .listqueue enable`
|
3. `.sc !!listqueue enable`
|
||||||
|
|
||||||
* Enables the "listqueue" command for everyone
|
* Enables the "listqueue" command for everyone
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ For this guide we will be using the folder /nadeko as our config root folder.
|
|||||||
```bash
|
```bash
|
||||||
docker create --name=nadeko -v /nadeko/conf/:/root/nadeko -v /nadeko/data:/opt/NadekoBot/src/NadekoBot/bin/Release/netcoreapp1.1/data uirel/nadeko:1.4
|
docker create --name=nadeko -v /nadeko/conf/:/root/nadeko -v /nadeko/data:/opt/NadekoBot/src/NadekoBot/bin/Release/netcoreapp1.1/data uirel/nadeko:1.4
|
||||||
```
|
```
|
||||||
-If you are coming from a previous version of nadeko (the old docker) make sure your credentials.json has been copied into this directory and is the only thing in this folder.
|
-If you are coming from a previous version of nadeko (the old docker) make sure your crednetials.json has been copied into this directory and is the only thing in this folder.
|
||||||
|
|
||||||
-If you are making a fresh install, create your credentials.json from the following guide and place it in the /nadeko folder [Nadeko JSON Guide](http://nadekobot.readthedocs.io/en/latest/JSON%20Explanations/)
|
-If you are making a fresh install, create your credentials.json from the following guide and place it in the /nadeko folder [Nadeko JSON Guide](http://nadekobot.readthedocs.io/en/latest/JSON%20Explanations/)
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ Next start the docker up with
|
|||||||
The docker will start and the log file will start scrolling past. Depending on hardware the bot start can take up to 5 minutes on a small DigitalOcean droplet.
|
The docker will start and the log file will start scrolling past. Depending on hardware the bot start can take up to 5 minutes on a small DigitalOcean droplet.
|
||||||
Once the log ends with "NadekoBot | Starting NadekoBot v1.0-rc2" the bot is ready and can be invited to your server. Ctrl+C at this point to stop viewing the logs.
|
Once the log ends with "NadekoBot | Starting NadekoBot v1.0-rc2" the bot is ready and can be invited to your server. Ctrl+C at this point to stop viewing the logs.
|
||||||
|
|
||||||
After a few moments you should be able to invite Nadeko to your server. If you cannot check the log file for errors.
|
After a few moments you should be able to invite Nadeko to your server. If you cannot check the log file for errors
|
||||||
|
|
||||||
## Monitoring
|
## Monitoring
|
||||||
|
|
||||||
|
@ -6,13 +6,13 @@ Prerequisites
|
|||||||
*Clone the repo*
|
*Clone the repo*
|
||||||
`git clone -b 1.4 https://github.com/Kwoth/NadekoBot`
|
`git clone -b 1.4 https://github.com/Kwoth/NadekoBot`
|
||||||
`cd NadekoBot/src/NadekoBot`
|
`cd NadekoBot/src/NadekoBot`
|
||||||
Edit `credentials.json.` Read the [JSON Explanations](http://nadekobot.readthedocs.io/en/latest/JSON%20Explanations/) guide if you don't know how to set it up.
|
Edit `credentials.json.` Read the JSON Exaplanations guide on the left if you don't know how to set it up
|
||||||
|
|
||||||
*run*
|
*run*
|
||||||
`dotnet restore`
|
`dotnet restore`
|
||||||
`dotnet run -c Release`
|
`dotnet run -c Release`
|
||||||
|
|
||||||
*when you decide to update in the future (might not work if you've made custom edits to the source, make sure you know how git works)*
|
*when you decide to updatein the future (might not work if you've made custom edits to the source, make sure you know how git works)*
|
||||||
`git pull`
|
`git pull`
|
||||||
`dotnet restore`
|
`dotnet restore`
|
||||||
`dotnet run -c Release`
|
`dotnet run -c Release`
|
||||||
|
@ -24,8 +24,6 @@ brew install opusfile
|
|||||||
brew install libffi
|
brew install libffi
|
||||||
brew install libsodium
|
brew install libsodium
|
||||||
brew install tmux
|
brew install tmux
|
||||||
brew install python
|
|
||||||
brew install youtube-dl
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Installing .NET Core SDK
|
#### Installing .NET Core SDK
|
||||||
|
@ -10,21 +10,21 @@
|
|||||||
|
|
||||||
#### If you are running Dockerised Nadeko
|
#### If you are running Dockerised Nadeko
|
||||||
|
|
||||||
- Shutdown your existing container `docker stop nadeko`.
|
- Shutdown your existing container **docker stop nadeko**.
|
||||||
- Move you credentials and other files to another folder.
|
- Move you credentials and other files to another folder.
|
||||||
- Delete your container `docker rm nadeko`.
|
- Delete your container **docker rm nadeko**.
|
||||||
- Create a new container `docker create --name=nadeko -v /nadeko/:/root/nadeko uirel/nadeko:1.4`.
|
- Create a new container **docker create --name=nadeko -v /nadeko/:/root/nadeko uirel/nadeko:1.4**.
|
||||||
- Start the container with `docker start nadeko`, and wait for it to complain about lacking credentials.
|
- Start the container **docker start nadeko** wait for it to complain about lacking credentials.
|
||||||
- Stop the container, `docker stop nadeko`, open the `Nadeko` folder and replace the credentials, database and other files with your copies.
|
- Stop the container **docker stop nadeko** open the nadeko folder and replace the credentials, database and other files with your copies.
|
||||||
- Restart the container `docker start nadeko`.
|
- Restart the container **docker start nadeko**.
|
||||||
|
|
||||||
#### If you have NadekoBot 1.x on Linux or macOS
|
#### If you have NadekoBot 1.x on Linux or macOS
|
||||||
|
|
||||||
- Backup the `NadekoBot.db` from `NadekoBot/src/NadekoBot/bin/Release/netcoreapp1.0/data`.
|
- Backup the `NadekoBot.db` from `NadekoBot/src/NadekoBot/bin/Release/netcoreapp1.0/data`
|
||||||
- Backup the `credentials.json` from `NadekoBot/src/NadekoBot/`.
|
- Backup the `credentials.json` from `NadekoBot/src/NadekoBot/`
|
||||||
- **For MacOS Users Only:** download and install the latest version of [.NET Core SDK](https://www.microsoft.com/net/core#macos).
|
- **For MacOS Users Only:** download and install the latest version of [.NET Core SDK](https://www.microsoft.com/net/core#macos)
|
||||||
- Next, use the command `cd ~ && wget -N https://github.com/Kwoth/NadekoBot-BashScript/raw/1.4/linuxAIO.sh && bash linuxAIO.sh`
|
- Next, use the command `cd ~ && wget -N https://github.com/Kwoth/NadekoBot-BashScript/raw/1.4/linuxAIO.sh && bash linuxAIO.sh`
|
||||||
- **For Ubuntu, Debian and CentOS Users Only:** use the option `4. Auto-Install Prerequisites` to install the latest version of .NET Core SDK.
|
- **For Ubuntu, Debian and CentOS Users Only:** use the option `4. Auto-Install Prerequisites` to install the latest version of .NET Core SDK.
|
||||||
- Use option `1. Download NadekoBot` to update your NadekoBot to 1.4+ version.
|
- Use option `1. Download NadekoBot` to update your NadekoBot to 1.4.x.
|
||||||
- Next, just [run your NadekoBot.](http://nadekobot.readthedocs.io/en/latest/guides/Linux%20Guide/#running-nadekobot)
|
- Next, just [run your NadekoBot.](http://nadekobot.readthedocs.io/en/latest/guides/Linux%20Guide/#running-nadekobot)
|
||||||
- *NOTE: 1.4+ version uses `NadekoBot.db` file from `NadekoBot/src/NadekoBot/bin/Release/netcoreapp1.1/data` folder.*
|
- *NOTE: 1.4.x uses `NadekoBot.db` file from `NadekoBot/src/NadekoBot/bin/Release/netcoreapp1.1/data` folder.*
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#### Guide
|
#### Guide
|
||||||
- Download and run the [NadekoBot Updater.][Updater]
|
- Download and run the [NadekoBot Updater.][Updater]
|
||||||
- Press **`Install ffmpeg`** and **`Install youtube-dl`** if you want music features.
|
- Press **`Install ffmpeg`** button if you want music features.
|
||||||
***NOTE:** RESTART YOUR PC IF YOU DO.*
|
***NOTE:** RESTART YOUR PC IF YOU DO.*
|
||||||
- Press **`Update`** and go through the installation wizard.
|
- Press **`Update`** and go through the installation wizard.
|
||||||
***NOTE:** If you're upgrading from 1.3, DO NOT select your old nadekobot folder. Install it in a separate directory and read the [upgrading guide](http://nadekobot.readthedocs.io/en/latest/guides/Upgrading%20Guide/).*
|
***NOTE:** If you're upgrading from 1.3, DO NOT select your old nadekobot folder. Install it in a separate directory and read the [upgrading guide](http://nadekobot.readthedocs.io/en/latest/guides/Upgrading%20Guide/).*
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
using System.Linq;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Services;
|
||||||
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Discord.Commands;
|
|
||||||
using NadekoBot.Services.Impl;
|
|
||||||
|
|
||||||
namespace NadekoBot.Common.Attributes
|
namespace NadekoBot.Attributes
|
||||||
{
|
{
|
||||||
public class Aliases : AliasAttribute
|
public class Aliases : AliasAttribute
|
||||||
{
|
{
|
@ -1,8 +1,8 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using Discord.Commands;
|
||||||
using Discord.Commands;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Services.Impl;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace NadekoBot.Common.Attributes
|
namespace NadekoBot.Attributes
|
||||||
{
|
{
|
||||||
public class Description : SummaryAttribute
|
public class Description : SummaryAttribute
|
||||||
{
|
{
|
@ -1,8 +1,8 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using Discord.Commands;
|
||||||
using Discord.Commands;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Services.Impl;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace NadekoBot.Common.Attributes
|
namespace NadekoBot.Attributes
|
||||||
{
|
{
|
||||||
public class NadekoCommand : CommandAttribute
|
public class NadekoCommand : CommandAttribute
|
||||||
{
|
{
|
@ -1,7 +1,7 @@
|
|||||||
using System;
|
using Discord.Commands;
|
||||||
using Discord.Commands;
|
using System;
|
||||||
|
|
||||||
namespace NadekoBot.Common.Attributes
|
namespace NadekoBot.Attributes
|
||||||
{
|
{
|
||||||
[AttributeUsage(AttributeTargets.Class)]
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
sealed class NadekoModuleAttribute : GroupAttribute
|
sealed class NadekoModuleAttribute : GroupAttribute
|
@ -1,9 +1,9 @@
|
|||||||
using System;
|
using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using System;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
|
|
||||||
namespace NadekoBot.Common.Attributes
|
namespace NadekoBot.Attributes
|
||||||
{
|
{
|
||||||
public class OwnerOnlyAttribute : PreconditionAttribute
|
public class OwnerOnlyAttribute : PreconditionAttribute
|
||||||
{
|
{
|
@ -1,8 +1,8 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using Discord.Commands;
|
||||||
using Discord.Commands;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Services.Impl;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace NadekoBot.Common.Attributes
|
namespace NadekoBot.Attributes
|
||||||
{
|
{
|
||||||
public class Usage : RemarksAttribute
|
public class Usage : RemarksAttribute
|
||||||
{
|
{
|
@ -1,26 +0,0 @@
|
|||||||
namespace NadekoBot.Common
|
|
||||||
{
|
|
||||||
public enum BotConfigEditType
|
|
||||||
{
|
|
||||||
BetflipMultiplier,
|
|
||||||
Betroll100Multiplier,
|
|
||||||
Betroll67Multiplier,
|
|
||||||
Betroll91Multiplier,
|
|
||||||
CurrencyGenerationChance,
|
|
||||||
CurrencyGenerationCooldown,
|
|
||||||
CurrencyName,
|
|
||||||
CurrencyPluralName,
|
|
||||||
CurrencySign,
|
|
||||||
DmHelpString,
|
|
||||||
HelpString,
|
|
||||||
CurrencyDropAmount,
|
|
||||||
CurrencyDropAmountMax,
|
|
||||||
MinimumBetAmount,
|
|
||||||
TriviaCurrencyReward,
|
|
||||||
XpPerMessage,
|
|
||||||
XpMinutesTimeout,
|
|
||||||
|
|
||||||
//ErrorColor, //after i fix the nadekobot.cs static variables
|
|
||||||
//OkColor
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
namespace NadekoBot.Common.TypeReaders
|
|
||||||
{
|
|
||||||
public enum AddRemove
|
|
||||||
{
|
|
||||||
Add = 0,
|
|
||||||
Rem = 1,
|
|
||||||
Rm = 1,
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,7 +2,7 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Common
|
namespace NadekoBot.DataStructures
|
||||||
{
|
{
|
||||||
public class AsyncLazy<T> : Lazy<Task<T>>
|
public class AsyncLazy<T> : Lazy<Task<T>>
|
||||||
{
|
{
|
@ -1,10 +1,8 @@
|
|||||||
using System;
|
using Discord;
|
||||||
using Discord;
|
|
||||||
using NadekoBot.Extensions;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
|
||||||
namespace NadekoBot.Common
|
namespace NadekoBot.DataStructures
|
||||||
{
|
{
|
||||||
public class CREmbed
|
public class CREmbed
|
||||||
{
|
{
|
||||||
@ -33,30 +31,18 @@ namespace NadekoBot.Common
|
|||||||
|
|
||||||
public EmbedBuilder ToEmbed()
|
public EmbedBuilder ToEmbed()
|
||||||
{
|
{
|
||||||
var embed = new EmbedBuilder();
|
var embed = new EmbedBuilder()
|
||||||
|
.WithTitle(Title)
|
||||||
if (!string.IsNullOrWhiteSpace(Title))
|
.WithDescription(Description)
|
||||||
embed.WithTitle(Title);
|
.WithColor(new Discord.Color(Color));
|
||||||
if (!string.IsNullOrWhiteSpace(Description))
|
|
||||||
embed.WithDescription(Description);
|
|
||||||
embed.WithColor(new Discord.Color(Color));
|
|
||||||
if (Footer != null)
|
if (Footer != null)
|
||||||
embed.WithFooter(efb =>
|
embed.WithFooter(efb => efb.WithIconUrl(Footer.IconUrl).WithText(Footer.Text));
|
||||||
{
|
embed.WithThumbnailUrl(Thumbnail)
|
||||||
efb.WithText(Footer.Text);
|
.WithImageUrl(Image);
|
||||||
if (Uri.IsWellFormedUriString(Footer.IconUrl, UriKind.Absolute))
|
|
||||||
efb.WithIconUrl(Footer.IconUrl);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (Thumbnail != null && Uri.IsWellFormedUriString(Thumbnail, UriKind.Absolute))
|
|
||||||
embed.WithThumbnailUrl(Thumbnail);
|
|
||||||
if(Image != null && Uri.IsWellFormedUriString(Image, UriKind.Absolute))
|
|
||||||
embed.WithImageUrl(Image);
|
|
||||||
|
|
||||||
if (Fields != null)
|
if (Fields != null)
|
||||||
foreach (var f in Fields)
|
foreach (var f in Fields)
|
||||||
{
|
{
|
||||||
if(!string.IsNullOrWhiteSpace(f.Name) && !string.IsNullOrWhiteSpace(f.Value))
|
|
||||||
embed.AddField(efb => efb.WithName(f.Name).WithValue(f.Value).WithIsInline(f.Inline));
|
embed.AddField(efb => efb.WithName(f.Name).WithValue(f.Value).WithIsInline(f.Inline));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,12 +59,6 @@ namespace NadekoBot.Common
|
|||||||
{
|
{
|
||||||
var crembed = JsonConvert.DeserializeObject<CREmbed>(input);
|
var crembed = JsonConvert.DeserializeObject<CREmbed>(input);
|
||||||
|
|
||||||
if(crembed.Fields != null && crembed.Fields.Length > 0)
|
|
||||||
foreach (var f in crembed.Fields)
|
|
||||||
{
|
|
||||||
f.Name = f.Name.TrimTo(256);
|
|
||||||
f.Value = f.Value.TrimTo(1024);
|
|
||||||
}
|
|
||||||
if (!crembed.IsValid)
|
if (!crembed.IsValid)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1,14 +1,13 @@
|
|||||||
// License MIT
|
// License MIT
|
||||||
// Source: https://github.com/i3arnon/ConcurrentHashSet
|
// Source: https://github.com/i3arnon/ConcurrentHashSet
|
||||||
|
|
||||||
using System;
|
using ConcurrentCollections;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace NadekoBot.Common.Collections
|
namespace System.Collections.Concurrent
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a thread-safe hash-based unique collection.
|
/// Represents a thread-safe hash-based unique collection.
|
@ -2,8 +2,9 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace NadekoBot.Common.Collections
|
namespace NadekoBot.DataStructures
|
||||||
{
|
{
|
||||||
|
|
||||||
public static class DisposableReadOnlyListExtensions
|
public static class DisposableReadOnlyListExtensions
|
||||||
{
|
{
|
||||||
public static IDisposableReadOnlyList<T> AsDisposable<T>(this IReadOnlyList<T> arr) where T : IDisposable
|
public static IDisposableReadOnlyList<T> AsDisposable<T>(this IReadOnlyList<T> arr) where T : IDisposable
|
@ -1,11 +1,11 @@
|
|||||||
using System.Collections;
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NadekoBot.Services.Database.Models;
|
|
||||||
|
|
||||||
namespace NadekoBot.Common.Collections
|
namespace NadekoBot.DataStructures
|
||||||
{
|
{
|
||||||
public class IndexedCollection<T> : IList<T> where T : class, IIndexed
|
public class IndexedCollection<T> : IList<T> where T : IIndexed
|
||||||
{
|
{
|
||||||
public List<T> Source { get; }
|
public List<T> Source { get; }
|
||||||
private readonly object _locker = new object();
|
private readonly object _locker = new object();
|
@ -1,7 +1,7 @@
|
|||||||
using System.Threading.Tasks;
|
using Discord;
|
||||||
using Discord;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Common.ModuleBehaviors
|
namespace NadekoBot.DataStructures.ModuleBehaviors
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Implemented by modules which block execution before anything is executed
|
/// Implemented by modules which block execution before anything is executed
|
@ -1,8 +1,8 @@
|
|||||||
using System.Threading.Tasks;
|
using Discord;
|
||||||
using Discord;
|
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Common.ModuleBehaviors
|
namespace NadekoBot.DataStructures.ModuleBehaviors
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Implemented by modules which can execute something and prevent further commands from being executed.
|
/// Implemented by modules which can execute something and prevent further commands from being executed.
|
@ -1,4 +1,4 @@
|
|||||||
namespace NadekoBot.Common.ModuleBehaviors
|
namespace NadekoBot.DataStructures.ModuleBehaviors
|
||||||
{
|
{
|
||||||
public interface IEarlyExecutor
|
public interface IEarlyExecutor
|
||||||
{
|
{
|
@ -1,7 +1,7 @@
|
|||||||
using System.Threading.Tasks;
|
using Discord;
|
||||||
using Discord;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Common.ModuleBehaviors
|
namespace NadekoBot.DataStructures.ModuleBehaviors
|
||||||
{
|
{
|
||||||
public interface IInputTransformer
|
public interface IInputTransformer
|
||||||
{
|
{
|
@ -1,8 +1,8 @@
|
|||||||
using System.Threading.Tasks;
|
using Discord;
|
||||||
using Discord;
|
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Common.ModuleBehaviors
|
namespace NadekoBot.DataStructures.ModuleBehaviors
|
||||||
{
|
{
|
||||||
public interface ILateBlocker
|
public interface ILateBlocker
|
||||||
{
|
{
|
@ -1,4 +1,4 @@
|
|||||||
namespace NadekoBot.Common.ModuleBehaviors
|
namespace NadekoBot.DataStructures.ModuleBehaviors
|
||||||
{
|
{
|
||||||
public interface ILateBlockingExecutor
|
public interface ILateBlockingExecutor
|
||||||
{
|
{
|
@ -1,8 +1,8 @@
|
|||||||
using System.Threading.Tasks;
|
using Discord;
|
||||||
using Discord;
|
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Common.ModuleBehaviors
|
namespace NadekoBot.DataStructures.ModuleBehaviors
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Last thing to be executed, won't stop further executions
|
/// Last thing to be executed, won't stop further executions
|
@ -1,21 +1,26 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace NadekoBot.Common
|
namespace NadekoBot.Services
|
||||||
{
|
{
|
||||||
public class NadekoRandom : Random
|
public class NadekoRandom : Random
|
||||||
{
|
{
|
||||||
readonly RandomNumberGenerator _rng;
|
RandomNumberGenerator rng;
|
||||||
|
|
||||||
public NadekoRandom() : base()
|
public NadekoRandom() : base()
|
||||||
{
|
{
|
||||||
_rng = RandomNumberGenerator.Create();
|
rng = RandomNumberGenerator.Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
private NadekoRandom(int Seed) : base(Seed)
|
||||||
|
{
|
||||||
|
rng = RandomNumberGenerator.Create();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int Next()
|
public override int Next()
|
||||||
{
|
{
|
||||||
var bytes = new byte[sizeof(int)];
|
var bytes = new byte[sizeof(int)];
|
||||||
_rng.GetBytes(bytes);
|
rng.GetBytes(bytes);
|
||||||
return Math.Abs(BitConverter.ToInt32(bytes, 0));
|
return Math.Abs(BitConverter.ToInt32(bytes, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,7 +29,7 @@ namespace NadekoBot.Common
|
|||||||
if (maxValue <= 0)
|
if (maxValue <= 0)
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
var bytes = new byte[sizeof(int)];
|
var bytes = new byte[sizeof(int)];
|
||||||
_rng.GetBytes(bytes);
|
rng.GetBytes(bytes);
|
||||||
return Math.Abs(BitConverter.ToInt32(bytes, 0)) % maxValue;
|
return Math.Abs(BitConverter.ToInt32(bytes, 0)) % maxValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,27 +40,27 @@ namespace NadekoBot.Common
|
|||||||
if (minValue == maxValue)
|
if (minValue == maxValue)
|
||||||
return minValue;
|
return minValue;
|
||||||
var bytes = new byte[sizeof(int)];
|
var bytes = new byte[sizeof(int)];
|
||||||
_rng.GetBytes(bytes);
|
rng.GetBytes(bytes);
|
||||||
var sign = Math.Sign(BitConverter.ToInt32(bytes, 0));
|
var sign = Math.Sign(BitConverter.ToInt32(bytes, 0));
|
||||||
return (sign * BitConverter.ToInt32(bytes, 0)) % (maxValue - minValue) + minValue;
|
return (sign * BitConverter.ToInt32(bytes, 0)) % (maxValue - minValue) + minValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void NextBytes(byte[] buffer)
|
public override void NextBytes(byte[] buffer)
|
||||||
{
|
{
|
||||||
_rng.GetBytes(buffer);
|
rng.GetBytes(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override double Sample()
|
protected override double Sample()
|
||||||
{
|
{
|
||||||
var bytes = new byte[sizeof(double)];
|
var bytes = new byte[sizeof(double)];
|
||||||
_rng.GetBytes(bytes);
|
rng.GetBytes(bytes);
|
||||||
return Math.Abs(BitConverter.ToDouble(bytes, 0) / double.MaxValue + 1);
|
return Math.Abs(BitConverter.ToDouble(bytes, 0) / double.MaxValue + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override double NextDouble()
|
public override double NextDouble()
|
||||||
{
|
{
|
||||||
var bytes = new byte[sizeof(double)];
|
var bytes = new byte[sizeof(double)];
|
||||||
_rng.GetBytes(bytes);
|
rng.GetBytes(bytes);
|
||||||
return BitConverter.ToDouble(bytes, 0);
|
return BitConverter.ToDouble(bytes, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,8 +1,8 @@
|
|||||||
using System;
|
using Discord.Commands;
|
||||||
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord.Commands;
|
|
||||||
|
|
||||||
namespace NadekoBot.Common
|
namespace NadekoBot.DataStructures
|
||||||
{
|
{
|
||||||
public class NoPublicBot : PreconditionAttribute
|
public class NoPublicBot : PreconditionAttribute
|
||||||
{
|
{
|
@ -1,4 +1,4 @@
|
|||||||
namespace NadekoBot.Common.TypeReaders.Models
|
namespace NadekoBot.Modules.Permissions
|
||||||
{
|
{
|
||||||
public class PermissionAction
|
public class PermissionAction
|
||||||
{
|
{
|
@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace NadekoBot.Common
|
namespace ConcurrentCollections
|
||||||
{
|
{
|
||||||
public static class PlatformHelper
|
public static class PlatformHelper
|
||||||
{
|
{
|
@ -1,19 +1,29 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Common.Collections
|
namespace NadekoBot.DataStructures
|
||||||
{
|
{
|
||||||
public class PoopyRingBuffer : IDisposable
|
public class PoopyRingBuffer : IDisposable
|
||||||
{
|
{
|
||||||
// readpos == writepos means empty
|
// readpos == writepos means empty
|
||||||
// writepos == readpos - 1 means full
|
// writepos == readpos - 1 means full
|
||||||
|
|
||||||
private byte[] _buffer;
|
private byte[] buffer;
|
||||||
public int Capacity { get; }
|
public int Capacity { get; }
|
||||||
|
|
||||||
private int ReadPos { get; set; } = 0;
|
private int _readPos = 0;
|
||||||
private int WritePos { get; set; } = 0;
|
private int ReadPos
|
||||||
|
{
|
||||||
|
get => _readPos;
|
||||||
|
set => _readPos = value;
|
||||||
|
}
|
||||||
|
private int _writePos = 0;
|
||||||
|
private int WritePos
|
||||||
|
{
|
||||||
|
get => _writePos;
|
||||||
|
set => _writePos = value;
|
||||||
|
}
|
||||||
public int Length => ReadPos <= WritePos
|
public int Length => ReadPos <= WritePos
|
||||||
? WritePos - ReadPos
|
? WritePos - ReadPos
|
||||||
: Capacity - (ReadPos - WritePos);
|
: Capacity - (ReadPos - WritePos);
|
||||||
@ -28,7 +38,7 @@ namespace NadekoBot.Common.Collections
|
|||||||
public PoopyRingBuffer(int capacity = 81920 * 100)
|
public PoopyRingBuffer(int capacity = 81920 * 100)
|
||||||
{
|
{
|
||||||
this.Capacity = capacity + 1;
|
this.Capacity = capacity + 1;
|
||||||
this._buffer = new byte[this.Capacity];
|
this.buffer = new byte[this.Capacity];
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Read(byte[] b, int offset, int toRead)
|
public int Read(byte[] b, int offset, int toRead)
|
||||||
@ -41,7 +51,7 @@ namespace NadekoBot.Common.Collections
|
|||||||
|
|
||||||
if (WritePos > ReadPos)
|
if (WritePos > ReadPos)
|
||||||
{
|
{
|
||||||
Array.Copy(_buffer, ReadPos, b, offset, toRead);
|
Array.Copy(buffer, ReadPos, b, offset, toRead);
|
||||||
ReadPos += toRead;
|
ReadPos += toRead;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -50,12 +60,12 @@ namespace NadekoBot.Common.Collections
|
|||||||
var firstRead = toRead > toEnd ?
|
var firstRead = toRead > toEnd ?
|
||||||
toEnd :
|
toEnd :
|
||||||
toRead;
|
toRead;
|
||||||
Array.Copy(_buffer, ReadPos, b, offset, firstRead);
|
Array.Copy(buffer, ReadPos, b, offset, firstRead);
|
||||||
ReadPos += firstRead;
|
ReadPos += firstRead;
|
||||||
var secondRead = toRead - firstRead;
|
var secondRead = toRead - firstRead;
|
||||||
if (secondRead > 0)
|
if (secondRead > 0)
|
||||||
{
|
{
|
||||||
Array.Copy(_buffer, 0, b, offset + firstRead, secondRead);
|
Array.Copy(buffer, 0, b, offset + firstRead, secondRead);
|
||||||
ReadPos = secondRead;
|
ReadPos = secondRead;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,7 +82,7 @@ namespace NadekoBot.Common.Collections
|
|||||||
|
|
||||||
if (WritePos < ReadPos)
|
if (WritePos < ReadPos)
|
||||||
{
|
{
|
||||||
Array.Copy(b, offset, _buffer, WritePos, toWrite);
|
Array.Copy(b, offset, buffer, WritePos, toWrite);
|
||||||
WritePos += toWrite;
|
WritePos += toWrite;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -81,11 +91,11 @@ namespace NadekoBot.Common.Collections
|
|||||||
var firstWrite = toWrite > toEnd ?
|
var firstWrite = toWrite > toEnd ?
|
||||||
toEnd :
|
toEnd :
|
||||||
toWrite;
|
toWrite;
|
||||||
Array.Copy(b, offset, _buffer, WritePos, firstWrite);
|
Array.Copy(b, offset, buffer, WritePos, firstWrite);
|
||||||
var secondWrite = toWrite - firstWrite;
|
var secondWrite = toWrite - firstWrite;
|
||||||
if (secondWrite > 0)
|
if (secondWrite > 0)
|
||||||
{
|
{
|
||||||
Array.Copy(b, offset + firstWrite, _buffer, 0, secondWrite);
|
Array.Copy(b, offset + firstWrite, buffer, 0, secondWrite);
|
||||||
WritePos = secondWrite;
|
WritePos = secondWrite;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -100,7 +110,7 @@ namespace NadekoBot.Common.Collections
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_buffer = null;
|
buffer = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,15 +1,16 @@
|
|||||||
using System;
|
using Discord;
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using Discord;
|
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Modules.Administration.Services;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Modules.Music.Services;
|
using NadekoBot.Services.Administration;
|
||||||
|
using NadekoBot.Services.Music;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace NadekoBot.Common.Replacements
|
namespace NadekoBot.DataStructures.Replacements
|
||||||
{
|
{
|
||||||
public class ReplacementBuilder
|
public class ReplacementBuilder
|
||||||
{
|
{
|
@ -2,7 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace NadekoBot.Common.Replacements
|
namespace NadekoBot.DataStructures.Replacements
|
||||||
{
|
{
|
||||||
public class Replacer
|
public class Replacer
|
||||||
{
|
{
|
@ -1,4 +1,8 @@
|
|||||||
using System;
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Services;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using NLog;
|
||||||
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -6,12 +10,9 @@ using System.Net.Http;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using NadekoBot.Common;
|
using System.Xml.Linq;
|
||||||
using NadekoBot.Extensions;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using NLog;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Searches.Common
|
namespace NadekoBot.DataStructures
|
||||||
{
|
{
|
||||||
public class SearchImageCacher
|
public class SearchImageCacher
|
||||||
{
|
{
|
||||||
@ -20,25 +21,18 @@ namespace NadekoBot.Modules.Searches.Common
|
|||||||
|
|
||||||
private readonly SortedSet<ImageCacherObject> _cache;
|
private readonly SortedSet<ImageCacherObject> _cache;
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly HttpClient _http;
|
|
||||||
|
|
||||||
public SearchImageCacher()
|
public SearchImageCacher()
|
||||||
{
|
{
|
||||||
_http = new HttpClient();
|
|
||||||
_http.AddFakeHeaders();
|
|
||||||
|
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_rng = new NadekoRandom();
|
_rng = new NadekoRandom();
|
||||||
_cache = new SortedSet<ImageCacherObject>();
|
_cache = new SortedSet<ImageCacherObject>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ImageCacherObject> GetImage(string tag, bool forceExplicit, DapiSearchType type,
|
public async Task<ImageCacherObject> GetImage(string tag, bool forceExplicit, DapiSearchType type)
|
||||||
HashSet<string> blacklistedTags = null)
|
|
||||||
{
|
{
|
||||||
tag = tag?.ToLowerInvariant();
|
tag = tag?.ToLowerInvariant();
|
||||||
|
|
||||||
blacklistedTags = blacklistedTags ?? new HashSet<string>();
|
|
||||||
|
|
||||||
if (type == DapiSearchType.E621)
|
if (type == DapiSearchType.E621)
|
||||||
tag = tag?.Replace("yuri", "female/female");
|
tag = tag?.Replace("yuri", "female/female");
|
||||||
|
|
||||||
@ -70,9 +64,6 @@ namespace NadekoBot.Modules.Searches.Common
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var images = await DownloadImages(tag, forceExplicit, type).ConfigureAwait(false);
|
var images = await DownloadImages(tag, forceExplicit, type).ConfigureAwait(false);
|
||||||
images = images
|
|
||||||
.Where(x => x.Tags.All(t => !blacklistedTags.Contains(t)))
|
|
||||||
.ToArray();
|
|
||||||
if (images.Length == 0)
|
if (images.Length == 0)
|
||||||
return null;
|
return null;
|
||||||
var toReturn = images[_rng.Next(images.Length)];
|
var toReturn = images[_rng.Next(images.Length)];
|
||||||
@ -111,26 +102,30 @@ namespace NadekoBot.Modules.Searches.Common
|
|||||||
website = $"https://e621.net/post/index.json?limit=1000&tags={tag}";
|
website = $"https://e621.net/post/index.json?limit=1000&tags={tag}";
|
||||||
break;
|
break;
|
||||||
case DapiSearchType.Danbooru:
|
case DapiSearchType.Danbooru:
|
||||||
website = $"http://danbooru.donmai.us/posts.json?limit=100&tags={tag}";
|
website = $"http://danbooru.donmai.us/posts.json?limit=200&tags={tag}";
|
||||||
break;
|
break;
|
||||||
case DapiSearchType.Gelbooru:
|
case DapiSearchType.Gelbooru:
|
||||||
website = $"http://gelbooru.com/index.php?page=dapi&s=post&q=index&limit=100&tags={tag}";
|
website = $"http://gelbooru.com/index.php?page=dapi&s=post&q=index&limit=1000&tags={tag}";
|
||||||
break;
|
break;
|
||||||
case DapiSearchType.Rule34:
|
case DapiSearchType.Rule34:
|
||||||
website = $"https://rule34.xxx/index.php?page=dapi&s=post&q=index&limit=100&tags={tag}";
|
website = $"https://rule34.xxx/index.php?page=dapi&s=post&q=index&limit=100&tags={tag}";
|
||||||
break;
|
break;
|
||||||
case DapiSearchType.Konachan:
|
case DapiSearchType.Konachan:
|
||||||
website = $"https://konachan.com/post.json?s=post&q=index&limit=100&tags={tag}";
|
website = $"https://konachan.com/post.json?s=post&q=index&limit=1000&tags={tag}";
|
||||||
break;
|
break;
|
||||||
case DapiSearchType.Yandere:
|
case DapiSearchType.Yandere:
|
||||||
website = $"https://yande.re/post.json?limit=100&tags={tag}";
|
website = $"https://yande.re/post.json?limit=1000&tags={tag}";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using (var http = new HttpClient())
|
||||||
|
{
|
||||||
|
http.AddFakeHeaders();
|
||||||
|
|
||||||
if (type == DapiSearchType.Konachan || type == DapiSearchType.Yandere ||
|
if (type == DapiSearchType.Konachan || type == DapiSearchType.Yandere ||
|
||||||
type == DapiSearchType.E621 || type == DapiSearchType.Danbooru)
|
type == DapiSearchType.E621 || type == DapiSearchType.Danbooru)
|
||||||
{
|
{
|
||||||
var data = await _http.GetStringAsync(website).ConfigureAwait(false);
|
var data = await http.GetStringAsync(website).ConfigureAwait(false);
|
||||||
return JsonConvert.DeserializeObject<DapiImageObject[]>(data)
|
return JsonConvert.DeserializeObject<DapiImageObject[]>(data)
|
||||||
.Where(x => x.File_Url != null)
|
.Where(x => x.File_Url != null)
|
||||||
.Select(x => new ImageCacherObject(x, type))
|
.Select(x => new ImageCacherObject(x, type))
|
||||||
@ -139,11 +134,14 @@ namespace NadekoBot.Modules.Searches.Common
|
|||||||
|
|
||||||
return (await LoadXmlAsync(website, type)).ToArray();
|
return (await LoadXmlAsync(website, type)).ToArray();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<ImageCacherObject[]> LoadXmlAsync(string website, DapiSearchType type)
|
private async Task<ImageCacherObject[]> LoadXmlAsync(string website, DapiSearchType type)
|
||||||
{
|
{
|
||||||
var list = new List<ImageCacherObject>();
|
var list = new List<ImageCacherObject>(1000);
|
||||||
using (var reader = XmlReader.Create(await _http.GetStreamAsync(website), new XmlReaderSettings()
|
using (var http = new HttpClient())
|
||||||
|
{
|
||||||
|
using (var reader = XmlReader.Create(await http.GetStreamAsync(website), new XmlReaderSettings()
|
||||||
{
|
{
|
||||||
Async = true,
|
Async = true,
|
||||||
}))
|
}))
|
||||||
@ -163,12 +161,8 @@ namespace NadekoBot.Modules.Searches.Common
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list.ToArray();
|
|
||||||
}
|
}
|
||||||
|
return list.ToArray();
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
_cache.Clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,19 +1,22 @@
|
|||||||
using System;
|
using Discord.Commands;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Discord.Commands;
|
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Common
|
namespace NadekoBot.DataStructures
|
||||||
{
|
{
|
||||||
public class Shard0Precondition : PreconditionAttribute
|
public class Shard0Precondition : PreconditionAttribute
|
||||||
{
|
{
|
||||||
public override Task<PreconditionResult> CheckPermissions(ICommandContext context, CommandInfo command, IServiceProvider services)
|
public override Task<PreconditionResult> CheckPermissions(ICommandContext context, CommandInfo command, IServiceProvider services)
|
||||||
{
|
{
|
||||||
var c = (DiscordSocketClient)context.Client;
|
var c = (DiscordSocketClient)context.Client;
|
||||||
if (c.ShardId != 0)
|
if (c.ShardId == 0)
|
||||||
return Task.FromResult(PreconditionResult.FromError("Must be ran from shard #0"));
|
|
||||||
|
|
||||||
return Task.FromResult(PreconditionResult.FromSuccess());
|
return Task.FromResult(PreconditionResult.FromSuccess());
|
||||||
|
else
|
||||||
|
return Task.FromResult(PreconditionResult.FromError("Must be ran from shard #0"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,11 @@
|
|||||||
using System;
|
using Discord;
|
||||||
using Discord;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Common.ShardCom
|
namespace NadekoBot.DataStructures.ShardCom
|
||||||
{
|
{
|
||||||
public class ShardComMessage
|
public class ShardComMessage
|
||||||
{
|
{
|
@ -1,10 +1,11 @@
|
|||||||
using System.Net;
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace NadekoBot.Common.ShardCom
|
namespace NadekoBot.DataStructures.ShardCom
|
||||||
{
|
{
|
||||||
public class ShardComClient
|
public class ShardComClient
|
||||||
{
|
{
|
@ -1,11 +1,11 @@
|
|||||||
using System;
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace NadekoBot.Common.ShardCom
|
namespace NadekoBot.DataStructures.ShardCom
|
||||||
{
|
{
|
||||||
public class ShardComServer : IDisposable
|
public class ShardComServer : IDisposable
|
||||||
{
|
{
|
23
src/NadekoBot/DataStructures/SyncPrecondition.cs
Normal file
23
src/NadekoBot/DataStructures/SyncPrecondition.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using Discord.Commands;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.DataStructures
|
||||||
|
{
|
||||||
|
//public class SyncPrecondition : PreconditionAttribute
|
||||||
|
//{
|
||||||
|
// public override Task<PreconditionResult> CheckPermissions(ICommandContext context,
|
||||||
|
// CommandInfo command,
|
||||||
|
// IServiceProvider services)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//public enum SyncType
|
||||||
|
//{
|
||||||
|
// Guild
|
||||||
|
//}
|
||||||
|
}
|
@ -1,18 +1,25 @@
|
|||||||
using System;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Services;
|
||||||
|
using NadekoBot.Services.CustomReactions;
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord.Commands;
|
|
||||||
using NadekoBot.Modules.CustomReactions.Services;
|
|
||||||
using NadekoBot.Services;
|
|
||||||
|
|
||||||
namespace NadekoBot.Common.TypeReaders
|
namespace NadekoBot.TypeReaders
|
||||||
{
|
{
|
||||||
public class CommandTypeReader : TypeReader
|
public class CommandTypeReader : TypeReader
|
||||||
{
|
{
|
||||||
public override Task<TypeReaderResult> Read(ICommandContext context, string input, IServiceProvider services)
|
private readonly CommandService _cmds;
|
||||||
|
private readonly CommandHandler _cmdHandler;
|
||||||
|
|
||||||
|
public CommandTypeReader(CommandService cmds, CommandHandler cmdHandler)
|
||||||
|
{
|
||||||
|
_cmds = cmds;
|
||||||
|
_cmdHandler = cmdHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task<TypeReaderResult> Read(ICommandContext context, string input, IServiceProvider _)
|
||||||
{
|
{
|
||||||
var _cmds = ((INServiceProvider)services).GetService<CommandService>();
|
|
||||||
var _cmdHandler = ((INServiceProvider)services).GetService<CommandHandler>();
|
|
||||||
input = input.ToUpperInvariant();
|
input = input.ToUpperInvariant();
|
||||||
var prefix = _cmdHandler.GetPrefix(context.Guild);
|
var prefix = _cmdHandler.GetPrefix(context.Guild);
|
||||||
if (!input.StartsWith(prefix.ToUpperInvariant()))
|
if (!input.StartsWith(prefix.ToUpperInvariant()))
|
||||||
@ -31,12 +38,17 @@ namespace NadekoBot.Common.TypeReaders
|
|||||||
|
|
||||||
public class CommandOrCrTypeReader : CommandTypeReader
|
public class CommandOrCrTypeReader : CommandTypeReader
|
||||||
{
|
{
|
||||||
public override async Task<TypeReaderResult> Read(ICommandContext context, string input, IServiceProvider services)
|
private readonly CustomReactionsService _crs;
|
||||||
|
|
||||||
|
public CommandOrCrTypeReader(CustomReactionsService crs, CommandService cmds, CommandHandler cmdHandler) : base(cmds, cmdHandler)
|
||||||
|
{
|
||||||
|
_crs = crs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<TypeReaderResult> Read(ICommandContext context, string input, IServiceProvider _)
|
||||||
{
|
{
|
||||||
input = input.ToUpperInvariant();
|
input = input.ToUpperInvariant();
|
||||||
|
|
||||||
var _crs = ((INServiceProvider)services).GetService<CustomReactionsService>();
|
|
||||||
|
|
||||||
if (_crs.GlobalReactions.Any(x => x.Trigger.ToUpperInvariant() == input))
|
if (_crs.GlobalReactions.Any(x => x.Trigger.ToUpperInvariant() == input))
|
||||||
{
|
{
|
||||||
return TypeReaderResult.FromSuccess(new CommandOrCrInfo(input));
|
return TypeReaderResult.FromSuccess(new CommandOrCrInfo(input));
|
||||||
@ -53,7 +65,7 @@ namespace NadekoBot.Common.TypeReaders
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmd = await base.Read(context, input, services);
|
var cmd = await base.Read(context, input, _);
|
||||||
if (cmd.IsSuccess)
|
if (cmd.IsSuccess)
|
||||||
{
|
{
|
||||||
return TypeReaderResult.FromSuccess(new CommandOrCrInfo(((CommandInfo)cmd.Values.First().Value).Name));
|
return TypeReaderResult.FromSuccess(new CommandOrCrInfo(((CommandInfo)cmd.Values.First().Value).Name));
|
@ -1,15 +1,21 @@
|
|||||||
using System;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Services.Administration;
|
||||||
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord.Commands;
|
|
||||||
using NadekoBot.Modules.Administration.Services;
|
|
||||||
|
|
||||||
namespace NadekoBot.Common.TypeReaders
|
namespace NadekoBot.TypeReaders
|
||||||
{
|
{
|
||||||
public class GuildDateTimeTypeReader : TypeReader
|
public class GuildDateTimeTypeReader : TypeReader
|
||||||
{
|
{
|
||||||
public override Task<TypeReaderResult> Read(ICommandContext context, string input, IServiceProvider services)
|
private readonly GuildTimezoneService _gts;
|
||||||
|
|
||||||
|
public GuildDateTimeTypeReader(GuildTimezoneService gts)
|
||||||
|
{
|
||||||
|
_gts = gts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task<TypeReaderResult> Read(ICommandContext context, string input, IServiceProvider _)
|
||||||
{
|
{
|
||||||
var _gts = (GuildTimezoneService)services.GetService(typeof(GuildTimezoneService));
|
|
||||||
if (!DateTime.TryParse(input, out var dt))
|
if (!DateTime.TryParse(input, out var dt))
|
||||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Input string is in an incorrect format."));
|
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Input string is in an incorrect format."));
|
||||||
|
|
@ -1,10 +1,10 @@
|
|||||||
using System;
|
using Discord.Commands;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord.Commands;
|
|
||||||
using Discord.WebSocket;
|
|
||||||
|
|
||||||
namespace NadekoBot.Common.TypeReaders
|
namespace NadekoBot.TypeReaders
|
||||||
{
|
{
|
||||||
public class GuildTypeReader : TypeReader
|
public class GuildTypeReader : TypeReader
|
||||||
{
|
{
|
@ -1,10 +1,10 @@
|
|||||||
using System;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord.Commands;
|
|
||||||
using NadekoBot.Extensions;
|
|
||||||
|
|
||||||
namespace NadekoBot.Common.TypeReaders
|
namespace NadekoBot.TypeReaders
|
||||||
{
|
{
|
||||||
public class ModuleTypeReader : TypeReader
|
public class ModuleTypeReader : TypeReader
|
||||||
{
|
{
|
@ -1,9 +1,9 @@
|
|||||||
using System;
|
using Discord.Commands;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord.Commands;
|
using NadekoBot.Modules.Permissions;
|
||||||
using NadekoBot.Common.TypeReaders.Models;
|
using System;
|
||||||
|
|
||||||
namespace NadekoBot.Common.TypeReaders
|
namespace NadekoBot.TypeReaders
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used instead of bool for more flexible keywords for true/false only in the permission module
|
/// Used instead of bool for more flexible keywords for true/false only in the permission module
|
@ -1,4 +1,6 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
namespace NadekoBot.Migrations
|
namespace NadekoBot.Migrations
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
namespace NadekoBot.Migrations
|
namespace NadekoBot.Migrations
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
namespace NadekoBot.Migrations
|
namespace NadekoBot.Migrations
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
namespace NadekoBot.Migrations
|
namespace NadekoBot.Migrations
|
||||||
{
|
{
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,45 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations
|
|
||||||
{
|
|
||||||
public partial class streamrole : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "StreamRoleSettings",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<int>(nullable: false)
|
|
||||||
.Annotation("Sqlite:Autoincrement", true),
|
|
||||||
AddRoleId = table.Column<ulong>(nullable: false),
|
|
||||||
DateAdded = table.Column<DateTime>(nullable: true),
|
|
||||||
FromRoleId = table.Column<ulong>(nullable: false),
|
|
||||||
GuildConfigId = table.Column<int>(nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_StreamRoleSettings", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_StreamRoleSettings_GuildConfigs_GuildConfigId",
|
|
||||||
column: x => x.GuildConfigId,
|
|
||||||
principalTable: "GuildConfigs",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_StreamRoleSettings_GuildConfigId",
|
|
||||||
table: "StreamRoleSettings",
|
|
||||||
column: "GuildConfigId",
|
|
||||||
unique: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "StreamRoleSettings");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,93 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations
|
|
||||||
{
|
|
||||||
public partial class streamrolekwblwl : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<bool>(
|
|
||||||
name: "Enabled",
|
|
||||||
table: "StreamRoleSettings",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: false);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<string>(
|
|
||||||
name: "Keyword",
|
|
||||||
table: "StreamRoleSettings",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "StreamRoleBlacklistedUser",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<int>(nullable: false)
|
|
||||||
.Annotation("Sqlite:Autoincrement", true),
|
|
||||||
DateAdded = table.Column<DateTime>(nullable: true),
|
|
||||||
StreamRoleSettingsId = table.Column<int>(nullable: true),
|
|
||||||
UserId = table.Column<ulong>(nullable: false),
|
|
||||||
Username = table.Column<string>(nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_StreamRoleBlacklistedUser", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_StreamRoleBlacklistedUser_StreamRoleSettings_StreamRoleSettingsId",
|
|
||||||
column: x => x.StreamRoleSettingsId,
|
|
||||||
principalTable: "StreamRoleSettings",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Restrict);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "StreamRoleWhitelistedUser",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<int>(nullable: false)
|
|
||||||
.Annotation("Sqlite:Autoincrement", true),
|
|
||||||
DateAdded = table.Column<DateTime>(nullable: true),
|
|
||||||
StreamRoleSettingsId = table.Column<int>(nullable: true),
|
|
||||||
UserId = table.Column<ulong>(nullable: false),
|
|
||||||
Username = table.Column<string>(nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_StreamRoleWhitelistedUser", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_StreamRoleWhitelistedUser_StreamRoleSettings_StreamRoleSettingsId",
|
|
||||||
column: x => x.StreamRoleSettingsId,
|
|
||||||
principalTable: "StreamRoleSettings",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Restrict);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_StreamRoleBlacklistedUser_StreamRoleSettingsId",
|
|
||||||
table: "StreamRoleBlacklistedUser",
|
|
||||||
column: "StreamRoleSettingsId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_StreamRoleWhitelistedUser_StreamRoleSettingsId",
|
|
||||||
table: "StreamRoleWhitelistedUser",
|
|
||||||
column: "StreamRoleSettingsId");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "StreamRoleBlacklistedUser");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "StreamRoleWhitelistedUser");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "Enabled",
|
|
||||||
table: "StreamRoleSettings");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "Keyword",
|
|
||||||
table: "StreamRoleSettings");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,44 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations
|
|
||||||
{
|
|
||||||
public partial class nsfwblacklist : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "NsfwBlacklitedTag",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<int>(nullable: false)
|
|
||||||
.Annotation("Sqlite:Autoincrement", true),
|
|
||||||
DateAdded = table.Column<DateTime>(nullable: true),
|
|
||||||
GuildConfigId = table.Column<int>(nullable: true),
|
|
||||||
Tag = table.Column<string>(nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_NsfwBlacklitedTag", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_NsfwBlacklitedTag_GuildConfigs_GuildConfigId",
|
|
||||||
column: x => x.GuildConfigId,
|
|
||||||
principalTable: "GuildConfigs",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Restrict);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_NsfwBlacklitedTag_GuildConfigId",
|
|
||||||
table: "NsfwBlacklitedTag",
|
|
||||||
column: "GuildConfigId");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "NsfwBlacklitedTag");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
1682
src/NadekoBot/Migrations/20170722074959_cr-ca.Designer.cs
generated
1682
src/NadekoBot/Migrations/20170722074959_cr-ca.Designer.cs
generated
File diff suppressed because it is too large
Load Diff
@ -1,25 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations
|
|
||||||
{
|
|
||||||
public partial class crca : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<bool>(
|
|
||||||
name: "ContainsAnywhere",
|
|
||||||
table: "CustomReactions",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "ContainsAnywhere",
|
|
||||||
table: "CustomReactions");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,46 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations
|
|
||||||
{
|
|
||||||
public partial class waifuitems : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "WaifuItem",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<int>(nullable: false)
|
|
||||||
.Annotation("Sqlite:Autoincrement", true),
|
|
||||||
DateAdded = table.Column<DateTime>(nullable: true),
|
|
||||||
Item = table.Column<int>(nullable: false),
|
|
||||||
ItemEmoji = table.Column<string>(nullable: true),
|
|
||||||
Price = table.Column<int>(nullable: false),
|
|
||||||
WaifuInfoId = table.Column<int>(nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_WaifuItem", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_WaifuItem_WaifuInfo_WaifuInfoId",
|
|
||||||
column: x => x.WaifuInfoId,
|
|
||||||
principalTable: "WaifuInfo",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Restrict);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_WaifuItem_WaifuInfoId",
|
|
||||||
table: "WaifuItem",
|
|
||||||
column: "WaifuInfoId");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "WaifuItem");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,25 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations
|
|
||||||
{
|
|
||||||
public partial class mutetimeantispam : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<int>(
|
|
||||||
name: "MuteTime",
|
|
||||||
table: "AntiSpamSetting",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "MuteTime",
|
|
||||||
table: "AntiSpamSetting");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,296 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations
|
|
||||||
{
|
|
||||||
public partial class xpandclubs : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<int>(
|
|
||||||
name: "XpMinutesTimeout",
|
|
||||||
table: "BotConfig",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 5)
|
|
||||||
.Annotation("Sqlite:Autoincrement", true);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<int>(
|
|
||||||
name: "XpPerMessage",
|
|
||||||
table: "BotConfig",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 3)
|
|
||||||
.Annotation("Sqlite:Autoincrement", true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Clubs",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<int>(nullable: false)
|
|
||||||
.Annotation("Sqlite:Autoincrement", true),
|
|
||||||
DateAdded = table.Column<DateTime>(nullable: true),
|
|
||||||
Discrim = table.Column<int>(nullable: false),
|
|
||||||
ImageUrl = table.Column<string>(nullable: true),
|
|
||||||
MinimumLevelReq = table.Column<int>(nullable: false),
|
|
||||||
Name = table.Column<string>(maxLength: 20, nullable: false),
|
|
||||||
OwnerId = table.Column<int>(nullable: false),
|
|
||||||
Xp = table.Column<int>(nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Clubs", x => x.Id);
|
|
||||||
table.UniqueConstraint("AK_Clubs_Name_Discrim", x => new { x.Name, x.Discrim });
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_Clubs_DiscordUser_OwnerId",
|
|
||||||
column: x => x.OwnerId,
|
|
||||||
principalTable: "DiscordUser",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.Sql(MigrationQueries.UserClub);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<DateTime>(
|
|
||||||
name: "LastLevelUp",
|
|
||||||
table: "DiscordUser",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: DateTime.UtcNow);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<int>(
|
|
||||||
name: "NotifyOnLevelUp",
|
|
||||||
table: "DiscordUser",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 0);
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "UserXpStats",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<int>(nullable: false)
|
|
||||||
.Annotation("Sqlite:Autoincrement", true),
|
|
||||||
AwardedXp = table.Column<int>(nullable: false),
|
|
||||||
DateAdded = table.Column<DateTime>(nullable: true),
|
|
||||||
GuildId = table.Column<ulong>(nullable: false),
|
|
||||||
LastLevelUp = table.Column<DateTime>(nullable: false, defaultValue: new DateTime(2017, 9, 9, 1, 7, 29, 858, DateTimeKind.Local)),
|
|
||||||
NotifyOnLevelUp = table.Column<int>(nullable: false),
|
|
||||||
UserId = table.Column<ulong>(nullable: false),
|
|
||||||
Xp = table.Column<int>(nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_UserXpStats", x => x.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "XpSettings",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<int>(nullable: false)
|
|
||||||
.Annotation("Sqlite:Autoincrement", true),
|
|
||||||
DateAdded = table.Column<DateTime>(nullable: true),
|
|
||||||
GuildConfigId = table.Column<int>(nullable: false),
|
|
||||||
NotifyMessage = table.Column<string>(nullable: true),
|
|
||||||
ServerExcluded = table.Column<bool>(nullable: false),
|
|
||||||
XpRoleRewardExclusive = table.Column<bool>(nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_XpSettings", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_XpSettings_GuildConfigs_GuildConfigId",
|
|
||||||
column: x => x.GuildConfigId,
|
|
||||||
principalTable: "GuildConfigs",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "ClubApplicants",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
ClubId = table.Column<int>(nullable: false),
|
|
||||||
UserId = table.Column<int>(nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_ClubApplicants", x => new { x.ClubId, x.UserId });
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_ClubApplicants_Clubs_ClubId",
|
|
||||||
column: x => x.ClubId,
|
|
||||||
principalTable: "Clubs",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_ClubApplicants_DiscordUser_UserId",
|
|
||||||
column: x => x.UserId,
|
|
||||||
principalTable: "DiscordUser",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "ClubBans",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
ClubId = table.Column<int>(nullable: false),
|
|
||||||
UserId = table.Column<int>(nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_ClubBans", x => new { x.ClubId, x.UserId });
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_ClubBans_Clubs_ClubId",
|
|
||||||
column: x => x.ClubId,
|
|
||||||
principalTable: "Clubs",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_ClubBans_DiscordUser_UserId",
|
|
||||||
column: x => x.UserId,
|
|
||||||
principalTable: "DiscordUser",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "ExcludedItem",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<int>(nullable: false)
|
|
||||||
.Annotation("Sqlite:Autoincrement", true),
|
|
||||||
DateAdded = table.Column<DateTime>(nullable: true),
|
|
||||||
ItemId = table.Column<ulong>(nullable: false),
|
|
||||||
ItemType = table.Column<int>(nullable: false),
|
|
||||||
XpSettingsId = table.Column<int>(nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_ExcludedItem", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_ExcludedItem_XpSettings_XpSettingsId",
|
|
||||||
column: x => x.XpSettingsId,
|
|
||||||
principalTable: "XpSettings",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Restrict);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "XpRoleReward",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<int>(nullable: false)
|
|
||||||
.Annotation("Sqlite:Autoincrement", true),
|
|
||||||
DateAdded = table.Column<DateTime>(nullable: true),
|
|
||||||
Level = table.Column<int>(nullable: false),
|
|
||||||
RoleId = table.Column<ulong>(nullable: false),
|
|
||||||
XpSettingsId = table.Column<int>(nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_XpRoleReward", x => x.Id);
|
|
||||||
table.UniqueConstraint("AK_XpRoleReward_Level", x => x.Level);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_XpRoleReward_XpSettings_XpSettingsId",
|
|
||||||
column: x => x.XpSettingsId,
|
|
||||||
principalTable: "XpSettings",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Restrict);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_DiscordUser_ClubId",
|
|
||||||
table: "DiscordUser",
|
|
||||||
column: "ClubId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_ClubApplicants_UserId",
|
|
||||||
table: "ClubApplicants",
|
|
||||||
column: "UserId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_ClubBans_UserId",
|
|
||||||
table: "ClubBans",
|
|
||||||
column: "UserId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Clubs_OwnerId",
|
|
||||||
table: "Clubs",
|
|
||||||
column: "OwnerId",
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_ExcludedItem_XpSettingsId",
|
|
||||||
table: "ExcludedItem",
|
|
||||||
column: "XpSettingsId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_UserXpStats_UserId_GuildId",
|
|
||||||
table: "UserXpStats",
|
|
||||||
columns: new[] { "UserId", "GuildId" },
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_XpRoleReward_XpSettingsId",
|
|
||||||
table: "XpRoleReward",
|
|
||||||
column: "XpSettingsId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_XpSettings_GuildConfigId",
|
|
||||||
table: "XpSettings",
|
|
||||||
column: "GuildConfigId",
|
|
||||||
unique: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_DiscordUser_Clubs_ClubId",
|
|
||||||
table: "DiscordUser");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "ClubApplicants");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "ClubBans");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "ExcludedItem");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "UserXpStats");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "XpRoleReward");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Clubs");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "XpSettings");
|
|
||||||
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "IX_DiscordUser_ClubId",
|
|
||||||
table: "DiscordUser");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "ClubId",
|
|
||||||
table: "DiscordUser");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "LastLevelUp",
|
|
||||||
table: "DiscordUser");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "NotifyOnLevelUp",
|
|
||||||
table: "DiscordUser");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "XpMinutesTimeout",
|
|
||||||
table: "BotConfig");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "XpPerMessage",
|
|
||||||
table: "BotConfig");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,27 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations
|
|
||||||
{
|
|
||||||
public partial class lastXpGain : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<DateTime>(
|
|
||||||
name: "LastXpGain",
|
|
||||||
table: "DiscordUser",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
|
||||||
|
|
||||||
migrationBuilder.Sql("DELETE FROM XpRoleReward WHERE XpSettingsId is null");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "LastXpGain",
|
|
||||||
table: "DiscordUser");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
namespace NadekoBot.Migrations
|
|
||||||
{
|
|
||||||
internal class MigrationQueries
|
|
||||||
{
|
|
||||||
public static string UserClub { get; } = @"
|
|
||||||
CREATE TABLE DiscordUser_tmp(
|
|
||||||
Id INTEGER PRIMARY KEY,
|
|
||||||
AvatarId TEXT,
|
|
||||||
Discriminator TEXT,
|
|
||||||
UserId INTEGER UNIQUE NOT NULL,
|
|
||||||
DateAdded TEXT,
|
|
||||||
Username TEXT
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO DiscordUser_tmp
|
|
||||||
SELECT Id, AvatarId, Discriminator, UserId, DateAdded, Username
|
|
||||||
FROM DiscordUser;
|
|
||||||
|
|
||||||
DROP TABLE DiscordUser;
|
|
||||||
|
|
||||||
CREATE TABLE DiscordUser(
|
|
||||||
Id INTEGER PRIMARY KEY,
|
|
||||||
AvatarId TEXT,
|
|
||||||
Discriminator TEXT,
|
|
||||||
UserId INTEGER UNIQUE NOT NULL,
|
|
||||||
DateAdded TEXT,
|
|
||||||
Username TEXT,
|
|
||||||
ClubId INTEGER,
|
|
||||||
CONSTRAINT FK_DiscordUser_Clubs_ClubId FOREIGN KEY(ClubId) REFERENCES Clubs(Id) ON DELETE RESTRICT
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO DiscordUser
|
|
||||||
SELECT Id, AvatarId, Discriminator, UserId, DateAdded, Username, NULL
|
|
||||||
FROM DiscordUser_tmp;
|
|
||||||
|
|
||||||
DROP TABLE DiscordUser_tmp;";
|
|
||||||
}
|
|
||||||
}
|
|
@ -70,8 +70,6 @@ namespace NadekoBot.Migrations
|
|||||||
|
|
||||||
b.Property<int>("MessageThreshold");
|
b.Property<int>("MessageThreshold");
|
||||||
|
|
||||||
b.Property<int>("MuteTime");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("GuildConfigId")
|
b.HasIndex("GuildConfigId")
|
||||||
@ -183,14 +181,6 @@ namespace NadekoBot.Migrations
|
|||||||
|
|
||||||
b.Property<int>("TriviaCurrencyReward");
|
b.Property<int>("TriviaCurrencyReward");
|
||||||
|
|
||||||
b.Property<int>("XpMinutesTimeout")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasDefaultValue(5);
|
|
||||||
|
|
||||||
b.Property<int>("XpPerMessage")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasDefaultValue(3);
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.ToTable("BotConfig");
|
b.ToTable("BotConfig");
|
||||||
@ -246,63 +236,6 @@ namespace NadekoBot.Migrations
|
|||||||
b.ToTable("ClashOfClans");
|
b.ToTable("ClashOfClans");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubApplicants", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("ClubId");
|
|
||||||
|
|
||||||
b.Property<int>("UserId");
|
|
||||||
|
|
||||||
b.HasKey("ClubId", "UserId");
|
|
||||||
|
|
||||||
b.HasIndex("UserId");
|
|
||||||
|
|
||||||
b.ToTable("ClubApplicants");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubBans", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("ClubId");
|
|
||||||
|
|
||||||
b.Property<int>("UserId");
|
|
||||||
|
|
||||||
b.HasKey("ClubId", "UserId");
|
|
||||||
|
|
||||||
b.HasIndex("UserId");
|
|
||||||
|
|
||||||
b.ToTable("ClubBans");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubInfo", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd();
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DateAdded");
|
|
||||||
|
|
||||||
b.Property<int>("Discrim");
|
|
||||||
|
|
||||||
b.Property<string>("ImageUrl");
|
|
||||||
|
|
||||||
b.Property<int>("MinimumLevelReq");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20);
|
|
||||||
|
|
||||||
b.Property<int>("OwnerId");
|
|
||||||
|
|
||||||
b.Property<int>("Xp");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasAlternateKey("Name", "Discrim");
|
|
||||||
|
|
||||||
b.HasIndex("OwnerId")
|
|
||||||
.IsUnique();
|
|
||||||
|
|
||||||
b.ToTable("Clubs");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@ -428,8 +361,6 @@ namespace NadekoBot.Migrations
|
|||||||
|
|
||||||
b.Property<bool>("AutoDeleteTrigger");
|
b.Property<bool>("AutoDeleteTrigger");
|
||||||
|
|
||||||
b.Property<bool>("ContainsAnywhere");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DateAdded");
|
b.Property<DateTime?>("DateAdded");
|
||||||
|
|
||||||
b.Property<bool>("DmResponse");
|
b.Property<bool>("DmResponse");
|
||||||
@ -456,20 +387,10 @@ namespace NadekoBot.Migrations
|
|||||||
|
|
||||||
b.Property<string>("AvatarId");
|
b.Property<string>("AvatarId");
|
||||||
|
|
||||||
b.Property<int?>("ClubId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DateAdded");
|
b.Property<DateTime?>("DateAdded");
|
||||||
|
|
||||||
b.Property<string>("Discriminator");
|
b.Property<string>("Discriminator");
|
||||||
|
|
||||||
b.Property<DateTime>("LastLevelUp")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasDefaultValue(new DateTime(2017, 9, 11, 22, 0, 31, 236, DateTimeKind.Local));
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastXpGain");
|
|
||||||
|
|
||||||
b.Property<int>("NotifyOnLevelUp");
|
|
||||||
|
|
||||||
b.Property<ulong>("UserId");
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
b.Property<string>("Username");
|
b.Property<string>("Username");
|
||||||
@ -478,8 +399,6 @@ namespace NadekoBot.Migrations
|
|||||||
|
|
||||||
b.HasAlternateKey("UserId");
|
b.HasAlternateKey("UserId");
|
||||||
|
|
||||||
b.HasIndex("ClubId");
|
|
||||||
|
|
||||||
b.ToTable("DiscordUser");
|
b.ToTable("DiscordUser");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -522,26 +441,6 @@ namespace NadekoBot.Migrations
|
|||||||
b.ToTable("EightBallResponses");
|
b.ToTable("EightBallResponses");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd();
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DateAdded");
|
|
||||||
|
|
||||||
b.Property<ulong>("ItemId");
|
|
||||||
|
|
||||||
b.Property<int>("ItemType");
|
|
||||||
|
|
||||||
b.Property<int?>("XpSettingsId");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("XpSettingsId");
|
|
||||||
|
|
||||||
b.ToTable("ExcludedItem");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@ -901,24 +800,6 @@ namespace NadekoBot.Migrations
|
|||||||
b.ToTable("MutedUserId");
|
b.ToTable("MutedUserId");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.NsfwBlacklitedTag", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd();
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DateAdded");
|
|
||||||
|
|
||||||
b.Property<int?>("GuildConfigId");
|
|
||||||
|
|
||||||
b.Property<string>("Tag");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("GuildConfigId");
|
|
||||||
|
|
||||||
b.ToTable("NsfwBlacklitedTag");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@ -1245,71 +1126,6 @@ namespace NadekoBot.Migrations
|
|||||||
b.ToTable("StartupCommand");
|
b.ToTable("StartupCommand");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd();
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DateAdded");
|
|
||||||
|
|
||||||
b.Property<int?>("StreamRoleSettingsId");
|
|
||||||
|
|
||||||
b.Property<ulong>("UserId");
|
|
||||||
|
|
||||||
b.Property<string>("Username");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("StreamRoleSettingsId");
|
|
||||||
|
|
||||||
b.ToTable("StreamRoleBlacklistedUser");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd();
|
|
||||||
|
|
||||||
b.Property<ulong>("AddRoleId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DateAdded");
|
|
||||||
|
|
||||||
b.Property<bool>("Enabled");
|
|
||||||
|
|
||||||
b.Property<ulong>("FromRoleId");
|
|
||||||
|
|
||||||
b.Property<int>("GuildConfigId");
|
|
||||||
|
|
||||||
b.Property<string>("Keyword");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("GuildConfigId")
|
|
||||||
.IsUnique();
|
|
||||||
|
|
||||||
b.ToTable("StreamRoleSettings");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd();
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DateAdded");
|
|
||||||
|
|
||||||
b.Property<int?>("StreamRoleSettingsId");
|
|
||||||
|
|
||||||
b.Property<ulong>("UserId");
|
|
||||||
|
|
||||||
b.Property<string>("Username");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("StreamRoleSettingsId");
|
|
||||||
|
|
||||||
b.ToTable("StreamRoleWhitelistedUser");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@ -1349,35 +1165,6 @@ namespace NadekoBot.Migrations
|
|||||||
b.ToTable("PokeGame");
|
b.ToTable("PokeGame");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.UserXpStats", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd();
|
|
||||||
|
|
||||||
b.Property<int>("AwardedXp");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DateAdded");
|
|
||||||
|
|
||||||
b.Property<ulong>("GuildId");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastLevelUp")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasDefaultValue(new DateTime(2017, 9, 11, 22, 0, 31, 238, DateTimeKind.Local));
|
|
||||||
|
|
||||||
b.Property<int>("NotifyOnLevelUp");
|
|
||||||
|
|
||||||
b.Property<ulong>("UserId");
|
|
||||||
|
|
||||||
b.Property<int>("Xp");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("UserId", "GuildId")
|
|
||||||
.IsUnique();
|
|
||||||
|
|
||||||
b.ToTable("UserXpStats");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@ -1425,28 +1212,6 @@ namespace NadekoBot.Migrations
|
|||||||
b.ToTable("WaifuInfo");
|
b.ToTable("WaifuInfo");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd();
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DateAdded");
|
|
||||||
|
|
||||||
b.Property<int>("Item");
|
|
||||||
|
|
||||||
b.Property<string>("ItemEmoji");
|
|
||||||
|
|
||||||
b.Property<int>("Price");
|
|
||||||
|
|
||||||
b.Property<int?>("WaifuInfoId");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("WaifuInfoId");
|
|
||||||
|
|
||||||
b.ToTable("WaifuItem");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@ -1519,51 +1284,6 @@ namespace NadekoBot.Migrations
|
|||||||
b.ToTable("WarningPunishment");
|
b.ToTable("WarningPunishment");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd();
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DateAdded");
|
|
||||||
|
|
||||||
b.Property<int>("Level");
|
|
||||||
|
|
||||||
b.Property<ulong>("RoleId");
|
|
||||||
|
|
||||||
b.Property<int?>("XpSettingsId");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasAlternateKey("Level");
|
|
||||||
|
|
||||||
b.HasIndex("XpSettingsId");
|
|
||||||
|
|
||||||
b.ToTable("XpRoleReward");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd();
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DateAdded");
|
|
||||||
|
|
||||||
b.Property<int>("GuildConfigId");
|
|
||||||
|
|
||||||
b.Property<string>("NotifyMessage");
|
|
||||||
|
|
||||||
b.Property<bool>("ServerExcluded");
|
|
||||||
|
|
||||||
b.Property<bool>("XpRoleRewardExclusive");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("GuildConfigId")
|
|
||||||
.IsUnique();
|
|
||||||
|
|
||||||
b.ToTable("XpSettings");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig")
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig")
|
||||||
@ -1613,40 +1333,6 @@ namespace NadekoBot.Migrations
|
|||||||
.OnDelete(DeleteBehavior.Cascade);
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubApplicants", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.ClubInfo", "Club")
|
|
||||||
.WithMany("Applicants")
|
|
||||||
.HasForeignKey("ClubId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
|
||||||
|
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "User")
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("UserId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubBans", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.ClubInfo", "Club")
|
|
||||||
.WithMany("Bans")
|
|
||||||
.HasForeignKey("ClubId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
|
||||||
|
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "User")
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("UserId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubInfo", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "Owner")
|
|
||||||
.WithOne()
|
|
||||||
.HasForeignKey("NadekoBot.Services.Database.Models.ClubInfo", "OwnerId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
@ -1668,13 +1354,6 @@ namespace NadekoBot.Migrations
|
|||||||
.HasForeignKey("BotConfigId");
|
.HasForeignKey("BotConfigId");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.DiscordUser", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.ClubInfo", "Club")
|
|
||||||
.WithMany("Users")
|
|
||||||
.HasForeignKey("ClubId");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
|
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
|
||||||
@ -1682,13 +1361,6 @@ namespace NadekoBot.Migrations
|
|||||||
.HasForeignKey("BotConfigId");
|
.HasForeignKey("BotConfigId");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.XpSettings")
|
|
||||||
.WithMany("ExclusionList")
|
|
||||||
.HasForeignKey("XpSettingsId");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
@ -1767,13 +1439,6 @@ namespace NadekoBot.Migrations
|
|||||||
.HasForeignKey("GuildConfigId");
|
.HasForeignKey("GuildConfigId");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.NsfwBlacklitedTag", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
|
||||||
.WithMany("NsfwBlacklistedTags")
|
|
||||||
.HasForeignKey("GuildConfigId");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.Permission", "Next")
|
b.HasOne("NadekoBot.Services.Database.Models.Permission", "Next")
|
||||||
@ -1845,28 +1510,6 @@ namespace NadekoBot.Migrations
|
|||||||
.HasForeignKey("BotConfigId");
|
.HasForeignKey("BotConfigId");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings")
|
|
||||||
.WithMany("Blacklist")
|
|
||||||
.HasForeignKey("StreamRoleSettingsId");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig")
|
|
||||||
.WithOne("StreamRole")
|
|
||||||
.HasForeignKey("NadekoBot.Services.Database.Models.StreamRoleSettings", "GuildConfigId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings")
|
|
||||||
.WithMany("Whitelist")
|
|
||||||
.HasForeignKey("StreamRoleSettingsId");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
@ -1897,13 +1540,6 @@ namespace NadekoBot.Migrations
|
|||||||
.OnDelete(DeleteBehavior.Cascade);
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.WaifuInfo")
|
|
||||||
.WithMany("Items")
|
|
||||||
.HasForeignKey("WaifuInfoId");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "New")
|
b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "New")
|
||||||
@ -1926,21 +1562,6 @@ namespace NadekoBot.Migrations
|
|||||||
.WithMany("WarnPunishments")
|
.WithMany("WarnPunishments")
|
||||||
.HasForeignKey("GuildConfigId");
|
.HasForeignKey("GuildConfigId");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.XpSettings")
|
|
||||||
.WithMany("RoleRewards")
|
|
||||||
.HasForeignKey("XpSettingsId");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig")
|
|
||||||
.WithOne("XpSettings")
|
|
||||||
.HasForeignKey("NadekoBot.Services.Database.Models.XpSettings", "GuildConfigId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,21 +5,23 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Modules.Administration.Services;
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using NadekoBot.Services.Administration;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
||||||
public partial class Administration : NadekoTopLevelModule<AdministrationService>
|
public partial class Administration : NadekoTopLevelModule
|
||||||
{
|
{
|
||||||
private IGuild _nadekoSupportServer;
|
private IGuild _nadekoSupportServer;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
private readonly AdministrationService _admin;
|
||||||
|
|
||||||
public Administration(DbService db)
|
public Administration(DbService db, AdministrationService admin)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
|
_admin = admin;
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -38,12 +40,12 @@ namespace NadekoBot.Modules.Administration
|
|||||||
}
|
}
|
||||||
if (enabled)
|
if (enabled)
|
||||||
{
|
{
|
||||||
_service.DeleteMessagesOnCommand.Add(Context.Guild.Id);
|
_admin.DeleteMessagesOnCommand.Add(Context.Guild.Id);
|
||||||
await ReplyConfirmLocalized("delmsg_on").ConfigureAwait(false);
|
await ReplyConfirmLocalized("delmsg_on").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_service.DeleteMessagesOnCommand.TryRemove(Context.Guild.Id);
|
_admin.DeleteMessagesOnCommand.TryRemove(Context.Guild.Id);
|
||||||
await ReplyConfirmLocalized("delmsg_off").ConfigureAwait(false);
|
await ReplyConfirmLocalized("delmsg_off").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,7 +58,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
var guser = (IGuildUser)Context.User;
|
var guser = (IGuildUser)Context.User;
|
||||||
var maxRole = guser.GetRoles().Max(x => x.Position);
|
var maxRole = guser.GetRoles().Max(x => x.Position);
|
||||||
if ((Context.User.Id != Context.Guild.OwnerId) && (maxRole <= role.Position || maxRole <= usr.GetRoles().Max(x => x.Position)))
|
if ((Context.User.Id != Context.Guild.OwnerId) && (maxRole < role.Position || maxRole <= usr.GetRoles().Max(x => x.Position)))
|
||||||
return;
|
return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -1,24 +1,26 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
|
using NadekoBot.Services.Administration;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
using NadekoBot.Modules.Administration.Services;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
||||||
public partial class Administration
|
public partial class Administration
|
||||||
{
|
{
|
||||||
[Group]
|
[Group]
|
||||||
public class AutoAssignRoleCommands : NadekoSubmodule<AutoAssignRoleService>
|
public class AutoAssignRoleCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
private readonly AutoAssignRoleService _service;
|
||||||
|
|
||||||
public AutoAssignRoleCommands(DbService db)
|
public AutoAssignRoleCommands(AutoAssignRoleService service, DbService db)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
|
_service = service;
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -37,7 +39,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
if (role == null)
|
if (role == null)
|
||||||
{
|
{
|
||||||
conf.AutoAssignRoleId = 0;
|
conf.AutoAssignRoleId = 0;
|
||||||
_service.AutoAssignedRoles.TryRemove(Context.Guild.Id, out _);
|
_service.AutoAssignedRoles.TryRemove(Context.Guild.Id, out ulong throwaway);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
@ -1,22 +1,24 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Common.Attributes;
|
using NadekoBot.Services.Administration;
|
||||||
using NadekoBot.Modules.Administration.Services;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
||||||
public partial class Administration
|
public partial class Administration
|
||||||
{
|
{
|
||||||
[Group]
|
[Group]
|
||||||
public class GameChannelCommands : NadekoSubmodule<GameVoiceChannelService>
|
public class GameChannelCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
private readonly GameVoiceChannelService _service;
|
||||||
|
|
||||||
public GameChannelCommands(DbService db)
|
public GameChannelCommands(GameVoiceChannelService service, DbService db)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
|
_service = service;
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
@ -1,5 +1,6 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -7,7 +8,6 @@ using System.Collections.Immutable;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
@ -1,16 +1,16 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.DataStructures;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Modules.Permissions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
|
using NadekoBot.Services.Administration;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Common;
|
using static NadekoBot.Services.Administration.LogCommandService;
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
using NadekoBot.Common.TypeReaders.Models;
|
|
||||||
using NadekoBot.Modules.Administration.Services;
|
|
||||||
using static NadekoBot.Modules.Administration.Services.LogCommandService;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
||||||
@ -18,12 +18,14 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
[Group]
|
[Group]
|
||||||
[NoPublicBot]
|
[NoPublicBot]
|
||||||
public class LogCommands : NadekoSubmodule<LogCommandService>
|
public class LogCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
|
private readonly LogCommandService _lc;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public LogCommands(DbService db)
|
public LogCommands(LogCommandService lc, DbService db)
|
||||||
{
|
{
|
||||||
|
_lc = lc;
|
||||||
_db = db;
|
_db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +46,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
logSetting = uow.GuildConfigs.LogSettingsFor(channel.Guild.Id).LogSetting;
|
logSetting = uow.GuildConfigs.LogSettingsFor(channel.Guild.Id).LogSetting;
|
||||||
_service.GuildLogSettings.AddOrUpdate(channel.Guild.Id, (id) => logSetting, (id, old) => logSetting);
|
_lc.GuildLogSettings.AddOrUpdate(channel.Guild.Id, (id) => logSetting, (id, old) => logSetting);
|
||||||
logSetting.LogOtherId =
|
logSetting.LogOtherId =
|
||||||
logSetting.MessageUpdatedId =
|
logSetting.MessageUpdatedId =
|
||||||
logSetting.MessageDeletedId =
|
logSetting.MessageDeletedId =
|
||||||
@ -80,7 +82,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
var config = uow.GuildConfigs.LogSettingsFor(channel.Guild.Id);
|
var config = uow.GuildConfigs.LogSettingsFor(channel.Guild.Id);
|
||||||
LogSetting logSetting = _service.GuildLogSettings.GetOrAdd(channel.Guild.Id, (id) => config.LogSetting);
|
LogSetting logSetting = _lc.GuildLogSettings.GetOrAdd(channel.Guild.Id, (id) => config.LogSetting);
|
||||||
removed = logSetting.IgnoredChannels.RemoveWhere(ilc => ilc.ChannelId == channel.Id);
|
removed = logSetting.IgnoredChannels.RemoveWhere(ilc => ilc.ChannelId == channel.Id);
|
||||||
config.LogSetting.IgnoredChannels.RemoveWhere(ilc => ilc.ChannelId == channel.Id);
|
config.LogSetting.IgnoredChannels.RemoveWhere(ilc => ilc.ChannelId == channel.Id);
|
||||||
if (removed == 0)
|
if (removed == 0)
|
||||||
@ -104,8 +106,8 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task LogEvents()
|
public async Task LogEvents()
|
||||||
{
|
{
|
||||||
await Context.Channel.SendConfirmAsync(Format.Bold(GetText("log_events")) + "\n" +
|
await Context.Channel.SendConfirmAsync(GetText("log_events") + "\n" +
|
||||||
$"```fix\n{string.Join(", ", Enum.GetNames(typeof(LogType)).Cast<string>())}```")
|
string.Join(", ", Enum.GetNames(typeof(LogType)).Cast<string>()))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +122,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
var logSetting = uow.GuildConfigs.LogSettingsFor(channel.Guild.Id).LogSetting;
|
var logSetting = uow.GuildConfigs.LogSettingsFor(channel.Guild.Id).LogSetting;
|
||||||
_service.GuildLogSettings.AddOrUpdate(channel.Guild.Id, (id) => logSetting, (id, old) => logSetting);
|
_lc.GuildLogSettings.AddOrUpdate(channel.Guild.Id, (id) => logSetting, (id, old) => logSetting);
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case LogType.Other:
|
case LogType.Other:
|
@ -4,28 +4,27 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using NadekoBot.Modules.Administration.Commands.Migration;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services.Database;
|
using NadekoBot.Services.Database;
|
||||||
using Microsoft.Data.Sqlite;
|
using Microsoft.Data.Sqlite;
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
using NadekoBot.Common.Collections;
|
|
||||||
using NadekoBot.Modules.Administration.Common.Migration;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
||||||
public partial class Administration
|
public partial class Administration
|
||||||
{
|
{
|
||||||
[Group]
|
[Group]
|
||||||
public class MigrationCommands : NadekoSubmodule
|
public class Migration : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private const int CURRENT_VERSION = 1;
|
private const int CURRENT_VERSION = 1;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public MigrationCommands(DbService db)
|
public Migration(DbService db)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
}
|
}
|
||||||
@ -212,10 +211,10 @@ namespace NadekoBot.Modules.Administration
|
|||||||
type = FollowedStream.FollowedStreamType.Twitch;
|
type = FollowedStream.FollowedStreamType.Twitch;
|
||||||
break;
|
break;
|
||||||
case StreamNotificationConfig0_9.StreamType.Beam:
|
case StreamNotificationConfig0_9.StreamType.Beam:
|
||||||
type = FollowedStream.FollowedStreamType.Mixer;
|
type = FollowedStream.FollowedStreamType.Beam;
|
||||||
break;
|
break;
|
||||||
case StreamNotificationConfig0_9.StreamType.Hitbox:
|
case StreamNotificationConfig0_9.StreamType.Hitbox:
|
||||||
type = FollowedStream.FollowedStreamType.Smashcast;
|
type = FollowedStream.FollowedStreamType.Hitbox;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -352,6 +351,54 @@ namespace NadekoBot.Modules.Administration
|
|||||||
oldConfig.RotatingStatuses.ForEach(i => messages.Add(new PlayingStatus { Status = i }));
|
oldConfig.RotatingStatuses.ForEach(i => messages.Add(new PlayingStatus { Status = i }));
|
||||||
botConfig.RotatingStatusMessages = messages;
|
botConfig.RotatingStatusMessages = messages;
|
||||||
|
|
||||||
|
//Prefix
|
||||||
|
botConfig.ModulePrefixes.Clear();
|
||||||
|
botConfig.ModulePrefixes.AddRange(new HashSet<ModulePrefix>
|
||||||
|
{
|
||||||
|
new ModulePrefix()
|
||||||
|
{
|
||||||
|
ModuleName = "Administration",
|
||||||
|
Prefix = oldConfig.CommandPrefixes.Administration
|
||||||
|
},
|
||||||
|
new ModulePrefix()
|
||||||
|
{
|
||||||
|
ModuleName = "Searches",
|
||||||
|
Prefix = oldConfig.CommandPrefixes.Searches
|
||||||
|
},
|
||||||
|
new ModulePrefix() {ModuleName = "NSFW", Prefix = oldConfig.CommandPrefixes.NSFW},
|
||||||
|
new ModulePrefix()
|
||||||
|
{
|
||||||
|
ModuleName = "Conversations",
|
||||||
|
Prefix = oldConfig.CommandPrefixes.Conversations
|
||||||
|
},
|
||||||
|
new ModulePrefix()
|
||||||
|
{
|
||||||
|
ModuleName = "ClashOfClans",
|
||||||
|
Prefix = oldConfig.CommandPrefixes.ClashOfClans
|
||||||
|
},
|
||||||
|
new ModulePrefix() {ModuleName = "Help", Prefix = oldConfig.CommandPrefixes.Help},
|
||||||
|
new ModulePrefix() {ModuleName = "Music", Prefix = oldConfig.CommandPrefixes.Music},
|
||||||
|
new ModulePrefix() {ModuleName = "Trello", Prefix = oldConfig.CommandPrefixes.Trello},
|
||||||
|
new ModulePrefix() {ModuleName = "Games", Prefix = oldConfig.CommandPrefixes.Games},
|
||||||
|
new ModulePrefix()
|
||||||
|
{
|
||||||
|
ModuleName = "Gambling",
|
||||||
|
Prefix = oldConfig.CommandPrefixes.Gambling
|
||||||
|
},
|
||||||
|
new ModulePrefix()
|
||||||
|
{
|
||||||
|
ModuleName = "Permissions",
|
||||||
|
Prefix = oldConfig.CommandPrefixes.Permissions
|
||||||
|
},
|
||||||
|
new ModulePrefix()
|
||||||
|
{
|
||||||
|
ModuleName = "Programming",
|
||||||
|
Prefix = oldConfig.CommandPrefixes.Programming
|
||||||
|
},
|
||||||
|
new ModulePrefix() {ModuleName = "Pokemon", Prefix = oldConfig.CommandPrefixes.Pokemon},
|
||||||
|
new ModulePrefix() {ModuleName = "Utility", Prefix = oldConfig.CommandPrefixes.Utility}
|
||||||
|
});
|
||||||
|
|
||||||
//Blacklist
|
//Blacklist
|
||||||
var blacklist = new HashSet<BlacklistItem>(oldConfig.ServerBlacklist.Select(server => new BlacklistItem() { ItemId = server, Type = BlacklistType.Server }));
|
var blacklist = new HashSet<BlacklistItem>(oldConfig.ServerBlacklist.Select(server => new BlacklistItem() { ItemId = server, Type = BlacklistType.Server }));
|
||||||
blacklist.AddRange(oldConfig.ChannelBlacklist.Select(channel => new BlacklistItem() { ItemId = channel, Type = BlacklistType.Channel }));
|
blacklist.AddRange(oldConfig.ChannelBlacklist.Select(channel => new BlacklistItem() { ItemId = channel, Type = BlacklistType.Channel }));
|
@ -2,7 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration.Common.Migration
|
namespace NadekoBot.Modules.Administration.Commands.Migration
|
||||||
{
|
{
|
||||||
public class CommandPrefixes0_9
|
public class CommandPrefixes0_9
|
||||||
{
|
{
|
@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration.Common.Migration
|
namespace NadekoBot.Modules.Administration.Commands.Migration
|
||||||
{
|
{
|
||||||
public class MigrationException : Exception
|
public class MigrationException : Exception
|
||||||
{
|
{
|
@ -1,29 +1,31 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
|
using NadekoBot.Services.Administration;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
using NadekoBot.Modules.Administration.Services;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
||||||
public partial class Administration
|
public partial class Administration
|
||||||
{
|
{
|
||||||
[Group]
|
[Group]
|
||||||
public class MuteCommands : NadekoSubmodule<MuteService>
|
public class MuteCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
|
private readonly MuteService _service;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public MuteCommands(DbService db)
|
public MuteCommands(MuteService service, DbService db)
|
||||||
{
|
{
|
||||||
|
_service = service;
|
||||||
_db = db;
|
_db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[RequireUserPermission(GuildPermission.ManageRoles)]
|
[RequireUserPermission(GuildPermission.ManageRoles)]
|
||||||
[Priority(0)]
|
[Priority(1)]
|
||||||
public async Task SetMuteRole([Remainder] string name)
|
public async Task SetMuteRole([Remainder] string name)
|
||||||
{
|
{
|
||||||
name = name.Trim();
|
name = name.Trim();
|
||||||
@ -43,7 +45,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[RequireUserPermission(GuildPermission.ManageRoles)]
|
[RequireUserPermission(GuildPermission.ManageRoles)]
|
||||||
[Priority(1)]
|
[Priority(0)]
|
||||||
public Task SetMuteRole([Remainder] IRole role)
|
public Task SetMuteRole([Remainder] IRole role)
|
||||||
=> SetMuteRole(role.Name);
|
=> SetMuteRole(role.Name);
|
||||||
|
|
||||||
@ -51,7 +53,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[RequireUserPermission(GuildPermission.ManageRoles)]
|
[RequireUserPermission(GuildPermission.ManageRoles)]
|
||||||
[RequireUserPermission(GuildPermission.MuteMembers)]
|
[RequireUserPermission(GuildPermission.MuteMembers)]
|
||||||
[Priority(0)]
|
[Priority(1)]
|
||||||
public async Task Mute(IGuildUser user)
|
public async Task Mute(IGuildUser user)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -69,7 +71,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[RequireUserPermission(GuildPermission.ManageRoles)]
|
[RequireUserPermission(GuildPermission.ManageRoles)]
|
||||||
[RequireUserPermission(GuildPermission.MuteMembers)]
|
[RequireUserPermission(GuildPermission.MuteMembers)]
|
||||||
[Priority(1)]
|
[Priority(0)]
|
||||||
public async Task Mute(int minutes, IGuildUser user)
|
public async Task Mute(int minutes, IGuildUser user)
|
||||||
{
|
{
|
||||||
if (minutes < 1 || minutes > 1440)
|
if (minutes < 1 || minutes > 1440)
|
@ -1,24 +1,26 @@
|
|||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
|
using NadekoBot.Services.Administration;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
using NadekoBot.Modules.Administration.Services;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
||||||
public partial class Administration
|
public partial class Administration
|
||||||
{
|
{
|
||||||
[Group]
|
[Group]
|
||||||
public class PlayingRotateCommands : NadekoSubmodule<PlayingRotateService>
|
public class PlayingRotateCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private static readonly object _locker = new object();
|
private static readonly object _locker = new object();
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
private readonly PlayingRotateService _service;
|
||||||
|
|
||||||
public PlayingRotateCommands(DbService db)
|
public PlayingRotateCommands(PlayingRotateService service, DbService db)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
|
_service = service;
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
@ -1,7 +1,7 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
||||||
@ -11,7 +11,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
public class PrefixCommands : NadekoSubmodule
|
public class PrefixCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[Priority(1)]
|
[Priority(0)]
|
||||||
public new async Task Prefix()
|
public new async Task Prefix()
|
||||||
{
|
{
|
||||||
await ReplyConfirmLocalized("prefix_current", Format.Code(_cmdHandler.GetPrefix(Context.Guild))).ConfigureAwait(false);
|
await ReplyConfirmLocalized("prefix_current", Format.Code(_cmdHandler.GetPrefix(Context.Guild))).ConfigureAwait(false);
|
||||||
@ -21,7 +21,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[RequireUserPermission(GuildPermission.Administrator)]
|
[RequireUserPermission(GuildPermission.Administrator)]
|
||||||
[Priority(0)]
|
[Priority(1)]
|
||||||
public new async Task Prefix([Remainder]string prefix)
|
public new async Task Prefix([Remainder]string prefix)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(prefix))
|
if (string.IsNullOrWhiteSpace(prefix))
|
@ -1,50 +1,42 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Common.Attributes;
|
using NadekoBot.Services.Administration;
|
||||||
using NadekoBot.Modules.Administration.Common;
|
|
||||||
using NadekoBot.Modules.Administration.Services;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
||||||
public partial class Administration
|
public partial class Administration
|
||||||
{
|
{
|
||||||
[Group]
|
[Group]
|
||||||
public class ProtectionCommands : NadekoSubmodule<ProtectionService>
|
public class ProtectionCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
|
private readonly ProtectionService _service;
|
||||||
private readonly MuteService _mute;
|
private readonly MuteService _mute;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public ProtectionCommands(MuteService mute, DbService db)
|
public ProtectionCommands(ProtectionService service, MuteService mute, DbService db)
|
||||||
{
|
{
|
||||||
|
_service = service;
|
||||||
_mute = mute;
|
_mute = mute;
|
||||||
_db = db;
|
_db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetAntiSpamString(AntiSpamStats stats)
|
private string GetAntiSpamString(AntiSpamStats stats)
|
||||||
{
|
{
|
||||||
var settings = stats.AntiSpamSettings;
|
var ignoredString = string.Join(", ", stats.AntiSpamSettings.IgnoredChannels.Select(c => $"<#{c.ChannelId}>"));
|
||||||
var ignoredString = string.Join(", ", settings.IgnoredChannels.Select(c => $"<#{c.ChannelId}>"));
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(ignoredString))
|
if (string.IsNullOrWhiteSpace(ignoredString))
|
||||||
ignoredString = "none";
|
ignoredString = "none";
|
||||||
|
|
||||||
string add = "";
|
|
||||||
if (settings.Action == PunishmentAction.Mute
|
|
||||||
&& settings.MuteTime > 0)
|
|
||||||
{
|
|
||||||
add = " (" + settings.MuteTime + "s)";
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetText("spam_stats",
|
return GetText("spam_stats",
|
||||||
Format.Bold(settings.MessageThreshold.ToString()),
|
Format.Bold(stats.AntiSpamSettings.MessageThreshold.ToString()),
|
||||||
Format.Bold(settings.Action.ToString() + add),
|
Format.Bold(stats.AntiSpamSettings.Action.ToString()),
|
||||||
ignoredString);
|
ignoredString);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +62,8 @@ namespace NadekoBot.Modules.Administration
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_service.AntiRaidGuilds.TryRemove(Context.Guild.Id, out _))
|
AntiRaidStats throwaway;
|
||||||
|
if (_service.AntiRaidGuilds.TryRemove(Context.Guild.Id, out throwaway))
|
||||||
{
|
{
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
@ -121,12 +114,15 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[RequireUserPermission(GuildPermission.Administrator)]
|
[RequireUserPermission(GuildPermission.Administrator)]
|
||||||
[Priority(1)]
|
public async Task AntiSpam(int messageCount = 3, PunishmentAction action = PunishmentAction.Mute)
|
||||||
public async Task AntiSpam()
|
|
||||||
{
|
{
|
||||||
if (_service.AntiSpamGuilds.TryRemove(Context.Guild.Id, out var removed))
|
if (messageCount < 2 || messageCount > 10)
|
||||||
|
return;
|
||||||
|
|
||||||
|
AntiSpamStats throwaway;
|
||||||
|
if (_service.AntiSpamGuilds.TryRemove(Context.Guild.Id, out throwaway))
|
||||||
{
|
{
|
||||||
removed.UserStats.ForEach(x => x.Value.Dispose());
|
throwaway.UserStats.ForEach(x => x.Value.Dispose());
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
var gc = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.AntiSpamSetting)
|
var gc = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.AntiSpamSetting)
|
||||||
@ -139,21 +135,6 @@ namespace NadekoBot.Modules.Administration
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await AntiSpam(3).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[RequireUserPermission(GuildPermission.Administrator)]
|
|
||||||
[Priority(0)]
|
|
||||||
public async Task AntiSpam(int messageCount, PunishmentAction action = PunishmentAction.Mute, int time = 0)
|
|
||||||
{
|
|
||||||
if (messageCount < 2 || messageCount > 10)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (time < 0 || time > 60 * 12)
|
|
||||||
return;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _mute.GetMuteRole(Context.Guild).ConfigureAwait(false);
|
await _mute.GetMuteRole(Context.Guild).ConfigureAwait(false);
|
||||||
@ -171,15 +152,10 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
Action = action,
|
Action = action,
|
||||||
MessageThreshold = messageCount,
|
MessageThreshold = messageCount,
|
||||||
MuteTime = time,
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
stats = _service.AntiSpamGuilds.AddOrUpdate(Context.Guild.Id, stats, (key, old) =>
|
_service.AntiSpamGuilds.AddOrUpdate(Context.Guild.Id, stats, (key, old) => stats);
|
||||||
{
|
|
||||||
stats.AntiSpamSettings.IgnoredChannels = old.AntiSpamSettings.IgnoredChannels;
|
|
||||||
return stats;
|
|
||||||
});
|
|
||||||
|
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
@ -1,19 +1,28 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Services.Administration;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
using NadekoBot.Modules.Administration.Services;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
||||||
public partial class Administration
|
public partial class Administration
|
||||||
{
|
{
|
||||||
[Group]
|
[Group]
|
||||||
public class PruneCommands : NadekoSubmodule<PruneService>
|
public class PruneCommands : ModuleBase
|
||||||
{
|
{
|
||||||
private readonly TimeSpan twoWeeks = TimeSpan.FromDays(14);
|
private readonly TimeSpan twoWeeks = TimeSpan.FromDays(14);
|
||||||
|
private readonly PruneService _prune;
|
||||||
|
|
||||||
|
public PruneCommands(PruneService prune)
|
||||||
|
{
|
||||||
|
_prune = prune;
|
||||||
|
}
|
||||||
|
|
||||||
//delets her own messages, no perm required
|
//delets her own messages, no perm required
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -22,7 +31,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
var user = await Context.Guild.GetCurrentUserAsync().ConfigureAwait(false);
|
var user = await Context.Guild.GetCurrentUserAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
await _service.PruneWhere((ITextChannel)Context.Channel, 100, (x) => x.Author.Id == user.Id).ConfigureAwait(false);
|
await _prune.PruneWhere((ITextChannel)Context.Channel, 100, (x) => x.Author.Id == user.Id).ConfigureAwait(false);
|
||||||
Context.Message.DeleteAfter(3);
|
Context.Message.DeleteAfter(3);
|
||||||
}
|
}
|
||||||
// prune x
|
// prune x
|
||||||
@ -30,7 +39,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[RequireUserPermission(ChannelPermission.ManageMessages)]
|
[RequireUserPermission(ChannelPermission.ManageMessages)]
|
||||||
[RequireBotPermission(GuildPermission.ManageMessages)]
|
[RequireBotPermission(GuildPermission.ManageMessages)]
|
||||||
[Priority(1)]
|
[Priority(0)]
|
||||||
public async Task Prune(int count)
|
public async Task Prune(int count)
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
@ -38,7 +47,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
return;
|
return;
|
||||||
if (count > 1000)
|
if (count > 1000)
|
||||||
count = 1000;
|
count = 1000;
|
||||||
await _service.PruneWhere((ITextChannel)Context.Channel, count, x => true).ConfigureAwait(false);
|
await _prune.PruneWhere((ITextChannel)Context.Channel, count, x => true).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//prune @user [x]
|
//prune @user [x]
|
||||||
@ -46,7 +55,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[RequireUserPermission(ChannelPermission.ManageMessages)]
|
[RequireUserPermission(ChannelPermission.ManageMessages)]
|
||||||
[RequireBotPermission(GuildPermission.ManageMessages)]
|
[RequireBotPermission(GuildPermission.ManageMessages)]
|
||||||
[Priority(0)]
|
[Priority(1)]
|
||||||
public async Task Prune(IGuildUser user, int count = 100)
|
public async Task Prune(IGuildUser user, int count = 100)
|
||||||
{
|
{
|
||||||
if (user.Id == Context.User.Id)
|
if (user.Id == Context.User.Id)
|
||||||
@ -57,7 +66,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
if (count > 1000)
|
if (count > 1000)
|
||||||
count = 1000;
|
count = 1000;
|
||||||
await _service.PruneWhere((ITextChannel)Context.Channel, count, m => m.Author.Id == user.Id && DateTime.UtcNow - m.CreatedAt < twoWeeks);
|
await _prune.PruneWhere((ITextChannel)Context.Channel, count, m => m.Author.Id == user.Id && DateTime.UtcNow - m.CreatedAt < twoWeeks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,27 +1,28 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
|
using NadekoBot.Services.Administration;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
using NadekoBot.Modules.Administration.Common;
|
|
||||||
using NadekoBot.Modules.Administration.Services;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
||||||
public partial class Administration
|
public partial class Administration
|
||||||
{
|
{
|
||||||
[Group]
|
[Group]
|
||||||
public class SlowModeCommands : NadekoSubmodule<SlowmodeService>
|
public class SlowModeCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
|
private readonly SlowmodeService _service;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public SlowModeCommands(DbService db)
|
public SlowModeCommands(SlowmodeService service, DbService db)
|
||||||
{
|
{
|
||||||
|
_service = service;
|
||||||
_db = db;
|
_db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,9 +31,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[RequireUserPermission(GuildPermission.ManageMessages)]
|
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||||
public async Task Slowmode()
|
public async Task Slowmode()
|
||||||
{
|
{
|
||||||
if (_service.RatelimitingChannels.TryRemove(Context.Channel.Id, out Ratelimiter removed))
|
if (_service.RatelimitingChannels.TryRemove(Context.Channel.Id, out Ratelimiter throwaway))
|
||||||
{
|
{
|
||||||
removed.CancelSource.Cancel();
|
throwaway.CancelSource.Cancel();
|
||||||
await ReplyConfirmLocalized("slowmode_disabled").ConfigureAwait(false);
|
await ReplyConfirmLocalized("slowmode_disabled").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,7 +67,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[RequireUserPermission(GuildPermission.ManageMessages)]
|
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||||
[Priority(0)]
|
[Priority(1)]
|
||||||
public async Task SlowmodeWhitelist(IGuildUser user)
|
public async Task SlowmodeWhitelist(IGuildUser user)
|
||||||
{
|
{
|
||||||
var siu = new SlowmodeIgnoredUser
|
var siu = new SlowmodeIgnoredUser
|
||||||
@ -98,7 +99,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[RequireUserPermission(GuildPermission.ManageMessages)]
|
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||||
[Priority(1)]
|
[Priority(0)]
|
||||||
public async Task SlowmodeWhitelist(IRole role)
|
public async Task SlowmodeWhitelist(IRole role)
|
||||||
{
|
{
|
||||||
var sir = new SlowmodeIgnoredRole
|
var sir = new SlowmodeIgnoredRole
|
@ -1,16 +1,16 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
using NadekoBot.Common.Collections;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
||||||
@ -195,23 +195,18 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var roleIds = roles.Select(x => x.RoleId).ToArray();
|
var roleIds = roles.Select(x => x.RoleId).ToArray();
|
||||||
if (conf.ExclusiveSelfAssignedRoles)
|
if (conf.ExclusiveSelfAssignedRoles)
|
||||||
{
|
{
|
||||||
var sameRoles = guildUser.RoleIds.Where(r => roleIds.Contains(r));
|
var sameRoleId = guildUser.RoleIds.FirstOrDefault(r => roleIds.Contains(r));
|
||||||
|
|
||||||
foreach (var roleId in sameRoles)
|
if (sameRoleId != default(ulong))
|
||||||
{
|
{
|
||||||
var sameRole = Context.Guild.GetRole(roleId);
|
var sameRole = Context.Guild.GetRole(sameRoleId);
|
||||||
if (sameRole != null)
|
if (sameRole != null)
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
await guildUser.RemoveRoleAsync(sameRole).ConfigureAwait(false);
|
await guildUser.RemoveRoleAsync(sameRole).ConfigureAwait(false);
|
||||||
await Task.Delay(300).ConfigureAwait(false);
|
await Task.Delay(500).ConfigureAwait(false);
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_log.Warn(ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
//await ReplyErrorLocalized("self_assign_already_excl", Format.Bold(sameRole?.Name)).ConfigureAwait(false);
|
||||||
|
//return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try
|
try
|
@ -1,5 +1,6 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -11,34 +12,34 @@ using Discord.WebSocket;
|
|||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using NadekoBot.Services.Administration;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using NadekoBot.Common.Attributes;
|
using NadekoBot.DataStructures;
|
||||||
using NadekoBot.Modules.Administration.Services;
|
using NadekoBot.Services.Music;
|
||||||
using NadekoBot.Modules.Music.Services;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
||||||
public partial class Administration
|
public partial class Administration
|
||||||
{
|
{
|
||||||
[Group]
|
[Group]
|
||||||
public class SelfCommands : NadekoSubmodule<SelfService>
|
public class SelfCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
private static readonly object _locker = new object();
|
private static readonly object _locker = new object();
|
||||||
|
private readonly SelfService _service;
|
||||||
private readonly DiscordSocketClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly IImagesService _images;
|
private readonly IImagesService _images;
|
||||||
private readonly MusicService _music;
|
private readonly MusicService _music;
|
||||||
private readonly IBotConfigProvider _bc;
|
|
||||||
|
|
||||||
public SelfCommands(DbService db, DiscordSocketClient client,
|
public SelfCommands(DbService db, SelfService service, DiscordSocketClient client,
|
||||||
MusicService music, IImagesService images, IBotConfigProvider bc)
|
MusicService music, IImagesService images)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
|
_service = service;
|
||||||
_client = client;
|
_client = client;
|
||||||
_images = images;
|
_images = images;
|
||||||
_music = music;
|
_music = music;
|
||||||
_bc = bc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -99,13 +100,13 @@ namespace NadekoBot.Modules.Administration
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await Context.Channel.SendConfirmAsync("", string.Join("\n", scmds.Select(x =>
|
await Context.Channel.SendConfirmAsync("", string.Join("\n--\n", scmds.Select(x =>
|
||||||
{
|
{
|
||||||
string str = $"```css\n[{GetText("server") + "]: " + (x.GuildId == null ? "-" : x.GuildName + " #" + x.GuildId)}";
|
string str = Format.Code(GetText("server")) + ": " + (x.GuildId == null ? "-" : x.GuildName + "/" + x.GuildId);
|
||||||
|
|
||||||
str += $@"
|
str += $@"
|
||||||
[{GetText("channel")}]: {x.ChannelName} #{x.ChannelId}
|
{Format.Code(GetText("channel"))}: {x.ChannelName}/{x.ChannelId}
|
||||||
[{GetText("command_text")}]: {x.CommandText}```";
|
{Format.Code(GetText("command_text"))}: {x.CommandText}";
|
||||||
return str;
|
return str;
|
||||||
})), footer: GetText("page", page + 1))
|
})), footer: GetText("page", page + 1))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
@ -181,11 +182,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
var config = uow.BotConfig.GetOrCreate();
|
var config = uow.BotConfig.GetOrCreate();
|
||||||
config.ForwardMessages = !config.ForwardMessages;
|
_service.ForwardDMs = config.ForwardMessages = !config.ForwardMessages;
|
||||||
uow.Complete();
|
uow.Complete();
|
||||||
}
|
}
|
||||||
_bc.Reload();
|
|
||||||
|
|
||||||
if (_service.ForwardDMs)
|
if (_service.ForwardDMs)
|
||||||
await ReplyConfirmLocalized("fwdm_start").ConfigureAwait(false);
|
await ReplyConfirmLocalized("fwdm_start").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
@ -200,11 +199,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
var config = uow.BotConfig.GetOrCreate();
|
var config = uow.BotConfig.GetOrCreate();
|
||||||
lock (_locker)
|
lock (_locker)
|
||||||
config.ForwardToAllOwners = !config.ForwardToAllOwners;
|
_service.ForwardDMsToAllOwners = config.ForwardToAllOwners = !config.ForwardToAllOwners;
|
||||||
uow.Complete();
|
uow.Complete();
|
||||||
}
|
}
|
||||||
_bc.Reload();
|
|
||||||
|
|
||||||
if (_service.ForwardDMsToAllOwners)
|
if (_service.ForwardDMsToAllOwners)
|
||||||
await ReplyConfirmLocalized("fwall_start").ConfigureAwait(false);
|
await ReplyConfirmLocalized("fwall_start").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
@ -292,7 +289,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireUserPermission(GuildPermission.ManageNicknames)]
|
[RequireUserPermission(GuildPermission.ManageNicknames)]
|
||||||
[Priority(0)]
|
[Priority(1)]
|
||||||
public async Task SetNick([Remainder] string newNick = null)
|
public async Task SetNick([Remainder] string newNick = null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(newNick))
|
if (string.IsNullOrWhiteSpace(newNick))
|
||||||
@ -306,7 +303,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireBotPermission(GuildPermission.ManageNicknames)]
|
[RequireBotPermission(GuildPermission.ManageNicknames)]
|
||||||
[RequireUserPermission(GuildPermission.ManageNicknames)]
|
[RequireUserPermission(GuildPermission.ManageNicknames)]
|
||||||
[Priority(1)]
|
[Priority(0)]
|
||||||
public async Task SetNick(IGuildUser gu, [Remainder] string newNick = null)
|
public async Task SetNick(IGuildUser gu, [Remainder] string newNick = null)
|
||||||
{
|
{
|
||||||
await gu.ModifyAsync(u => u.Nickname = newNick).ConfigureAwait(false);
|
await gu.ModifyAsync(u => u.Nickname = newNick).ConfigureAwait(false);
|
||||||
@ -409,6 +406,19 @@ namespace NadekoBot.Modules.Administration
|
|||||||
await ReplyConfirmLocalized("message_sent").ConfigureAwait(false);
|
await ReplyConfirmLocalized("message_sent").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[OwnerOnly]
|
||||||
|
public async Task Announce([Remainder] string message)
|
||||||
|
{
|
||||||
|
var channels = _client.Guilds.Select(g => g.DefaultChannel).ToArray();
|
||||||
|
if (channels == null)
|
||||||
|
return;
|
||||||
|
await Task.WhenAll(channels.Where(c => c != null).Select(c => c.SendConfirmAsync(GetText("message_from_bo", Context.User.ToString()), message)))
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
await ReplyConfirmLocalized("message_sent").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task ReloadImages()
|
public async Task ReloadImages()
|
@ -1,22 +1,24 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
||||||
public partial class Administration
|
public partial class Administration
|
||||||
{
|
{
|
||||||
[Group]
|
[Group]
|
||||||
public class ServerGreetCommands : NadekoSubmodule<GreetSettingsService>
|
public class ServerGreetCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
|
private readonly GreetSettingsService _greetService;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public ServerGreetCommands(DbService db)
|
public ServerGreetCommands(GreetSettingsService greetService, DbService db)
|
||||||
{
|
{
|
||||||
|
_greetService = greetService;
|
||||||
_db = db;
|
_db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,7 +30,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
if (timer < 0 || timer > 600)
|
if (timer < 0 || timer > 600)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await _service.SetGreetDel(Context.Guild.Id, timer).ConfigureAwait(false);
|
await _greetService.SetGreetDel(Context.Guild.Id, timer).ConfigureAwait(false);
|
||||||
|
|
||||||
if (timer > 0)
|
if (timer > 0)
|
||||||
await ReplyConfirmLocalized("greetdel_on", timer).ConfigureAwait(false);
|
await ReplyConfirmLocalized("greetdel_on", timer).ConfigureAwait(false);
|
||||||
@ -41,7 +43,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||||
public async Task Greet()
|
public async Task Greet()
|
||||||
{
|
{
|
||||||
var enabled = await _service.SetGreet(Context.Guild.Id, Context.Channel.Id).ConfigureAwait(false);
|
var enabled = await _greetService.SetGreet(Context.Guild.Id, Context.Channel.Id).ConfigureAwait(false);
|
||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
await ReplyConfirmLocalized("greet_on").ConfigureAwait(false);
|
await ReplyConfirmLocalized("greet_on").ConfigureAwait(false);
|
||||||
@ -65,7 +67,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sendGreetEnabled = _service.SetGreetMessage(Context.Guild.Id, ref text);
|
var sendGreetEnabled = _greetService.SetGreetMessage(Context.Guild.Id, ref text);
|
||||||
|
|
||||||
await ReplyConfirmLocalized("greetmsg_new").ConfigureAwait(false);
|
await ReplyConfirmLocalized("greetmsg_new").ConfigureAwait(false);
|
||||||
if (!sendGreetEnabled)
|
if (!sendGreetEnabled)
|
||||||
@ -77,7 +79,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||||
public async Task GreetDm()
|
public async Task GreetDm()
|
||||||
{
|
{
|
||||||
var enabled = await _service.SetGreetDm(Context.Guild.Id).ConfigureAwait(false);
|
var enabled = await _greetService.SetGreetDm(Context.Guild.Id).ConfigureAwait(false);
|
||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
await ReplyConfirmLocalized("greetdm_on").ConfigureAwait(false);
|
await ReplyConfirmLocalized("greetdm_on").ConfigureAwait(false);
|
||||||
@ -101,7 +103,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sendGreetEnabled = _service.SetGreetDmMessage(Context.Guild.Id, ref text);
|
var sendGreetEnabled = _greetService.SetGreetDmMessage(Context.Guild.Id, ref text);
|
||||||
|
|
||||||
await ReplyConfirmLocalized("greetdmmsg_new").ConfigureAwait(false);
|
await ReplyConfirmLocalized("greetdmmsg_new").ConfigureAwait(false);
|
||||||
if (!sendGreetEnabled)
|
if (!sendGreetEnabled)
|
||||||
@ -113,7 +115,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||||
public async Task Bye()
|
public async Task Bye()
|
||||||
{
|
{
|
||||||
var enabled = await _service.SetBye(Context.Guild.Id, Context.Channel.Id).ConfigureAwait(false);
|
var enabled = await _greetService.SetBye(Context.Guild.Id, Context.Channel.Id).ConfigureAwait(false);
|
||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
await ReplyConfirmLocalized("bye_on").ConfigureAwait(false);
|
await ReplyConfirmLocalized("bye_on").ConfigureAwait(false);
|
||||||
@ -137,7 +139,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sendByeEnabled = _service.SetByeMessage(Context.Guild.Id, ref text);
|
var sendByeEnabled = _greetService.SetByeMessage(Context.Guild.Id, ref text);
|
||||||
|
|
||||||
await ReplyConfirmLocalized("byemsg_new").ConfigureAwait(false);
|
await ReplyConfirmLocalized("byemsg_new").ConfigureAwait(false);
|
||||||
if (!sendByeEnabled)
|
if (!sendByeEnabled)
|
||||||
@ -149,7 +151,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||||
public async Task ByeDel(int timer = 30)
|
public async Task ByeDel(int timer = 30)
|
||||||
{
|
{
|
||||||
await _service.SetByeDel(Context.Guild.Id, timer).ConfigureAwait(false);
|
await _greetService.SetByeDel(Context.Guild.Id, timer).ConfigureAwait(false);
|
||||||
|
|
||||||
if (timer > 0)
|
if (timer > 0)
|
||||||
await ReplyConfirmLocalized("byedel_on", timer).ConfigureAwait(false);
|
await ReplyConfirmLocalized("byedel_on", timer).ConfigureAwait(false);
|
@ -1,20 +1,27 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Services.Administration;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
using NadekoBot.Modules.Administration.Services;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
||||||
public partial class Administration
|
public partial class Administration
|
||||||
{
|
{
|
||||||
[Group]
|
[Group]
|
||||||
public class TimeZoneCommands : NadekoSubmodule<GuildTimezoneService>
|
public class TimeZoneCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
|
private readonly GuildTimezoneService _service;
|
||||||
|
|
||||||
|
public TimeZoneCommands(GuildTimezoneService service)
|
||||||
|
{
|
||||||
|
_service = service;
|
||||||
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task Timezones(int page = 1)
|
public async Task Timezones(int page = 1)
|
@ -2,26 +2,104 @@
|
|||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
|
using NadekoBot.Services.Administration;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
using NadekoBot.Modules.Administration.Services;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
||||||
public partial class Administration
|
public partial class Administration
|
||||||
{
|
{
|
||||||
[Group]
|
[Group]
|
||||||
public class UserPunishCommands : NadekoSubmodule<UserPunishService>
|
public class UserPunishCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
private readonly MuteService _muteService;
|
||||||
|
|
||||||
public UserPunishCommands(DbService db, MuteService muteService)
|
public UserPunishCommands(DbService db, MuteService muteService)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
|
_muteService = muteService;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<PunishmentAction?> InternalWarn(IGuild guild, ulong userId, string modName, string reason)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(reason))
|
||||||
|
reason = "-";
|
||||||
|
|
||||||
|
var guildId = guild.Id;
|
||||||
|
|
||||||
|
var warn = new Warning()
|
||||||
|
{
|
||||||
|
UserId = userId,
|
||||||
|
GuildId = guildId,
|
||||||
|
Forgiven = false,
|
||||||
|
Reason = reason,
|
||||||
|
Moderator = modName,
|
||||||
|
};
|
||||||
|
|
||||||
|
int warnings = 1;
|
||||||
|
List<WarningPunishment> ps;
|
||||||
|
using (var uow = _db.UnitOfWork)
|
||||||
|
{
|
||||||
|
ps = uow.GuildConfigs.For(guildId, set => set.Include(x => x.WarnPunishments))
|
||||||
|
.WarnPunishments;
|
||||||
|
|
||||||
|
warnings += uow.Warnings
|
||||||
|
.For(guildId, userId)
|
||||||
|
.Where(w => !w.Forgiven && w.UserId == userId)
|
||||||
|
.Count();
|
||||||
|
|
||||||
|
uow.Warnings.Add(warn);
|
||||||
|
|
||||||
|
uow.Complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
var p = ps.FirstOrDefault(x => x.Count == warnings);
|
||||||
|
|
||||||
|
if (p != null)
|
||||||
|
{
|
||||||
|
var user = await guild.GetUserAsync(userId);
|
||||||
|
if (user == null)
|
||||||
|
return null;
|
||||||
|
switch (p.Punishment)
|
||||||
|
{
|
||||||
|
case PunishmentAction.Mute:
|
||||||
|
if (p.Time == 0)
|
||||||
|
await _muteService.MuteUser(user).ConfigureAwait(false);
|
||||||
|
else
|
||||||
|
await _muteService.TimedMute(user, TimeSpan.FromMinutes(p.Time)).ConfigureAwait(false);
|
||||||
|
break;
|
||||||
|
case PunishmentAction.Kick:
|
||||||
|
await user.KickAsync().ConfigureAwait(false);
|
||||||
|
break;
|
||||||
|
case PunishmentAction.Ban:
|
||||||
|
await guild.AddBanAsync(user).ConfigureAwait(false);
|
||||||
|
break;
|
||||||
|
case PunishmentAction.Softban:
|
||||||
|
await guild.AddBanAsync(user, 7).ConfigureAwait(false);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await guild.RemoveBanAsync(user).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await guild.RemoveBanAsync(user).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return p.Punishment;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -38,7 +116,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
var punishment = await _service.Warn(Context.Guild, user.Id, Context.User.ToString(), reason).ConfigureAwait(false);
|
var punishment = await InternalWarn(Context.Guild, user.Id, Context.User.ToString(), reason).ConfigureAwait(false);
|
||||||
|
|
||||||
if (punishment == null)
|
if (punishment == null)
|
||||||
{
|
{
|
||||||
@ -53,27 +131,27 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[RequireUserPermission(GuildPermission.BanMembers)]
|
[RequireUserPermission(GuildPermission.BanMembers)]
|
||||||
[Priority(2)]
|
[Priority(1)]
|
||||||
public Task Warnlog(int page, IGuildUser user)
|
public Task Warnlog(int page, IGuildUser user)
|
||||||
=> Warnlog(page, user.Id);
|
=> Warnlog(page, user.Id);
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[Priority(3)]
|
[Priority(0)]
|
||||||
public Task Warnlog(IGuildUser user)
|
public Task Warnlog(IGuildUser user)
|
||||||
=> Context.User.Id == user.Id || ((IGuildUser)Context.User).GuildPermissions.BanMembers ? Warnlog(user.Id) : Task.CompletedTask;
|
=> Context.User.Id == user.Id || ((IGuildUser)Context.User).GuildPermissions.BanMembers ? Warnlog(user.Id) : Task.CompletedTask;
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[RequireUserPermission(GuildPermission.BanMembers)]
|
[RequireUserPermission(GuildPermission.BanMembers)]
|
||||||
[Priority(0)]
|
[Priority(3)]
|
||||||
public Task Warnlog(int page, ulong userId)
|
public Task Warnlog(int page, ulong userId)
|
||||||
=> InternalWarnlog(userId, page - 1);
|
=> InternalWarnlog(userId, page - 1);
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[RequireUserPermission(GuildPermission.BanMembers)]
|
[RequireUserPermission(GuildPermission.BanMembers)]
|
||||||
[Priority(1)]
|
[Priority(2)]
|
||||||
public Task Warnlog(ulong userId)
|
public Task Warnlog(ulong userId)
|
||||||
=> InternalWarnlog(userId, 0);
|
=> InternalWarnlog(userId, 0);
|
||||||
|
|
||||||
@ -126,7 +204,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
IGrouping<ulong, Warning>[] warnings;
|
IGrouping<ulong, Warning>[] warnings;
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
warnings = uow.Warnings.GetForGuild(Context.Guild.Id).GroupBy(x => x.UserId).ToArray();
|
warnings = uow.Warnings.GetAll().GroupBy(x => x.UserId).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
await Context.Channel.SendPaginatedConfirmAsync((DiscordSocketClient)Context.Client, page, async (curPage) =>
|
await Context.Channel.SendPaginatedConfirmAsync((DiscordSocketClient)Context.Client, page, async (curPage) =>
|
@ -2,26 +2,28 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Modules.Administration.Services;
|
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using NadekoBot.Services.Administration;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
||||||
public partial class Administration
|
public partial class Administration
|
||||||
{
|
{
|
||||||
[Group]
|
[Group]
|
||||||
public class VcRoleCommands : NadekoSubmodule<VcRoleService>
|
public class VcRoleCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
|
private readonly VcRoleService _service;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public VcRoleCommands(DbService db)
|
public VcRoleCommands(VcRoleService service, DbService db)
|
||||||
{
|
{
|
||||||
|
_service = service;
|
||||||
_db = db;
|
_db = db;
|
||||||
}
|
}
|
||||||
|
|
@ -1,26 +1,28 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
|
using NadekoBot.Services.Administration;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
using NadekoBot.Modules.Administration.Services;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
||||||
public partial class Administration
|
public partial class Administration
|
||||||
{
|
{
|
||||||
[Group]
|
[Group]
|
||||||
public class VoicePlusTextCommands : NadekoSubmodule<VplusTService>
|
public class VoicePlusTextCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
|
private readonly VplusTService _service;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public VoicePlusTextCommands(DbService db)
|
public VoicePlusTextCommands(VplusTService service, DbService db)
|
||||||
{
|
{
|
||||||
|
_service = service;
|
||||||
_db = db;
|
_db = db;
|
||||||
}
|
}
|
||||||
|
|
@ -1,97 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Discord;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using NadekoBot.Services;
|
|
||||||
using NadekoBot.Services.Database.Models;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration.Services
|
|
||||||
{
|
|
||||||
public class UserPunishService : INService
|
|
||||||
{
|
|
||||||
private readonly MuteService _mute;
|
|
||||||
private readonly DbService _db;
|
|
||||||
|
|
||||||
public UserPunishService(MuteService mute, DbService db)
|
|
||||||
{
|
|
||||||
_mute = mute;
|
|
||||||
_db = db;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<PunishmentAction?> Warn(IGuild guild, ulong userId, string modName, string reason)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(reason))
|
|
||||||
reason = "-";
|
|
||||||
|
|
||||||
var guildId = guild.Id;
|
|
||||||
|
|
||||||
var warn = new Warning()
|
|
||||||
{
|
|
||||||
UserId = userId,
|
|
||||||
GuildId = guildId,
|
|
||||||
Forgiven = false,
|
|
||||||
Reason = reason,
|
|
||||||
Moderator = modName,
|
|
||||||
};
|
|
||||||
|
|
||||||
int warnings = 1;
|
|
||||||
List<WarningPunishment> ps;
|
|
||||||
using (var uow = _db.UnitOfWork)
|
|
||||||
{
|
|
||||||
ps = uow.GuildConfigs.For(guildId, set => set.Include(x => x.WarnPunishments))
|
|
||||||
.WarnPunishments;
|
|
||||||
|
|
||||||
warnings += uow.Warnings
|
|
||||||
.For(guildId, userId)
|
|
||||||
.Where(w => !w.Forgiven && w.UserId == userId)
|
|
||||||
.Count();
|
|
||||||
|
|
||||||
uow.Warnings.Add(warn);
|
|
||||||
|
|
||||||
uow.Complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
var p = ps.FirstOrDefault(x => x.Count == warnings);
|
|
||||||
|
|
||||||
if (p != null)
|
|
||||||
{
|
|
||||||
var user = await guild.GetUserAsync(userId);
|
|
||||||
if (user == null)
|
|
||||||
return null;
|
|
||||||
switch (p.Punishment)
|
|
||||||
{
|
|
||||||
case PunishmentAction.Mute:
|
|
||||||
if (p.Time == 0)
|
|
||||||
await _mute.MuteUser(user).ConfigureAwait(false);
|
|
||||||
else
|
|
||||||
await _mute.TimedMute(user, TimeSpan.FromMinutes(p.Time)).ConfigureAwait(false);
|
|
||||||
break;
|
|
||||||
case PunishmentAction.Kick:
|
|
||||||
await user.KickAsync().ConfigureAwait(false);
|
|
||||||
break;
|
|
||||||
case PunishmentAction.Ban:
|
|
||||||
await guild.AddBanAsync(user).ConfigureAwait(false);
|
|
||||||
break;
|
|
||||||
case PunishmentAction.Softban:
|
|
||||||
await guild.AddBanAsync(user, 7).ConfigureAwait(false);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await guild.RemoveBanAsync(user).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
await guild.RemoveBanAsync(user).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return p.Punishment;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
239
src/NadekoBot/Modules/ClashOfClans/ClashOfClans.cs
Normal file
239
src/NadekoBot/Modules/ClashOfClans/ClashOfClans.cs
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
using Discord.Commands;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Services.ClashOfClans;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.ClashOfClans
|
||||||
|
{
|
||||||
|
public class ClashOfClans : NadekoTopLevelModule
|
||||||
|
{
|
||||||
|
private readonly ClashOfClansService _service;
|
||||||
|
|
||||||
|
public ClashOfClans(ClashOfClansService service)
|
||||||
|
{
|
||||||
|
_service = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||||
|
public async Task CreateWar(int size, [Remainder] string enemyClan = null)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(enemyClan))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (size < 10 || size > 50 || size % 5 != 0)
|
||||||
|
{
|
||||||
|
await ReplyErrorLocalized("invalid_size").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<ClashWar> wars;
|
||||||
|
if (!_service.ClashWars.TryGetValue(Context.Guild.Id, out wars))
|
||||||
|
{
|
||||||
|
wars = new List<ClashWar>();
|
||||||
|
if (!_service.ClashWars.TryAdd(Context.Guild.Id, wars))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var cw = await _service.CreateWar(enemyClan, size, Context.Guild.Id, Context.Channel.Id);
|
||||||
|
|
||||||
|
wars.Add(cw);
|
||||||
|
await ReplyErrorLocalized("war_created", _service.ShortPrint(cw)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task StartWar([Remainder] string number = null)
|
||||||
|
{
|
||||||
|
int num = 0;
|
||||||
|
int.TryParse(number, out num);
|
||||||
|
|
||||||
|
var warsInfo = _service.GetWarInfo(Context.Guild, num);
|
||||||
|
if (warsInfo == null)
|
||||||
|
{
|
||||||
|
await ReplyErrorLocalized("war_not_exist").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var war = warsInfo.Item1[warsInfo.Item2];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
war.Start();
|
||||||
|
await ReplyConfirmLocalized("war_started", _service.ShortPrint(war)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await ReplyErrorLocalized("war_already_started", _service.ShortPrint(war)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
_service.SaveWar(war);
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task ListWar([Remainder] string number = null)
|
||||||
|
{
|
||||||
|
|
||||||
|
// if number is null, print all wars in a short way
|
||||||
|
if (string.IsNullOrWhiteSpace(number))
|
||||||
|
{
|
||||||
|
//check if there are any wars
|
||||||
|
List<ClashWar> wars = null;
|
||||||
|
_service.ClashWars.TryGetValue(Context.Guild.Id, out wars);
|
||||||
|
if (wars == null || wars.Count == 0)
|
||||||
|
{
|
||||||
|
await ReplyErrorLocalized("no_active_wars").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendLine("**-------------------------**");
|
||||||
|
for (var i = 0; i < wars.Count; i++)
|
||||||
|
{
|
||||||
|
sb.AppendLine($"**#{i + 1}.** `{GetText("enemy")}:` **{wars[i].EnemyClan}**");
|
||||||
|
sb.AppendLine($"\t\t`{GetText("size")}:` **{wars[i].Size} v {wars[i].Size}**");
|
||||||
|
sb.AppendLine("**-------------------------**");
|
||||||
|
}
|
||||||
|
await Context.Channel.SendConfirmAsync(GetText("list_active_wars"), sb.ToString()).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var num = 0;
|
||||||
|
int.TryParse(number, out num);
|
||||||
|
//if number is not null, print the war needed
|
||||||
|
var warsInfo = _service.GetWarInfo(Context.Guild, num);
|
||||||
|
if (warsInfo == null)
|
||||||
|
{
|
||||||
|
await ReplyErrorLocalized("war_not_exist").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var war = warsInfo.Item1[warsInfo.Item2];
|
||||||
|
await Context.Channel.SendConfirmAsync(_service.Localize(war, "info_about_war", $"`{war.EnemyClan}` ({war.Size} v {war.Size})"), _service.ToPrettyString(war)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task BaseCall(int number, int baseNumber, [Remainder] string other_name = null)
|
||||||
|
{
|
||||||
|
var warsInfo = _service.GetWarInfo(Context.Guild, number);
|
||||||
|
if (warsInfo == null || warsInfo.Item1.Count == 0)
|
||||||
|
{
|
||||||
|
await ReplyErrorLocalized("war_not_exist").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var usr =
|
||||||
|
string.IsNullOrWhiteSpace(other_name) ?
|
||||||
|
Context.User.Username :
|
||||||
|
other_name;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var war = warsInfo.Item1[warsInfo.Item2];
|
||||||
|
_service.Call(war, usr, baseNumber - 1);
|
||||||
|
_service.SaveWar(war);
|
||||||
|
await ConfirmLocalized("claimed_base", Format.Bold(usr.ToString()), baseNumber, _service.ShortPrint(war)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await Context.Channel.SendErrorAsync(ex.Message).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task CallFinish1(int number, int baseNumber = 0)
|
||||||
|
{
|
||||||
|
await FinishClaim(number, baseNumber - 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task CallFinish2(int number, int baseNumber = 0)
|
||||||
|
{
|
||||||
|
await FinishClaim(number, baseNumber - 1, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task CallFinish(int number, int baseNumber = 0)
|
||||||
|
{
|
||||||
|
await FinishClaim(number, baseNumber - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task EndWar(int number)
|
||||||
|
{
|
||||||
|
var warsInfo = _service.GetWarInfo(Context.Guild, number);
|
||||||
|
if (warsInfo == null)
|
||||||
|
{
|
||||||
|
await ReplyErrorLocalized("war_not_exist").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var war = warsInfo.Item1[warsInfo.Item2];
|
||||||
|
war.End();
|
||||||
|
_service.SaveWar(war);
|
||||||
|
await ReplyConfirmLocalized("war_ended", _service.ShortPrint(warsInfo.Item1[warsInfo.Item2])).ConfigureAwait(false);
|
||||||
|
|
||||||
|
warsInfo.Item1.RemoveAt(warsInfo.Item2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task Unclaim(int number, [Remainder] string otherName = null)
|
||||||
|
{
|
||||||
|
var warsInfo = _service.GetWarInfo(Context.Guild, number);
|
||||||
|
if (warsInfo == null || warsInfo.Item1.Count == 0)
|
||||||
|
{
|
||||||
|
await ReplyErrorLocalized("war_not_exist").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var usr =
|
||||||
|
string.IsNullOrWhiteSpace(otherName) ?
|
||||||
|
Context.User.Username :
|
||||||
|
otherName;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var war = warsInfo.Item1[warsInfo.Item2];
|
||||||
|
var baseNumber = _service.Uncall(war, usr);
|
||||||
|
_service.SaveWar(war);
|
||||||
|
await ReplyConfirmLocalized("base_unclaimed", usr, baseNumber + 1, _service.ShortPrint(war)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await Context.Channel.SendErrorAsync(ex.Message).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task FinishClaim(int number, int baseNumber, int stars = 3)
|
||||||
|
{
|
||||||
|
var warInfo = _service.GetWarInfo(Context.Guild, number);
|
||||||
|
if (warInfo == null || warInfo.Item1.Count == 0)
|
||||||
|
{
|
||||||
|
await ReplyErrorLocalized("war_not_exist").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var war = warInfo.Item1[warInfo.Item2];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (baseNumber == -1)
|
||||||
|
{
|
||||||
|
baseNumber = _service.FinishClaim(war, Context.User.Username, stars);
|
||||||
|
_service.SaveWar(war);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_service.FinishClaim(war, baseNumber, stars);
|
||||||
|
}
|
||||||
|
await ReplyConfirmLocalized("base_destroyed", baseNumber + 1, _service.ShortPrint(war)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await Context.Channel.SendErrorAsync($"🔰 {ex.Message}").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,27 +2,29 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using Discord;
|
using Discord;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using System;
|
using System;
|
||||||
using NadekoBot.Common.Attributes;
|
using NadekoBot.Services.CustomReactions;
|
||||||
using NadekoBot.Modules.CustomReactions.Services;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.CustomReactions
|
namespace NadekoBot.Modules.CustomReactions
|
||||||
{
|
{
|
||||||
public class CustomReactions : NadekoTopLevelModule<CustomReactionsService>
|
public class CustomReactions : NadekoTopLevelModule
|
||||||
{
|
{
|
||||||
private readonly IBotCredentials _creds;
|
private readonly IBotCredentials _creds;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
private readonly CustomReactionsService _crs;
|
||||||
private readonly DiscordSocketClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
|
|
||||||
public CustomReactions(IBotCredentials creds, DbService db,
|
public CustomReactions(IBotCredentials creds, DbService db, CustomReactionsService crs,
|
||||||
DiscordSocketClient client)
|
DiscordSocketClient client)
|
||||||
{
|
{
|
||||||
_creds = creds;
|
_creds = creds;
|
||||||
_db = db;
|
_db = db;
|
||||||
|
_crs = crs;
|
||||||
_client = client;
|
_client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,12 +60,12 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
|
|
||||||
if (channel == null)
|
if (channel == null)
|
||||||
{
|
{
|
||||||
Array.Resize(ref _service.GlobalReactions, _service.GlobalReactions.Length + 1);
|
Array.Resize(ref _crs.GlobalReactions, _crs.GlobalReactions.Length + 1);
|
||||||
_service.GlobalReactions[_service.GlobalReactions.Length - 1] = cr;
|
_crs.GlobalReactions[_crs.GlobalReactions.Length - 1] = cr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_service.GuildReactions.AddOrUpdate(Context.Guild.Id,
|
_crs.GuildReactions.AddOrUpdate(Context.Guild.Id,
|
||||||
new CustomReaction[] { cr },
|
new CustomReaction[] { cr },
|
||||||
(k, old) =>
|
(k, old) =>
|
||||||
{
|
{
|
||||||
@ -77,21 +79,21 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
.WithTitle(GetText("new_cust_react"))
|
.WithTitle(GetText("new_cust_react"))
|
||||||
.WithDescription($"#{cr.Id}")
|
.WithDescription($"#{cr.Id}")
|
||||||
.AddField(efb => efb.WithName(GetText("trigger")).WithValue(key))
|
.AddField(efb => efb.WithName(GetText("trigger")).WithValue(key))
|
||||||
.AddField(efb => efb.WithName(GetText("response")).WithValue(message.Length > 1024 ? GetText("redacted_too_long") : message))
|
.AddField(efb => efb.WithName(GetText("response")).WithValue(message))
|
||||||
).ConfigureAwait(false);
|
).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[Priority(1)]
|
[Priority(0)]
|
||||||
public async Task ListCustReact(int page = 1)
|
public async Task ListCustReact(int page = 1)
|
||||||
{
|
{
|
||||||
if (--page < 0 || page > 999)
|
if (--page < 0 || page > 999)
|
||||||
return;
|
return;
|
||||||
CustomReaction[] customReactions;
|
CustomReaction[] customReactions;
|
||||||
if (Context.Guild == null)
|
if (Context.Guild == null)
|
||||||
customReactions = _service.GlobalReactions.Where(cr => cr != null).ToArray();
|
customReactions = _crs.GlobalReactions.Where(cr => cr != null).ToArray();
|
||||||
else
|
else
|
||||||
customReactions = _service.GuildReactions.GetOrAdd(Context.Guild.Id, Array.Empty<CustomReaction>()).Where(cr => cr != null).ToArray();
|
customReactions = _crs.GuildReactions.GetOrAdd(Context.Guild.Id, Array.Empty<CustomReaction>()).Where(cr => cr != null).ToArray();
|
||||||
|
|
||||||
if (customReactions == null || !customReactions.Any())
|
if (customReactions == null || !customReactions.Any())
|
||||||
{
|
{
|
||||||
@ -128,14 +130,14 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[Priority(0)]
|
[Priority(1)]
|
||||||
public async Task ListCustReact(All x)
|
public async Task ListCustReact(All x)
|
||||||
{
|
{
|
||||||
CustomReaction[] customReactions;
|
CustomReaction[] customReactions;
|
||||||
if (Context.Guild == null)
|
if (Context.Guild == null)
|
||||||
customReactions = _service.GlobalReactions.Where(cr => cr != null).ToArray();
|
customReactions = _crs.GlobalReactions.Where(cr => cr != null).ToArray();
|
||||||
else
|
else
|
||||||
customReactions = _service.GuildReactions.GetOrAdd(Context.Guild.Id, new CustomReaction[]{ }).Where(cr => cr != null).ToArray();
|
customReactions = _crs.GuildReactions.GetOrAdd(Context.Guild.Id, new CustomReaction[]{ }).Where(cr => cr != null).ToArray();
|
||||||
|
|
||||||
if (customReactions == null || !customReactions.Any())
|
if (customReactions == null || !customReactions.Any())
|
||||||
{
|
{
|
||||||
@ -153,7 +155,7 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
if (Context.Guild == null) // its a private one, just send back
|
if (Context.Guild == null) // its a private one, just send back
|
||||||
await Context.Channel.SendFileAsync(txtStream, "customreactions.txt", GetText("list_all")).ConfigureAwait(false);
|
await Context.Channel.SendFileAsync(txtStream, "customreactions.txt", GetText("list_all")).ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await ((IGuildUser)Context.User).SendFileAsync(txtStream, "customreactions.txt", GetText("list_all"), false).ConfigureAwait(false);
|
await ((IGuildUser)Context.User).SendFileAsync(txtStream, "customreactions.txt", GetText("list_all")).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -163,9 +165,9 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
return;
|
return;
|
||||||
CustomReaction[] customReactions;
|
CustomReaction[] customReactions;
|
||||||
if (Context.Guild == null)
|
if (Context.Guild == null)
|
||||||
customReactions = _service.GlobalReactions.Where(cr => cr != null).ToArray();
|
customReactions = _crs.GlobalReactions.Where(cr => cr != null).ToArray();
|
||||||
else
|
else
|
||||||
customReactions = _service.GuildReactions.GetOrAdd(Context.Guild.Id, new CustomReaction[]{ }).Where(cr => cr != null).ToArray();
|
customReactions = _crs.GuildReactions.GetOrAdd(Context.Guild.Id, new CustomReaction[]{ }).Where(cr => cr != null).ToArray();
|
||||||
|
|
||||||
if (customReactions == null || !customReactions.Any())
|
if (customReactions == null || !customReactions.Any())
|
||||||
{
|
{
|
||||||
@ -195,9 +197,9 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
{
|
{
|
||||||
CustomReaction[] customReactions;
|
CustomReaction[] customReactions;
|
||||||
if (Context.Guild == null)
|
if (Context.Guild == null)
|
||||||
customReactions = _service.GlobalReactions;
|
customReactions = _crs.GlobalReactions;
|
||||||
else
|
else
|
||||||
customReactions = _service.GuildReactions.GetOrAdd(Context.Guild.Id, new CustomReaction[]{ });
|
customReactions = _crs.GuildReactions.GetOrAdd(Context.Guild.Id, new CustomReaction[]{ });
|
||||||
|
|
||||||
var found = customReactions.FirstOrDefault(cr => cr?.Id == id);
|
var found = customReactions.FirstOrDefault(cr => cr?.Id == id);
|
||||||
|
|
||||||
@ -238,13 +240,13 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
{
|
{
|
||||||
uow.CustomReactions.Remove(toDelete);
|
uow.CustomReactions.Remove(toDelete);
|
||||||
//todo 91 i can dramatically improve performance of this, if Ids are ordered.
|
//todo 91 i can dramatically improve performance of this, if Ids are ordered.
|
||||||
_service.GlobalReactions = _service.GlobalReactions.Where(cr => cr?.Id != toDelete.Id).ToArray();
|
_crs.GlobalReactions = _crs.GlobalReactions.Where(cr => cr?.Id != toDelete.Id).ToArray();
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
else if ((toDelete.GuildId != null && toDelete.GuildId != 0) && Context.Guild.Id == toDelete.GuildId)
|
else if ((toDelete.GuildId != null && toDelete.GuildId != 0) && Context.Guild.Id == toDelete.GuildId)
|
||||||
{
|
{
|
||||||
uow.CustomReactions.Remove(toDelete);
|
uow.CustomReactions.Remove(toDelete);
|
||||||
_service.GuildReactions.AddOrUpdate(Context.Guild.Id, new CustomReaction[] { }, (key, old) =>
|
_crs.GuildReactions.AddOrUpdate(Context.Guild.Id, new CustomReaction[] { }, (key, old) =>
|
||||||
{
|
{
|
||||||
return old.Where(cr => cr?.Id != toDelete.Id).ToArray();
|
return old.Where(cr => cr?.Id != toDelete.Id).ToArray();
|
||||||
});
|
});
|
||||||
@ -269,57 +271,6 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
public async Task CrCa(int id)
|
|
||||||
{
|
|
||||||
if ((Context.Guild == null && !_creds.IsOwner(Context.User)) ||
|
|
||||||
(Context.Guild != null && !((IGuildUser)Context.User).GuildPermissions.Administrator))
|
|
||||||
{
|
|
||||||
await ReplyErrorLocalized("insuff_perms").ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomReaction[] reactions = new CustomReaction[0];
|
|
||||||
|
|
||||||
if (Context.Guild == null)
|
|
||||||
reactions = _service.GlobalReactions;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_service.GuildReactions.TryGetValue(Context.Guild.Id, out reactions);
|
|
||||||
}
|
|
||||||
if (reactions.Any())
|
|
||||||
{
|
|
||||||
var reaction = reactions.FirstOrDefault(x => x.Id == id);
|
|
||||||
|
|
||||||
if (reaction == null)
|
|
||||||
{
|
|
||||||
await ReplyErrorLocalized("no_found_id").ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var setValue = reaction.ContainsAnywhere = !reaction.ContainsAnywhere;
|
|
||||||
|
|
||||||
using (var uow = _db.UnitOfWork)
|
|
||||||
{
|
|
||||||
uow.CustomReactions.Get(id).ContainsAnywhere = setValue;
|
|
||||||
uow.Complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setValue)
|
|
||||||
{
|
|
||||||
await ReplyConfirmLocalized("crca_enabled", Format.Code(reaction.Id.ToString())).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await ReplyConfirmLocalized("crca_disabled", Format.Code(reaction.Id.ToString())).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await ReplyErrorLocalized("no_found").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
public async Task CrDm(int id)
|
public async Task CrDm(int id)
|
||||||
{
|
{
|
||||||
@ -333,10 +284,10 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
CustomReaction[] reactions = new CustomReaction[0];
|
CustomReaction[] reactions = new CustomReaction[0];
|
||||||
|
|
||||||
if (Context.Guild == null)
|
if (Context.Guild == null)
|
||||||
reactions = _service.GlobalReactions;
|
reactions = _crs.GlobalReactions;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_service.GuildReactions.TryGetValue(Context.Guild.Id, out reactions);
|
_crs.GuildReactions.TryGetValue(Context.Guild.Id, out reactions);
|
||||||
}
|
}
|
||||||
if (reactions.Any())
|
if (reactions.Any())
|
||||||
{
|
{
|
||||||
@ -384,10 +335,10 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
CustomReaction[] reactions = new CustomReaction[0];
|
CustomReaction[] reactions = new CustomReaction[0];
|
||||||
|
|
||||||
if (Context.Guild == null)
|
if (Context.Guild == null)
|
||||||
reactions = _service.GlobalReactions;
|
reactions = _crs.GlobalReactions;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_service.GuildReactions.TryGetValue(Context.Guild.Id, out reactions);
|
_crs.GuildReactions.TryGetValue(Context.Guild.Id, out reactions);
|
||||||
}
|
}
|
||||||
if (reactions.Any())
|
if (reactions.Any())
|
||||||
{
|
{
|
||||||
@ -428,12 +379,13 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(trigger))
|
if (string.IsNullOrWhiteSpace(trigger))
|
||||||
{
|
{
|
||||||
_service.ClearStats();
|
_crs.ClearStats();
|
||||||
await ReplyConfirmLocalized("all_stats_cleared").ConfigureAwait(false);
|
await ReplyConfirmLocalized("all_stats_cleared").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_service.ReactionStats.TryRemove(trigger, out _))
|
uint throwaway;
|
||||||
|
if (_crs.ReactionStats.TryRemove(trigger, out throwaway))
|
||||||
{
|
{
|
||||||
await ReplyErrorLocalized("stats_cleared", Format.Bold(trigger)).ConfigureAwait(false);
|
await ReplyErrorLocalized("stats_cleared", Format.Bold(trigger)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -449,7 +401,7 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
{
|
{
|
||||||
if (--page < 0)
|
if (--page < 0)
|
||||||
return;
|
return;
|
||||||
var ordered = _service.ReactionStats.OrderByDescending(x => x.Value).ToArray();
|
var ordered = _crs.ReactionStats.OrderByDescending(x => x.Value).ToArray();
|
||||||
if (!ordered.Any())
|
if (!ordered.Any())
|
||||||
return;
|
return;
|
||||||
var lastPage = ordered.Length / 9;
|
var lastPage = ordered.Length / 9;
|
||||||
|
@ -1,151 +0,0 @@
|
|||||||
using Discord;
|
|
||||||
using Discord.Commands;
|
|
||||||
using Discord.WebSocket;
|
|
||||||
using NadekoBot.Extensions;
|
|
||||||
using NadekoBot.Services;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
using NadekoBot.Modules.Gambling.Common.AnimalRacing.Exceptions;
|
|
||||||
using NadekoBot.Modules.Gambling.Common.AnimalRacing;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Gambling
|
|
||||||
{
|
|
||||||
public partial class Gambling
|
|
||||||
{
|
|
||||||
[Group]
|
|
||||||
public class AnimalRacingCommands : NadekoSubmodule
|
|
||||||
{
|
|
||||||
private readonly IBotConfigProvider _bc;
|
|
||||||
private readonly CurrencyService _cs;
|
|
||||||
private readonly DiscordSocketClient _client;
|
|
||||||
|
|
||||||
|
|
||||||
public static ConcurrentDictionary<ulong, AnimalRace> AnimalRaces { get; } = new ConcurrentDictionary<ulong, AnimalRace>();
|
|
||||||
|
|
||||||
public AnimalRacingCommands(IBotConfigProvider bc, CurrencyService cs, DiscordSocketClient client)
|
|
||||||
{
|
|
||||||
_bc = bc;
|
|
||||||
_cs = cs;
|
|
||||||
_client = client;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IUserMessage raceMessage = null;
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
public Task Race()
|
|
||||||
{
|
|
||||||
var ar = new AnimalRace(_cs, _bc.BotConfig.RaceAnimals.Shuffle().ToArray());
|
|
||||||
if (!AnimalRaces.TryAdd(Context.Guild.Id, ar))
|
|
||||||
return Context.Channel.SendErrorAsync(GetText("animal_race"), GetText("animal_race_already_started"));
|
|
||||||
ar.Initialize();
|
|
||||||
|
|
||||||
ar.OnStartingFailed += Ar_OnStartingFailed;
|
|
||||||
ar.OnStateUpdate += Ar_OnStateUpdate;
|
|
||||||
ar.OnEnded += Ar_OnEnded;
|
|
||||||
ar.OnStarted += Ar_OnStarted;
|
|
||||||
|
|
||||||
return Context.Channel.SendConfirmAsync(GetText("animal_race"), GetText("animal_race_starting"),
|
|
||||||
footer: GetText("animal_race_join_instr", Prefix));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task Ar_OnStarted(AnimalRace race)
|
|
||||||
{
|
|
||||||
if(race.Users.Length == race.MaxUsers)
|
|
||||||
return Context.Channel.SendConfirmAsync(GetText("animal_race"), GetText("animal_race_full"));
|
|
||||||
else
|
|
||||||
return Context.Channel.SendConfirmAsync(GetText("animal_race"), GetText("animal_race_starting_with_x", race.Users.Length));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task Ar_OnEnded(AnimalRace race)
|
|
||||||
{
|
|
||||||
AnimalRaces.TryRemove(Context.Guild.Id, out _);
|
|
||||||
var winner = race.FinishedUsers[0];
|
|
||||||
if (race.FinishedUsers[0].Bet > 0)
|
|
||||||
{
|
|
||||||
return Context.Channel.SendConfirmAsync(GetText("animal_race"),
|
|
||||||
GetText("animal_race_won_money", Format.Bold(winner.Username),
|
|
||||||
winner.Animal.Icon, (race.FinishedUsers[0].Bet * (race.Users.Length - 1)) + _bc.BotConfig.CurrencySign));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Context.Channel.SendConfirmAsync(GetText("animal_race"),
|
|
||||||
GetText("animal_race_won", Format.Bold(winner.Username), winner.Animal.Icon));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task Ar_OnStateUpdate(AnimalRace race)
|
|
||||||
{
|
|
||||||
var text = $@"|🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🔚|
|
|
||||||
{String.Join("\n", race.Users.Select(p =>
|
|
||||||
{
|
|
||||||
var index = race.FinishedUsers.IndexOf(p);
|
|
||||||
var extra = (index == -1 ? "" : $"#{index + 1} {(index == 0 ? "🏆" : "")}");
|
|
||||||
return $"{(int)(p.Progress / 60f * 100),-2}%|{new string('‣', p.Progress) + p.Animal.Icon + extra}";
|
|
||||||
}))}
|
|
||||||
|🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🔚|";
|
|
||||||
|
|
||||||
if (raceMessage == null)
|
|
||||||
raceMessage = await Context.Channel.SendConfirmAsync(text)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
else
|
|
||||||
await raceMessage.ModifyAsync(x => x.Embed = new EmbedBuilder()
|
|
||||||
.WithTitle(GetText("animal_race"))
|
|
||||||
.WithDescription(text)
|
|
||||||
.WithOkColor()
|
|
||||||
.Build())
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task Ar_OnStartingFailed(AnimalRace race)
|
|
||||||
{
|
|
||||||
AnimalRaces.TryRemove(Context.Guild.Id, out _);
|
|
||||||
return ReplyErrorLocalized("animal_race_failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
public async Task JoinRace(int amount = 0)
|
|
||||||
{
|
|
||||||
if (!AnimalRaces.TryGetValue(Context.Guild.Id, out var ar))
|
|
||||||
{
|
|
||||||
await ReplyErrorLocalized("race_not_exist").ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var user = await ar.JoinRace(Context.User.Id, Context.User.ToString(), amount)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
if (amount > 0)
|
|
||||||
await Context.Channel.SendConfirmAsync(GetText("animal_race_join_bet", Context.User.Mention, user.Animal.Icon, amount + _bc.BotConfig.CurrencySign)).ConfigureAwait(false);
|
|
||||||
else
|
|
||||||
await Context.Channel.SendConfirmAsync(GetText("animal_race_join", Context.User.Mention, user.Animal.Icon)).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (ArgumentOutOfRangeException)
|
|
||||||
{
|
|
||||||
//ignore if user inputed an invalid amount
|
|
||||||
}
|
|
||||||
catch (AlreadyJoinedException)
|
|
||||||
{
|
|
||||||
// just ignore this
|
|
||||||
}
|
|
||||||
catch (AlreadyStartedException)
|
|
||||||
{
|
|
||||||
//ignore
|
|
||||||
}
|
|
||||||
catch (AnimalRaceFullException)
|
|
||||||
{
|
|
||||||
await Context.Channel.SendConfirmAsync(GetText("animal_race"), GetText("animal_race_full"))
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (NotEnoughFundsException)
|
|
||||||
{
|
|
||||||
await Context.Channel.SendErrorAsync(GetText("not_enough", _bc.BotConfig.CurrencySign)).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
362
src/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs
Normal file
362
src/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs
Normal file
@ -0,0 +1,362 @@
|
|||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Services;
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using NLog;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Gambling
|
||||||
|
{
|
||||||
|
public partial class Gambling
|
||||||
|
{
|
||||||
|
[Group]
|
||||||
|
public class AnimalRacing : NadekoSubmodule
|
||||||
|
{
|
||||||
|
private readonly BotConfig _bc;
|
||||||
|
private readonly CurrencyService _cs;
|
||||||
|
private readonly DiscordSocketClient _client;
|
||||||
|
|
||||||
|
|
||||||
|
public static ConcurrentDictionary<ulong, AnimalRace> AnimalRaces { get; } = new ConcurrentDictionary<ulong, AnimalRace>();
|
||||||
|
|
||||||
|
public AnimalRacing(BotConfig bc, CurrencyService cs, DiscordSocketClient client)
|
||||||
|
{
|
||||||
|
_bc = bc;
|
||||||
|
_cs = cs;
|
||||||
|
_client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task Race()
|
||||||
|
{
|
||||||
|
var ar = new AnimalRace(Context.Guild.Id, (ITextChannel)Context.Channel, Prefix,
|
||||||
|
_bc, _cs, _client,_localization, _strings);
|
||||||
|
|
||||||
|
if (ar.Fail)
|
||||||
|
await ReplyErrorLocalized("race_failed_starting").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task JoinRace(int amount = 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (amount < 0)
|
||||||
|
amount = 0;
|
||||||
|
|
||||||
|
|
||||||
|
AnimalRace ar;
|
||||||
|
if (!AnimalRaces.TryGetValue(Context.Guild.Id, out ar))
|
||||||
|
{
|
||||||
|
await ReplyErrorLocalized("race_not_exist").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await ar.JoinRace(Context.User as IGuildUser, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
//todo 85 needs to be completely isolated, shouldn't use any services in the constructor,
|
||||||
|
//then move the rest either to the module itself, or the service
|
||||||
|
public class AnimalRace
|
||||||
|
{
|
||||||
|
|
||||||
|
private ConcurrentQueue<string> animals { get; }
|
||||||
|
|
||||||
|
public bool Fail { get; set; }
|
||||||
|
|
||||||
|
private readonly List<Participant> _participants = new List<Participant>();
|
||||||
|
private readonly ulong _serverId;
|
||||||
|
private int _messagesSinceGameStarted;
|
||||||
|
private readonly string _prefix;
|
||||||
|
|
||||||
|
private readonly Logger _log;
|
||||||
|
|
||||||
|
private readonly ITextChannel _raceChannel;
|
||||||
|
private readonly BotConfig _bc;
|
||||||
|
private readonly CurrencyService _cs;
|
||||||
|
private readonly DiscordSocketClient _client;
|
||||||
|
private readonly ILocalization _localization;
|
||||||
|
private readonly NadekoStrings _strings;
|
||||||
|
|
||||||
|
public bool Started { get; private set; }
|
||||||
|
|
||||||
|
public AnimalRace(ulong serverId, ITextChannel channel, string prefix, BotConfig bc,
|
||||||
|
CurrencyService cs, DiscordSocketClient client, ILocalization localization,
|
||||||
|
NadekoStrings strings)
|
||||||
|
{
|
||||||
|
_prefix = prefix;
|
||||||
|
_bc = bc;
|
||||||
|
_cs = cs;
|
||||||
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
_serverId = serverId;
|
||||||
|
_raceChannel = channel;
|
||||||
|
_client = client;
|
||||||
|
_localization = localization;
|
||||||
|
_strings = strings;
|
||||||
|
|
||||||
|
if (!AnimalRaces.TryAdd(serverId, this))
|
||||||
|
{
|
||||||
|
Fail = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
animals = new ConcurrentQueue<string>(_bc.RaceAnimals.Select(ra => ra.Icon).Shuffle());
|
||||||
|
|
||||||
|
|
||||||
|
var cancelSource = new CancellationTokenSource();
|
||||||
|
var token = cancelSource.Token;
|
||||||
|
var fullgame = CheckForFullGameAsync(token);
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _raceChannel.SendConfirmAsync(GetText("animal_race"), GetText("animal_race_starting"),
|
||||||
|
footer: GetText("animal_race_join_instr", _prefix));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_log.Warn(ex);
|
||||||
|
}
|
||||||
|
var t = await Task.WhenAny(Task.Delay(20000, token), fullgame);
|
||||||
|
Started = true;
|
||||||
|
cancelSource.Cancel();
|
||||||
|
if (t == fullgame)
|
||||||
|
{
|
||||||
|
try { await _raceChannel.SendConfirmAsync(GetText("animal_race"), GetText("animal_race_full") ); } catch (Exception ex) { _log.Warn(ex); }
|
||||||
|
}
|
||||||
|
else if (_participants.Count > 1)
|
||||||
|
{
|
||||||
|
try { await _raceChannel.SendConfirmAsync(GetText("animal_race"), GetText("animal_race_starting_with_x", _participants.Count)); } catch (Exception ex) { _log.Warn(ex); }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try { await _raceChannel.SendErrorAsync(GetText("animal_race"), GetText("animal_race_failed")); } catch (Exception ex) { _log.Warn(ex); }
|
||||||
|
var p = _participants.FirstOrDefault();
|
||||||
|
|
||||||
|
if (p != null && p.AmountBet > 0)
|
||||||
|
await _cs.AddAsync(p.User, "BetRace", p.AmountBet, false).ConfigureAwait(false);
|
||||||
|
End();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await Task.Run(StartRace);
|
||||||
|
End();
|
||||||
|
}
|
||||||
|
catch { try { End(); } catch { } }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void End()
|
||||||
|
{
|
||||||
|
AnimalRace throwaway;
|
||||||
|
AnimalRaces.TryRemove(_serverId, out throwaway);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task StartRace()
|
||||||
|
{
|
||||||
|
var rng = new NadekoRandom();
|
||||||
|
Participant winner = null;
|
||||||
|
IUserMessage msg = null;
|
||||||
|
var place = 1;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_client.MessageReceived += Client_MessageReceived;
|
||||||
|
|
||||||
|
while (!_participants.All(p => p.Total >= 60))
|
||||||
|
{
|
||||||
|
//update the state
|
||||||
|
_participants.ForEach(p =>
|
||||||
|
{
|
||||||
|
p.Total += 1 + rng.Next(0, 10);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
_participants
|
||||||
|
.OrderByDescending(p => p.Total)
|
||||||
|
.ForEach(p =>
|
||||||
|
{
|
||||||
|
if (p.Total > 60)
|
||||||
|
{
|
||||||
|
if (winner == null)
|
||||||
|
{
|
||||||
|
winner = p;
|
||||||
|
}
|
||||||
|
p.Total = 60;
|
||||||
|
if (p.Place == 0)
|
||||||
|
p.Place = place++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//draw the state
|
||||||
|
|
||||||
|
var text = $@"|🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🔚|
|
||||||
|
{String.Join("\n", _participants.Select(p => $"{(int)(p.Total / 60f * 100),-2}%|{p.ToString()}"))}
|
||||||
|
|🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🔚|";
|
||||||
|
if (msg == null || _messagesSinceGameStarted >= 10) // also resend the message if channel was spammed
|
||||||
|
{
|
||||||
|
if (msg != null)
|
||||||
|
try { await msg.DeleteAsync(); } catch { }
|
||||||
|
_messagesSinceGameStarted = 0;
|
||||||
|
try { msg = await _raceChannel.SendMessageAsync(text).ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try { await msg.ModifyAsync(m => m.Content = text).ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(2500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_client.MessageReceived -= Client_MessageReceived;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (winner != null)
|
||||||
|
{
|
||||||
|
if (winner.AmountBet > 0)
|
||||||
|
{
|
||||||
|
var wonAmount = winner.AmountBet * (_participants.Count - 1);
|
||||||
|
|
||||||
|
await _cs.AddAsync(winner.User, "Won a Race", wonAmount, true)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
await _raceChannel.SendConfirmAsync(GetText("animal_race"),
|
||||||
|
Format.Bold(GetText("animal_race_won_money", winner.User.Mention,
|
||||||
|
winner.Animal, wonAmount + _bc.CurrencySign)))
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await _raceChannel.SendConfirmAsync(GetText("animal_race"),
|
||||||
|
Format.Bold(GetText("animal_race_won", winner.User.Mention, winner.Animal))).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task Client_MessageReceived(SocketMessage imsg)
|
||||||
|
{
|
||||||
|
var _ = Task.Run(() =>
|
||||||
|
{
|
||||||
|
var msg = imsg as SocketUserMessage;
|
||||||
|
if (msg == null)
|
||||||
|
return Task.CompletedTask;
|
||||||
|
if ((msg.Author.Id == _client.CurrentUser.Id) || !(imsg.Channel is ITextChannel) || imsg.Channel != _raceChannel)
|
||||||
|
return Task.CompletedTask;
|
||||||
|
Interlocked.Increment(ref _messagesSinceGameStarted);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
});
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CheckForFullGameAsync(CancellationToken cancelToken)
|
||||||
|
{
|
||||||
|
while (animals.Count > 0)
|
||||||
|
{
|
||||||
|
await Task.Delay(100, cancelToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task JoinRace(IGuildUser u, int amount = 0)
|
||||||
|
{
|
||||||
|
string animal;
|
||||||
|
if (!animals.TryDequeue(out animal))
|
||||||
|
{
|
||||||
|
await _raceChannel.SendErrorAsync(GetText("animal_race_no_race")).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var p = new Participant(u, animal, amount);
|
||||||
|
if (_participants.Contains(p))
|
||||||
|
{
|
||||||
|
await _raceChannel.SendErrorAsync(GetText("animal_race_already_in")).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Started)
|
||||||
|
{
|
||||||
|
await _raceChannel.SendErrorAsync(GetText("animal_race_already_started")).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (amount > 0)
|
||||||
|
if (!await _cs.RemoveAsync(u, "BetRace", amount, false).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
await _raceChannel.SendErrorAsync(GetText("not_enough", _bc.CurrencySign)).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_participants.Add(p);
|
||||||
|
string confStr;
|
||||||
|
if (amount > 0)
|
||||||
|
confStr = GetText("animal_race_join_bet", u.Mention, p.Animal, amount + _bc.CurrencySign);
|
||||||
|
else
|
||||||
|
confStr = GetText("animal_race_join", u.Mention, p.Animal);
|
||||||
|
await _raceChannel.SendConfirmAsync(GetText("animal_race"), Format.Bold(confStr)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetText(string text)
|
||||||
|
=> _strings.GetText(text,
|
||||||
|
_localization.GetCultureInfo(_raceChannel.Guild),
|
||||||
|
typeof(Gambling).Name.ToLowerInvariant());
|
||||||
|
|
||||||
|
private string GetText(string text, params object[] replacements)
|
||||||
|
=> _strings.GetText(text,
|
||||||
|
_localization.GetCultureInfo(_raceChannel.Guild),
|
||||||
|
typeof(Gambling).Name.ToLowerInvariant(),
|
||||||
|
replacements);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Participant
|
||||||
|
{
|
||||||
|
public IGuildUser User { get; }
|
||||||
|
public string Animal { get; }
|
||||||
|
public int AmountBet { get; }
|
||||||
|
|
||||||
|
public float Coeff { get; set; }
|
||||||
|
public int Total { get; set; }
|
||||||
|
|
||||||
|
public int Place { get; set; }
|
||||||
|
|
||||||
|
public Participant(IGuildUser u, string a, int amount)
|
||||||
|
{
|
||||||
|
User = u;
|
||||||
|
Animal = a;
|
||||||
|
AmountBet = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode() => User.GetHashCode();
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
var p = obj as Participant;
|
||||||
|
return p != null && p.User == User;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
var str = new string('‣', Total) + Animal;
|
||||||
|
if (Place == 0)
|
||||||
|
return str;
|
||||||
|
|
||||||
|
str += $"`#{Place}`";
|
||||||
|
|
||||||
|
if (Place == 1)
|
||||||
|
str += "🏆";
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,25 +1,23 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using NadekoBot.Common;
|
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
using NadekoBot.Common.Collections;
|
|
||||||
using NLog;
|
using NLog;
|
||||||
using System.Collections.Concurrent;
|
using NadekoBot.Services.Database.Models;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Gambling
|
namespace NadekoBot.Modules.Gambling
|
||||||
{
|
{
|
||||||
public partial class Gambling
|
public partial class Gambling
|
||||||
{
|
{
|
||||||
[Group]
|
[Group]
|
||||||
public class CurrencyEventsCommands : NadekoSubmodule
|
public class CurrencyEvents : NadekoSubmodule
|
||||||
{
|
{
|
||||||
public enum CurrencyEvent
|
public enum CurrencyEvent
|
||||||
{
|
{
|
||||||
@ -37,10 +35,10 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
|
|
||||||
private string _secretCode = string.Empty;
|
private string _secretCode = string.Empty;
|
||||||
private readonly DiscordSocketClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly IBotConfigProvider _bc;
|
private readonly BotConfig _bc;
|
||||||
private readonly CurrencyService _cs;
|
private readonly CurrencyService _cs;
|
||||||
|
|
||||||
public CurrencyEventsCommands(DiscordSocketClient client, IBotConfigProvider bc, CurrencyService cs)
|
public CurrencyEvents(DiscordSocketClient client, BotConfig bc, CurrencyService cs)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
@ -80,12 +78,12 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
_secretCode += _sneakyGameStatusChars[rng.Next(0, _sneakyGameStatusChars.Length)];
|
_secretCode += _sneakyGameStatusChars[rng.Next(0, _sneakyGameStatusChars.Length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
await _client.SetGameAsync($"type {_secretCode} for " + _bc.BotConfig.CurrencyPluralName)
|
await _client.SetGameAsync($"type {_secretCode} for " + _bc.CurrencyPluralName)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var title = GetText("sneakygamestatus_title");
|
var title = GetText("sneakygamestatus_title");
|
||||||
var desc = GetText("sneakygamestatus_desc", Format.Bold(100.ToString()) + _bc.BotConfig.CurrencySign, Format.Bold(num.ToString()));
|
var desc = GetText("sneakygamestatus_desc", Format.Bold(100.ToString()) + _bc.CurrencySign, Format.Bold(num.ToString()));
|
||||||
await context.Channel.SendConfirmAsync(title, desc).ConfigureAwait(false);
|
await context.Channel.SendConfirmAsync(title, desc).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@ -133,20 +131,20 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
amount = 100;
|
amount = 100;
|
||||||
|
|
||||||
var title = GetText("flowerreaction_title");
|
var title = GetText("flowerreaction_title");
|
||||||
var desc = GetText("flowerreaction_desc", "🌸", Format.Bold(amount.ToString()) + _bc.BotConfig.CurrencySign);
|
var desc = GetText("flowerreaction_desc", "🌸", Format.Bold(amount.ToString()) + _bc.CurrencySign);
|
||||||
var footer = GetText("flowerreaction_footer", 24);
|
var footer = GetText("flowerreaction_footer", 24);
|
||||||
var msg = await context.Channel.SendConfirmAsync(title,
|
var msg = await context.Channel.SendConfirmAsync(title,
|
||||||
desc, footer: footer)
|
desc, footer: footer)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
await new FlowerReactionEvent(_client, _cs, amount).Start(msg, context);
|
await new FlowerReactionEvent(_client, _cs).Start(msg, context, amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class CurrencyEvent
|
public abstract class CurrencyEvent
|
||||||
{
|
{
|
||||||
public abstract Task Start(IUserMessage msg, ICommandContext channel);
|
public abstract Task Start(IUserMessage msg, ICommandContext channel, int amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FlowerReactionEvent : CurrencyEvent
|
public class FlowerReactionEvent : CurrencyEvent
|
||||||
@ -162,39 +160,14 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
private CancellationTokenSource Source { get; }
|
private CancellationTokenSource Source { get; }
|
||||||
private CancellationToken CancelToken { get; }
|
private CancellationToken CancelToken { get; }
|
||||||
|
|
||||||
private readonly ConcurrentQueue<ulong> _toGiveTo = new ConcurrentQueue<ulong>();
|
public FlowerReactionEvent(DiscordSocketClient client, CurrencyService cs)
|
||||||
private readonly int _amount;
|
|
||||||
|
|
||||||
public FlowerReactionEvent(DiscordSocketClient client, CurrencyService cs, int amount)
|
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_client = client;
|
_client = client;
|
||||||
_cs = cs;
|
_cs = cs;
|
||||||
_botUser = client.CurrentUser;
|
_botUser = client.CurrentUser;
|
||||||
_amount = amount;
|
|
||||||
Source = new CancellationTokenSource();
|
Source = new CancellationTokenSource();
|
||||||
CancelToken = Source.Token;
|
CancelToken = Source.Token;
|
||||||
|
|
||||||
var _ = Task.Run(async () =>
|
|
||||||
{
|
|
||||||
|
|
||||||
var users = new List<ulong>();
|
|
||||||
while (!CancelToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
await Task.Delay(1000).ConfigureAwait(false);
|
|
||||||
while (_toGiveTo.TryDequeue(out var usrId))
|
|
||||||
{
|
|
||||||
users.Add(usrId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (users.Count > 0)
|
|
||||||
{
|
|
||||||
await _cs.AddToManyAsync("", _amount, users.ToArray()).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
users.Clear();
|
|
||||||
}
|
|
||||||
}, CancelToken);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task End()
|
private async Task End()
|
||||||
@ -218,7 +191,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task Start(IUserMessage umsg, ICommandContext context)
|
public override async Task Start(IUserMessage umsg, ICommandContext context, int amount)
|
||||||
{
|
{
|
||||||
StartingMessage = umsg;
|
StartingMessage = umsg;
|
||||||
_client.MessageDeleted += MessageDeletedEventHandler;
|
_client.MessageDeleted += MessageDeletedEventHandler;
|
||||||
@ -233,7 +206,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
catch { return; }
|
catch { return; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
using (StartingMessage.OnReaction(_client, (r) =>
|
using (StartingMessage.OnReaction(_client, async (r) =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -242,7 +215,8 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
|
|
||||||
if (r.Emote.Name == "🌸" && r.User.IsSpecified && ((DateTime.UtcNow - r.User.Value.CreatedAt).TotalDays > 5) && _flowerReactionAwardedUsers.Add(r.User.Value.Id))
|
if (r.Emote.Name == "🌸" && r.User.IsSpecified && ((DateTime.UtcNow - r.User.Value.CreatedAt).TotalDays > 5) && _flowerReactionAwardedUsers.Add(r.User.Value.Id))
|
||||||
{
|
{
|
||||||
_toGiveTo.Enqueue(r.UserId);
|
await _cs.AddAsync(r.User.Value, "Flower Reaction Event", amount, false)
|
||||||
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
@ -1,5 +1,6 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using System;
|
using System;
|
||||||
@ -8,10 +9,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Common;
|
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
using Image = ImageSharp.Image;
|
using Image = ImageSharp.Image;
|
||||||
using ImageSharp;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Gambling
|
namespace NadekoBot.Modules.Gambling
|
||||||
{
|
{
|
||||||
@ -20,8 +18,8 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
[Group]
|
[Group]
|
||||||
public class DriceRollCommands : NadekoSubmodule
|
public class DriceRollCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly Regex dndRegex = new Regex(@"^(?<n1>\d+)d(?<n2>\d+)(?:\+(?<add>\d+))?(?:\-(?<sub>\d+))?$", RegexOptions.Compiled);
|
private Regex dndRegex { get; } = new Regex(@"^(?<n1>\d+)d(?<n2>\d+)(?:\+(?<add>\d+))?(?:\-(?<sub>\d+))?$", RegexOptions.Compiled);
|
||||||
private readonly Regex fudgeRegex = new Regex(@"^(?<n1>\d+)d(?:F|f)$", RegexOptions.Compiled);
|
private Regex fudgeRegex { get; } = new Regex(@"^(?<n1>\d+)d(?:F|f)$", RegexOptions.Compiled);
|
||||||
|
|
||||||
private readonly char[] _fateRolls = { '-', ' ', '+' };
|
private readonly char[] _fateRolls = { '-', ' ', '+' };
|
||||||
private readonly IImagesService _images;
|
private readonly IImagesService _images;
|
||||||
@ -43,7 +41,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
var imageStream = await Task.Run(() =>
|
var imageStream = await Task.Run(() =>
|
||||||
{
|
{
|
||||||
var ms = new MemoryStream();
|
var ms = new MemoryStream();
|
||||||
new[] { GetDice(num1), GetDice(num2) }.Merge().SaveAsPng(ms);
|
new[] { GetDice(num1), GetDice(num2) }.Merge().Save(ms);
|
||||||
ms.Position = 0;
|
ms.Position = 0;
|
||||||
return ms;
|
return ms;
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
@ -60,7 +58,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[Priority(1)]
|
[Priority(0)]
|
||||||
public async Task Roll(int num)
|
public async Task Roll(int num)
|
||||||
{
|
{
|
||||||
await InternalRoll(num, true).ConfigureAwait(false);
|
await InternalRoll(num, true).ConfigureAwait(false);
|
||||||
@ -68,21 +66,21 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[Priority(1)]
|
[Priority(0)]
|
||||||
public async Task Rolluo(int num = 1)
|
public async Task Rolluo(int num = 1)
|
||||||
{
|
{
|
||||||
await InternalRoll(num, false).ConfigureAwait(false);
|
await InternalRoll(num, false).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[Priority(0)]
|
[Priority(1)]
|
||||||
public async Task Roll(string arg)
|
public async Task Roll(string arg)
|
||||||
{
|
{
|
||||||
await InternallDndRoll(arg, true).ConfigureAwait(false);
|
await InternallDndRoll(arg, true).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[Priority(0)]
|
[Priority(1)]
|
||||||
public async Task Rolluo(string arg)
|
public async Task Rolluo(string arg)
|
||||||
{
|
{
|
||||||
await InternallDndRoll(arg, false).ConfigureAwait(false);
|
await InternallDndRoll(arg, false).ConfigureAwait(false);
|
||||||
@ -98,7 +96,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
|
|
||||||
var rng = new NadekoRandom();
|
var rng = new NadekoRandom();
|
||||||
|
|
||||||
var dice = new List<Image<Rgba32>>(num);
|
var dice = new List<Image>(num);
|
||||||
var values = new List<int>(num);
|
var values = new List<int>(num);
|
||||||
for (var i = 0; i < num; i++)
|
for (var i = 0; i < num; i++)
|
||||||
{
|
{
|
||||||
@ -128,7 +126,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
|
|
||||||
var bitmap = dice.Merge();
|
var bitmap = dice.Merge();
|
||||||
var ms = new MemoryStream();
|
var ms = new MemoryStream();
|
||||||
bitmap.SaveAsPng(ms);
|
bitmap.Save(ms);
|
||||||
ms.Position = 0;
|
ms.Position = 0;
|
||||||
await Context.Channel.SendFileAsync(ms, "dice.png",
|
await Context.Channel.SendFileAsync(ms, "dice.png",
|
||||||
Context.User.Mention + " " +
|
Context.User.Mention + " " +
|
||||||
@ -214,7 +212,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
await ReplyConfirmLocalized("dice_rolled", Format.Bold(rolled.ToString())).ConfigureAwait(false);
|
await ReplyConfirmLocalized("dice_rolled", Format.Bold(rolled.ToString())).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Image<Rgba32> GetDice(int num)
|
private Image GetDice(int num)
|
||||||
{
|
{
|
||||||
if (num < 0 || num > 10)
|
if (num < 0 || num > 10)
|
||||||
throw new ArgumentOutOfRangeException(nameof(num));
|
throw new ArgumentOutOfRangeException(nameof(num));
|
||||||
@ -225,15 +223,15 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
using (var imgOneStream = images[1].ToStream())
|
using (var imgOneStream = images[1].ToStream())
|
||||||
using (var imgZeroStream = images[0].ToStream())
|
using (var imgZeroStream = images[0].ToStream())
|
||||||
{
|
{
|
||||||
var imgOne = Image.Load(imgOneStream);
|
Image imgOne = new Image(imgOneStream);
|
||||||
var imgZero = Image.Load(imgZeroStream);
|
Image imgZero = new Image(imgZeroStream);
|
||||||
|
|
||||||
return new[] { imgOne, imgZero }.Merge();
|
return new[] { imgOne, imgZero }.Merge();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
using (var die = _images.Dice[num].ToStream())
|
using (var die = _images.Dice[num].ToStream())
|
||||||
{
|
{
|
||||||
return Image.Load(die);
|
return new Image(die);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,15 +1,14 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Modules.Gambling.Models;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
using NadekoBot.Modules.Gambling.Common;
|
|
||||||
using Image = ImageSharp.Image;
|
using Image = ImageSharp.Image;
|
||||||
using ImageSharp;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Gambling
|
namespace NadekoBot.Modules.Gambling
|
||||||
{
|
{
|
||||||
@ -28,7 +27,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
throw new ArgumentOutOfRangeException(nameof(num));
|
throw new ArgumentOutOfRangeException(nameof(num));
|
||||||
|
|
||||||
Cards cards = guildId == null ? new Cards() : _allDecks.GetOrAdd(Context.Guild, (s) => new Cards());
|
Cards cards = guildId == null ? new Cards() : _allDecks.GetOrAdd(Context.Guild, (s) => new Cards());
|
||||||
var images = new List<Image<Rgba32>>();
|
var images = new List<Image>();
|
||||||
var cardObjects = new List<Cards.Card>();
|
var cardObjects = new List<Cards.Card>();
|
||||||
for (var i = 0; i < num; i++)
|
for (var i = 0; i < num; i++)
|
||||||
{
|
{
|
||||||
@ -47,10 +46,10 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
var currentCard = cards.DrawACard();
|
var currentCard = cards.DrawACard();
|
||||||
cardObjects.Add(currentCard);
|
cardObjects.Add(currentCard);
|
||||||
using (var stream = File.OpenRead(Path.Combine(_cardsPath, currentCard.ToString().ToLowerInvariant() + ".jpg").Replace(' ', '_')))
|
using (var stream = File.OpenRead(Path.Combine(_cardsPath, currentCard.ToString().ToLowerInvariant() + ".jpg").Replace(' ', '_')))
|
||||||
images.Add(Image.Load(stream));
|
images.Add(new Image(stream));
|
||||||
}
|
}
|
||||||
MemoryStream bitmapStream = new MemoryStream();
|
MemoryStream bitmapStream = new MemoryStream();
|
||||||
images.Merge().SaveAsPng(bitmapStream);
|
images.Merge().Save(bitmapStream);
|
||||||
bitmapStream.Position = 0;
|
bitmapStream.Position = 0;
|
||||||
|
|
||||||
var toSend = $"{Context.User.Mention}";
|
var toSend = $"{Context.User.Mention}";
|
@ -1,14 +1,13 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Common;
|
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
using Image = ImageSharp.Image;
|
using Image = ImageSharp.Image;
|
||||||
using ImageSharp;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Gambling
|
namespace NadekoBot.Modules.Gambling
|
||||||
{
|
{
|
||||||
@ -18,12 +17,12 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
public class FlipCoinCommands : NadekoSubmodule
|
public class FlipCoinCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly IImagesService _images;
|
private readonly IImagesService _images;
|
||||||
private readonly IBotConfigProvider _bc;
|
private readonly BotConfig _bc;
|
||||||
private readonly CurrencyService _cs;
|
private readonly CurrencyService _cs;
|
||||||
|
|
||||||
private readonly NadekoRandom rng = new NadekoRandom();
|
private readonly NadekoRandom rng = new NadekoRandom();
|
||||||
|
|
||||||
public FlipCoinCommands(IImagesService images, CurrencyService cs, IBotConfigProvider bc)
|
public FlipCoinCommands(IImagesService images, CurrencyService cs, BotConfig bc)
|
||||||
{
|
{
|
||||||
_images = images;
|
_images = images;
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
@ -56,7 +55,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
await ReplyErrorLocalized("flip_invalid", 10).ConfigureAwait(false);
|
await ReplyErrorLocalized("flip_invalid", 10).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var imgs = new Image<Rgba32>[count];
|
var imgs = new Image[count];
|
||||||
for (var i = 0; i < count; i++)
|
for (var i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
using (var heads = _images.Heads.ToStream())
|
using (var heads = _images.Heads.ToStream())
|
||||||
@ -64,11 +63,11 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
{
|
{
|
||||||
if (rng.Next(0, 10) < 5)
|
if (rng.Next(0, 10) < 5)
|
||||||
{
|
{
|
||||||
imgs[i] = Image.Load(heads);
|
imgs[i] = new Image(heads);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
imgs[i] = Image.Load(tails);
|
imgs[i] = new Image(tails);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,15 +87,15 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
public async Task Betflip(int amount, BetFlipGuess guess)
|
public async Task Betflip(int amount, BetFlipGuess guess)
|
||||||
{
|
{
|
||||||
if (amount < _bc.BotConfig.MinimumBetAmount)
|
if (amount < _bc.MinimumBetAmount)
|
||||||
{
|
{
|
||||||
await ReplyErrorLocalized("min_bet_limit", _bc.BotConfig.MinimumBetAmount + _bc.BotConfig.CurrencySign).ConfigureAwait(false);
|
await ReplyErrorLocalized("min_bet_limit", _bc.MinimumBetAmount + _bc.CurrencySign).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var removed = await _cs.RemoveAsync(Context.User, "Betflip Gamble", amount, false).ConfigureAwait(false);
|
var removed = await _cs.RemoveAsync(Context.User, "Betflip Gamble", amount, false).ConfigureAwait(false);
|
||||||
if (!removed)
|
if (!removed)
|
||||||
{
|
{
|
||||||
await ReplyErrorLocalized("not_enough", _bc.BotConfig.CurrencyPluralName).ConfigureAwait(false);
|
await ReplyErrorLocalized("not_enough", _bc.CurrencyPluralName).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BetFlipGuess result;
|
BetFlipGuess result;
|
||||||
@ -115,8 +114,8 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
string str;
|
string str;
|
||||||
if (guess == result)
|
if (guess == result)
|
||||||
{
|
{
|
||||||
var toWin = (int)Math.Round(amount * _bc.BotConfig.BetflipMultiplier);
|
var toWin = (int)Math.Round(amount * _bc.BetflipMultiplier);
|
||||||
str = Context.User.Mention + " " + GetText("flip_guess", toWin + _bc.BotConfig.CurrencySign);
|
str = Context.User.Mention + " " + GetText("flip_guess", toWin + _bc.CurrencySign);
|
||||||
await _cs.AddAsync(Context.User, "Betflip Gamble", toWin, false).ConfigureAwait(false);
|
await _cs.AddAsync(Context.User, "Betflip Gamble", toWin, false).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
@ -2,6 +2,8 @@
|
|||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.DataStructures;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
@ -9,18 +11,15 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Common;
|
|
||||||
using NadekoBot.Common.Attributes;
|
|
||||||
using NadekoBot.Common.Collections;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Gambling
|
namespace NadekoBot.Modules.Gambling
|
||||||
{
|
{
|
||||||
public partial class Gambling
|
public partial class Gambling
|
||||||
{
|
{
|
||||||
[Group]
|
[Group]
|
||||||
public class FlowerShopCommands : NadekoSubmodule
|
public class FlowerShop : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly IBotConfigProvider _bc;
|
private readonly BotConfig _bc;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
private readonly CurrencyService _cs;
|
private readonly CurrencyService _cs;
|
||||||
private readonly DiscordSocketClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
@ -35,7 +34,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
List
|
List
|
||||||
}
|
}
|
||||||
|
|
||||||
public FlowerShopCommands(IBotConfigProvider bc, DbService db, CurrencyService cs, DiscordSocketClient client)
|
public FlowerShop(BotConfig bc, DbService db, CurrencyService cs, DiscordSocketClient client)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
@ -59,18 +58,18 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
|
|
||||||
await Context.Channel.SendPaginatedConfirmAsync(_client, page, (curPage) =>
|
await Context.Channel.SendPaginatedConfirmAsync(_client, page, (curPage) =>
|
||||||
{
|
{
|
||||||
var theseEntries = entries.Skip(curPage * 9).Take(9).ToArray();
|
var theseEntries = entries.Skip(curPage * 9).Take(9);
|
||||||
|
|
||||||
if (!theseEntries.Any())
|
if (!theseEntries.Any())
|
||||||
return new EmbedBuilder().WithErrorColor()
|
return new EmbedBuilder().WithErrorColor()
|
||||||
.WithDescription(GetText("shop_none"));
|
.WithDescription(GetText("shop_none"));
|
||||||
var embed = new EmbedBuilder().WithOkColor()
|
var embed = new EmbedBuilder().WithOkColor()
|
||||||
.WithTitle(GetText("shop", _bc.BotConfig.CurrencySign));
|
.WithTitle(GetText("shop", _bc.CurrencySign));
|
||||||
|
|
||||||
for (int i = 0; i < theseEntries.Length; i++)
|
for (int i = 0; i < entries.Count; i++)
|
||||||
{
|
{
|
||||||
var entry = theseEntries[i];
|
var entry = entries[i];
|
||||||
embed.AddField(efb => efb.WithName($"#{curPage * 9 + i + 1} - {entry.Price}{_bc.BotConfig.CurrencySign}").WithValue(EntryToString(entry)).WithIsInline(true));
|
embed.AddField(efb => efb.WithName($"#{i + 1} - {entry.Price}{_bc.CurrencySign}").WithValue(EntryToString(entry)).WithIsInline(true));
|
||||||
}
|
}
|
||||||
return embed;
|
return embed;
|
||||||
}, entries.Count / 9, true);
|
}, entries.Count / 9, true);
|
||||||
@ -130,7 +129,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await ReplyErrorLocalized("not_enough", _bc.BotConfig.CurrencySign).ConfigureAwait(false);
|
await ReplyErrorLocalized("not_enough", _bc.CurrencySign).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -186,7 +185,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await ReplyErrorLocalized("not_enough", _bc.BotConfig.CurrencySign).ConfigureAwait(false);
|
await ReplyErrorLocalized("not_enough", _bc.CurrencySign).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user