commit
cd9a7cfdbf
20
Dockerfile
Normal file
20
Dockerfile
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
FROM microsoft/dotnet:sdk
|
||||||
|
MAINTAINER Poag <poag@gany.net>
|
||||||
|
|
||||||
|
WORKDIR /opt/
|
||||||
|
|
||||||
|
#Install required software
|
||||||
|
RUN echo "deb http://www.deb-multimedia.org jessie main non-free" | tee /etc/apt/sources.list.d/debian-backports.list \
|
||||||
|
&& apt-get update \
|
||||||
|
&& apt-get install -y --force-yes deb-multimedia-keyring \
|
||||||
|
&& apt-get update \
|
||||||
|
&& apt-get install -y git libopus0 opus-tools libopus-dev libsodium-dev ffmpeg
|
||||||
|
|
||||||
|
#Download and install stable version of Nadeko
|
||||||
|
RUN curl -L https://github.com/Kwoth/NadekoBot-BashScript/raw/master/nadeko_installer_latest.sh | sh \
|
||||||
|
&& curl -L https://github.com/Kwoth/NadekoBot-BashScript/raw/master/nadeko_autorestart.sh > nadeko.sh \
|
||||||
|
&& chmod 755 nadeko.sh
|
||||||
|
|
||||||
|
VOLUME ["/opt"]
|
||||||
|
|
||||||
|
CMD ["/opt/nadeko.sh"]
|
@ -1,14 +1,14 @@
|
|||||||
![img](https://ci.appveyor.com/api/projects/status/gmu6b3ltc80hr3k9?svg=true)
|
![img](https://ci.appveyor.com/api/projects/status/gmu6b3ltc80hr3k9?svg=true)
|
||||||
[![Discord](https://discordapp.com/api/guilds/117523346618318850/widget.png)](https://discord.gg/0ehQwTK2RBjAxzEY)
|
[![Discord](https://discordapp.com/api/guilds/117523346618318850/widget.png)](https://discord.gg/0ehQwTK2RBjAxzEY)
|
||||||
[![Documentation Status](https://readthedocs.org/projects/nadekobot/badge/?version=latest)](http://nadekobot.readthedocs.io/en/1.0/?badge=latest)
|
[![Documentation Status](https://readthedocs.org/projects/nadekobot/badge/?version=latest)](http://nadekobot.readthedocs.io/en/latest/?badge=latest)
|
||||||
# NadekoBot
|
# NadekoBot
|
||||||
[![nadeko1](https://cdn.discordapp.com/attachments/155726317222887425/252095170676391936/A1.jpg)](https://discordapp.com/oauth2/authorize?client_id=170254782546575360&scope=bot&permissions=66186303)
|
[![nadeko1](https://cdn.discordapp.com/attachments/155726317222887425/252095170676391936/A1.jpg)](https://discordapp.com/oauth2/authorize?client_id=170254782546575360&scope=bot&permissions=66186303)
|
||||||
[![nadeko2](https://cdn.discordapp.com/attachments/155726317222887425/252095207514832896/A2.jpg)](http://nadekobot.readthedocs.io/en/1.0/Commands%20List/)
|
[![nadeko2](https://cdn.discordapp.com/attachments/155726317222887425/252095207514832896/A2.jpg)](http://nadekobot.readthedocs.io/en/latest/Commands%20List/)
|
||||||
|
|
||||||
##For Update, Help and Guidlines
|
##For Update, Help and Guidlines
|
||||||
|
|
||||||
`Follow me on twitter for updates. | Join my Discord server if you need help. | Read the Docs for hosting guides.`
|
`Follow me on twitter for updates. | Join my Discord server if you need help. | Read the Docs for hosting guides.`
|
||||||
|
|
||||||
[![twitter](https://cdn.discordapp.com/attachments/155726317222887425/252192520094613504/twiter_banner.JPG)](https://twitter.com/TheNadekoBot) [![discord](https://cdn.discordapp.com/attachments/155726317222887425/252192415673221122/discord_banner.JPG)](https://discord.gg/0ehQwTK2RBjAxzEY) [![Wiki](https://cdn.discordapp.com/attachments/155726317222887425/252192472849973250/read_the_docs_banner.JPG)](http://nadekobot.readthedocs.io/en/1.0/)
|
[![twitter](https://cdn.discordapp.com/attachments/155726317222887425/252192520094613504/twiter_banner.JPG)](https://twitter.com/TheNadekoBot) [![discord](https://cdn.discordapp.com/attachments/155726317222887425/252192415673221122/discord_banner.JPG)](https://discord.gg/0ehQwTK2RBjAxzEY) [![Wiki](https://cdn.discordapp.com/attachments/155726317222887425/252192472849973250/read_the_docs_banner.JPG)](http://nadekobot.readthedocs.io/en/latest/)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 48b66d55f3f26f60fc001123ff6d7afeade3a51d
|
Subproject commit 508026d5d4f4d8780d983c63ab25e4c15ad69e59
|
@ -10,6 +10,7 @@ You can support the project on patreon: <https://patreon.com/nadekobot> or paypa
|
|||||||
- [Music](#music)
|
- [Music](#music)
|
||||||
- [NSFW](#nsfw)
|
- [NSFW](#nsfw)
|
||||||
- [Permissions](#permissions)
|
- [Permissions](#permissions)
|
||||||
|
- [Pokemon](#pokemon)
|
||||||
- [Searches](#searches)
|
- [Searches](#searches)
|
||||||
- [Utility](#utility)
|
- [Utility](#utility)
|
||||||
|
|
||||||
@ -28,13 +29,6 @@ Command and aliases | Description | Usage
|
|||||||
`.ban` `.b` | Bans a user by ID or name with an optional message. **Requires BanMembers server permission.** | `.b "@some Guy" Your behaviour is toxic.`
|
`.ban` `.b` | Bans a user by ID or name with an optional message. **Requires BanMembers server permission.** | `.b "@some Guy" Your behaviour is toxic.`
|
||||||
`.softban` `.sb` | Bans and then unbans a user by ID or name with an optional message. **Requires KickMembers server permission.** **Requires ManageMessages server permission.** | `.sb "@some Guy" Your behaviour is toxic.`
|
`.softban` `.sb` | Bans and then unbans a user by ID or name with an optional message. **Requires KickMembers server permission.** **Requires ManageMessages server permission.** | `.sb "@some Guy" Your behaviour is toxic.`
|
||||||
`.kick` `.k` | Kicks a mentioned user. **Requires KickMembers server permission.** | `.k "@some Guy" Your behaviour is toxic.`
|
`.kick` `.k` | Kicks a mentioned user. **Requires KickMembers server permission.** | `.k "@some Guy" Your behaviour is toxic.`
|
||||||
`.setmuterole` | Sets a name of the role which will be assigned to people who should be muted. Default is nadeko-mute. **Requires ManageRoles server permission.** | `.setmuterole Silenced`
|
|
||||||
`.mute` | Mutes a mentioned user both from speaking and chatting. **Requires ManageRoles server permission.** **Requires MuteMembers server permission.** | `.mute @Someone`
|
|
||||||
`.unmute` | Unmutes a mentioned user previously muted with `.mute` command. **Requires ManageRoles server permission.** **Requires MuteMembers server permission.** | `.unmute @Someone`
|
|
||||||
`.chatmute` | Prevents a mentioned user from chatting in text channels. **Requires ManageRoles server permission.** | `.chatmute @Someone`
|
|
||||||
`.chatunmute` | Removes a mute role previously set on a mentioned user with `.chatmute` which prevented him from chatting in text channels. **Requires ManageRoles server permission.** | `.chatunmute @Someone`
|
|
||||||
`.voicemute` | Prevents a mentioned user from speaking in voice channels. **Requires MuteMembers server permission.** | `.voicemute @Someone`
|
|
||||||
`.voiceunmute` | Gives a previously voice-muted user a permission to speak. **Requires MuteMembers server permission.** | `.voiceunmute @Someguy`
|
|
||||||
`.deafen` `.deaf` | Deafens mentioned user or users. **Requires DeafenMembers server permission.** | `.deaf "@Someguy"` or `.deaf "@Someguy" "@Someguy"`
|
`.deafen` `.deaf` | Deafens mentioned user or users. **Requires DeafenMembers server permission.** | `.deaf "@Someguy"` or `.deaf "@Someguy" "@Someguy"`
|
||||||
`.undeafen` `.undef` | Undeafens mentioned user or users. **Requires DeafenMembers server permission.** | `.undef "@Someguy"` or `.undef "@Someguy" "@Someguy"`
|
`.undeafen` `.undef` | Undeafens mentioned user or users. **Requires DeafenMembers server permission.** | `.undef "@Someguy"` or `.undef "@Someguy" "@Someguy"`
|
||||||
`.delvoichanl` `.dvch` | Deletes a voice channel with a given name. **Requires ManageChannels server permission.** | `.dvch VoiceChannelName`
|
`.delvoichanl` `.dvch` | Deletes a voice channel with a given name. **Requires ManageChannels server permission.** | `.dvch VoiceChannelName`
|
||||||
@ -63,13 +57,20 @@ Command and aliases | Description | Usage
|
|||||||
`.lcsc` | Leaves Cross server channel instance from this channel. **Requires ManageServer server permission.** | `.lcsc`
|
`.lcsc` | Leaves Cross server channel instance from this channel. **Requires ManageServer server permission.** | `.lcsc`
|
||||||
`.fwmsgs` | Toggles forwarding of non-command messages sent to bot's DM to the bot owners **Bot Owner only.** | `.fwmsgs`
|
`.fwmsgs` | Toggles forwarding of non-command messages sent to bot's DM to the bot owners **Bot Owner only.** | `.fwmsgs`
|
||||||
`.fwtoall` | Toggles whether messages will be forwarded to all bot owners or only to the first one specified in the credentials.json **Bot Owner only.** | `.fwtoall`
|
`.fwtoall` | Toggles whether messages will be forwarded to all bot owners or only to the first one specified in the credentials.json **Bot Owner only.** | `.fwtoall`
|
||||||
`.logserver` | Logs server activity in this channel. **Requires Administrator server permission.** **Bot Owner only.** | `.logserver`
|
`.logserver` | Enables or Disables ALL log events. If enabled, all log events will log to this channel. **Requires Administrator server permission.** **Bot Owner only.** | `.logserver enable` or `.logserver disable`
|
||||||
`.logignore` | Toggles whether the .logserver command ignores this channel. Useful if you have hidden admin channel and public log channel. **Requires Administrator server permission.** **Bot Owner only.** | `.logignore`
|
`.logignore` | Toggles whether the .logserver command ignores this channel. Useful if you have hidden admin channel and public log channel. **Requires Administrator server permission.** **Bot Owner only.** | `.logignore`
|
||||||
`.userpresence` | Starts logging to this channel when someone from the server goes online/offline/idle. **Requires Administrator server permission.** | `.userpresence`
|
`.logevents` | Shows a list of all events you can subscribe to with `.log` **Requires Administrator server permission.** **Bot Owner only.** | `.logevents`
|
||||||
`.voicepresence` | Toggles logging to this channel whenever someone joins or leaves a voice channel you are currently in. **Requires Administrator server permission.** | `.voicepresence`
|
`.log` | Toggles logging event. Disables it if it's active anywhere on the server. Enables if it's not active. Use `.logevents` to see a lit of all events you can subscribe to. **Requires Administrator server permission.** **Bot Owner only.** | `.log userpresence` or `.log userbanned`
|
||||||
`.repeatinvoke` `.repinv` | Immediately shows the repeat message and restarts the timer. **Requires ManageMessages server permission.** | `.repinv`
|
`.repeatinvoke` `.repinv` | Immediately shows the repeat message and restarts the timer. **Requires ManageMessages server permission.** | `.repinv`
|
||||||
`.repeat` | Repeat a message every X minutes. If no parameters are specified, repeat is disabled. **Requires ManageMessages server permission.** | `.repeat 5 Hello there`
|
`.repeat` | Repeat a message every X minutes. If no parameters are specified, repeat is disabled. **Requires ManageMessages server permission.** | `.repeat 5 Hello there`
|
||||||
`.migratedata` | Migrate data from old bot configuration **Bot Owner only.** | `.migratedata`
|
`.migratedata` | Migrate data from old bot configuration **Bot Owner only.** | `.migratedata`
|
||||||
|
`.setmuterole` | Sets a name of the role which will be assigned to people who should be muted. Default is nadeko-mute. **Requires ManageRoles server permission.** | `.setmuterole Silenced`
|
||||||
|
`.mute` | Mutes a mentioned user both from speaking and chatting. **Requires ManageRoles server permission.** **Requires MuteMembers server permission.** | `.mute @Someone`
|
||||||
|
`.unmute` | Unmutes a mentioned user previously muted with `.mute` command. **Requires ManageRoles server permission.** **Requires MuteMembers server permission.** | `.unmute @Someone`
|
||||||
|
`.chatmute` | Prevents a mentioned user from chatting in text channels. **Requires ManageRoles server permission.** | `.chatmute @Someone`
|
||||||
|
`.chatunmute` | Removes a mute role previously set on a mentioned user with `.chatmute` which prevented him from chatting in text channels. **Requires ManageRoles server permission.** | `.chatunmute @Someone`
|
||||||
|
`.voicemute` | Prevents a mentioned user from speaking in voice channels. **Requires MuteMembers server permission.** | `.voicemute @Someone`
|
||||||
|
`.voiceunmute` | Gives a previously voice-muted user a permission to speak. **Requires MuteMembers server permission.** | `.voiceunmute @Someguy`
|
||||||
`.rotateplaying` `.ropl` | Toggles rotation of playing status of the dynamic strings you previously specified. **Bot Owner only.** | `.ropl`
|
`.rotateplaying` `.ropl` | Toggles rotation of playing status of the dynamic strings you previously specified. **Bot Owner only.** | `.ropl`
|
||||||
`.addplaying` `.adpl` | Adds a specified string to the list of playing strings to rotate. Supported placeholders: %servers%, %users%, %playing%, %queued% **Bot Owner only.** | `.adpl`
|
`.addplaying` `.adpl` | Adds a specified string to the list of playing strings to rotate. Supported placeholders: %servers%, %users%, %playing%, %queued% **Bot Owner only.** | `.adpl`
|
||||||
`.listplaying` `.lipl` | Lists all playing statuses with their corresponding number. **Bot Owner only.** | `.lipl`
|
`.listplaying` `.lipl` | Lists all playing statuses with their corresponding number. **Bot Owner only.** | `.lipl`
|
||||||
@ -89,7 +90,7 @@ Command and aliases | Description | Usage
|
|||||||
`.greetdm` | Toggles whether the greet messages will be sent in a DM (This is separate from greet - you can have both, any or neither enabled). **Requires ManageServer server permission.** | `.greetdm`
|
`.greetdm` | Toggles whether the greet messages will be sent in a DM (This is separate from greet - you can have both, any or neither enabled). **Requires ManageServer server permission.** | `.greetdm`
|
||||||
`.greetdmmsg` | Sets a new join announcement message which will be sent to the user who joined. Type %user% if you want to mention the new member. Using it with no message will show the current DM greet message. **Requires ManageServer server permission.** | `.greetdmmsg Welcome to the server, %user%`.
|
`.greetdmmsg` | Sets a new join announcement message which will be sent to the user who joined. Type %user% if you want to mention the new member. Using it with no message will show the current DM greet message. **Requires ManageServer server permission.** | `.greetdmmsg Welcome to the server, %user%`.
|
||||||
`.bye` | Toggles anouncements on the current channel when someone leaves the server. **Requires ManageServer server permission.** | `.bye`
|
`.bye` | Toggles anouncements on the current channel when someone leaves the server. **Requires ManageServer server permission.** | `.bye`
|
||||||
`.byemsg` | Sets a new leave announcement message. Type %user% if you want to mention the new member. Using it with no message will show the current bye message. **Requires ManageServer server permission.** | `.byemsg %user% has left.`
|
`.byemsg` | Sets a new leave announcement message. Type %user% if you want to show the name the user who left. Type %id% to show id. Using this command with no message will show the current bye message. **Requires ManageServer server permission.** | `.byemsg %user% has left.`
|
||||||
`.byedel` | Sets the time it takes (in seconds) for bye messages to be auto-deleted. Set 0 to disable automatic deletion. **Requires ManageServer server permission.** | `.byedel 0` or `.byedel 30`
|
`.byedel` | Sets the time it takes (in seconds) for bye messages to be auto-deleted. Set 0 to disable automatic deletion. **Requires ManageServer server permission.** | `.byedel 0` or `.byedel 30`
|
||||||
`.voice+text` `.v+t` | Creates a text channel for each voice channel only users in that voice channel can see.If you are server owner, keep in mind you will see them all the time regardless. **Requires ManageRoles server permission.** **Requires ManageChannels server permission.** | `.voice+text`
|
`.voice+text` `.v+t` | Creates a text channel for each voice channel only users in that voice channel can see.If you are server owner, keep in mind you will see them all the time regardless. **Requires ManageRoles server permission.** **Requires ManageChannels server permission.** | `.voice+text`
|
||||||
`.cleanvplust` `.cv+t` | Deletes all text channels ending in `-voice` for which voicechannels are not found. Use at your own risk. **Requires ManageChannels server permission.** **Requires ManageRoles server permission.** | `.cleanv+t`
|
`.cleanvplust` `.cv+t` | Deletes all text channels ending in `-voice` for which voicechannels are not found. Use at your own risk. **Requires ManageChannels server permission.** **Requires ManageRoles server permission.** | `.cleanv+t`
|
||||||
@ -119,6 +120,8 @@ Command 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 priviledges 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 priviledges and removes server custom reaction. | `.dcr 5`
|
||||||
|
`.crstatsclear` | Resets the counters on `.crstats`. You can specify a trigger to clear stats only for that trigger. | `.crstatsclear` or `.crstatsclear rng`
|
||||||
|
`.crstats` | Shows a list of custom reactions and the number of times they have been executed. Paginated with 10 per page. Use `.crstatsclear` to reset the counters. | `.crstats` or `.crstats 3`
|
||||||
|
|
||||||
###### [Back to TOC](#table-of-contents)
|
###### [Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
@ -134,7 +137,7 @@ Command and aliases | Description | Usage
|
|||||||
`$leaderboard` `$lb` | Displays bot currency leaderboard. | `$lb`
|
`$leaderboard` `$lb` | Displays bot currency leaderboard. | `$lb`
|
||||||
`$race` | Starts a new animal race. | `$race`
|
`$race` | Starts a new animal race. | `$race`
|
||||||
`$joinrace` `$jr` | Joins a new race. You can specify an amount of currency for betting (optional). You will get YourBet*(participants-1) back if you win. | `$jr` or `$jr 5`
|
`$joinrace` `$jr` | Joins a new race. You can specify an amount of currency for betting (optional). You will get YourBet*(participants-1) back if you win. | `$jr` or `$jr 5`
|
||||||
`$roll` | Rolls 0-100. If you supply a number [x] it rolls up to 30 normal dice. If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | `$roll` or `$roll 7` or `$roll 3d5`
|
`$roll` | Rolls 0-100. If you supply a number [x] it rolls up to 30 normal dice. If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. Y can be a letter 'F' if you want to roll fate dice instead of dnd. | `$roll` or `$roll 7` or `$roll 3d5` or `$roll 5dF`
|
||||||
`$rolluo` | Rolls X normal dice (up to 30) unordered. If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | `$rolluo` or `$rolluo 7` or `$rolluo 3d5`
|
`$rolluo` | Rolls X normal dice (up to 30) unordered. If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | `$rolluo` or `$rolluo 7` or `$rolluo 3d5`
|
||||||
`$nroll` | Rolls in a given range. | `$nroll 5` (rolls 0-5) or `$nroll 5-15`
|
`$nroll` | Rolls in a given range. | `$nroll 5` (rolls 0-5) or `$nroll 5-15`
|
||||||
`$draw` | Draws a card from the deck.If you supply number X, she draws up to 5 cards from the deck. | `$draw` or `$draw 5`
|
`$draw` | Draws a card from the deck.If you supply number X, she draws up to 5 cards from the deck. | `$draw` or `$draw 5`
|
||||||
@ -155,8 +158,11 @@ Command and aliases | Description | Usage
|
|||||||
`>poll` | Creates a poll which requires users to send the number of the voting option to the bot. **Requires ManageMessages server permission.** | `>poll Question?;Answer1;Answ 2;A_3`
|
`>poll` | Creates a poll which requires users to send the number of the voting option to the bot. **Requires ManageMessages server permission.** | `>poll Question?;Answer1;Answ 2;A_3`
|
||||||
`>publicpoll` `>ppoll` | Creates a public poll which requires users to type a number of the voting option in the channel command is ran in. **Requires ManageMessages server permission.** | `>ppoll Question?;Answer1;Answ 2;A_3`
|
`>publicpoll` `>ppoll` | Creates a public poll which requires users to type a number of the voting option in the channel command is ran in. **Requires ManageMessages server permission.** | `>ppoll Question?;Answer1;Answ 2;A_3`
|
||||||
`>pollend` | Stops active poll on this server and prints the results in this channel. **Requires ManageMessages server permission.** | `>pollend`
|
`>pollend` | Stops active poll on this server and prints the results in this channel. **Requires ManageMessages server permission.** | `>pollend`
|
||||||
|
`>acrophobia` `>acro` | Starts an Acrophobia game. Second argment 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`
|
||||||
`>pick` | Picks the currency planted in this channel. | `>pick`
|
`>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`
|
||||||
|
`>pick` | Picks the currency planted in this channel. 60 seconds cooldown. | `>pick`
|
||||||
`>plant` | Spend a unit of currency to plant it in this channel. (If bot is restarted or crashes, the currency will be lost) | `>plant`
|
`>plant` | Spend a unit of currency to plant it in this channel. (If bot is restarted or crashes, the currency will be lost) | `>plant`
|
||||||
`>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`
|
||||||
`>typestart` | Starts a typing contest. | `>typestart`
|
`>typestart` | Starts a typing contest. | `>typestart`
|
||||||
@ -189,6 +195,7 @@ Command and aliases | Description | Usage
|
|||||||
`!!stop` `!!s` | Stops the music and clears the playlist. 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`
|
||||||
|
`!!fairplay` `!!fp` | Toggles fairplay. While enabled, music player will prioritize songs from users who didn't have their song recently played instead of the song's position in the queue. | `!!fp`
|
||||||
`!!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`
|
||||||
`!!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`
|
||||||
`!!listqueue` `!!lq` | Lists 15 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`
|
||||||
@ -205,14 +212,14 @@ Command and aliases | Description | Usage
|
|||||||
`!!remove` `!!rm` | Remove a song by its # in the queue, or 'all' to remove whole queue. | `!!rm 5`
|
`!!remove` `!!rm` | Remove a song by its # in the queue, or 'all' to remove whole queue. | `!!rm 5`
|
||||||
`!!movesong` `!!ms` | Moves a song from one position to another. | `!!ms 5>3`
|
`!!movesong` `!!ms` | Moves a song from one position to another. | `!!ms 5>3`
|
||||||
`!!setmaxqueue` `!!smq` | Sets a maximum queue size. Supply 0 or no argument to have no limit. | `!!smq 50` or `!!smq`
|
`!!setmaxqueue` `!!smq` | Sets a maximum queue size. Supply 0 or no argument to have no limit. | `!!smq 50` or `!!smq`
|
||||||
|
`!!setmaxplaytime` `!!smp` | Sets a maximum number of seconds (>14) a song can run before being skipped automatically. Set 0 to have no limit. | `!!smp 0` or `!!smp 270`
|
||||||
`!!reptcursong` `!!rcs` | Toggles repeat of current song. | `!!rcs`
|
`!!reptcursong` `!!rcs` | Toggles repeat of current song. | `!!rcs`
|
||||||
`!!rpeatplaylst` `!!rpl` | Toggles repeat of all songs in the queue (every song that finishes is added to the end of the queue). | `!!rpl`
|
`!!rpeatplaylst` `!!rpl` | Toggles repeat of all songs in the queue (every song that finishes is added to the end of the queue). | `!!rpl`
|
||||||
`!!save` | Saves a playlist under a certain name. Name must be no longer than 20 characters and mustn't contain dashes. | `!!save classical1`
|
`!!save` | Saves a playlist under a certain name. Name must be no longer than 20 characters and mustn't contain dashes. | `!!save classical1`
|
||||||
`!!load` | Loads a playlist under a certain name. | `!!load classical-1`
|
`!!load` | Loads a saved playlist using it's ID. Use `!!pls` to list all saved playlists and !!save to save new ones. | `!!load 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. Only if you made it or if you are the bot owner. | `!!delpls animu-5`
|
`!!deleteplaylist` `!!delpls` | Deletes a saved playlist. Only if you made it or if you are the bot owner. | `!!delpls animu-5`
|
||||||
`!!goto` | Goes to a specific time in seconds in a song. | `!!goto 30`
|
`!!goto` | Goes to a specific time in seconds in a song. | `!!goto 30`
|
||||||
`!!getlink` `!!gl` | Shows a link to the song in the queue by index, or the currently playing song by default. | `!!gl`
|
|
||||||
`!!autoplay` `!!ap` | Toggles autoplay - When the song is finished, automatically queue a related youtube song. (Works only for youtube songs and when queue is empty) | `!!ap`
|
`!!autoplay` `!!ap` | Toggles autoplay - When the song is finished, automatically queue a related youtube song. (Works only for youtube songs and when queue is empty) | `!!ap`
|
||||||
|
|
||||||
###### [Back to TOC](#table-of-contents)
|
###### [Back to TOC](#table-of-contents)
|
||||||
@ -222,8 +229,8 @@ Command and aliases | Description | Usage
|
|||||||
----------------|--------------|-------
|
----------------|--------------|-------
|
||||||
`~hentai` | Shows a hentai image from a random website (gelbooru or danbooru or konachan or atfbooru or yandere) with a given tag. Tag is optional but preferred. Only 1 tag allowed. | `~hentai yuri`
|
`~hentai` | Shows a hentai image from a random website (gelbooru or danbooru or konachan or atfbooru or yandere) with a given tag. Tag is optional but preferred. Only 1 tag allowed. | `~hentai yuri`
|
||||||
`~hentaibomb` | Shows a total 5 images (from gelbooru, danbooru, konachan, yandere and atfbooru). Tag is optional but preferred. | `~hentaibomb yuri`
|
`~hentaibomb` | Shows a total 5 images (from gelbooru, danbooru, konachan, yandere and atfbooru). Tag is optional but preferred. | `~hentaibomb yuri`
|
||||||
`~yandere` | Shows a random image from yandere with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~yandere tag1+tag2`
|
|
||||||
`~danbooru` | Shows a random hentai image from danbooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~danbooru yuri+kissing`
|
`~danbooru` | Shows a random hentai image from danbooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~danbooru yuri+kissing`
|
||||||
|
`~yandere` | Shows a random image from yandere with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~yandere tag1+tag2`
|
||||||
`~konachan` | Shows a random hentai image from konachan with a given tag. Tag is optional but preferred. | `~konachan yuri`
|
`~konachan` | Shows a random hentai image from konachan with a given tag. Tag is optional but preferred. | `~konachan yuri`
|
||||||
`~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`
|
||||||
`~rule34` | Shows a random image from rule34.xx with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~rule34 yuri+kissing`
|
`~rule34` | Shows a random image from rule34.xx with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~rule34 yuri+kissing`
|
||||||
@ -243,13 +250,13 @@ Command and aliases | Description | Usage
|
|||||||
`;removeperm` `;rp` | Removes a permission from a given position in Permissions list. | `;rp 1`
|
`;removeperm` `;rp` | Removes a permission from a given position in Permissions list. | `;rp 1`
|
||||||
`;moveperm` `;mp` | Moves permission from one position to another in Permissions list. | `;mp 2 4`
|
`;moveperm` `;mp` | Moves permission from one position to another in Permissions list. | `;mp 2 4`
|
||||||
`;srvrcmd` `;sc` | Sets a command's permission at the server level. | `;sc "command name" disable`
|
`;srvrcmd` `;sc` | Sets a command's permission at the server level. | `;sc "command name" disable`
|
||||||
`;srvrmdl` `;sm` | Sets a module's permission at the server level. | `;sm "module name" enable`
|
`;srvrmdl` `;sm` | Sets a module's permission at the server level. | `;sm ModuleName enable`
|
||||||
`;usrcmd` `;uc` | Sets a command's permission at the user level. | `;uc "command name" enable SomeUsername`
|
`;usrcmd` `;uc` | Sets a command's permission at the user level. | `;uc "command name" enable SomeUsername`
|
||||||
`;usrmdl` `;um` | Sets a module's permission at the user level. | `;um "module name" enable SomeUsername`
|
`;usrmdl` `;um` | Sets a module's permission at the user level. | `;um ModuleName enable SomeUsername`
|
||||||
`;rolecmd` `;rc` | Sets a command's permission at the role level. | `;rc "command name" disable MyRole`
|
`;rolecmd` `;rc` | Sets a command's permission at the role level. | `;rc "command name" disable MyRole`
|
||||||
`;rolemdl` `;rm` | Sets a module's permission at the role level. | `;rm "module name" enable MyRole`
|
`;rolemdl` `;rm` | Sets a module's permission at the role level. | `;rm ModuleName enable MyRole`
|
||||||
`;chnlcmd` `;cc` | Sets a command's permission at the channel level. | `;cc "command name" enable SomeChannel`
|
`;chnlcmd` `;cc` | Sets a command's permission at the channel level. | `;cc "command name" enable SomeChannel`
|
||||||
`;chnlmdl` `;cm` | Sets a module's permission at the channel level. | `;cm "module name" enable SomeChannel`
|
`;chnlmdl` `;cm` | Sets a module's permission at the channel level. | `;cm ModuleName enable SomeChannel`
|
||||||
`;allchnlmdls` `;acm` | Enable or disable all modules in a specified channel. | `;acm enable #SomeChannel`
|
`;allchnlmdls` `;acm` | Enable or disable all modules in a specified channel. | `;acm enable #SomeChannel`
|
||||||
`;allrolemdls` `;arm` | Enable or disable all modules for a specific role. | `;arm [enable/disable] MyRole`
|
`;allrolemdls` `;arm` | Enable or disable all modules for a specific role. | `;arm [enable/disable] MyRole`
|
||||||
`;allusrmdls` `;aum` | Enable or disable all modules for a specific user. | `;aum enable @someone`
|
`;allusrmdls` `;aum` | Enable or disable all modules for a specific user. | `;aum enable @someone`
|
||||||
@ -268,10 +275,21 @@ Command and aliases | Description | Usage
|
|||||||
|
|
||||||
###### [Back to TOC](#table-of-contents)
|
###### [Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
### Pokemon
|
||||||
|
Command and aliases | Description | Usage
|
||||||
|
----------------|--------------|-------
|
||||||
|
`>attack` | Attacks a target with the given move. Use `>movelist` to see a list of moves your type can use. | `>attack "vine whip" @someguy`
|
||||||
|
`>movelist` `>ml` | Lists the moves you are able to use | `>ml`
|
||||||
|
`>heal` | Heals someone. Revives those who fainted. Costs a NadekoFlower | `>heal @someone`
|
||||||
|
`>type` | Get the poketype of the target. | `>type @someone`
|
||||||
|
`>settype` | Set your poketype. Costs a NadekoFlower. Provide no arguments to see a list of available types. | `>settype fire` or `>settype`
|
||||||
|
|
||||||
|
###### [Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
### Searches
|
### Searches
|
||||||
Command and aliases | Description | Usage
|
Command and aliases | Description | Usage
|
||||||
----------------|--------------|-------
|
----------------|--------------|-------
|
||||||
`~weather` `~we` | Shows weather data for a specified city and a country. BOTH ARE REQUIRED. Use country abbrevations. | `~we Moscow RF`
|
`~weather` `~we` | Shows weather data for a specified city. You can also specify a country after a comma. | `~we Moscow, RU`
|
||||||
`~youtube` `~yt` | Searches youtubes and shows the first result | `~yt query`
|
`~youtube` `~yt` | Searches youtubes and shows the first result | `~yt query`
|
||||||
`~imdb` `~omdb` | Queries omdb for movies or series, show first result. | `~imdb Batman vs Superman`
|
`~imdb` `~omdb` | Queries omdb for movies or series, show first result. | `~imdb Batman vs Superman`
|
||||||
`~randomcat` `~meow` | Shows a random cat image. | `~meow`
|
`~randomcat` `~meow` | Shows a random cat image. | `~meow`
|
||||||
@ -283,7 +301,9 @@ Command and aliases | Description | Usage
|
|||||||
`~google` `~g` | Get a google search link for some terms. | `~google query`
|
`~google` `~g` | Get a google search link for some terms. | `~google query`
|
||||||
`~magicthegathering` `~mtg` | Searches for a Magic The Gathering card. | `~magicthegathering about face` or `~mtg about face`
|
`~magicthegathering` `~mtg` | Searches for a Magic The Gathering card. | `~magicthegathering about face` or `~mtg about face`
|
||||||
`~hearthstone` `~hs` | Searches for a Hearthstone card and shows its image. Takes a while to complete. | `~hs Ysera`
|
`~hearthstone` `~hs` | Searches for a Hearthstone card and shows its image. Takes a while to complete. | `~hs Ysera`
|
||||||
|
`~yodify` `~yoda` | Translates your normal sentences into Yoda styled sentences! | ~yodify I was once an adventurer like you` or `~yoda my feelings hurt`
|
||||||
`~urbandict` `~ud` | Searches Urban Dictionary for a word. | `~ud Pineapple`
|
`~urbandict` `~ud` | Searches Urban Dictionary for a word. | `~ud Pineapple`
|
||||||
|
`~define` `~def` | Finds a definition of a word. | `~def heresy`
|
||||||
`~#` | Searches Tagdef.com for a hashtag. | `~# ff`
|
`~#` | Searches Tagdef.com for a hashtag. | `~# ff`
|
||||||
`~catfact` | Shows a random catfact from <http://catfacts-api.appspot.com/api/facts> | `~catfact`
|
`~catfact` | Shows a random catfact from <http://catfacts-api.appspot.com/api/facts> | `~catfact`
|
||||||
`~revav` | Returns a google reverse image search for someone's avatar. | `~revav "@SomeGuy"`
|
`~revav` | Returns a google reverse image search for someone's avatar. | `~revav "@SomeGuy"`
|
||||||
@ -293,8 +313,6 @@ Command and aliases | Description | Usage
|
|||||||
`~color` `~clr` | Shows you what color corresponds to that hex. | `~clr 00ff00`
|
`~color` `~clr` | Shows you what color corresponds to that hex. | `~clr 00ff00`
|
||||||
`~videocall` | Creates a private <http://www.appear.in> video call link for you and other mentioned people. The link is sent to mentioned people via a private message. | `~videocall "@SomeGuy"`
|
`~videocall` | Creates a private <http://www.appear.in> video call link for you and other mentioned people. The link is sent to mentioned people via a private message. | `~videocall "@SomeGuy"`
|
||||||
`~avatar` `~av` | Shows a mentioned person's avatar. | `~av "@SomeGuy"`
|
`~avatar` `~av` | Shows a mentioned person's avatar. | `~av "@SomeGuy"`
|
||||||
`~bfonline` `~bfo` | Gives you online players for BF3 and BF4 | `~bfo bf3` or `~bfo bf4`
|
|
||||||
`~bfuser` `~bfu` | Gives you back a battlefield user's stats. | `~bfu platform game user`
|
|
||||||
`~wikia` | Gives you back a wikia link | `~wikia mtg Vigilance` or `~wikia mlp Dashy`
|
`~wikia` | Gives you back a wikia link | `~wikia mtg Vigilance` or `~wikia mlp Dashy`
|
||||||
`~minecraftping` `~mcping` | Pings a minecraft server. | `~mcping 127.0.0.1:25565`
|
`~minecraftping` `~mcping` | Pings a minecraft server. | `~mcping 127.0.0.1:25565`
|
||||||
`~minecraftquery` `~mcq` | Finds information about a minecraft server. | `~mcq server:ip`
|
`~minecraftquery` `~mcq` | Finds information about a minecraft server. | `~mcq server:ip`
|
||||||
@ -311,6 +329,7 @@ Command and aliases | Description | Usage
|
|||||||
`~osu` | Shows osu stats for a player. | `~osu Name` or `~osu Name taiko`
|
`~osu` | Shows osu stats for a player. | `~osu Name` or `~osu Name taiko`
|
||||||
`~osub` | Shows information about an osu beatmap. | `~osub https://osu.ppy.sh/s/127712`
|
`~osub` | Shows information about an osu beatmap. | `~osub https://osu.ppy.sh/s/127712`
|
||||||
`~osu5` | Displays a user's top 5 plays. | `~osu5 Name`
|
`~osu5` | Displays a user's top 5 plays. | `~osu5 Name`
|
||||||
|
`~overwatch` `~ow` | Show's basic stats on a player (competitive rank, playtime, level etc) Region codes are: `eu` `us` `cn` `kr` | `~ow us Battletag#1337` or `~overwatch eu Battletag#2016`
|
||||||
`~placelist` | Shows the list of available tags for the `~place` command. | `~placelist`
|
`~placelist` | Shows the list of available tags for the `~place` command. | `~placelist`
|
||||||
`~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`
|
||||||
@ -319,7 +338,7 @@ Command and aliases | Description | Usage
|
|||||||
`~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`
|
||||||
`~beam` `~bm` | Notifies this channel when a certain user starts streaming. **Requires ManageMessages server permission.** | `~beam 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 on this channel. **Requires ManageMessages server permission.** | `~rms SomeGuy`
|
`~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`
|
||||||
@ -332,6 +351,7 @@ Command and aliases | Description | Usage
|
|||||||
### Utility
|
### Utility
|
||||||
Command and aliases | Description | Usage
|
Command and aliases | Description | Usage
|
||||||
----------------|--------------|-------
|
----------------|--------------|-------
|
||||||
|
`.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 provided role or roles (separated by a ',') on this server. If the list is too long for 1 message, you must have Manage Messages permission. | `.inrole Role`
|
`.inrole` | Lists every person from the provided role or roles (separated by a ',') on this server. If the list is too long for 1 message, you must have Manage Messages permission. | `.inrole Role`
|
||||||
`.checkmyperms` | Checks your user-specific permissions on this channel. | `.checkmyperms`
|
`.checkmyperms` | Checks your user-specific permissions on this channel. | `.checkmyperms`
|
||||||
@ -345,7 +365,6 @@ Command 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`
|
||||||
`.calculate` `.calc` | Evaluate a mathematical expression. | `.calc 1+1`
|
`.calculate` `.calc` | Evaluate a mathematical expression. | `.calc 1+1`
|
||||||
`.calcops` | Shows all available operations in .calc command | `.calcops`
|
`.calcops` | Shows all available operations in .calc command | `.calcops`
|
||||||
`.togethertube` `.totube` | Creates a new room on <https://togethertube.com> and shows the link in the chat. | `.totube`
|
|
||||||
`.serverinfo` `.sinfo` | Shows info about the server the bot is on. If no channel 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`
|
||||||
@ -354,7 +373,7 @@ Command and aliases | Description | Usage
|
|||||||
`..` | Adds a new quote with the specified name and message. | `.. sayhi Hi`
|
`..` | Adds a new quote with the specified name and message. | `.. sayhi Hi`
|
||||||
`.deletequote` `.delq` | Deletes a random quote with the specified keyword. You have to either be server Administrator or the creator of the quote to delete it. | `.delq abc`
|
`.deletequote` `.delq` | Deletes a random quote with the specified keyword. You have to either be server Administrator or the creator of the quote to delete it. | `.delq abc`
|
||||||
`.delallq` `.daq` | Deletes all quotes on a specified keyword. **Requires Administrator server permission.** | `.delallq kek`
|
`.delallq` `.daq` | Deletes all quotes on a specified keyword. **Requires Administrator server permission.** | `.delallq kek`
|
||||||
`.remind` | Sends a message to you or a channel after certain amount of time. First argument is me/here/'channelname'. Second argument is time in a descending order (mo>w>d>h>m) example: 1w5d3h10m. Third argument is a (multiword)message. | `.remind me 1d5h Do something` or `.remind #general Start now!`
|
`.remind` | Sends a message to you or a channel after certain amount of time. First argument is me/here/'channelname'. Second argument is time in a descending order (mo>w>d>h>m) example: 1w5d3h10m. Third argument is a (multiword)message. | `.remind me 1d5h Do something` or `.remind #general 1m Start now!`
|
||||||
`.remindtemplate` | Sets message for when the remind is triggered. Available placeholders are %user% - user who ran the command, %message% - Message specified in the remind, %target% - target channel of the remind. **Bot Owner only.** | `.remindtemplate %user%, do %message%!`
|
`.remindtemplate` | Sets message for when the remind is triggered. Available placeholders are %user% - user who ran the command, %message% - Message specified in the remind, %target% - target channel of the remind. **Bot Owner only.** | `.remindtemplate %user%, do %message%!`
|
||||||
`.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`
|
||||||
|
@ -27,6 +27,14 @@ There's no special requirement for the formatting of the response, so we could j
|
|||||||
|
|
||||||
Now, if that command was ran in a server, anyone on that server can make the bot mention them, saying `It sure is, @Username` anytime they say "Nice Weather". If the command is ran in a direct message with the bot, then the custom reaction can be used on every server the bot is connected to.
|
Now, if that command was ran in a server, anyone on that server can make the bot mention them, saying `It sure is, @Username` anytime they say "Nice Weather". If the command is ran in a direct message with the bot, then the custom reaction can be used on every server the bot is connected to.
|
||||||
|
|
||||||
|
###Block global Custom Reactions
|
||||||
|
If you want to disable some global custom reactions which you do not like, and you do not want to remove them or you are not the bot owner you can do so by adding a new Custom Reaction with the same trigger on your server, and set the response to `-`.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
`.acr /o/ -`
|
||||||
|
|
||||||
|
Now if you try to trigger `/o/`, it won't print anything.
|
||||||
|
|
||||||
###Placeholders!
|
###Placeholders!
|
||||||
There are currently three different placeholders which we will look at, with more placeholders potentially coming in the future.
|
There are currently three different placeholders which we will look at, with more placeholders potentially coming in the future.
|
||||||
|
|
||||||
@ -34,7 +42,8 @@ There are currently three different placeholders which we will look at, with mor
|
|||||||
|:-----------:|-------------|---------------|-------|
|
|:-----------:|-------------|---------------|-------|
|
||||||
|`%mention`|The `%mention%` placeholder is triggered when you type `@BotName` - It's important to note that if you've given the bot a custom nickname, this trigger won't work!|```.acr "Hello %mention%" I, %mention%, also say hello!```|Input: "Hello @BotName" Output: "I, @BotName, also say hello!"|
|
|`%mention`|The `%mention%` placeholder is triggered when you type `@BotName` - It's important to note that if you've given the bot a custom nickname, this trigger won't work!|```.acr "Hello %mention%" I, %mention%, also say hello!```|Input: "Hello @BotName" Output: "I, @BotName, also say hello!"|
|
||||||
|`%user%`|The `%user%` placeholder mentions the person who said the command|`.acr "Who am I?" You are %user%!`|Input: "Who am I?" Output: "You are @Username!"|
|
|`%user%`|The `%user%` placeholder mentions the person who said the command|`.acr "Who am I?" You are %user%!`|Input: "Who am I?" Output: "You are @Username!"|
|
||||||
|`%rng%`|The `%rng%` placeholder generates a random number between 0 and 10|`.acr "Random number" %rng%`|Input: "Random number" Output: "2"|
|
|`%rng%`|The `%rng%` placeholder generates a random number between 0 and 10. You can also specify a custom range (%rng1-100%) even with negative numbers: `%rng-9--1%` (from -9 to -1) . |`.acr "Random number" %rng%`|Input: "Random number" Output: "2"|
|
||||||
|
|`%rnduser%`|The `%rnduser%` placeholder mentions a random user from the server. |`.acr "Random user" %rnduser%`|Input: "Random number" Output: @SomeUser|
|
||||||
|`%target%`|The `%target%` placeholder is used to make Nadeko Mention another person or phrase, it is only supported as part of the response|`.acr "Say this: " %target%`|Input: "Say this: I, @BotName, am a parrot!". Output: "I, @BotName, am a parrot!".|
|
|`%target%`|The `%target%` placeholder is used to make Nadeko Mention another person or phrase, it is only supported as part of the response|`.acr "Say this: " %target%`|Input: "Say this: I, @BotName, am a parrot!". Output: "I, @BotName, am a parrot!".|
|
||||||
|
|
||||||
Thanks to Nekai for being creative. <3
|
Thanks to Nekai for being creative. <3
|
||||||
|
@ -1,3 +1,34 @@
|
|||||||
# Docker Guide with DigitalOcean
|
# NadekoBot a Discord bot
|
||||||
|
Nadeko is written in C# and Discord.net for more information visit https://github.com/Kwoth/NadekoBot
|
||||||
|
|
||||||
## There is no docker image for 1.0 nadeko right now. Soon.
|
## Install Docker
|
||||||
|
Follow the respective guide for your operating system found here https://docs.docker.com/engine/installation/
|
||||||
|
|
||||||
|
## Nadeko Setup Guide
|
||||||
|
For this guide we will be using the folder /nadeko as our config root folder.
|
||||||
|
|
||||||
|
```
|
||||||
|
docker create --name=nadeko -v /nadeko/data:/opt/NadekoBot/src/NadekoBot/bin/Release/netcoreapp1.0/data -v /nadeko/credentials.json:/opt/NadekoBot/src/NadekoBot/credentials.json kwoth/nadeko:dev
|
||||||
|
```
|
||||||
|
-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 palce it in the /nadeko folder
|
||||||
|
http://nadekobot.readthedocs.io/en/latest/JSON%20Explanations/
|
||||||
|
|
||||||
|
Next start the docker up with
|
||||||
|
|
||||||
|
```docker start nadeko; docker logs -f nadeko```
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
After a few moments you should be able to invite Nadeko to your server. If you cannot check the log file for errors
|
||||||
|
|
||||||
|
## Updates / Monitoring
|
||||||
|
|
||||||
|
* Upgrade to the latest version of Nadeko simply `docker restart nadeko`.
|
||||||
|
* Monitor the logs of the container in realtime `docker logs -f nadeko`.
|
||||||
|
|
||||||
|
If you have any issues with the docker setup, please ask in #help but indicate you are using the docker.
|
||||||
|
|
||||||
|
For information about configuring your bot or its functionality, please check the http://nadekobot.readthedocs.io/en/latest guides.
|
||||||
|
@ -95,7 +95,7 @@ sudo apt-get update && sudo apt-get install ffmpeg -y
|
|||||||
Use the following command to get and run `linuxAIO.sh`:
|
Use the following command to get and run `linuxAIO.sh`:
|
||||||
(Remember **DO NOT** rename the file `linuxAIO.sh`)
|
(Remember **DO NOT** rename the file `linuxAIO.sh`)
|
||||||
|
|
||||||
`cd ~ && wget https://github.com/Kwoth/NadekoBot-BashScript/raw/master/linuxAIO.sh && bash linuxAIO.sh`
|
`cd ~ && wget -N https://github.com/Kwoth/NadekoBot-BashScript/raw/master/linuxAIO.sh && bash linuxAIO.sh`
|
||||||
|
|
||||||
Follow the on screen instructions:
|
Follow the on screen instructions:
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ A dialog box will open asking if you want to install `xcode-select`. Select inst
|
|||||||
Use the following command to get and run `linuxAIO.sh`:
|
Use the following command to get and run `linuxAIO.sh`:
|
||||||
(Remember **DO NOT** rename the file `linuxAIO.sh`)
|
(Remember **DO NOT** rename the file `linuxAIO.sh`)
|
||||||
|
|
||||||
`cd ~ && wget https://github.com/Kwoth/NadekoBot-BashScript/raw/master/linuxAIO.sh && bash linuxAIO.sh`
|
`cd ~ && wget -N https://github.com/Kwoth/NadekoBot-BashScript/raw/master/linuxAIO.sh && bash linuxAIO.sh`
|
||||||
|
|
||||||
Follow the on screen instructions:
|
Follow the on screen instructions:
|
||||||
|
|
||||||
|
@ -1,6 +1,69 @@
|
|||||||
@ECHO off
|
@ECHO off
|
||||||
@TITLE NadekoBot
|
@TITLE NadekoBot
|
||||||
:auto
|
|
||||||
|
|
||||||
|
SET root=%~dp0
|
||||||
|
CD /D %root%
|
||||||
|
|
||||||
|
CLS
|
||||||
|
ECHO Welcome to NadekoBot Auto Restart and Update!
|
||||||
|
ECHO --------------------------------------------
|
||||||
|
ECHO 1.Auto Restart and Update with Dev Build (latest)
|
||||||
|
ECHO 2.Auto Restart and Update with Stable Build
|
||||||
|
ECHO 3.Run Auto Restart normally without Updating (will restart faster)
|
||||||
|
ECHO 4.To exit
|
||||||
|
ECHO.
|
||||||
|
|
||||||
|
CHOICE /C 1234 /M "Enter your choice:"
|
||||||
|
|
||||||
|
:: Note - list ERRORLEVELS in decreasing order
|
||||||
|
IF ERRORLEVEL 4 GOTO exit
|
||||||
|
IF ERRORLEVEL 3 GOTO autorun
|
||||||
|
IF ERRORLEVEL 2 GOTO stablear
|
||||||
|
IF ERRORLEVEL 1 GOTO latestar
|
||||||
|
|
||||||
|
:latestar
|
||||||
|
ECHO Auto Restart and Update with Dev Build (latest)
|
||||||
|
ECHO Bot will auto update on every restart!
|
||||||
|
timeout /t 3
|
||||||
CD /D %~dp0NadekoBot\src\NadekoBot
|
CD /D %~dp0NadekoBot\src\NadekoBot
|
||||||
dotnet run --configuration Release
|
dotnet run --configuration Release
|
||||||
goto auto
|
ECHO Updating...
|
||||||
|
timeout /t 3
|
||||||
|
SET "FILENAME=%~dp0\Latest.bat"
|
||||||
|
bitsadmin.exe /transfer "Downloading Nadeko (Latest)" /priority high https://github.com/Kwoth/NadekoBot/raw/master/scripts/Latest.bat "%FILENAME%"
|
||||||
|
ECHO NadekoBot Dev Build (latest) downloaded.
|
||||||
|
SET root=%~dp0
|
||||||
|
CD /D %root%
|
||||||
|
CALL Latest.bat
|
||||||
|
GOTO latestar
|
||||||
|
|
||||||
|
:stablear
|
||||||
|
ECHO Auto Restart and Update with Stable Build
|
||||||
|
ECHO Bot will auto update on every restart!
|
||||||
|
timeout /t 3
|
||||||
|
CD /D %~dp0NadekoBot\src\NadekoBot
|
||||||
|
dotnet run --configuration Release
|
||||||
|
ECHO Updating...
|
||||||
|
timeout /t 3
|
||||||
|
SET "FILENAME=%~dp0\Stable.bat"
|
||||||
|
bitsadmin.exe /transfer "Downloading Nadeko (Stable)" /priority high https://github.com/Kwoth/NadekoBot/raw/master/scripts/Stable.bat "%FILENAME%"
|
||||||
|
ECHO NadekoBot Stable build downloaded.
|
||||||
|
SET root=%~dp0
|
||||||
|
CD /D %root%
|
||||||
|
CALL Stable.bat
|
||||||
|
GOTO stablear
|
||||||
|
|
||||||
|
:autorun
|
||||||
|
ECHO Normal Auto Restart
|
||||||
|
ECHO Bot will not auto update on every restart!
|
||||||
|
timeout /t 3
|
||||||
|
CD /D %~dp0NadekoBot\src\NadekoBot
|
||||||
|
dotnet run --configuration Release
|
||||||
|
goto autorun
|
||||||
|
|
||||||
|
:Exit
|
||||||
|
SET root=%~dp0
|
||||||
|
CD /D %root%
|
||||||
|
del NadekoAutoRun.bat
|
||||||
|
CALL NadekoInstaller.bat
|
||||||
|
802
src/NadekoBot/Migrations/20161127233843_PokeGame.Designer.cs
generated
Normal file
802
src/NadekoBot/Migrations/20161127233843_PokeGame.Designer.cs
generated
Normal file
@ -0,0 +1,802 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using NadekoBot.Services.Database;
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using NadekoBot.Modules.Music.Classes;
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(NadekoContext))]
|
||||||
|
[Migration("20161127233843_PokeGame")]
|
||||||
|
partial class PokeGame
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "1.1.0-rtm-22752");
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("BotConfigId");
|
||||||
|
|
||||||
|
b.Property<ulong>("ItemId");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BotConfigId");
|
||||||
|
|
||||||
|
b.ToTable("BlacklistItem");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.BotConfig", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("BufferSize");
|
||||||
|
|
||||||
|
b.Property<float>("CurrencyGenerationChance");
|
||||||
|
|
||||||
|
b.Property<int>("CurrencyGenerationCooldown");
|
||||||
|
|
||||||
|
b.Property<string>("CurrencyName");
|
||||||
|
|
||||||
|
b.Property<string>("CurrencyPluralName");
|
||||||
|
|
||||||
|
b.Property<string>("CurrencySign");
|
||||||
|
|
||||||
|
b.Property<string>("DMHelpString");
|
||||||
|
|
||||||
|
b.Property<bool>("ForwardMessages");
|
||||||
|
|
||||||
|
b.Property<bool>("ForwardToAllOwners");
|
||||||
|
|
||||||
|
b.Property<string>("HelpString");
|
||||||
|
|
||||||
|
b.Property<int>("MigrationVersion");
|
||||||
|
|
||||||
|
b.Property<string>("RemindMessageFormat");
|
||||||
|
|
||||||
|
b.Property<bool>("RotatingStatuses");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("BotConfig");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("BaseDestroyed");
|
||||||
|
|
||||||
|
b.Property<string>("CallUser");
|
||||||
|
|
||||||
|
b.Property<int>("ClashWarId");
|
||||||
|
|
||||||
|
b.Property<int?>("SequenceNumber");
|
||||||
|
|
||||||
|
b.Property<int>("Stars");
|
||||||
|
|
||||||
|
b.Property<DateTime>("TimeAdded");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClashWarId");
|
||||||
|
|
||||||
|
b.ToTable("ClashCallers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashWar", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<string>("EnemyClan");
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId");
|
||||||
|
|
||||||
|
b.Property<int>("Size");
|
||||||
|
|
||||||
|
b.Property<DateTime>("StartedAt");
|
||||||
|
|
||||||
|
b.Property<int>("WarState");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ClashOfClans");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("CommandName");
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId");
|
||||||
|
|
||||||
|
b.Property<int>("Seconds");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId");
|
||||||
|
|
||||||
|
b.ToTable("CommandCooldown");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.ConvertUnit", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("InternalTrigger");
|
||||||
|
|
||||||
|
b.Property<decimal>("Modifier");
|
||||||
|
|
||||||
|
b.Property<string>("UnitType");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ConversionUnits");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Currency", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<long>("Amount");
|
||||||
|
|
||||||
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Currency");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<long>("Amount");
|
||||||
|
|
||||||
|
b.Property<string>("Reason");
|
||||||
|
|
||||||
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CurrencyTransactions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.CustomReaction", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong?>("GuildId");
|
||||||
|
|
||||||
|
b.Property<bool>("IsRegex");
|
||||||
|
|
||||||
|
b.Property<bool>("OwnerOnly");
|
||||||
|
|
||||||
|
b.Property<string>("Response");
|
||||||
|
|
||||||
|
b.Property<string>("Trigger");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CustomReactions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Donator", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("Amount");
|
||||||
|
|
||||||
|
b.Property<string>("Name");
|
||||||
|
|
||||||
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Donators");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("BotConfigId");
|
||||||
|
|
||||||
|
b.Property<string>("Text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BotConfigId");
|
||||||
|
|
||||||
|
b.ToTable("EightBallResponses");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId");
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId1");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId1");
|
||||||
|
|
||||||
|
b.ToTable("FilterChannelId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId");
|
||||||
|
|
||||||
|
b.Property<string>("Word");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId");
|
||||||
|
|
||||||
|
b.ToTable("FilteredWord");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId");
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Username");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId");
|
||||||
|
|
||||||
|
b.ToTable("FollowedStream");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId");
|
||||||
|
|
||||||
|
b.ToTable("GCChannelId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("AutoAssignRoleId");
|
||||||
|
|
||||||
|
b.Property<bool>("AutoDeleteByeMessages");
|
||||||
|
|
||||||
|
b.Property<int>("AutoDeleteByeMessagesTimer");
|
||||||
|
|
||||||
|
b.Property<bool>("AutoDeleteGreetMessages");
|
||||||
|
|
||||||
|
b.Property<int>("AutoDeleteGreetMessagesTimer");
|
||||||
|
|
||||||
|
b.Property<bool>("AutoDeleteSelfAssignedRoleMessages");
|
||||||
|
|
||||||
|
b.Property<ulong>("ByeMessageChannelId");
|
||||||
|
|
||||||
|
b.Property<string>("ChannelByeMessageText");
|
||||||
|
|
||||||
|
b.Property<string>("ChannelGreetMessageText");
|
||||||
|
|
||||||
|
b.Property<bool>("CleverbotEnabled");
|
||||||
|
|
||||||
|
b.Property<float>("DefaultMusicVolume");
|
||||||
|
|
||||||
|
b.Property<bool>("DeleteMessageOnCommand");
|
||||||
|
|
||||||
|
b.Property<string>("DmGreetMessageText");
|
||||||
|
|
||||||
|
b.Property<bool>("ExclusiveSelfAssignedRoles");
|
||||||
|
|
||||||
|
b.Property<bool>("FilterInvites");
|
||||||
|
|
||||||
|
b.Property<bool>("FilterWords");
|
||||||
|
|
||||||
|
b.Property<ulong>("GreetMessageChannelId");
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId");
|
||||||
|
|
||||||
|
b.Property<int?>("LogSettingId");
|
||||||
|
|
||||||
|
b.Property<string>("MuteRoleName");
|
||||||
|
|
||||||
|
b.Property<string>("PermissionRole");
|
||||||
|
|
||||||
|
b.Property<int?>("RootPermissionId");
|
||||||
|
|
||||||
|
b.Property<bool>("SendChannelByeMessage");
|
||||||
|
|
||||||
|
b.Property<bool>("SendChannelGreetMessage");
|
||||||
|
|
||||||
|
b.Property<bool>("SendDmGreetMessage");
|
||||||
|
|
||||||
|
b.Property<bool>("VerbosePermissions");
|
||||||
|
|
||||||
|
b.Property<bool>("VoicePlusTextEnabled");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.HasIndex("LogSettingId");
|
||||||
|
|
||||||
|
b.HasIndex("RootPermissionId");
|
||||||
|
|
||||||
|
b.ToTable("GuildConfigs");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogChannel", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<int?>("LogSettingId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("LogSettingId");
|
||||||
|
|
||||||
|
b.ToTable("IgnoredLogChannels");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<int?>("LogSettingId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("LogSettingId");
|
||||||
|
|
||||||
|
b.ToTable("IgnoredVoicePresenceCHannels");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("ChannelCreated");
|
||||||
|
|
||||||
|
b.Property<bool>("ChannelDestroyed");
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<bool>("ChannelUpdated");
|
||||||
|
|
||||||
|
b.Property<bool>("IsLogging");
|
||||||
|
|
||||||
|
b.Property<bool>("LogUserPresence");
|
||||||
|
|
||||||
|
b.Property<bool>("LogVoicePresence");
|
||||||
|
|
||||||
|
b.Property<bool>("MessageDeleted");
|
||||||
|
|
||||||
|
b.Property<bool>("MessageUpdated");
|
||||||
|
|
||||||
|
b.Property<bool>("UserBanned");
|
||||||
|
|
||||||
|
b.Property<bool>("UserJoined");
|
||||||
|
|
||||||
|
b.Property<bool>("UserLeft");
|
||||||
|
|
||||||
|
b.Property<ulong>("UserPresenceChannelId");
|
||||||
|
|
||||||
|
b.Property<bool>("UserUnbanned");
|
||||||
|
|
||||||
|
b.Property<bool>("UserUpdated");
|
||||||
|
|
||||||
|
b.Property<ulong>("VoicePresenceChannelId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("LogSettings");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("BotConfigId");
|
||||||
|
|
||||||
|
b.Property<string>("ModuleName");
|
||||||
|
|
||||||
|
b.Property<string>("Prefix");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BotConfigId");
|
||||||
|
|
||||||
|
b.ToTable("ModulePrefixes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Author");
|
||||||
|
|
||||||
|
b.Property<ulong>("AuthorId");
|
||||||
|
|
||||||
|
b.Property<string>("Name");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("MusicPlaylists");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("NextId");
|
||||||
|
|
||||||
|
b.Property<int>("PrimaryTarget");
|
||||||
|
|
||||||
|
b.Property<ulong>("PrimaryTargetId");
|
||||||
|
|
||||||
|
b.Property<int>("SecondaryTarget");
|
||||||
|
|
||||||
|
b.Property<string>("SecondaryTargetName");
|
||||||
|
|
||||||
|
b.Property<bool>("State");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NextId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Permission");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("BotConfigId");
|
||||||
|
|
||||||
|
b.Property<string>("Status");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BotConfigId");
|
||||||
|
|
||||||
|
b.ToTable("PlayingStatus");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("MusicPlaylistId");
|
||||||
|
|
||||||
|
b.Property<string>("Provider");
|
||||||
|
|
||||||
|
b.Property<int>("ProviderType");
|
||||||
|
|
||||||
|
b.Property<string>("Query");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("Uri");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("MusicPlaylistId");
|
||||||
|
|
||||||
|
b.ToTable("PlaylistSong");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("AuthorId");
|
||||||
|
|
||||||
|
b.Property<string>("AuthorName")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId");
|
||||||
|
|
||||||
|
b.Property<string>("Keyword")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Text")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Quotes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("BotConfigId");
|
||||||
|
|
||||||
|
b.Property<string>("Icon");
|
||||||
|
|
||||||
|
b.Property<string>("Name");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BotConfigId");
|
||||||
|
|
||||||
|
b.ToTable("RaceAnimals");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPrivate");
|
||||||
|
|
||||||
|
b.Property<string>("Message");
|
||||||
|
|
||||||
|
b.Property<ulong>("ServerId");
|
||||||
|
|
||||||
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("When");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Reminders");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId");
|
||||||
|
|
||||||
|
b.Property<TimeSpan>("Interval");
|
||||||
|
|
||||||
|
b.Property<string>("Message");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ChannelId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Repeaters");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId");
|
||||||
|
|
||||||
|
b.Property<ulong>("RoleId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildId", "RoleId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("SelfAssignableRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.UserPokeTypes", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<long>("UserId");
|
||||||
|
|
||||||
|
b.Property<string>("type");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("PokeGame");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
|
||||||
|
.WithMany("Blacklist")
|
||||||
|
.HasForeignKey("BotConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.ClashWar", "ClashWar")
|
||||||
|
.WithMany("Bases")
|
||||||
|
.HasForeignKey("ClashWarId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("CommandCooldowns")
|
||||||
|
.HasForeignKey("GuildConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
|
||||||
|
.WithMany("EightBallResponses")
|
||||||
|
.HasForeignKey("BotConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("FilterInvitesChannelIds")
|
||||||
|
.HasForeignKey("GuildConfigId");
|
||||||
|
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("FilterWordsChannelIds")
|
||||||
|
.HasForeignKey("GuildConfigId1");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("FilteredWords")
|
||||||
|
.HasForeignKey("GuildConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("FollowedStreams")
|
||||||
|
.HasForeignKey("GuildConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("GenerateCurrencyChannelIds")
|
||||||
|
.HasForeignKey("GuildConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("LogSettingId");
|
||||||
|
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.Permission", "RootPermission")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RootPermissionId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogChannel", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting")
|
||||||
|
.WithMany("IgnoredChannels")
|
||||||
|
.HasForeignKey("LogSettingId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting")
|
||||||
|
.WithMany("IgnoredVoicePresenceChannelIds")
|
||||||
|
.HasForeignKey("LogSettingId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
|
||||||
|
.WithMany("ModulePrefixes")
|
||||||
|
.HasForeignKey("BotConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.Permission", "Next")
|
||||||
|
.WithOne("Previous")
|
||||||
|
.HasForeignKey("NadekoBot.Services.Database.Models.Permission", "NextId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
|
||||||
|
.WithMany("RotatingStatusMessages")
|
||||||
|
.HasForeignKey("BotConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.MusicPlaylist")
|
||||||
|
.WithMany("Songs")
|
||||||
|
.HasForeignKey("MusicPlaylistId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
|
||||||
|
.WithMany("RaceAnimals")
|
||||||
|
.HasForeignKey("BotConfigId");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
src/NadekoBot/Migrations/20161127233843_PokeGame.cs
Normal file
38
src/NadekoBot/Migrations/20161127233843_PokeGame.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations
|
||||||
|
{
|
||||||
|
public partial class PokeGame : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "PokeGame",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
UserId = table.Column<ulong>(nullable: false),
|
||||||
|
type = table.Column<string>(nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_PokeGame", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_PokeGame_UserId",
|
||||||
|
table: "PokeGame",
|
||||||
|
column: "UserId",
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "PokeGame");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
825
src/NadekoBot/Migrations/20161213025624_mutedusers.Designer.cs
generated
Normal file
825
src/NadekoBot/Migrations/20161213025624_mutedusers.Designer.cs
generated
Normal file
@ -0,0 +1,825 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using NadekoBot.Services.Database;
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using NadekoBot.Modules.Music.Classes;
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(NadekoContext))]
|
||||||
|
[Migration("20161213025624_mutedusers")]
|
||||||
|
partial class mutedusers
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "1.1.0-rtm-22752");
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("BotConfigId");
|
||||||
|
|
||||||
|
b.Property<ulong>("ItemId");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BotConfigId");
|
||||||
|
|
||||||
|
b.ToTable("BlacklistItem");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.BotConfig", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("BufferSize");
|
||||||
|
|
||||||
|
b.Property<float>("CurrencyGenerationChance");
|
||||||
|
|
||||||
|
b.Property<int>("CurrencyGenerationCooldown");
|
||||||
|
|
||||||
|
b.Property<string>("CurrencyName");
|
||||||
|
|
||||||
|
b.Property<string>("CurrencyPluralName");
|
||||||
|
|
||||||
|
b.Property<string>("CurrencySign");
|
||||||
|
|
||||||
|
b.Property<string>("DMHelpString");
|
||||||
|
|
||||||
|
b.Property<bool>("ForwardMessages");
|
||||||
|
|
||||||
|
b.Property<bool>("ForwardToAllOwners");
|
||||||
|
|
||||||
|
b.Property<string>("HelpString");
|
||||||
|
|
||||||
|
b.Property<int>("MigrationVersion");
|
||||||
|
|
||||||
|
b.Property<string>("RemindMessageFormat");
|
||||||
|
|
||||||
|
b.Property<bool>("RotatingStatuses");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("BotConfig");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("BaseDestroyed");
|
||||||
|
|
||||||
|
b.Property<string>("CallUser");
|
||||||
|
|
||||||
|
b.Property<int>("ClashWarId");
|
||||||
|
|
||||||
|
b.Property<int?>("SequenceNumber");
|
||||||
|
|
||||||
|
b.Property<int>("Stars");
|
||||||
|
|
||||||
|
b.Property<DateTime>("TimeAdded");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClashWarId");
|
||||||
|
|
||||||
|
b.ToTable("ClashCallers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashWar", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<string>("EnemyClan");
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId");
|
||||||
|
|
||||||
|
b.Property<int>("Size");
|
||||||
|
|
||||||
|
b.Property<DateTime>("StartedAt");
|
||||||
|
|
||||||
|
b.Property<int>("WarState");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ClashOfClans");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("CommandName");
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId");
|
||||||
|
|
||||||
|
b.Property<int>("Seconds");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId");
|
||||||
|
|
||||||
|
b.ToTable("CommandCooldown");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.ConvertUnit", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("InternalTrigger");
|
||||||
|
|
||||||
|
b.Property<decimal>("Modifier");
|
||||||
|
|
||||||
|
b.Property<string>("UnitType");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ConversionUnits");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Currency", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<long>("Amount");
|
||||||
|
|
||||||
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Currency");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<long>("Amount");
|
||||||
|
|
||||||
|
b.Property<string>("Reason");
|
||||||
|
|
||||||
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CurrencyTransactions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.CustomReaction", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong?>("GuildId");
|
||||||
|
|
||||||
|
b.Property<bool>("IsRegex");
|
||||||
|
|
||||||
|
b.Property<bool>("OwnerOnly");
|
||||||
|
|
||||||
|
b.Property<string>("Response");
|
||||||
|
|
||||||
|
b.Property<string>("Trigger");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CustomReactions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Donator", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("Amount");
|
||||||
|
|
||||||
|
b.Property<string>("Name");
|
||||||
|
|
||||||
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Donators");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("BotConfigId");
|
||||||
|
|
||||||
|
b.Property<string>("Text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BotConfigId");
|
||||||
|
|
||||||
|
b.ToTable("EightBallResponses");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId");
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId1");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId1");
|
||||||
|
|
||||||
|
b.ToTable("FilterChannelId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId");
|
||||||
|
|
||||||
|
b.Property<string>("Word");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId");
|
||||||
|
|
||||||
|
b.ToTable("FilteredWord");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId");
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Username");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId");
|
||||||
|
|
||||||
|
b.ToTable("FollowedStream");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId");
|
||||||
|
|
||||||
|
b.ToTable("GCChannelId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("AutoAssignRoleId");
|
||||||
|
|
||||||
|
b.Property<bool>("AutoDeleteByeMessages");
|
||||||
|
|
||||||
|
b.Property<int>("AutoDeleteByeMessagesTimer");
|
||||||
|
|
||||||
|
b.Property<bool>("AutoDeleteGreetMessages");
|
||||||
|
|
||||||
|
b.Property<int>("AutoDeleteGreetMessagesTimer");
|
||||||
|
|
||||||
|
b.Property<bool>("AutoDeleteSelfAssignedRoleMessages");
|
||||||
|
|
||||||
|
b.Property<ulong>("ByeMessageChannelId");
|
||||||
|
|
||||||
|
b.Property<string>("ChannelByeMessageText");
|
||||||
|
|
||||||
|
b.Property<string>("ChannelGreetMessageText");
|
||||||
|
|
||||||
|
b.Property<bool>("CleverbotEnabled");
|
||||||
|
|
||||||
|
b.Property<float>("DefaultMusicVolume");
|
||||||
|
|
||||||
|
b.Property<bool>("DeleteMessageOnCommand");
|
||||||
|
|
||||||
|
b.Property<string>("DmGreetMessageText");
|
||||||
|
|
||||||
|
b.Property<bool>("ExclusiveSelfAssignedRoles");
|
||||||
|
|
||||||
|
b.Property<bool>("FilterInvites");
|
||||||
|
|
||||||
|
b.Property<bool>("FilterWords");
|
||||||
|
|
||||||
|
b.Property<ulong>("GreetMessageChannelId");
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId");
|
||||||
|
|
||||||
|
b.Property<int?>("LogSettingId");
|
||||||
|
|
||||||
|
b.Property<string>("MuteRoleName");
|
||||||
|
|
||||||
|
b.Property<string>("PermissionRole");
|
||||||
|
|
||||||
|
b.Property<int?>("RootPermissionId");
|
||||||
|
|
||||||
|
b.Property<bool>("SendChannelByeMessage");
|
||||||
|
|
||||||
|
b.Property<bool>("SendChannelGreetMessage");
|
||||||
|
|
||||||
|
b.Property<bool>("SendDmGreetMessage");
|
||||||
|
|
||||||
|
b.Property<bool>("VerbosePermissions");
|
||||||
|
|
||||||
|
b.Property<bool>("VoicePlusTextEnabled");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.HasIndex("LogSettingId");
|
||||||
|
|
||||||
|
b.HasIndex("RootPermissionId");
|
||||||
|
|
||||||
|
b.ToTable("GuildConfigs");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogChannel", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<int?>("LogSettingId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("LogSettingId");
|
||||||
|
|
||||||
|
b.ToTable("IgnoredLogChannels");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<int?>("LogSettingId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("LogSettingId");
|
||||||
|
|
||||||
|
b.ToTable("IgnoredVoicePresenceCHannels");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("ChannelCreated");
|
||||||
|
|
||||||
|
b.Property<bool>("ChannelDestroyed");
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<bool>("ChannelUpdated");
|
||||||
|
|
||||||
|
b.Property<bool>("IsLogging");
|
||||||
|
|
||||||
|
b.Property<bool>("LogUserPresence");
|
||||||
|
|
||||||
|
b.Property<bool>("LogVoicePresence");
|
||||||
|
|
||||||
|
b.Property<bool>("MessageDeleted");
|
||||||
|
|
||||||
|
b.Property<bool>("MessageUpdated");
|
||||||
|
|
||||||
|
b.Property<bool>("UserBanned");
|
||||||
|
|
||||||
|
b.Property<bool>("UserJoined");
|
||||||
|
|
||||||
|
b.Property<bool>("UserLeft");
|
||||||
|
|
||||||
|
b.Property<ulong>("UserPresenceChannelId");
|
||||||
|
|
||||||
|
b.Property<bool>("UserUnbanned");
|
||||||
|
|
||||||
|
b.Property<bool>("UserUpdated");
|
||||||
|
|
||||||
|
b.Property<ulong>("VoicePresenceChannelId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("LogSettings");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("BotConfigId");
|
||||||
|
|
||||||
|
b.Property<string>("ModuleName");
|
||||||
|
|
||||||
|
b.Property<string>("Prefix");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BotConfigId");
|
||||||
|
|
||||||
|
b.ToTable("ModulePrefixes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Author");
|
||||||
|
|
||||||
|
b.Property<ulong>("AuthorId");
|
||||||
|
|
||||||
|
b.Property<string>("Name");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("MusicPlaylists");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId");
|
||||||
|
|
||||||
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId");
|
||||||
|
|
||||||
|
b.ToTable("MutedUserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("NextId");
|
||||||
|
|
||||||
|
b.Property<int>("PrimaryTarget");
|
||||||
|
|
||||||
|
b.Property<ulong>("PrimaryTargetId");
|
||||||
|
|
||||||
|
b.Property<int>("SecondaryTarget");
|
||||||
|
|
||||||
|
b.Property<string>("SecondaryTargetName");
|
||||||
|
|
||||||
|
b.Property<bool>("State");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NextId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Permission");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("BotConfigId");
|
||||||
|
|
||||||
|
b.Property<string>("Status");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BotConfigId");
|
||||||
|
|
||||||
|
b.ToTable("PlayingStatus");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("MusicPlaylistId");
|
||||||
|
|
||||||
|
b.Property<string>("Provider");
|
||||||
|
|
||||||
|
b.Property<int>("ProviderType");
|
||||||
|
|
||||||
|
b.Property<string>("Query");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("Uri");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("MusicPlaylistId");
|
||||||
|
|
||||||
|
b.ToTable("PlaylistSong");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("AuthorId");
|
||||||
|
|
||||||
|
b.Property<string>("AuthorName")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId");
|
||||||
|
|
||||||
|
b.Property<string>("Keyword")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Text")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Quotes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("BotConfigId");
|
||||||
|
|
||||||
|
b.Property<string>("Icon");
|
||||||
|
|
||||||
|
b.Property<string>("Name");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BotConfigId");
|
||||||
|
|
||||||
|
b.ToTable("RaceAnimals");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPrivate");
|
||||||
|
|
||||||
|
b.Property<string>("Message");
|
||||||
|
|
||||||
|
b.Property<ulong>("ServerId");
|
||||||
|
|
||||||
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("When");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Reminders");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId");
|
||||||
|
|
||||||
|
b.Property<TimeSpan>("Interval");
|
||||||
|
|
||||||
|
b.Property<string>("Message");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ChannelId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Repeaters");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId");
|
||||||
|
|
||||||
|
b.Property<ulong>("RoleId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildId", "RoleId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("SelfAssignableRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.UserPokeTypes", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
|
b.Property<string>("type");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("PokeGame");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
|
||||||
|
.WithMany("Blacklist")
|
||||||
|
.HasForeignKey("BotConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.ClashWar", "ClashWar")
|
||||||
|
.WithMany("Bases")
|
||||||
|
.HasForeignKey("ClashWarId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("CommandCooldowns")
|
||||||
|
.HasForeignKey("GuildConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
|
||||||
|
.WithMany("EightBallResponses")
|
||||||
|
.HasForeignKey("BotConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("FilterInvitesChannelIds")
|
||||||
|
.HasForeignKey("GuildConfigId");
|
||||||
|
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("FilterWordsChannelIds")
|
||||||
|
.HasForeignKey("GuildConfigId1");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("FilteredWords")
|
||||||
|
.HasForeignKey("GuildConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("FollowedStreams")
|
||||||
|
.HasForeignKey("GuildConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("GenerateCurrencyChannelIds")
|
||||||
|
.HasForeignKey("GuildConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("LogSettingId");
|
||||||
|
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.Permission", "RootPermission")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RootPermissionId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogChannel", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting")
|
||||||
|
.WithMany("IgnoredChannels")
|
||||||
|
.HasForeignKey("LogSettingId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting")
|
||||||
|
.WithMany("IgnoredVoicePresenceChannelIds")
|
||||||
|
.HasForeignKey("LogSettingId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
|
||||||
|
.WithMany("ModulePrefixes")
|
||||||
|
.HasForeignKey("BotConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("MutedUsers")
|
||||||
|
.HasForeignKey("GuildConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.Permission", "Next")
|
||||||
|
.WithOne("Previous")
|
||||||
|
.HasForeignKey("NadekoBot.Services.Database.Models.Permission", "NextId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
|
||||||
|
.WithMany("RotatingStatusMessages")
|
||||||
|
.HasForeignKey("BotConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.MusicPlaylist")
|
||||||
|
.WithMany("Songs")
|
||||||
|
.HasForeignKey("MusicPlaylistId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
|
||||||
|
.WithMany("RaceAnimals")
|
||||||
|
.HasForeignKey("BotConfigId");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
src/NadekoBot/Migrations/20161213025624_mutedusers.cs
Normal file
43
src/NadekoBot/Migrations/20161213025624_mutedusers.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations
|
||||||
|
{
|
||||||
|
public partial class mutedusers : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "MutedUserId",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
GuildConfigId = table.Column<int>(nullable: true),
|
||||||
|
UserId = table.Column<ulong>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_MutedUserId", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_MutedUserId_GuildConfigs_GuildConfigId",
|
||||||
|
column: x => x.GuildConfigId,
|
||||||
|
principalTable: "GuildConfigs",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_MutedUserId_GuildConfigId",
|
||||||
|
table: "MutedUserId",
|
||||||
|
column: "GuildConfigId");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "MutedUserId");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
855
src/NadekoBot/Migrations/20161224032833_logsettings.Designer.cs
generated
Normal file
855
src/NadekoBot/Migrations/20161224032833_logsettings.Designer.cs
generated
Normal file
@ -0,0 +1,855 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using NadekoBot.Services.Database;
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using NadekoBot.Modules.Music.Classes;
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(NadekoContext))]
|
||||||
|
[Migration("20161224032833_logsettings")]
|
||||||
|
partial class logsettings
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "1.1.0-rtm-22752");
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("BotConfigId");
|
||||||
|
|
||||||
|
b.Property<ulong>("ItemId");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BotConfigId");
|
||||||
|
|
||||||
|
b.ToTable("BlacklistItem");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.BotConfig", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("BufferSize");
|
||||||
|
|
||||||
|
b.Property<float>("CurrencyGenerationChance");
|
||||||
|
|
||||||
|
b.Property<int>("CurrencyGenerationCooldown");
|
||||||
|
|
||||||
|
b.Property<string>("CurrencyName");
|
||||||
|
|
||||||
|
b.Property<string>("CurrencyPluralName");
|
||||||
|
|
||||||
|
b.Property<string>("CurrencySign");
|
||||||
|
|
||||||
|
b.Property<string>("DMHelpString");
|
||||||
|
|
||||||
|
b.Property<bool>("ForwardMessages");
|
||||||
|
|
||||||
|
b.Property<bool>("ForwardToAllOwners");
|
||||||
|
|
||||||
|
b.Property<string>("HelpString");
|
||||||
|
|
||||||
|
b.Property<int>("MigrationVersion");
|
||||||
|
|
||||||
|
b.Property<string>("RemindMessageFormat");
|
||||||
|
|
||||||
|
b.Property<bool>("RotatingStatuses");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("BotConfig");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("BaseDestroyed");
|
||||||
|
|
||||||
|
b.Property<string>("CallUser");
|
||||||
|
|
||||||
|
b.Property<int>("ClashWarId");
|
||||||
|
|
||||||
|
b.Property<int?>("SequenceNumber");
|
||||||
|
|
||||||
|
b.Property<int>("Stars");
|
||||||
|
|
||||||
|
b.Property<DateTime>("TimeAdded");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClashWarId");
|
||||||
|
|
||||||
|
b.ToTable("ClashCallers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashWar", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<string>("EnemyClan");
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId");
|
||||||
|
|
||||||
|
b.Property<int>("Size");
|
||||||
|
|
||||||
|
b.Property<DateTime>("StartedAt");
|
||||||
|
|
||||||
|
b.Property<int>("WarState");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ClashOfClans");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("CommandName");
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId");
|
||||||
|
|
||||||
|
b.Property<int>("Seconds");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId");
|
||||||
|
|
||||||
|
b.ToTable("CommandCooldown");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.ConvertUnit", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("InternalTrigger");
|
||||||
|
|
||||||
|
b.Property<decimal>("Modifier");
|
||||||
|
|
||||||
|
b.Property<string>("UnitType");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ConversionUnits");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Currency", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<long>("Amount");
|
||||||
|
|
||||||
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Currency");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<long>("Amount");
|
||||||
|
|
||||||
|
b.Property<string>("Reason");
|
||||||
|
|
||||||
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CurrencyTransactions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.CustomReaction", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong?>("GuildId");
|
||||||
|
|
||||||
|
b.Property<bool>("IsRegex");
|
||||||
|
|
||||||
|
b.Property<bool>("OwnerOnly");
|
||||||
|
|
||||||
|
b.Property<string>("Response");
|
||||||
|
|
||||||
|
b.Property<string>("Trigger");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CustomReactions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Donator", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("Amount");
|
||||||
|
|
||||||
|
b.Property<string>("Name");
|
||||||
|
|
||||||
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Donators");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("BotConfigId");
|
||||||
|
|
||||||
|
b.Property<string>("Text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BotConfigId");
|
||||||
|
|
||||||
|
b.ToTable("EightBallResponses");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId");
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId1");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId1");
|
||||||
|
|
||||||
|
b.ToTable("FilterChannelId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId");
|
||||||
|
|
||||||
|
b.Property<string>("Word");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId");
|
||||||
|
|
||||||
|
b.ToTable("FilteredWord");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId");
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Username");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId");
|
||||||
|
|
||||||
|
b.ToTable("FollowedStream");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId");
|
||||||
|
|
||||||
|
b.ToTable("GCChannelId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("AutoAssignRoleId");
|
||||||
|
|
||||||
|
b.Property<bool>("AutoDeleteByeMessages");
|
||||||
|
|
||||||
|
b.Property<int>("AutoDeleteByeMessagesTimer");
|
||||||
|
|
||||||
|
b.Property<bool>("AutoDeleteGreetMessages");
|
||||||
|
|
||||||
|
b.Property<int>("AutoDeleteGreetMessagesTimer");
|
||||||
|
|
||||||
|
b.Property<bool>("AutoDeleteSelfAssignedRoleMessages");
|
||||||
|
|
||||||
|
b.Property<ulong>("ByeMessageChannelId");
|
||||||
|
|
||||||
|
b.Property<string>("ChannelByeMessageText");
|
||||||
|
|
||||||
|
b.Property<string>("ChannelGreetMessageText");
|
||||||
|
|
||||||
|
b.Property<bool>("CleverbotEnabled");
|
||||||
|
|
||||||
|
b.Property<float>("DefaultMusicVolume");
|
||||||
|
|
||||||
|
b.Property<bool>("DeleteMessageOnCommand");
|
||||||
|
|
||||||
|
b.Property<string>("DmGreetMessageText");
|
||||||
|
|
||||||
|
b.Property<bool>("ExclusiveSelfAssignedRoles");
|
||||||
|
|
||||||
|
b.Property<bool>("FilterInvites");
|
||||||
|
|
||||||
|
b.Property<bool>("FilterWords");
|
||||||
|
|
||||||
|
b.Property<ulong>("GreetMessageChannelId");
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId");
|
||||||
|
|
||||||
|
b.Property<int?>("LogSettingId");
|
||||||
|
|
||||||
|
b.Property<string>("MuteRoleName");
|
||||||
|
|
||||||
|
b.Property<string>("PermissionRole");
|
||||||
|
|
||||||
|
b.Property<int?>("RootPermissionId");
|
||||||
|
|
||||||
|
b.Property<bool>("SendChannelByeMessage");
|
||||||
|
|
||||||
|
b.Property<bool>("SendChannelGreetMessage");
|
||||||
|
|
||||||
|
b.Property<bool>("SendDmGreetMessage");
|
||||||
|
|
||||||
|
b.Property<bool>("VerbosePermissions");
|
||||||
|
|
||||||
|
b.Property<bool>("VoicePlusTextEnabled");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.HasIndex("LogSettingId");
|
||||||
|
|
||||||
|
b.HasIndex("RootPermissionId");
|
||||||
|
|
||||||
|
b.ToTable("GuildConfigs");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogChannel", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<int?>("LogSettingId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("LogSettingId");
|
||||||
|
|
||||||
|
b.ToTable("IgnoredLogChannels");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<int?>("LogSettingId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("LogSettingId");
|
||||||
|
|
||||||
|
b.ToTable("IgnoredVoicePresenceCHannels");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("ChannelCreated");
|
||||||
|
|
||||||
|
b.Property<ulong?>("ChannelCreatedId");
|
||||||
|
|
||||||
|
b.Property<bool>("ChannelDestroyed");
|
||||||
|
|
||||||
|
b.Property<ulong?>("ChannelDestroyedId");
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<bool>("ChannelUpdated");
|
||||||
|
|
||||||
|
b.Property<ulong?>("ChannelUpdatedId");
|
||||||
|
|
||||||
|
b.Property<bool>("IsLogging");
|
||||||
|
|
||||||
|
b.Property<ulong?>("LogOtherId");
|
||||||
|
|
||||||
|
b.Property<bool>("LogUserPresence");
|
||||||
|
|
||||||
|
b.Property<ulong?>("LogUserPresenceId");
|
||||||
|
|
||||||
|
b.Property<bool>("LogVoicePresence");
|
||||||
|
|
||||||
|
b.Property<ulong?>("LogVoicePresenceId");
|
||||||
|
|
||||||
|
b.Property<ulong?>("LogVoicePresenceTTSId");
|
||||||
|
|
||||||
|
b.Property<bool>("MessageDeleted");
|
||||||
|
|
||||||
|
b.Property<ulong?>("MessageDeletedId");
|
||||||
|
|
||||||
|
b.Property<bool>("MessageUpdated");
|
||||||
|
|
||||||
|
b.Property<ulong?>("MessageUpdatedId");
|
||||||
|
|
||||||
|
b.Property<bool>("UserBanned");
|
||||||
|
|
||||||
|
b.Property<ulong?>("UserBannedId");
|
||||||
|
|
||||||
|
b.Property<bool>("UserJoined");
|
||||||
|
|
||||||
|
b.Property<ulong?>("UserJoinedId");
|
||||||
|
|
||||||
|
b.Property<bool>("UserLeft");
|
||||||
|
|
||||||
|
b.Property<ulong?>("UserLeftId");
|
||||||
|
|
||||||
|
b.Property<ulong?>("UserMutedId");
|
||||||
|
|
||||||
|
b.Property<ulong>("UserPresenceChannelId");
|
||||||
|
|
||||||
|
b.Property<bool>("UserUnbanned");
|
||||||
|
|
||||||
|
b.Property<ulong?>("UserUnbannedId");
|
||||||
|
|
||||||
|
b.Property<bool>("UserUpdated");
|
||||||
|
|
||||||
|
b.Property<ulong?>("UserUpdatedId");
|
||||||
|
|
||||||
|
b.Property<ulong>("VoicePresenceChannelId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("LogSettings");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("BotConfigId");
|
||||||
|
|
||||||
|
b.Property<string>("ModuleName");
|
||||||
|
|
||||||
|
b.Property<string>("Prefix");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BotConfigId");
|
||||||
|
|
||||||
|
b.ToTable("ModulePrefixes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Author");
|
||||||
|
|
||||||
|
b.Property<ulong>("AuthorId");
|
||||||
|
|
||||||
|
b.Property<string>("Name");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("MusicPlaylists");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId");
|
||||||
|
|
||||||
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId");
|
||||||
|
|
||||||
|
b.ToTable("MutedUserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("NextId");
|
||||||
|
|
||||||
|
b.Property<int>("PrimaryTarget");
|
||||||
|
|
||||||
|
b.Property<ulong>("PrimaryTargetId");
|
||||||
|
|
||||||
|
b.Property<int>("SecondaryTarget");
|
||||||
|
|
||||||
|
b.Property<string>("SecondaryTargetName");
|
||||||
|
|
||||||
|
b.Property<bool>("State");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NextId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Permission");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("BotConfigId");
|
||||||
|
|
||||||
|
b.Property<string>("Status");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BotConfigId");
|
||||||
|
|
||||||
|
b.ToTable("PlayingStatus");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("MusicPlaylistId");
|
||||||
|
|
||||||
|
b.Property<string>("Provider");
|
||||||
|
|
||||||
|
b.Property<int>("ProviderType");
|
||||||
|
|
||||||
|
b.Property<string>("Query");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("Uri");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("MusicPlaylistId");
|
||||||
|
|
||||||
|
b.ToTable("PlaylistSong");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("AuthorId");
|
||||||
|
|
||||||
|
b.Property<string>("AuthorName")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId");
|
||||||
|
|
||||||
|
b.Property<string>("Keyword")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Text")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Quotes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("BotConfigId");
|
||||||
|
|
||||||
|
b.Property<string>("Icon");
|
||||||
|
|
||||||
|
b.Property<string>("Name");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BotConfigId");
|
||||||
|
|
||||||
|
b.ToTable("RaceAnimals");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPrivate");
|
||||||
|
|
||||||
|
b.Property<string>("Message");
|
||||||
|
|
||||||
|
b.Property<ulong>("ServerId");
|
||||||
|
|
||||||
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("When");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Reminders");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId");
|
||||||
|
|
||||||
|
b.Property<TimeSpan>("Interval");
|
||||||
|
|
||||||
|
b.Property<string>("Message");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ChannelId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Repeaters");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId");
|
||||||
|
|
||||||
|
b.Property<ulong>("RoleId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildId", "RoleId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("SelfAssignableRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.UserPokeTypes", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
|
b.Property<string>("type");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("PokeGame");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
|
||||||
|
.WithMany("Blacklist")
|
||||||
|
.HasForeignKey("BotConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.ClashWar", "ClashWar")
|
||||||
|
.WithMany("Bases")
|
||||||
|
.HasForeignKey("ClashWarId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("CommandCooldowns")
|
||||||
|
.HasForeignKey("GuildConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
|
||||||
|
.WithMany("EightBallResponses")
|
||||||
|
.HasForeignKey("BotConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("FilterInvitesChannelIds")
|
||||||
|
.HasForeignKey("GuildConfigId");
|
||||||
|
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("FilterWordsChannelIds")
|
||||||
|
.HasForeignKey("GuildConfigId1");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("FilteredWords")
|
||||||
|
.HasForeignKey("GuildConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("FollowedStreams")
|
||||||
|
.HasForeignKey("GuildConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("GenerateCurrencyChannelIds")
|
||||||
|
.HasForeignKey("GuildConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("LogSettingId");
|
||||||
|
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.Permission", "RootPermission")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RootPermissionId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogChannel", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting")
|
||||||
|
.WithMany("IgnoredChannels")
|
||||||
|
.HasForeignKey("LogSettingId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting")
|
||||||
|
.WithMany("IgnoredVoicePresenceChannelIds")
|
||||||
|
.HasForeignKey("LogSettingId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
|
||||||
|
.WithMany("ModulePrefixes")
|
||||||
|
.HasForeignKey("BotConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("MutedUsers")
|
||||||
|
.HasForeignKey("GuildConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.Permission", "Next")
|
||||||
|
.WithOne("Previous")
|
||||||
|
.HasForeignKey("NadekoBot.Services.Database.Models.Permission", "NextId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
|
||||||
|
.WithMany("RotatingStatusMessages")
|
||||||
|
.HasForeignKey("BotConfigId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.MusicPlaylist")
|
||||||
|
.WithMany("Songs")
|
||||||
|
.HasForeignKey("MusicPlaylistId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
|
||||||
|
.WithMany("RaceAnimals")
|
||||||
|
.HasForeignKey("BotConfigId");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
150
src/NadekoBot/Migrations/20161224032833_logsettings.cs
Normal file
150
src/NadekoBot/Migrations/20161224032833_logsettings.cs
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations
|
||||||
|
{
|
||||||
|
public partial class logsettings : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "ChannelCreatedId",
|
||||||
|
table: "LogSettings",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "ChannelDestroyedId",
|
||||||
|
table: "LogSettings",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "ChannelUpdatedId",
|
||||||
|
table: "LogSettings",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "LogOtherId",
|
||||||
|
table: "LogSettings",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "LogUserPresenceId",
|
||||||
|
table: "LogSettings",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "LogVoicePresenceId",
|
||||||
|
table: "LogSettings",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "LogVoicePresenceTTSId",
|
||||||
|
table: "LogSettings",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "MessageDeletedId",
|
||||||
|
table: "LogSettings",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "MessageUpdatedId",
|
||||||
|
table: "LogSettings",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "UserBannedId",
|
||||||
|
table: "LogSettings",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "UserJoinedId",
|
||||||
|
table: "LogSettings",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "UserLeftId",
|
||||||
|
table: "LogSettings",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "UserMutedId",
|
||||||
|
table: "LogSettings",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "UserUnbannedId",
|
||||||
|
table: "LogSettings",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "UserUpdatedId",
|
||||||
|
table: "LogSettings",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "ChannelCreatedId",
|
||||||
|
table: "LogSettings");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "ChannelDestroyedId",
|
||||||
|
table: "LogSettings");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "ChannelUpdatedId",
|
||||||
|
table: "LogSettings");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "LogOtherId",
|
||||||
|
table: "LogSettings");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "LogUserPresenceId",
|
||||||
|
table: "LogSettings");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "LogVoicePresenceId",
|
||||||
|
table: "LogSettings");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "LogVoicePresenceTTSId",
|
||||||
|
table: "LogSettings");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "MessageDeletedId",
|
||||||
|
table: "LogSettings");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "MessageUpdatedId",
|
||||||
|
table: "LogSettings");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "UserBannedId",
|
||||||
|
table: "LogSettings");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "UserJoinedId",
|
||||||
|
table: "LogSettings");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "UserLeftId",
|
||||||
|
table: "LogSettings");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "UserMutedId",
|
||||||
|
table: "LogSettings");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "UserUnbannedId",
|
||||||
|
table: "LogSettings");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "UserUpdatedId",
|
||||||
|
table: "LogSettings");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -423,34 +423,64 @@ namespace NadekoBot.Migrations
|
|||||||
|
|
||||||
b.Property<bool>("ChannelCreated");
|
b.Property<bool>("ChannelCreated");
|
||||||
|
|
||||||
|
b.Property<ulong?>("ChannelCreatedId");
|
||||||
|
|
||||||
b.Property<bool>("ChannelDestroyed");
|
b.Property<bool>("ChannelDestroyed");
|
||||||
|
|
||||||
|
b.Property<ulong?>("ChannelDestroyedId");
|
||||||
|
|
||||||
b.Property<ulong>("ChannelId");
|
b.Property<ulong>("ChannelId");
|
||||||
|
|
||||||
b.Property<bool>("ChannelUpdated");
|
b.Property<bool>("ChannelUpdated");
|
||||||
|
|
||||||
|
b.Property<ulong?>("ChannelUpdatedId");
|
||||||
|
|
||||||
b.Property<bool>("IsLogging");
|
b.Property<bool>("IsLogging");
|
||||||
|
|
||||||
|
b.Property<ulong?>("LogOtherId");
|
||||||
|
|
||||||
b.Property<bool>("LogUserPresence");
|
b.Property<bool>("LogUserPresence");
|
||||||
|
|
||||||
|
b.Property<ulong?>("LogUserPresenceId");
|
||||||
|
|
||||||
b.Property<bool>("LogVoicePresence");
|
b.Property<bool>("LogVoicePresence");
|
||||||
|
|
||||||
|
b.Property<ulong?>("LogVoicePresenceId");
|
||||||
|
|
||||||
|
b.Property<ulong?>("LogVoicePresenceTTSId");
|
||||||
|
|
||||||
b.Property<bool>("MessageDeleted");
|
b.Property<bool>("MessageDeleted");
|
||||||
|
|
||||||
|
b.Property<ulong?>("MessageDeletedId");
|
||||||
|
|
||||||
b.Property<bool>("MessageUpdated");
|
b.Property<bool>("MessageUpdated");
|
||||||
|
|
||||||
|
b.Property<ulong?>("MessageUpdatedId");
|
||||||
|
|
||||||
b.Property<bool>("UserBanned");
|
b.Property<bool>("UserBanned");
|
||||||
|
|
||||||
|
b.Property<ulong?>("UserBannedId");
|
||||||
|
|
||||||
b.Property<bool>("UserJoined");
|
b.Property<bool>("UserJoined");
|
||||||
|
|
||||||
|
b.Property<ulong?>("UserJoinedId");
|
||||||
|
|
||||||
b.Property<bool>("UserLeft");
|
b.Property<bool>("UserLeft");
|
||||||
|
|
||||||
|
b.Property<ulong?>("UserLeftId");
|
||||||
|
|
||||||
|
b.Property<ulong?>("UserMutedId");
|
||||||
|
|
||||||
b.Property<ulong>("UserPresenceChannelId");
|
b.Property<ulong>("UserPresenceChannelId");
|
||||||
|
|
||||||
b.Property<bool>("UserUnbanned");
|
b.Property<bool>("UserUnbanned");
|
||||||
|
|
||||||
|
b.Property<ulong?>("UserUnbannedId");
|
||||||
|
|
||||||
b.Property<bool>("UserUpdated");
|
b.Property<bool>("UserUpdated");
|
||||||
|
|
||||||
|
b.Property<ulong?>("UserUpdatedId");
|
||||||
|
|
||||||
b.Property<ulong>("VoicePresenceChannelId");
|
b.Property<ulong>("VoicePresenceChannelId");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
@ -492,6 +522,22 @@ namespace NadekoBot.Migrations
|
|||||||
b.ToTable("MusicPlaylists");
|
b.ToTable("MusicPlaylists");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("GuildConfigId");
|
||||||
|
|
||||||
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId");
|
||||||
|
|
||||||
|
b.ToTable("MutedUserId");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@ -658,6 +704,23 @@ namespace NadekoBot.Migrations
|
|||||||
b.ToTable("SelfAssignableRoles");
|
b.ToTable("SelfAssignableRoles");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.UserPokeTypes", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
|
b.Property<string>("type");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("PokeGame");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
|
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
|
||||||
@ -751,6 +814,13 @@ namespace NadekoBot.Migrations
|
|||||||
.HasForeignKey("BotConfigId");
|
.HasForeignKey("BotConfigId");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
|
.WithMany("MutedUsers")
|
||||||
|
.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")
|
||||||
|
@ -15,6 +15,9 @@ using System.Net.Http;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using static NadekoBot.Modules.Permissions.Permissions;
|
using static NadekoBot.Modules.Permissions.Permissions;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using NLog;
|
||||||
|
using NadekoBot.Services.Database;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
||||||
@ -24,27 +27,25 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
private static ConcurrentDictionary<ulong, string> GuildMuteRoles { get; } = new ConcurrentDictionary<ulong, string>();
|
private static ConcurrentDictionary<ulong, string> GuildMuteRoles { get; } = new ConcurrentDictionary<ulong, string>();
|
||||||
|
|
||||||
public Administration(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
|
private new static Logger _log { get; }
|
||||||
|
|
||||||
|
public Administration() : base()
|
||||||
{
|
{
|
||||||
NadekoBot.CommandHandler.CommandExecuted += DelMsgOnCmd_Handler;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Administration()
|
static Administration()
|
||||||
{
|
{
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
{
|
NadekoBot.CommandHandler.CommandExecuted += DelMsgOnCmd_Handler;
|
||||||
var configs = NadekoBot.AllGuildConfigs;
|
|
||||||
GuildMuteRoles = new ConcurrentDictionary<ulong, string>(configs
|
|
||||||
.Where(c=>!string.IsNullOrWhiteSpace(c.MuteRoleName))
|
|
||||||
.ToDictionary(c => c.GuildId, c => c.MuteRoleName));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void DelMsgOnCmd_Handler(object sender, CommandExecutedEventArgs e)
|
private static async Task DelMsgOnCmd_Handler(IUserMessage msg, Command cmd)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var channel = e.Message.Channel as ITextChannel;
|
var channel = msg.Channel as ITextChannel;
|
||||||
if (channel == null)
|
if (channel == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -52,11 +53,11 @@ namespace NadekoBot.Modules.Administration
|
|||||||
bool shouldDelete;
|
bool shouldDelete;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
shouldDelete = uow.GuildConfigs.For(channel.Guild.Id).DeleteMessageOnCommand;
|
shouldDelete = uow.GuildConfigs.For(channel.Guild.Id, set => set).DeleteMessageOnCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldDelete)
|
if (shouldDelete)
|
||||||
await e.Message.DeleteAsync().ConfigureAwait(false);
|
await msg.DeleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -64,39 +65,6 @@ namespace NadekoBot.Modules.Administration
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<IRole> GetMuteRole(IGuild guild)
|
|
||||||
{
|
|
||||||
const string defaultMuteRoleName = "nadeko-mute";
|
|
||||||
|
|
||||||
var muteRoleName = GuildMuteRoles.GetOrAdd(guild.Id, defaultMuteRoleName);
|
|
||||||
|
|
||||||
var muteRole = guild.Roles.FirstOrDefault(r => r.Name == muteRoleName);
|
|
||||||
if (muteRole == null)
|
|
||||||
{
|
|
||||||
|
|
||||||
//if it doesn't exist, create it
|
|
||||||
try { muteRole = await guild.CreateRoleAsync(muteRoleName, GuildPermissions.None).ConfigureAwait(false); }
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
//if creations fails, maybe the name is not correct, find default one, if doesn't work, create default one
|
|
||||||
muteRole = guild.Roles.FirstOrDefault(r => r.Name == muteRoleName) ??
|
|
||||||
await guild.CreateRoleAsync(defaultMuteRoleName, GuildPermissions.None).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var toOverwrite in guild.GetTextChannels())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await toOverwrite.AddPermissionOverwriteAsync(muteRole, new OverwritePermissions(sendMessages: PermValue.Deny, attachFiles: PermValue.Deny))
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
await Task.Delay(200).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return muteRole;
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[RequirePermission(GuildPermission.Administrator)]
|
[RequirePermission(GuildPermission.Administrator)]
|
||||||
@ -119,7 +87,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
await uow.CompleteAsync();
|
await uow.CompleteAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync($"{imsg.Author.Mention} 🆗 **Permissions for this server are reset.**");
|
await channel.SendConfirmAsync($"{imsg.Author.Mention} 🆗 **Permissions for this server are reset.**");
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -128,18 +96,18 @@ namespace NadekoBot.Modules.Administration
|
|||||||
public async Task Delmsgoncmd(IUserMessage umsg)
|
public async Task Delmsgoncmd(IUserMessage umsg)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
GuildConfig conf;
|
bool enabled;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
conf = uow.GuildConfigs.For(channel.Guild.Id);
|
var conf = uow.GuildConfigs.For(channel.Guild.Id, set => set);
|
||||||
conf.DeleteMessageOnCommand = !conf.DeleteMessageOnCommand;
|
enabled = conf.DeleteMessageOnCommand = !conf.DeleteMessageOnCommand;
|
||||||
uow.GuildConfigs.Update(conf);
|
|
||||||
await uow.CompleteAsync();
|
await uow.CompleteAsync();
|
||||||
}
|
}
|
||||||
if (conf.DeleteMessageOnCommand)
|
if (enabled)
|
||||||
await channel.SendMessageAsync("✅ **Now automatically deleting successful command invokations.**").ConfigureAwait(false);
|
await channel.SendConfirmAsync("✅ **Now automatically deleting successful command invokations.**").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync("❗**Stopped automatic deletion of successful command invokations.**").ConfigureAwait(false);
|
await channel.SendConfirmAsync("❗**Stopped automatic deletion of successful command invokations.**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -151,11 +119,11 @@ namespace NadekoBot.Modules.Administration
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await usr.AddRolesAsync(role).ConfigureAwait(false);
|
await usr.AddRolesAsync(role).ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync($"ℹ️ Successfully added role **{role.Name}** to user **{usr.Username}**").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"ℹ️ Successfully added role **{role.Name}** to user **{usr.Username}**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ Failed to add role. **Bot has insufficient permissions.**\n").ConfigureAwait(false);
|
await channel.SendErrorAsync("⚠️ Failed to add role. **Bot has insufficient permissions.**\n").ConfigureAwait(false);
|
||||||
Console.WriteLine(ex.ToString());
|
Console.WriteLine(ex.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -169,11 +137,11 @@ namespace NadekoBot.Modules.Administration
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await usr.RemoveRolesAsync(role).ConfigureAwait(false);
|
await usr.RemoveRolesAsync(role).ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync($"ℹ️ Successfully removed role **{role.Name}** from user **{usr.Username}**").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"ℹ️ Successfully removed role **{role.Name}** from user **{usr.Username}**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ Failed to remove role. Most likely reason: **Insufficient permissions.**").ConfigureAwait(false);
|
await channel.SendErrorAsync("⚠️ Failed to remove role. Most likely reason: **Insufficient permissions.**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,15 +155,15 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
if (roleToEdit.Position > (await channel.Guild.GetCurrentUserAsync().ConfigureAwait(false)).Roles.Max(r => r.Position))
|
if (roleToEdit.Position > (await channel.Guild.GetCurrentUserAsync().ConfigureAwait(false)).Roles.Max(r => r.Position))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("🚫 You can't edit roles higher than your highest role.").ConfigureAwait(false);
|
await channel.SendErrorAsync("🚫 You can't edit roles higher than your highest role.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await roleToEdit.ModifyAsync(g => g.Name = newname).ConfigureAwait(false);
|
await roleToEdit.ModifyAsync(g => g.Name = newname).ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync("✅ Role renamed.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("✅ Role renamed.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ Failed to rename role. Probably **insufficient permissions.**").ConfigureAwait(false);
|
await channel.SendErrorAsync("⚠️ Failed to rename role. Probably **insufficient permissions.**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,11 +177,11 @@ namespace NadekoBot.Modules.Administration
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await user.RemoveRolesAsync(user.Roles).ConfigureAwait(false);
|
await user.RemoveRolesAsync(user.Roles).ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync($"🗑 Successfully removed **all** roles from user **{user.Username}**").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"🗑 Successfully removed **all** roles from user **{user.Username}**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ Failed to remove roles. Most likely reason: **Insufficient permissions.**").ConfigureAwait(false);
|
await channel.SendErrorAsync("⚠️ Failed to remove roles. Most likely reason: **Insufficient permissions.**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,11 +198,11 @@ namespace NadekoBot.Modules.Administration
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var r = await channel.Guild.CreateRoleAsync(roleName).ConfigureAwait(false);
|
var r = await channel.Guild.CreateRoleAsync(roleName).ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync($"✅ Successfully created role **{r.Name}**.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"✅ Successfully created role **{r.Name}**.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ Unspecified error.").ConfigureAwait(false);
|
await channel.SendErrorAsync("⚠️ Unspecified error.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,15 +215,15 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
if (args.Count() != 2 && args.Count() != 4)
|
if (args.Count() != 2 && args.Count() != 4)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("❌ The parameters specified are **invalid.**").ConfigureAwait(false);
|
await channel.SendErrorAsync("❌ The parameters specified are **invalid.**").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var roleName = args[0].ToUpperInvariant();
|
var roleName = args[0].ToUpperInvariant();
|
||||||
var role = channel.Guild.Roles.Where(r=>r.Name.ToUpperInvariant() == roleName).FirstOrDefault();
|
var role = channel.Guild.Roles.Where(r => r.Name.ToUpperInvariant() == roleName).FirstOrDefault();
|
||||||
|
|
||||||
if (role == null)
|
if (role == null)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("🚫 That role **does not exist.**").ConfigureAwait(false);
|
await channel.SendErrorAsync("🚫 That role **does not exist.**").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
@ -268,11 +236,11 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var blue = Convert.ToByte(rgb ? int.Parse(args[3]) : Convert.ToInt32(arg1.Substring(4, 2), 16));
|
var blue = Convert.ToByte(rgb ? int.Parse(args[3]) : Convert.ToInt32(arg1.Substring(4, 2), 16));
|
||||||
|
|
||||||
await role.ModifyAsync(r => r.Color = new Discord.Color(red, green, blue).RawValue).ConfigureAwait(false);
|
await role.ModifyAsync(r => r.Color = new Discord.Color(red, green, blue).RawValue).ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync($"☑️ Role **{role.Name}'s** color has been changed.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"☑️ Role **{role.Name}'s** color has been changed.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ Error occured, most likely **invalid parameters** or **insufficient permissions.**").ConfigureAwait(false);
|
await channel.SendErrorAsync("⚠️ Error occured, most likely **invalid parameters** or **insufficient permissions.**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,14 +254,14 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
msg = "❗️No reason provided.";
|
msg = "❗️No reason provided.";
|
||||||
}
|
}
|
||||||
if (umsg.Author.Id != user.Guild.OwnerId && user.Roles.Select(r=>r.Position).Max() >= ((IGuildUser)umsg.Author).Roles.Select(r => r.Position).Max())
|
if (umsg.Author.Id != user.Guild.OwnerId && user.Roles.Select(r => r.Position).Max() >= ((IGuildUser)umsg.Author).Roles.Select(r => r.Position).Max())
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ You can't use this command on users with a role higher or equal to yours in the role hierarchy.");
|
await channel.SendErrorAsync("⚠️ You can't use this command on users with a role higher or equal to yours in the role hierarchy.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await (await user.CreateDMChannelAsync()).SendMessageAsync($"⛔️ **You have been BANNED from `{channel.Guild.Name}` server.**\n" +
|
await (await user.CreateDMChannelAsync()).SendErrorAsync($"⛔️ **You have been BANNED from `{channel.Guild.Name}` server.**\n" +
|
||||||
$"⚖ *Reason:* {msg}").ConfigureAwait(false);
|
$"⚖ *Reason:* {msg}").ConfigureAwait(false);
|
||||||
await Task.Delay(2000).ConfigureAwait(false);
|
await Task.Delay(2000).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -302,11 +270,11 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
await channel.Guild.AddBanAsync(user, 7).ConfigureAwait(false);
|
await channel.Guild.AddBanAsync(user, 7).ConfigureAwait(false);
|
||||||
|
|
||||||
await channel.SendMessageAsync("⛔️ **Banned** user **" + user.Username + "** ID: `" + user.Id + "`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("⛔️ **Banned** user **" + user.Username + "** ID: `" + user.Id + "`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ **Error.** Most likely I don't have sufficient permissions.").ConfigureAwait(false);
|
await channel.SendErrorAsync("⚠️ **Error.** Most likely I don't have sufficient permissions.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,12 +291,12 @@ namespace NadekoBot.Modules.Administration
|
|||||||
}
|
}
|
||||||
if (umsg.Author.Id != user.Guild.OwnerId && user.Roles.Select(r => r.Position).Max() >= ((IGuildUser)umsg.Author).Roles.Select(r => r.Position).Max())
|
if (umsg.Author.Id != user.Guild.OwnerId && user.Roles.Select(r => r.Position).Max() >= ((IGuildUser)umsg.Author).Roles.Select(r => r.Position).Max())
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ You can't use this command on users with a role higher or equal to yours in the role hierarchy.");
|
await channel.SendErrorAsync("⚠️ You can't use this command on users with a role higher or equal to yours in the role hierarchy.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await user.SendMessageAsync($"☣ **You have been SOFT-BANNED from `{channel.Guild.Name}` server.**\n" +
|
await user.SendErrorAsync($"☣ **You have been SOFT-BANNED from `{channel.Guild.Name}` server.**\n" +
|
||||||
$"⚖ *Reason:* {msg}").ConfigureAwait(false);
|
$"⚖ *Reason:* {msg}").ConfigureAwait(false);
|
||||||
await Task.Delay(2000).ConfigureAwait(false);
|
await Task.Delay(2000).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -339,11 +307,11 @@ namespace NadekoBot.Modules.Administration
|
|||||||
try { await channel.Guild.RemoveBanAsync(user).ConfigureAwait(false); }
|
try { await channel.Guild.RemoveBanAsync(user).ConfigureAwait(false); }
|
||||||
catch { await channel.Guild.RemoveBanAsync(user).ConfigureAwait(false); }
|
catch { await channel.Guild.RemoveBanAsync(user).ConfigureAwait(false); }
|
||||||
|
|
||||||
await channel.SendMessageAsync("☣ **Soft-Banned** user **" + user.Username + "** ID: `" + user.Id + "`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("☣ **Soft-Banned** user **" + user.Username + "** ID: `" + user.Id + "`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ Error. Most likely I don't have sufficient permissions.").ConfigureAwait(false);
|
await channel.SendErrorAsync("⚠️ Error. Most likely I don't have sufficient permissions.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,20 +324,20 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("❗️User not found.").ConfigureAwait(false);
|
await channel.SendErrorAsync("❗️User not found.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (umsg.Author.Id != user.Guild.OwnerId && user.Roles.Select(r => r.Position).Max() >= ((IGuildUser)umsg.Author).Roles.Select(r => r.Position).Max())
|
if (umsg.Author.Id != user.Guild.OwnerId && user.Roles.Select(r => r.Position).Max() >= ((IGuildUser)umsg.Author).Roles.Select(r => r.Position).Max())
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ You can't use this command on users with a role higher or equal to yours in the role hierarchy.");
|
await channel.SendErrorAsync("⚠️ You can't use this command on users with a role higher or equal to yours in the role hierarchy.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!string.IsNullOrWhiteSpace(msg))
|
if (!string.IsNullOrWhiteSpace(msg))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await user.SendMessageAsync($"‼️**You have been KICKED from `{channel.Guild.Name}` server.**\n" +
|
await user.SendErrorAsync($"‼️**You have been KICKED from `{channel.Guild.Name}` server.**\n" +
|
||||||
$"⚖ *Reason:* {msg}").ConfigureAwait(false);
|
$"⚖ *Reason:* {msg}").ConfigureAwait(false);
|
||||||
await Task.Delay(2000).ConfigureAwait(false);
|
await Task.Delay(2000).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -378,150 +346,11 @@ namespace NadekoBot.Modules.Administration
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await user.KickAsync().ConfigureAwait(false);
|
await user.KickAsync().ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync("‼️**Kicked** user **" + user.Username + "** ID: `" + user.Id + "`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("‼️**Kicked** user **" + user.Username + "** ID: `" + user.Id + "`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ Error. Most likely I don't have sufficient permissions.").ConfigureAwait(false);
|
await channel.SendErrorAsync("⚠️ Error. Most likely I don't have sufficient permissions.").ConfigureAwait(false);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[RequirePermission(GuildPermission.ManageRoles)]
|
|
||||||
[Priority(1)]
|
|
||||||
public async Task SetMuteRole(IUserMessage imsg, [Remainder] string name)
|
|
||||||
{
|
|
||||||
var channel = (ITextChannel)imsg.Channel;
|
|
||||||
name = name.Trim();
|
|
||||||
if (string.IsNullOrWhiteSpace(name))
|
|
||||||
return;
|
|
||||||
|
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
|
||||||
{
|
|
||||||
var config = uow.GuildConfigs.For(channel.Guild.Id);
|
|
||||||
config.MuteRoleName = name;
|
|
||||||
GuildMuteRoles.AddOrUpdate(channel.Guild.Id, name, (id, old) => name);
|
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
await channel.SendMessageAsync("☑️ **New mute role set.**").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[RequirePermission(GuildPermission.ManageRoles)]
|
|
||||||
[Priority(0)]
|
|
||||||
public Task SetMuteRole(IUserMessage imsg, [Remainder] IRole role)
|
|
||||||
=> SetMuteRole(imsg, role.Name);
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[RequirePermission(GuildPermission.ManageRoles)]
|
|
||||||
[RequirePermission(GuildPermission.MuteMembers)]
|
|
||||||
public async Task Mute(IUserMessage umsg, IGuildUser user)
|
|
||||||
{
|
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await user.ModifyAsync(usr => usr.Mute = true).ConfigureAwait(false);
|
|
||||||
await user.AddRolesAsync(await GetMuteRole(channel.Guild).ConfigureAwait(false)).ConfigureAwait(false);
|
|
||||||
await channel.SendMessageAsync($"🔇 **{user}** has been **muted** from text and voice chat successfully.").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
await channel.SendMessageAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[RequirePermission(GuildPermission.ManageRoles)]
|
|
||||||
[RequirePermission(GuildPermission.MuteMembers)]
|
|
||||||
public async Task Unmute(IUserMessage umsg, IGuildUser user)
|
|
||||||
{
|
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await user.ModifyAsync(usr => usr.Mute = false).ConfigureAwait(false);
|
|
||||||
await user.RemoveRolesAsync(await GetMuteRole(channel.Guild).ConfigureAwait(false)).ConfigureAwait(false);
|
|
||||||
await channel.SendMessageAsync($"🔉 **{user}** has been **unmuted** from text and voice chat successfully.").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
await channel.SendMessageAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[RequirePermission(GuildPermission.ManageRoles)]
|
|
||||||
public async Task ChatMute(IUserMessage umsg, IGuildUser user)
|
|
||||||
{
|
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await user.AddRolesAsync(await GetMuteRole(channel.Guild).ConfigureAwait(false)).ConfigureAwait(false);
|
|
||||||
await channel.SendMessageAsync($"✏️🚫 **{user}** has been **muted** from chatting successfully.").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
await channel.SendMessageAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[RequirePermission(GuildPermission.ManageRoles)]
|
|
||||||
public async Task ChatUnmute(IUserMessage umsg, IGuildUser user)
|
|
||||||
{
|
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await user.RemoveRolesAsync(await GetMuteRole(channel.Guild).ConfigureAwait(false)).ConfigureAwait(false);
|
|
||||||
await channel.SendMessageAsync($"✏️✅ **{user}** has been **unmuted** from chatting successfully.").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
await channel.SendMessageAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[RequirePermission(GuildPermission.MuteMembers)]
|
|
||||||
public async Task VoiceMute(IUserMessage umsg, IGuildUser user)
|
|
||||||
{
|
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await user.ModifyAsync(usr => usr.Mute = true).ConfigureAwait(false);
|
|
||||||
await channel.SendMessageAsync($"🎙🚫 **{user}** has been **voice muted** successfully.").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
await channel.SendMessageAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[RequirePermission(GuildPermission.MuteMembers)]
|
|
||||||
public async Task VoiceUnmute(IUserMessage umsg, IGuildUser user)
|
|
||||||
{
|
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await user.ModifyAsync(usr => usr.Mute = false).ConfigureAwait(false);
|
|
||||||
await channel.SendMessageAsync($"🎙✅ **{user}** has been **voice unmuted** successfully.").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
await channel.SendMessageAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,13 +367,13 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
foreach (var u in users)
|
foreach (var u in users)
|
||||||
{
|
{
|
||||||
await u.ModifyAsync(usr=>usr.Deaf = true).ConfigureAwait(false);
|
await u.ModifyAsync(usr => usr.Deaf = true).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync("🔇 **Deafen** successful.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("🔇 **Deafen** successful.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
|
await channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -561,13 +390,13 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
foreach (var u in users)
|
foreach (var u in users)
|
||||||
{
|
{
|
||||||
await u.ModifyAsync(usr=> usr.Deaf = false).ConfigureAwait(false);
|
await u.ModifyAsync(usr => usr.Deaf = false).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync("🔊 **Undeafen** successful.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("🔊 **Undeafen** successful.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
|
await channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -577,7 +406,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
public async Task DelVoiChanl(IUserMessage umsg, [Remainder] IVoiceChannel voiceChannel)
|
public async Task DelVoiChanl(IUserMessage umsg, [Remainder] IVoiceChannel voiceChannel)
|
||||||
{
|
{
|
||||||
await voiceChannel.DeleteAsync().ConfigureAwait(false);
|
await voiceChannel.DeleteAsync().ConfigureAwait(false);
|
||||||
await umsg.Channel.SendMessageAsync($"🗑 Removed voice channel **{voiceChannel.Name}** successfully.").ConfigureAwait(false);
|
await umsg.Channel.SendConfirmAsync($"🗑 Removed voice channel **{voiceChannel.Name}** successfully.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -587,7 +416,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
var ch = await channel.Guild.CreateVoiceChannelAsync(channelName).ConfigureAwait(false);
|
var ch = await channel.Guild.CreateVoiceChannelAsync(channelName).ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync($"✅ Created voice channel **{ch.Name}**. ID: `{ch.Id}`").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"✅ Created voice channel **{ch.Name}**. ID: `{ch.Id}`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -596,7 +425,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
public async Task DelTxtChanl(IUserMessage umsg, [Remainder] ITextChannel toDelete)
|
public async Task DelTxtChanl(IUserMessage umsg, [Remainder] ITextChannel toDelete)
|
||||||
{
|
{
|
||||||
await toDelete.DeleteAsync().ConfigureAwait(false);
|
await toDelete.DeleteAsync().ConfigureAwait(false);
|
||||||
await umsg.Channel.SendMessageAsync($"🗑 Removed text channel **{toDelete.Name}**. ID: `{toDelete.Id}`").ConfigureAwait(false);
|
await umsg.Channel.SendConfirmAsync($"🗑 Removed text channel **{toDelete.Name}**. ID: `{toDelete.Id}`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -606,7 +435,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
var txtCh = await channel.Guild.CreateTextChannelAsync(channelName).ConfigureAwait(false);
|
var txtCh = await channel.Guild.CreateTextChannelAsync(channelName).ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync($"✅ Added text channel **{txtCh.Name}**. ID: `{txtCh.Id}`").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"✅ Added text channel **{txtCh.Name}**. ID: `{txtCh.Id}`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -617,7 +446,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
topic = topic ?? "";
|
topic = topic ?? "";
|
||||||
await channel.ModifyAsync(c => c.Topic = topic);
|
await channel.ModifyAsync(c => c.Topic = topic);
|
||||||
await channel.SendMessageAsync("🆗 **New channel topic set.**").ConfigureAwait(false);
|
await channel.SendConfirmAsync("🆗 **New channel topic set.**").ConfigureAwait(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -628,7 +457,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
await channel.ModifyAsync(c => c.Name = name).ConfigureAwait(false);
|
await channel.ModifyAsync(c => c.Name = name).ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync("🆗 **New channel name set.**").ConfigureAwait(false);
|
await channel.SendConfirmAsync("🆗 **New channel name set.**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -643,7 +472,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
var enumerable = (await umsg.Channel.GetMessagesAsync()).AsEnumerable();
|
var enumerable = (await umsg.Channel.GetMessagesAsync()).AsEnumerable();
|
||||||
enumerable = enumerable.Where(x => x.Author.Id == user.Id);
|
enumerable = enumerable.Where(x => x.Author.Id == user.Id);
|
||||||
await umsg.Channel.DeleteMessagesAsync(enumerable);
|
await umsg.Channel.DeleteMessagesAsync(enumerable).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// prune x
|
// prune x
|
||||||
@ -656,7 +485,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
await (msg as IUserMessage).DeleteAsync();
|
await (msg as IUserMessage).DeleteAsync();
|
||||||
int limit = (count < 100) ? count : 100;
|
int limit = (count < 100) ? count : 100;
|
||||||
var enumerable = (await msg.Channel.GetMessagesAsync(limit: limit));
|
var enumerable = (await msg.Channel.GetMessagesAsync(limit: limit));
|
||||||
await msg.Channel.DeleteMessagesAsync(enumerable);
|
await msg.Channel.DeleteMessagesAsync(enumerable).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//prune @user [x]
|
//prune @user [x]
|
||||||
@ -668,42 +497,34 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var channel = (ITextChannel)msg.Channel;
|
var channel = (ITextChannel)msg.Channel;
|
||||||
int limit = (count < 100) ? count : 100;
|
int limit = (count < 100) ? count : 100;
|
||||||
var enumerable = (await msg.Channel.GetMessagesAsync(limit: limit)).Where(m => m.Author == user);
|
var enumerable = (await msg.Channel.GetMessagesAsync(limit: limit)).Where(m => m.Author == user);
|
||||||
await msg.Channel.DeleteMessagesAsync(enumerable);
|
await msg.Channel.DeleteMessagesAsync(enumerable).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task Die(IUserMessage umsg)
|
public async Task Die(IUserMessage umsg)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
try { await umsg.Channel.SendConfirmAsync("ℹ️ **Shutting down.**").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||||
|
|
||||||
try { await channel.SendMessageAsync("ℹ️ **Shutting down.**").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
|
||||||
await Task.Delay(2000).ConfigureAwait(false);
|
await Task.Delay(2000).ConfigureAwait(false);
|
||||||
Environment.Exit(0);
|
Environment.Exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task Setname(IUserMessage umsg, [Remainder] string newName)
|
public async Task SetName(IUserMessage umsg, [Remainder] string newName)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
if (string.IsNullOrWhiteSpace(newName))
|
if (string.IsNullOrWhiteSpace(newName))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await (await NadekoBot.Client.GetCurrentUserAsync()).ModifyAsync(u => u.Username = newName).ConfigureAwait(false);
|
await (await NadekoBot.Client.GetCurrentUserAsync()).ModifyAsync(u => u.Username = newName).ConfigureAwait(false);
|
||||||
|
|
||||||
await channel.SendMessageAsync($"ℹ️ Successfully changed name to **{newName}**").ConfigureAwait(false);
|
await umsg.Channel.SendConfirmAsync($"ℹ️ Successfully changed name to **{newName}**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task SetAvatar(IUserMessage umsg, [Remainder] string img = null)
|
public async Task SetAvatar(IUserMessage umsg, [Remainder] string img = null)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(img))
|
if (string.IsNullOrWhiteSpace(img))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -719,44 +540,35 @@ namespace NadekoBot.Modules.Administration
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync("🆒 **New avatar set.**").ConfigureAwait(false);
|
await umsg.Channel.SendConfirmAsync("🆒 **New avatar set.**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task SetGame(IUserMessage umsg, [Remainder] string game = null)
|
public async Task SetGame(IUserMessage umsg, [Remainder] string game = null)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
|
|
||||||
game = game ?? "";
|
game = game ?? "";
|
||||||
|
|
||||||
await NadekoBot.Client.SetGame(game).ConfigureAwait(false);
|
await NadekoBot.Client.SetGame(game).ConfigureAwait(false);
|
||||||
|
|
||||||
await channel.SendMessageAsync("👾 **New game set.**").ConfigureAwait(false);
|
await umsg.Channel.SendConfirmAsync("👾 **New game set.**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task SetStream(IUserMessage umsg, string url, [Remainder] string name = null)
|
public async Task SetStream(IUserMessage umsg, string url, [Remainder] string name = null)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
|
|
||||||
name = name ?? "";
|
name = name ?? "";
|
||||||
|
|
||||||
await NadekoBot.Client.SetStream(name, url).ConfigureAwait(false);
|
await NadekoBot.Client.SetStream(name, url).ConfigureAwait(false);
|
||||||
|
|
||||||
await channel.SendMessageAsync("ℹ️ **New stream set.**").ConfigureAwait(false);
|
await umsg.Channel.SendConfirmAsync("ℹ️ **New stream set.**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task Send(IUserMessage umsg, string where, [Remainder] string msg = null)
|
public async Task Send(IUserMessage umsg, string where, [Remainder] string msg = null)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(msg))
|
if (string.IsNullOrWhiteSpace(msg))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -791,25 +603,24 @@ namespace NadekoBot.Modules.Administration
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ Invalid format.").ConfigureAwait(false);
|
await umsg.Channel.SendErrorAsync("⚠️ Invalid format.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task Announce(IUserMessage umsg, [Remainder] string message)
|
public async Task Announce(IUserMessage umsg, [Remainder] string message)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channels = await Task.WhenAll(NadekoBot.Client.GetGuilds().Select(g =>
|
||||||
|
|
||||||
var channels = await Task.WhenAll(_client.GetGuilds().Select(g =>
|
|
||||||
g.GetDefaultChannelAsync()
|
g.GetDefaultChannelAsync()
|
||||||
)).ConfigureAwait(false);
|
)).ConfigureAwait(false);
|
||||||
|
|
||||||
await Task.WhenAll(channels.Select(c => c.SendMessageAsync($"🆕 **Message from {umsg.Author} `(Bot Owner)`:** " + message)))
|
if (channels == null)
|
||||||
|
return;
|
||||||
|
await Task.WhenAll(channels.Where(c => c != null).Select(c => c.SendConfirmAsync($"🆕 Message from {umsg.Author} `[Bot Owner]`:", message)))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
await channel.SendMessageAsync("🆗").ConfigureAwait(false);
|
await umsg.Channel.SendConfirmAsync("🆗").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -839,8 +650,10 @@ namespace NadekoBot.Modules.Administration
|
|||||||
cnt -= 100;
|
cnt -= 100;
|
||||||
}
|
}
|
||||||
var title = $"Chatlog-{channel.Guild.Name}/#{channel.Name}-{DateTime.Now}.txt";
|
var title = $"Chatlog-{channel.Guild.Name}/#{channel.Name}-{DateTime.Now}.txt";
|
||||||
|
var grouping = msgs.GroupBy(x => $"{x.CreatedAt.Date:dd.MM.yyyy}")
|
||||||
|
.Select(g => new { date = g.Key, messages = g.OrderBy(x=>x.CreatedAt).Select(s => $"【{s.Timestamp:HH:mm:ss}】{s.Author}:" + s.ToString()) });
|
||||||
await (umsg.Author as IGuildUser).SendFileAsync(
|
await (umsg.Author as IGuildUser).SendFileAsync(
|
||||||
await JsonConvert.SerializeObject(new { Messages = msgs.Select(s => $"【{s.Timestamp:HH:mm:ss}】{s.Author}:" + s.ToString()) }, Formatting.Indented).ToStream().ConfigureAwait(false),
|
await JsonConvert.SerializeObject(grouping, Formatting.Indented).ToStream().ConfigureAwait(false),
|
||||||
title, title).ConfigureAwait(false);
|
title, title).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -852,11 +665,11 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
string send = $"❕{umsg.Author.Mention} __`has invoked a mention on the following roles`__❕";
|
string send = $"❕{umsg.Author.Mention} has invoked a mention on the following roles ❕";
|
||||||
foreach (var role in roles)
|
foreach (var role in roles)
|
||||||
{
|
{
|
||||||
send += $"\n**{role.Name}**\n";
|
send += $"\n**{role.Name}**\n";
|
||||||
send += string.Join(", ", (await channel.Guild.GetUsersAsync()).Where(u => u.Roles.Contains(role)).Distinct().Select(u=>u.Mention));
|
send += string.Join(", ", (await channel.Guild.GetUsersAsync()).Where(u => u.Roles.Contains(role)).Distinct().Select(u => u.Mention));
|
||||||
}
|
}
|
||||||
|
|
||||||
while (send.Length > 2000)
|
while (send.Length > 2000)
|
||||||
@ -872,19 +685,15 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
IGuild nadekoSupportServer;
|
IGuild nadekoSupportServer;
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
public async Task Donators(IUserMessage umsg)
|
public async Task Donators(IUserMessage umsg)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
IEnumerable<Donator> donatorsOrdered;
|
IEnumerable<Donator> donatorsOrdered;
|
||||||
|
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
donatorsOrdered = uow.Donators.GetDonatorsOrdered();
|
donatorsOrdered = uow.Donators.GetDonatorsOrdered();
|
||||||
}
|
}
|
||||||
|
await umsg.Channel.SendConfirmAsync("Thanks to the people listed below for making this project happen!", string.Join("⭐", donatorsOrdered.Select(d => d.Name))).ConfigureAwait(false);
|
||||||
string str = $"**Thanks to the people listed below for making this project happen!**\n";
|
|
||||||
await channel.SendMessageAsync(str + string.Join("⭐", donatorsOrdered.Select(d => d.Name))).ConfigureAwait(false);
|
|
||||||
|
|
||||||
nadekoSupportServer = nadekoSupportServer ?? NadekoBot.Client.GetGuild(117523346618318850);
|
nadekoSupportServer = nadekoSupportServer ?? NadekoBot.Client.GetGuild(117523346618318850);
|
||||||
|
|
||||||
@ -896,17 +705,14 @@ namespace NadekoBot.Modules.Administration
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var usrs = nadekoSupportServer.GetUsers().Where(u => u.Roles.Contains(patreonRole));
|
var usrs = nadekoSupportServer.GetUsers().Where(u => u.Roles.Contains(patreonRole));
|
||||||
await channel.SendMessageAsync("\n`Patreon supporters:`\n" + string.Join("⭐", usrs.Select(d => d.Username))).ConfigureAwait(false);
|
await umsg.Channel.SendConfirmAsync("Patreon supporters", string.Join("⭐", usrs.Select(d => d.Username))).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task Donadd(IUserMessage umsg, IUser donator, int amount)
|
public async Task Donadd(IUserMessage umsg, IUser donator, int amount)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
|
|
||||||
Donator don;
|
Donator don;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
@ -914,7 +720,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
await uow.CompleteAsync();
|
await uow.CompleteAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync($"Successfuly added a new donator. Total donated amount from this user: {don.Amount} 👑").ConfigureAwait(false);
|
await umsg.Channel.SendConfirmAsync($"Successfuly added a new donator. Total donated amount from this user: {don.Amount} 👑").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
using NLog;
|
using NLog;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
@ -74,26 +75,24 @@ namespace NadekoBot.Modules.Administration
|
|||||||
private static ConcurrentDictionary<ulong, AntiSpamSetting> antiSpamGuilds =
|
private static ConcurrentDictionary<ulong, AntiSpamSetting> antiSpamGuilds =
|
||||||
new ConcurrentDictionary<ulong, AntiSpamSetting>();
|
new ConcurrentDictionary<ulong, AntiSpamSetting>();
|
||||||
|
|
||||||
private Logger _log { get; }
|
private static Logger _log { get; }
|
||||||
|
|
||||||
public AntiRaidCommands(ShardedDiscordClient client)
|
static AntiRaidCommands()
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
client.MessageReceived += (imsg) =>
|
NadekoBot.Client.MessageReceived += async (imsg) =>
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var msg = imsg as IUserMessage;
|
var msg = imsg as IUserMessage;
|
||||||
if (msg == null || msg.Author.IsBot)
|
if (msg == null || msg.Author.IsBot)
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
|
|
||||||
var channel = msg.Channel as ITextChannel;
|
var channel = msg.Channel as ITextChannel;
|
||||||
if (channel == null)
|
if (channel == null)
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
|
|
||||||
var t = Task.Run(async () =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
AntiSpamSetting spamSettings;
|
AntiSpamSetting spamSettings;
|
||||||
if (!antiSpamGuilds.TryGetValue(channel.Guild.Id, out spamSettings))
|
if (!antiSpamGuilds.TryGetValue(channel.Guild.Id, out spamSettings))
|
||||||
return;
|
return;
|
||||||
@ -105,27 +104,23 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
if (spamSettings.UserStats.TryRemove(msg.Author.Id, out stats))
|
if (spamSettings.UserStats.TryRemove(msg.Author.Id, out stats))
|
||||||
{
|
{
|
||||||
await PunishUsers(spamSettings.Action, await GetMuteRole(channel.Guild), ProtectionType.Spamming, (IGuildUser)msg.Author)
|
await PunishUsers(spamSettings.Action, ProtectionType.Spamming, (IGuildUser)msg.Author)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
});
|
|
||||||
return Task.CompletedTask;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
client.UserJoined += (usr) =>
|
NadekoBot.Client.UserJoined += async (usr) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if (usr.IsBot)
|
if (usr.IsBot)
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
|
|
||||||
AntiRaidSetting settings;
|
AntiRaidSetting settings;
|
||||||
if (!antiRaidGuilds.TryGetValue(usr.Guild.Id, out settings))
|
if (!antiRaidGuilds.TryGetValue(usr.Guild.Id, out settings))
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
|
|
||||||
var t = Task.Run(async () =>
|
|
||||||
{
|
|
||||||
if (!settings.RaidUsers.Add(usr))
|
if (!settings.RaidUsers.Add(usr))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -136,19 +131,19 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var users = settings.RaidUsers.ToArray();
|
var users = settings.RaidUsers.ToArray();
|
||||||
settings.RaidUsers.Clear();
|
settings.RaidUsers.Clear();
|
||||||
|
|
||||||
await PunishUsers(settings.Action, await GetMuteRole(usr.Guild), ProtectionType.Raiding, users).ConfigureAwait(false);
|
await PunishUsers(settings.Action, ProtectionType.Raiding, users).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
await Task.Delay(1000 * settings.Seconds).ConfigureAwait(false);
|
await Task.Delay(1000 * settings.Seconds).ConfigureAwait(false);
|
||||||
|
|
||||||
settings.RaidUsers.TryRemove(usr);
|
settings.RaidUsers.TryRemove(usr);
|
||||||
--settings.UsersCount;
|
--settings.UsersCount;
|
||||||
});
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
}
|
||||||
|
catch { }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task PunishUsers(PunishmentAction action, IRole muteRole, ProtectionType pt, params IGuildUser[] gus)
|
private static async Task PunishUsers(PunishmentAction action, ProtectionType pt, params IGuildUser[] gus)
|
||||||
{
|
{
|
||||||
foreach (var gu in gus)
|
foreach (var gu in gus)
|
||||||
{
|
{
|
||||||
@ -157,21 +152,21 @@ namespace NadekoBot.Modules.Administration
|
|||||||
case PunishmentAction.Mute:
|
case PunishmentAction.Mute:
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await gu.AddRolesAsync(muteRole);
|
await MuteCommands.Mute(gu).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex) { _log.Warn(ex, "I can't apply punishement"); }
|
catch (Exception ex) { _log.Warn(ex, "I can't apply punishement"); }
|
||||||
break;
|
break;
|
||||||
case PunishmentAction.Kick:
|
case PunishmentAction.Kick:
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await gu.Guild.AddBanAsync(gu, 7);
|
await gu.Guild.AddBanAsync(gu, 7).ConfigureAwait(false);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await gu.Guild.RemoveBanAsync(gu);
|
await gu.Guild.RemoveBanAsync(gu).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
await gu.Guild.RemoveBanAsync(gu);
|
await gu.Guild.RemoveBanAsync(gu).ConfigureAwait(false);
|
||||||
// try it twice, really don't want to ban user if
|
// try it twice, really don't want to ban user if
|
||||||
// only kick has been specified as the punishement
|
// only kick has been specified as the punishement
|
||||||
}
|
}
|
||||||
@ -181,7 +176,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
case PunishmentAction.Ban:
|
case PunishmentAction.Ban:
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await gu.Guild.AddBanAsync(gu, 7);
|
await gu.Guild.AddBanAsync(gu, 7).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex) { _log.Warn(ex, "I can't apply punishment"); }
|
catch (Exception ex) { _log.Warn(ex, "I can't apply punishment"); }
|
||||||
break;
|
break;
|
||||||
@ -202,23 +197,23 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
if (userThreshold < 2 || userThreshold > 30)
|
if (userThreshold < 2 || userThreshold > 30)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("❗️User threshold must be between **2** and **30**.").ConfigureAwait(false);
|
await channel.SendErrorAsync("❗️User threshold must be between **2** and **30**.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seconds < 2 || seconds > 300)
|
if (seconds < 2 || seconds > 300)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("❗️Time must be between **2** and **300** seconds.").ConfigureAwait(false);
|
await channel.SendErrorAsync("❗️Time must be between **2** and **300** seconds.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await GetMuteRole(channel.Guild).ConfigureAwait(false);
|
await MuteCommands.GetMuteRole(channel.Guild).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ Failed creating a mute role. Give me ManageRoles permission" +
|
await channel.SendConfirmAsync("⚠️ Failed creating a mute role. Give me ManageRoles permission" +
|
||||||
"or create 'nadeko-mute' role with disabled SendMessages and try again.")
|
"or create 'nadeko-mute' role with disabled SendMessages and try again.")
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
_log.Warn(ex);
|
_log.Warn(ex);
|
||||||
@ -233,14 +228,14 @@ namespace NadekoBot.Modules.Administration
|
|||||||
};
|
};
|
||||||
antiRaidGuilds.AddOrUpdate(channel.Guild.Id, setting, (id, old) => setting);
|
antiRaidGuilds.AddOrUpdate(channel.Guild.Id, setting, (id, old) => setting);
|
||||||
|
|
||||||
await channel.SendMessageAsync($"ℹ️ {imsg.Author.Mention} If **{userThreshold}** or more users join within **{seconds}** seconds, I will **{action}** them.")
|
await channel.SendConfirmAsync($"ℹ️ {imsg.Author.Mention} If **{userThreshold}** or more users join within **{seconds}** seconds, I will **{action}** them.")
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[RequirePermission(GuildPermission.Administrator)]
|
[RequirePermission(GuildPermission.Administrator)]
|
||||||
public async Task AntiSpam(IUserMessage imsg, int messageCount=3, PunishmentAction action = PunishmentAction.Mute)
|
public async Task AntiSpam(IUserMessage imsg, int messageCount = 3, PunishmentAction action = PunishmentAction.Mute)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)imsg.Channel;
|
var channel = (ITextChannel)imsg.Channel;
|
||||||
|
|
||||||
@ -250,17 +245,17 @@ namespace NadekoBot.Modules.Administration
|
|||||||
AntiSpamSetting throwaway;
|
AntiSpamSetting throwaway;
|
||||||
if (antiSpamGuilds.TryRemove(channel.Guild.Id, out throwaway))
|
if (antiSpamGuilds.TryRemove(channel.Guild.Id, out throwaway))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("🆗 **Anti-Spam feature** has been **disabled** on this server.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("🆗 **Anti-Spam feature** has been **disabled** on this server.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await GetMuteRole(channel.Guild).ConfigureAwait(false);
|
await MuteCommands.GetMuteRole(channel.Guild).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ Failed creating a mute role. Give me ManageRoles permission" +
|
await channel.SendErrorAsync("⚠️ Failed creating a mute role. Give me ManageRoles permission" +
|
||||||
"or create 'nadeko-mute' role with disabled SendMessages and try again.")
|
"or create 'nadeko-mute' role with disabled SendMessages and try again.")
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
_log.Warn(ex);
|
_log.Warn(ex);
|
||||||
@ -272,7 +267,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
Action = action,
|
Action = action,
|
||||||
MessageThreshold = messageCount,
|
MessageThreshold = messageCount,
|
||||||
}))
|
}))
|
||||||
await channel.SendMessageAsync("✅ **Anti-Spam feature** has been **enabled** on this server.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("✅ **Anti-Spam feature** has been **enabled** on this server.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using NLog;
|
using NLog;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -15,35 +17,31 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[Group]
|
[Group]
|
||||||
public class AutoAssignRoleCommands
|
public class AutoAssignRoleCommands
|
||||||
{
|
{
|
||||||
private Logger _log { get; }
|
private static Logger _log { get; }
|
||||||
|
//guildid/roleid
|
||||||
|
private static ConcurrentDictionary<ulong, ulong> AutoAssignedRoles { get; }
|
||||||
|
|
||||||
public AutoAssignRoleCommands()
|
static AutoAssignRoleCommands()
|
||||||
{
|
{
|
||||||
var _client = NadekoBot.Client;
|
AutoAssignedRoles = new ConcurrentDictionary<ulong, ulong>(NadekoBot.AllGuildConfigs.Where(x => x.AutoAssignRoleId != 0)
|
||||||
this._log = LogManager.GetCurrentClassLogger();
|
.ToDictionary(k => k.GuildId, v => v.AutoAssignRoleId));
|
||||||
_client.UserJoined += (user) =>
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
{
|
NadekoBot.Client.UserJoined += async (user) =>
|
||||||
var t = Task.Run(async () =>
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
GuildConfig conf;
|
ulong roleId = 0;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
AutoAssignedRoles.TryGetValue(user.Guild.Id, out roleId);
|
||||||
{
|
|
||||||
conf = uow.GuildConfigs.For(user.Guild.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conf.AutoAssignRoleId == 0)
|
if (roleId == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var role = user.Guild.Roles.FirstOrDefault(r => r.Id == conf.AutoAssignRoleId);
|
var role = user.Guild.Roles.FirstOrDefault(r => r.Id == roleId);
|
||||||
|
|
||||||
if (role != null)
|
if (role != null)
|
||||||
await user.AddRolesAsync(role);
|
await user.AddRolesAsync(role).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex) { _log.Warn(ex); }
|
catch (Exception ex) { _log.Warn(ex); }
|
||||||
});
|
|
||||||
return Task.CompletedTask;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,23 +55,29 @@ namespace NadekoBot.Modules.Administration
|
|||||||
GuildConfig conf;
|
GuildConfig conf;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
conf = uow.GuildConfigs.For(channel.Guild.Id);
|
conf = uow.GuildConfigs.For(channel.Guild.Id, set => set);
|
||||||
if (role == null)
|
if (role == null)
|
||||||
|
{
|
||||||
conf.AutoAssignRoleId = 0;
|
conf.AutoAssignRoleId = 0;
|
||||||
|
ulong throwaway;
|
||||||
|
AutoAssignedRoles.TryRemove(channel.Guild.Id, out throwaway);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
conf.AutoAssignRoleId = role.Id;
|
conf.AutoAssignRoleId = role.Id;
|
||||||
|
AutoAssignedRoles.AddOrUpdate(channel.Guild.Id, role.Id, (key, val) => role.Id);
|
||||||
|
}
|
||||||
|
|
||||||
uow.GuildConfigs.Update(conf);
|
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (role == null)
|
if (role == null)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("🆗 **Auto assign role** on user join is now **disabled**.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("🆗 **Auto assign role** on user join is now **disabled**.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync("✅ **Auto assign role** on user join is now **enabled**.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("✅ **Auto assign role** on user join is now **enabled**.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,24 +16,21 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[Group]
|
[Group]
|
||||||
public class CrossServerTextChannel
|
public class CrossServerTextChannel
|
||||||
{
|
{
|
||||||
public CrossServerTextChannel()
|
static CrossServerTextChannel()
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
NadekoBot.Client.MessageReceived += (imsg) =>
|
NadekoBot.Client.MessageReceived += async (imsg) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if (imsg.Author.IsBot)
|
if (imsg.Author.IsBot)
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
|
|
||||||
var msg = imsg as IUserMessage;
|
var msg = imsg as IUserMessage;
|
||||||
if (msg == null)
|
if (msg == null)
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
|
|
||||||
var channel = imsg.Channel as ITextChannel;
|
var channel = imsg.Channel as ITextChannel;
|
||||||
if (channel == null)
|
if (channel == null)
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
if (msg.Author.Id == NadekoBot.Client.GetCurrentUser().Id) return;
|
if (msg.Author.Id == NadekoBot.Client.GetCurrentUser().Id) return;
|
||||||
foreach (var subscriber in Subscribers)
|
foreach (var subscriber in Subscribers)
|
||||||
{
|
{
|
||||||
@ -45,16 +42,18 @@ namespace NadekoBot.Modules.Administration
|
|||||||
try { await chan.SendMessageAsync(GetText(channel.Guild, channel, (IGuildUser)msg.Author, msg)).ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
try { await chan.SendMessageAsync(GetText(channel.Guild, channel, (IGuildUser)msg.Author, msg)).ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
return Task.CompletedTask;
|
catch (Exception ex) {
|
||||||
|
_log.Warn(ex);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetText(IGuild server, ITextChannel channel, IGuildUser user, IUserMessage message) =>
|
private static string GetText(IGuild server, ITextChannel channel, IGuildUser user, IUserMessage message) =>
|
||||||
$"**{server.Name} | {channel.Name}** `{user.Username}`: " + message.Content;
|
$"**{server.Name} | {channel.Name}** `{user.Username}`: " + message.Content;
|
||||||
|
|
||||||
public static readonly ConcurrentDictionary<int, ConcurrentHashSet<ITextChannel>> Subscribers = new ConcurrentDictionary<int, ConcurrentHashSet<ITextChannel>>();
|
public static readonly ConcurrentDictionary<int, ConcurrentHashSet<ITextChannel>> Subscribers = new ConcurrentDictionary<int, ConcurrentHashSet<ITextChannel>>();
|
||||||
private Logger _log { get; }
|
private static Logger _log { get; }
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
@ -67,7 +66,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
if (Subscribers.TryAdd(token, set))
|
if (Subscribers.TryAdd(token, set))
|
||||||
{
|
{
|
||||||
set.Add(channel);
|
set.Add(channel);
|
||||||
await ((IGuildUser)msg.Author).SendMessageAsync("This is your CSC token:" + token.ToString()).ConfigureAwait(false);
|
await ((IGuildUser)msg.Author).SendConfirmAsync("This is your CSC token", token.ToString()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +81,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
if (!Subscribers.TryGetValue(token, out set))
|
if (!Subscribers.TryGetValue(token, out set))
|
||||||
return;
|
return;
|
||||||
set.Add(channel);
|
set.Add(channel);
|
||||||
await channel.SendMessageAsync(":ok:").ConfigureAwait(false);
|
await channel.SendConfirmAsync("Joined cross server channel.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -96,7 +95,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
subscriber.Value.TryRemove(channel);
|
subscriber.Value.TryRemove(channel);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync(":ok:").ConfigureAwait(false);
|
await channel.SendMessageAsync("Left cross server channel.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -39,9 +40,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
uow.Complete();
|
uow.Complete();
|
||||||
}
|
}
|
||||||
if (ForwardDMs)
|
if (ForwardDMs)
|
||||||
await channel.SendMessageAsync("✅ **I will forward DMs from now on.**").ConfigureAwait(false);
|
await channel.SendConfirmAsync("✅ **I will forward DMs from now on.**").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync("🆗 **I will stop forwarding DMs from now on.**").ConfigureAwait(false);
|
await channel.SendConfirmAsync("🆗 **I will stop forwarding DMs from now on.**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -57,9 +58,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
uow.Complete();
|
uow.Complete();
|
||||||
}
|
}
|
||||||
if (ForwardDMsToAllOwners)
|
if (ForwardDMsToAllOwners)
|
||||||
await channel.SendMessageAsync("ℹ️ **I will forward DMs to all owners.**").ConfigureAwait(false);
|
await channel.SendConfirmAsync("ℹ️ **I will forward DMs to all owners.**").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync("ℹ️ **I will forward DMs only to the first owner.**").ConfigureAwait(false);
|
await channel.SendConfirmAsync("ℹ️ **I will forward DMs only to the first owner.**").ConfigureAwait(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,17 +68,17 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
if (ForwardDMs && ownerChannels.Any())
|
if (ForwardDMs && ownerChannels.Any())
|
||||||
{
|
{
|
||||||
var toSend = $"```markdown\n I received a message from [{msg.Author}]({msg.Author.Id}): {msg.Content}```";
|
var title = $"DM from [{msg.Author}]({msg.Author.Id})";
|
||||||
if (ForwardDMsToAllOwners)
|
if (ForwardDMsToAllOwners)
|
||||||
{
|
{
|
||||||
var msgs = await Task.WhenAll(ownerChannels.Where(ch => ch.Recipient.Id != msg.Author.Id)
|
var msgs = await Task.WhenAll(ownerChannels.Where(ch => ch.Recipient.Id != msg.Author.Id)
|
||||||
.Select(ch => ch.SendMessageAsync(toSend))).ConfigureAwait(false);
|
.Select(ch => ch.SendConfirmAsync(title, msg.Content))).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var firstOwnerChannel = ownerChannels.First();
|
var firstOwnerChannel = ownerChannels.First();
|
||||||
if (firstOwnerChannel.Recipient.Id != msg.Author.Id)
|
if (firstOwnerChannel.Recipient.Id != msg.Author.Id)
|
||||||
try { await firstOwnerChannel.SendMessageAsync(toSend).ConfigureAwait(false); } catch { }
|
try { await firstOwnerChannel.SendConfirmAsync(title, msg.Content).ConfigureAwait(false); } catch { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,7 @@
|
|||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using NLog;
|
using NLog;
|
||||||
@ -18,7 +19,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[Group]
|
[Group]
|
||||||
public class RepeatCommands
|
public class RepeatCommands
|
||||||
{
|
{
|
||||||
public ConcurrentDictionary<ulong, RepeatRunner> repeaters;
|
public static ConcurrentDictionary<ulong, RepeatRunner> repeaters { get; }
|
||||||
|
|
||||||
public class RepeatRunner
|
public class RepeatRunner
|
||||||
{
|
{
|
||||||
@ -49,10 +50,16 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
while (!token.IsCancellationRequested)
|
while (!token.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
var toSend = "🔄 " + Repeater.Message;
|
||||||
await Task.Delay(Repeater.Interval, token).ConfigureAwait(false);
|
await Task.Delay(Repeater.Interval, token).ConfigureAwait(false);
|
||||||
|
|
||||||
|
//var lastMsgInChannel = (await Channel.GetMessagesAsync(2)).FirstOrDefault();
|
||||||
|
// if (lastMsgInChannel.Id == oldMsg?.Id) //don't send if it's the same message in the channel
|
||||||
|
// continue;
|
||||||
|
|
||||||
if (oldMsg != null)
|
if (oldMsg != null)
|
||||||
try { await oldMsg.DeleteAsync(); } catch { }
|
try { await oldMsg.DeleteAsync(); } catch { }
|
||||||
try { oldMsg = await Channel.SendMessageAsync("🔄 " + Repeater.Message).ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); try { source.Cancel(); } catch { } }
|
try { oldMsg = await Channel.SendMessageAsync(toSend).ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException) { }
|
catch (OperationCanceledException) { }
|
||||||
@ -70,7 +77,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public RepeatCommands()
|
static RepeatCommands()
|
||||||
{
|
{
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
@ -88,7 +95,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
RepeatRunner rep;
|
RepeatRunner rep;
|
||||||
if (!repeaters.TryGetValue(channel.Id, out rep))
|
if (!repeaters.TryGetValue(channel.Id, out rep))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("ℹ️ **No repeating message found on this server.**").ConfigureAwait(false);
|
await channel.SendErrorAsync("ℹ️ **No repeating message found on this server.**").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rep.Reset();
|
rep.Reset();
|
||||||
@ -110,10 +117,10 @@ namespace NadekoBot.Modules.Administration
|
|||||||
await uow.CompleteAsync();
|
await uow.CompleteAsync();
|
||||||
}
|
}
|
||||||
rep.Stop();
|
rep.Stop();
|
||||||
await channel.SendMessageAsync("✅ **Stopped repeating a message.**").ConfigureAwait(false);
|
await channel.SendConfirmAsync("✅ **Stopped repeating a message.**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync("ℹ️ **No message is repeating.**").ConfigureAwait(false);
|
await channel.SendConfirmAsync("ℹ️ **No message is repeating.**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -159,7 +166,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
return old;
|
return old;
|
||||||
});
|
});
|
||||||
|
|
||||||
await channel.SendMessageAsync($"🔁 Repeating **\"{rep.Repeater.Message}\"** every `{rep.Repeater.Interval.Days} day(s), {rep.Repeater.Interval.Hours} hour(s) and {rep.Repeater.Interval.Minutes} minute(s)`.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"🔁 Repeating **\"{rep.Repeater.Message}\"** every `{rep.Repeater.Interval.Days} day(s), {rep.Repeater.Interval.Hours} hour(s) and {rep.Repeater.Interval.Minutes} minute(s)`.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var byeMsg = (string)reader["ByeText"];
|
var byeMsg = (string)reader["ByeText"];
|
||||||
var grdel = false;
|
var grdel = false;
|
||||||
var byedel = grdel;
|
var byedel = grdel;
|
||||||
var gc = uow.GuildConfigs.For(gid);
|
var gc = uow.GuildConfigs.For(gid, set => set);
|
||||||
|
|
||||||
if (greetDM)
|
if (greetDM)
|
||||||
gc.SendDmGreetMessage = greet;
|
gc.SendDmGreetMessage = greet;
|
||||||
@ -195,12 +195,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
guildConfig.GenerateCurrencyChannelIds = new HashSet<GCChannelId>(data.GenerateCurrencyChannels.Select(gc => new GCChannelId() { ChannelId = gc.Key }));
|
guildConfig.GenerateCurrencyChannelIds = new HashSet<GCChannelId>(data.GenerateCurrencyChannels.Select(gc => new GCChannelId() { ChannelId = gc.Key }));
|
||||||
selfAssRoles.AddRange(data.ListOfSelfAssignableRoles.Select(r => new SelfAssignedRole() { GuildId = guildConfig.GuildId, RoleId = r }).ToArray());
|
selfAssRoles.AddRange(data.ListOfSelfAssignableRoles.Select(r => new SelfAssignedRole() { GuildId = guildConfig.GuildId, RoleId = r }).ToArray());
|
||||||
var logSetting = guildConfig.LogSetting;
|
var logSetting = guildConfig.LogSetting;
|
||||||
guildConfig.LogSetting.IsLogging = data.LogChannel != null;
|
|
||||||
guildConfig.LogSetting.ChannelId = data.LogChannel ?? 0;
|
|
||||||
guildConfig.LogSetting.IgnoredChannels = new HashSet<IgnoredLogChannel>(data.LogserverIgnoreChannels.Select(id => new IgnoredLogChannel() { ChannelId = id }));
|
guildConfig.LogSetting.IgnoredChannels = new HashSet<IgnoredLogChannel>(data.LogserverIgnoreChannels.Select(id => new IgnoredLogChannel() { ChannelId = id }));
|
||||||
|
|
||||||
guildConfig.LogSetting.LogUserPresence = data.LogPresenceChannel != null;
|
guildConfig.LogSetting.LogUserPresenceId = data.LogPresenceChannel;
|
||||||
guildConfig.LogSetting.UserPresenceChannelId = data.LogPresenceChannel ?? 0;
|
|
||||||
|
|
||||||
|
|
||||||
guildConfig.FollowedStreams = new HashSet<FollowedStream>(data.ObservingStreams.Select(x =>
|
guildConfig.FollowedStreams = new HashSet<FollowedStream>(data.ObservingStreams.Select(x =>
|
||||||
|
287
src/NadekoBot/Modules/Administration/Commands/MuteCommands.cs
Normal file
287
src/NadekoBot/Modules/Administration/Commands/MuteCommands.cs
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Services;
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Administration
|
||||||
|
{
|
||||||
|
public partial class Administration
|
||||||
|
{
|
||||||
|
[Group]
|
||||||
|
public class MuteCommands
|
||||||
|
{
|
||||||
|
private static ConcurrentDictionary<ulong, string> GuildMuteRoles { get; } = new ConcurrentDictionary<ulong, string>();
|
||||||
|
|
||||||
|
private static ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>> MutedUsers { get; } = new ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>>();
|
||||||
|
|
||||||
|
public static event Action<IGuildUser, MuteType> UserMuted = delegate { };
|
||||||
|
public static event Action<IGuildUser, MuteType> UserUnmuted = delegate { };
|
||||||
|
|
||||||
|
|
||||||
|
public enum MuteType {
|
||||||
|
Voice,
|
||||||
|
Chat,
|
||||||
|
All
|
||||||
|
}
|
||||||
|
|
||||||
|
static MuteCommands() {
|
||||||
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
|
{
|
||||||
|
var configs = NadekoBot.AllGuildConfigs;
|
||||||
|
GuildMuteRoles = new ConcurrentDictionary<ulong, string>(configs
|
||||||
|
.Where(c => !string.IsNullOrWhiteSpace(c.MuteRoleName))
|
||||||
|
.ToDictionary(c => c.GuildId, c => c.MuteRoleName));
|
||||||
|
|
||||||
|
MutedUsers = new ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>>(configs.ToDictionary(
|
||||||
|
k => k.GuildId,
|
||||||
|
v => new ConcurrentHashSet<ulong>(v.MutedUsers.Select(m => m.UserId))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
NadekoBot.Client.UserJoined += Client_UserJoined;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async void Client_UserJoined(IGuildUser usr)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ConcurrentHashSet<ulong> muted;
|
||||||
|
MutedUsers.TryGetValue(usr.Guild.Id, out muted);
|
||||||
|
|
||||||
|
if (muted == null || !muted.Contains(usr.Id))
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
await Mute(usr).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_log.Warn(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task Mute(IGuildUser usr)
|
||||||
|
{
|
||||||
|
await usr.ModifyAsync(x => x.Mute = true).ConfigureAwait(false);
|
||||||
|
await usr.AddRolesAsync(await GetMuteRole(usr.Guild)).ConfigureAwait(false);
|
||||||
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
|
{
|
||||||
|
var config = uow.GuildConfigs.For(usr.Guild.Id, set => set.Include(gc => gc.MutedUsers));
|
||||||
|
config.MutedUsers.Add(new MutedUserId()
|
||||||
|
{
|
||||||
|
UserId = usr.Id
|
||||||
|
});
|
||||||
|
ConcurrentHashSet<ulong> muted;
|
||||||
|
if (MutedUsers.TryGetValue(usr.Guild.Id, out muted))
|
||||||
|
muted.Add(usr.Id);
|
||||||
|
|
||||||
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
UserMuted(usr, MuteType.All);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task Unmute(IGuildUser usr)
|
||||||
|
{
|
||||||
|
await usr.ModifyAsync(x => x.Mute = false).ConfigureAwait(false);
|
||||||
|
await usr.RemoveRolesAsync(await GetMuteRole(usr.Guild)).ConfigureAwait(false);
|
||||||
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
|
{
|
||||||
|
var config = uow.GuildConfigs.For(usr.Guild.Id, set => set.Include(gc => gc.MutedUsers));
|
||||||
|
config.MutedUsers.Remove(new MutedUserId()
|
||||||
|
{
|
||||||
|
UserId = usr.Id
|
||||||
|
});
|
||||||
|
ConcurrentHashSet<ulong> muted;
|
||||||
|
if (MutedUsers.TryGetValue(usr.Guild.Id, out muted))
|
||||||
|
muted.TryRemove(usr.Id);
|
||||||
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
UserUnmuted(usr, MuteType.All);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<IRole> GetMuteRole(IGuild guild)
|
||||||
|
{
|
||||||
|
const string defaultMuteRoleName = "nadeko-mute";
|
||||||
|
|
||||||
|
var muteRoleName = GuildMuteRoles.GetOrAdd(guild.Id, defaultMuteRoleName);
|
||||||
|
|
||||||
|
var muteRole = guild.Roles.FirstOrDefault(r => r.Name == muteRoleName);
|
||||||
|
if (muteRole == null)
|
||||||
|
{
|
||||||
|
|
||||||
|
//if it doesn't exist, create it
|
||||||
|
try { muteRole = await guild.CreateRoleAsync(muteRoleName, GuildPermissions.None).ConfigureAwait(false); }
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
//if creations fails, maybe the name is not correct, find default one, if doesn't work, create default one
|
||||||
|
muteRole = guild.Roles.FirstOrDefault(r => r.Name == muteRoleName) ??
|
||||||
|
await guild.CreateRoleAsync(defaultMuteRoleName, GuildPermissions.None).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var toOverwrite in guild.GetTextChannels())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await toOverwrite.AddPermissionOverwriteAsync(muteRole, new OverwritePermissions(sendMessages: PermValue.Deny, attachFiles: PermValue.Deny))
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
await Task.Delay(200).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return muteRole;
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[RequirePermission(GuildPermission.ManageRoles)]
|
||||||
|
[Priority(1)]
|
||||||
|
public async Task SetMuteRole(IUserMessage imsg, [Remainder] string name)
|
||||||
|
{
|
||||||
|
var channel = (ITextChannel)imsg.Channel;
|
||||||
|
name = name.Trim();
|
||||||
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
|
return;
|
||||||
|
|
||||||
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
|
{
|
||||||
|
var config = uow.GuildConfigs.For(channel.Guild.Id, set => set);
|
||||||
|
config.MuteRoleName = name;
|
||||||
|
GuildMuteRoles.AddOrUpdate(channel.Guild.Id, name, (id, old) => name);
|
||||||
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
await channel.SendConfirmAsync("☑️ **New mute role set.**").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[RequirePermission(GuildPermission.ManageRoles)]
|
||||||
|
[Priority(0)]
|
||||||
|
public Task SetMuteRole(IUserMessage imsg, [Remainder] IRole role)
|
||||||
|
=> SetMuteRole(imsg, role.Name);
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[RequirePermission(GuildPermission.ManageRoles)]
|
||||||
|
[RequirePermission(GuildPermission.MuteMembers)]
|
||||||
|
public async Task Mute(IUserMessage umsg, IGuildUser user)
|
||||||
|
{
|
||||||
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Mute(user).ConfigureAwait(false);
|
||||||
|
await channel.SendConfirmAsync($"🔇 **{user}** has been **muted** from text and voice chat.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[RequirePermission(GuildPermission.ManageRoles)]
|
||||||
|
[RequirePermission(GuildPermission.MuteMembers)]
|
||||||
|
public async Task Unmute(IUserMessage umsg, IGuildUser user)
|
||||||
|
{
|
||||||
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Unmute(user).ConfigureAwait(false);
|
||||||
|
await channel.SendConfirmAsync($"🔉 **{user}** has been **unmuted** from text and voice chat.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[RequirePermission(GuildPermission.ManageRoles)]
|
||||||
|
public async Task ChatMute(IUserMessage umsg, IGuildUser user)
|
||||||
|
{
|
||||||
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await user.AddRolesAsync(await GetMuteRole(channel.Guild).ConfigureAwait(false)).ConfigureAwait(false);
|
||||||
|
UserMuted(user, MuteType.Chat);
|
||||||
|
await channel.SendConfirmAsync($"✏️🚫 **{user}** has been **muted** from chatting.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[RequirePermission(GuildPermission.ManageRoles)]
|
||||||
|
public async Task ChatUnmute(IUserMessage umsg, IGuildUser user)
|
||||||
|
{
|
||||||
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await user.RemoveRolesAsync(await GetMuteRole(channel.Guild).ConfigureAwait(false)).ConfigureAwait(false);
|
||||||
|
UserUnmuted(user, MuteType.Chat);
|
||||||
|
await channel.SendConfirmAsync($"✏️✅ **{user}** has been **unmuted** from chatting.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[RequirePermission(GuildPermission.MuteMembers)]
|
||||||
|
public async Task VoiceMute(IUserMessage umsg, IGuildUser user)
|
||||||
|
{
|
||||||
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await user.ModifyAsync(usr => usr.Mute = true).ConfigureAwait(false);
|
||||||
|
UserMuted(user, MuteType.Voice);
|
||||||
|
await channel.SendConfirmAsync($"🎙🚫 **{user}** has been **voice muted**.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[RequirePermission(GuildPermission.MuteMembers)]
|
||||||
|
public async Task VoiceUnmute(IUserMessage umsg, IGuildUser user)
|
||||||
|
{
|
||||||
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await user.ModifyAsync(usr => usr.Mute = false).ConfigureAwait(false);
|
||||||
|
UserUnmuted(user, MuteType.Voice);
|
||||||
|
await channel.SendConfirmAsync($"🎙✅ **{user}** has been **voice unmuted**.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[Group]
|
[Group]
|
||||||
public class PlayingRotateCommands
|
public class PlayingRotateCommands
|
||||||
{
|
{
|
||||||
private Logger _log { get; }
|
private static Logger _log { get; }
|
||||||
public static List<PlayingStatus> RotatingStatusMessages { get; }
|
public static List<PlayingStatus> RotatingStatusMessages { get; }
|
||||||
public static bool RotatingStatuses { get; private set; } = false;
|
public static bool RotatingStatuses { get; private set; } = false;
|
||||||
|
|
||||||
@ -30,12 +30,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
RotatingStatusMessages = conf.RotatingStatusMessages;
|
RotatingStatusMessages = conf.RotatingStatusMessages;
|
||||||
RotatingStatuses = conf.RotatingStatuses;
|
RotatingStatuses = conf.RotatingStatuses;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public PlayingRotateCommands()
|
|
||||||
{
|
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
Task.Run(async () =>
|
var t = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
var index = 0;
|
var index = 0;
|
||||||
do
|
do
|
||||||
@ -90,12 +87,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
};
|
};
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task RotatePlaying(IUserMessage umsg)
|
public async Task RotatePlaying(IUserMessage umsg)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
|
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var config = uow.BotConfig.GetOrCreate();
|
var config = uow.BotConfig.GetOrCreate();
|
||||||
@ -104,18 +98,15 @@ namespace NadekoBot.Modules.Administration
|
|||||||
await uow.CompleteAsync();
|
await uow.CompleteAsync();
|
||||||
}
|
}
|
||||||
if (RotatingStatuses)
|
if (RotatingStatuses)
|
||||||
await channel.SendMessageAsync("🆗 **Rotating playing status enabled.**");
|
await umsg.Channel.SendConfirmAsync("🆗 **Rotating playing status enabled.**").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync("ℹ️ **Rotating playing status disabled.**");
|
await umsg.Channel.SendConfirmAsync("ℹ️ **Rotating playing status disabled.**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task AddPlaying(IUserMessage umsg, [Remainder] string status)
|
public async Task AddPlaying(IUserMessage umsg, [Remainder] string status)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
|
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var config = uow.BotConfig.GetOrCreate();
|
var config = uow.BotConfig.GetOrCreate();
|
||||||
@ -125,33 +116,27 @@ namespace NadekoBot.Modules.Administration
|
|||||||
await uow.CompleteAsync();
|
await uow.CompleteAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync("✅ **Added.**").ConfigureAwait(false);
|
await umsg.Channel.SendConfirmAsync("✅ **Added.**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task ListPlaying(IUserMessage umsg)
|
public async Task ListPlaying(IUserMessage umsg)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
|
|
||||||
|
|
||||||
if (!RotatingStatusMessages.Any())
|
if (!RotatingStatusMessages.Any())
|
||||||
await channel.SendMessageAsync("❎ **No rotating playing statuses set.**");
|
await umsg.Channel.SendErrorAsync("❎ **No rotating playing statuses set.**");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var i = 1;
|
var i = 1;
|
||||||
await channel.SendMessageAsync($"ℹ️ {umsg.Author.Mention} `Here is a list of rotating statuses:`\n\n\t" + string.Join("\n\t", RotatingStatusMessages.Select(rs => $"`{i++}.` {rs.Status}")));
|
await umsg.Channel.SendConfirmAsync($"ℹ️ {umsg.Author.Mention} `Here is a list of rotating statuses:`\n\n\t" + string.Join("\n\t", RotatingStatusMessages.Select(rs => $"`{i++}.` {rs.Status}")));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task RemovePlaying(IUserMessage umsg, int index)
|
public async Task RemovePlaying(IUserMessage umsg, int index)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
index -= 1;
|
index -= 1;
|
||||||
|
|
||||||
string msg = "";
|
string msg = "";
|
||||||
@ -166,7 +151,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
RotatingStatusMessages.RemoveAt(index);
|
RotatingStatusMessages.RemoveAt(index);
|
||||||
await uow.CompleteAsync();
|
await uow.CompleteAsync();
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"🗑 **Removed the the playing message:** {msg}").ConfigureAwait(false);
|
await umsg.Channel.SendConfirmAsync($"🗑 **Removed the the playing message:** {msg}").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,9 +16,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
public class RatelimitCommand
|
public class RatelimitCommand
|
||||||
{
|
{
|
||||||
public static ConcurrentDictionary<ulong, Ratelimiter> RatelimitingChannels = new ConcurrentDictionary<ulong, Ratelimiter>();
|
public static ConcurrentDictionary<ulong, Ratelimiter> RatelimitingChannels = new ConcurrentDictionary<ulong, Ratelimiter>();
|
||||||
private Logger _log { get; }
|
private static Logger _log { get; }
|
||||||
|
|
||||||
private ShardedDiscordClient _client { get; }
|
|
||||||
|
|
||||||
public class Ratelimiter
|
public class Ratelimiter
|
||||||
{
|
{
|
||||||
@ -47,7 +45,8 @@ namespace NadekoBot.Modules.Administration
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
usr.MessageCount++;
|
usr.MessageCount++;
|
||||||
var t = Task.Run(async () => {
|
var t = Task.Run(async () =>
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await Task.Delay(PerSeconds * 1000, cancelSource.Token);
|
await Task.Delay(PerSeconds * 1000, cancelSource.Token);
|
||||||
@ -61,16 +60,17 @@ namespace NadekoBot.Modules.Administration
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public RatelimitCommand()
|
static RatelimitCommand()
|
||||||
{
|
{
|
||||||
this._client = NadekoBot.Client;
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
this._log = LogManager.GetCurrentClassLogger();
|
|
||||||
|
|
||||||
_client.MessageReceived += (umsg) =>
|
NadekoBot.Client.MessageReceived += async (umsg) =>
|
||||||
{
|
{
|
||||||
var t = Task.Run(async () =>
|
try
|
||||||
{
|
{
|
||||||
var usrMsg = umsg as IUserMessage;
|
var usrMsg = umsg as IUserMessage;
|
||||||
|
if (usrMsg == null)
|
||||||
|
return;
|
||||||
var channel = usrMsg.Channel as ITextChannel;
|
var channel = usrMsg.Channel as ITextChannel;
|
||||||
|
|
||||||
if (channel == null || usrMsg.IsAuthor())
|
if (channel == null || usrMsg.IsAuthor())
|
||||||
@ -80,9 +80,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (limiter.CheckUserRatelimit(usrMsg.Author.Id))
|
if (limiter.CheckUserRatelimit(usrMsg.Author.Id))
|
||||||
try { await usrMsg.DeleteAsync(); } catch (Exception ex) { _log.Warn(ex); }
|
await usrMsg.DeleteAsync();
|
||||||
});
|
}
|
||||||
return Task.CompletedTask;
|
catch (Exception ex) { _log.Warn(ex); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
if (RatelimitingChannels.TryRemove(channel.Id, out throwaway))
|
if (RatelimitingChannels.TryRemove(channel.Id, out throwaway))
|
||||||
{
|
{
|
||||||
throwaway.cancelSource.Cancel();
|
throwaway.cancelSource.Cancel();
|
||||||
await channel.SendMessageAsync("ℹ️ **Slow mode disabled.**").ConfigureAwait(false);
|
await channel.SendConfirmAsync("ℹ️ Slow mode disabled.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,7 +112,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
if (msg < 1 || perSec < 1 || msg > 100 || perSec > 3600)
|
if (msg < 1 || perSec < 1 || msg > 100 || perSec > 3600)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ `Invalid parameters.`");
|
await channel.SendErrorAsync("⚠️ Invalid parameters.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var toAdd = new Ratelimiter()
|
var toAdd = new Ratelimiter()
|
||||||
@ -121,10 +121,10 @@ namespace NadekoBot.Modules.Administration
|
|||||||
MaxMessages = msg,
|
MaxMessages = msg,
|
||||||
PerSeconds = perSec,
|
PerSeconds = perSec,
|
||||||
};
|
};
|
||||||
if(RatelimitingChannels.TryAdd(channel.Id, toAdd))
|
if (RatelimitingChannels.TryAdd(channel.Id, toAdd))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("✅ **Slow mode initiated: " +
|
await channel.SendConfirmAsync("Slow mode initiated",
|
||||||
$"Users can't send more than `{toAdd.MaxMessages} message(s)` every `{toAdd.PerSeconds} second(s)`.**")
|
$"Users can't send more than `{toAdd.MaxMessages} message(s)` every `{toAdd.PerSeconds} second(s)`.")
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using System;
|
using System;
|
||||||
@ -27,12 +28,12 @@ namespace NadekoBot.Modules.Administration
|
|||||||
bool newval;
|
bool newval;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var config = uow.GuildConfigs.For(channel.Guild.Id);
|
var config = uow.GuildConfigs.For(channel.Guild.Id, set => set);
|
||||||
newval = config.AutoDeleteSelfAssignedRoleMessages = !config.AutoDeleteSelfAssignedRoleMessages;
|
newval = config.AutoDeleteSelfAssignedRoleMessages = !config.AutoDeleteSelfAssignedRoleMessages;
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync($"ℹ️ Automatic deleting of `iam` and `iamn` confirmations has been {(newval ? "**enabled**" : "**disabled**")}.")
|
await channel.SendConfirmAsync($"ℹ️ Automatic deleting of `iam` and `iamn` confirmations has been {(newval ? "**enabled**" : "**disabled**")}.")
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +52,8 @@ namespace NadekoBot.Modules.Administration
|
|||||||
roles = uow.SelfAssignedRoles.GetFromGuild(channel.Guild.Id);
|
roles = uow.SelfAssignedRoles.GetFromGuild(channel.Guild.Id);
|
||||||
if (roles.Any(s => s.RoleId == role.Id && s.GuildId == role.GuildId))
|
if (roles.Any(s => s.RoleId == role.Id && s.GuildId == role.GuildId))
|
||||||
{
|
{
|
||||||
msg = $"💢 Role **{role.Name}** is already in the list.";
|
await channel.SendMessageAsync($"💢 Role **{role.Name}** is already in the list.").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -63,7 +65,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
msg = $"🆗 Role **{role.Name}** added to the list.";
|
msg = $"🆗 Role **{role.Name}** added to the list.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync(msg.ToString()).ConfigureAwait(false);
|
await channel.SendConfirmAsync(msg.ToString()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -81,10 +83,10 @@ namespace NadekoBot.Modules.Administration
|
|||||||
}
|
}
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("❎ That role is not self-assignable.").ConfigureAwait(false);
|
await channel.SendErrorAsync("❎ That role is not self-assignable.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"🗑 **{role.Name}** has been removed from the list of self-assignable roles.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"🗑 **{role.Name}** has been removed from the list of self-assignable roles.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -96,10 +98,12 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var toRemove = new ConcurrentHashSet<SelfAssignedRole>();
|
var toRemove = new ConcurrentHashSet<SelfAssignedRole>();
|
||||||
var removeMsg = new StringBuilder();
|
var removeMsg = new StringBuilder();
|
||||||
var msg = new StringBuilder();
|
var msg = new StringBuilder();
|
||||||
|
var roleCnt = 0;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var roleModels = uow.SelfAssignedRoles.GetFromGuild(channel.Guild.Id);
|
var roleModels = uow.SelfAssignedRoles.GetFromGuild(channel.Guild.Id).ToList();
|
||||||
msg.AppendLine($"ℹ️ There are `{roleModels.Count()}` self assignable roles:");
|
roleCnt = roleModels.Count;
|
||||||
|
msg.AppendLine();
|
||||||
|
|
||||||
foreach (var roleModel in roleModels)
|
foreach (var roleModel in roleModels)
|
||||||
{
|
{
|
||||||
@ -119,7 +123,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
}
|
}
|
||||||
await uow.CompleteAsync();
|
await uow.CompleteAsync();
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync(msg.ToString() + "\n\n" + removeMsg.ToString()).ConfigureAwait(false);
|
await channel.SendConfirmAsync($"ℹ️ There are `{roleCnt}` self assignable roles:", msg.ToString() + "\n\n" + removeMsg.ToString()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -132,13 +136,13 @@ namespace NadekoBot.Modules.Administration
|
|||||||
bool areExclusive;
|
bool areExclusive;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var config = uow.GuildConfigs.For(channel.Guild.Id);
|
var config = uow.GuildConfigs.For(channel.Guild.Id, set => set);
|
||||||
|
|
||||||
areExclusive = config.ExclusiveSelfAssignedRoles = !config.ExclusiveSelfAssignedRoles;
|
areExclusive = config.ExclusiveSelfAssignedRoles = !config.ExclusiveSelfAssignedRoles;
|
||||||
await uow.CompleteAsync();
|
await uow.CompleteAsync();
|
||||||
}
|
}
|
||||||
string exl = areExclusive ? "**exclusive**." : "**not exclusive**.";
|
string exl = areExclusive ? "**exclusive**." : "**not exclusive**.";
|
||||||
await channel.SendMessageAsync("ℹ️ Self assigned roles are now " + exl);
|
await channel.SendConfirmAsync("ℹ️ Self assigned roles are now " + exl);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -153,18 +157,18 @@ namespace NadekoBot.Modules.Administration
|
|||||||
IEnumerable<SelfAssignedRole> roles;
|
IEnumerable<SelfAssignedRole> roles;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
conf = uow.GuildConfigs.For(channel.Guild.Id);
|
conf = uow.GuildConfigs.For(channel.Guild.Id, set => set);
|
||||||
roles = uow.SelfAssignedRoles.GetFromGuild(channel.Guild.Id);
|
roles = uow.SelfAssignedRoles.GetFromGuild(channel.Guild.Id);
|
||||||
}
|
}
|
||||||
SelfAssignedRole roleModel;
|
SelfAssignedRole roleModel;
|
||||||
if ((roleModel = roles.FirstOrDefault(r=>r.RoleId == role.Id)) == null)
|
if ((roleModel = roles.FirstOrDefault(r=>r.RoleId == role.Id)) == null)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 That role is not self-assignable.").ConfigureAwait(false);
|
await channel.SendErrorAsync("That role is not self-assignable.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (guildUser.Roles.Contains(role))
|
if (guildUser.Roles.Contains(role))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"❎ You already have **{role.Name}** role.").ConfigureAwait(false);
|
await channel.SendErrorAsync($"You already have **{role.Name}** role.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,7 +177,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var sameRoles = guildUser.Roles.Where(r => roles.Any(rm => rm.RoleId == r.Id));
|
var sameRoles = guildUser.Roles.Where(r => roles.Any(rm => rm.RoleId == r.Id));
|
||||||
if (sameRoles.Any())
|
if (sameRoles.Any())
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"❎ You already have **{sameRoles.FirstOrDefault().Name}** `exclusive self-assigned` role.").ConfigureAwait(false);
|
await channel.SendErrorAsync($"You already have **{sameRoles.FirstOrDefault().Name}** `exclusive self-assigned` role.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -183,20 +187,16 @@ namespace NadekoBot.Modules.Administration
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"⚠️ I am unable to add that role to you. `I can't add roles to owners or other roles higher than my role in the role hierarchy.`").ConfigureAwait(false);
|
await channel.SendErrorAsync($"⚠️ I am unable to add that role to you. `I can't add roles to owners or other roles higher than my role in the role hierarchy.`").ConfigureAwait(false);
|
||||||
Console.WriteLine(ex);
|
Console.WriteLine(ex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var msg = await channel.SendMessageAsync($"🆗 You now have **{role.Name}** role.").ConfigureAwait(false);
|
var msg = await channel.SendConfirmAsync($"🆗 You now have **{role.Name}** role.").ConfigureAwait(false);
|
||||||
|
|
||||||
if (conf.AutoDeleteSelfAssignedRoleMessages)
|
if (conf.AutoDeleteSelfAssignedRoleMessages)
|
||||||
{
|
{
|
||||||
var t = Task.Run(async () =>
|
msg.DeleteAfter(3);
|
||||||
{
|
umsg.DeleteAfter(3);
|
||||||
await Task.Delay(3000).ConfigureAwait(false);
|
|
||||||
try { await msg.DeleteAsync().ConfigureAwait(false); } catch { } // if 502 or something, i don't want bot crashing
|
|
||||||
try { await usrMsg.DeleteAsync().ConfigureAwait(false); } catch { }
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,22 +207,22 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
var guildUser = (IGuildUser)umsg.Author;
|
var guildUser = (IGuildUser)umsg.Author;
|
||||||
|
|
||||||
GuildConfig conf;
|
bool autoDeleteSelfAssignedRoleMessages;
|
||||||
IEnumerable<SelfAssignedRole> roles;
|
IEnumerable<SelfAssignedRole> roles;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
conf = uow.GuildConfigs.For(channel.Guild.Id);
|
autoDeleteSelfAssignedRoleMessages = uow.GuildConfigs.For(channel.Guild.Id, set => set).AutoDeleteSelfAssignedRoleMessages;
|
||||||
roles = uow.SelfAssignedRoles.GetFromGuild(channel.Guild.Id);
|
roles = uow.SelfAssignedRoles.GetFromGuild(channel.Guild.Id);
|
||||||
}
|
}
|
||||||
SelfAssignedRole roleModel;
|
SelfAssignedRole roleModel;
|
||||||
if ((roleModel = roles.FirstOrDefault(r => r.RoleId == role.Id)) == null)
|
if ((roleModel = roles.FirstOrDefault(r => r.RoleId == role.Id)) == null)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 That role is not self-assignable.").ConfigureAwait(false);
|
await channel.SendErrorAsync("💢 That role is not self-assignable.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!guildUser.Roles.Contains(role))
|
if (!guildUser.Roles.Contains(role))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"❎ You don't have **{role.Name}** role.").ConfigureAwait(false);
|
await channel.SendErrorAsync($"❎ You don't have **{role.Name}** role.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
@ -231,19 +231,15 @@ namespace NadekoBot.Modules.Administration
|
|||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"⚠️ I am unable to add that role to you. `I can't remove roles to owners or other roles higher than my role in the role hierarchy.`").ConfigureAwait(false);
|
await channel.SendErrorAsync($"⚠️ I am unable to add that role to you. `I can't remove roles to owners or other roles higher than my role in the role hierarchy.`").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var msg = await channel.SendMessageAsync($"🆗 You no longer have **{role.Name}** role.").ConfigureAwait(false);
|
var msg = await channel.SendConfirmAsync($"🆗 You no longer have **{role.Name}** role.").ConfigureAwait(false);
|
||||||
|
|
||||||
if (conf.AutoDeleteSelfAssignedRoleMessages)
|
if (autoDeleteSelfAssignedRoleMessages)
|
||||||
{
|
{
|
||||||
var t = Task.Run(async () =>
|
msg.DeleteAfter(3);
|
||||||
{
|
umsg.DeleteAfter(3);
|
||||||
await Task.Delay(3000).ConfigureAwait(false);
|
|
||||||
try { await msg.DeleteAsync().ConfigureAwait(false); } catch { } // if 502 or something, i don't want bot crashing
|
|
||||||
try { await umsg.DeleteAsync().ConfigureAwait(false); } catch { }
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -13,9 +14,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
private ShardedDiscordClient _client;
|
private ShardedDiscordClient _client;
|
||||||
|
|
||||||
public SelfCommands(ShardedDiscordClient client)
|
public SelfCommands()
|
||||||
{
|
{
|
||||||
this._client = client;
|
this._client = NadekoBot.Client;
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -31,18 +32,18 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
if (server == null)
|
if (server == null)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ Cannot find that server").ConfigureAwait(false);
|
await channel.SendErrorAsync("⚠️ Cannot find that server").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (server.OwnerId != _client.GetCurrentUser().Id)
|
if (server.OwnerId != _client.GetCurrentUser().Id)
|
||||||
{
|
{
|
||||||
await server.LeaveAsync().ConfigureAwait(false);
|
await server.LeaveAsync().ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync("✅ Left server " + server.Name).ConfigureAwait(false);
|
await channel.SendConfirmAsync("✅ Left server " + server.Name).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await server.DeleteAsync().ConfigureAwait(false);
|
await server.DeleteAsync().ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync("Deleted server " + server.Name).ConfigureAwait(false);
|
await channel.SendConfirmAsync("Deleted server " + server.Name).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,26 +17,23 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[Group]
|
[Group]
|
||||||
public class ServerGreetCommands
|
public class ServerGreetCommands
|
||||||
{
|
{
|
||||||
public static long Greeted = 0;
|
private static Logger _log { get; }
|
||||||
private Logger _log;
|
|
||||||
|
|
||||||
public ServerGreetCommands()
|
static ServerGreetCommands()
|
||||||
{
|
{
|
||||||
NadekoBot.Client.UserJoined += UserJoined;
|
NadekoBot.Client.UserJoined += UserJoined;
|
||||||
NadekoBot.Client.UserLeft += UserLeft;
|
NadekoBot.Client.UserLeft += UserLeft;
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
}
|
}
|
||||||
|
//todo optimize ASAP
|
||||||
private Task UserLeft(IGuildUser user)
|
private static async void UserLeft(IGuildUser user)
|
||||||
{
|
|
||||||
var leftTask = Task.Run(async () =>
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
GuildConfig conf;
|
GuildConfig conf;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
conf = uow.GuildConfigs.For(user.Guild.Id);
|
conf = uow.GuildConfigs.For(user.Guild.Id, set => set);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!conf.SendChannelByeMessage) return;
|
if (!conf.SendChannelByeMessage) return;
|
||||||
@ -53,30 +50,22 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var toDelete = await channel.SendMessageAsync(msg.SanitizeMentions()).ConfigureAwait(false);
|
var toDelete = await channel.SendMessageAsync(msg.SanitizeMentions()).ConfigureAwait(false);
|
||||||
if (conf.AutoDeleteByeMessagesTimer > 0)
|
if (conf.AutoDeleteByeMessagesTimer > 0)
|
||||||
{
|
{
|
||||||
var t = Task.Run(async () =>
|
toDelete.DeleteAfter(conf.AutoDeleteByeMessagesTimer);
|
||||||
{
|
|
||||||
await Task.Delay(conf.AutoDeleteByeMessagesTimer * 1000).ConfigureAwait(false); // 5 minutes
|
|
||||||
try { await toDelete.DeleteAsync().ConfigureAwait(false); } catch { }
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex) { _log.Warn(ex); }
|
catch (Exception ex) { _log.Warn(ex); }
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
});
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task UserJoined(IGuildUser user)
|
private static async void UserJoined(IGuildUser user)
|
||||||
{
|
|
||||||
var joinedTask = Task.Run(async () =>
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
GuildConfig conf;
|
GuildConfig conf;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
conf = uow.GuildConfigs.For(user.Guild.Id);
|
conf = uow.GuildConfigs.For(user.Guild.Id, set => set);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf.SendChannelGreetMessage)
|
if (conf.SendChannelGreetMessage)
|
||||||
@ -92,11 +81,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var toDelete = await channel.SendMessageAsync(msg.SanitizeMentions()).ConfigureAwait(false);
|
var toDelete = await channel.SendMessageAsync(msg.SanitizeMentions()).ConfigureAwait(false);
|
||||||
if (conf.AutoDeleteGreetMessagesTimer > 0)
|
if (conf.AutoDeleteGreetMessagesTimer > 0)
|
||||||
{
|
{
|
||||||
var t = Task.Run(async () =>
|
toDelete.DeleteAfter(conf.AutoDeleteGreetMessagesTimer);
|
||||||
{
|
|
||||||
await Task.Delay(conf.AutoDeleteGreetMessagesTimer * 1000).ConfigureAwait(false); // 5 minutes
|
|
||||||
try { await toDelete.DeleteAsync().ConfigureAwait(false); } catch { }
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex) { _log.Warn(ex); }
|
catch (Exception ex) { _log.Warn(ex); }
|
||||||
@ -113,14 +98,12 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var msg = conf.DmGreetMessageText.Replace("%user%", user.Username).Replace("%server%", user.Guild.Name);
|
var msg = conf.DmGreetMessageText.Replace("%user%", user.Username).Replace("%server%", user.Guild.Name);
|
||||||
if (!string.IsNullOrWhiteSpace(msg))
|
if (!string.IsNullOrWhiteSpace(msg))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync(msg).ConfigureAwait(false);
|
await channel.SendConfirmAsync(msg).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
});
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -135,9 +118,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
await ServerGreetCommands.SetGreetDel(channel.Guild.Id, timer).ConfigureAwait(false);
|
await ServerGreetCommands.SetGreetDel(channel.Guild.Id, timer).ConfigureAwait(false);
|
||||||
|
|
||||||
if (timer > 0)
|
if (timer > 0)
|
||||||
await channel.SendMessageAsync($"🆗 Greet messages **will be deleted** after `{timer} seconds`.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"🆗 Greet messages **will be deleted** after `{timer} seconds`.").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync("ℹ️ Automatic deletion of greet messages has been **disabled**.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("ℹ️ Automatic deletion of greet messages has been **disabled**.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task SetGreetDel(ulong id, int timer)
|
private static async Task SetGreetDel(ulong id, int timer)
|
||||||
@ -147,9 +130,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var conf = uow.GuildConfigs.For(id);
|
var conf = uow.GuildConfigs.For(id, set => set);
|
||||||
conf.AutoDeleteGreetMessagesTimer = timer;
|
conf.AutoDeleteGreetMessagesTimer = timer;
|
||||||
uow.GuildConfigs.Update(conf);
|
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,9 +147,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var enabled = await ServerGreetCommands.SetGreet(channel.Guild.Id, channel.Id).ConfigureAwait(false);
|
var enabled = await ServerGreetCommands.SetGreet(channel.Guild.Id, channel.Id).ConfigureAwait(false);
|
||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
await channel.SendMessageAsync("✅ Greeting messages **enabled** on this channel.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("✅ Greeting messages **enabled** on this channel.").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync("ℹ️ Greeting messages **disabled**.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("ℹ️ Greeting messages **disabled**.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<bool> SetGreet(ulong guildId, ulong channelId, bool? value = null)
|
private static async Task<bool> SetGreet(ulong guildId, ulong channelId, bool? value = null)
|
||||||
@ -174,10 +157,10 @@ namespace NadekoBot.Modules.Administration
|
|||||||
bool enabled;
|
bool enabled;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var conf = uow.GuildConfigs.For(guildId);
|
var conf = uow.GuildConfigs.For(guildId, set => set);
|
||||||
enabled = conf.SendChannelGreetMessage = value ?? !conf.SendChannelGreetMessage;
|
enabled = conf.SendChannelGreetMessage = value ?? !conf.SendChannelGreetMessage;
|
||||||
conf.GreetMessageChannelId = channelId;
|
conf.GreetMessageChannelId = channelId;
|
||||||
uow.GuildConfigs.Update(conf);
|
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
return enabled;
|
return enabled;
|
||||||
@ -192,20 +175,20 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(text))
|
if (string.IsNullOrWhiteSpace(text))
|
||||||
{
|
{
|
||||||
GuildConfig config;
|
string channelGreetMessageText;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
config = uow.GuildConfigs.For(channel.Guild.Id);
|
channelGreetMessageText = uow.GuildConfigs.For(channel.Guild.Id, set => set).ChannelGreetMessageText;
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync("ℹ️ Current **greet** message: `" + config.ChannelGreetMessageText?.SanitizeMentions() + "`");
|
await channel.SendConfirmAsync("Current greet message: ", channelGreetMessageText?.SanitizeMentions());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sendGreetEnabled = ServerGreetCommands.SetGreetMessage(channel.Guild.Id, ref text);
|
var sendGreetEnabled = ServerGreetCommands.SetGreetMessage(channel.Guild.Id, ref text);
|
||||||
|
|
||||||
await channel.SendMessageAsync("🆗 New greet message **set**.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("🆗 New greet message **set**.").ConfigureAwait(false);
|
||||||
if (!sendGreetEnabled)
|
if (!sendGreetEnabled)
|
||||||
await channel.SendMessageAsync("ℹ️ Enable greet messsages by typing `.greet`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("ℹ️ Enable greet messsages by typing `.greet`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool SetGreetMessage(ulong guildId, ref string message)
|
public static bool SetGreetMessage(ulong guildId, ref string message)
|
||||||
@ -218,11 +201,10 @@ namespace NadekoBot.Modules.Administration
|
|||||||
bool greetMsgEnabled;
|
bool greetMsgEnabled;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var conf = uow.GuildConfigs.For(guildId);
|
var conf = uow.GuildConfigs.For(guildId, set => set);
|
||||||
conf.ChannelGreetMessageText = message;
|
conf.ChannelGreetMessageText = message;
|
||||||
greetMsgEnabled = conf.SendChannelGreetMessage;
|
greetMsgEnabled = conf.SendChannelGreetMessage;
|
||||||
|
|
||||||
uow.GuildConfigs.Update(conf);
|
|
||||||
uow.Complete();
|
uow.Complete();
|
||||||
}
|
}
|
||||||
return greetMsgEnabled;
|
return greetMsgEnabled;
|
||||||
@ -238,9 +220,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var enabled = await ServerGreetCommands.SetGreetDm(channel.Guild.Id).ConfigureAwait(false);
|
var enabled = await ServerGreetCommands.SetGreetDm(channel.Guild.Id).ConfigureAwait(false);
|
||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
await channel.SendMessageAsync("🆗 DM Greet announcements **enabled**.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("🆗 DM Greet announcements **enabled**.").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync("ℹ️ Greet announcements **disabled**.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("ℹ️ Greet announcements **disabled**.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<bool> SetGreetDm(ulong guildId, bool? value = null)
|
private static async Task<bool> SetGreetDm(ulong guildId, bool? value = null)
|
||||||
@ -248,9 +230,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
bool enabled;
|
bool enabled;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var conf = uow.GuildConfigs.For(guildId);
|
var conf = uow.GuildConfigs.For(guildId, set => set);
|
||||||
enabled = conf.SendDmGreetMessage = value ?? !conf.SendDmGreetMessage;
|
enabled = conf.SendDmGreetMessage = value ?? !conf.SendDmGreetMessage;
|
||||||
uow.GuildConfigs.Update(conf);
|
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
return enabled;
|
return enabled;
|
||||||
@ -270,15 +252,15 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
config = uow.GuildConfigs.For(channel.Guild.Id);
|
config = uow.GuildConfigs.For(channel.Guild.Id);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync("ℹ️ Current **DM greet** message: `" + config.DmGreetMessageText?.SanitizeMentions() + "`");
|
await channel.SendConfirmAsync("ℹ️ Current **DM greet** message: `" + config.DmGreetMessageText?.SanitizeMentions() + "`");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sendGreetEnabled = ServerGreetCommands.SetGreetDmMessage(channel.Guild.Id, ref text);
|
var sendGreetEnabled = ServerGreetCommands.SetGreetDmMessage(channel.Guild.Id, ref text);
|
||||||
|
|
||||||
await channel.SendMessageAsync("🆗 New DM greet message **set**.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("🆗 New DM greet message **set**.").ConfigureAwait(false);
|
||||||
if (!sendGreetEnabled)
|
if (!sendGreetEnabled)
|
||||||
await channel.SendMessageAsync($"ℹ️ Enable DM greet messsages by typing `{NadekoBot.ModulePrefixes[typeof(Administration).Name]}greetdm`").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"ℹ️ Enable DM greet messsages by typing `{NadekoBot.ModulePrefixes[typeof(Administration).Name]}greetdm`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool SetGreetDmMessage(ulong guildId, ref string message)
|
public static bool SetGreetDmMessage(ulong guildId, ref string message)
|
||||||
@ -295,7 +277,6 @@ namespace NadekoBot.Modules.Administration
|
|||||||
conf.DmGreetMessageText = message;
|
conf.DmGreetMessageText = message;
|
||||||
greetMsgEnabled = conf.SendDmGreetMessage;
|
greetMsgEnabled = conf.SendDmGreetMessage;
|
||||||
|
|
||||||
uow.GuildConfigs.Update(conf);
|
|
||||||
uow.Complete();
|
uow.Complete();
|
||||||
}
|
}
|
||||||
return greetMsgEnabled;
|
return greetMsgEnabled;
|
||||||
@ -311,9 +292,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var enabled = await ServerGreetCommands.SetBye(channel.Guild.Id, channel.Id).ConfigureAwait(false);
|
var enabled = await ServerGreetCommands.SetBye(channel.Guild.Id, channel.Id).ConfigureAwait(false);
|
||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
await channel.SendMessageAsync("✅ Bye announcements **enabled** on this channel.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("✅ Bye announcements **enabled** on this channel.").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync("ℹ️ Bye announcements **disabled**.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("ℹ️ Bye announcements **disabled**.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<bool> SetBye(ulong guildId, ulong channelId, bool? value = null)
|
private static async Task<bool> SetBye(ulong guildId, ulong channelId, bool? value = null)
|
||||||
@ -321,10 +302,10 @@ namespace NadekoBot.Modules.Administration
|
|||||||
bool enabled;
|
bool enabled;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var conf = uow.GuildConfigs.For(guildId);
|
var conf = uow.GuildConfigs.For(guildId, set => set);
|
||||||
enabled = conf.SendChannelByeMessage = value ?? !conf.SendChannelByeMessage;
|
enabled = conf.SendChannelByeMessage = value ?? !conf.SendChannelByeMessage;
|
||||||
conf.ByeMessageChannelId = channelId;
|
conf.ByeMessageChannelId = channelId;
|
||||||
uow.GuildConfigs.Update(conf);
|
|
||||||
await uow.CompleteAsync();
|
await uow.CompleteAsync();
|
||||||
}
|
}
|
||||||
return enabled;
|
return enabled;
|
||||||
@ -339,20 +320,20 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(text))
|
if (string.IsNullOrWhiteSpace(text))
|
||||||
{
|
{
|
||||||
GuildConfig config;
|
string byeMessageText;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
config = uow.GuildConfigs.For(channel.Guild.Id);
|
byeMessageText = uow.GuildConfigs.For(channel.Guild.Id, set => set).ChannelByeMessageText;
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync("ℹ️ Current **bye** message: `" + config.ChannelByeMessageText?.SanitizeMentions() + "`");
|
await channel.SendConfirmAsync("ℹ️ Current **bye** message: `" + byeMessageText?.SanitizeMentions() + "`");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sendByeEnabled = ServerGreetCommands.SetByeMessage(channel.Guild.Id, ref text);
|
var sendByeEnabled = ServerGreetCommands.SetByeMessage(channel.Guild.Id, ref text);
|
||||||
|
|
||||||
await channel.SendMessageAsync("🆗 New bye message **set**.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("🆗 New bye message **set**.").ConfigureAwait(false);
|
||||||
if (!sendByeEnabled)
|
if (!sendByeEnabled)
|
||||||
await channel.SendMessageAsync($"ℹ️ Enable bye messsages by typing `{NadekoBot.ModulePrefixes[typeof(Administration).Name]}bye`").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"ℹ️ Enable bye messsages by typing `{NadekoBot.ModulePrefixes[typeof(Administration).Name]}bye`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool SetByeMessage(ulong guildId, ref string message)
|
public static bool SetByeMessage(ulong guildId, ref string message)
|
||||||
@ -365,11 +346,10 @@ namespace NadekoBot.Modules.Administration
|
|||||||
bool byeMsgEnabled;
|
bool byeMsgEnabled;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var conf = uow.GuildConfigs.For(guildId);
|
var conf = uow.GuildConfigs.For(guildId, set => set);
|
||||||
conf.ChannelByeMessageText = message;
|
conf.ChannelByeMessageText = message;
|
||||||
byeMsgEnabled = conf.SendChannelByeMessage;
|
byeMsgEnabled = conf.SendChannelByeMessage;
|
||||||
|
|
||||||
uow.GuildConfigs.Update(conf);
|
|
||||||
uow.Complete();
|
uow.Complete();
|
||||||
}
|
}
|
||||||
return byeMsgEnabled;
|
return byeMsgEnabled;
|
||||||
@ -385,9 +365,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
await ServerGreetCommands.SetByeDel(channel.Guild.Id, timer).ConfigureAwait(false);
|
await ServerGreetCommands.SetByeDel(channel.Guild.Id, timer).ConfigureAwait(false);
|
||||||
|
|
||||||
if (timer > 0)
|
if (timer > 0)
|
||||||
await channel.SendMessageAsync($"🆗 Bye messages **will be deleted** after `{timer} seconds`.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"🆗 Bye messages **will be deleted** after `{timer} seconds`.").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync("ℹ️ Automatic deletion of bye messages has been **disabled**.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("ℹ️ Automatic deletion of bye messages has been **disabled**.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task SetByeDel(ulong id, int timer)
|
private static async Task SetByeDel(ulong id, int timer)
|
||||||
@ -397,9 +377,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var conf = uow.GuildConfigs.For(id);
|
var conf = uow.GuildConfigs.For(id, set => set);
|
||||||
conf.AutoDeleteByeMessagesTimer = timer;
|
conf.AutoDeleteByeMessagesTimer = timer;
|
||||||
uow.GuildConfigs.Update(conf);
|
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,10 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[Group]
|
[Group]
|
||||||
public class VoicePlusTextCommands
|
public class VoicePlusTextCommands
|
||||||
{
|
{
|
||||||
Regex channelNameRegex = new Regex(@"[^a-zA-Z0-9 -]", RegexOptions.Compiled);
|
private static Regex channelNameRegex = new Regex(@"[^a-zA-Z0-9 -]", RegexOptions.Compiled);
|
||||||
|
|
||||||
private ConcurrentHashSet<ulong> voicePlusTextCache;
|
private static ConcurrentHashSet<ulong> voicePlusTextCache { get; }
|
||||||
public VoicePlusTextCommands()
|
static VoicePlusTextCommands()
|
||||||
{
|
{
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
@ -29,15 +29,14 @@ namespace NadekoBot.Modules.Administration
|
|||||||
NadekoBot.Client.UserVoiceStateUpdated += UserUpdatedEventHandler;
|
NadekoBot.Client.UserVoiceStateUpdated += UserUpdatedEventHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task UserUpdatedEventHandler(IUser iuser, IVoiceState before, IVoiceState after)
|
private static async void UserUpdatedEventHandler(IUser iuser, IVoiceState before, IVoiceState after)
|
||||||
{
|
{
|
||||||
var user = (iuser as IGuildUser);
|
var user = (iuser as IGuildUser);
|
||||||
var guild = user?.Guild;
|
var guild = user?.Guild;
|
||||||
|
|
||||||
if (guild == null)
|
if (guild == null)
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
var task = Task.Run(async () =>
|
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var botUserPerms = guild.GetCurrentUser().GuildPermissions;
|
var botUserPerms = guild.GetCurrentUser().GuildPermissions;
|
||||||
@ -51,14 +50,14 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await (await guild.GetOwnerAsync()).SendMessageAsync(
|
await (await guild.GetOwnerAsync()).SendErrorAsync(
|
||||||
"⚠️ I don't have **manage server** and/or **manage channels** permission," +
|
"⚠️ I don't have **manage server** and/or **manage channels** permission," +
|
||||||
$" so I cannot run `voice+text` on **{guild.Name}** server.").ConfigureAwait(false);
|
$" so I cannot run `voice+text` on **{guild.Name}** server.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
uow.GuildConfigs.For(guild.Id).VoicePlusTextEnabled = false;
|
uow.GuildConfigs.For(guild.Id, set => set).VoicePlusTextEnabled = false;
|
||||||
voicePlusTextCache.TryRemove(guild.Id);
|
voicePlusTextCache.TryRemove(guild.Id);
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -97,11 +96,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
Console.WriteLine(ex);
|
Console.WriteLine(ex);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetChannelName(string voiceName) =>
|
private static string GetChannelName(string voiceName) =>
|
||||||
channelNameRegex.Replace(voiceName, "").Trim().Replace(" ", "-").TrimTo(90, true) + "-voice";
|
channelNameRegex.Replace(voiceName, "").Trim().Replace(" ", "-").TrimTo(90, true) + "-voice";
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -116,7 +113,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var botUser = await guild.GetCurrentUserAsync().ConfigureAwait(false);
|
var botUser = await guild.GetCurrentUserAsync().ConfigureAwait(false);
|
||||||
if (!botUser.GuildPermissions.ManageRoles || !botUser.GuildPermissions.ManageChannels)
|
if (!botUser.GuildPermissions.ManageRoles || !botUser.GuildPermissions.ManageChannels)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 I require atleast **manage roles** and **manage channels permissions** to enable this feature. `(preffered Administration permission)`");
|
await channel.SendErrorAsync("I require atleast **manage roles** and **manage channels permissions** to enable this feature. `(preffered Administration permission)`");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +121,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ You are enabling this feature and **I do not have ADMINISTRATOR permissions**. " +
|
await channel.SendErrorAsync("⚠️ You are enabling this feature and **I do not have ADMINISTRATOR permissions**. " +
|
||||||
"`This may cause some issues, and you will have to clean up text channels yourself afterwards.`");
|
"`This may cause some issues, and you will have to clean up text channels yourself afterwards.`");
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
@ -134,7 +131,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
bool isEnabled;
|
bool isEnabled;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var conf = uow.GuildConfigs.For(guild.Id);
|
var conf = uow.GuildConfigs.For(guild.Id, set => set);
|
||||||
isEnabled = conf.VoicePlusTextEnabled = !conf.VoicePlusTextEnabled;
|
isEnabled = conf.VoicePlusTextEnabled = !conf.VoicePlusTextEnabled;
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -145,16 +142,16 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
try { await textChannel.DeleteAsync().ConfigureAwait(false); } catch { }
|
try { await textChannel.DeleteAsync().ConfigureAwait(false); } catch { }
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync("ℹ️ Successfuly **removed** voice + text feature.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("ℹ️ Successfuly **removed** voice + text feature.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
voicePlusTextCache.Add(guild.Id);
|
voicePlusTextCache.Add(guild.Id);
|
||||||
await channel.SendMessageAsync("🆗 Successfuly **enabled** voice + text feature.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("🆗 Successfuly **enabled** voice + text feature.").ConfigureAwait(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync(ex.ToString()).ConfigureAwait(false);
|
await channel.SendErrorAsync(ex.ToString()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -168,7 +165,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var botUser = await guild.GetCurrentUserAsync().ConfigureAwait(false);
|
var botUser = await guild.GetCurrentUserAsync().ConfigureAwait(false);
|
||||||
if (!botUser.GuildPermissions.Administrator)
|
if (!botUser.GuildPermissions.Administrator)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ I need **Administrator permission** to do that.").ConfigureAwait(false);
|
await channel.SendErrorAsync("I need **Administrator permission** to do that.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,7 +180,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync("✅ Done.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("Cleaned v+t.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,8 @@ using NadekoBot.Attributes;
|
|||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.ClashOfClans
|
namespace NadekoBot.Modules.ClashOfClans
|
||||||
{
|
{
|
||||||
@ -18,6 +20,8 @@ namespace NadekoBot.Modules.ClashOfClans
|
|||||||
{
|
{
|
||||||
public static ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; set; } = new ConcurrentDictionary<ulong, List<ClashWar>>();
|
public static ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; set; } = new ConcurrentDictionary<ulong, List<ClashWar>>();
|
||||||
|
|
||||||
|
private static Timer checkWarTimer { get; }
|
||||||
|
|
||||||
static ClashOfClans()
|
static ClashOfClans()
|
||||||
{
|
{
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
@ -31,13 +35,21 @@ namespace NadekoBot.Modules.ClashOfClans
|
|||||||
?.GetTextChannel(cw.ChannelId);
|
?.GetTextChannel(cw.ChannelId);
|
||||||
return cw;
|
return cw;
|
||||||
})
|
})
|
||||||
.Where(cw => cw?.Channel != null)
|
.Where(cw => cw.Channel != null)
|
||||||
.GroupBy(cw => cw.GuildId)
|
.GroupBy(cw => cw.GuildId)
|
||||||
.ToDictionary(g => g.Key, g => g.ToList()));
|
.ToDictionary(g => g.Key, g => g.ToList()));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
public ClashOfClans(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
|
checkWarTimer = new Timer(async _ =>
|
||||||
{
|
{
|
||||||
|
foreach (var kvp in ClashWars)
|
||||||
|
{
|
||||||
|
foreach (var war in kvp.Value)
|
||||||
|
{
|
||||||
|
try { await CheckWar(TimeSpan.FromHours(2), war).ConfigureAwait(false); } catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task CheckWar(TimeSpan callExpire, ClashWar war)
|
private static async Task CheckWar(TimeSpan callExpire, ClashWar war)
|
||||||
@ -45,11 +57,20 @@ namespace NadekoBot.Modules.ClashOfClans
|
|||||||
var Bases = war.Bases;
|
var Bases = war.Bases;
|
||||||
for (var i = 0; i < Bases.Count; i++)
|
for (var i = 0; i < Bases.Count; i++)
|
||||||
{
|
{
|
||||||
if (Bases[i].CallUser == null) continue;
|
var callUser = Bases[i].CallUser;
|
||||||
if (!Bases[i].BaseDestroyed && DateTime.UtcNow - Bases[i].TimeAdded >= callExpire)
|
if (callUser == null) continue;
|
||||||
|
if ((!Bases[i].BaseDestroyed) && DateTime.UtcNow - Bases[i].TimeAdded >= callExpire)
|
||||||
{
|
{
|
||||||
|
if (Bases[i].Stars != 3)
|
||||||
|
Bases[i].BaseDestroyed = true;
|
||||||
|
else
|
||||||
Bases[i] = null;
|
Bases[i] = null;
|
||||||
try { await war.Channel.SendMessageAsync($"❗🔰**Claim from @{Bases[i].CallUser} for a war against {war.ShortPrint()} has expired.**").ConfigureAwait(false); } catch { }
|
try
|
||||||
|
{
|
||||||
|
SaveWar(war);
|
||||||
|
await war.Channel.SendErrorAsync($"❗🔰**Claim from @{Bases[i].CallUser} for a war against {war.ShortPrint()} has expired.**").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,7 +89,7 @@ namespace NadekoBot.Modules.ClashOfClans
|
|||||||
|
|
||||||
if (size < 10 || size > 50 || size % 5 != 0)
|
if (size < 10 || size > 50 || size % 5 != 0)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢🔰 Not a Valid war size").ConfigureAwait(false);
|
await channel.SendErrorAsync("🔰 Not a Valid war size").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
List<ClashWar> wars;
|
List<ClashWar> wars;
|
||||||
@ -83,7 +104,7 @@ namespace NadekoBot.Modules.ClashOfClans
|
|||||||
var cw = await CreateWar(enemyClan, size, channel.Guild.Id, umsg.Channel.Id);
|
var cw = await CreateWar(enemyClan, size, channel.Guild.Id, umsg.Channel.Id);
|
||||||
|
|
||||||
wars.Add(cw);
|
wars.Add(cw);
|
||||||
await channel.SendMessageAsync($"❗🔰**CREATED CLAN WAR AGAINST {cw.ShortPrint()}**").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"❗🔰**CREATED CLAN WAR AGAINST {cw.ShortPrint()}**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -98,18 +119,18 @@ namespace NadekoBot.Modules.ClashOfClans
|
|||||||
var warsInfo = GetWarInfo(umsg, num);
|
var warsInfo = GetWarInfo(umsg, num);
|
||||||
if (warsInfo == null)
|
if (warsInfo == null)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false);
|
await channel.SendErrorAsync("🔰 **That war does not exist.**").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var war = warsInfo.Item1[warsInfo.Item2];
|
var war = warsInfo.Item1[warsInfo.Item2];
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
war.Start();
|
war.Start();
|
||||||
await channel.SendMessageAsync($"🔰**STARTED WAR AGAINST {war.ShortPrint()}**").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"🔰**STARTED WAR AGAINST {war.ShortPrint()}**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"🔰**WAR AGAINST {war.ShortPrint()} HAS ALREADY STARTED**").ConfigureAwait(false);
|
await channel.SendErrorAsync($"🔰**WAR AGAINST {war.ShortPrint()} HAS ALREADY STARTED**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
SaveWar(war);
|
SaveWar(war);
|
||||||
}
|
}
|
||||||
@ -128,7 +149,7 @@ namespace NadekoBot.Modules.ClashOfClans
|
|||||||
ClashWars.TryGetValue(channel.Guild.Id, out wars);
|
ClashWars.TryGetValue(channel.Guild.Id, out wars);
|
||||||
if (wars == null || wars.Count == 0)
|
if (wars == null || wars.Count == 0)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("🔰 **No active wars.**").ConfigureAwait(false);
|
await channel.SendErrorAsync("🔰 **No active wars.**").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +162,7 @@ namespace NadekoBot.Modules.ClashOfClans
|
|||||||
sb.AppendLine($"\t\t`Size:` **{wars[i].Size} v {wars[i].Size}**");
|
sb.AppendLine($"\t\t`Size:` **{wars[i].Size} v {wars[i].Size}**");
|
||||||
sb.AppendLine("**-------------------------**");
|
sb.AppendLine("**-------------------------**");
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync(sb.ToString()).ConfigureAwait(false);
|
await channel.SendConfirmAsync(sb.ToString()).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -151,10 +172,10 @@ namespace NadekoBot.Modules.ClashOfClans
|
|||||||
var warsInfo = GetWarInfo(umsg, num);
|
var warsInfo = GetWarInfo(umsg, num);
|
||||||
if (warsInfo == null)
|
if (warsInfo == null)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false);
|
await channel.SendErrorAsync("🔰 **That war does not exist.**").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync(warsInfo.Item1[warsInfo.Item2].ToPrettyString()).ConfigureAwait(false);
|
await channel.SendConfirmAsync(warsInfo.Item1[warsInfo.Item2].ToPrettyString()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -165,7 +186,7 @@ namespace NadekoBot.Modules.ClashOfClans
|
|||||||
var warsInfo = GetWarInfo(umsg, number);
|
var warsInfo = GetWarInfo(umsg, number);
|
||||||
if (warsInfo == null || warsInfo.Item1.Count == 0)
|
if (warsInfo == null || warsInfo.Item1.Count == 0)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false);
|
await channel.SendErrorAsync("🔰 **That war does not exist.**").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var usr =
|
var usr =
|
||||||
@ -177,11 +198,11 @@ namespace NadekoBot.Modules.ClashOfClans
|
|||||||
var war = warsInfo.Item1[warsInfo.Item2];
|
var war = warsInfo.Item1[warsInfo.Item2];
|
||||||
war.Call(usr, baseNumber - 1);
|
war.Call(usr, baseNumber - 1);
|
||||||
SaveWar(war);
|
SaveWar(war);
|
||||||
await channel.SendMessageAsync($"🔰**{usr}** claimed a base #{baseNumber} for a war against {war.ShortPrint()}").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"🔰**{usr}** claimed a base #{baseNumber} for a war against {war.ShortPrint()}").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"💢🔰 {ex.Message}").ConfigureAwait(false);
|
await channel.SendErrorAsync($"🔰 {ex.Message}").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,16 +236,16 @@ namespace NadekoBot.Modules.ClashOfClans
|
|||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
var warsInfo = GetWarInfo(umsg,number);
|
var warsInfo = GetWarInfo(umsg, number);
|
||||||
if (warsInfo == null)
|
if (warsInfo == null)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢🔰 That war does not exist.").ConfigureAwait(false);
|
await channel.SendErrorAsync("🔰 That war does not exist.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var war = warsInfo.Item1[warsInfo.Item2];
|
var war = warsInfo.Item1[warsInfo.Item2];
|
||||||
war.End();
|
war.End();
|
||||||
SaveWar(war);
|
SaveWar(war);
|
||||||
await channel.SendMessageAsync($"❗🔰**War against {warsInfo.Item1[warsInfo.Item2].ShortPrint()} ended.**").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"❗🔰**War against {warsInfo.Item1[warsInfo.Item2].ShortPrint()} ended.**").ConfigureAwait(false);
|
||||||
|
|
||||||
var size = warsInfo.Item1[warsInfo.Item2].Size;
|
var size = warsInfo.Item1[warsInfo.Item2].Size;
|
||||||
warsInfo.Item1.RemoveAt(warsInfo.Item2);
|
warsInfo.Item1.RemoveAt(warsInfo.Item2);
|
||||||
@ -239,7 +260,7 @@ namespace NadekoBot.Modules.ClashOfClans
|
|||||||
var warsInfo = GetWarInfo(umsg, number);
|
var warsInfo = GetWarInfo(umsg, number);
|
||||||
if (warsInfo == null || warsInfo.Item1.Count == 0)
|
if (warsInfo == null || warsInfo.Item1.Count == 0)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false);
|
await channel.SendErrorAsync("🔰 **That war does not exist.**").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var usr =
|
var usr =
|
||||||
@ -251,11 +272,11 @@ namespace NadekoBot.Modules.ClashOfClans
|
|||||||
var war = warsInfo.Item1[warsInfo.Item2];
|
var war = warsInfo.Item1[warsInfo.Item2];
|
||||||
var baseNumber = war.Uncall(usr);
|
var baseNumber = war.Uncall(usr);
|
||||||
SaveWar(war);
|
SaveWar(war);
|
||||||
await channel.SendMessageAsync($"🔰 @{usr} has **UNCLAIMED** a base #{baseNumber + 1} from a war against {war.ShortPrint()}").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"🔰 @{usr} has **UNCLAIMED** a base #{baseNumber + 1} from a war against {war.ShortPrint()}").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"💢🔰 {ex.Message}").ConfigureAwait(false);
|
await channel.SendErrorAsync($"🔰 {ex.Message}").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,7 +286,7 @@ namespace NadekoBot.Modules.ClashOfClans
|
|||||||
var warInfo = GetWarInfo(umsg, number);
|
var warInfo = GetWarInfo(umsg, number);
|
||||||
if (warInfo == null || warInfo.Item1.Count == 0)
|
if (warInfo == null || warInfo.Item1.Count == 0)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false);
|
await channel.SendErrorAsync("🔰 **That war does not exist.**").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var war = warInfo.Item1[warInfo.Item2];
|
var war = warInfo.Item1[warInfo.Item2];
|
||||||
@ -280,11 +301,11 @@ namespace NadekoBot.Modules.ClashOfClans
|
|||||||
{
|
{
|
||||||
war.FinishClaim(baseNumber, stars);
|
war.FinishClaim(baseNumber, stars);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"❗🔰{umsg.Author.Mention} **DESTROYED** a base #{baseNumber + 1} in a war against {war.ShortPrint()}").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"❗🔰{umsg.Author.Mention} **DESTROYED** a base #{baseNumber + 1} in a war against {war.ShortPrint()}").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"💢🔰 {ex.Message}").ConfigureAwait(false);
|
await channel.SendErrorAsync($"🔰 {ex.Message}").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,8 +28,8 @@ namespace NadekoBot.Modules.ClashOfClans
|
|||||||
{
|
{
|
||||||
if (baseNumber < 0 || baseNumber >= cw.Bases.Count)
|
if (baseNumber < 0 || baseNumber >= cw.Bases.Count)
|
||||||
throw new ArgumentException("Invalid base number");
|
throw new ArgumentException("Invalid base number");
|
||||||
if (cw.Bases[baseNumber].CallUser != null)
|
if (cw.Bases[baseNumber].CallUser != null && cw.Bases[baseNumber].Stars == 3)
|
||||||
throw new ArgumentException("That base is already claimed.");
|
throw new ArgumentException("That base is already destroyed.");
|
||||||
for (var i = 0; i < cw.Bases.Count; i++)
|
for (var i = 0; i < cw.Bases.Count; i++)
|
||||||
{
|
{
|
||||||
if (cw.Bases[i]?.BaseDestroyed == false && cw.Bases[i]?.CallUser == u)
|
if (cw.Bases[i]?.BaseDestroyed == false && cw.Bases[i]?.CallUser == u)
|
||||||
@ -95,8 +95,15 @@ namespace NadekoBot.Modules.ClashOfClans
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var left = (cw.WarState == StateOfWar.Started) ? twoHours - (DateTime.UtcNow - cw.Bases[i].TimeAdded) : twoHours;
|
var left = (cw.WarState == StateOfWar.Started) ? twoHours - (DateTime.UtcNow - cw.Bases[i].TimeAdded) : twoHours;
|
||||||
|
if (cw.Bases[i].Stars == 3)
|
||||||
|
{
|
||||||
sb.AppendLine($"`{i + 1}.` ✅ `{cw.Bases[i].CallUser}` {left.Hours}h {left.Minutes}m {left.Seconds}s left");
|
sb.AppendLine($"`{i + 1}.` ✅ `{cw.Bases[i].CallUser}` {left.Hours}h {left.Minutes}m {left.Seconds}s left");
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.AppendLine($"`{i + 1}.` ✅ `{cw.Bases[i].CallUser}` {left.Hours}h {left.Minutes}m {left.Seconds}s left {new string('⭐', cw.Bases[i].Stars)} {string.Concat(Enumerable.Repeat("🔸", 3 - cw.Bases[i].Stars))}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,12 +10,14 @@ using NadekoBot.Extensions;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.CustomReactions
|
namespace NadekoBot.Modules.CustomReactions
|
||||||
{
|
{
|
||||||
[NadekoModule("CustomReactions",".")]
|
[NadekoModule("CustomReactions", ".")]
|
||||||
public class CustomReactions : DiscordModule
|
public class CustomReactions : DiscordModule
|
||||||
{
|
{
|
||||||
public static ConcurrentHashSet<CustomReaction> GlobalReactions { get; } = new ConcurrentHashSet<CustomReaction>();
|
public static ConcurrentHashSet<CustomReaction> GlobalReactions { get; } = new ConcurrentHashSet<CustomReaction>();
|
||||||
public static ConcurrentDictionary<ulong, ConcurrentHashSet<CustomReaction>> GuildReactions { get; } = new ConcurrentDictionary<ulong, ConcurrentHashSet<CustomReaction>>();
|
public static ConcurrentDictionary<ulong, ConcurrentHashSet<CustomReaction>> GuildReactions { get; } = new ConcurrentDictionary<ulong, ConcurrentHashSet<CustomReaction>>();
|
||||||
|
|
||||||
|
public static ConcurrentDictionary<string, uint> ReactionStats { get; } = new ConcurrentDictionary<string, uint>();
|
||||||
|
|
||||||
static CustomReactions()
|
static CustomReactions()
|
||||||
{
|
{
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
@ -25,10 +27,12 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
GlobalReactions = new ConcurrentHashSet<CustomReaction>(items.Where(g => g.GuildId == null || g.GuildId == 0));
|
GlobalReactions = new ConcurrentHashSet<CustomReaction>(items.Where(g => g.GuildId == null || g.GuildId == 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public CustomReactions(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
|
public CustomReactions() : base()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClearStats() => ReactionStats.Clear();
|
||||||
|
|
||||||
public static async Task<bool> TryExecuteCustomReaction(IUserMessage umsg)
|
public static async Task<bool> TryExecuteCustomReaction(IUserMessage umsg)
|
||||||
{
|
{
|
||||||
var channel = umsg.Channel as ITextChannel;
|
var channel = umsg.Channel as ITextChannel;
|
||||||
@ -40,14 +44,18 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
GuildReactions.TryGetValue(channel.Guild.Id, out reactions);
|
GuildReactions.TryGetValue(channel.Guild.Id, out reactions);
|
||||||
if (reactions != null && reactions.Any())
|
if (reactions != null && reactions.Any())
|
||||||
{
|
{
|
||||||
var reaction = reactions.Where(cr => {
|
var reaction = reactions.Where(cr =>
|
||||||
|
{
|
||||||
var hasTarget = cr.Response.ToLowerInvariant().Contains("%target%");
|
var hasTarget = cr.Response.ToLowerInvariant().Contains("%target%");
|
||||||
var trigger = cr.TriggerWithContext(umsg).Trim().ToLowerInvariant();
|
var trigger = cr.TriggerWithContext(umsg).Trim().ToLowerInvariant();
|
||||||
return ((hasTarget && content.StartsWith(trigger + " ")) || content == trigger);
|
return ((hasTarget && content.StartsWith(trigger + " ")) || content == trigger);
|
||||||
}).Shuffle().FirstOrDefault();
|
}).Shuffle().FirstOrDefault();
|
||||||
if (reaction != null)
|
if (reaction != null)
|
||||||
{
|
{
|
||||||
|
if (reaction.Response != "-")
|
||||||
try { await channel.SendMessageAsync(reaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { }
|
try { await channel.SendMessageAsync(reaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { }
|
||||||
|
|
||||||
|
ReactionStats.AddOrUpdate(reaction.Trigger, 1, (k, old) => ++old);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,6 +69,7 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
if (greaction != null)
|
if (greaction != null)
|
||||||
{
|
{
|
||||||
try { await channel.SendMessageAsync(greaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { }
|
try { await channel.SendMessageAsync(greaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { }
|
||||||
|
ReactionStats.AddOrUpdate(greaction.Trigger, 1, (k, old) => ++old);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -77,7 +86,7 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
|
|
||||||
if ((channel == null && !NadekoBot.Credentials.IsOwner(imsg.Author)) || (channel != null && !((IGuildUser)imsg.Author).GuildPermissions.Administrator))
|
if ((channel == null && !NadekoBot.Credentials.IsOwner(imsg.Author)) || (channel != null && !((IGuildUser)imsg.Author).GuildPermissions.Administrator))
|
||||||
{
|
{
|
||||||
try { await imsg.Channel.SendMessageAsync("Insufficient permissions. Requires Bot ownership for global custom reactions, and Administrator for guild custom reactions."); } catch { }
|
try { await imsg.Channel.SendErrorAsync("Insufficient permissions. Requires Bot ownership for global custom reactions, and Administrator for guild custom reactions."); } catch { }
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +115,12 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
reactions.Add(cr);
|
reactions.Add(cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
await imsg.Channel.SendMessageAsync($"`Added new custom reaction {cr.Id}:`\n\t`Trigger:` {key}\n\t`Response:` {message}").ConfigureAwait(false);
|
await imsg.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||||
|
.WithTitle("New Custom Reaction")
|
||||||
|
.WithDescription($"#{cr.Id}")
|
||||||
|
.AddField(efb => efb.WithName("Trigger").WithValue(key))
|
||||||
|
.AddField(efb => efb.WithName("Response").WithValue(message))
|
||||||
|
.Build()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -124,12 +138,11 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
customReactions = GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CustomReaction>());
|
customReactions = GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CustomReaction>());
|
||||||
|
|
||||||
if (customReactions == null || !customReactions.Any())
|
if (customReactions == null || !customReactions.Any())
|
||||||
await imsg.Channel.SendMessageAsync("`No custom reactions found`").ConfigureAwait(false);
|
await imsg.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await imsg.Channel.SendMessageAsync(
|
await imsg.Channel.SendConfirmAsync(
|
||||||
$"`Page {page} of custom reactions:`\n" +
|
$"Page {page} of custom reactions:",
|
||||||
string.Join("\n", customReactions
|
string.Join("\n", customReactions.OrderBy(cr => cr.Trigger)
|
||||||
.OrderBy(cr => cr.Trigger)
|
|
||||||
.Skip((page - 1) * 20)
|
.Skip((page - 1) * 20)
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.Select(cr => $"`#{cr.Id}` `Trigger:` {cr.Trigger}")))
|
.Select(cr => $"`#{cr.Id}` `Trigger:` {cr.Trigger}")))
|
||||||
@ -154,12 +167,12 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
customReactions = GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CustomReaction>());
|
customReactions = GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CustomReaction>());
|
||||||
|
|
||||||
if (customReactions == null || !customReactions.Any())
|
if (customReactions == null || !customReactions.Any())
|
||||||
await imsg.Channel.SendMessageAsync("`No custom reactions found`").ConfigureAwait(false);
|
await imsg.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var txtStream = await customReactions.GroupBy(cr => cr.Trigger)
|
var txtStream = await customReactions.GroupBy(cr => cr.Trigger)
|
||||||
.OrderBy(cr => cr.Key)
|
.OrderBy(cr => cr.Key)
|
||||||
.Select(cr => new { Trigger = cr.Key, Responses = cr.Select(y => y.Response).ToList() })
|
.Select(cr => new { Trigger = cr.Key, Responses = cr.Select(y => new { id = y.Id, text = y.Response }).ToList() })
|
||||||
.ToJson()
|
.ToJson()
|
||||||
.ToStream()
|
.ToStream()
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
@ -183,11 +196,11 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
customReactions = GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CustomReaction>());
|
customReactions = GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CustomReaction>());
|
||||||
|
|
||||||
if (customReactions == null || !customReactions.Any())
|
if (customReactions == null || !customReactions.Any())
|
||||||
await imsg.Channel.SendMessageAsync("`No custom reactions found`").ConfigureAwait(false);
|
await imsg.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await imsg.Channel.SendMessageAsync($"{imsg.Author.Mention}\n`Page {page} of custom reactions (grouped):`\n" +
|
await imsg.Channel.SendConfirmAsync($"Page {page} of custom reactions (grouped):",
|
||||||
string.Join("\r\n", customReactions
|
string.Join("\r\n", customReactions
|
||||||
.GroupBy(cr=>cr.Trigger)
|
.GroupBy(cr => cr.Trigger)
|
||||||
.OrderBy(cr => cr.Key)
|
.OrderBy(cr => cr.Key)
|
||||||
.Skip((page - 1) * 20)
|
.Skip((page - 1) * 20)
|
||||||
.Take(20)
|
.Take(20)
|
||||||
@ -209,11 +222,14 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
var found = customReactions.FirstOrDefault(cr => cr.Id == id);
|
var found = customReactions.FirstOrDefault(cr => cr.Id == id);
|
||||||
|
|
||||||
if (found == null)
|
if (found == null)
|
||||||
await imsg.Channel.SendMessageAsync("`No custom reaction found with that id.`").ConfigureAwait(false);
|
await imsg.Channel.SendErrorAsync("No custom reaction found with that id.").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await imsg.Channel.SendMessageAsync($"`Custom reaction #{id}`\n`Trigger:` {found.Trigger}\n`Response:` {found.Response} ```css\n{found.Response}```")
|
await imsg.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||||
.ConfigureAwait(false);
|
.WithDescription($"#{id}")
|
||||||
|
.AddField(efb => efb.WithName("Trigger").WithValue(found.Trigger))
|
||||||
|
.AddField(efb => efb.WithName("Response").WithValue(found.Response + "\n```css\n" + found.Response + "```"))
|
||||||
|
.Build()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +240,7 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
|
|
||||||
if ((channel == null && !NadekoBot.Credentials.IsOwner(imsg.Author)) || (channel != null && !((IGuildUser)imsg.Author).GuildPermissions.Administrator))
|
if ((channel == null && !NadekoBot.Credentials.IsOwner(imsg.Author)) || (channel != null && !((IGuildUser)imsg.Author).GuildPermissions.Administrator))
|
||||||
{
|
{
|
||||||
try { await imsg.Channel.SendMessageAsync("Insufficient permissions. Requires Bot ownership for global custom reactions, and Administrator for guild custom reactions."); } catch { }
|
try { await imsg.Channel.SendErrorAsync("Insufficient permissions. Requires Bot ownership for global custom reactions, and Administrator for guild custom reactions."); } catch { }
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,14 +264,50 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CustomReaction>()).RemoveWhere(cr => cr.Id == toDelete.Id);
|
GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CustomReaction>()).RemoveWhere(cr => cr.Id == toDelete.Id);
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
if(success)
|
if (success)
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
await imsg.Channel.SendMessageAsync("**Successfully deleted custom reaction** " + toDelete.ToString()).ConfigureAwait(false);
|
await imsg.Channel.SendConfirmAsync("Deleted custom reaction", toDelete.ToString()).ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await imsg.Channel.SendMessageAsync("`Failed to find that custom reaction.`").ConfigureAwait(false);
|
await imsg.Channel.SendErrorAsync("Failed to find that custom reaction.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
public async Task CrStatsClear(IUserMessage imsg, string trigger = null)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(trigger))
|
||||||
|
{
|
||||||
|
ClearStats();
|
||||||
|
await imsg.Channel.SendConfirmAsync($"Custom reaction stats cleared.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint throwaway;
|
||||||
|
if (ReactionStats.TryRemove(trigger, out throwaway))
|
||||||
|
{
|
||||||
|
await imsg.Channel.SendConfirmAsync($"Stats cleared for `{trigger}` custom reaction.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await imsg.Channel.SendErrorAsync("No stats for that trigger found, no action taken.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
public async Task CrStats(IUserMessage imsg, int page = 1)
|
||||||
|
{
|
||||||
|
if (page < 1)
|
||||||
|
return;
|
||||||
|
await imsg.Channel.EmbedAsync(ReactionStats.OrderByDescending(x => x.Value)
|
||||||
|
.Skip((page - 1) * 9)
|
||||||
|
.Take(9)
|
||||||
|
.Aggregate(new EmbedBuilder().WithOkColor().WithTitle($"Custom Reaction stats page #{page}"),
|
||||||
|
(agg, cur) => agg.AddField(efb => efb.WithName(cur.Key).WithValue(cur.Value.ToString()).WithIsInline(true)))
|
||||||
|
.Build())
|
||||||
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,8 +1,11 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
|
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.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.CustomReactions
|
namespace NadekoBot.Modules.CustomReactions
|
||||||
{
|
{
|
||||||
@ -17,7 +20,41 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
{
|
{
|
||||||
{"%mention%", (ctx) => { return $"<@{NadekoBot.Client.GetCurrentUser().Id}>"; } },
|
{"%mention%", (ctx) => { return $"<@{NadekoBot.Client.GetCurrentUser().Id}>"; } },
|
||||||
{"%user%", (ctx) => { return ctx.Author.Mention; } },
|
{"%user%", (ctx) => { return ctx.Author.Mention; } },
|
||||||
{"%rng%", (ctx) => { return new NadekoRandom().Next(0,10).ToString(); } }
|
{"%rnduser%", (ctx) => {
|
||||||
|
var ch = ctx.Channel as ITextChannel;
|
||||||
|
if(ch == null)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
var usrs = (ch.Guild.GetUsersAsync().GetAwaiter().GetResult());
|
||||||
|
|
||||||
|
return usrs.Skip(new NadekoRandom().Next(0,usrs.Count-1)).Shuffle().FirstOrDefault()?.Mention ?? "";
|
||||||
|
} }
|
||||||
|
//{"%rng%", (ctx) => { return new NadekoRandom().Next(0,10).ToString(); } }
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly Regex rngRegex = new Regex("%rng(?:(?<from>(?:-)?\\d+)-(?<to>(?:-)?\\d+))?%", RegexOptions.Compiled);
|
||||||
|
|
||||||
|
private static readonly NadekoRandom rng = new NadekoRandom();
|
||||||
|
|
||||||
|
public static Dictionary<Regex, MatchEvaluator> regexPlaceholders = new Dictionary<Regex, MatchEvaluator>()
|
||||||
|
{
|
||||||
|
{ rngRegex, (match) => {
|
||||||
|
int from = 0;
|
||||||
|
int.TryParse(match.Groups["from"].ToString(), out from);
|
||||||
|
|
||||||
|
int to = 0;
|
||||||
|
int.TryParse(match.Groups["to"].ToString(), out to);
|
||||||
|
|
||||||
|
if(from == 0 && to == 0)
|
||||||
|
{
|
||||||
|
return rng.Next(0, 11).ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(from >= to)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
return rng.Next(from,to+1).ToString();
|
||||||
|
} }
|
||||||
};
|
};
|
||||||
|
|
||||||
private static string ResolveTriggerString(this string str, IUserMessage ctx)
|
private static string ResolveTriggerString(this string str, IUserMessage ctx)
|
||||||
@ -40,6 +77,11 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
{
|
{
|
||||||
str = str.Replace(ph.Key.ToLowerInvariant(), ph.Value(ctx, resolvedTrigger));
|
str = str.Replace(ph.Key.ToLowerInvariant(), ph.Value(ctx, resolvedTrigger));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var ph in regexPlaceholders)
|
||||||
|
{
|
||||||
|
str = ph.Key.Replace(str, ph.Value);
|
||||||
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,13 +6,10 @@ namespace NadekoBot.Modules
|
|||||||
{
|
{
|
||||||
public class DiscordModule
|
public class DiscordModule
|
||||||
{
|
{
|
||||||
protected ILocalization _l { get; }
|
|
||||||
protected CommandService _commands { get; }
|
|
||||||
protected ShardedDiscordClient _client { get; }
|
|
||||||
protected Logger _log { get; }
|
protected Logger _log { get; }
|
||||||
protected string _prefix { get; }
|
protected string _prefix { get; }
|
||||||
|
|
||||||
public DiscordModule(ILocalization loc, CommandService cmds, ShardedDiscordClient client)
|
public DiscordModule()
|
||||||
{
|
{
|
||||||
string prefix;
|
string prefix;
|
||||||
if (NadekoBot.ModulePrefixes.TryGetValue(this.GetType().Name, out prefix))
|
if (NadekoBot.ModulePrefixes.TryGetValue(this.GetType().Name, out prefix))
|
||||||
@ -20,9 +17,6 @@ namespace NadekoBot.Modules
|
|||||||
else
|
else
|
||||||
_prefix = "?missing_prefix?";
|
_prefix = "?missing_prefix?";
|
||||||
|
|
||||||
_l = loc;
|
|
||||||
_commands = cmds;
|
|
||||||
_client = client;
|
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,11 +18,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
[Group]
|
[Group]
|
||||||
public class AnimalRacing
|
public class AnimalRacing
|
||||||
{
|
{
|
||||||
|
public static ConcurrentDictionary<ulong, AnimalRace> AnimalRaces { get; } = new ConcurrentDictionary<ulong, AnimalRace>();
|
||||||
public AnimalRacing()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
public static ConcurrentDictionary<ulong, AnimalRace> AnimalRaces = new ConcurrentDictionary<ulong, AnimalRace>();
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
@ -33,7 +29,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
var ar = new AnimalRace(channel.Guild.Id, channel);
|
var ar = new AnimalRace(channel.Guild.Id, channel);
|
||||||
|
|
||||||
if (ar.Fail)
|
if (ar.Fail)
|
||||||
await channel.SendMessageAsync("🏁 `Failed starting a race. Another race is probably running.`");
|
await channel.SendErrorAsync("Animal Race", "Failed starting. Another race is probably running.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -49,7 +45,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
AnimalRace ar;
|
AnimalRace ar;
|
||||||
if (!AnimalRaces.TryGetValue(channel.Guild.Id, out ar))
|
if (!AnimalRaces.TryGetValue(channel.Guild.Id, out ar))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("No race exists on this server");
|
await channel.SendErrorAsync("No race exists on this server").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await ar.JoinRace(umsg.Author as IGuildUser, amount);
|
await ar.JoinRace(umsg.Author as IGuildUser, amount);
|
||||||
@ -94,21 +90,29 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
try { await raceChannel.SendMessageAsync($"🏁`Race is starting in 20 seconds or when the room is full. Type {NadekoBot.ModulePrefixes[typeof(Gambling).Name]}jr to join the race.`"); } catch (Exception ex) { _log.Warn(ex); }
|
try
|
||||||
|
{
|
||||||
|
await raceChannel.SendConfirmAsync("Animal Race", $"Starting in 20 seconds or when the room is full.",
|
||||||
|
footer: $"Type {NadekoBot.ModulePrefixes[typeof(Gambling).Name]}jr to join the race.");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_log.Warn(ex);
|
||||||
|
}
|
||||||
var t = await Task.WhenAny(Task.Delay(20000, token), fullgame);
|
var t = await Task.WhenAny(Task.Delay(20000, token), fullgame);
|
||||||
Started = true;
|
Started = true;
|
||||||
cancelSource.Cancel();
|
cancelSource.Cancel();
|
||||||
if (t == fullgame)
|
if (t == fullgame)
|
||||||
{
|
{
|
||||||
try { await raceChannel.SendMessageAsync("🏁`Race full, starting right now!`"); } catch (Exception ex) { _log.Warn(ex); }
|
try { await raceChannel.SendConfirmAsync("Animal Race", "Full! Starting immediately."); } catch (Exception ex) { _log.Warn(ex); }
|
||||||
}
|
}
|
||||||
else if (participants.Count > 1)
|
else if (participants.Count > 1)
|
||||||
{
|
{
|
||||||
try { await raceChannel.SendMessageAsync("🏁`Game starting with " + participants.Count + " participants.`"); } catch (Exception ex) { _log.Warn(ex); }
|
try { await raceChannel.SendConfirmAsync("Animal Race", "Starting with " + participants.Count + " participants."); } catch (Exception ex) { _log.Warn(ex); }
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
try { await raceChannel.SendMessageAsync("🏁`Race failed to start since there was not enough participants.`"); } catch (Exception ex) { _log.Warn(ex); }
|
try { await raceChannel.SendErrorAsync("Animal Race", "Failed to start since there was not enough participants."); } catch (Exception ex) { _log.Warn(ex); }
|
||||||
var p = participants.FirstOrDefault();
|
var p = participants.FirstOrDefault();
|
||||||
|
|
||||||
if (p != null && p.AmountBet > 0)
|
if (p != null && p.AmountBet > 0)
|
||||||
@ -119,7 +123,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
await Task.Run(StartRace);
|
await Task.Run(StartRace);
|
||||||
End();
|
End();
|
||||||
}
|
}
|
||||||
catch { }
|
catch { try { End(); } catch { } }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,13 +149,20 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
participants.ForEach(p =>
|
participants.ForEach(p =>
|
||||||
{
|
{
|
||||||
p.Total += 1 + rng.Next(0, 10);
|
p.Total += 1 + rng.Next(0, 10);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
participants
|
||||||
|
.OrderByDescending(p => p.Total)
|
||||||
|
.ForEach(p =>
|
||||||
|
{
|
||||||
if (p.Total > 60)
|
if (p.Total > 60)
|
||||||
{
|
{
|
||||||
p.Total = 60;
|
|
||||||
if (winner == null)
|
if (winner == null)
|
||||||
{
|
{
|
||||||
winner = p;
|
winner = p;
|
||||||
}
|
}
|
||||||
|
p.Total = 60;
|
||||||
if (p.Place == 0)
|
if (p.Place == 0)
|
||||||
p.Place = place++;
|
p.Place = place++;
|
||||||
}
|
}
|
||||||
@ -188,25 +199,25 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
{
|
{
|
||||||
var wonAmount = winner.AmountBet * (participants.Count - 1);
|
var wonAmount = winner.AmountBet * (participants.Count - 1);
|
||||||
|
|
||||||
await CurrencyHandler.AddCurrencyAsync(winner.User, "Won a Race", wonAmount, false).ConfigureAwait(false);
|
await CurrencyHandler.AddCurrencyAsync(winner.User, "Won a Race", wonAmount, true).ConfigureAwait(false);
|
||||||
await raceChannel.SendMessageAsync($"🏁 {winner.User.Mention} as {winner.Animal} **Won the race and {wonAmount}{CurrencySign}!**").ConfigureAwait(false);
|
await raceChannel.SendConfirmAsync("Animal Race", $"{winner.User.Mention} as {winner.Animal} **Won the race and {wonAmount}{CurrencySign}!**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await raceChannel.SendMessageAsync($"🏁 {winner.User.Mention} as {winner.Animal} **Won the race!**");
|
await raceChannel.SendConfirmAsync("Animal Race", $"{winner.User.Mention} as {winner.Animal} **Won the race!**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task Client_MessageReceived(IMessage imsg)
|
private void Client_MessageReceived(IMessage imsg)
|
||||||
{
|
{
|
||||||
var msg = imsg as IUserMessage;
|
var msg = imsg as IUserMessage;
|
||||||
if (msg == null)
|
if (msg == null)
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
if (msg.IsAuthor() || !(imsg.Channel is ITextChannel) || imsg.Channel != raceChannel)
|
if (msg.IsAuthor() || !(imsg.Channel is ITextChannel) || imsg.Channel != raceChannel)
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
messagesSinceGameStarted++;
|
messagesSinceGameStarted++;
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CheckForFullGameAsync(CancellationToken cancelToken)
|
private async Task CheckForFullGameAsync(CancellationToken cancelToken)
|
||||||
@ -222,28 +233,29 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
var animal = "";
|
var animal = "";
|
||||||
if (!animals.TryDequeue(out animal))
|
if (!animals.TryDequeue(out animal))
|
||||||
{
|
{
|
||||||
await raceChannel.SendMessageAsync($"{u.Mention} `There is no running race on this server.`");
|
await raceChannel.SendErrorAsync($"{u.Mention} `There is no running race on this server.`").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var p = new Participant(u, animal, amount);
|
var p = new Participant(u, animal, amount);
|
||||||
if (participants.Contains(p))
|
if (participants.Contains(p))
|
||||||
{
|
{
|
||||||
await raceChannel.SendMessageAsync($"{u.Mention} `You already joined this race.`");
|
await raceChannel.SendErrorAsync($"{u.Mention} `You already joined this race.`").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Started)
|
if (Started)
|
||||||
{
|
{
|
||||||
await raceChannel.SendMessageAsync($"{u.Mention} `Race is already started`");
|
await raceChannel.SendErrorAsync($"{u.Mention} `Race is already started`").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (amount > 0)
|
if (amount > 0)
|
||||||
if (!await CurrencyHandler.RemoveCurrencyAsync((IGuildUser)u, "BetRace", amount, true).ConfigureAwait(false))
|
if (!await CurrencyHandler.RemoveCurrencyAsync((IGuildUser)u, "BetRace", amount, false).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
try { await raceChannel.SendMessageAsync($"{u.Mention} You don't have enough {Gambling.CurrencyName}s.").ConfigureAwait(false); } catch { }
|
try { await raceChannel.SendErrorAsync($"{u.Mention} You don't have enough {Gambling.CurrencyName}s.").ConfigureAwait(false); } catch { }
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
participants.Add(p);
|
participants.Add(p);
|
||||||
await raceChannel.SendMessageAsync($"{u.Mention} **joined the race as a {p.Animal}" + (amount > 0 ? $" and bet {amount} {CurrencySign}!**" : "**"));
|
await raceChannel.SendConfirmAsync("Animal Race", $"{u.Mention} **joined as a {p.Animal}" + (amount > 0 ? $" and bet {amount} {CurrencySign}!**" : "**"))
|
||||||
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,10 +277,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
this.AmountBet = amount;
|
this.AmountBet = amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode() => User.GetHashCode();
|
||||||
{
|
|
||||||
return User.GetHashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj)
|
||||||
{
|
{
|
||||||
|
@ -19,6 +19,9 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
public class DriceRollCommands
|
public class DriceRollCommands
|
||||||
{
|
{
|
||||||
private Regex dndRegex { get; } = 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 Regex fudgeRegex { get; } = new Regex(@"^(?<n1>\d+)d(?:F|f)$", RegexOptions.Compiled);
|
||||||
|
|
||||||
|
private readonly char[] fateRolls = new[] { '-', ' ', '+' };
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
@ -46,57 +49,55 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
|
|
||||||
await channel.SendFileAsync(imageStream, "dice.png", $"{umsg.Author.Mention} rolled " + Format.Code(gen.ToString())).ConfigureAwait(false);
|
await channel.SendFileAsync(imageStream, "dice.png", $"{umsg.Author.Mention} rolled " + Format.Code(gen.ToString())).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
//todo merge into internallDndRoll and internalRoll
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[Priority(1)]
|
|
||||||
public async Task Roll(IUserMessage umsg, string arg)
|
|
||||||
{
|
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
if (channel == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var ordered = true;
|
public enum RollOrderType
|
||||||
var rng = new NadekoRandom();
|
|
||||||
Match match;
|
|
||||||
if ((match = dndRegex.Match(arg)).Length != 0)
|
|
||||||
{
|
{
|
||||||
int n1;
|
Ordered,
|
||||||
int n2;
|
Unordered
|
||||||
if (int.TryParse(match.Groups["n1"].ToString(), out n1) &&
|
|
||||||
int.TryParse(match.Groups["n2"].ToString(), out n2) &&
|
|
||||||
n1 <= 50 && n2 <= 100000 && n1 > 0 && n2 > 0)
|
|
||||||
{
|
|
||||||
var add = 0;
|
|
||||||
var sub = 0;
|
|
||||||
int.TryParse(match.Groups["add"].Value, out add);
|
|
||||||
int.TryParse(match.Groups["sub"].Value, out sub);
|
|
||||||
|
|
||||||
var arr = new int[n1];
|
|
||||||
for (int i = 0; i < n1; i++)
|
|
||||||
{
|
|
||||||
arr[i] = rng.Next(1, n2 + 1) + add - sub;
|
|
||||||
}
|
|
||||||
var elemCnt = 0;
|
|
||||||
await channel.SendMessageAsync($"{umsg.Author.Mention} rolled {n1} {(n1 == 1 ? "die" : "dice")} `1 to {n2}` +`{add}` -`{sub}`.\n`Result:` " + string.Join(", ", (ordered ? arr.OrderBy(x => x).AsEnumerable() : arr).Select(x => elemCnt++ % 2 == 0 ? $"**{x}**" : x.ToString()))).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[Priority(0)]
|
[Priority(0)]
|
||||||
public async Task Roll(IUserMessage umsg, int num)
|
public async Task Roll(IUserMessage umsg, int num)
|
||||||
|
{
|
||||||
|
await InternalRoll(umsg, num, true).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[Priority(0)]
|
||||||
|
public async Task Rolluo(IUserMessage umsg, int num)
|
||||||
|
{
|
||||||
|
await InternalRoll(umsg, num, false).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[Priority(1)]
|
||||||
|
public async Task Roll(IUserMessage umsg, string arg)
|
||||||
|
{
|
||||||
|
await InternallDndRoll(umsg, arg, true).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[Priority(1)]
|
||||||
|
public async Task Rolluo(IUserMessage umsg, string arg)
|
||||||
|
{
|
||||||
|
await InternallDndRoll(umsg, arg, false).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task InternalRoll(IUserMessage umsg, int num, bool ordered)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
if (channel == null)
|
if (channel == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var ordered = true;
|
|
||||||
|
|
||||||
if (num < 1 || num > 30)
|
if (num < 1 || num > 30)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("Invalid number specified. You can roll up to 1-30 dice at a time.").ConfigureAwait(false);
|
await channel.SendErrorAsync("Invalid number specified. You can roll up to 1-30 dice at a time.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,21 +138,35 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
await channel.SendFileAsync(ms, "dice.png", $"{umsg.Author.Mention} rolled {values.Count} {(values.Count == 1 ? "die" : "dice")}. Total: **{values.Sum()}** Average: **{(values.Sum() / (1.0f * values.Count)).ToString("N2")}**").ConfigureAwait(false);
|
await channel.SendFileAsync(ms, "dice.png", $"{umsg.Author.Mention} rolled {values.Count} {(values.Count == 1 ? "die" : "dice")}. Total: **{values.Sum()}** Average: **{(values.Sum() / (1.0f * values.Count)).ToString("N2")}**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
private async Task InternallDndRoll(IUserMessage umsg, string arg, bool ordered)
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
public async Task Rolluo(IUserMessage umsg, string arg)
|
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
if (channel == null)
|
if (channel == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var ordered = false;
|
|
||||||
var rng = new NadekoRandom();
|
|
||||||
Match match;
|
Match match;
|
||||||
if ((match = dndRegex.Match(arg)).Length != 0)
|
|
||||||
{
|
|
||||||
int n1;
|
int n1;
|
||||||
int n2;
|
int n2;
|
||||||
|
if ((match = fudgeRegex.Match(arg)).Length != 0 &&
|
||||||
|
int.TryParse(match.Groups["n1"].ToString(), out n1) &&
|
||||||
|
n1 > 0 && n1 < 500)
|
||||||
|
{
|
||||||
|
var rng = new NadekoRandom();
|
||||||
|
|
||||||
|
var rolls = new List<char>();
|
||||||
|
|
||||||
|
for (int i = 0; i < n1; i++)
|
||||||
|
{
|
||||||
|
rolls.Add(fateRolls[rng.Next(0, fateRolls.Length)]);
|
||||||
|
}
|
||||||
|
var embed = new EmbedBuilder().WithOkColor().WithDescription($"{umsg.Author.Mention} rolled {n1} fate {(n1 == 1 ? "die" : "dice")}.")
|
||||||
|
.AddField(efb => efb.WithName(Format.Bold("Result"))
|
||||||
|
.WithValue(string.Join(" ", rolls.Select(c => Format.Code($"[{c}]")))));
|
||||||
|
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else if ((match = dndRegex.Match(arg)).Length != 0)
|
||||||
|
{
|
||||||
|
var rng = new NadekoRandom();
|
||||||
if (int.TryParse(match.Groups["n1"].ToString(), out n1) &&
|
if (int.TryParse(match.Groups["n1"].ToString(), out n1) &&
|
||||||
int.TryParse(match.Groups["n2"].ToString(), out n2) &&
|
int.TryParse(match.Groups["n2"].ToString(), out n2) &&
|
||||||
n1 <= 50 && n2 <= 100000 && n1 > 0 && n2 > 0)
|
n1 <= 50 && n2 <= 100000 && n1 > 0 && n2 > 0)
|
||||||
@ -166,64 +181,14 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
{
|
{
|
||||||
arr[i] = rng.Next(1, n2 + 1) + add - sub;
|
arr[i] = rng.Next(1, n2 + 1) + add - sub;
|
||||||
}
|
}
|
||||||
var elemCnt = 0;
|
|
||||||
await channel.SendMessageAsync($"{umsg.Author.Mention} rolled {n1} {(n1 == 1 ? "die" : "dice")} `1 to {n2}` +`{add}` -`{sub}`.\n`Result:` " + string.Join(", ", (ordered ? arr.OrderBy(x => x).AsEnumerable() : arr).Select(x => elemCnt++ % 2 == 0 ? $"**{x}**" : x.ToString()))).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
var embed = new EmbedBuilder().WithOkColor().WithDescription($"{umsg.Author.Mention} rolled {n1} {(n1 == 1 ? "die" : "dice")} `1 to {n2}` +`{add}` -`{sub}`")
|
||||||
[RequireContext(ContextType.Guild)]
|
.AddField(efb => efb.WithName(Format.Bold("Result"))
|
||||||
public async Task Rolluo(IUserMessage umsg, int num)
|
.WithValue(string.Join(" ", (ordered ? arr.OrderBy(x => x).AsEnumerable() : arr).Select(x => Format.Code(x.ToString())))));
|
||||||
{
|
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
if (channel == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var ordered = false;
|
|
||||||
|
|
||||||
if (num < 1 || num > 30)
|
|
||||||
{
|
|
||||||
await channel.SendMessageAsync("Invalid number specified. You can roll up to 1-30 dice at a time.").ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var rng = new NadekoRandom();
|
|
||||||
|
|
||||||
var dice = new List<Image>(num);
|
|
||||||
var values = new List<int>(num);
|
|
||||||
for (var i = 0; i < num; i++)
|
|
||||||
{
|
|
||||||
var randomNumber = rng.Next(1, 7);
|
|
||||||
var toInsert = dice.Count;
|
|
||||||
if (ordered)
|
|
||||||
{
|
|
||||||
if (randomNumber == 6 || dice.Count == 0)
|
|
||||||
toInsert = 0;
|
|
||||||
else if (randomNumber != 1)
|
|
||||||
for (var j = 0; j < dice.Count; j++)
|
|
||||||
{
|
|
||||||
if (values[j] < randomNumber)
|
|
||||||
{
|
|
||||||
toInsert = j;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
toInsert = dice.Count;
|
|
||||||
}
|
|
||||||
dice.Insert(toInsert, GetDice(randomNumber));
|
|
||||||
values.Insert(toInsert, randomNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
var bitmap = dice.Merge();
|
|
||||||
var ms = new MemoryStream();
|
|
||||||
bitmap.SaveAsPng(ms);
|
|
||||||
ms.Position = 0;
|
|
||||||
await channel.SendFileAsync(ms, "dice.png", $"{umsg.Author.Mention} rolled {values.Count} {(values.Count == 1 ? "die" : "dice")}. Total: **{values.Sum()}** Average: **{(values.Sum() / (1.0f * values.Count)).ToString("N2")}**").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
@ -241,7 +206,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
.Select(int.Parse)
|
.Select(int.Parse)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
if (arr[0] > arr[1])
|
if (arr[0] > arr[1])
|
||||||
throw new ArgumentException("First argument should be bigger than the second one.");
|
throw new ArgumentException("Second argument must be larger than the first one.");
|
||||||
rolled = new NadekoRandom().Next(arr[0], arr[1] + 1);
|
rolled = new NadekoRandom().Next(arr[0], arr[1] + 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -249,11 +214,11 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
rolled = new NadekoRandom().Next(0, int.Parse(range) + 1);
|
rolled = new NadekoRandom().Next(0, int.Parse(range) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync($"{umsg.Author.Mention} rolled **{rolled}**.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{umsg.Author.Mention} rolled **{rolled}**.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($":anger: {ex.Message}").ConfigureAwait(false);
|
await channel.SendErrorAsync($":anger: {ex.Message}").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
{
|
{
|
||||||
if (cards.CardPool.Count == 0 && i != 0)
|
if (cards.CardPool.Count == 0 && i != 0)
|
||||||
{
|
{
|
||||||
try { await channel.SendMessageAsync("No more cards in a deck.").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
try { await channel.SendErrorAsync("No more cards in a deck.").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var currentCard = cards.DrawACard();
|
var currentCard = cards.DrawACard();
|
||||||
@ -53,7 +53,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
MemoryStream bitmapStream = new MemoryStream();
|
MemoryStream bitmapStream = new MemoryStream();
|
||||||
images.Merge().SaveAsPng(bitmapStream);
|
images.Merge().SaveAsPng(bitmapStream);
|
||||||
bitmapStream.Position = 0;
|
bitmapStream.Position = 0;
|
||||||
//todo CARD NAMES?
|
|
||||||
var toSend = $"{msg.Author.Mention}";
|
var toSend = $"{msg.Author.Mention}";
|
||||||
if (cardObjects.Count == 5)
|
if (cardObjects.Count == 5)
|
||||||
toSend += $" drew `{Cards.GetHandValue(cardObjects)}`";
|
toSend += $" drew `{Cards.GetHandValue(cardObjects)}`";
|
||||||
@ -75,7 +75,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
return c;
|
return c;
|
||||||
});
|
});
|
||||||
|
|
||||||
await channel.SendMessageAsync("`Deck reshuffled.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("Deck reshuffled.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,9 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
[Group]
|
[Group]
|
||||||
public class FlipCoinCommands
|
public class FlipCoinCommands
|
||||||
{
|
{
|
||||||
NadekoRandom rng { get; } = new NadekoRandom();
|
private static NadekoRandom rng { get; } = new NadekoRandom();
|
||||||
private const string headsPath = "data/images/coins/heads.png";
|
private const string headsPath = "data/images/coins/heads.png";
|
||||||
private const string tailsPath = "data/images/coins/tails.png";
|
private const string tailsPath = "data/images/coins/tails.png";
|
||||||
public FlipCoinCommands() { }
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
@ -28,14 +27,14 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
if (count == 1)
|
if (count == 1)
|
||||||
{
|
{
|
||||||
if (rng.Next(0, 2) == 1)
|
if (rng.Next(0, 2) == 1)
|
||||||
await channel.SendFileAsync(headsPath, $"{imsg.Author.Mention} rolled " + Format.Code("Heads") + ".").ConfigureAwait(false);
|
await channel.SendFileAsync(headsPath, $"{imsg.Author.Mention} flipped " + Format.Code("Heads") + ".").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendFileAsync(tailsPath, $"{imsg.Author.Mention} rolled " + Format.Code("Tails") + ".").ConfigureAwait(false);
|
await channel.SendFileAsync(tailsPath, $"{imsg.Author.Mention} flipped " + Format.Code("Tails") + ".").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (count > 10 || count < 1)
|
if (count > 10 || count < 1)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("`Invalid number specified. You can flip 1 to 10 coins.`");
|
await channel.SendErrorAsync("`Invalid number specified. You can flip 1 to 10 coins.`");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var imgs = new Image[count];
|
var imgs = new Image[count];
|
||||||
@ -60,24 +59,16 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
|
|
||||||
if (amount < 3)
|
if (amount < 3)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"You can't bet less than 3{Gambling.CurrencySign}.")
|
await channel.SendErrorAsync($"You can't bet less than 3{Gambling.CurrencySign}.")
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// todo update this
|
var removed = await CurrencyHandler.RemoveCurrencyAsync(guildUser, "Betflip Gamble", amount, false).ConfigureAwait(false);
|
||||||
long userFlowers;
|
if (!removed)
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
|
||||||
{
|
{
|
||||||
userFlowers = uow.Currency.GetOrCreate(umsg.Author.Id).Amount;
|
await channel.SendErrorAsync($"{guildUser.Mention} You don't have enough {Gambling.CurrencyPluralName}.").ConfigureAwait(false);
|
||||||
}
|
|
||||||
|
|
||||||
if (userFlowers < amount)
|
|
||||||
{
|
|
||||||
await channel.SendMessageAsync($"{umsg.Author.Mention} You don't have enough {Gambling.CurrencyPluralName}. You only have {userFlowers}{Gambling.CurrencySign}.").ConfigureAwait(false);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await CurrencyHandler.RemoveCurrencyAsync(guildUser, "Betflip Gamble", amount, false).ConfigureAwait(false);
|
|
||||||
//heads = true
|
//heads = true
|
||||||
//tails = false
|
//tails = false
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
public static string CurrencyPluralName { get; set; }
|
public static string CurrencyPluralName { get; set; }
|
||||||
public static string CurrencySign { get; set; }
|
public static string CurrencySign { get; set; }
|
||||||
|
|
||||||
public Gambling(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
|
public Gambling() : base()
|
||||||
{
|
{
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
@ -51,7 +51,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
var members = role.Members().Where(u => u.Status != UserStatus.Offline && u.Status != UserStatus.Unknown);
|
var members = role.Members().Where(u => u.Status != UserStatus.Offline && u.Status != UserStatus.Unknown);
|
||||||
var membersArray = members as IUser[] ?? members.ToArray();
|
var membersArray = members as IUser[] ?? members.ToArray();
|
||||||
var usr = membersArray[new NadekoRandom().Next(0, membersArray.Length)];
|
var usr = membersArray[new NadekoRandom().Next(0, membersArray.Length)];
|
||||||
await channel.SendMessageAsync($"🎟 Raffled user: **{usr.Username}#{usr.Discriminator}** ID: `{usr.Id}`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("🎟 Raffled user", $"**{usr.Username}#{usr.Discriminator}** ID: `{usr.Id}`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -62,7 +62,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
|
|
||||||
user = user ?? umsg.Author;
|
user = user ?? umsg.Author;
|
||||||
|
|
||||||
await channel.SendMessageAsync($"{user.Username} has {GetCurrency(user.Id)} {CurrencySign}").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{user.Username} has {GetCurrency(user.Id)} {CurrencySign}").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -71,7 +71,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
{
|
{
|
||||||
var channel = umsg.Channel;
|
var channel = umsg.Channel;
|
||||||
|
|
||||||
await channel.SendMessageAsync($"`{userId}` has {GetCurrency(userId)} {CurrencySign}").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"`{userId}` has {GetCurrency(userId)} {CurrencySign}").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -84,11 +84,11 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
var success = await CurrencyHandler.RemoveCurrencyAsync((IGuildUser)umsg.Author, $"Gift to {receiver.Username} ({receiver.Id}).", amount, true).ConfigureAwait(false);
|
var success = await CurrencyHandler.RemoveCurrencyAsync((IGuildUser)umsg.Author, $"Gift to {receiver.Username} ({receiver.Id}).", amount, true).ConfigureAwait(false);
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"{umsg.Author.Mention} You don't have enough {Gambling.CurrencyPluralName}.").ConfigureAwait(false);
|
await channel.SendErrorAsync($"{umsg.Author.Mention} You don't have enough {Gambling.CurrencyPluralName}.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await CurrencyHandler.AddCurrencyAsync(receiver, $"Gift from {umsg.Author.Username} ({umsg.Author.Id}).", amount, true).ConfigureAwait(false);
|
await CurrencyHandler.AddCurrencyAsync(receiver, $"Gift from {umsg.Author.Username} ({umsg.Author.Id}).", amount, true).ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync($"{umsg.Author.Mention} successfully sent {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} to {receiver.Mention}!").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{umsg.Author.Mention} successfully sent {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} to {receiver.Mention}!").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -111,7 +111,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
|
|
||||||
await CurrencyHandler.AddCurrencyAsync(usrId, $"Awarded by bot owner. ({umsg.Author.Username}/{umsg.Author.Id})", amount).ConfigureAwait(false);
|
await CurrencyHandler.AddCurrencyAsync(usrId, $"Awarded by bot owner. ({umsg.Author.Username}/{umsg.Author.Id})", amount).ConfigureAwait(false);
|
||||||
|
|
||||||
await channel.SendMessageAsync($"{umsg.Author.Mention} successfully awarded {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} to <@{usrId}>!").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{umsg.Author.Mention} successfully awarded {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} to <@{usrId}>!").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -129,7 +129,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
amount)))
|
amount)))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
await channel.SendMessageAsync($"Awarded `{amount}` {Gambling.CurrencyPluralName} to `{users.Count}` users from `{role.Name}` role.")
|
await channel.SendConfirmAsync($"Awarded `{amount}` {Gambling.CurrencyPluralName} to `{users.Count}` users from `{role.Name}` role.")
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -144,9 +144,9 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if(await CurrencyHandler.RemoveCurrencyAsync(user, $"Taken by bot owner.({umsg.Author.Username}/{umsg.Author.Id})", amount, true).ConfigureAwait(false))
|
if(await CurrencyHandler.RemoveCurrencyAsync(user, $"Taken by bot owner.({umsg.Author.Username}/{umsg.Author.Id})", amount, true).ConfigureAwait(false))
|
||||||
await channel.SendMessageAsync($"{umsg.Author.Mention} successfully took {amount} {(amount == 1? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from {user}!").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{umsg.Author.Mention} successfully took {amount} {(amount == 1? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from {user}!").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync($"{umsg.Author.Mention} was unable to take {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from {user} because the user doesn't have that much {Gambling.CurrencyPluralName}!").ConfigureAwait(false);
|
await channel.SendErrorAsync($"{umsg.Author.Mention} was unable to take {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from {user} because the user doesn't have that much {Gambling.CurrencyPluralName}!").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -160,9 +160,9 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if(await CurrencyHandler.RemoveCurrencyAsync(usrId, $"Taken by bot owner.({umsg.Author.Username}/{umsg.Author.Id})", amount).ConfigureAwait(false))
|
if(await CurrencyHandler.RemoveCurrencyAsync(usrId, $"Taken by bot owner.({umsg.Author.Username}/{umsg.Author.Id})", amount).ConfigureAwait(false))
|
||||||
await channel.SendMessageAsync($"{umsg.Author.Mention} successfully took {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from <@{usrId}>!").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{umsg.Author.Mention} successfully took {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from <@{usrId}>!").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync($"{umsg.Author.Mention} was unable to take {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from `{usrId}` because the user doesn't have that much {Gambling.CurrencyPluralName}!").ConfigureAwait(false);
|
await channel.SendErrorAsync($"{umsg.Author.Mention} was unable to take {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from `{usrId}` because the user doesn't have that much {Gambling.CurrencyPluralName}!").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -184,7 +184,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
|
|
||||||
if (userFlowers < amount)
|
if (userFlowers < amount)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"{guildUser.Mention} You don't have enough {Gambling.CurrencyPluralName}. You only have {userFlowers}{Gambling.CurrencySign}.").ConfigureAwait(false);
|
await channel.SendErrorAsync($"{guildUser.Mention} You don't have enough {Gambling.CurrencyPluralName}. You only have {userFlowers}{Gambling.CurrencySign}.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,7 +212,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
await CurrencyHandler.AddCurrencyAsync(guildUser, "Betroll Gamble", amount * 10, false).ConfigureAwait(false);
|
await CurrencyHandler.AddCurrencyAsync(guildUser, "Betroll Gamble", amount * 10, false).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync(str).ConfigureAwait(false);
|
await channel.SendConfirmAsync(str).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -221,7 +221,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
IEnumerable<Currency> richest;
|
IEnumerable<Currency> richest = new List<Currency>();
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
richest = uow.Currency.GetTopRichest(10);
|
richest = uow.Currency.GetTopRichest(10);
|
||||||
@ -235,7 +235,7 @@ $@"```xl
|
|||||||
┃ Id ┃ $$$ ┃
|
┃ Id ┃ $$$ ┃
|
||||||
"),
|
"),
|
||||||
(cur, cs) => cur.AppendLine($@"┣━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━┫
|
(cur, cs) => cur.AppendLine($@"┣━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━┫
|
||||||
┃{(channel.Guild.GetUser(cs.UserId)?.Username.TrimTo(18, true) ?? cs.UserId.ToString()),-20} ┃ {cs.Amount,6} ┃")
|
┃{(channel.Guild.GetUser(cs.UserId)?.Username?.TrimTo(18, true) ?? cs.UserId.ToString()),-20} ┃ {cs.Amount,6} ┃")
|
||||||
).ToString() + "┗━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━┛```").ConfigureAwait(false);
|
).ToString() + "┗━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━┛```").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
291
src/NadekoBot/Modules/Games/Commands/Acropobia.cs
Normal file
291
src/NadekoBot/Modules/Games/Commands/Acropobia.cs
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Services;
|
||||||
|
using NLog;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Games
|
||||||
|
{
|
||||||
|
public partial class Games
|
||||||
|
{
|
||||||
|
[Group]
|
||||||
|
public class Acropobia
|
||||||
|
{
|
||||||
|
//channelId, game
|
||||||
|
public static ConcurrentDictionary<ulong, AcrophobiaGame> AcrophobiaGames { get; } = new ConcurrentDictionary<ulong, AcrophobiaGame>();
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task Acro(IUserMessage imsg, int time = 60)
|
||||||
|
{
|
||||||
|
var channel = (ITextChannel)imsg.Channel;
|
||||||
|
|
||||||
|
var game = new AcrophobiaGame(channel, time);
|
||||||
|
if (AcrophobiaGames.TryAdd(channel.Id, game))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await game.Run();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
game.EnsureStopped();
|
||||||
|
AcrophobiaGames.TryRemove(channel.Id, out game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await channel.SendErrorAsync("Acrophobia game is already running in this channel.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum AcroPhase
|
||||||
|
{
|
||||||
|
Submitting,
|
||||||
|
Idle, // used to wait for some other actions while transitioning through phases
|
||||||
|
Voting
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AcrophobiaGame
|
||||||
|
{
|
||||||
|
private readonly ITextChannel channel;
|
||||||
|
private readonly int time;
|
||||||
|
private readonly NadekoRandom rng;
|
||||||
|
private readonly ImmutableArray<char> startingLetters;
|
||||||
|
private readonly CancellationTokenSource source;
|
||||||
|
private AcroPhase phase { get; set; } = AcroPhase.Submitting;
|
||||||
|
|
||||||
|
private readonly ConcurrentDictionary<string, IGuildUser> submissions = new ConcurrentDictionary<string, IGuildUser>();
|
||||||
|
public IReadOnlyDictionary<string, IGuildUser> Submissions => submissions;
|
||||||
|
|
||||||
|
private readonly ConcurrentHashSet<ulong> usersWhoVoted = new ConcurrentHashSet<ulong>();
|
||||||
|
|
||||||
|
private int spamCount = 0;
|
||||||
|
|
||||||
|
//text, votes
|
||||||
|
private readonly ConcurrentDictionary<string, int> votes = new ConcurrentDictionary<string, int>();
|
||||||
|
private readonly Logger _log;
|
||||||
|
|
||||||
|
public AcrophobiaGame(ITextChannel channel, int time)
|
||||||
|
{
|
||||||
|
this._log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
this.channel = channel;
|
||||||
|
this.time = time;
|
||||||
|
this.source = new CancellationTokenSource();
|
||||||
|
|
||||||
|
this.rng = new NadekoRandom();
|
||||||
|
var wordCount = rng.Next(3, 6);
|
||||||
|
|
||||||
|
var lettersArr = new char[wordCount];
|
||||||
|
|
||||||
|
for (int i = 0; i < wordCount; i++)
|
||||||
|
{
|
||||||
|
var randChar = (char)rng.Next(65, 91);
|
||||||
|
lettersArr[i] = randChar == 'X' ? (char)rng.Next(65, 88) : randChar;
|
||||||
|
}
|
||||||
|
startingLetters = lettersArr.ToImmutableArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private EmbedBuilder GetEmbed()
|
||||||
|
{
|
||||||
|
var i = 0;
|
||||||
|
return phase == AcroPhase.Submitting
|
||||||
|
|
||||||
|
? new EmbedBuilder().WithOkColor()
|
||||||
|
.WithTitle("Acrophobia")
|
||||||
|
.WithDescription($"Game started. Create a sentence with the following acronym: **{string.Join(".", startingLetters)}.**\n")
|
||||||
|
.WithFooter(efb => efb.WithText("You have " + this.time + " seconds to make a submission."))
|
||||||
|
|
||||||
|
: new EmbedBuilder()
|
||||||
|
.WithOkColor()
|
||||||
|
.WithTitle("Acrophobia - Submissions Closed")
|
||||||
|
.WithDescription($@"Acronym was **{string.Join(".", startingLetters)}.**
|
||||||
|
--
|
||||||
|
{this.submissions.Aggregate("", (agg, cur) => agg + $"`{++i}.` **{cur.Key.ToLowerInvariant().ToTitleCase()}**\n")}
|
||||||
|
--")
|
||||||
|
.WithFooter(efb => efb.WithText("Vote by typing a number of the submission"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Run()
|
||||||
|
{
|
||||||
|
NadekoBot.Client.MessageReceived += PotentialAcro;
|
||||||
|
var embed = GetEmbed();
|
||||||
|
|
||||||
|
//SUBMISSIONS PHASE
|
||||||
|
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Task.Delay(time * 1000, source.Token).ConfigureAwait(false);
|
||||||
|
phase = AcroPhase.Idle;
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//var i = 0;
|
||||||
|
if (submissions.Count == 0)
|
||||||
|
{
|
||||||
|
await channel.SendErrorAsync("Acrophobia", "Game ended with no submissions.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (submissions.Count == 1)
|
||||||
|
{
|
||||||
|
await channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||||
|
.WithDescription($"{submissions.First().Value.Mention} is the winner for being the only user who made a submission!")
|
||||||
|
.WithFooter(efb => efb.WithText(submissions.First().Key.ToLowerInvariant().ToTitleCase()))
|
||||||
|
.Build()).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var submissionClosedEmbed = GetEmbed();
|
||||||
|
|
||||||
|
await channel.EmbedAsync(submissionClosedEmbed.Build()).ConfigureAwait(false);
|
||||||
|
|
||||||
|
//VOTING PHASE
|
||||||
|
this.phase = AcroPhase.Voting;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//30 secondds for voting
|
||||||
|
await Task.Delay(30000, source.Token).ConfigureAwait(false);
|
||||||
|
this.phase = AcroPhase.Idle;
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await End().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void PotentialAcro(IMessage arg)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var msg = arg as IUserMessage;
|
||||||
|
if (msg == null || msg.Author.IsBot || msg.Channel.Id != channel.Id)
|
||||||
|
return;
|
||||||
|
|
||||||
|
++spamCount;
|
||||||
|
|
||||||
|
var guildUser = (IGuildUser)msg.Author;
|
||||||
|
|
||||||
|
var input = msg.Content.ToUpperInvariant().Trim();
|
||||||
|
|
||||||
|
if (phase == AcroPhase.Submitting)
|
||||||
|
{
|
||||||
|
if (spamCount > 10)
|
||||||
|
{
|
||||||
|
spamCount = 0;
|
||||||
|
try { await channel.EmbedAsync(GetEmbed().Build()).ConfigureAwait(false); }
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
//user didn't input something already
|
||||||
|
IGuildUser throwaway;
|
||||||
|
if (submissions.TryGetValue(input, out throwaway))
|
||||||
|
return;
|
||||||
|
var inputWords = input.Split(' '); //get all words
|
||||||
|
|
||||||
|
if (inputWords.Length != startingLetters.Length) // number of words must be the same as the number of the starting letters
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < startingLetters.Length; i++)
|
||||||
|
{
|
||||||
|
var letter = startingLetters[i];
|
||||||
|
|
||||||
|
if (!inputWords[i].StartsWith(letter.ToString())) // all first letters must match
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//try adding it to the list of answers
|
||||||
|
if (!submissions.TryAdd(input, guildUser))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// all good. valid input. answer recorded
|
||||||
|
await channel.SendConfirmAsync("Acrophobia", $"{guildUser.Mention} submitted their sentence. ({submissions.Count} total)");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await msg.DeleteAsync();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await msg.DeleteAsync(); //try twice
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (phase == AcroPhase.Voting)
|
||||||
|
{
|
||||||
|
if (spamCount > 10)
|
||||||
|
{
|
||||||
|
spamCount = 0;
|
||||||
|
try { await channel.EmbedAsync(GetEmbed().Build()).ConfigureAwait(false); }
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
IGuildUser usr;
|
||||||
|
//if (submissions.TryGetValue(input, out usr) && usr.Id != guildUser.Id)
|
||||||
|
//{
|
||||||
|
// if (!usersWhoVoted.Add(guildUser.Id))
|
||||||
|
// return;
|
||||||
|
// votes.AddOrUpdate(input, 1, (key, old) => ++old);
|
||||||
|
// await channel.SendConfirmAsync("Acrophobia", $"{guildUser.Mention} cast their vote!").ConfigureAwait(false);
|
||||||
|
// await msg.DeleteAsync().ConfigureAwait(false);
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
|
||||||
|
int num;
|
||||||
|
if (int.TryParse(input, out num) && num > 0 && num <= submissions.Count)
|
||||||
|
{
|
||||||
|
var kvp = submissions.Skip(num - 1).First();
|
||||||
|
usr = kvp.Value;
|
||||||
|
//can't vote for yourself, can't vote multiple times
|
||||||
|
if (usr.Id == guildUser.Id || !usersWhoVoted.Add(guildUser.Id))
|
||||||
|
return;
|
||||||
|
votes.AddOrUpdate(kvp.Key, 1, (key, old) => ++old);
|
||||||
|
await channel.SendConfirmAsync("Acrophobia", $"{guildUser.Mention} cast their vote!").ConfigureAwait(false);
|
||||||
|
await msg.DeleteAsync().ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_log.Warn(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task End()
|
||||||
|
{
|
||||||
|
if (!votes.Any())
|
||||||
|
{
|
||||||
|
await channel.SendErrorAsync("Acrophobia", "No votes cast. Game ended with no winner.").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var table = votes.OrderByDescending(v => v.Value);
|
||||||
|
var winner = table.First();
|
||||||
|
var embed = new EmbedBuilder().WithOkColor()
|
||||||
|
.WithTitle("Acrophobia")
|
||||||
|
.WithDescription($"Winner is {submissions[winner.Key].Mention} with {winner.Value} points.\n")
|
||||||
|
.WithFooter(efb => efb.WithText(winner.Key.ToLowerInvariant().ToTitleCase()));
|
||||||
|
|
||||||
|
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EnsureStopped()
|
||||||
|
{
|
||||||
|
NadekoBot.Client.MessageReceived -= PotentialAcro;
|
||||||
|
if (!source.IsCancellationRequested)
|
||||||
|
source.Cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using NLog;
|
using NLog;
|
||||||
using Services.CleverBotApi;
|
using Services.CleverBotApi;
|
||||||
@ -34,7 +35,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
{
|
{
|
||||||
var bot = ChatterBotFactory.Create(ChatterBotType.CLEVERBOT);
|
var bot = ChatterBotFactory.Create(ChatterBotType.CLEVERBOT);
|
||||||
CleverbotGuilds = new ConcurrentDictionary<ulong, ChatterBotSession>(
|
CleverbotGuilds = new ConcurrentDictionary<ulong, ChatterBotSession>(
|
||||||
uow.GuildConfigs.GetAll()
|
NadekoBot.AllGuildConfigs
|
||||||
.Where(gc => gc.CleverbotEnabled)
|
.Where(gc => gc.CleverbotEnabled)
|
||||||
.ToDictionary(gc => gc.GuildId, gc => bot.CreateSession()));
|
.ToDictionary(gc => gc.GuildId, gc => bot.CreateSession()));
|
||||||
}
|
}
|
||||||
@ -72,12 +73,11 @@ namespace NadekoBot.Modules.Games
|
|||||||
var response = await cleverbot.Think(message).ConfigureAwait(false);
|
var response = await cleverbot.Think(message).ConfigureAwait(false);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await msg.Channel.SendMessageAsync(response).ConfigureAwait(false);
|
await msg.Channel.SendConfirmAsync(response.SanitizeMentions()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch
|
||||||
{
|
{
|
||||||
_log.Warn(ex, "Eror sending response");
|
await msg.Channel.SendConfirmAsync(response.SanitizeMentions()).ConfigureAwait(false); // try twice :\
|
||||||
await msg.Channel.SendMessageAsync(msg.Author.Mention+" "+response).ConfigureAwait(false); // try twice :\
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -97,7 +97,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
uow.GuildConfigs.SetCleverbotEnabled(channel.Guild.Id, false);
|
uow.GuildConfigs.SetCleverbotEnabled(channel.Guild.Id, false);
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"{imsg.Author.Mention} `Disabled cleverbot on this server.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{imsg.Author.Mention} Disabled cleverbot on this server.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync($"{imsg.Author.Mention} `Enabled cleverbot on this server.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{imsg.Author.Mention} Enabled cleverbot on this server.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
215
src/NadekoBot/Modules/Games/Commands/Hangman/HangmanGame.cs
Normal file
215
src/NadekoBot/Modules/Games/Commands/Hangman/HangmanGame.cs
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
using Discord;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Services;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using NLog;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Games.Commands.Hangman
|
||||||
|
{
|
||||||
|
public class HangmanModel
|
||||||
|
{
|
||||||
|
public List<HangmanObject> All { get; set; }
|
||||||
|
public List<HangmanObject> Animals { get; set; }
|
||||||
|
public List<HangmanObject> Countries { get; set; }
|
||||||
|
public List<HangmanObject> Movies { get; set; }
|
||||||
|
public List<HangmanObject> Things { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class HangmanTermPool
|
||||||
|
{
|
||||||
|
public enum HangmanTermType
|
||||||
|
{
|
||||||
|
All,
|
||||||
|
Animals,
|
||||||
|
Countries,
|
||||||
|
Movies,
|
||||||
|
Things
|
||||||
|
}
|
||||||
|
|
||||||
|
const string termsPath = "data/hangman.json";
|
||||||
|
public static HangmanModel data { get; }
|
||||||
|
static HangmanTermPool()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
data = JsonConvert.DeserializeObject<HangmanModel>(File.ReadAllText(termsPath));
|
||||||
|
data.All = data.Animals.Concat(data.Countries)
|
||||||
|
.Concat(data.Movies)
|
||||||
|
.Concat(data.Things)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HangmanObject GetTerm(HangmanTermType type)
|
||||||
|
{
|
||||||
|
var rng = new NadekoRandom();
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case HangmanTermType.Animals:
|
||||||
|
return data.Animals[rng.Next(0, data.Animals.Count)];
|
||||||
|
case HangmanTermType.Countries:
|
||||||
|
return data.Countries[rng.Next(0, data.Countries.Count)];
|
||||||
|
case HangmanTermType.Movies:
|
||||||
|
return data.Movies[rng.Next(0, data.Movies.Count)];
|
||||||
|
case HangmanTermType.Things:
|
||||||
|
return data.Things[rng.Next(0, data.Things.Count)];
|
||||||
|
default:
|
||||||
|
return data.All[rng.Next(0, data.All.Count)];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class HangmanGame
|
||||||
|
{
|
||||||
|
private readonly Logger _log;
|
||||||
|
|
||||||
|
public IMessageChannel GameChannel { get; }
|
||||||
|
public HashSet<char> Guesses { get; } = new HashSet<char>();
|
||||||
|
public HangmanObject Term { get; private set; }
|
||||||
|
public uint Errors { get; private set; } = 0;
|
||||||
|
public uint MaxErrors { get; } = 6;
|
||||||
|
public uint MessagesSinceLastPost { get; private set; } = 0;
|
||||||
|
public string ScrambledWord => "`" + String.Concat(Term.Word.Select(c =>
|
||||||
|
{
|
||||||
|
if (!(char.IsLetter(c) || char.IsDigit(c)))
|
||||||
|
return $" {c}";
|
||||||
|
|
||||||
|
c = char.ToUpperInvariant(c);
|
||||||
|
|
||||||
|
if (c == ' ')
|
||||||
|
return " ";
|
||||||
|
return Guesses.Contains(c) ? $" {c}" : " _";
|
||||||
|
})) + "`";
|
||||||
|
|
||||||
|
public bool GuessedAll => Guesses.IsSupersetOf(Term.Word.ToUpperInvariant()
|
||||||
|
.Where(c => char.IsLetter(c) || char.IsDigit(c)));
|
||||||
|
|
||||||
|
public HangmanTermPool.HangmanTermType TermType { get; }
|
||||||
|
|
||||||
|
public event Action<HangmanGame> OnEnded;
|
||||||
|
|
||||||
|
public HangmanGame(IMessageChannel channel, HangmanTermPool.HangmanTermType type)
|
||||||
|
{
|
||||||
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
this.GameChannel = channel;
|
||||||
|
this.TermType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
this.Term = HangmanTermPool.GetTerm(TermType);
|
||||||
|
// start listening for answers when game starts
|
||||||
|
NadekoBot.Client.MessageReceived += PotentialGuess;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task End()
|
||||||
|
{
|
||||||
|
NadekoBot.Client.MessageReceived -= PotentialGuess;
|
||||||
|
OnEnded(this);
|
||||||
|
var toSend = "Game ended. You **" + (Errors >= MaxErrors ? "LOSE" : "WIN") + "**!\n" + GetHangman();
|
||||||
|
var embed = new EmbedBuilder().WithTitle("Hangman Game")
|
||||||
|
.WithDescription(toSend)
|
||||||
|
.AddField(efb => efb.WithName("It was").WithValue(Term.Word))
|
||||||
|
.WithImage(eib => eib.WithUrl(Term.ImageUrl))
|
||||||
|
.WithFooter(efb => efb.WithText(string.Join(" ", Guesses)));
|
||||||
|
if (Errors >= MaxErrors)
|
||||||
|
await GameChannel.EmbedAsync(embed.WithErrorColor().Build()).ConfigureAwait(false);
|
||||||
|
else
|
||||||
|
await GameChannel.EmbedAsync(embed.WithOkColor().Build()).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void PotentialGuess(IMessage msg)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!(msg is IUserMessage))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (msg.Channel != GameChannel)
|
||||||
|
return; // message's channel has to be the same as game's
|
||||||
|
if (msg.Content.Length == 1) // message must be 1 char long
|
||||||
|
{
|
||||||
|
if (++MessagesSinceLastPost > 10)
|
||||||
|
{
|
||||||
|
MessagesSinceLastPost = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await GameChannel.SendConfirmAsync("Hangman Game",
|
||||||
|
ScrambledWord + "\n" + GetHangman(),
|
||||||
|
footer: string.Join(" ", Guesses)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(char.IsLetter(msg.Content[0]) || char.IsDigit(msg.Content[0])))// and a letter or a digit
|
||||||
|
return;
|
||||||
|
|
||||||
|
var guess = char.ToUpperInvariant(msg.Content[0]);
|
||||||
|
if (Guesses.Contains(guess))
|
||||||
|
{
|
||||||
|
MessagesSinceLastPost = 0;
|
||||||
|
++Errors;
|
||||||
|
if (Errors < MaxErrors)
|
||||||
|
await GameChannel.SendErrorAsync("Hangman Game", $"{msg.Author.Mention} Letter `{guess}` has already been used.\n" + ScrambledWord + "\n" + GetHangman(),
|
||||||
|
footer: string.Join(" ", Guesses)).ConfigureAwait(false);
|
||||||
|
else
|
||||||
|
await End().ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Guesses.Add(guess);
|
||||||
|
|
||||||
|
if (Term.Word.ToUpperInvariant().Contains(guess))
|
||||||
|
{
|
||||||
|
if (GuessedAll)
|
||||||
|
{
|
||||||
|
try { await GameChannel.SendConfirmAsync("Hangman Game", $"{msg.Author.Mention} guessed a letter `{guess}`!").ConfigureAwait(false); } catch { }
|
||||||
|
|
||||||
|
await End().ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MessagesSinceLastPost = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await GameChannel.SendConfirmAsync("Hangman Game", $"{msg.Author.Mention} guessed a letter `{guess}`!\n" + ScrambledWord + "\n" + GetHangman(),
|
||||||
|
footer: string.Join(" ", Guesses)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MessagesSinceLastPost = 0;
|
||||||
|
++Errors;
|
||||||
|
if (Errors < MaxErrors)
|
||||||
|
await GameChannel.SendErrorAsync("Hangman Game", $"{msg.Author.Mention} Letter `{guess}` does not exist.\n" + ScrambledWord + "\n" + GetHangman(),
|
||||||
|
footer: string.Join(" ", Guesses)).ConfigureAwait(false);
|
||||||
|
else
|
||||||
|
await End().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex) { _log.Warn(ex); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetHangman() => $@"\_\_\_\_\_\_\_\_\_
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
{(Errors > 0 ? "😲" : " ")} |
|
||||||
|
{(Errors > 1 ? "/" : " ")} {(Errors > 2 ? "|" : " ")} {(Errors > 3 ? "\\" : " ")} |
|
||||||
|
{(Errors > 4 ? "/" : " ")} {(Errors > 5 ? "\\" : " ")} |
|
||||||
|
/-\";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Games.Commands.Hangman
|
||||||
|
{
|
||||||
|
public class HangmanObject
|
||||||
|
{
|
||||||
|
public string Word { get; set; }
|
||||||
|
public string ImageUrl { get; set; }
|
||||||
|
}
|
||||||
|
}
|
66
src/NadekoBot/Modules/Games/Commands/HangmanCommands.cs
Normal file
66
src/NadekoBot/Modules/Games/Commands/HangmanCommands.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Modules.Games.Commands.Hangman;
|
||||||
|
using NLog;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Games
|
||||||
|
{
|
||||||
|
public partial class Games
|
||||||
|
{
|
||||||
|
|
||||||
|
[Group]
|
||||||
|
public class HangmanCommands
|
||||||
|
{
|
||||||
|
private static Logger _log { get; }
|
||||||
|
|
||||||
|
//channelId, game
|
||||||
|
public static ConcurrentDictionary<ulong, HangmanGame> HangmanGames { get; } = new ConcurrentDictionary<ulong, HangmanGame>();
|
||||||
|
|
||||||
|
static HangmanCommands()
|
||||||
|
{
|
||||||
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
}
|
||||||
|
|
||||||
|
string typesStr { get; } = "";
|
||||||
|
public HangmanCommands()
|
||||||
|
{
|
||||||
|
typesStr = $"`List of \"{NadekoBot.ModulePrefixes[typeof(Games).Name]}hangman\" term types:`\n" + String.Join(", ", Enum.GetNames(typeof(HangmanTermPool.HangmanTermType)));
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
public async Task Hangmanlist(IUserMessage imsg)
|
||||||
|
{
|
||||||
|
await imsg.Channel.SendConfirmAsync(typesStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
public async Task Hangman(IUserMessage imsg, HangmanTermPool.HangmanTermType type = HangmanTermPool.HangmanTermType.All)
|
||||||
|
{
|
||||||
|
var hm = new HangmanGame(imsg.Channel, type);
|
||||||
|
|
||||||
|
if (!HangmanGames.TryAdd(imsg.Channel.Id, hm))
|
||||||
|
{
|
||||||
|
await imsg.Channel.SendErrorAsync("Hangman game already running on this channel.").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hm.OnEnded += (g) =>
|
||||||
|
{
|
||||||
|
HangmanGame throwaway;
|
||||||
|
HangmanGames.TryRemove(g.GameChannel.Id, out throwaway);
|
||||||
|
};
|
||||||
|
hm.Start();
|
||||||
|
|
||||||
|
await imsg.Channel.SendConfirmAsync("Hangman game started", hm.ScrambledWord + "\n" + hm.GetHangman() + "\n" + hm.ScrambledWord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -21,7 +21,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
text = text.Trim();
|
text = text.Trim();
|
||||||
if (string.IsNullOrWhiteSpace(text))
|
if (string.IsNullOrWhiteSpace(text))
|
||||||
return;
|
return;
|
||||||
await channel.SendMessageAsync(ToLeet(text, level)).ConfigureAwait(false);
|
await channel.SendConfirmAsync("L33t", ToLeet(text, level).SanitizeMentions()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
@ -16,8 +17,6 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.Games
|
namespace NadekoBot.Modules.Games
|
||||||
{
|
{
|
||||||
//todo make currency generation change and cooldown modifyable
|
|
||||||
//only by bot owner through commands
|
|
||||||
public partial class Games
|
public partial class Games
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -30,51 +29,51 @@ namespace NadekoBot.Modules.Games
|
|||||||
[Group]
|
[Group]
|
||||||
public class PlantPickCommands
|
public class PlantPickCommands
|
||||||
{
|
{
|
||||||
private Random rng;
|
private static ConcurrentHashSet<ulong> generationChannels { get; } = new ConcurrentHashSet<ulong>();
|
||||||
|
|
||||||
private ConcurrentHashSet<ulong> generationChannels = new ConcurrentHashSet<ulong>();
|
|
||||||
//channelid/message
|
//channelid/message
|
||||||
private ConcurrentDictionary<ulong, List<IUserMessage>> plantedFlowers = new ConcurrentDictionary<ulong, List<IUserMessage>>();
|
private static ConcurrentDictionary<ulong, List<IUserMessage>> plantedFlowers { get; } = new ConcurrentDictionary<ulong, List<IUserMessage>>();
|
||||||
//channelId/last generation
|
//channelId/last generation
|
||||||
private ConcurrentDictionary<ulong, DateTime> lastGenerations = new ConcurrentDictionary<ulong, DateTime>();
|
private static ConcurrentDictionary<ulong, DateTime> lastGenerations { get; } = new ConcurrentDictionary<ulong, DateTime>();
|
||||||
|
|
||||||
private float chance;
|
private static ConcurrentHashSet<ulong> usersRecentlyPicked { get; } = new ConcurrentHashSet<ulong>();
|
||||||
private int cooldown;
|
|
||||||
private Logger _log { get; }
|
|
||||||
|
|
||||||
public PlantPickCommands()
|
private static float chance { get; }
|
||||||
|
private static int cooldown { get; }
|
||||||
|
private static Logger _log { get; }
|
||||||
|
|
||||||
|
static PlantPickCommands()
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
NadekoBot.Client.MessageReceived += PotentialFlowerGeneration;
|
NadekoBot.Client.MessageReceived += PotentialFlowerGeneration;
|
||||||
rng = new NadekoRandom();
|
|
||||||
|
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var conf = uow.BotConfig.GetOrCreate();
|
var conf = uow.BotConfig.GetOrCreate();
|
||||||
var x =
|
var x =
|
||||||
generationChannels = new ConcurrentHashSet<ulong>(NadekoBot.AllGuildConfigs
|
generationChannels = new ConcurrentHashSet<ulong>(NadekoBot.AllGuildConfigs
|
||||||
.SelectMany(c => c.GenerateCurrencyChannelIds.Select(obj=>obj.ChannelId)));
|
.SelectMany(c => c.GenerateCurrencyChannelIds.Select(obj => obj.ChannelId)));
|
||||||
chance = conf.CurrencyGenerationChance;
|
chance = conf.CurrencyGenerationChance;
|
||||||
cooldown = conf.CurrencyGenerationCooldown;
|
cooldown = conf.CurrencyGenerationCooldown;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task PotentialFlowerGeneration(IMessage imsg)
|
private static async void PotentialFlowerGeneration(IMessage imsg)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var msg = imsg as IUserMessage;
|
var msg = imsg as IUserMessage;
|
||||||
if (msg == null || msg.IsAuthor() || msg.Author.IsBot)
|
if (msg == null || msg.IsAuthor() || msg.Author.IsBot)
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
|
|
||||||
var channel = imsg.Channel as ITextChannel;
|
var channel = imsg.Channel as ITextChannel;
|
||||||
if (channel == null)
|
if (channel == null)
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
|
|
||||||
if (!generationChannels.Contains(channel.Id))
|
if (!generationChannels.Contains(channel.Id))
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
|
|
||||||
var t = Task.Run(async () =>
|
|
||||||
{
|
|
||||||
var lastGeneration = lastGenerations.GetOrAdd(channel.Id, DateTime.MinValue);
|
var lastGeneration = lastGenerations.GetOrAdd(channel.Id, DateTime.MinValue);
|
||||||
|
var rng = new NadekoRandom();
|
||||||
|
|
||||||
if (DateTime.Now - TimeSpan.FromSeconds(cooldown) < lastGeneration) //recently generated in this channel, don't generate again
|
if (DateTime.Now - TimeSpan.FromSeconds(cooldown) < lastGeneration) //recently generated in this channel, don't generate again
|
||||||
return;
|
return;
|
||||||
@ -84,31 +83,30 @@ namespace NadekoBot.Modules.Games
|
|||||||
if (num > 100)
|
if (num > 100)
|
||||||
{
|
{
|
||||||
lastGenerations.AddOrUpdate(channel.Id, DateTime.Now, (id, old) => DateTime.Now);
|
lastGenerations.AddOrUpdate(channel.Id, DateTime.Now, (id, old) => DateTime.Now);
|
||||||
try
|
|
||||||
{
|
|
||||||
var sent = await channel.SendFileAsync(
|
var sent = await channel.SendFileAsync(
|
||||||
GetRandomCurrencyImagePath(),
|
GetRandomCurrencyImagePath(),
|
||||||
$"❗ A random { Gambling.Gambling.CurrencyName } appeared! Pick it up by typing `{NadekoBot.ModulePrefixes[typeof(Games).Name]}pick`")
|
$"❗ A random { Gambling.Gambling.CurrencyName } appeared! Pick it up by typing `{NadekoBot.ModulePrefixes[typeof(Games).Name]}pick`")
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
plantedFlowers.AddOrUpdate(channel.Id, new List<IUserMessage>() { sent }, (id, old) => { old.Add(sent); return old; });
|
plantedFlowers.AddOrUpdate(channel.Id, new List<IUserMessage>() { sent }, (id, old) => { old.Add(sent); return old; });
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task Pick(IUserMessage imsg)
|
public async Task Pick(IUserMessage imsg)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)imsg.Channel;
|
var channel = (ITextChannel)imsg.Channel;
|
||||||
|
|
||||||
if (!channel.Guild.GetCurrentUser().GetPermissions(channel).ManageMessages)
|
if (!channel.Guild.GetCurrentUser().GetPermissions(channel).ManageMessages || !usersRecentlyPicked.Add(imsg.Author.Id))
|
||||||
{
|
|
||||||
await channel.SendMessageAsync("`I need manage channel permissions in order to process this command.`").ConfigureAwait(false);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
List<IUserMessage> msgs;
|
List<IUserMessage> msgs;
|
||||||
|
|
||||||
@ -119,12 +117,14 @@ namespace NadekoBot.Modules.Games
|
|||||||
await Task.WhenAll(msgs.Select(toDelete => toDelete.DeleteAsync())).ConfigureAwait(false);
|
await Task.WhenAll(msgs.Select(toDelete => toDelete.DeleteAsync())).ConfigureAwait(false);
|
||||||
|
|
||||||
await CurrencyHandler.AddCurrencyAsync((IGuildUser)imsg.Author, "Picked flower(s).", msgs.Count, false).ConfigureAwait(false);
|
await CurrencyHandler.AddCurrencyAsync((IGuildUser)imsg.Author, "Picked flower(s).", msgs.Count, false).ConfigureAwait(false);
|
||||||
var msg = await channel.SendMessageAsync($"**{imsg.Author.Username}** picked {msgs.Count}{Gambling.Gambling.CurrencySign}!").ConfigureAwait(false);
|
var msg = await channel.SendConfirmAsync($"**{imsg.Author}** picked {msgs.Count}{Gambling.Gambling.CurrencySign}!").ConfigureAwait(false);
|
||||||
var t = Task.Run(async () =>
|
msg.DeleteAfter(10);
|
||||||
|
}
|
||||||
|
finally
|
||||||
{
|
{
|
||||||
await Task.Delay(10000).ConfigureAwait(false);
|
await Task.Delay(60000);
|
||||||
try { await msg.DeleteAsync().ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
usersRecentlyPicked.TryRemove(imsg.Author.Id);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -136,7 +136,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
var removed = await CurrencyHandler.RemoveCurrencyAsync((IGuildUser)imsg.Author, "Planted a flower.", 1, false).ConfigureAwait(false);
|
var removed = await CurrencyHandler.RemoveCurrencyAsync((IGuildUser)imsg.Author, "Planted a flower.", 1, false).ConfigureAwait(false);
|
||||||
if (!removed)
|
if (!removed)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"You don't have any {Gambling.Gambling.CurrencyPluralName}.").ConfigureAwait(false);
|
await channel.SendErrorAsync($"You don't have any {Gambling.Gambling.CurrencyPluralName}.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
var msgToSend = $"Oh how Nice! **{imsg.Author.Username}** planted {(vowelFirst ? "an" : "a")} {Gambling.Gambling.CurrencyName}. Pick it using {NadekoBot.ModulePrefixes[typeof(Games).Name]}pick";
|
var msgToSend = $"Oh how Nice! **{imsg.Author.Username}** planted {(vowelFirst ? "an" : "a")} {Gambling.Gambling.CurrencyName}. Pick it using {NadekoBot.ModulePrefixes[typeof(Games).Name]}pick";
|
||||||
if (file == null)
|
if (file == null)
|
||||||
{
|
{
|
||||||
msg = await channel.SendMessageAsync(Gambling.Gambling.CurrencySign).ConfigureAwait(false);
|
msg = await channel.SendConfirmAsync(Gambling.Gambling.CurrencySign).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -166,7 +166,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
bool enabled;
|
bool enabled;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var guildConfig = uow.GuildConfigs.For(channel.Id);
|
var guildConfig = uow.GuildConfigs.For(channel.Id, set => set.Include(gc => gc.GenerateCurrencyChannelIds));
|
||||||
|
|
||||||
var toAdd = new GCChannelId() { ChannelId = channel.Id };
|
var toAdd = new GCChannelId() { ChannelId = channel.Id };
|
||||||
if (!guildConfig.GenerateCurrencyChannelIds.Contains(toAdd))
|
if (!guildConfig.GenerateCurrencyChannelIds.Contains(toAdd))
|
||||||
@ -185,16 +185,19 @@ namespace NadekoBot.Modules.Games
|
|||||||
}
|
}
|
||||||
if (enabled)
|
if (enabled)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("`Currency generation enabled on this channel.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("Currency generation enabled on this channel.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"`Currency generation disabled on this channel.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("Currency generation disabled on this channel.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetRandomCurrencyImagePath() =>
|
private static string GetRandomCurrencyImagePath()
|
||||||
Directory.GetFiles("data/currency_images").OrderBy(s => rng.Next()).FirstOrDefault();
|
{
|
||||||
|
var rng = new NadekoRandom();
|
||||||
|
return Directory.GetFiles("data/currency_images").OrderBy(s => rng.Next()).FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
int GetRandomNumber()
|
int GetRandomNumber()
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -44,7 +45,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
await poll.StartPoll().ConfigureAwait(false);
|
await poll.StartPoll().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync("`Poll is already running on this server.`").ConfigureAwait(false);
|
await channel.SendErrorAsync("Poll is already running on this server.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -91,7 +92,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
msgToSend += "\n**Private Message me with the corresponding number of the answer.**";
|
msgToSend += "\n**Private Message me with the corresponding number of the answer.**";
|
||||||
else
|
else
|
||||||
msgToSend += "\n**Send a Message here with the corresponding number of the answer.**";
|
msgToSend += "\n**Send a Message here with the corresponding number of the answer.**";
|
||||||
await originalMessage.Channel.SendMessageAsync(msgToSend).ConfigureAwait(false);
|
await originalMessage.Channel.SendConfirmAsync(msgToSend).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task StopPoll()
|
public async Task StopPoll()
|
||||||
@ -115,7 +116,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
$" has {kvp.Value} votes." +
|
$" has {kvp.Value} votes." +
|
||||||
$"({kvp.Value * 1.0f / totalVotesCast * 100}%)\n");
|
$"({kvp.Value * 1.0f / totalVotesCast * 100}%)\n");
|
||||||
|
|
||||||
await originalMessage.Channel.SendMessageAsync($"📄 **Total votes cast**: {totalVotesCast}\n{closeMessage}").ConfigureAwait(false);
|
await originalMessage.Channel.SendConfirmAsync($"📄 **Total votes cast**: {totalVotesCast}\n{closeMessage}").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -123,24 +124,22 @@ namespace NadekoBot.Modules.Games
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task Vote(IMessage imsg)
|
private async void Vote(IMessage imsg)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
// has to be a user message
|
// has to be a user message
|
||||||
var msg = imsg as IUserMessage;
|
var msg = imsg as IUserMessage;
|
||||||
if (msg == null || msg.Author.IsBot)
|
if (msg == null || msg.Author.IsBot)
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
|
|
||||||
// has to be an integer
|
// has to be an integer
|
||||||
int vote;
|
int vote;
|
||||||
if (!int.TryParse(imsg.Content, out vote))
|
if (!int.TryParse(imsg.Content, out vote))
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
if (vote < 1 || vote > answers.Length)
|
if (vote < 1 || vote > answers.Length)
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
|
|
||||||
var t = Task.Run(async () =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
IMessageChannel ch;
|
IMessageChannel ch;
|
||||||
if (isPublic)
|
if (isPublic)
|
||||||
{
|
{
|
||||||
@ -166,19 +165,16 @@ namespace NadekoBot.Modules.Games
|
|||||||
{
|
{
|
||||||
if (!isPublic)
|
if (!isPublic)
|
||||||
{
|
{
|
||||||
await ch.SendMessageAsync($"Thanks for voting **{msg.Author.Username}**.").ConfigureAwait(false);
|
await ch.SendConfirmAsync($"Thanks for voting **{msg.Author.Username}**.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var toDelete = await ch.SendMessageAsync($"{msg.Author.Mention} cast their vote.").ConfigureAwait(false);
|
var toDelete = await ch.SendConfirmAsync($"{msg.Author.Mention} cast their vote.").ConfigureAwait(false);
|
||||||
await Task.Delay(5000);
|
toDelete.DeleteAfter(5);
|
||||||
await toDelete.DeleteAsync().ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
});
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -21,9 +21,9 @@ namespace NadekoBot.Modules.Games
|
|||||||
public class TypingGame
|
public class TypingGame
|
||||||
{
|
{
|
||||||
public const float WORD_VALUE = 4.5f;
|
public const float WORD_VALUE = 4.5f;
|
||||||
private readonly ITextChannel channel;
|
public ITextChannel Channel { get; }
|
||||||
public string CurrentSentence;
|
public string CurrentSentence { get; private set; }
|
||||||
public bool IsActive;
|
public bool IsActive { get; private set; }
|
||||||
private readonly Stopwatch sw;
|
private readonly Stopwatch sw;
|
||||||
private readonly List<ulong> finishedUserIds;
|
private readonly List<ulong> finishedUserIds;
|
||||||
private Logger _log { get; }
|
private Logger _log { get; }
|
||||||
@ -31,14 +31,12 @@ namespace NadekoBot.Modules.Games
|
|||||||
public TypingGame(ITextChannel channel)
|
public TypingGame(ITextChannel channel)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
this.channel = channel;
|
this.Channel = channel;
|
||||||
IsActive = false;
|
IsActive = false;
|
||||||
sw = new Stopwatch();
|
sw = new Stopwatch();
|
||||||
finishedUserIds = new List<ulong>();
|
finishedUserIds = new List<ulong>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ITextChannel Channel { get; set; }
|
|
||||||
|
|
||||||
public async Task<bool> Stop()
|
public async Task<bool> Stop()
|
||||||
{
|
{
|
||||||
if (!IsActive) return false;
|
if (!IsActive) return false;
|
||||||
@ -47,7 +45,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
IsActive = false;
|
IsActive = false;
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
sw.Reset();
|
sw.Reset();
|
||||||
try { await channel.SendMessageAsync("Typing contest stopped").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
try { await Channel.SendConfirmAsync("Typing contest stopped.").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,10 +57,10 @@ namespace NadekoBot.Modules.Games
|
|||||||
var i = (int)(CurrentSentence.Length / WORD_VALUE * 1.7f);
|
var i = (int)(CurrentSentence.Length / WORD_VALUE * 1.7f);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($@":clock2: Next contest will last for {i} seconds. Type the bolded text as fast as you can.").ConfigureAwait(false);
|
await Channel.SendConfirmAsync($@":clock2: Next contest will last for {i} seconds. Type the bolded text as fast as you can.").ConfigureAwait(false);
|
||||||
|
|
||||||
|
|
||||||
var msg = await channel.SendMessageAsync("Starting new typing contest in **3**...").ConfigureAwait(false);
|
var msg = await Channel.SendMessageAsync("Starting new typing contest in **3**...").ConfigureAwait(false);
|
||||||
await Task.Delay(1000).ConfigureAwait(false);
|
await Task.Delay(1000).ConfigureAwait(false);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -107,18 +105,17 @@ namespace NadekoBot.Modules.Games
|
|||||||
NadekoBot.Client.MessageReceived += AnswerReceived;
|
NadekoBot.Client.MessageReceived += AnswerReceived;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task AnswerReceived(IMessage imsg)
|
private async void AnswerReceived(IMessage imsg)
|
||||||
{
|
|
||||||
if (imsg.Author.IsBot)
|
|
||||||
return Task.CompletedTask;
|
|
||||||
var msg = imsg as IUserMessage;
|
|
||||||
if (msg == null)
|
|
||||||
return Task.CompletedTask;
|
|
||||||
var t = Task.Run(async () =>
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (channel == null || channel.Id != channel.Id) return;
|
if (imsg.Author.IsBot)
|
||||||
|
return;
|
||||||
|
var msg = imsg as IUserMessage;
|
||||||
|
if (msg == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this.Channel == null || this.Channel.Id != this.Channel.Id) return;
|
||||||
|
|
||||||
var guess = msg.Content;
|
var guess = msg.Content;
|
||||||
|
|
||||||
@ -126,17 +123,21 @@ namespace NadekoBot.Modules.Games
|
|||||||
var decision = Judge(distance, guess.Length);
|
var decision = Judge(distance, guess.Length);
|
||||||
if (decision && !finishedUserIds.Contains(msg.Author.Id))
|
if (decision && !finishedUserIds.Contains(msg.Author.Id))
|
||||||
{
|
{
|
||||||
|
var wpm = CurrentSentence.Length / WORD_VALUE / sw.Elapsed.Seconds * 60;
|
||||||
finishedUserIds.Add(msg.Author.Id);
|
finishedUserIds.Add(msg.Author.Id);
|
||||||
await channel.SendMessageAsync($"{msg.Author.Mention} finished in **{sw.Elapsed.Seconds}** seconds with { distance } errors, **{ CurrentSentence.Length / WORD_VALUE / sw.Elapsed.Seconds * 60 }** WPM!").ConfigureAwait(false);
|
await Extensions.Extensions.EmbedAsync(this.Channel, (Discord.API.Embed)new EmbedBuilder().WithColor((uint)NadekoBot.OkColor)
|
||||||
|
.WithTitle((string)$"{msg.Author} finished the race!")
|
||||||
|
.AddField(efb => efb.WithName("Place").WithValue($"#{finishedUserIds.Count}").WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName("WPM").WithValue($"{wpm:F2} *[{sw.Elapsed.Seconds.ToString()}sec]*").WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName((string)"Errors").WithValue((string)distance.ToString()).WithIsInline((bool)true))
|
||||||
|
.Build()).ConfigureAwait(false);
|
||||||
if (finishedUserIds.Count % 4 == 0)
|
if (finishedUserIds.Count % 4 == 0)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($":exclamation: `A lot of people finished, here is the text for those still typing:`\n\n**{Format.Sanitize(CurrentSentence.Replace(" ", " \x200B")).SanitizeMentions()}**").ConfigureAwait(false);
|
await Extensions.Extensions.SendConfirmAsync(this.Channel, (string)$":exclamation: A lot of people finished, here is the text for those still typing:\n\n**{Format.Sanitize((string)CurrentSentence.Replace((string)" ", (string)" \x200B")).SanitizeMentions()}**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch { }
|
catch (Exception ex) { _log.Warn(ex); }
|
||||||
});
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool Judge(int errors, int textLength) => errors <= textLength / 25;
|
private bool Judge(int errors, int textLength) => errors <= textLength / 25;
|
||||||
@ -172,7 +173,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
|
|
||||||
if (game.IsActive)
|
if (game.IsActive)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync(
|
await channel.SendErrorAsync(
|
||||||
$"Contest already running in " +
|
$"Contest already running in " +
|
||||||
$"{game.Channel.Mention} channel.")
|
$"{game.Channel.Mention} channel.")
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
@ -194,7 +195,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
await game.Stop().ConfigureAwait(false);
|
await game.Stop().ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync("No contest to stop on this channel.").ConfigureAwait(false);
|
await channel.SendErrorAsync("No contest to stop on this channel.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -213,7 +214,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
|
|
||||||
File.WriteAllText(typingArticlesPath, JsonConvert.SerializeObject(TypingArticles));
|
File.WriteAllText(typingArticlesPath, JsonConvert.SerializeObject(TypingArticles));
|
||||||
|
|
||||||
await channel.SendMessageAsync("Added new article for typing game.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("Added new article for typing game.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -229,11 +230,11 @@ namespace NadekoBot.Modules.Games
|
|||||||
|
|
||||||
if (!articles.Any())
|
if (!articles.Any())
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"{imsg.Author.Mention} `No articles found on that page.`").ConfigureAwait(false);
|
await channel.SendErrorAsync($"{imsg.Author.Mention} `No articles found on that page.`").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var i = (page - 1) * 15;
|
var i = (page - 1) * 15;
|
||||||
await channel.SendMessageAsync(String.Join("\n", articles.Select(a => $"`#{++i}` - {a.Text.TrimTo(50)}")))
|
await channel.SendConfirmAsync("List of articles for Type Race", String.Join("\n", articles.Select(a => $"`#{++i}` - {a.Text.TrimTo(50)}")))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,7 +254,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
|
|
||||||
File.WriteAllText(typingArticlesPath, JsonConvert.SerializeObject(TypingArticles));
|
File.WriteAllText(typingArticlesPath, JsonConvert.SerializeObject(TypingArticles));
|
||||||
|
|
||||||
await channel.SendMessageAsync($"`Removed typing article:` #{index + 1} - {removed.Text.TrimTo(50)}")
|
await channel.SendConfirmAsync($"`Removed typing article:` #{index + 1} - {removed.Text.TrimTo(50)}")
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ namespace NadekoBot.Modules.Games.Trivia
|
|||||||
|
|
||||||
private int QuestionDurationMiliseconds { get; } = 30000;
|
private int QuestionDurationMiliseconds { get; } = 30000;
|
||||||
private int HintTimeoutMiliseconds { get; } = 6000;
|
private int HintTimeoutMiliseconds { get; } = 6000;
|
||||||
public bool ShowHints { get; set; } = true;
|
public bool ShowHints { get; } = true;
|
||||||
private CancellationTokenSource triviaCancelSource { get; set; }
|
private CancellationTokenSource triviaCancelSource { get; set; }
|
||||||
|
|
||||||
public TriviaQuestion CurrentQuestion { get; private set; }
|
public TriviaQuestion CurrentQuestion { get; private set; }
|
||||||
@ -35,52 +35,71 @@ namespace NadekoBot.Modules.Games.Trivia
|
|||||||
|
|
||||||
public int WinRequirement { get; } = 10;
|
public int WinRequirement { get; } = 10;
|
||||||
|
|
||||||
public TriviaGame(IGuild guild, ITextChannel channel, bool showHints, int winReq = 10)
|
public TriviaGame(IGuild guild, ITextChannel channel, bool showHints, int winReq)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
this._log = LogManager.GetCurrentClassLogger();
|
||||||
ShowHints = showHints;
|
|
||||||
|
this.ShowHints = showHints;
|
||||||
this.guild = guild;
|
this.guild = guild;
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
WinRequirement = winReq;
|
this.WinRequirement = winReq;
|
||||||
Task.Run(async () => { try { await StartGame().ConfigureAwait(false); } catch { } });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task StartGame()
|
public async Task StartGame()
|
||||||
{
|
{
|
||||||
while (!ShouldStopGame)
|
while (!ShouldStopGame)
|
||||||
{
|
{
|
||||||
// reset the cancellation source
|
// reset the cancellation source
|
||||||
triviaCancelSource = new CancellationTokenSource();
|
triviaCancelSource = new CancellationTokenSource();
|
||||||
var token = triviaCancelSource.Token;
|
|
||||||
// load question
|
// load question
|
||||||
CurrentQuestion = TriviaQuestionPool.Instance.GetRandomQuestion(oldQuestions);
|
CurrentQuestion = TriviaQuestionPool.Instance.GetRandomQuestion(oldQuestions);
|
||||||
if (CurrentQuestion == null)
|
if (CurrentQuestion == null)
|
||||||
{
|
{
|
||||||
try { await channel.SendMessageAsync($":exclamation: Failed loading a trivia question").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
await channel.SendErrorAsync("Trivia Game", "Failed loading a question.").ConfigureAwait(false);
|
||||||
await End().ConfigureAwait(false);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
oldQuestions.Add(CurrentQuestion); //add it to exclusion list so it doesn't show up again
|
oldQuestions.Add(CurrentQuestion); //add it to exclusion list so it doesn't show up again
|
||||||
//sendquestion
|
|
||||||
try { await channel.SendMessageAsync($":question: **{CurrentQuestion.Question}**").ConfigureAwait(false); }
|
EmbedBuilder questionEmbed;
|
||||||
|
IUserMessage questionMessage;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
questionEmbed = new EmbedBuilder().WithOkColor()
|
||||||
|
.WithTitle("Trivia Game")
|
||||||
|
.AddField(eab => eab.WithName("Category").WithValue(CurrentQuestion.Category))
|
||||||
|
.AddField(eab => eab.WithName("Question").WithValue(CurrentQuestion.Question));
|
||||||
|
|
||||||
|
questionMessage = await channel.EmbedAsync(questionEmbed.Build()).ConfigureAwait(false);
|
||||||
|
}
|
||||||
catch (HttpException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound || ex.StatusCode == System.Net.HttpStatusCode.Forbidden)
|
catch (HttpException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound || ex.StatusCode == System.Net.HttpStatusCode.Forbidden)
|
||||||
{
|
{
|
||||||
break;
|
return;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_log.Warn(ex);
|
||||||
|
await Task.Delay(2000).ConfigureAwait(false);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
catch (Exception ex) { _log.Warn(ex); }
|
|
||||||
|
|
||||||
//receive messages
|
//receive messages
|
||||||
|
try
|
||||||
|
{
|
||||||
NadekoBot.Client.MessageReceived += PotentialGuess;
|
NadekoBot.Client.MessageReceived += PotentialGuess;
|
||||||
|
|
||||||
//allow people to guess
|
//allow people to guess
|
||||||
GameActive = true;
|
GameActive = true;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//hint
|
//hint
|
||||||
await Task.Delay(HintTimeoutMiliseconds, token).ConfigureAwait(false);
|
await Task.Delay(HintTimeoutMiliseconds, triviaCancelSource.Token).ConfigureAwait(false);
|
||||||
if (ShowHints)
|
if (ShowHints)
|
||||||
try { await channel.SendMessageAsync($":exclamation:**Hint:** {CurrentQuestion.GetHint()}").ConfigureAwait(false); }
|
try
|
||||||
|
{
|
||||||
|
await questionMessage.ModifyAsync(m => m.Embed = questionEmbed.WithFooter(efb => efb.WithText(CurrentQuestion.GetHint())).Build())
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
catch (HttpException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound || ex.StatusCode == System.Net.HttpStatusCode.Forbidden)
|
catch (HttpException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound || ex.StatusCode == System.Net.HttpStatusCode.Forbidden)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@ -88,53 +107,57 @@ namespace NadekoBot.Modules.Games.Trivia
|
|||||||
catch (Exception ex) { _log.Warn(ex); }
|
catch (Exception ex) { _log.Warn(ex); }
|
||||||
|
|
||||||
//timeout
|
//timeout
|
||||||
await Task.Delay(QuestionDurationMiliseconds - HintTimeoutMiliseconds, token).ConfigureAwait(false);
|
await Task.Delay(QuestionDurationMiliseconds - HintTimeoutMiliseconds, triviaCancelSource.Token).ConfigureAwait(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (TaskCanceledException) { } //means someone guessed the answer
|
catch (TaskCanceledException) { } //means someone guessed the answer
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
GameActive = false;
|
GameActive = false;
|
||||||
if (!triviaCancelSource.IsCancellationRequested)
|
|
||||||
try { await channel.SendMessageAsync($":clock2: :question: **Time's up!** The correct answer was **{CurrentQuestion.Answer}**").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
|
||||||
NadekoBot.Client.MessageReceived -= PotentialGuess;
|
NadekoBot.Client.MessageReceived -= PotentialGuess;
|
||||||
// load next question if game is still running
|
}
|
||||||
|
if (!triviaCancelSource.IsCancellationRequested)
|
||||||
|
try { await channel.SendErrorAsync("Trivia Game", $"**Time's up!** The correct answer was **{CurrentQuestion.Answer}**").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||||
await Task.Delay(2000).ConfigureAwait(false);
|
await Task.Delay(2000).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
try { NadekoBot.Client.MessageReceived -= PotentialGuess; } catch { }
|
|
||||||
GameActive = false;
|
|
||||||
await End().ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task End()
|
public async Task EnsureStopped()
|
||||||
{
|
{
|
||||||
ShouldStopGame = true;
|
ShouldStopGame = true;
|
||||||
TriviaGame throwaway;
|
|
||||||
Games.TriviaCommands.RunningTrivias.TryRemove(channel.Guild.Id, out throwaway);
|
await channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||||
try { await channel.SendMessageAsync("**Trivia game ended**\n" + GetLeaderboard()).ConfigureAwait(false); } catch { }
|
.WithAuthor(eab => eab.WithName("Trivia Game Ended"))
|
||||||
|
.WithTitle("Final Results")
|
||||||
|
.WithDescription(GetLeaderboard())
|
||||||
|
.Build()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task StopGame()
|
public async Task StopGame()
|
||||||
{
|
{
|
||||||
if (!ShouldStopGame)
|
var old = ShouldStopGame;
|
||||||
try { await channel.SendMessageAsync(":exclamation: Trivia will stop after this question.").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
|
||||||
ShouldStopGame = true;
|
ShouldStopGame = true;
|
||||||
|
if (!old)
|
||||||
|
try { await channel.SendConfirmAsync("Trivia Game", "Stopping after this question.").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task PotentialGuess(IMessage imsg)
|
private async void PotentialGuess(IMessage imsg)
|
||||||
{
|
|
||||||
if (imsg.Author.IsBot)
|
|
||||||
return Task.CompletedTask;
|
|
||||||
var umsg = imsg as IUserMessage;
|
|
||||||
if (umsg == null)
|
|
||||||
return Task.CompletedTask;
|
|
||||||
var t = Task.Run(async () =>
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!(umsg.Channel is IGuildChannel && umsg.Channel is ITextChannel)) return;
|
if (imsg.Author.IsBot)
|
||||||
if ((umsg.Channel as ITextChannel).Guild != guild) return;
|
return;
|
||||||
if (umsg.Author.Id == NadekoBot.Client.GetCurrentUser().Id) return;
|
|
||||||
|
|
||||||
var guildUser = umsg.Author as IGuildUser;
|
var umsg = imsg as IUserMessage;
|
||||||
|
if (umsg == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var textChannel = umsg.Channel as ITextChannel;
|
||||||
|
if (textChannel == null || textChannel.Guild != guild)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var guildUser = (IGuildUser)umsg.Author;
|
||||||
|
|
||||||
var guess = false;
|
var guess = false;
|
||||||
await _guessLock.WaitAsync().ConfigureAwait(false);
|
await _guessLock.WaitAsync().ConfigureAwait(false);
|
||||||
@ -149,23 +172,26 @@ namespace NadekoBot.Modules.Games.Trivia
|
|||||||
finally { _guessLock.Release(); }
|
finally { _guessLock.Release(); }
|
||||||
if (!guess) return;
|
if (!guess) return;
|
||||||
triviaCancelSource.Cancel();
|
triviaCancelSource.Cancel();
|
||||||
try { await channel.SendMessageAsync($"☑️ {guildUser.Mention} guessed it! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
|
||||||
if (Users[guildUser] != WinRequirement) return;
|
|
||||||
|
if (Users[guildUser] == WinRequirement)
|
||||||
|
{
|
||||||
ShouldStopGame = true;
|
ShouldStopGame = true;
|
||||||
await channel.SendMessageAsync($":exclamation: We have a winner! It's {guildUser.Mention}.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("Trivia Game", $"{guildUser.Mention} guessed it and WON the game! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await channel.SendConfirmAsync("Trivia Game", $"{guildUser.Mention} guessed it! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception ex) { _log.Warn(ex); }
|
catch (Exception ex) { _log.Warn(ex); }
|
||||||
});
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetLeaderboard()
|
public string GetLeaderboard()
|
||||||
{
|
{
|
||||||
if (Users.Count == 0)
|
if (Users.Count == 0)
|
||||||
return "";
|
return "No results.";
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
sb.Append("**Leaderboard:**\n-----------\n");
|
|
||||||
|
|
||||||
foreach (var kvp in Users.OrderByDescending(kvp => kvp.Value))
|
foreach (var kvp in Users.OrderByDescending(kvp => kvp.Value))
|
||||||
{
|
{
|
||||||
|
@ -18,9 +18,9 @@ namespace NadekoBot.Modules.Games.Trivia
|
|||||||
};
|
};
|
||||||
public static int maxStringLength = 22;
|
public static int maxStringLength = 22;
|
||||||
|
|
||||||
public string Category;
|
public string Category { get; set; }
|
||||||
public string Question;
|
public string Question { get; set; }
|
||||||
public string Answer;
|
public string Answer { get; set; }
|
||||||
|
|
||||||
public TriviaQuestion(string q, string a, string c)
|
public TriviaQuestion(string q, string a, string c)
|
||||||
{
|
{
|
||||||
@ -79,12 +79,9 @@ namespace NadekoBot.Modules.Games.Trivia
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString() =>
|
|
||||||
"Question: **" + this.Question + "?**";
|
|
||||||
|
|
||||||
private static string Scramble(string word)
|
private static string Scramble(string word)
|
||||||
{
|
{
|
||||||
var letters = word.ToArray();
|
var letters = word.ToCharArray();
|
||||||
var count = 0;
|
var count = 0;
|
||||||
for (var i = 0; i < letters.Length; i++)
|
for (var i = 0; i < letters.Length; i++)
|
||||||
{
|
{
|
||||||
@ -101,7 +98,7 @@ namespace NadekoBot.Modules.Games.Trivia
|
|||||||
if (letters[i] != ' ')
|
if (letters[i] != ' ')
|
||||||
letters[i] = '_';
|
letters[i] = '_';
|
||||||
}
|
}
|
||||||
return "`" + string.Join(" ", letters) + "`";
|
return string.Join(" \x200B", new string(letters).Replace(" ", " \x200B").AsEnumerable());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
@ -11,36 +12,31 @@ namespace NadekoBot.Modules.Games.Trivia
|
|||||||
{
|
{
|
||||||
public class TriviaQuestionPool
|
public class TriviaQuestionPool
|
||||||
{
|
{
|
||||||
public static TriviaQuestionPool Instance { get; } = new TriviaQuestionPool();
|
private static TriviaQuestionPool _instance;
|
||||||
public ConcurrentHashSet<TriviaQuestion> pool = new ConcurrentHashSet<TriviaQuestion>();
|
public static TriviaQuestionPool Instance { get; } = _instance ?? (_instance = new TriviaQuestionPool());
|
||||||
|
|
||||||
|
private const string questionsFile = "data/trivia_questions.json";
|
||||||
|
|
||||||
private Random rng { get; } = new NadekoRandom();
|
private Random rng { get; } = new NadekoRandom();
|
||||||
|
|
||||||
|
private TriviaQuestion[] pool { get; }
|
||||||
|
|
||||||
static TriviaQuestionPool() { }
|
static TriviaQuestionPool() { }
|
||||||
|
|
||||||
private TriviaQuestionPool()
|
private TriviaQuestionPool()
|
||||||
{
|
{
|
||||||
Reload();
|
pool = JsonConvert.DeserializeObject<TriviaQuestion[]>(File.ReadAllText(questionsFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
public TriviaQuestion GetRandomQuestion(IEnumerable<TriviaQuestion> exclude)
|
public TriviaQuestion GetRandomQuestion(HashSet<TriviaQuestion> exclude)
|
||||||
{
|
{
|
||||||
var list = pool.Except(exclude).ToList();
|
if (pool.Length == 0)
|
||||||
var rand = rng.Next(0, list.Count);
|
return null;
|
||||||
return list[rand];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reload()
|
TriviaQuestion randomQuestion;
|
||||||
{
|
while (exclude.Contains(randomQuestion = pool[rng.Next(0, pool.Length)])) ;
|
||||||
var arr = JArray.Parse(File.ReadAllText("data/questions.json"));
|
|
||||||
|
|
||||||
foreach (var item in arr)
|
return randomQuestion;
|
||||||
{
|
|
||||||
var tq = new TriviaQuestion(item["Question"].ToString().SanitizeMentions(), item["Answer"].ToString().SanitizeMentions(), item["Category"]?.ToString());
|
|
||||||
pool.Add(tq);
|
|
||||||
}
|
|
||||||
var r = new NadekoRandom();
|
|
||||||
pool = new ConcurrentHashSet<TriviaQuestion>(pool.OrderBy(x => r.Next()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Modules.Games.Trivia;
|
using NadekoBot.Modules.Games.Trivia;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
@ -19,29 +20,33 @@ namespace NadekoBot.Modules.Games
|
|||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task Trivia(IUserMessage umsg, params string[] args)
|
public Task Trivia(IUserMessage umsg, [Remainder] string additionalArgs = "")
|
||||||
|
=> Trivia(umsg, 10, additionalArgs);
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task Trivia(IUserMessage umsg, int winReq = 10, [Remainder] string additionalArgs = "")
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
TriviaGame trivia;
|
var showHints = !additionalArgs.Contains("nohint");
|
||||||
if (!RunningTrivias.TryGetValue(channel.Guild.Id, out trivia))
|
|
||||||
|
TriviaGame trivia = new TriviaGame(channel.Guild, channel, showHints, winReq);
|
||||||
|
if (RunningTrivias.TryAdd(channel.Guild.Id, trivia))
|
||||||
{
|
{
|
||||||
var showHints = !args.Contains("nohint");
|
try
|
||||||
var number = args.Select(s =>
|
|
||||||
{
|
{
|
||||||
int num;
|
await trivia.StartGame().ConfigureAwait(false);
|
||||||
return new Tuple<bool, int>(int.TryParse(s, out num), num);
|
|
||||||
}).Where(t => t.Item1).Select(t => t.Item2).FirstOrDefault();
|
|
||||||
if (number < 0)
|
|
||||||
return;
|
|
||||||
var triviaGame = new TriviaGame(channel.Guild, (ITextChannel)umsg.Channel, showHints, number == 0 ? 10 : number);
|
|
||||||
if (RunningTrivias.TryAdd(channel.Guild.Id, triviaGame))
|
|
||||||
await channel.SendMessageAsync($"**Trivia game started! {triviaGame.WinRequirement} points needed to win.**").ConfigureAwait(false);
|
|
||||||
else
|
|
||||||
await triviaGame.StopGame().ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
else
|
finally
|
||||||
await channel.SendMessageAsync("Trivia game is already running on this server.\n" + trivia.CurrentQuestion).ConfigureAwait(false);
|
{
|
||||||
|
RunningTrivias.TryRemove(channel.Guild.Id, out trivia);
|
||||||
|
await trivia.EnsureStopped().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await channel.SendErrorAsync("Trivia game is already running on this server.\n" + trivia.CurrentQuestion).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -52,9 +57,12 @@ namespace NadekoBot.Modules.Games
|
|||||||
|
|
||||||
TriviaGame trivia;
|
TriviaGame trivia;
|
||||||
if (RunningTrivias.TryGetValue(channel.Guild.Id, out trivia))
|
if (RunningTrivias.TryGetValue(channel.Guild.Id, out trivia))
|
||||||
await channel.SendMessageAsync(trivia.GetLeaderboard()).ConfigureAwait(false);
|
{
|
||||||
else
|
await channel.SendConfirmAsync("Leaderboard", trivia.GetLeaderboard()).ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync("No trivia is running on this server.").ConfigureAwait(false);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await channel.SendErrorAsync("No trivia is running on this server.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -64,12 +72,13 @@ namespace NadekoBot.Modules.Games
|
|||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
TriviaGame trivia;
|
TriviaGame trivia;
|
||||||
if (RunningTrivias.TryRemove(channel.Guild.Id, out trivia))
|
if (RunningTrivias.TryGetValue(channel.Guild.Id, out trivia))
|
||||||
{
|
{
|
||||||
await trivia.StopGame().ConfigureAwait(false);
|
await trivia.StopGame().ConfigureAwait(false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
await channel.SendMessageAsync("No trivia is running on this server.").ConfigureAwait(false);
|
await channel.SendErrorAsync("No trivia is running on this server.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public Games(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
|
public Games() : base()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
if (listArr.Count() < 2)
|
if (listArr.Count() < 2)
|
||||||
return;
|
return;
|
||||||
var rng = new NadekoRandom();
|
var rng = new NadekoRandom();
|
||||||
await channel.SendMessageAsync(listArr[rng.Next(0, listArr.Length)]).ConfigureAwait(false);
|
await channel.SendConfirmAsync("🤔", listArr[rng.Next(0, listArr.Length)]).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -48,8 +48,11 @@ namespace NadekoBot.Modules.Games
|
|||||||
if (string.IsNullOrWhiteSpace(question))
|
if (string.IsNullOrWhiteSpace(question))
|
||||||
return;
|
return;
|
||||||
var rng = new NadekoRandom();
|
var rng = new NadekoRandom();
|
||||||
await channel.SendMessageAsync($@"❓ `Question` __**{question}**__
|
|
||||||
🎱 `8Ball Answers` __**{_8BallResponses.Shuffle().FirstOrDefault()}**__").ConfigureAwait(false);
|
await channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||||
|
.AddField(efb => efb.WithName("❓ Question").WithValue(question).WithIsInline(false))
|
||||||
|
.AddField(efb => efb.WithName("🎱 8Ball").WithValue(_8BallResponses.Shuffle().FirstOrDefault()).WithIsInline(false))
|
||||||
|
.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -99,7 +102,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
else
|
else
|
||||||
msg = $"{umsg.Author.Mention} won! {GetRPSPick(pick)} beats {GetRPSPick(nadekoPick)}";
|
msg = $"{umsg.Author.Mention} won! {GetRPSPick(pick)} beats {GetRPSPick(nadekoPick)}";
|
||||||
|
|
||||||
await channel.SendMessageAsync(msg).ConfigureAwait(false);
|
await channel.SendConfirmAsync(msg).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -108,7 +111,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
await channel.SendMessageAsync(
|
await channel.SendConfirmAsync(
|
||||||
$@"I'd just like to interject for moment. What you're refering to as {loonix}, is in fact, {guhnoo}/{loonix}, or as I've recently taken to calling it, {guhnoo} plus {loonix}. {loonix} is not an operating system unto itself, but rather another free component of a fully functioning {guhnoo} system made useful by the {guhnoo} corelibs, shell utilities and vital system components comprising a full OS as defined by POSIX.
|
$@"I'd just like to interject for moment. What you're refering to as {loonix}, is in fact, {guhnoo}/{loonix}, or as I've recently taken to calling it, {guhnoo} plus {loonix}. {loonix} is not an operating system unto itself, but rather another free component of a fully functioning {guhnoo} system made useful by the {guhnoo} corelibs, shell utilities and vital system components comprising a full OS as defined by POSIX.
|
||||||
|
|
||||||
Many computer users run a modified version of the {guhnoo} system every day, without realizing it. Through a peculiar turn of events, the version of {guhnoo} which is widely used today is often called {loonix}, and many of its users are not aware that it is basically the {guhnoo} system, developed by the {guhnoo} Project.
|
Many computer users run a modified version of the {guhnoo} system every day, without realizing it. Through a peculiar turn of events, the version of {guhnoo} which is widely used today is often called {loonix}, and many of its users are not aware that it is basically the {guhnoo} system, developed by the {guhnoo} Project.
|
||||||
|
@ -30,7 +30,7 @@ namespace NadekoBot.Modules.Help
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Help(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
|
public Help() : base()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,8 +38,10 @@ namespace NadekoBot.Modules.Help
|
|||||||
public async Task Modules(IUserMessage umsg)
|
public async Task Modules(IUserMessage umsg)
|
||||||
{
|
{
|
||||||
|
|
||||||
await umsg.Channel.SendMessageAsync("📜 **List of modules:** ```css\n• " + string.Join("\n• ", _commands.Modules.Select(m => m.Name)) + $"\n``` ℹ️ **Type** `-commands module_name` **to get a list of commands in that module.** ***e.g.*** `-commands games`")
|
var embed = new EmbedBuilder().WithOkColor().WithFooter(efb => efb.WithText($" ℹ️ Type `-cmds ModuleName` to get a list of commands in that module. eg `-cmds games`"))
|
||||||
.ConfigureAwait(false);
|
.WithTitle("📜 List Of Modules").WithDescription("\n• " + string.Join("\n• ", NadekoBot.CommandService.Modules.Select(m => m.Name).OrderBy(s=>s)))
|
||||||
|
.Build();
|
||||||
|
await umsg.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -50,7 +52,7 @@ namespace NadekoBot.Modules.Help
|
|||||||
module = module?.Trim().ToUpperInvariant();
|
module = module?.Trim().ToUpperInvariant();
|
||||||
if (string.IsNullOrWhiteSpace(module))
|
if (string.IsNullOrWhiteSpace(module))
|
||||||
return;
|
return;
|
||||||
var cmds = _commands.Commands.Where(c => c.Module.Name.ToUpperInvariant().StartsWith(module))
|
var cmds = NadekoBot.CommandService.Commands.Where(c => c.Module.Name.ToUpperInvariant().StartsWith(module))
|
||||||
.OrderBy(c => c.Text)
|
.OrderBy(c => c.Text)
|
||||||
.Distinct(new CommandTextEqualityComparer())
|
.Distinct(new CommandTextEqualityComparer())
|
||||||
.AsEnumerable();
|
.AsEnumerable();
|
||||||
@ -58,7 +60,7 @@ namespace NadekoBot.Modules.Help
|
|||||||
var cmdsArray = cmds as Command[] ?? cmds.ToArray();
|
var cmdsArray = cmds as Command[] ?? cmds.ToArray();
|
||||||
if (!cmdsArray.Any())
|
if (!cmdsArray.Any())
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("🚫 **That module does not exist.**").ConfigureAwait(false);
|
await channel.SendErrorAsync("That module does not exist.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (module != "customreactions" && module != "conversations")
|
if (module != "customreactions" && module != "conversations")
|
||||||
@ -69,7 +71,7 @@ namespace NadekoBot.Modules.Help
|
|||||||
{
|
{
|
||||||
await channel.SendMessageAsync("📃 **List Of Commands:**\n• " + string.Join("\n• ", cmdsArray.Select(c => $"{c.Text}")));
|
await channel.SendMessageAsync("📃 **List Of Commands:**\n• " + string.Join("\n• ", cmdsArray.Select(c => $"{c.Text}")));
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"ℹ️ **Type** `\"{NadekoBot.ModulePrefixes[typeof(Help).Name]}h CommandName\"` **to see the help for that specified command.** ***e.g.*** `-h >8ball`").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"ℹ️ **Type** `\"{NadekoBot.ModulePrefixes[typeof(Help).Name]}h CommandName\"` **to see the help for that specified command.** ***e.g.*** `-h >8ball`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -84,20 +86,22 @@ namespace NadekoBot.Modules.Help
|
|||||||
await ch.SendMessageAsync(HelpString).ConfigureAwait(false);
|
await ch.SendMessageAsync(HelpString).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var com = _commands.Commands.FirstOrDefault(c => c.Text.ToLowerInvariant() == comToFind || c.Aliases.Select(a=>a.ToLowerInvariant()).Contains(comToFind));
|
var com = NadekoBot.CommandService.Commands.FirstOrDefault(c => c.Text.ToLowerInvariant() == comToFind || c.Aliases.Select(a=>a.ToLowerInvariant()).Contains(comToFind));
|
||||||
|
|
||||||
if (com == null)
|
if (com == null)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("🔍 **I can't find that command.**");
|
await channel.SendErrorAsync("I can't find that command. Please check the **command** and **command prefix** before trying again.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var str = $"**__Help for:__ `{com.Text}`**";
|
var str = $"**`{com.Text}`**";
|
||||||
var alias = com.Aliases.Skip(1).FirstOrDefault();
|
var alias = com.Aliases.Skip(1).FirstOrDefault();
|
||||||
if (alias != null)
|
if (alias != null)
|
||||||
str += $" / `{alias}`";
|
str += $" **/ `{alias}`**";
|
||||||
if (com != null)
|
var embed = new EmbedBuilder()
|
||||||
await channel.SendMessageAsync(str + $@"{Environment.NewLine}**Desc:** {string.Format(com.Summary, com.Module.Prefix)} {GetCommandRequirements(com)}
|
.AddField(fb => fb.WithIndex(1).WithName(str).WithValue($"{ string.Format(com.Summary, com.Module.Prefix)} { GetCommandRequirements(com)}").WithIsInline(true))
|
||||||
**Usage:** {string.Format(com.Remarks, com.Module.Prefix)}").ConfigureAwait(false);
|
.AddField(fb => fb.WithIndex(2).WithName("**Usage**").WithValue($"{string.Format(com.Remarks, com.Module.Prefix)}").WithIsInline(false))
|
||||||
|
.WithOkColor();
|
||||||
|
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetCommandRequirements(Command cmd)
|
private string GetCommandRequirements(Command cmd)
|
||||||
@ -126,7 +130,7 @@ namespace NadekoBot.Modules.Help
|
|||||||
helpstr.AppendLine(string.Join("\n", NadekoBot.CommandService.Modules.Where(m => m.Name.ToLowerInvariant() != "help").OrderBy(m => m.Name).Prepend(NadekoBot.CommandService.Modules.FirstOrDefault(m=>m.Name.ToLowerInvariant()=="help")).Select(m => $"- [{m.Name}](#{m.Name.ToLowerInvariant()})")));
|
helpstr.AppendLine(string.Join("\n", NadekoBot.CommandService.Modules.Where(m => m.Name.ToLowerInvariant() != "help").OrderBy(m => m.Name).Prepend(NadekoBot.CommandService.Modules.FirstOrDefault(m=>m.Name.ToLowerInvariant()=="help")).Select(m => $"- [{m.Name}](#{m.Name.ToLowerInvariant()})")));
|
||||||
helpstr.AppendLine();
|
helpstr.AppendLine();
|
||||||
string lastModule = null;
|
string lastModule = null;
|
||||||
foreach (var com in _commands.Commands.OrderBy(com=>com.Module.Name).GroupBy(c=>c.Text).Select(g=>g.First()))
|
foreach (var com in NadekoBot.CommandService.Commands.OrderBy(com=>com.Module.Name).GroupBy(c=>c.Text).Select(g=>g.First()))
|
||||||
{
|
{
|
||||||
if (com.Module.Name != lastModule)
|
if (com.Module.Name != lastModule)
|
||||||
{
|
{
|
||||||
@ -154,7 +158,7 @@ namespace NadekoBot.Modules.Help
|
|||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
await channel.SendMessageAsync(
|
await channel.SendConfirmAsync(
|
||||||
@"**LIST OF COMMANDS**: <http://nadekobot.readthedocs.io/en/latest/Commands%20List/>
|
@"**LIST OF COMMANDS**: <http://nadekobot.readthedocs.io/en/latest/Commands%20List/>
|
||||||
**Hosting Guides and docs can be found here**: <http://nadekobot.readthedocs.io/en/latest/>").ConfigureAwait(false);
|
**Hosting Guides and docs can be found here**: <http://nadekobot.readthedocs.io/en/latest/>").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -165,7 +169,7 @@ namespace NadekoBot.Modules.Help
|
|||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
await channel.SendMessageAsync(
|
await channel.SendConfirmAsync(
|
||||||
$@"You can support the NadekoBot project on patreon. <https://patreon.com/nadekobot> or
|
$@"You can support the NadekoBot project on patreon. <https://patreon.com/nadekobot> or
|
||||||
You can send donations to `nadekodiscordbot@gmail.com`
|
You can send donations to `nadekodiscordbot@gmail.com`
|
||||||
Don't forget to leave your discord name or id in the message.
|
Don't forget to leave your discord name or id in the message.
|
||||||
|
@ -30,6 +30,26 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
{
|
{
|
||||||
private IAudioClient audioClient { get; set; }
|
private IAudioClient audioClient { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Player will prioritize different queuer name
|
||||||
|
/// over the song position in the playlist
|
||||||
|
/// </summary>
|
||||||
|
public bool FairPlay { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Song will stop playing after this amount of time.
|
||||||
|
/// To prevent people queueing radio or looped songs
|
||||||
|
/// while other people want to listen to other songs too.
|
||||||
|
/// </summary>
|
||||||
|
public uint MaxPlaytimeSeconds { get; set; } = 0;
|
||||||
|
|
||||||
|
public TimeSpan TotalPlaytime => new TimeSpan(playlist.Sum(s => s.TotalTime.Ticks));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Users who recently got their music wish
|
||||||
|
/// </summary>
|
||||||
|
private ConcurrentHashSet<string> recentlyPlayedUsers { get; } = new ConcurrentHashSet<string>();
|
||||||
|
|
||||||
private readonly List<Song> playlist = new List<Song>();
|
private readonly List<Song> playlist = new List<Song>();
|
||||||
public IReadOnlyCollection<Song> Playlist => playlist;
|
public IReadOnlyCollection<Song> Playlist => playlist;
|
||||||
|
|
||||||
@ -41,8 +61,9 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
|
|
||||||
public float Volume { get; private set; }
|
public float Volume { get; private set; }
|
||||||
|
|
||||||
public event EventHandler<Song> OnCompleted = delegate { };
|
public event Action<MusicPlayer, Song> OnCompleted = delegate { };
|
||||||
public event EventHandler<Song> OnStarted = delegate { };
|
public event Action<MusicPlayer, Song> OnStarted = delegate { };
|
||||||
|
public event Action<bool> OnPauseChanged = delegate { };
|
||||||
|
|
||||||
public IVoiceChannel PlaybackVoiceChannel { get; private set; }
|
public IVoiceChannel PlaybackVoiceChannel { get; private set; }
|
||||||
|
|
||||||
@ -52,7 +73,9 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
public bool Autoplay { get; set; } = false;
|
public bool Autoplay { get; set; } = false;
|
||||||
public uint MaxQueueSize { get; set; } = 0;
|
public uint MaxQueueSize { get; set; } = 0;
|
||||||
|
|
||||||
private ConcurrentQueue<Action> actionQueue { get; set; } = new ConcurrentQueue<Action>();
|
private ConcurrentQueue<Action> actionQueue { get; } = new ConcurrentQueue<Action>();
|
||||||
|
|
||||||
|
public string PrettyVolume => $"🔉 {(int)(Volume * 100)}%";
|
||||||
|
|
||||||
public MusicPlayer(IVoiceChannel startingVoiceChannel, float? defaultVolume)
|
public MusicPlayer(IVoiceChannel startingVoiceChannel, float? defaultVolume)
|
||||||
{
|
{
|
||||||
@ -106,11 +129,13 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
}
|
}
|
||||||
|
|
||||||
CurrentSong = GetNextSong();
|
CurrentSong = GetNextSong();
|
||||||
RemoveSongAt(0);
|
|
||||||
|
|
||||||
if (CurrentSong == null)
|
if (CurrentSong == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
var index = playlist.IndexOf(CurrentSong);
|
||||||
|
if (index != -1)
|
||||||
|
RemoveSongAt(index);
|
||||||
|
|
||||||
OnStarted(this, CurrentSong);
|
OnStarted(this, CurrentSong);
|
||||||
await CurrentSong.Play(audioClient, cancelToken);
|
await CurrentSong.Play(audioClient, cancelToken);
|
||||||
@ -129,6 +154,7 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
{
|
{
|
||||||
Console.WriteLine("Music thread almost crashed.");
|
Console.WriteLine("Music thread almost crashed.");
|
||||||
Console.WriteLine(ex);
|
Console.WriteLine(ex);
|
||||||
|
await Task.Delay(3000).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -168,7 +194,7 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TogglePause() => Paused = !Paused;
|
public void TogglePause() => OnPauseChanged(Paused = !Paused);
|
||||||
|
|
||||||
public int SetVolume(int volume)
|
public int SetVolume(int volume)
|
||||||
{
|
{
|
||||||
@ -181,8 +207,26 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
return volume;
|
return volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Song GetNextSong() =>
|
private Song GetNextSong()
|
||||||
playlist.FirstOrDefault();
|
{
|
||||||
|
if (!FairPlay)
|
||||||
|
{
|
||||||
|
return playlist.FirstOrDefault();
|
||||||
|
}
|
||||||
|
var song = playlist.FirstOrDefault(c => !recentlyPlayedUsers.Contains(c.QueuerName))
|
||||||
|
?? playlist.FirstOrDefault();
|
||||||
|
|
||||||
|
if (song == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (recentlyPlayedUsers.Contains(song.QueuerName))
|
||||||
|
{
|
||||||
|
recentlyPlayedUsers.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
recentlyPlayedUsers.Add(song.QueuerName);
|
||||||
|
return song;
|
||||||
|
}
|
||||||
|
|
||||||
public void Shuffle()
|
public void Shuffle()
|
||||||
{
|
{
|
||||||
@ -249,7 +293,7 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
{
|
{
|
||||||
var curSong = CurrentSong;
|
var curSong = CurrentSong;
|
||||||
var toUpdate = playlist.Where(s => s.SongInfo.ProviderType == MusicType.Normal &&
|
var toUpdate = playlist.Where(s => s.SongInfo.ProviderType == MusicType.Normal &&
|
||||||
s.TotalLength == TimeSpan.Zero);
|
s.TotalTime == TimeSpan.Zero);
|
||||||
if (curSong != null)
|
if (curSong != null)
|
||||||
toUpdate = toUpdate.Append(curSong);
|
toUpdate = toUpdate.Append(curSong);
|
||||||
var ids = toUpdate.Select(s => s.SongInfo.Query.Substring(s.SongInfo.Query.LastIndexOf("?v=") + 3))
|
var ids = toUpdate.Select(s => s.SongInfo.Query.Substring(s.SongInfo.Query.LastIndexOf("?v=") + 3))
|
||||||
@ -263,11 +307,12 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
{
|
{
|
||||||
if (s.SongInfo.Query.EndsWith(kvp.Key))
|
if (s.SongInfo.Query.EndsWith(kvp.Key))
|
||||||
{
|
{
|
||||||
s.TotalLength = kvp.Value;
|
s.TotalTime = kvp.Value;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Destroy()
|
public void Destroy()
|
||||||
|
15
src/NadekoBot/Modules/Music/Classes/MusicExtensions.cs
Normal file
15
src/NadekoBot/Modules/Music/Classes/MusicExtensions.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using Discord;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Music.Classes
|
||||||
|
{
|
||||||
|
public static class MusicExtensions
|
||||||
|
{
|
||||||
|
public static EmbedAuthorBuilder WithMusicIcon(this EmbedAuthorBuilder eab) =>
|
||||||
|
eab.WithIconUrl("http://i.imgur.com/nhKS3PT.png");
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ using System.Text.RegularExpressions;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using VideoLibrary;
|
using VideoLibrary;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Music.Classes
|
namespace NadekoBot.Modules.Music.Classes
|
||||||
{
|
{
|
||||||
@ -18,35 +19,20 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
{
|
{
|
||||||
public string Provider { get; set; }
|
public string Provider { get; set; }
|
||||||
public MusicType ProviderType { get; set; }
|
public MusicType ProviderType { get; set; }
|
||||||
/// <summary>
|
|
||||||
/// Will be set only if the providertype is normal
|
|
||||||
/// </summary>
|
|
||||||
public string Query { get; set; }
|
public string Query { get; set; }
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
public string Uri { get; set; }
|
public string Uri { get; set; }
|
||||||
|
public string AlbumArt { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Song
|
public class Song
|
||||||
{
|
{
|
||||||
public StreamState State { get; set; }
|
|
||||||
public string PrettyName =>
|
|
||||||
$"**【 {SongInfo.Title.TrimTo(55)} 】**`{(SongInfo.Provider ?? "-")}` `by {QueuerName}`";
|
|
||||||
public SongInfo SongInfo { get; }
|
public SongInfo SongInfo { get; }
|
||||||
|
public MusicPlayer MusicPlayer { get; set; }
|
||||||
public string QueuerName { get; set; }
|
public string QueuerName { get; set; }
|
||||||
|
|
||||||
public MusicPlayer MusicPlayer { get; set; }
|
public TimeSpan TotalTime { get; set; } = TimeSpan.Zero;
|
||||||
|
public TimeSpan CurrentTime => TimeSpan.FromSeconds(bytesSent / frameBytes / (1000 / milliseconds));
|
||||||
public string PrettyCurrentTime()
|
|
||||||
{
|
|
||||||
var time = TimeSpan.FromSeconds(bytesSent / 3840 / 50);
|
|
||||||
var str = $"【{(int)time.TotalMinutes}m {time.Seconds}s】**/** ";
|
|
||||||
if (TotalLength == TimeSpan.Zero)
|
|
||||||
str += "**?**";
|
|
||||||
else if (TotalLength == TimeSpan.MaxValue)
|
|
||||||
str += "**∞**";
|
|
||||||
else
|
|
||||||
str += $"【{(int)TotalLength.TotalMinutes}m {TotalLength.Seconds}s】";
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int milliseconds = 20;
|
const int milliseconds = 20;
|
||||||
const int samplesPerFrame = (48000 / 1000) * milliseconds;
|
const int samplesPerFrame = (48000 / 1000) * milliseconds;
|
||||||
@ -54,11 +40,71 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
|
|
||||||
private ulong bytesSent { get; set; } = 0;
|
private ulong bytesSent { get; set; } = 0;
|
||||||
|
|
||||||
public bool PrintStatusMessage { get; set; } = true;
|
//pwetty
|
||||||
|
|
||||||
|
public string PrettyProvider =>
|
||||||
|
$"{(SongInfo.Provider ?? "No Provider")}";
|
||||||
|
|
||||||
|
public string PrettyFullTime => PrettyCurrentTime + " / " + PrettyTotalTime;
|
||||||
|
|
||||||
|
public string PrettyName => $"**[{SongInfo.Title.TrimTo(65)}]({songUrl})**";
|
||||||
|
|
||||||
|
public string PrettyInfo => $"{MusicPlayer.PrettyVolume} | {PrettyTotalTime} | {PrettyProvider} | {QueuerName}";
|
||||||
|
|
||||||
|
public string PrettyFullName => $"{PrettyName}\n\t\t`{PrettyTotalTime} | {PrettyProvider} | {QueuerName}`";
|
||||||
|
|
||||||
|
public string PrettyCurrentTime => CurrentTime.ToString(@"mm\:ss");
|
||||||
|
|
||||||
|
private string PrettyTotalTime {
|
||||||
|
get {
|
||||||
|
if (TotalTime == TimeSpan.Zero)
|
||||||
|
return "(?)";
|
||||||
|
else if (TotalTime == TimeSpan.MaxValue)
|
||||||
|
return "∞";
|
||||||
|
else
|
||||||
|
return TotalTime.ToString(@"mm\:ss");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Thumbnail {
|
||||||
|
get {
|
||||||
|
switch (SongInfo.ProviderType)
|
||||||
|
{
|
||||||
|
case MusicType.Radio:
|
||||||
|
//todo have videoid in songinfo from the start
|
||||||
|
var videoId = Regex.Match(SongInfo.Query, "<=v=[a-zA-Z0-9-]+(?=&)|(?<=[0-9])[^&\n]+|(?<=v=)[^&\n]+");
|
||||||
|
return $"https://img.youtube.com/vi/{ videoId }/0.jpg";
|
||||||
|
case MusicType.Normal:
|
||||||
|
return $"https://cdn.discordapp.com/attachments/155726317222887425/261850925063340032/1482522097_radio.png"; //test links
|
||||||
|
case MusicType.Local:
|
||||||
|
return $"https://cdn.discordapp.com/attachments/155726317222887425/261850914783100928/1482522077_music.png"; //test links
|
||||||
|
case MusicType.Soundcloud:
|
||||||
|
return SongInfo.AlbumArt;
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string songUrl {
|
||||||
|
get {
|
||||||
|
switch (SongInfo.ProviderType)
|
||||||
|
{
|
||||||
|
case MusicType.Normal:
|
||||||
|
return SongInfo.Query;
|
||||||
|
case MusicType.Soundcloud:
|
||||||
|
return SongInfo.Query;
|
||||||
|
case MusicType.Local:
|
||||||
|
return $"https://google.com/search?q={ WebUtility.UrlEncode(SongInfo.Title).Replace(' ', '+') }";
|
||||||
|
case MusicType.Radio:
|
||||||
|
return $"https://google.com/search?q={SongInfo.Title}";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private int skipTo = 0;
|
private int skipTo = 0;
|
||||||
private Logger _log;
|
|
||||||
|
|
||||||
public int SkipTo {
|
public int SkipTo {
|
||||||
get { return skipTo; }
|
get { return skipTo; }
|
||||||
set {
|
set {
|
||||||
@ -67,7 +113,7 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeSpan TotalLength { get; set; } = TimeSpan.Zero;
|
private readonly Logger _log;
|
||||||
|
|
||||||
public Song(SongInfo songInfo)
|
public Song(SongInfo songInfo)
|
||||||
{
|
{
|
||||||
@ -79,16 +125,10 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
{
|
{
|
||||||
var s = new Song(SongInfo);
|
var s = new Song(SongInfo);
|
||||||
s.MusicPlayer = MusicPlayer;
|
s.MusicPlayer = MusicPlayer;
|
||||||
s.State = StreamState.Queued;
|
s.QueuerName = QueuerName;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Song SetMusicPlayer(MusicPlayer mp)
|
|
||||||
{
|
|
||||||
this.MusicPlayer = mp;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Play(IAudioClient voiceClient, CancellationToken cancelToken)
|
public async Task Play(IAudioClient voiceClient, CancellationToken cancelToken)
|
||||||
{
|
{
|
||||||
var filename = Path.Combine(Music.MusicDataPath, DateTime.Now.UnixTimestamp().ToString());
|
var filename = Path.Combine(Music.MusicDataPath, DateTime.Now.UnixTimestamp().ToString());
|
||||||
@ -96,8 +136,6 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
SongBuffer inStream = new SongBuffer(MusicPlayer, filename, SongInfo, skipTo, frameBytes * 100);
|
SongBuffer inStream = new SongBuffer(MusicPlayer, filename, SongInfo, skipTo, frameBytes * 100);
|
||||||
var bufferTask = inStream.BufferSong(cancelToken).ConfigureAwait(false);
|
var bufferTask = inStream.BufferSong(cancelToken).ConfigureAwait(false);
|
||||||
|
|
||||||
bytesSent = 0;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var attempt = 0;
|
var attempt = 0;
|
||||||
@ -140,19 +178,20 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
finished = true;
|
finished = true;
|
||||||
}
|
}
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
_log.Debug("Prebuffering successfully completed in "+ sw.Elapsed);
|
_log.Debug("Prebuffering successfully completed in " + sw.Elapsed);
|
||||||
|
|
||||||
var outStream = voiceClient.CreatePCMStream(960);
|
var outStream = voiceClient.CreatePCMStream(960);
|
||||||
|
|
||||||
int nextTime = Environment.TickCount + milliseconds;
|
int nextTime = Environment.TickCount + milliseconds;
|
||||||
|
|
||||||
byte[] buffer = new byte[frameBytes];
|
byte[] buffer = new byte[frameBytes];
|
||||||
while (!cancelToken.IsCancellationRequested)
|
while (!cancelToken.IsCancellationRequested && //song canceled for whatever reason
|
||||||
|
!(MusicPlayer.MaxPlaytimeSeconds != 0 && CurrentTime.TotalSeconds >= MusicPlayer.MaxPlaytimeSeconds)) // or exceedded max playtime
|
||||||
{
|
{
|
||||||
//Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------");
|
//Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------");
|
||||||
var read = await inStream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
|
var read = await inStream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
|
||||||
//await inStream.CopyToAsync(voiceClient.OutputStream);
|
//await inStream.CopyToAsync(voiceClient.OutputStream);
|
||||||
if(read < frameBytes)
|
if (read < frameBytes)
|
||||||
_log.Debug("read {0}", read);
|
_log.Debug("read {0}", read);
|
||||||
unchecked
|
unchecked
|
||||||
{
|
{
|
||||||
@ -172,10 +211,15 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
if (slowconnection)
|
if (slowconnection)
|
||||||
{
|
{
|
||||||
_log.Warn("Slow connection has disrupted music, waiting a bit for buffer");
|
_log.Warn("Slow connection has disrupted music, waiting a bit for buffer");
|
||||||
|
|
||||||
await Task.Delay(1000, cancelToken).ConfigureAwait(false);
|
await Task.Delay(1000, cancelToken).ConfigureAwait(false);
|
||||||
|
nextTime = Environment.TickCount + milliseconds;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
await Task.Delay(100, cancelToken).ConfigureAwait(false);
|
await Task.Delay(100, cancelToken).ConfigureAwait(false);
|
||||||
|
nextTime = Environment.TickCount + milliseconds;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
attempt = 0;
|
attempt = 0;
|
||||||
@ -184,7 +228,10 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
attempt = 0;
|
attempt = 0;
|
||||||
|
|
||||||
while (this.MusicPlayer.Paused)
|
while (this.MusicPlayer.Paused)
|
||||||
|
{
|
||||||
await Task.Delay(200, cancelToken).ConfigureAwait(false);
|
await Task.Delay(200, cancelToken).ConfigureAwait(false);
|
||||||
|
nextTime = Environment.TickCount + milliseconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
buffer = AdjustVolume(buffer, MusicPlayer.Volume);
|
buffer = AdjustVolume(buffer, MusicPlayer.Volume);
|
||||||
@ -199,7 +246,7 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
await bufferTask;
|
await bufferTask;
|
||||||
if(inStream != null)
|
if (inStream != null)
|
||||||
inStream.Dispose();
|
inStream.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,35 +260,6 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
_log.Debug("Buffering successfull");
|
_log.Debug("Buffering successfull");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
//stackoverflow ftw
|
|
||||||
private static byte[] AdjustVolume(byte[] audioSamples, float volume)
|
|
||||||
{
|
|
||||||
if (Math.Abs(volume - 1.0f) < 0.01f)
|
|
||||||
return audioSamples;
|
|
||||||
var array = new byte[audioSamples.Length];
|
|
||||||
for (var i = 0; i < array.Length; i += 2)
|
|
||||||
{
|
|
||||||
|
|
||||||
// convert byte pair to int
|
|
||||||
short buf1 = audioSamples[i + 1];
|
|
||||||
short buf2 = audioSamples[i];
|
|
||||||
|
|
||||||
buf1 = (short)((buf1 & 0xff) << 8);
|
|
||||||
buf2 = (short)(buf2 & 0xff);
|
|
||||||
|
|
||||||
var res = (short)(buf1 | buf2);
|
|
||||||
res = (short)(res * volume);
|
|
||||||
|
|
||||||
// convert back
|
|
||||||
array[i] = (byte)res;
|
|
||||||
array[i + 1] = (byte)(res >> 8);
|
|
||||||
|
|
||||||
}
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
//aidiakapi ftw
|
//aidiakapi ftw
|
||||||
public unsafe static byte[] AdjustVolume(byte[] audioSamples, float volume)
|
public unsafe static byte[] AdjustVolume(byte[] audioSamples, float volume)
|
||||||
{
|
{
|
||||||
@ -267,200 +285,5 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
|
|
||||||
return audioSamples;
|
return audioSamples;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<Song> ResolveSong(string query, MusicType musicType = MusicType.Normal)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(query))
|
|
||||||
throw new ArgumentNullException(nameof(query));
|
|
||||||
|
|
||||||
if (musicType != MusicType.Local && IsRadioLink(query))
|
|
||||||
{
|
|
||||||
musicType = MusicType.Radio;
|
|
||||||
query = await HandleStreamContainers(query).ConfigureAwait(false) ?? query;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
switch (musicType)
|
|
||||||
{
|
|
||||||
case MusicType.Local:
|
|
||||||
return new Song(new SongInfo
|
|
||||||
{
|
|
||||||
Uri = "\"" + Path.GetFullPath(query) + "\"",
|
|
||||||
Title = Path.GetFileNameWithoutExtension(query),
|
|
||||||
Provider = "Local File",
|
|
||||||
ProviderType = musicType,
|
|
||||||
Query = query,
|
|
||||||
});
|
|
||||||
case MusicType.Radio:
|
|
||||||
return new Song(new SongInfo
|
|
||||||
{
|
|
||||||
Uri = query,
|
|
||||||
Title = $"{query}",
|
|
||||||
Provider = "Radio Stream",
|
|
||||||
ProviderType = musicType,
|
|
||||||
Query = query
|
|
||||||
})
|
|
||||||
{ TotalLength = TimeSpan.MaxValue };
|
|
||||||
}
|
|
||||||
if (SoundCloud.Default.IsSoundCloudLink(query))
|
|
||||||
{
|
|
||||||
var svideo = await SoundCloud.Default.ResolveVideoAsync(query).ConfigureAwait(false);
|
|
||||||
return new Song(new SongInfo
|
|
||||||
{
|
|
||||||
Title = svideo.FullName,
|
|
||||||
Provider = "SoundCloud",
|
|
||||||
Uri = svideo.StreamLink,
|
|
||||||
ProviderType = musicType,
|
|
||||||
Query = svideo.TrackLink,
|
|
||||||
})
|
|
||||||
{ TotalLength = TimeSpan.FromMilliseconds(svideo.Duration) };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (musicType == MusicType.Soundcloud)
|
|
||||||
{
|
|
||||||
var svideo = await SoundCloud.Default.GetVideoByQueryAsync(query).ConfigureAwait(false);
|
|
||||||
return new Song(new SongInfo
|
|
||||||
{
|
|
||||||
Title = svideo.FullName,
|
|
||||||
Provider = "SoundCloud",
|
|
||||||
Uri = svideo.StreamLink,
|
|
||||||
ProviderType = MusicType.Normal,
|
|
||||||
Query = svideo.TrackLink,
|
|
||||||
})
|
|
||||||
{ TotalLength = TimeSpan.FromMilliseconds(svideo.Duration) };
|
|
||||||
}
|
|
||||||
|
|
||||||
var link = (await NadekoBot.Google.GetVideosByKeywordsAsync(query).ConfigureAwait(false)).FirstOrDefault();
|
|
||||||
if (string.IsNullOrWhiteSpace(link))
|
|
||||||
throw new OperationCanceledException("Not a valid youtube query.");
|
|
||||||
var allVideos = await Task.Run(async () => { try { return await YouTube.Default.GetAllVideosAsync(link).ConfigureAwait(false); } catch { return Enumerable.Empty<YouTubeVideo>(); } }).ConfigureAwait(false);
|
|
||||||
var videos = allVideos.Where(v => v.AdaptiveKind == AdaptiveKind.Audio);
|
|
||||||
var video = videos
|
|
||||||
.Where(v => v.AudioBitrate < 256)
|
|
||||||
.OrderByDescending(v => v.AudioBitrate)
|
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
if (video == null) // do something with this error
|
|
||||||
throw new Exception("Could not load any video elements based on the query.");
|
|
||||||
var m = Regex.Match(query, @"\?t=(?<t>\d*)");
|
|
||||||
int gotoTime = 0;
|
|
||||||
if (m.Captures.Count > 0)
|
|
||||||
int.TryParse(m.Groups["t"].ToString(), out gotoTime);
|
|
||||||
var song = new Song(new SongInfo
|
|
||||||
{
|
|
||||||
Title = video.Title.Substring(0, video.Title.Length - 10), // removing trailing "- You Tube"
|
|
||||||
Provider = "YouTube",
|
|
||||||
Uri = video.Uri,
|
|
||||||
Query = link,
|
|
||||||
ProviderType = musicType,
|
|
||||||
});
|
|
||||||
song.SkipTo = gotoTime;
|
|
||||||
return song;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Failed resolving the link.{ex.Message}");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task<string> HandleStreamContainers(string query)
|
|
||||||
{
|
|
||||||
string file = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (var http = new HttpClient())
|
|
||||||
{
|
|
||||||
file = await http.GetStringAsync(query).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
if (query.Contains(".pls"))
|
|
||||||
{
|
|
||||||
//File1=http://armitunes.com:8000/
|
|
||||||
//Regex.Match(query)
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var m = Regex.Match(file, "File1=(?<url>.*?)\\n");
|
|
||||||
var res = m.Groups["url"]?.ToString();
|
|
||||||
return res?.Trim();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Failed reading .pls:\n{file}");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (query.Contains(".m3u"))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
# This is a comment
|
|
||||||
C:\xxx4xx\xxxxxx3x\xx2xxxx\xx.mp3
|
|
||||||
C:\xxx5xx\x6xxxxxx\x7xxxxx\xx.mp3
|
|
||||||
*/
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var m = Regex.Match(file, "(?<url>^[^#].*)", RegexOptions.Multiline);
|
|
||||||
var res = m.Groups["url"]?.ToString();
|
|
||||||
return res?.Trim();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Failed reading .m3u:\n{file}");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if (query.Contains(".asx"))
|
|
||||||
{
|
|
||||||
//<ref href="http://armitunes.com:8000"/>
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var m = Regex.Match(file, "<ref href=\"(?<url>.*?)\"");
|
|
||||||
var res = m.Groups["url"]?.ToString();
|
|
||||||
return res?.Trim();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Failed reading .asx:\n{file}");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (query.Contains(".xspf"))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<playlist version="1" xmlns="http://xspf.org/ns/0/">
|
|
||||||
<trackList>
|
|
||||||
<track><location>file:///mp3s/song_1.mp3</location></track>
|
|
||||||
*/
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var m = Regex.Match(file, "<location>(?<url>.*?)</location>");
|
|
||||||
var res = m.Groups["url"]?.ToString();
|
|
||||||
return res?.Trim();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Failed reading .xspf:\n{file}");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsRadioLink(string query) =>
|
|
||||||
(query.StartsWith("http") ||
|
|
||||||
query.StartsWith("ww"))
|
|
||||||
&&
|
|
||||||
(query.Contains(".pls") ||
|
|
||||||
query.Contains(".m3u") ||
|
|
||||||
query.Contains(".asx") ||
|
|
||||||
query.Contains(".xspf"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -25,21 +25,21 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
}
|
}
|
||||||
|
|
||||||
MusicPlayer MusicPlayer;
|
MusicPlayer MusicPlayer { get; }
|
||||||
|
|
||||||
private string Basename;
|
private string Basename { get; }
|
||||||
|
|
||||||
private SongInfo SongInfo;
|
private SongInfo SongInfo { get; }
|
||||||
|
|
||||||
private int SkipTo;
|
private int SkipTo { get; }
|
||||||
|
|
||||||
private int MaxFileSize = 2.MiB();
|
private int MaxFileSize { get; } = 2.MiB();
|
||||||
|
|
||||||
private long FileNumber = -1;
|
private long FileNumber = -1;
|
||||||
|
|
||||||
private long NextFileToRead = 0;
|
private long NextFileToRead = 0;
|
||||||
|
|
||||||
public bool BufferingCompleted { get; private set;} = false;
|
public bool BufferingCompleted { get; private set; } = false;
|
||||||
|
|
||||||
private ulong CurrentBufferSize = 0;
|
private ulong CurrentBufferSize = 0;
|
||||||
|
|
||||||
@ -76,7 +76,8 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
outStream.Dispose();
|
outStream.Dispose();
|
||||||
}catch { }
|
}
|
||||||
|
catch { }
|
||||||
outStream = new FileStream(Basename + "-" + ++FileNumber, FileMode.Append, FileAccess.Write, FileShare.Read);
|
outStream = new FileStream(Basename + "-" + ++FileNumber, FileMode.Append, FileAccess.Write, FileShare.Read);
|
||||||
currentFileSize = bytesRead;
|
currentFileSize = bytesRead;
|
||||||
}
|
}
|
||||||
@ -108,7 +109,7 @@ Check the guides for your platform on how to setup ffmpeg correctly:
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if(outStream != null)
|
if (outStream != null)
|
||||||
outStream.Dispose();
|
outStream.Dispose();
|
||||||
Console.WriteLine($"Buffering done.");
|
Console.WriteLine($"Buffering done.");
|
||||||
if (p != null)
|
if (p != null)
|
||||||
@ -151,7 +152,7 @@ Check the guides for your platform on how to setup ffmpeg correctly:
|
|||||||
|
|
||||||
private void CleanFiles()
|
private void CleanFiles()
|
||||||
{
|
{
|
||||||
for (long i = NextFileToRead - 1 ; i <= FileNumber; i++)
|
for (long i = NextFileToRead - 1; i <= FileNumber; i++)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -169,7 +170,7 @@ Check the guides for your platform on how to setup ffmpeg correctly:
|
|||||||
|
|
||||||
public override bool CanWrite => false;
|
public override bool CanWrite => false;
|
||||||
|
|
||||||
public override long Length => (long) CurrentBufferSize;
|
public override long Length => (long)CurrentBufferSize;
|
||||||
|
|
||||||
public override long Position { get; set; } = 0;
|
public override long Position { get; set; } = 0;
|
||||||
|
|
||||||
@ -178,7 +179,7 @@ Check the guides for your platform on how to setup ffmpeg correctly:
|
|||||||
public override int Read(byte[] buffer, int offset, int count)
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
int read = CurrentFileStream.Read(buffer, offset, count);
|
int read = CurrentFileStream.Read(buffer, offset, count);
|
||||||
if(read < count)
|
if (read < count)
|
||||||
{
|
{
|
||||||
if (!BufferingCompleted || IsNextFileReady())
|
if (!BufferingCompleted || IsNextFileReady())
|
||||||
{
|
{
|
||||||
|
212
src/NadekoBot/Modules/Music/Classes/SongHandler.cs
Normal file
212
src/NadekoBot/Modules/Music/Classes/SongHandler.cs
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using VideoLibrary;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Music.Classes
|
||||||
|
{
|
||||||
|
public static class SongHandler
|
||||||
|
{
|
||||||
|
public static async Task<Song> ResolveSong(string query, MusicType musicType = MusicType.Normal)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(query))
|
||||||
|
throw new ArgumentNullException(nameof(query));
|
||||||
|
|
||||||
|
if (musicType != MusicType.Local && IsRadioLink(query))
|
||||||
|
{
|
||||||
|
musicType = MusicType.Radio;
|
||||||
|
query = await HandleStreamContainers(query).ConfigureAwait(false) ?? query;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (musicType)
|
||||||
|
{
|
||||||
|
case MusicType.Local:
|
||||||
|
return new Song(new SongInfo
|
||||||
|
{
|
||||||
|
Uri = "\"" + Path.GetFullPath(query) + "\"",
|
||||||
|
Title = Path.GetFileNameWithoutExtension(query),
|
||||||
|
Provider = "Local File",
|
||||||
|
ProviderType = musicType,
|
||||||
|
Query = query,
|
||||||
|
});
|
||||||
|
case MusicType.Radio:
|
||||||
|
return new Song(new SongInfo
|
||||||
|
{
|
||||||
|
Uri = query,
|
||||||
|
Title = $"{query}",
|
||||||
|
Provider = "Radio Stream",
|
||||||
|
ProviderType = musicType,
|
||||||
|
Query = query
|
||||||
|
})
|
||||||
|
{ TotalTime = TimeSpan.MaxValue };
|
||||||
|
}
|
||||||
|
if (SoundCloud.Default.IsSoundCloudLink(query))
|
||||||
|
{
|
||||||
|
var svideo = await SoundCloud.Default.ResolveVideoAsync(query).ConfigureAwait(false);
|
||||||
|
return new Song(new SongInfo
|
||||||
|
{
|
||||||
|
Title = svideo.FullName,
|
||||||
|
Provider = "SoundCloud",
|
||||||
|
Uri = svideo.StreamLink,
|
||||||
|
ProviderType = musicType,
|
||||||
|
Query = svideo.TrackLink,
|
||||||
|
AlbumArt = svideo.artwork_url,
|
||||||
|
})
|
||||||
|
{ TotalTime = TimeSpan.FromMilliseconds(svideo.Duration) };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (musicType == MusicType.Soundcloud)
|
||||||
|
{
|
||||||
|
var svideo = await SoundCloud.Default.GetVideoByQueryAsync(query).ConfigureAwait(false);
|
||||||
|
return new Song(new SongInfo
|
||||||
|
{
|
||||||
|
Title = svideo.FullName,
|
||||||
|
Provider = "SoundCloud",
|
||||||
|
Uri = svideo.StreamLink,
|
||||||
|
ProviderType = MusicType.Soundcloud,
|
||||||
|
Query = svideo.TrackLink,
|
||||||
|
AlbumArt = svideo.artwork_url,
|
||||||
|
})
|
||||||
|
{ TotalTime = TimeSpan.FromMilliseconds(svideo.Duration) };
|
||||||
|
}
|
||||||
|
|
||||||
|
var link = (await NadekoBot.Google.GetVideosByKeywordsAsync(query).ConfigureAwait(false)).FirstOrDefault();
|
||||||
|
if (string.IsNullOrWhiteSpace(link))
|
||||||
|
throw new OperationCanceledException("Not a valid youtube query.");
|
||||||
|
var allVideos = await Task.Run(async () => { try { return await YouTube.Default.GetAllVideosAsync(link).ConfigureAwait(false); } catch { return Enumerable.Empty<YouTubeVideo>(); } }).ConfigureAwait(false);
|
||||||
|
var videos = allVideos.Where(v => v.AdaptiveKind == AdaptiveKind.Audio);
|
||||||
|
var video = videos
|
||||||
|
.Where(v => v.AudioBitrate < 256)
|
||||||
|
.OrderByDescending(v => v.AudioBitrate)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (video == null) // do something with this error
|
||||||
|
throw new Exception("Could not load any video elements based on the query.");
|
||||||
|
var m = Regex.Match(query, @"\?t=(?<t>\d*)");
|
||||||
|
int gotoTime = 0;
|
||||||
|
if (m.Captures.Count > 0)
|
||||||
|
int.TryParse(m.Groups["t"].ToString(), out gotoTime);
|
||||||
|
var song = new Song(new SongInfo
|
||||||
|
{
|
||||||
|
Title = video.Title.Substring(0, video.Title.Length - 10), // removing trailing "- You Tube"
|
||||||
|
Provider = "YouTube",
|
||||||
|
Uri = video.Uri,
|
||||||
|
Query = link,
|
||||||
|
ProviderType = musicType,
|
||||||
|
});
|
||||||
|
song.SkipTo = gotoTime;
|
||||||
|
return song;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Failed resolving the link.{ex.Message}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<string> HandleStreamContainers(string query)
|
||||||
|
{
|
||||||
|
string file = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var http = new HttpClient())
|
||||||
|
{
|
||||||
|
file = await http.GetStringAsync(query).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
if (query.Contains(".pls"))
|
||||||
|
{
|
||||||
|
//File1=http://armitunes.com:8000/
|
||||||
|
//Regex.Match(query)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var m = Regex.Match(file, "File1=(?<url>.*?)\\n");
|
||||||
|
var res = m.Groups["url"]?.ToString();
|
||||||
|
return res?.Trim();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Failed reading .pls:\n{file}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (query.Contains(".m3u"))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
# This is a comment
|
||||||
|
C:\xxx4xx\xxxxxx3x\xx2xxxx\xx.mp3
|
||||||
|
C:\xxx5xx\x6xxxxxx\x7xxxxx\xx.mp3
|
||||||
|
*/
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var m = Regex.Match(file, "(?<url>^[^#].*)", RegexOptions.Multiline);
|
||||||
|
var res = m.Groups["url"]?.ToString();
|
||||||
|
return res?.Trim();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Failed reading .m3u:\n{file}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (query.Contains(".asx"))
|
||||||
|
{
|
||||||
|
//<ref href="http://armitunes.com:8000"/>
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var m = Regex.Match(file, "<ref href=\"(?<url>.*?)\"");
|
||||||
|
var res = m.Groups["url"]?.ToString();
|
||||||
|
return res?.Trim();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Failed reading .asx:\n{file}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (query.Contains(".xspf"))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<playlist version="1" xmlns="http://xspf.org/ns/0/">
|
||||||
|
<trackList>
|
||||||
|
<track><location>file:///mp3s/song_1.mp3</location></track>
|
||||||
|
*/
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var m = Regex.Match(file, "<location>(?<url>.*?)</location>");
|
||||||
|
var res = m.Groups["url"]?.ToString();
|
||||||
|
return res?.Trim();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Failed reading .xspf:\n{file}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsRadioLink(string query) =>
|
||||||
|
(query.StartsWith("http") ||
|
||||||
|
query.StartsWith("ww"))
|
||||||
|
&&
|
||||||
|
(query.Contains(".pls") ||
|
||||||
|
query.Contains(".m3u") ||
|
||||||
|
query.Contains(".asx") ||
|
||||||
|
query.Contains(".xspf"));
|
||||||
|
}
|
||||||
|
}
|
@ -73,6 +73,7 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
public int Duration { get; set; }
|
public int Duration { get; set; }
|
||||||
[JsonProperty("permalink_url")]
|
[JsonProperty("permalink_url")]
|
||||||
public string TrackLink { get; set; } = "";
|
public string TrackLink { get; set; } = "";
|
||||||
|
public string artwork_url { get; set; } = "";
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public string StreamLink => $"https://api.soundcloud.com/tracks/{Id}/stream?client_id={NadekoBot.Credentials.SoundCloudClientId}";
|
public string StreamLink => $"https://api.soundcloud.com/tracks/{Id}/stream?client_id={NadekoBot.Credentials.SoundCloudClientId}";
|
||||||
}
|
}
|
||||||
|
@ -14,25 +14,47 @@ using System.Net.Http;
|
|||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Music
|
namespace NadekoBot.Modules.Music
|
||||||
{
|
{
|
||||||
[NadekoModule("Music", "!!", AutoLoad = false)]
|
[NadekoModule("Music", "!!", AutoLoad = false)]
|
||||||
public partial class Music : DiscordModule
|
public partial class Music : DiscordModule
|
||||||
{
|
{
|
||||||
public static ConcurrentDictionary<ulong, MusicPlayer> MusicPlayers = new ConcurrentDictionary<ulong, MusicPlayer>();
|
public static ConcurrentDictionary<ulong, MusicPlayer> MusicPlayers { get; } = new ConcurrentDictionary<ulong, MusicPlayer>();
|
||||||
|
|
||||||
public const string MusicDataPath = "data/musicdata";
|
public const string MusicDataPath = "data/musicdata";
|
||||||
private IGoogleApiService _google;
|
|
||||||
|
|
||||||
public Music(ILocalization loc, CommandService cmds, ShardedDiscordClient client, IGoogleApiService google) : base(loc, cmds, client)
|
public Music() : base()
|
||||||
{
|
{
|
||||||
//it can fail if its currenctly opened or doesn't exist. Either way i don't care
|
//it can fail if its currenctly opened or doesn't exist. Either way i don't care
|
||||||
try { Directory.Delete(MusicDataPath, true); } catch { }
|
try { Directory.Delete(MusicDataPath, true); } catch { }
|
||||||
|
|
||||||
Directory.CreateDirectory(MusicDataPath);
|
NadekoBot.Client.UserVoiceStateUpdated += Client_UserVoiceStateUpdated;
|
||||||
|
|
||||||
_google = google;
|
Directory.CreateDirectory(MusicDataPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Client_UserVoiceStateUpdated(IUser iusr, IVoiceState oldState, IVoiceState newState)
|
||||||
|
{
|
||||||
|
var usr = iusr as IGuildUser;
|
||||||
|
if (usr == null ||
|
||||||
|
oldState.VoiceChannel == newState.VoiceChannel)
|
||||||
|
return;
|
||||||
|
MusicPlayer player;
|
||||||
|
if (!MusicPlayers.TryGetValue(usr.Guild.Id, out player))
|
||||||
|
return;
|
||||||
|
if ((player.PlaybackVoiceChannel == newState.VoiceChannel && //if joined first, and player paused, unpause
|
||||||
|
player.Paused &&
|
||||||
|
player.PlaybackVoiceChannel.GetUsers().Count == 2) || // keep in mind bot is in the channel (+1)
|
||||||
|
(player.PlaybackVoiceChannel == oldState.VoiceChannel && // if left last, and player unpaused, pause
|
||||||
|
!player.Paused &&
|
||||||
|
player.PlaybackVoiceChannel.GetUsers().Count == 1))
|
||||||
|
{
|
||||||
|
player.TogglePause();
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -75,33 +97,45 @@ namespace NadekoBot.Modules.Music
|
|||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public Task Destroy(IUserMessage umsg)
|
public async Task Destroy(IUserMessage umsg)
|
||||||
|
{
|
||||||
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
await channel.SendErrorAsync("This command is temporarily disabled.").ConfigureAwait(false);
|
||||||
|
|
||||||
|
/*MusicPlayer musicPlayer;
|
||||||
|
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return Task.CompletedTask;
|
||||||
|
if (((IGuildUser)umsg.Author).VoiceChannel == musicPlayer.PlaybackVoiceChannel)
|
||||||
|
if(MusicPlayers.TryRemove(channel.Guild.Id, out musicPlayer))
|
||||||
|
musicPlayer.Destroy();
|
||||||
|
return Task.CompletedTask;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public Task Pause(IUserMessage umsg)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
MusicPlayer musicPlayer;
|
MusicPlayer musicPlayer;
|
||||||
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return Task.CompletedTask;
|
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return Task.CompletedTask;
|
||||||
if (((IGuildUser)umsg.Author).VoiceChannel == musicPlayer.PlaybackVoiceChannel)
|
if (((IGuildUser)umsg.Author).VoiceChannel != musicPlayer.PlaybackVoiceChannel)
|
||||||
if(MusicPlayers.TryRemove(channel.Guild.Id, out musicPlayer))
|
return Task.CompletedTask;
|
||||||
musicPlayer.Destroy();
|
musicPlayer.TogglePause();
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task Pause(IUserMessage umsg)
|
public async Task Fairplay(IUserMessage umsg)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
MusicPlayer musicPlayer;
|
MusicPlayer musicPlayer;
|
||||||
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return;
|
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return;
|
||||||
if (((IGuildUser)umsg.Author).VoiceChannel != musicPlayer.PlaybackVoiceChannel)
|
if (((IGuildUser)umsg.Author).VoiceChannel != musicPlayer.PlaybackVoiceChannel)
|
||||||
return;
|
return;
|
||||||
musicPlayer.TogglePause();
|
var val = musicPlayer.FairPlay = !musicPlayer.FairPlay;
|
||||||
if (musicPlayer.Paused)
|
|
||||||
await channel.SendMessageAsync("🎵`Music Player paused.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("Fair play " + (val ? "enabled" : "disabled") + ".").ConfigureAwait(false);
|
||||||
else
|
|
||||||
await channel.SendMessageAsync("🎵`Music Player unpaused.`").ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -113,8 +147,7 @@ namespace NadekoBot.Modules.Music
|
|||||||
await QueueSong(((IGuildUser)umsg.Author), channel, ((IGuildUser)umsg.Author).VoiceChannel, query).ConfigureAwait(false);
|
await QueueSong(((IGuildUser)umsg.Author), channel, ((IGuildUser)umsg.Author).VoiceChannel, query).ConfigureAwait(false);
|
||||||
if (channel.Guild.GetCurrentUser().GetPermissions(channel).ManageMessages)
|
if (channel.Guild.GetCurrentUser().GetPermissions(channel).ManageMessages)
|
||||||
{
|
{
|
||||||
await Task.Delay(10000).ConfigureAwait(false);
|
umsg.DeleteAfter(10);
|
||||||
await ((IUserMessage)umsg).DeleteAsync().ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,8 +160,7 @@ namespace NadekoBot.Modules.Music
|
|||||||
await QueueSong(((IGuildUser)umsg.Author), channel, ((IGuildUser)umsg.Author).VoiceChannel, query, musicType: MusicType.Soundcloud).ConfigureAwait(false);
|
await QueueSong(((IGuildUser)umsg.Author), channel, ((IGuildUser)umsg.Author).VoiceChannel, query, musicType: MusicType.Soundcloud).ConfigureAwait(false);
|
||||||
if (channel.Guild.GetCurrentUser().GetPermissions(channel).ManageMessages)
|
if (channel.Guild.GetCurrentUser().GetPermissions(channel).ManageMessages)
|
||||||
{
|
{
|
||||||
await Task.Delay(10000).ConfigureAwait(false);
|
umsg.DeleteAfter(10);
|
||||||
await ((IUserMessage)umsg).DeleteAsync().ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +172,7 @@ namespace NadekoBot.Modules.Music
|
|||||||
MusicPlayer musicPlayer;
|
MusicPlayer musicPlayer;
|
||||||
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer))
|
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("🎵 No active music player.").ConfigureAwait(false);
|
await channel.SendErrorAsync("🎵 No active music player.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (page <= 0)
|
if (page <= 0)
|
||||||
@ -148,27 +180,44 @@ namespace NadekoBot.Modules.Music
|
|||||||
|
|
||||||
var currentSong = musicPlayer.CurrentSong;
|
var currentSong = musicPlayer.CurrentSong;
|
||||||
if (currentSong == null)
|
if (currentSong == null)
|
||||||
return;
|
|
||||||
|
|
||||||
if (currentSong.TotalLength == TimeSpan.Zero)
|
|
||||||
{
|
{
|
||||||
await musicPlayer.UpdateSongDurationsAsync().ConfigureAwait(false);
|
await channel.SendErrorAsync("🎵 No active music player.").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var toSend = $"🎵`Now Playing` {currentSong.PrettyName} " + $"{currentSong.PrettyCurrentTime()}\n";
|
try { await musicPlayer.UpdateSongDurationsAsync().ConfigureAwait(false); } catch { }
|
||||||
if (musicPlayer.RepeatSong)
|
|
||||||
toSend += "🔂";
|
const int itemsPerPage = 10;
|
||||||
else if (musicPlayer.RepeatPlaylist)
|
|
||||||
toSend += "🔁";
|
|
||||||
toSend += $" **{musicPlayer.Playlist.Count}** `tracks currently queued. Showing page {page}` ";
|
|
||||||
if (musicPlayer.MaxQueueSize != 0 && musicPlayer.Playlist.Count >= musicPlayer.MaxQueueSize)
|
|
||||||
toSend += "**Song queue is full!**\n";
|
|
||||||
else
|
|
||||||
toSend += "\n";
|
|
||||||
const int itemsPerPage = 15;
|
|
||||||
int startAt = itemsPerPage * (page - 1);
|
int startAt = itemsPerPage * (page - 1);
|
||||||
var number = 1 + startAt;
|
var number = 0 + startAt;
|
||||||
await channel.SendMessageAsync(toSend + string.Join("\n", musicPlayer.Playlist.Skip(startAt).Take(15).Select(v => $"`{number++}.` {v.PrettyName}"))).ConfigureAwait(false);
|
|
||||||
|
var total = musicPlayer.TotalPlaytime;
|
||||||
|
var maxPlaytime = musicPlayer.MaxPlaytimeSeconds;
|
||||||
|
var embed = new EmbedBuilder()
|
||||||
|
.WithAuthor(eab => eab.WithName($"Player Queue - Page {page}")
|
||||||
|
.WithMusicIcon())
|
||||||
|
.WithDescription(string.Join("\n", musicPlayer.Playlist
|
||||||
|
.Skip(startAt)
|
||||||
|
.Take(10)
|
||||||
|
.Select(v => $"`{++number}.` {v.PrettyFullName}")))
|
||||||
|
.WithFooter(ef => ef.WithText($"{musicPlayer.PrettyVolume} | {musicPlayer.Playlist.Count} " +
|
||||||
|
$"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {total.Minutes}m {total.Seconds}s | " +
|
||||||
|
(musicPlayer.FairPlay? "✔️fairplay" : "✖️fairplay") + $" | " + (maxPlaytime == 0 ? "unlimited" : $"{maxPlaytime}s limit")))
|
||||||
|
.WithOkColor();
|
||||||
|
|
||||||
|
if (musicPlayer.RepeatSong)
|
||||||
|
{
|
||||||
|
embed.WithTitle($"🔂 Repeating Song: {currentSong.SongInfo.Title} | {currentSong.PrettyFullTime}");
|
||||||
|
}
|
||||||
|
else if (musicPlayer.RepeatPlaylist)
|
||||||
|
{
|
||||||
|
embed.WithTitle("🔁 Repeating Playlist");
|
||||||
|
}
|
||||||
|
if (musicPlayer.MaxQueueSize != 0 && musicPlayer.Playlist.Count >= musicPlayer.MaxQueueSize)
|
||||||
|
{
|
||||||
|
embed.WithTitle("🎵 Song queue is full!");
|
||||||
|
}
|
||||||
|
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -176,19 +225,22 @@ namespace NadekoBot.Modules.Music
|
|||||||
public async Task NowPlaying(IUserMessage umsg)
|
public async Task NowPlaying(IUserMessage umsg)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
MusicPlayer musicPlayer;
|
MusicPlayer musicPlayer;
|
||||||
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer))
|
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer))
|
||||||
return;
|
return;
|
||||||
var currentSong = musicPlayer.CurrentSong;
|
var currentSong = musicPlayer.CurrentSong;
|
||||||
if (currentSong == null)
|
if (currentSong == null)
|
||||||
return;
|
return;
|
||||||
|
try { await musicPlayer.UpdateSongDurationsAsync().ConfigureAwait(false); } catch { }
|
||||||
|
|
||||||
if (currentSong.TotalLength == TimeSpan.Zero)
|
var embed = new EmbedBuilder().WithOkColor()
|
||||||
{
|
.WithAuthor(eab => eab.WithName("Now Playing").WithMusicIcon())
|
||||||
await musicPlayer.UpdateSongDurationsAsync().ConfigureAwait(false);
|
.WithDescription(currentSong.PrettyName)
|
||||||
}
|
.WithThumbnail(tn => tn.Url = currentSong.Thumbnail)
|
||||||
await channel.SendMessageAsync($"🎵`Now Playing` {currentSong.PrettyName} " +
|
.WithFooter(ef => ef.WithText(musicPlayer.PrettyVolume + " | " + currentSong.PrettyFullTime + $" | {currentSong.PrettyProvider} | {currentSong.QueuerName}"));
|
||||||
$"{currentSong.PrettyCurrentTime()}").ConfigureAwait(false);
|
|
||||||
|
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -204,7 +256,7 @@ namespace NadekoBot.Modules.Music
|
|||||||
if (val < 0)
|
if (val < 0)
|
||||||
return;
|
return;
|
||||||
var volume = musicPlayer.SetVolume(val);
|
var volume = musicPlayer.SetVolume(val);
|
||||||
await channel.SendMessageAsync($"🎵 `Volume set to {volume}%`").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"🎵 Volume set to {volume}%").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -215,15 +267,15 @@ namespace NadekoBot.Modules.Music
|
|||||||
|
|
||||||
if (val < 0 || val > 100)
|
if (val < 0 || val > 100)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("Volume number invalid. Must be between 0 and 100").ConfigureAwait(false);
|
await channel.SendErrorAsync("Volume number invalid. Must be between 0 and 100").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
uow.GuildConfigs.For(channel.Guild.Id).DefaultMusicVolume = val / 100.0f;
|
uow.GuildConfigs.For(channel.Guild.Id, set => set).DefaultMusicVolume = val / 100.0f;
|
||||||
uow.Complete();
|
uow.Complete();
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"🎵 `Default volume set to {val}%`").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"🎵 Default volume set to {val}%").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -238,12 +290,12 @@ namespace NadekoBot.Modules.Music
|
|||||||
return;
|
return;
|
||||||
if (musicPlayer.Playlist.Count < 2)
|
if (musicPlayer.Playlist.Count < 2)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 Not enough songs in order to perform the shuffle.").ConfigureAwait(false);
|
await channel.SendErrorAsync("💢 Not enough songs in order to perform the shuffle.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
musicPlayer.Shuffle();
|
musicPlayer.Shuffle();
|
||||||
await channel.SendMessageAsync("🎵 `Songs shuffled.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("🎵 Songs shuffled.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -256,35 +308,48 @@ namespace NadekoBot.Modules.Music
|
|||||||
return;
|
return;
|
||||||
if (((IGuildUser)umsg.Author).VoiceChannel?.Guild != channel.Guild)
|
if (((IGuildUser)umsg.Author).VoiceChannel?.Guild != channel.Guild)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 You need to be in a voice channel on this server.\n If you are already in a voice channel, try rejoining it.").ConfigureAwait(false);
|
await channel.SendErrorAsync("💢 You need to be in a **voice channel** on this server.\n If you are already in a voice channel, try rejoining it.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var plId = (await _google.GetPlaylistIdsByKeywordsAsync(arg).ConfigureAwait(false)).FirstOrDefault();
|
var plId = (await NadekoBot.Google.GetPlaylistIdsByKeywordsAsync(arg).ConfigureAwait(false)).FirstOrDefault();
|
||||||
if (plId == null)
|
if (plId == null)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("No search results for that query.");
|
await channel.SendErrorAsync("No search results for that query.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var ids = await _google.GetPlaylistTracksAsync(plId, 500).ConfigureAwait(false);
|
var ids = await NadekoBot.Google.GetPlaylistTracksAsync(plId, 500).ConfigureAwait(false);
|
||||||
if (!ids.Any())
|
if (!ids.Any())
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"🎵 `Failed to find any songs.`").ConfigureAwait(false);
|
await channel.SendErrorAsync($"🎵 Failed to find any songs.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var idArray = ids as string[] ?? ids.ToArray();
|
var count = ids.Count();
|
||||||
var count = idArray.Length;
|
|
||||||
var msg =
|
var msg = await channel.SendMessageAsync($"🎵 Attempting to queue **{count}** songs".SnPl(count) + "...").ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync($"🎵 `Attempting to queue {count} songs".SnPl(count) + "...`").ConfigureAwait(false);
|
|
||||||
foreach (var id in idArray)
|
var cancelSource = new CancellationTokenSource();
|
||||||
|
|
||||||
|
var gusr = (IGuildUser)umsg.Author;
|
||||||
|
|
||||||
|
while (ids.Any() && !cancelSource.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
var tasks = Task.WhenAll(ids.Take(5).Select(async id =>
|
||||||
|
{
|
||||||
|
if (cancelSource.Token.IsCancellationRequested)
|
||||||
|
return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await QueueSong(((IGuildUser)umsg.Author), channel, ((IGuildUser)umsg.Author).VoiceChannel, id, true).ConfigureAwait(false);
|
await QueueSong(gusr, channel, gusr.VoiceChannel, id, true).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (SongNotFoundException) { }
|
catch (SongNotFoundException) { }
|
||||||
catch { break; }
|
catch { try { cancelSource.Cancel(); } catch { } }
|
||||||
|
}));
|
||||||
|
|
||||||
|
await Task.WhenAny(tasks, Task.Delay(Timeout.Infinite, cancelSource.Token));
|
||||||
|
ids = ids.Skip(5);
|
||||||
}
|
}
|
||||||
await msg.ModifyAsync(m => m.Content = "🎵 `Playlist queue complete.`").ConfigureAwait(false);
|
|
||||||
|
await msg.ModifyAsync(m => m.Content = "✅ Playlist queue complete.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -338,11 +403,12 @@ namespace NadekoBot.Modules.Music
|
|||||||
var dir = new DirectoryInfo(arg);
|
var dir = new DirectoryInfo(arg);
|
||||||
var fileEnum = dir.GetFiles("*", SearchOption.AllDirectories)
|
var fileEnum = dir.GetFiles("*", SearchOption.AllDirectories)
|
||||||
.Where(x => !x.Attributes.HasFlag(FileAttributes.Hidden | FileAttributes.System));
|
.Where(x => !x.Attributes.HasFlag(FileAttributes.Hidden | FileAttributes.System));
|
||||||
|
var gusr = (IGuildUser)umsg.Author;
|
||||||
foreach (var file in fileEnum)
|
foreach (var file in fileEnum)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await QueueSong(((IGuildUser)umsg.Author), channel, ((IGuildUser)umsg.Author).VoiceChannel, file.FullName, true, MusicType.Local).ConfigureAwait(false);
|
await QueueSong(gusr, channel, gusr.VoiceChannel, file.FullName, true, MusicType.Local).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (PlaylistFullException)
|
catch (PlaylistFullException)
|
||||||
{
|
{
|
||||||
@ -350,7 +416,7 @@ namespace NadekoBot.Modules.Music
|
|||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync("🎵 `Directory queue complete.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("🎵 Directory queue complete.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
@ -362,14 +428,13 @@ namespace NadekoBot.Modules.Music
|
|||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
if (((IGuildUser)umsg.Author).VoiceChannel?.Guild != channel.Guild)
|
if (((IGuildUser)umsg.Author).VoiceChannel?.Guild != channel.Guild)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 You need to be in a voice channel on this server.\n If you are already in a voice channel, try rejoining it.").ConfigureAwait(false);
|
await channel.SendErrorAsync("💢 You need to be in a voice channel on this server.\n If you are already in a voice channel, try rejoining it.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await QueueSong(((IGuildUser)umsg.Author), channel, ((IGuildUser)umsg.Author).VoiceChannel, radio_link, musicType: MusicType.Radio).ConfigureAwait(false);
|
await QueueSong(((IGuildUser)umsg.Author), channel, ((IGuildUser)umsg.Author).VoiceChannel, radio_link, musicType: MusicType.Radio).ConfigureAwait(false);
|
||||||
if (channel.Guild.GetCurrentUser().GetPermissions(channel).ManageMessages)
|
if (channel.Guild.GetCurrentUser().GetPermissions(channel).ManageMessages)
|
||||||
{
|
{
|
||||||
await Task.Delay(10000).ConfigureAwait(false);
|
umsg.DeleteAfter(10);
|
||||||
await ((IUserMessage)umsg).DeleteAsync().ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,7 +481,15 @@ namespace NadekoBot.Modules.Music
|
|||||||
return;
|
return;
|
||||||
var song = (musicPlayer.Playlist as List<Song>)?[num - 1];
|
var song = (musicPlayer.Playlist as List<Song>)?[num - 1];
|
||||||
musicPlayer.RemoveSongAt(num - 1);
|
musicPlayer.RemoveSongAt(num - 1);
|
||||||
await channel.SendMessageAsync($"🎵**Track {song.PrettyName} at position `#{num}` has been removed.**").ConfigureAwait(false);
|
|
||||||
|
var embed = new EmbedBuilder()
|
||||||
|
.WithAuthor(eab => eab.WithName("Song Removed!").WithMusicIcon())
|
||||||
|
.AddField(fb => fb.WithName("**Song Position**").WithValue($"#{num}").WithIsInline(true))
|
||||||
|
.AddField(fb => fb.WithName("**Song Name**").WithValue(song.PrettyName).WithIsInline(true))
|
||||||
|
.WithFooter(ef => ef.WithText($"{song.PrettyProvider} | {song.QueuerName}"))
|
||||||
|
.WithErrorColor();
|
||||||
|
|
||||||
|
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -431,7 +504,7 @@ namespace NadekoBot.Modules.Music
|
|||||||
MusicPlayer musicPlayer;
|
MusicPlayer musicPlayer;
|
||||||
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return;
|
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return;
|
||||||
musicPlayer.ClearQueue();
|
musicPlayer.ClearQueue();
|
||||||
await channel.SendMessageAsync($"🎵`Queue cleared!`").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"🎵 Queue cleared!").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,7 +530,7 @@ namespace NadekoBot.Modules.Music
|
|||||||
!int.TryParse(fromtoArr[1], out n2) || n1 < 1 || n2 < 1 || n1 == n2 ||
|
!int.TryParse(fromtoArr[1], out n2) || n1 < 1 || n2 < 1 || n1 == n2 ||
|
||||||
n1 > playlist.Count || n2 > playlist.Count)
|
n1 > playlist.Count || n2 > playlist.Count)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("`Invalid input.`").ConfigureAwait(false);
|
await channel.SendErrorAsync("Invalid input.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,9 +539,15 @@ namespace NadekoBot.Modules.Music
|
|||||||
var nn1 = n2 < n1 ? n1 : n1 - 1;
|
var nn1 = n2 < n1 ? n1 : n1 - 1;
|
||||||
playlist.RemoveAt(nn1);
|
playlist.RemoveAt(nn1);
|
||||||
|
|
||||||
await channel.SendMessageAsync($"🎵`Moved` {s.PrettyName} `from #{n1} to #{n2}`").ConfigureAwait(false);
|
var embed = new EmbedBuilder()
|
||||||
|
.WithTitle(s.SongInfo.Title.TrimTo(70))
|
||||||
|
.WithUrl(s.SongInfo.Query)
|
||||||
|
.WithAuthor(eab => eab.WithName("Song Moved").WithMusicIcon())
|
||||||
|
.AddField(fb => fb.WithName("**From Position**").WithValue($"#{n1}").WithIsInline(true))
|
||||||
|
.AddField(fb => fb.WithName("**To Position**").WithValue($"#{n2}").WithIsInline(true))
|
||||||
|
.WithFooter(ef => ef.WithText($"{s.PrettyProvider} | {s.QueuerName}"))
|
||||||
|
.WithOkColor();
|
||||||
|
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -478,11 +557,27 @@ namespace NadekoBot.Modules.Music
|
|||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
MusicPlayer musicPlayer;
|
MusicPlayer musicPlayer;
|
||||||
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer))
|
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer))
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
musicPlayer.MaxQueueSize = size;
|
musicPlayer.MaxQueueSize = size;
|
||||||
await channel.SendMessageAsync($"🎵 `Max queue set to {(size == 0 ? ("unlimited") : size + " tracks")}`");
|
await channel.SendConfirmAsync($"🎵 Max queue set to {(size == 0 ? ("unlimited") : size + " tracks")}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task SetMaxPlaytime(IUserMessage imsg, uint seconds)
|
||||||
|
{
|
||||||
|
if (seconds < 15 && seconds != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var channel = (ITextChannel)imsg.Channel;
|
||||||
|
MusicPlayer musicPlayer;
|
||||||
|
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer))
|
||||||
|
return;
|
||||||
|
musicPlayer.MaxPlaytimeSeconds = seconds;
|
||||||
|
if(seconds == 0)
|
||||||
|
await channel.SendConfirmAsync($"🎵 Max playtime has no limit now.");
|
||||||
|
else
|
||||||
|
await channel.SendConfirmAsync($"🎵 Max playtime set to {seconds} seconds.");
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -497,9 +592,16 @@ namespace NadekoBot.Modules.Music
|
|||||||
if (currentSong == null)
|
if (currentSong == null)
|
||||||
return;
|
return;
|
||||||
var currentValue = musicPlayer.ToggleRepeatSong();
|
var currentValue = musicPlayer.ToggleRepeatSong();
|
||||||
await channel.SendMessageAsync(currentValue ?
|
|
||||||
$"🎵🔂`Repeating track:`{currentSong.PrettyName}" :
|
if (currentValue)
|
||||||
$"🎵🔂`Current track repeat stopped.`")
|
await channel.EmbedAsync(new EmbedBuilder()
|
||||||
|
.WithOkColor()
|
||||||
|
.WithAuthor(eab => eab.WithMusicIcon().WithName("🔂 Repeating track"))
|
||||||
|
.WithDescription(currentSong.PrettyName)
|
||||||
|
.WithFooter(ef => ef.WithText(currentSong.PrettyInfo))
|
||||||
|
.Build()).ConfigureAwait(false);
|
||||||
|
else
|
||||||
|
await channel.SendConfirmAsync($"🔂 Current track repeat stopped.")
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,7 +614,7 @@ namespace NadekoBot.Modules.Music
|
|||||||
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer))
|
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer))
|
||||||
return;
|
return;
|
||||||
var currentValue = musicPlayer.ToggleRepeatPlaylist();
|
var currentValue = musicPlayer.ToggleRepeatPlaylist();
|
||||||
await channel.SendMessageAsync($"🎵🔁`Repeat playlist {(currentValue ? "enabled" : "disabled")}`").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"🔁 Repeat playlist {(currentValue ? "**enabled**." : "**disabled**.")}").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -526,7 +628,8 @@ namespace NadekoBot.Modules.Music
|
|||||||
|
|
||||||
var curSong = musicPlayer.CurrentSong;
|
var curSong = musicPlayer.CurrentSong;
|
||||||
var songs = musicPlayer.Playlist.Append(curSong)
|
var songs = musicPlayer.Playlist.Append(curSong)
|
||||||
.Select(s=> new PlaylistSong() {
|
.Select(s => new PlaylistSong()
|
||||||
|
{
|
||||||
Provider = s.SongInfo.Provider,
|
Provider = s.SongInfo.Provider,
|
||||||
ProviderType = s.SongInfo.ProviderType,
|
ProviderType = s.SongInfo.ProviderType,
|
||||||
Title = s.SongInfo.Title,
|
Title = s.SongInfo.Title,
|
||||||
@ -548,7 +651,7 @@ namespace NadekoBot.Modules.Music
|
|||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync(($"🎵 `Saved playlist as {name}.` `Id: {playlist.Id}`")).ConfigureAwait(false);
|
await channel.SendConfirmAsync(($"🎵 Saved playlist as **{name}**, ID: {playlist.Id}.")).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -565,14 +668,15 @@ namespace NadekoBot.Modules.Music
|
|||||||
|
|
||||||
if (mpl == null)
|
if (mpl == null)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("`Can't find playlist with that ID`").ConfigureAwait(false);
|
await channel.SendErrorAsync("Can't find playlist with that ID.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
IUserMessage msg = null;
|
IUserMessage msg = null;
|
||||||
try { msg = await channel.SendMessageAsync($"`Attempting to load {mpl.Songs.Count} songs...`").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
try { msg = await channel.SendMessageAsync($"🎶 Attempting to load **{mpl.Songs.Count}** songs...").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||||
|
|
||||||
|
var usr = (IGuildUser)umsg.Author;
|
||||||
foreach (var item in mpl.Songs)
|
foreach (var item in mpl.Songs)
|
||||||
{
|
{
|
||||||
var usr = (IGuildUser)umsg.Author;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await QueueSong(usr, channel, usr.VoiceChannel, item.Query, true, item.ProviderType).ConfigureAwait(false);
|
await QueueSong(usr, channel, usr.VoiceChannel, item.Query, true, item.ProviderType).ConfigureAwait(false);
|
||||||
@ -581,7 +685,7 @@ namespace NadekoBot.Modules.Music
|
|||||||
catch { break; }
|
catch { break; }
|
||||||
}
|
}
|
||||||
if (msg != null)
|
if (msg != null)
|
||||||
await msg.ModifyAsync(m => m.Content = $"`Done loading playlist {mpl.Name}.`").ConfigureAwait(false);
|
await msg.ModifyAsync(m => m.Content = $"✅ Done loading playlist **{mpl.Name}**.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -600,9 +704,12 @@ namespace NadekoBot.Modules.Music
|
|||||||
playlists = uow.MusicPlaylists.GetPlaylistsOnPage(num);
|
playlists = uow.MusicPlaylists.GetPlaylistsOnPage(num);
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync($@"`Page {num} of saved playlists`
|
var embed = new EmbedBuilder()
|
||||||
|
.WithAuthor(eab => eab.WithName($"Page {num} of Saved Playlists").WithMusicIcon())
|
||||||
|
.WithDescription(string.Join("\n", playlists.Select(r => $"`#{r.Id}` - **{r.Name}** by *{r.Author}* ({r.Songs.Count} songs)")))
|
||||||
|
.WithOkColor();
|
||||||
|
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
|
|
||||||
" + string.Join("\n", playlists.Select(r => $"`#{r.Id}` - `{r.Name}` by {r.Author} - **{r.Songs.Count}** songs"))).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo only author or owner
|
//todo only author or owner
|
||||||
@ -634,9 +741,9 @@ namespace NadekoBot.Modules.Music
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!success)
|
if (!success)
|
||||||
await channel.SendMessageAsync("Failed to delete that playlist. It either doesn't exist, or you are not its author.").ConfigureAwait(false);
|
await channel.SendErrorAsync("Failed to delete that playlist. It either doesn't exist, or you are not its author.").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync("`Playlist successfully deleted.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("🗑 Playlist successfully **deleted**.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -678,42 +785,7 @@ namespace NadekoBot.Modules.Music
|
|||||||
if (seconds.Length == 1)
|
if (seconds.Length == 1)
|
||||||
seconds = "0" + seconds;
|
seconds = "0" + seconds;
|
||||||
|
|
||||||
await channel.SendMessageAsync($"`Skipped to {minutes}:{seconds}`").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"Skipped to `{minutes}:{seconds}`").ConfigureAwait(false);
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
public async Task GetLink(IUserMessage umsg, int index = 0)
|
|
||||||
{
|
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
MusicPlayer musicPlayer;
|
|
||||||
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (index < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (index > 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
var selSong = musicPlayer.Playlist.DefaultIfEmpty(null).ElementAtOrDefault(index - 1);
|
|
||||||
if (selSong == null)
|
|
||||||
{
|
|
||||||
await channel.SendMessageAsync("Could not select song, likely wrong index");
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await channel.SendMessageAsync($"🎶`Selected song {selSong.SongInfo.Title}:` <{selSong.SongInfo.Query}>").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var curSong = musicPlayer.CurrentSong;
|
|
||||||
if (curSong == null)
|
|
||||||
return;
|
|
||||||
await channel.SendMessageAsync($"🎶`Current song:` <{curSong.SongInfo.Query}>").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -726,9 +798,9 @@ namespace NadekoBot.Modules.Music
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (!musicPlayer.ToggleAutoplay())
|
if (!musicPlayer.ToggleAutoplay())
|
||||||
await channel.SendMessageAsync("🎶`Autoplay disabled.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("❌ Autoplay disabled.").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync("🎶`Autoplay enabled.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("✅ Autoplay enabled.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task QueueSong(IGuildUser queuer, ITextChannel textCh, IVoiceChannel voiceCh, string query, bool silent = false, MusicType musicType = MusicType.Normal)
|
public static async Task QueueSong(IGuildUser queuer, ITextChannel textCh, IVoiceChannel voiceCh, string query, bool silent = false, MusicType musicType = MusicType.Normal)
|
||||||
@ -736,7 +808,7 @@ namespace NadekoBot.Modules.Music
|
|||||||
if (voiceCh == null || voiceCh.Guild != textCh.Guild)
|
if (voiceCh == null || voiceCh.Guild != textCh.Guild)
|
||||||
{
|
{
|
||||||
if (!silent)
|
if (!silent)
|
||||||
await textCh.SendMessageAsync("💢 You need to be in a voice channel on this server.\n If you are already in a voice channel, try rejoining.").ConfigureAwait(false);
|
await textCh.SendErrorAsync("💢 You need to be in a voice channel on this server.\n If you are already in a voice channel, try rejoining.").ConfigureAwait(false);
|
||||||
throw new ArgumentNullException(nameof(voiceCh));
|
throw new ArgumentNullException(nameof(voiceCh));
|
||||||
}
|
}
|
||||||
if (string.IsNullOrWhiteSpace(query) || query.Length < 3)
|
if (string.IsNullOrWhiteSpace(query) || query.Length < 3)
|
||||||
@ -747,43 +819,72 @@ namespace NadekoBot.Modules.Music
|
|||||||
float vol = 1;// SpecificConfigurations.Default.Of(server.Id).DefaultMusicVolume;
|
float vol = 1;// SpecificConfigurations.Default.Of(server.Id).DefaultMusicVolume;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
vol = uow.GuildConfigs.For(textCh.Guild.Id).DefaultMusicVolume;
|
vol = uow.GuildConfigs.For(textCh.Guild.Id, set => set).DefaultMusicVolume;
|
||||||
}
|
}
|
||||||
var mp = new MusicPlayer(voiceCh, vol);
|
var mp = new MusicPlayer(voiceCh, vol);
|
||||||
|
|
||||||
|
IUserMessage finishedMessage = null;
|
||||||
IUserMessage playingMessage = null;
|
|
||||||
IUserMessage lastFinishedMessage = null;
|
|
||||||
mp.OnCompleted += async (s, song) =>
|
mp.OnCompleted += async (s, song) =>
|
||||||
{
|
|
||||||
if (song.PrintStatusMessage)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (lastFinishedMessage != null)
|
if (finishedMessage != null)
|
||||||
await lastFinishedMessage.DeleteAsync().ConfigureAwait(false);
|
finishedMessage.DeleteAfter(0);
|
||||||
if (playingMessage != null)
|
|
||||||
await playingMessage.DeleteAsync().ConfigureAwait(false);
|
finishedMessage = await textCh.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||||
try { lastFinishedMessage = await textCh.SendMessageAsync($"🎵`Finished`{song.PrettyName}").ConfigureAwait(false); } catch { }
|
.WithAuthor(eab => eab.WithName("Finished Song").WithMusicIcon())
|
||||||
|
.WithDescription(song.PrettyName)
|
||||||
|
.WithFooter(ef => ef.WithText(song.PrettyInfo))
|
||||||
|
.Build())
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
if (mp.Autoplay && mp.Playlist.Count == 0 && song.SongInfo.Provider == "YouTube")
|
if (mp.Autoplay && mp.Playlist.Count == 0 && song.SongInfo.Provider == "YouTube")
|
||||||
{
|
{
|
||||||
await QueueSong(queuer.Guild.GetCurrentUser(), textCh, voiceCh, (await NadekoBot.Google.GetRelatedVideosAsync(song.SongInfo.Query, 4)).ToList().Shuffle().FirstOrDefault(), silent, musicType).ConfigureAwait(false);
|
await QueueSong(queuer.Guild.GetCurrentUser(), textCh, voiceCh, (await NadekoBot.Google.GetRelatedVideosAsync(song.SongInfo.Query, 4)).ToList().Shuffle().FirstOrDefault(), silent, musicType).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
}
|
|
||||||
};
|
};
|
||||||
mp.OnStarted += async (s, song) =>
|
IUserMessage playingMessage = null;
|
||||||
|
|
||||||
|
mp.OnStarted += async (player, song) =>
|
||||||
{
|
{
|
||||||
if (song.PrintStatusMessage)
|
try { await mp.UpdateSongDurationsAsync().ConfigureAwait(false); } catch { }
|
||||||
{
|
var sender = player as MusicPlayer;
|
||||||
var sender = s as MusicPlayer;
|
|
||||||
if (sender == null)
|
if (sender == null)
|
||||||
return;
|
return;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (playingMessage != null)
|
||||||
|
playingMessage.DeleteAfter(0);
|
||||||
|
|
||||||
var msgTxt = $"🎵`Playing`{song.PrettyName} `Vol: {(int)(sender.Volume * 100)}%`";
|
playingMessage = await textCh.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||||
try { playingMessage = await textCh.SendMessageAsync(msgTxt).ConfigureAwait(false); } catch { }
|
.WithAuthor(eab => eab.WithName("Playing Song").WithMusicIcon())
|
||||||
|
.WithDescription(song.PrettyName)
|
||||||
|
.WithFooter(ef => ef.WithText(song.PrettyInfo))
|
||||||
|
.Build())
|
||||||
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
catch { }
|
||||||
|
};
|
||||||
|
|
||||||
|
mp.OnPauseChanged += async (paused) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IUserMessage pauseMessage = null;
|
||||||
|
if (paused)
|
||||||
|
{
|
||||||
|
pauseMessage = await textCh.SendConfirmAsync("🎵 Music playback **paused**.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pauseMessage = await textCh.SendConfirmAsync("🎵 Music playback **resumed**.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
if (pauseMessage != null)
|
||||||
|
pauseMessage.DeleteAfter(15);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
};
|
};
|
||||||
return mp;
|
return mp;
|
||||||
});
|
});
|
||||||
@ -791,7 +892,7 @@ namespace NadekoBot.Modules.Music
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
musicPlayer.ThrowIfQueueFull();
|
musicPlayer.ThrowIfQueueFull();
|
||||||
resolvedSong = await Song.ResolveSong(query, musicType).ConfigureAwait(false);
|
resolvedSong = await SongHandler.ResolveSong(query, musicType).ConfigureAwait(false);
|
||||||
|
|
||||||
if (resolvedSong == null)
|
if (resolvedSong == null)
|
||||||
throw new SongNotFoundException();
|
throw new SongNotFoundException();
|
||||||
@ -800,24 +901,23 @@ namespace NadekoBot.Modules.Music
|
|||||||
}
|
}
|
||||||
catch (PlaylistFullException)
|
catch (PlaylistFullException)
|
||||||
{
|
{
|
||||||
try { await textCh.SendMessageAsync($"🎵 `Queue is full at {musicPlayer.MaxQueueSize}/{musicPlayer.MaxQueueSize}.` "); } catch { }
|
try { await textCh.SendConfirmAsync($"🎵 Queue is full at **{musicPlayer.MaxQueueSize}/{musicPlayer.MaxQueueSize}**."); } catch { }
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
if (!silent)
|
if (!silent)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var queuedMessage = await textCh.SendMessageAsync($"🎵`Queued`{resolvedSong.PrettyName} **at** `#{musicPlayer.Playlist.Count + 1}`").ConfigureAwait(false);
|
//var queuedMessage = await textCh.SendConfirmAsync($"🎵 Queued **{resolvedSong.SongInfo.Title}** at `#{musicPlayer.Playlist.Count + 1}`").ConfigureAwait(false);
|
||||||
var t = Task.Run(async () =>
|
var queuedMessage = await textCh.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||||
{
|
.WithAuthor(eab => eab.WithName("Queued Song #" + (musicPlayer.Playlist.Count + 1)).WithMusicIcon())
|
||||||
try
|
.WithDescription($"{resolvedSong.PrettyName}\nQueue ")
|
||||||
{
|
.WithThumbnail(tn => tn.Url = resolvedSong.Thumbnail)
|
||||||
await Task.Delay(10000).ConfigureAwait(false);
|
.WithFooter(ef => ef.WithText(resolvedSong.PrettyProvider))
|
||||||
|
.Build())
|
||||||
await queuedMessage.DeleteAsync().ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
if (queuedMessage != null)
|
||||||
catch { }
|
queuedMessage.DeleteAfter(10);
|
||||||
}).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
catch { } // if queued message sending fails, don't attempt to delete it
|
catch { } // if queued message sending fails, don't attempt to delete it
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,14 @@ using System.Net.Http;
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.NSFW
|
namespace NadekoBot.Modules.NSFW
|
||||||
{
|
{
|
||||||
[NadekoModule("NSFW", "~")]
|
[NadekoModule("NSFW", "~")]
|
||||||
public class NSFW : DiscordModule
|
public class NSFW : DiscordModule
|
||||||
{
|
{
|
||||||
public NSFW(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
|
public NSFW() : base()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ namespace NadekoBot.Modules.NSFW
|
|||||||
|
|
||||||
var rng = new NadekoRandom();
|
var rng = new NadekoRandom();
|
||||||
Task<string> provider = Task.FromResult("");
|
Task<string> provider = Task.FromResult("");
|
||||||
switch (rng.Next(0,4))
|
switch (rng.Next(0, 4))
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
provider = GetDanbooruImageLink(tag);
|
provider = GetDanbooruImageLink(tag);
|
||||||
@ -51,11 +52,12 @@ namespace NadekoBot.Modules.NSFW
|
|||||||
}
|
}
|
||||||
var link = await provider.ConfigureAwait(false);
|
var link = await provider.ConfigureAwait(false);
|
||||||
if (string.IsNullOrWhiteSpace(link))
|
if (string.IsNullOrWhiteSpace(link))
|
||||||
await channel.SendMessageAsync("Search yielded no results ;(").ConfigureAwait(false);
|
await channel.SendErrorAsync("No results found.").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync(link).ConfigureAwait(false);
|
await channel.SendMessageAsync(link).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task HentaiBomb(IUserMessage umsg, [Remainder] string tag = null)
|
public async Task HentaiBomb(IUserMessage umsg, [Remainder] string tag = null)
|
||||||
@ -72,45 +74,13 @@ namespace NadekoBot.Modules.NSFW
|
|||||||
|
|
||||||
if (links.All(l => l == null))
|
if (links.All(l => l == null))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("`No results.`").ConfigureAwait(false);
|
await channel.SendErrorAsync("No results found.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync(String.Join("\n\n", links)).ConfigureAwait(false);
|
await channel.SendMessageAsync(String.Join("\n\n", links)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<string> GetYandereImageLink(string tag)
|
|
||||||
{
|
|
||||||
var rng = new NadekoRandom();
|
|
||||||
var url =
|
|
||||||
$"https://yande.re/post.xml?" +
|
|
||||||
$"limit=25" +
|
|
||||||
$"&page={rng.Next(0, 15)}" +
|
|
||||||
$"&tags={tag.Replace(" ", "_")}";
|
|
||||||
using (var http = new HttpClient())
|
|
||||||
{
|
|
||||||
var webpage = await http.GetStringAsync(url).ConfigureAwait(false);
|
|
||||||
var matches = Regex.Matches(webpage, "file_url=\"(?<url>.*?)\"");
|
|
||||||
//var rating = Regex.Matches(webpage, "rating=\"(?<rate>.*?)\"");
|
|
||||||
if (matches.Count == 0)
|
|
||||||
return null;
|
|
||||||
return matches[rng.Next(0, matches.Count)].Groups["url"].Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
public async Task Yandere(IUserMessage umsg, [Remainder] string tag = null)
|
|
||||||
{
|
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
|
|
||||||
tag = tag?.Trim() ?? "";
|
|
||||||
var link = await GetYandereImageLink(tag).ConfigureAwait(false);
|
|
||||||
if (string.IsNullOrWhiteSpace(link))
|
|
||||||
await channel.SendMessageAsync("Search yielded no results ;(").ConfigureAwait(false);
|
|
||||||
else
|
|
||||||
await channel.SendMessageAsync(link).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
@ -119,54 +89,38 @@ namespace NadekoBot.Modules.NSFW
|
|||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
tag = tag?.Trim() ?? "";
|
tag = tag?.Trim() ?? "";
|
||||||
var link = await GetDanbooruImageLink(tag).ConfigureAwait(false);
|
|
||||||
if (string.IsNullOrWhiteSpace(link))
|
var url = await GetDanbooruImageLink(tag).ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync("Search yielded no results ;(").ConfigureAwait(false);
|
|
||||||
|
if (url == null)
|
||||||
|
await channel.SendErrorAsync(umsg.Author.Mention + " No results.");
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync(link).ConfigureAwait(false);
|
await channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||||
|
.WithDescription(umsg.Author.Mention + " " + tag)
|
||||||
|
.WithImageUrl(url)
|
||||||
|
.WithFooter(efb => efb.WithText("Danbooru"))
|
||||||
|
.Build()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task Konachan(IUserMessage umsg, [Remainder] string tag = null)
|
public Task Yandere(IUserMessage umsg, [Remainder] string tag = null)
|
||||||
{
|
=> Searches.Searches.InternalDapiCommand(umsg, tag, Searches.Searches.DapiSearchType.Yandere);
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
|
|
||||||
tag = tag?.Trim() ?? "";
|
|
||||||
var link = await GetKonachanImageLink(tag).ConfigureAwait(false);
|
|
||||||
if (string.IsNullOrWhiteSpace(link))
|
|
||||||
await channel.SendMessageAsync("Search yielded no results ;(").ConfigureAwait(false);
|
|
||||||
else
|
|
||||||
await channel.SendMessageAsync(link).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task Gelbooru(IUserMessage umsg, [Remainder] string tag = null)
|
public Task Konachan(IUserMessage umsg, [Remainder] string tag = null)
|
||||||
{
|
=> Searches.Searches.InternalDapiCommand(umsg, tag, Searches.Searches.DapiSearchType.Konachan);
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
|
|
||||||
tag = tag?.Trim() ?? "";
|
|
||||||
var link = await GetGelbooruImageLink(tag).ConfigureAwait(false);
|
|
||||||
if (string.IsNullOrWhiteSpace(link))
|
|
||||||
await channel.SendMessageAsync("Search yielded no results ;(").ConfigureAwait(false);
|
|
||||||
else
|
|
||||||
await channel.SendMessageAsync(link).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task Rule34(IUserMessage umsg, [Remainder] string tag = null)
|
public Task Gelbooru(IUserMessage umsg, [Remainder] string tag = null)
|
||||||
{
|
=> Searches.Searches.InternalDapiCommand(umsg, tag, Searches.Searches.DapiSearchType.Gelbooru);
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
|
|
||||||
tag = tag?.Trim() ?? "";
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
var link = await GetRule34ImageLink(tag).ConfigureAwait(false);
|
[RequireContext(ContextType.Guild)]
|
||||||
if (string.IsNullOrWhiteSpace(link))
|
public Task Rule34(IUserMessage umsg, [Remainder] string tag = null)
|
||||||
await channel.SendMessageAsync("Search yielded no results ;(").ConfigureAwait(false);
|
=> Searches.Searches.InternalDapiCommand(umsg, tag, Searches.Searches.DapiSearchType.Rule34);
|
||||||
else
|
|
||||||
await channel.SendMessageAsync(link).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
@ -175,11 +129,17 @@ namespace NadekoBot.Modules.NSFW
|
|||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
tag = tag?.Trim() ?? "";
|
tag = tag?.Trim() ?? "";
|
||||||
var link = await GetE621ImageLink(tag).ConfigureAwait(false);
|
|
||||||
if (string.IsNullOrWhiteSpace(link))
|
var url = await GetE621ImageLink(tag).ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync("Search yielded no results ;(").ConfigureAwait(false);
|
|
||||||
|
if (url == null)
|
||||||
|
await channel.SendErrorAsync(umsg.Author.Mention + " No results.");
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync(link).ConfigureAwait(false);
|
await channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||||
|
.WithDescription(umsg.Author.Mention + " " + tag)
|
||||||
|
.WithImageUrl(url)
|
||||||
|
.WithFooter(efb => efb.WithText("e621"))
|
||||||
|
.Build()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -201,13 +161,13 @@ namespace NadekoBot.Modules.NSFW
|
|||||||
JToken obj;
|
JToken obj;
|
||||||
using (var http = new HttpClient())
|
using (var http = new HttpClient())
|
||||||
{
|
{
|
||||||
obj = JArray.Parse(await http.GetStringAsync($"http://api.oboobs.ru/boobs/{ new NadekoRandom().Next(0, 9880) }").ConfigureAwait(false))[0];
|
obj = JArray.Parse(await http.GetStringAsync($"http://api.oboobs.ru/boobs/{ new NadekoRandom().Next(0, 10229) }").ConfigureAwait(false))[0];
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"http://media.oboobs.ru/{ obj["preview"].ToString() }").ConfigureAwait(false);
|
await channel.SendMessageAsync($"http://media.oboobs.ru/{ obj["preview"].ToString() }").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"💢 {ex.Message}").ConfigureAwait(false);
|
await channel.SendErrorAsync(ex.Message).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,109 +182,71 @@ namespace NadekoBot.Modules.NSFW
|
|||||||
JToken obj;
|
JToken obj;
|
||||||
using (var http = new HttpClient())
|
using (var http = new HttpClient())
|
||||||
{
|
{
|
||||||
obj = JArray.Parse(await http.GetStringAsync($"http://api.obutts.ru/butts/{ new NadekoRandom().Next(0, 3873) }").ConfigureAwait(false))[0];
|
obj = JArray.Parse(await http.GetStringAsync($"http://api.obutts.ru/butts/{ new NadekoRandom().Next(0, 4222) }").ConfigureAwait(false))[0];
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"http://media.obutts.ru/{ obj["preview"].ToString() }").ConfigureAwait(false);
|
await channel.SendMessageAsync($"http://media.obutts.ru/{ obj["preview"].ToString() }").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"💢 {ex.Message}").ConfigureAwait(false);
|
await channel.SendErrorAsync(ex.Message).ConfigureAwait(false);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<string> GetKonachanImageLink(string tag)
|
|
||||||
{
|
|
||||||
var rng = new NadekoRandom();
|
|
||||||
|
|
||||||
var link = $"http://konachan.com/post?" +
|
|
||||||
$"page={rng.Next(0, 5)}";
|
|
||||||
if (!string.IsNullOrWhiteSpace(tag))
|
|
||||||
link += $"&tags={tag.Replace(" ", "_")}";
|
|
||||||
using (var http = new HttpClient())
|
|
||||||
{
|
|
||||||
var webpage = await http.GetStringAsync(link).ConfigureAwait(false);
|
|
||||||
var matches = Regex.Matches(webpage, "<a class=\"directlink largeimg\" href=\"(?<ll>.*?)\">");
|
|
||||||
|
|
||||||
if (matches.Count == 0)
|
|
||||||
return null;
|
|
||||||
return matches[rng.Next(0, matches.Count)].Groups["ll"].Value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<string> GetDanbooruImageLink(string tag)
|
public static async Task<string> GetDanbooruImageLink(string tag)
|
||||||
{
|
|
||||||
var rng = new NadekoRandom();
|
|
||||||
|
|
||||||
if (tag == "loli") //loli doesn't work for some reason atm
|
|
||||||
tag = "flat_chest";
|
|
||||||
|
|
||||||
var link = $"http://danbooru.donmai.us/posts?" +
|
|
||||||
$"page={rng.Next(0, 15)}";
|
|
||||||
if (!string.IsNullOrWhiteSpace(tag))
|
|
||||||
link += $"&tags={tag.Replace(" ", "_")}";
|
|
||||||
using (var http = new HttpClient())
|
|
||||||
{
|
|
||||||
var webpage = await http.GetStringAsync(link).ConfigureAwait(false);
|
|
||||||
var matches = Regex.Matches(webpage, "data-large-file-url=\"(?<id>.*?)\"");
|
|
||||||
|
|
||||||
if (matches.Count == 0)
|
|
||||||
return null;
|
|
||||||
return $"http://danbooru.donmai.us" +
|
|
||||||
$"{matches[rng.Next(0, matches.Count)].Groups["id"].Value}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<string> GetGelbooruImageLink(string tag)
|
|
||||||
{
|
|
||||||
using (var http = new HttpClient())
|
|
||||||
{
|
|
||||||
http.AddFakeHeaders();
|
|
||||||
|
|
||||||
var webpage = await http.GetStringAsync("http://gelbooru.com/index.php?page=dapi&s=post&q=index&limit=100&tags="+ tag.Replace(" ", "_")).ConfigureAwait(false);
|
|
||||||
var matches = Regex.Matches(webpage, "file_url=\"(?<url>.*?)\"");
|
|
||||||
if (matches.Count == 0)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var rng = new NadekoRandom();
|
|
||||||
var match = matches[rng.Next(0, matches.Count)];
|
|
||||||
return matches[rng.Next(0, matches.Count)].Groups["url"].Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<string> GetRule34ImageLink(string tag)
|
|
||||||
{
|
|
||||||
var rng = new NadekoRandom();
|
|
||||||
var url =
|
|
||||||
$"http://rule34.xxx/index.php?page=dapi&s=post&q=index&limit=100&tags={tag.Replace(" ", "_")}";
|
|
||||||
using (var http = new HttpClient())
|
|
||||||
{
|
|
||||||
var webpage = await http.GetStringAsync(url).ConfigureAwait(false);
|
|
||||||
var matches = Regex.Matches(webpage, "file_url=\"(?<url>.*?)\"");
|
|
||||||
if (matches.Count == 0)
|
|
||||||
return null;
|
|
||||||
var match = matches[rng.Next(0, matches.Count)];
|
|
||||||
return "http:" + matches[rng.Next(0, matches.Count)].Groups["url"].Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static async Task<string> GetE621ImageLink(string tags)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var http = new HttpClient())
|
using (var http = new HttpClient())
|
||||||
{
|
{
|
||||||
http.AddFakeHeaders();
|
http.AddFakeHeaders();
|
||||||
var data = await http.GetStreamAsync("http://e621.net/post/index.xml?tags=" + Uri.EscapeUriString(tags) + "%20order:random&limit=1");
|
var data = await http.GetStreamAsync("https://danbooru.donmai.us/posts.xml?limit=100&tags=" + tag);
|
||||||
var doc = XDocument.Load(data);
|
var doc = new XmlDocument();
|
||||||
return doc.Descendants("file_url").FirstOrDefault().Value;
|
doc.Load(data);
|
||||||
|
var nodes = doc.GetElementsByTagName("file-url");
|
||||||
|
|
||||||
|
var node = nodes[new NadekoRandom().Next(0, nodes.Count)];
|
||||||
|
return "https://danbooru.donmai.us" + node.InnerText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch
|
||||||
{
|
{
|
||||||
Console.WriteLine("Error in e621 search: \n" + ex);
|
return null;
|
||||||
return "Error, do you have too many tags?";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static async Task<string> GetE621ImageLink(string tag)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var http = new HttpClient())
|
||||||
|
{
|
||||||
|
http.AddFakeHeaders();
|
||||||
|
var data = await http.GetStreamAsync("http://e621.net/post/index.xml?tags=" + tag);
|
||||||
|
var doc = new XmlDocument();
|
||||||
|
doc.Load(data);
|
||||||
|
var nodes = doc.GetElementsByTagName("file_url");
|
||||||
|
|
||||||
|
var node = nodes[new NadekoRandom().Next(0, nodes.Count)];
|
||||||
|
return node.InnerText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Task<string> GetYandereImageLink(string tag) =>
|
||||||
|
Searches.Searches.InternalDapiSearch(tag, Searches.Searches.DapiSearchType.Yandere);
|
||||||
|
|
||||||
|
public static Task<string> GetKonachanImageLink(string tag) =>
|
||||||
|
Searches.Searches.InternalDapiSearch(tag, Searches.Searches.DapiSearchType.Konachan);
|
||||||
|
|
||||||
|
public static Task<string> GetGelbooruImageLink(string tag) =>
|
||||||
|
Searches.Searches.InternalDapiSearch(tag, Searches.Searches.DapiSearchType.Gelbooru);
|
||||||
|
|
||||||
|
public static Task<string> GetRule34ImageLink(string tag) =>
|
||||||
|
Searches.Searches.InternalDapiSearch(tag, Searches.Searches.DapiSearchType.Rule34);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Modules.Games.Trivia;
|
using NadekoBot.Modules.Games.Trivia;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
@ -104,7 +105,10 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync(":ok:").ConfigureAwait(false);
|
if(action == AddRemove.Add)
|
||||||
|
await channel.SendConfirmAsync($"Blacklisted a `{type}` with id `{id}`").ConfigureAwait(false);
|
||||||
|
else
|
||||||
|
await channel.SendConfirmAsync($"Unblacklisted a `{type}` with id `{id}`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
@ -23,7 +24,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
public class CmdCdsCommands
|
public class CmdCdsCommands
|
||||||
{
|
{
|
||||||
public static ConcurrentDictionary<ulong, ConcurrentHashSet<CommandCooldown>> commandCooldowns { get; }
|
public static ConcurrentDictionary<ulong, ConcurrentHashSet<CommandCooldown>> commandCooldowns { get; }
|
||||||
private static ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>> activeCooldowns = new ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>>();
|
private static ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>> activeCooldowns { get; } = new ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>>();
|
||||||
|
|
||||||
static CmdCdsCommands()
|
static CmdCdsCommands()
|
||||||
{
|
{
|
||||||
@ -40,13 +41,13 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
var channel = (ITextChannel)imsg.Channel;
|
var channel = (ITextChannel)imsg.Channel;
|
||||||
if (secs < 0 || secs > 3600)
|
if (secs < 0 || secs > 3600)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("⚠️ Invalid second parameter. (Must be a number between 0 and 3600)").ConfigureAwait(false);
|
await channel.SendErrorAsync("Invalid second parameter. (Must be a number between 0 and 3600)").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var config = uow.GuildConfigs.For(channel.Guild.Id);
|
var config = uow.GuildConfigs.For(channel.Guild.Id, set => set.Include(gc => gc.CommandCooldowns));
|
||||||
var localSet = commandCooldowns.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CommandCooldown>());
|
var localSet = commandCooldowns.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CommandCooldown>());
|
||||||
|
|
||||||
config.CommandCooldowns.RemoveWhere(cc => cc.CommandName == command.Text.ToLowerInvariant());
|
config.CommandCooldowns.RemoveWhere(cc => cc.CommandName == command.Text.ToLowerInvariant());
|
||||||
@ -67,10 +68,14 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
{
|
{
|
||||||
var activeCds = activeCooldowns.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<ActiveCooldown>());
|
var activeCds = activeCooldowns.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<ActiveCooldown>());
|
||||||
activeCds.RemoveWhere(ac => ac.Command == command.Text.ToLowerInvariant());
|
activeCds.RemoveWhere(ac => ac.Command == command.Text.ToLowerInvariant());
|
||||||
await channel.SendMessageAsync($"🚮 Command **{command}** has no coooldown now and all existing cooldowns have been cleared.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"🚮 Command **{command}** has no coooldown now and all existing cooldowns have been cleared.")
|
||||||
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync($"✅ Command **{command}** now has a **{secs} {(secs == 1 ? "second" : "seconds")}** cooldown.").ConfigureAwait(false);
|
{
|
||||||
|
await channel.SendConfirmAsync($"✅ Command **{command}** now has a **{secs} {"seconds".SnPl(secs)}** cooldown.")
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -81,7 +86,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
var localSet = commandCooldowns.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CommandCooldown>());
|
var localSet = commandCooldowns.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CommandCooldown>());
|
||||||
|
|
||||||
if (!localSet.Any())
|
if (!localSet.Any())
|
||||||
await channel.SendMessageAsync("ℹ️ `No command cooldowns set.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("ℹ️ `No command cooldowns set.`").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendTableAsync("", localSet.Select(c => c.CommandName + ": " + c.Seconds + " secs"), s => $"{s,-30}", 2).ConfigureAwait(false);
|
await channel.SendTableAsync("", localSet.Select(c => c.CommandName + ": " + c.Seconds + " secs"), s => $"{s,-30}", 2).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -13,14 +15,14 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
[Group]
|
[Group]
|
||||||
public class FilterCommands
|
public class FilterCommands
|
||||||
{
|
{
|
||||||
public static ConcurrentHashSet<ulong> InviteFilteringChannels { get; set; }
|
public static ConcurrentHashSet<ulong> InviteFilteringChannels { get; }
|
||||||
public static ConcurrentHashSet<ulong> InviteFilteringServers { get; set; }
|
public static ConcurrentHashSet<ulong> InviteFilteringServers { get; }
|
||||||
|
|
||||||
//serverid, filteredwords
|
//serverid, filteredwords
|
||||||
private static ConcurrentDictionary<ulong, ConcurrentHashSet<string>> ServerFilteredWords { get; set; }
|
private static ConcurrentDictionary<ulong, ConcurrentHashSet<string>> ServerFilteredWords { get; }
|
||||||
|
|
||||||
public static ConcurrentHashSet<ulong> WordFilteringChannels { get; set; }
|
public static ConcurrentHashSet<ulong> WordFilteringChannels { get; }
|
||||||
public static ConcurrentHashSet<ulong> WordFilteringServers { get; set; }
|
public static ConcurrentHashSet<ulong> WordFilteringServers { get; }
|
||||||
|
|
||||||
public static ConcurrentHashSet<string> FilteredWordsForChannel(ulong channelId, ulong guildId)
|
public static ConcurrentHashSet<string> FilteredWordsForChannel(ulong channelId, ulong guildId)
|
||||||
{
|
{
|
||||||
@ -68,7 +70,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
bool enabled;
|
bool enabled;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var config = uow.GuildConfigs.For(channel.Guild.Id);
|
var config = uow.GuildConfigs.For(channel.Guild.Id, set => set);
|
||||||
enabled = config.FilterInvites = !config.FilterInvites;
|
enabled = config.FilterInvites = !config.FilterInvites;
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -76,12 +78,12 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
if (enabled)
|
if (enabled)
|
||||||
{
|
{
|
||||||
InviteFilteringServers.Add(channel.Guild.Id);
|
InviteFilteringServers.Add(channel.Guild.Id);
|
||||||
await channel.SendMessageAsync("✅ `Invite filtering enabled on this server.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("Invite filtering enabled on this server.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
InviteFilteringServers.TryRemove(channel.Guild.Id);
|
InviteFilteringServers.TryRemove(channel.Guild.Id);
|
||||||
await channel.SendMessageAsync("ℹ️ `Invite filtering disabled on this server.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("Invite filtering disabled on this server.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +96,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
int removed;
|
int removed;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var config = uow.GuildConfigs.For(channel.Guild.Id);
|
var config = uow.GuildConfigs.For(channel.Guild.Id, set => set.Include(gc => gc.FilterInvitesChannelIds));
|
||||||
removed = config.FilterInvitesChannelIds.RemoveWhere(fc => fc.ChannelId == channel.Id);
|
removed = config.FilterInvitesChannelIds.RemoveWhere(fc => fc.ChannelId == channel.Id);
|
||||||
if (removed == 0)
|
if (removed == 0)
|
||||||
{
|
{
|
||||||
@ -109,12 +111,12 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
if (removed == 0)
|
if (removed == 0)
|
||||||
{
|
{
|
||||||
InviteFilteringChannels.Add(channel.Id);
|
InviteFilteringChannels.Add(channel.Id);
|
||||||
await channel.SendMessageAsync("✅ `Invite filtering enabled on this channel.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("Invite filtering enabled on this channel.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
InviteFilteringChannels.TryRemove(channel.Id);
|
InviteFilteringChannels.TryRemove(channel.Id);
|
||||||
await channel.SendMessageAsync("ℹ️ `Invite filtering disabled on this channel.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("Invite filtering disabled on this channel.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +129,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
bool enabled;
|
bool enabled;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var config = uow.GuildConfigs.For(channel.Guild.Id);
|
var config = uow.GuildConfigs.For(channel.Guild.Id, set => set);
|
||||||
enabled = config.FilterWords = !config.FilterWords;
|
enabled = config.FilterWords = !config.FilterWords;
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -135,12 +137,12 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
if (enabled)
|
if (enabled)
|
||||||
{
|
{
|
||||||
WordFilteringServers.Add(channel.Guild.Id);
|
WordFilteringServers.Add(channel.Guild.Id);
|
||||||
await channel.SendMessageAsync("✅ `Word filtering enabled on this server.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("Word filtering enabled on this server.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WordFilteringServers.TryRemove(channel.Guild.Id);
|
WordFilteringServers.TryRemove(channel.Guild.Id);
|
||||||
await channel.SendMessageAsync("ℹ️ `Word filtering disabled on this server.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("Word filtering disabled on this server.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +155,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
int removed;
|
int removed;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var config = uow.GuildConfigs.For(channel.Guild.Id);
|
var config = uow.GuildConfigs.For(channel.Guild.Id, set => set.Include(gc => gc.FilterWordsChannelIds));
|
||||||
removed = config.FilterWordsChannelIds.RemoveWhere(fc => fc.ChannelId == channel.Id);
|
removed = config.FilterWordsChannelIds.RemoveWhere(fc => fc.ChannelId == channel.Id);
|
||||||
if (removed == 0)
|
if (removed == 0)
|
||||||
{
|
{
|
||||||
@ -168,12 +170,12 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
if (removed == 0)
|
if (removed == 0)
|
||||||
{
|
{
|
||||||
WordFilteringChannels.Add(channel.Id);
|
WordFilteringChannels.Add(channel.Id);
|
||||||
await channel.SendMessageAsync("✅ `Word filtering enabled on this channel.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("Word filtering enabled on this channel.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WordFilteringChannels.TryRemove(channel.Id);
|
WordFilteringChannels.TryRemove(channel.Id);
|
||||||
await channel.SendMessageAsync("ℹ️ `Word filtering disabled on this channel.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync("Word filtering disabled on this channel.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +193,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
int removed;
|
int removed;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var config = uow.GuildConfigs.For(channel.Guild.Id);
|
var config = uow.GuildConfigs.For(channel.Guild.Id, set => set.Include(gc => gc.FilteredWords));
|
||||||
|
|
||||||
removed = config.FilteredWords.RemoveWhere(fw => fw.Word == word);
|
removed = config.FilteredWords.RemoveWhere(fw => fw.Word == word);
|
||||||
|
|
||||||
@ -206,13 +208,13 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
if (removed == 0)
|
if (removed == 0)
|
||||||
{
|
{
|
||||||
filteredWords.Add(word);
|
filteredWords.Add(word);
|
||||||
await channel.SendMessageAsync($"✅ Word `{word}` successfully added to the list of filtered words.")
|
await channel.SendConfirmAsync($"Word `{word}` successfully added to the list of filtered words.")
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
filteredWords.TryRemove(word);
|
filteredWords.TryRemove(word);
|
||||||
await channel.SendMessageAsync($"ℹ️ Word `{word}` removed from the list of filtered words.")
|
await channel.SendConfirmAsync($"Word `{word}` removed from the list of filtered words.")
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -226,7 +228,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
ConcurrentHashSet<string> filteredWords;
|
ConcurrentHashSet<string> filteredWords;
|
||||||
ServerFilteredWords.TryGetValue(channel.Guild.Id, out filteredWords);
|
ServerFilteredWords.TryGetValue(channel.Guild.Id, out filteredWords);
|
||||||
|
|
||||||
await channel.SendMessageAsync($"ℹ️ `List of banned words:`\n" + string.Join(",\n", filteredWords))
|
await channel.SendConfirmAsync($"List of filtered words", string.Join("\n", filteredWords))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ using NadekoBot.Services;
|
|||||||
using Discord;
|
using Discord;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Permissions
|
namespace NadekoBot.Modules.Permissions
|
||||||
{
|
{
|
||||||
@ -21,7 +22,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
}
|
}
|
||||||
|
|
||||||
//guildid, root permission
|
//guildid, root permission
|
||||||
public static ConcurrentDictionary<ulong, PermissionCache> Cache;
|
public static ConcurrentDictionary<ulong, PermissionCache> Cache { get; }
|
||||||
|
|
||||||
static Permissions()
|
static Permissions()
|
||||||
{
|
{
|
||||||
@ -39,7 +40,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Permissions(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
|
public Permissions() : base()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +52,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
|
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var config = uow.GuildConfigs.For(channel.Guild.Id);
|
var config = uow.GuildConfigs.For(channel.Guild.Id, set => set);
|
||||||
config.VerbosePermissions = action.Value;
|
config.VerbosePermissions = action.Value;
|
||||||
Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache()
|
Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache()
|
||||||
{
|
{
|
||||||
@ -62,7 +63,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync("ℹ️ I will " + (action.Value ? "now" : "no longer") + " show permission warnings.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("ℹ️ I will " + (action.Value ? "now" : "no longer") + " show permission warnings.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -72,10 +73,10 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
var channel = (ITextChannel)msg.Channel;
|
var channel = (ITextChannel)msg.Channel;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var config = uow.GuildConfigs.For(channel.Guild.Id);
|
var config = uow.GuildConfigs.For(channel.Guild.Id, set => set);
|
||||||
if (role == null)
|
if (role == null)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"ℹ️ Current permission role is **{config.PermissionRole}**.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"ℹ️ Current permission role is **{config.PermissionRole}**.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -90,7 +91,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync($"✅ Users now require **{role.Name}** role in order to edit permissions.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"Users now require **{role.Name}** role in order to edit permissions.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -109,9 +110,6 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
toSend = Format.Code($"📄 Permissions page {page}") + "\n\n" + String.Join("\n", perms.AsEnumerable().Skip((page - 1) * 20).Take(20).Select(p => $"`{(i++)}.` {(p.Next == null ? Format.Bold(p.GetCommand(channel.Guild) + " [uneditable]") : (p.GetCommand(channel.Guild)))}"));
|
toSend = Format.Code($"📄 Permissions page {page}") + "\n\n" + String.Join("\n", perms.AsEnumerable().Skip((page - 1) * 20).Take(20).Select(p => $"`{(i++)}.` {(p.Next == null ? Format.Bold(p.GetCommand(channel.Guild) + " [uneditable]") : (p.GetCommand(channel.Guild)))}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(toSend))
|
|
||||||
await channel.SendMessageAsync("❗️`No permissions set.`").ConfigureAwait(false);
|
|
||||||
else
|
|
||||||
await channel.SendMessageAsync(toSend).ConfigureAwait(false);
|
await channel.SendMessageAsync(toSend).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,11 +154,11 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
uow2._context.SaveChanges();
|
uow2._context.SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync($"✅ {imsg.Author.Mention} removed permission **{p.GetCommand(channel.Guild)}** from position #{index + 1}.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"✅ {imsg.Author.Mention} removed permission **{p.GetCommand(channel.Guild)}** from position #{index + 1}.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (ArgumentOutOfRangeException)
|
catch (ArgumentOutOfRangeException)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("❗️`No command on that index found.`").ConfigureAwait(false);
|
await channel.SendErrorAsync("❗️`No command on that index found.`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,13 +206,13 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
{
|
{
|
||||||
if (!fromFound)
|
if (!fromFound)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"❗️`Can't find permission at index `#{++from}`").ConfigureAwait(false);
|
await channel.SendErrorAsync($"Can't find permission at index `#{++from}`").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!toFound)
|
if (!toFound)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"❗️`Can't find permission at index `#{++to}`").ConfigureAwait(false);
|
await channel.SendErrorAsync($"Can't find permission at index `#{++to}`").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -264,14 +262,14 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"✅ `Moved permission:` \"{fromPerm.GetCommand(channel.Guild)}\" `from #{++from} to #{++to}.`").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"`Moved permission:` \"{fromPerm.GetCommand(channel.Guild)}\" `from #{++from} to #{++to}.`").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (Exception e) when (e is ArgumentOutOfRangeException || e is IndexOutOfRangeException)
|
catch (Exception e) when (e is ArgumentOutOfRangeException || e is IndexOutOfRangeException)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync("`Invalid index(es) specified.`").ConfigureAwait(false);
|
await channel.SendErrorAsync("`Invalid index(es) specified.`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -300,7 +298,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
|
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `{command.Text}` command on this server.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `{command.Text}` command on this server.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -328,7 +326,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of **`{module.Name}`** module on this server.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of **`{module.Name}`** module on this server.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -356,7 +354,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `{command.Text}` command for `{user}` user.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `{command.Text}` command for `{user}` user.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -384,7 +382,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `{module.Name}` module for `{user}` user.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `{module.Name}` module for `{user}` user.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -412,7 +410,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `{command.Text}` command for `{role}` role.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `{command.Text}` command for `{role}` role.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -440,7 +438,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `{module.Name}` module for `{role}` role.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `{module.Name}` module for `{role}` role.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -471,9 +469,9 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
Console.WriteLine(ex);
|
_log.Error(ex);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `{command.Text}` command for `{chnl}` channel.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `{command.Text}` command for `{chnl}` channel.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -501,7 +499,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `{module.Name}` module for `{chnl}` channel.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `{module.Name}` module for `{chnl}` channel.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -529,7 +527,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `ALL MODULES` for `{chnl}` channel.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `ALL MODULES` for `{chnl}` channel.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -557,7 +555,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `ALL MODULES` for `{role}` role.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `ALL MODULES` for `{role}` role.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -585,7 +583,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `ALL MODULES` for `{user}` user.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `ALL MODULES` for `{user}` user.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -624,7 +622,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `ALL MODULES` on this server.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{(action.Value ? "✅ Allowed" : "🆗 Denied")} usage of `ALL MODULES` on this server.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
src/NadekoBot/Modules/Pokemon/PokeStats.cs
Normal file
15
src/NadekoBot/Modules/Pokemon/PokeStats.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Pokemon
|
||||||
|
{
|
||||||
|
class PokeStats
|
||||||
|
{
|
||||||
|
//Health left
|
||||||
|
public int Hp { get; set; } = 500;
|
||||||
|
public int MaxHp { get; } = 500;
|
||||||
|
//Amount of moves made since last time attacked
|
||||||
|
public int MovesMade { get; set; } = 0;
|
||||||
|
//Last people attacked
|
||||||
|
public List<ulong> LastAttacked { get; set; } = new List<ulong>();
|
||||||
|
}
|
||||||
|
}
|
375
src/NadekoBot/Modules/Pokemon/Pokemon.cs
Normal file
375
src/NadekoBot/Modules/Pokemon/Pokemon.cs
Normal file
@ -0,0 +1,375 @@
|
|||||||
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
using System.Linq;
|
||||||
|
using NadekoBot.Services;
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord;
|
||||||
|
using NLog;
|
||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using static NadekoBot.Modules.Gambling.Gambling;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Pokemon
|
||||||
|
{
|
||||||
|
|
||||||
|
[NadekoModule("Pokemon", ">")]
|
||||||
|
public partial class Pokemon : DiscordModule
|
||||||
|
{
|
||||||
|
private static List<PokemonType> PokemonTypes = new List<PokemonType>();
|
||||||
|
private static ConcurrentDictionary<ulong, PokeStats> Stats = new ConcurrentDictionary<ulong, PokeStats>();
|
||||||
|
|
||||||
|
public const string PokemonTypesFile = "data/pokemon_types.json";
|
||||||
|
|
||||||
|
private Logger _pokelog { get; }
|
||||||
|
|
||||||
|
public Pokemon() : base()
|
||||||
|
{
|
||||||
|
_pokelog = LogManager.GetCurrentClassLogger();
|
||||||
|
if (File.Exists(PokemonTypesFile))
|
||||||
|
{
|
||||||
|
PokemonTypes = JsonConvert.DeserializeObject<List<PokemonType>>(File.ReadAllText(PokemonTypesFile));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_pokelog.Warn(PokemonTypesFile + " is missing. Pokemon types not loaded.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int GetDamage(PokemonType usertype, PokemonType targetType)
|
||||||
|
{
|
||||||
|
var rng = new Random();
|
||||||
|
int damage = rng.Next(40, 60);
|
||||||
|
foreach (PokemonMultiplier Multiplier in usertype.Multipliers)
|
||||||
|
{
|
||||||
|
if (Multiplier.Type == targetType.Name)
|
||||||
|
{
|
||||||
|
var multiplier = Multiplier.Multiplication;
|
||||||
|
damage = (int)(damage * multiplier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return damage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private PokemonType GetPokeType(ulong id)
|
||||||
|
{
|
||||||
|
|
||||||
|
Dictionary<ulong, string> setTypes;
|
||||||
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
|
{
|
||||||
|
setTypes = uow.PokeGame.GetAll().ToDictionary(x => x.UserId, y => y.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setTypes.ContainsKey(id))
|
||||||
|
{
|
||||||
|
return StringToPokemonType(setTypes[id]);
|
||||||
|
}
|
||||||
|
int count = PokemonTypes.Count;
|
||||||
|
|
||||||
|
int remainder = Math.Abs((int)(id % (ulong)count));
|
||||||
|
|
||||||
|
return PokemonTypes[remainder];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private PokemonType StringToPokemonType(string v)
|
||||||
|
{
|
||||||
|
var str = v?.ToUpperInvariant();
|
||||||
|
var list = PokemonTypes;
|
||||||
|
foreach (PokemonType p in list)
|
||||||
|
{
|
||||||
|
if (str == p.Name)
|
||||||
|
{
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task Attack(IUserMessage umsg, string move, IGuildUser targetUser = null)
|
||||||
|
{
|
||||||
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
IGuildUser user = (IGuildUser)umsg.Author;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(move)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetUser == null)
|
||||||
|
{
|
||||||
|
await channel.SendMessageAsync("No such person.").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (targetUser == user)
|
||||||
|
{
|
||||||
|
await channel.SendMessageAsync("You can't attack yourself.").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checking stats first, then move
|
||||||
|
//Set up the userstats
|
||||||
|
PokeStats userStats;
|
||||||
|
userStats = Stats.GetOrAdd(user.Id, new PokeStats());
|
||||||
|
|
||||||
|
//Check if able to move
|
||||||
|
//User not able if HP < 0, has made more than 4 attacks
|
||||||
|
if (userStats.Hp < 0)
|
||||||
|
{
|
||||||
|
await channel.SendMessageAsync($"{user.Mention} has fainted and was not able to move!").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (userStats.MovesMade >= 5)
|
||||||
|
{
|
||||||
|
await channel.SendMessageAsync($"{user.Mention} has used too many moves in a row and was not able to move!").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (userStats.LastAttacked.Contains(targetUser.Id))
|
||||||
|
{
|
||||||
|
await channel.SendMessageAsync($"{user.Mention} can't attack again without retaliation!").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//get target stats
|
||||||
|
PokeStats targetStats;
|
||||||
|
targetStats = Stats.GetOrAdd(targetUser.Id, new PokeStats());
|
||||||
|
|
||||||
|
//If target's HP is below 0, no use attacking
|
||||||
|
if (targetStats.Hp <= 0)
|
||||||
|
{
|
||||||
|
await channel.SendMessageAsync($"{targetUser.Mention} has already fainted!").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check whether move can be used
|
||||||
|
PokemonType userType = GetPokeType(user.Id);
|
||||||
|
|
||||||
|
var enabledMoves = userType.Moves;
|
||||||
|
if (!enabledMoves.Contains(move.ToLowerInvariant()))
|
||||||
|
{
|
||||||
|
await channel.SendMessageAsync($"{user.Mention} is not able to use **{move}**. Type {NadekoBot.ModulePrefixes[typeof(Pokemon).Name]}ml to see moves").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get target type
|
||||||
|
PokemonType targetType = GetPokeType(targetUser.Id);
|
||||||
|
//generate damage
|
||||||
|
int damage = GetDamage(userType, targetType);
|
||||||
|
//apply damage to target
|
||||||
|
targetStats.Hp -= damage;
|
||||||
|
|
||||||
|
var response = $"{user.Mention} used **{move}**{userType.Icon} on {targetUser.Mention}{targetType.Icon} for **{damage}** damage";
|
||||||
|
|
||||||
|
//Damage type
|
||||||
|
if (damage < 40)
|
||||||
|
{
|
||||||
|
response += "\nIt's not effective..";
|
||||||
|
}
|
||||||
|
else if (damage > 60)
|
||||||
|
{
|
||||||
|
response += "\nIt's super effective!";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response += "\nIt's somewhat effective";
|
||||||
|
}
|
||||||
|
|
||||||
|
//check fainted
|
||||||
|
|
||||||
|
if (targetStats.Hp <= 0)
|
||||||
|
{
|
||||||
|
response += $"\n**{targetUser.Mention}** has fainted!";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response += $"\n**{targetUser.Mention}** has {targetStats.Hp} HP remaining";
|
||||||
|
}
|
||||||
|
|
||||||
|
//update other stats
|
||||||
|
userStats.LastAttacked.Add(targetUser.Id);
|
||||||
|
userStats.MovesMade++;
|
||||||
|
targetStats.MovesMade = 0;
|
||||||
|
if (targetStats.LastAttacked.Contains(user.Id))
|
||||||
|
{
|
||||||
|
targetStats.LastAttacked.Remove(user.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
//update dictionary
|
||||||
|
//This can stay the same right?
|
||||||
|
Stats[user.Id] = userStats;
|
||||||
|
Stats[targetUser.Id] = targetStats;
|
||||||
|
|
||||||
|
await channel.SendMessageAsync(response).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task Movelist(IUserMessage umsg)
|
||||||
|
{
|
||||||
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
IGuildUser user = (IGuildUser)umsg.Author;
|
||||||
|
|
||||||
|
var userType = GetPokeType(user.Id);
|
||||||
|
var movesList = userType.Moves;
|
||||||
|
var str = $"**Moves for `{userType.Name}` type.**";
|
||||||
|
foreach (string m in movesList)
|
||||||
|
{
|
||||||
|
str += $"\n{userType.Icon}{m}";
|
||||||
|
}
|
||||||
|
await channel.SendMessageAsync(str).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task Heal(IUserMessage umsg, IGuildUser targetUser = null)
|
||||||
|
{
|
||||||
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
IGuildUser user = (IGuildUser)umsg.Author;
|
||||||
|
|
||||||
|
if (targetUser == null) {
|
||||||
|
await channel.SendMessageAsync("No such person.").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Stats.ContainsKey(targetUser.Id))
|
||||||
|
{
|
||||||
|
var targetStats = Stats[targetUser.Id];
|
||||||
|
if (targetStats.Hp == targetStats.MaxHp)
|
||||||
|
{
|
||||||
|
await channel.SendMessageAsync($"{targetUser.Mention} already has full HP!").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//Payment~
|
||||||
|
var amount = 1;
|
||||||
|
|
||||||
|
var target = (targetUser.Id == user.Id) ? "yourself" : targetUser.Mention;
|
||||||
|
if (amount > 0)
|
||||||
|
{
|
||||||
|
if (!await CurrencyHandler.RemoveCurrencyAsync(user, $"Poke-Heal {target}", amount, true).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
try { await channel.SendMessageAsync($"{user.Mention} You don't have enough {CurrencyName}s.").ConfigureAwait(false); } catch { }
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//healing
|
||||||
|
targetStats.Hp = targetStats.MaxHp;
|
||||||
|
if (targetStats.Hp < 0)
|
||||||
|
{
|
||||||
|
//Could heal only for half HP?
|
||||||
|
Stats[targetUser.Id].Hp = (targetStats.MaxHp / 2);
|
||||||
|
if (target == "yourself")
|
||||||
|
{
|
||||||
|
await channel.SendMessageAsync($"You revived yourself with one {CurrencySign}").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await channel.SendMessageAsync($"{user.Mention} revived {targetUser.Mention} with one {CurrencySign}").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await channel.SendMessageAsync($"{user.Mention} healed {targetUser.Mention} with one {CurrencySign}").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await channel.SendMessageAsync($"{targetUser.Mention} already has full HP!").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task Type(IUserMessage umsg, IGuildUser targetUser = null)
|
||||||
|
{
|
||||||
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
IGuildUser user = (IGuildUser)umsg.Author;
|
||||||
|
|
||||||
|
if (targetUser == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pType = GetPokeType(targetUser.Id);
|
||||||
|
await channel.SendMessageAsync($"Type of {targetUser.Mention} is **{pType.Name.ToLowerInvariant()}**{pType.Icon}").ConfigureAwait(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task Settype(IUserMessage umsg, [Remainder] string typeTargeted = null)
|
||||||
|
{
|
||||||
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
IGuildUser user = (IGuildUser)umsg.Author;
|
||||||
|
|
||||||
|
var targetType = StringToPokemonType(typeTargeted);
|
||||||
|
if (targetType == null)
|
||||||
|
{
|
||||||
|
await channel.EmbedAsync(PokemonTypes.Aggregate(new EmbedBuilder().WithDescription("List of the available types:"), (eb, pt) => eb.AddField(efb => efb.WithName(pt.Name).WithValue(pt.Icon).WithIsInline(true))).WithOkColor().Build()).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (targetType == GetPokeType(user.Id))
|
||||||
|
{
|
||||||
|
await channel.SendMessageAsync($"Your type is already {targetType.Name.ToLowerInvariant()}{targetType.Icon}").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Payment~
|
||||||
|
var amount = 1;
|
||||||
|
if (amount > 0)
|
||||||
|
{
|
||||||
|
if (!await CurrencyHandler.RemoveCurrencyAsync(user, $"{user.Mention} change type to {typeTargeted}", amount, true).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
try { await channel.SendMessageAsync($"{user.Mention} You don't have enough {CurrencyName}s.").ConfigureAwait(false); } catch { }
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Actually changing the type here
|
||||||
|
Dictionary<ulong, string> setTypes;
|
||||||
|
|
||||||
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
|
{
|
||||||
|
var pokeUsers = uow.PokeGame.GetAll();
|
||||||
|
setTypes = pokeUsers.ToDictionary(x => x.UserId, y => y.type);
|
||||||
|
var pt = new UserPokeTypes
|
||||||
|
{
|
||||||
|
UserId = user.Id,
|
||||||
|
type = targetType.Name,
|
||||||
|
};
|
||||||
|
if (!setTypes.ContainsKey(user.Id))
|
||||||
|
{
|
||||||
|
//create user in db
|
||||||
|
uow.PokeGame.Add(pt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//update user in db
|
||||||
|
var pokeUserCmd = pokeUsers.Where(p => p.UserId == user.Id).FirstOrDefault();
|
||||||
|
pokeUserCmd.type = targetType.Name;
|
||||||
|
uow.PokeGame.Update(pokeUserCmd);
|
||||||
|
}
|
||||||
|
await uow.CompleteAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Now for the response
|
||||||
|
await channel.SendMessageAsync($"Set type of {user.Mention} to {typeTargeted}{targetType.Icon} for a {CurrencySign}").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
33
src/NadekoBot/Modules/Pokemon/PokemonType.cs
Normal file
33
src/NadekoBot/Modules/Pokemon/PokemonType.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Pokemon
|
||||||
|
{
|
||||||
|
public class PokemonType
|
||||||
|
{
|
||||||
|
public PokemonType(string n, string i, string[] m, List<PokemonMultiplier> multi)
|
||||||
|
{
|
||||||
|
Name = n;
|
||||||
|
Icon = i;
|
||||||
|
Moves = m;
|
||||||
|
Multipliers = multi;
|
||||||
|
}
|
||||||
|
public string Name { get; set; }
|
||||||
|
public List<PokemonMultiplier> Multipliers { get; set; }
|
||||||
|
public string Icon { get; set; }
|
||||||
|
public string[] Moves { get; set; }
|
||||||
|
}
|
||||||
|
public class PokemonMultiplier
|
||||||
|
{
|
||||||
|
public PokemonMultiplier(string t, double m)
|
||||||
|
{
|
||||||
|
Type = t;
|
||||||
|
Multiplication = m;
|
||||||
|
}
|
||||||
|
public string Type { get; set; }
|
||||||
|
public double Multiplication { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ using NLog;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Searches
|
namespace NadekoBot.Modules.Searches
|
||||||
@ -19,14 +20,37 @@ namespace NadekoBot.Modules.Searches
|
|||||||
[Group]
|
[Group]
|
||||||
public class AnimeSearchCommands
|
public class AnimeSearchCommands
|
||||||
{
|
{
|
||||||
private Logger _log;
|
private static Timer anilistTokenRefresher { get; }
|
||||||
|
private static Logger _log { get; }
|
||||||
|
private static string anilistToken { get; set; }
|
||||||
|
|
||||||
private string anilistToken { get; set; }
|
static AnimeSearchCommands()
|
||||||
private DateTime lastRefresh { get; set; }
|
|
||||||
|
|
||||||
public AnimeSearchCommands()
|
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
anilistTokenRefresher = new Timer(async (state) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var headers = new Dictionary<string, string> {
|
||||||
|
{"grant_type", "client_credentials"},
|
||||||
|
{"client_id", "kwoth-w0ki9"},
|
||||||
|
{"client_secret", "Qd6j4FIAi1ZK6Pc7N7V4Z"},
|
||||||
|
};
|
||||||
|
|
||||||
|
using (var http = new HttpClient())
|
||||||
|
{
|
||||||
|
http.AddFakeHeaders();
|
||||||
|
var formContent = new FormUrlEncodedContent(headers);
|
||||||
|
var response = await http.PostAsync("http://anilist.co/api/auth/access_token", formContent).ConfigureAwait(false);
|
||||||
|
var stringContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||||
|
anilistToken = JObject.Parse(stringContent)["access_token"].ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_log.Error(ex);
|
||||||
|
}
|
||||||
|
}, null, TimeSpan.FromSeconds(0), TimeSpan.FromMinutes(29));
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -40,34 +64,22 @@ namespace NadekoBot.Modules.Searches
|
|||||||
|
|
||||||
var animeData = await GetAnimeData(query).ConfigureAwait(false);
|
var animeData = await GetAnimeData(query).ConfigureAwait(false);
|
||||||
|
|
||||||
var embed = new Discord.API.Embed()
|
if (animeData == null)
|
||||||
{
|
{
|
||||||
Description = animeData.Synopsis,
|
await umsg.Channel.SendErrorAsync("Failed finding that animu.").ConfigureAwait(false);
|
||||||
Title = animeData.title_english,
|
return;
|
||||||
Url = animeData.Link,
|
|
||||||
Image = new Discord.API.EmbedImage() {
|
|
||||||
Url = animeData.image_url_lge
|
|
||||||
},
|
|
||||||
Fields = new[] {
|
|
||||||
new Discord.API.EmbedField() {
|
|
||||||
Inline = true,
|
|
||||||
Name = "Episodes",
|
|
||||||
Value = animeData.total_episodes.ToString()
|
|
||||||
},
|
|
||||||
new Discord.API.EmbedField() {
|
|
||||||
Inline = true,
|
|
||||||
Name = "Status",
|
|
||||||
Value = animeData.AiringStatus.ToString()
|
|
||||||
},
|
|
||||||
new Discord.API.EmbedField() {
|
|
||||||
Inline = true,
|
|
||||||
Name = "Genres",
|
|
||||||
Value = String.Join(", ", animeData.Genres)
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
Color = NadekoBot.OkColor
|
var embed = new EmbedBuilder().WithColor(NadekoBot.OkColor)
|
||||||
};
|
.WithDescription(animeData.Synopsis.Replace("<br>", Environment.NewLine))
|
||||||
await channel.EmbedAsync(embed).ConfigureAwait(false);
|
.WithTitle(animeData.title_english)
|
||||||
|
.WithUrl(animeData.Link)
|
||||||
|
.WithImageUrl(animeData.image_url_lge)
|
||||||
|
.AddField(efb => efb.WithName("Episodes").WithValue(animeData.total_episodes.ToString()).WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName("Status").WithValue(animeData.AiringStatus.ToString()).WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName("Genres").WithValue(String.Join(", ", animeData.Genres)).WithIsInline(true))
|
||||||
|
.WithFooter(efb => efb.WithText("Score: " + animeData.average_score + " / 100"));
|
||||||
|
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -79,38 +91,25 @@ namespace NadekoBot.Modules.Searches
|
|||||||
if (string.IsNullOrWhiteSpace(query))
|
if (string.IsNullOrWhiteSpace(query))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var animeData = await GetMangaData(query).ConfigureAwait(false);
|
var mangaData = await GetMangaData(query).ConfigureAwait(false);
|
||||||
|
|
||||||
var embed = new Discord.API.Embed()
|
if (mangaData == null)
|
||||||
{
|
{
|
||||||
Description = animeData.Synopsis,
|
await umsg.Channel.SendErrorAsync("Failed finding that mango.").ConfigureAwait(false);
|
||||||
Title = animeData.title_english,
|
return;
|
||||||
Url = animeData.Link,
|
|
||||||
Image = new Discord.API.EmbedImage()
|
|
||||||
{
|
|
||||||
Url = animeData.image_url_lge
|
|
||||||
},
|
|
||||||
Fields = new[] {
|
|
||||||
new Discord.API.EmbedField() {
|
|
||||||
Inline = true,
|
|
||||||
Name = "Chapters",
|
|
||||||
Value = animeData.total_chapters.ToString()
|
|
||||||
},
|
|
||||||
new Discord.API.EmbedField() {
|
|
||||||
Inline = true,
|
|
||||||
Name = "Status",
|
|
||||||
Value = animeData.publishing_status.ToString()
|
|
||||||
},
|
|
||||||
new Discord.API.EmbedField() {
|
|
||||||
Inline = true,
|
|
||||||
Name = "Genres",
|
|
||||||
Value = String.Join(", ", animeData.Genres)
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
Color = NadekoBot.OkColor
|
|
||||||
};
|
|
||||||
|
|
||||||
await channel.EmbedAsync(embed).ConfigureAwait(false);
|
var embed = new EmbedBuilder().WithColor(NadekoBot.OkColor)
|
||||||
|
.WithDescription(mangaData.Synopsis.Replace("<br>", Environment.NewLine))
|
||||||
|
.WithTitle(mangaData.title_english)
|
||||||
|
.WithUrl(mangaData.Link)
|
||||||
|
.WithImageUrl(mangaData.image_url_lge)
|
||||||
|
.AddField(efb => efb.WithName("Episodes").WithValue(mangaData.total_chapters.ToString()).WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName("Status").WithValue(mangaData.publishing_status.ToString()).WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName("Genres").WithValue(String.Join(", ", mangaData.Genres)).WithIsInline(true))
|
||||||
|
.WithFooter(efb => efb.WithText("Score: " + mangaData.average_score + " / 100"));
|
||||||
|
|
||||||
|
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<AnimeResult> GetAnimeData(string query)
|
private async Task<AnimeResult> GetAnimeData(string query)
|
||||||
@ -119,7 +118,6 @@ namespace NadekoBot.Modules.Searches
|
|||||||
throw new ArgumentNullException(nameof(query));
|
throw new ArgumentNullException(nameof(query));
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await RefreshAnilistToken().ConfigureAwait(false);
|
|
||||||
|
|
||||||
var link = "http://anilist.co/api/anime/search/" + Uri.EscapeUriString(query);
|
var link = "http://anilist.co/api/anime/search/" + Uri.EscapeUriString(query);
|
||||||
using (var http = new HttpClient())
|
using (var http = new HttpClient())
|
||||||
@ -131,43 +129,19 @@ namespace NadekoBot.Modules.Searches
|
|||||||
return await Task.Run(() => { try { return JsonConvert.DeserializeObject<AnimeResult>(aniData); } catch { return null; } }).ConfigureAwait(false);
|
return await Task.Run(() => { try { return JsonConvert.DeserializeObject<AnimeResult>(aniData); } catch { return null; } }).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex)
|
||||||
|
{
|
||||||
_log.Warn(ex, "Failed anime search for {0}", query);
|
_log.Warn(ex, "Failed anime search for {0}", query);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RefreshAnilistToken()
|
|
||||||
{
|
|
||||||
if (DateTime.Now - lastRefresh > TimeSpan.FromMinutes(29))
|
|
||||||
lastRefresh = DateTime.Now;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var headers = new Dictionary<string, string> {
|
|
||||||
{"grant_type", "client_credentials"},
|
|
||||||
{"client_id", "kwoth-w0ki9"},
|
|
||||||
{"client_secret", "Qd6j4FIAi1ZK6Pc7N7V4Z"},
|
|
||||||
};
|
|
||||||
using (var http = new HttpClient())
|
|
||||||
{
|
|
||||||
http.AddFakeHeaders();
|
|
||||||
var formContent = new FormUrlEncodedContent(headers);
|
|
||||||
var response = await http.PostAsync("http://anilist.co/api/auth/access_token", formContent).ConfigureAwait(false);
|
|
||||||
var stringContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
|
||||||
anilistToken = JObject.Parse(stringContent)["access_token"].ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<MangaResult> GetMangaData(string query)
|
private async Task<MangaResult> GetMangaData(string query)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(query))
|
if (string.IsNullOrWhiteSpace(query))
|
||||||
throw new ArgumentNullException(nameof(query));
|
throw new ArgumentNullException(nameof(query));
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await RefreshAnilistToken().ConfigureAwait(false);
|
|
||||||
using (var http = new HttpClient())
|
using (var http = new HttpClient())
|
||||||
{
|
{
|
||||||
var res = await http.GetStringAsync("http://anilist.co/api/manga/search/" + Uri.EscapeUriString(query) + $"?access_token={anilistToken}").ConfigureAwait(false);
|
var res = await http.GetStringAsync("http://anilist.co/api/manga/search/" + Uri.EscapeUriString(query) + $"?access_token={anilistToken}").ConfigureAwait(false);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Modules.Searches.Models;
|
using NadekoBot.Modules.Searches.Models;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
@ -19,11 +20,11 @@ namespace NadekoBot.Modules.Searches
|
|||||||
[Group]
|
[Group]
|
||||||
public class JokeCommands
|
public class JokeCommands
|
||||||
{
|
{
|
||||||
private List<WoWJoke> wowJokes = new List<WoWJoke>();
|
private static List<WoWJoke> wowJokes { get; } = new List<WoWJoke>();
|
||||||
private List<MagicItem> magicItems;
|
private static List<MagicItem> magicItems { get; } = new List<MagicItem>();
|
||||||
private Logger _log;
|
private static Logger _log { get; }
|
||||||
|
|
||||||
public JokeCommands()
|
static JokeCommands()
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
if (File.Exists("data/wowjokes.json"))
|
if (File.Exists("data/wowjokes.json"))
|
||||||
@ -43,61 +44,63 @@ namespace NadekoBot.Modules.Searches
|
|||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task Yomama(IUserMessage umsg)
|
public async Task Yomama(IUserMessage msg)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
using (var http = new HttpClient())
|
using (var http = new HttpClient())
|
||||||
{
|
{
|
||||||
var response = await http.GetStringAsync("http://api.yomomma.info/").ConfigureAwait(false);
|
var response = await http.GetStringAsync("http://api.yomomma.info/").ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync("`" + JObject.Parse(response)["joke"].ToString() + "` 😆").ConfigureAwait(false);
|
System.Console.WriteLine(response);
|
||||||
|
await msg.Channel.SendConfirmAsync(JObject.Parse(response)["joke"].ToString() + " 😆").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task Randjoke(IUserMessage umsg)
|
public async Task Randjoke(IUserMessage msg)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
using (var http = new HttpClient())
|
using (var http = new HttpClient())
|
||||||
{
|
{
|
||||||
var response = await http.GetStringAsync("http://tambal.azurewebsites.net/joke/random").ConfigureAwait(false);
|
var response = await http.GetStringAsync("http://tambal.azurewebsites.net/joke/random").ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync("`" + JObject.Parse(response)["joke"].ToString() + "` 😆").ConfigureAwait(false);
|
await msg.Channel.SendConfirmAsync(JObject.Parse(response)["joke"].ToString() + " 😆").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task ChuckNorris(IUserMessage umsg)
|
public async Task ChuckNorris(IUserMessage msg)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
using (var http = new HttpClient())
|
using (var http = new HttpClient())
|
||||||
{
|
{
|
||||||
var response = await http.GetStringAsync("http://api.icndb.com/jokes/random/").ConfigureAwait(false);
|
var response = await http.GetStringAsync("http://api.icndb.com/jokes/random/").ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync("`" + JObject.Parse(response)["value"]["joke"].ToString() + "` 😆").ConfigureAwait(false);
|
await msg.Channel.SendConfirmAsync(JObject.Parse(response)["value"]["joke"].ToString() + " 😆").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task WowJoke(IUserMessage umsg)
|
public async Task WowJoke(IUserMessage msg)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
|
|
||||||
if (!wowJokes.Any())
|
if (!wowJokes.Any())
|
||||||
{
|
{
|
||||||
|
await msg.Channel.SendErrorAsync("Jokes not loaded.").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync(wowJokes[new NadekoRandom().Next(0, wowJokes.Count)].ToString());
|
var joke = wowJokes[new NadekoRandom().Next(0, wowJokes.Count)];
|
||||||
|
await msg.Channel.SendConfirmAsync(joke.Question, joke.Answer).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task MagicItem(IUserMessage umsg)
|
public async Task MagicItem(IUserMessage msg)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
if (!wowJokes.Any())
|
||||||
var rng = new NadekoRandom();
|
{
|
||||||
var item = magicItems[rng.Next(0, magicItems.Count)].ToString();
|
await msg.Channel.SendErrorAsync("MagicItems not loaded.").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var item = magicItems[new NadekoRandom().Next(0, magicItems.Count)];
|
||||||
|
|
||||||
await channel.SendMessageAsync(item).ConfigureAwait(false);
|
await msg.Channel.SendConfirmAsync("✨" + item.Name, item.Description).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using System;
|
using System;
|
||||||
@ -23,7 +24,7 @@ namespace NadekoBot.Modules.Searches
|
|||||||
obj["name"].GetHashCode();
|
obj["name"].GetHashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
private string[] trashTalk { get; } = { "Better ban your counters. You are going to carry the game anyway.",
|
private static string[] trashTalk { get; } = { "Better ban your counters. You are going to carry the game anyway.",
|
||||||
"Go with the flow. Don't think. Just ban one of these.",
|
"Go with the flow. Don't think. Just ban one of these.",
|
||||||
"DONT READ BELOW! Ban Urgot mid OP 100%. Im smurf Diamond 1.",
|
"DONT READ BELOW! Ban Urgot mid OP 100%. Im smurf Diamond 1.",
|
||||||
"Ask your teammates what would they like to play, and ban that.",
|
"Ask your teammates what would they like to play, and ban that.",
|
||||||
@ -50,23 +51,19 @@ namespace NadekoBot.Modules.Searches
|
|||||||
$"limit={showCount}")
|
$"limit={showCount}")
|
||||||
.ConfigureAwait(false))["data"] as JArray;
|
.ConfigureAwait(false))["data"] as JArray;
|
||||||
var dataList = data.Distinct(new ChampionNameComparer()).Take(showCount).ToList();
|
var dataList = data.Distinct(new ChampionNameComparer()).Take(showCount).ToList();
|
||||||
var sb = new StringBuilder();
|
var eb = new EmbedBuilder().WithOkColor().WithTitle(Format.Underline($"{dataList.Count} most banned champions"));
|
||||||
sb.AppendLine($"**Showing {dataList.Count} top banned champions.**");
|
|
||||||
sb.AppendLine($"`{trashTalk[new NadekoRandom().Next(0, trashTalk.Length)]}`");
|
|
||||||
for (var i = 0; i < dataList.Count; i++)
|
for (var i = 0; i < dataList.Count; i++)
|
||||||
{
|
{
|
||||||
if (i % 2 == 0 && i != 0)
|
var champ = dataList[i];
|
||||||
sb.AppendLine();
|
eb.AddField(efb => efb.WithName(champ["name"].ToString()).WithValue(champ["general"]["banRate"] + "%").WithIsInline(true));
|
||||||
sb.Append($"`{i + 1}.` **{dataList[i]["name"]}** {dataList[i]["general"]["banRate"]}% ");
|
|
||||||
//sb.AppendLine($" ({dataList[i]["general"]["banRate"]}%)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync(sb.ToString()).ConfigureAwait(false);
|
await channel.EmbedAsync(eb.Build(), Format.Italics(trashTalk[new NadekoRandom().Next(0, trashTalk.Length)])).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($":anger: `Something went wrong.`").ConfigureAwait(false);
|
await channel.SendMessageAsync("Something went wrong.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,20 +25,11 @@ namespace NadekoBot.Modules.Searches
|
|||||||
|
|
||||||
using (var http = new HttpClient(handler))
|
using (var http = new HttpClient(handler))
|
||||||
{
|
{
|
||||||
http.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
|
var rawJson = await http.GetStringAsync("https://memegen.link/api/templates/").ConfigureAwait(false);
|
||||||
string rawJson = "";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
rawJson = await http.GetStringAsync("https://memegen.link/api/templates/").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine(ex);
|
|
||||||
}
|
|
||||||
var data = JsonConvert.DeserializeObject<Dictionary<string, string>>(rawJson)
|
var data = JsonConvert.DeserializeObject<Dictionary<string, string>>(rawJson)
|
||||||
.Select(kvp => Path.GetFileName(kvp.Value));
|
.Select(kvp => Path.GetFileName(kvp.Value));
|
||||||
|
|
||||||
await channel.SendTableAsync(data, x => $"{x,-17}", 3);
|
await channel.SendTableAsync(data, x => $"{x,-17}", 3).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,9 +39,10 @@ namespace NadekoBot.Modules.Searches
|
|||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
var top = Uri.EscapeDataString(topText.Replace(' ', '-'));
|
var top = topText.Replace(' ', '-');
|
||||||
var bot = Uri.EscapeDataString(botText.Replace(' ', '-'));
|
var bot = botText.Replace(' ', '-');
|
||||||
await channel.SendMessageAsync($"http://memegen.link/{meme}/{top}/{bot}.jpg");
|
await channel.SendMessageAsync($"http://memegen.link/{meme}/{top}/{bot}.jpg")
|
||||||
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ namespace NadekoBot.Modules.Searches.Models
|
|||||||
public string description;
|
public string description;
|
||||||
public string image_url_lge;
|
public string image_url_lge;
|
||||||
public string[] Genres;
|
public string[] Genres;
|
||||||
|
public string average_score;
|
||||||
|
|
||||||
public string Link => "http://anilist.co/anime/" + id;
|
public string Link => "http://anilist.co/anime/" + id;
|
||||||
public string Synopsis => description?.Substring(0, description.Length > 500 ? 500 : description.Length) + "...";
|
public string Synopsis => description?.Substring(0, description.Length > 500 ? 500 : description.Length) + "...";
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Searches.Commands.Models
|
||||||
|
{
|
||||||
|
public class Audio
|
||||||
|
{
|
||||||
|
public string url { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Example
|
||||||
|
{
|
||||||
|
public List<Audio> audio { get; set; }
|
||||||
|
public string text { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GramaticalInfo
|
||||||
|
{
|
||||||
|
public string type { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Sens
|
||||||
|
{
|
||||||
|
public object Definition { get; set; }
|
||||||
|
public List<Example> Examples { get; set; }
|
||||||
|
public GramaticalInfo Gramatical_info { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Result
|
||||||
|
{
|
||||||
|
public string Part_of_speech { get; set; }
|
||||||
|
public List<Sens> Senses { get; set; }
|
||||||
|
public string Url { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DefineModel
|
||||||
|
{
|
||||||
|
public List<Result> Results { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Searches.Commands.Models
|
||||||
|
{
|
||||||
|
public struct GoogleSearchResult
|
||||||
|
{
|
||||||
|
public string Title { get; }
|
||||||
|
public string Link { get; }
|
||||||
|
public string Text { get; }
|
||||||
|
|
||||||
|
public GoogleSearchResult(string title, string link, string text)
|
||||||
|
{
|
||||||
|
this.Title = title;
|
||||||
|
this.Link = link;
|
||||||
|
this.Text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,5 @@
|
|||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
public override string ToString() =>
|
|
||||||
$"✨`{Name}`\n\t*{Description}*";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ namespace NadekoBot.Modules.Searches.Models
|
|||||||
public int total_volumes;
|
public int total_volumes;
|
||||||
public string description;
|
public string description;
|
||||||
public string[] Genres;
|
public string[] Genres;
|
||||||
|
public string average_score;
|
||||||
public string Link => "http://anilist.co/manga/" + id;
|
public string Link => "http://anilist.co/manga/" + id;
|
||||||
public string Synopsis => description?.Substring(0, description.Length > 500 ? 500 : description.Length) + "...";
|
public string Synopsis => description?.Substring(0, description.Length > 500 ? 500 : description.Length) + "...";
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Searches.Models
|
||||||
|
{
|
||||||
|
public class OverwatchApiModel
|
||||||
|
{
|
||||||
|
public OverwatchPlayer Player { get; set; }
|
||||||
|
|
||||||
|
public class OverwatchPlayer
|
||||||
|
{
|
||||||
|
public Data data { get; set; }
|
||||||
|
public class Data
|
||||||
|
{
|
||||||
|
public bool Missing { get; set; } = false;
|
||||||
|
public string username { get; set; }
|
||||||
|
public int level { get; set; }
|
||||||
|
public string avatar { get; set; }
|
||||||
|
public string levelFrame { get; set; }
|
||||||
|
public string star { get; set; }
|
||||||
|
[JsonProperty("games")]
|
||||||
|
public OverwatchGames Games { get; set; }
|
||||||
|
[JsonProperty("playtime")]
|
||||||
|
public OverwatchPlaytime Playtime { get; set; }
|
||||||
|
[JsonProperty("competitive")]
|
||||||
|
public OverwatchCompetitive Competitive { get; set; }
|
||||||
|
public class OverwatchGames
|
||||||
|
{
|
||||||
|
[JsonProperty("quick")]
|
||||||
|
public OverwatchQG Quick { get; set; }
|
||||||
|
[JsonProperty("competitive")]
|
||||||
|
public OverwatchCOMP Competitive { get; set; }
|
||||||
|
|
||||||
|
public class OverwatchQG
|
||||||
|
{
|
||||||
|
public string wins { get; set; }
|
||||||
|
}
|
||||||
|
public class OverwatchCOMP
|
||||||
|
{
|
||||||
|
public string wins { get; set; }
|
||||||
|
public int lost { get; set; }
|
||||||
|
public string played { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class OverwatchCompetitive
|
||||||
|
{
|
||||||
|
public string rank { get; set; }
|
||||||
|
public string rank_img { get; set; }
|
||||||
|
}
|
||||||
|
public class OverwatchPlaytime
|
||||||
|
{
|
||||||
|
public string quick { get; set; }
|
||||||
|
public string competitive { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//This is to strip the html from patch notes content
|
||||||
|
internal static string StripHTML(string input)
|
||||||
|
{
|
||||||
|
var re = Regex.Replace(input, "<.*?>", String.Empty);
|
||||||
|
re = Regex.Replace(re, " ", $@" ");
|
||||||
|
return re;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,9 +18,8 @@ namespace NadekoBot.Modules.Searches.Models
|
|||||||
public int SPD { get; set; }
|
public int SPD { get; set; }
|
||||||
public int SPE { get; set; }
|
public int SPE { get; set; }
|
||||||
|
|
||||||
public override string ToString() => $@"
|
public override string ToString() => $@"**HP:** {HP,-4} **ATK:** {ATK,-4} **DEF:** {DEF,-4}
|
||||||
**HP:** {HP,-4} **ATK:** {ATK,-4} **DEF:** {DEF,-4}
|
**SPA:** {SPA,-4} **SPD:** {SPD,-4} **SPE:** {SPE,-4}";
|
||||||
**SPA:** {SPA,-4} **SPD:** {SPD,-4} **SPE:** {SPE,-4}";
|
|
||||||
}
|
}
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public string Species { get; set; }
|
public string Species { get; set; }
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Searches.Commands.Models
|
||||||
|
{
|
||||||
|
public class Coord
|
||||||
|
{
|
||||||
|
public double lon { get; set; }
|
||||||
|
public double lat { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Weather
|
||||||
|
{
|
||||||
|
public int id { get; set; }
|
||||||
|
public string main { get; set; }
|
||||||
|
public string description { get; set; }
|
||||||
|
public string icon { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Main
|
||||||
|
{
|
||||||
|
public double temp { get; set; }
|
||||||
|
public int pressure { get; set; }
|
||||||
|
public int humidity { get; set; }
|
||||||
|
public double temp_min { get; set; }
|
||||||
|
public double temp_max { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Wind
|
||||||
|
{
|
||||||
|
public double speed { get; set; }
|
||||||
|
public double deg { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Clouds
|
||||||
|
{
|
||||||
|
public int all { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Sys
|
||||||
|
{
|
||||||
|
public int type { get; set; }
|
||||||
|
public int id { get; set; }
|
||||||
|
public double message { get; set; }
|
||||||
|
public string country { get; set; }
|
||||||
|
public double sunrise { get; set; }
|
||||||
|
public double sunset { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class WeatherData
|
||||||
|
{
|
||||||
|
public Coord coord { get; set; }
|
||||||
|
public List<Weather> weather { get; set; }
|
||||||
|
public Main main { get; set; }
|
||||||
|
public int visibility { get; set; }
|
||||||
|
public Wind wind { get; set; }
|
||||||
|
public Clouds clouds { get; set; }
|
||||||
|
public int dt { get; set; }
|
||||||
|
public Sys sys { get; set; }
|
||||||
|
public int id { get; set; }
|
||||||
|
public string name { get; set; }
|
||||||
|
public int cod { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,7 @@
|
|||||||
using Newtonsoft.Json;
|
using Discord;
|
||||||
|
using Discord.API;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -32,6 +35,17 @@ namespace NadekoBot.Modules.Searches.Commands.OMDB
|
|||||||
public string Plot { get; set; }
|
public string Plot { get; set; }
|
||||||
public string Poster { get; set; }
|
public string Poster { get; set; }
|
||||||
|
|
||||||
|
public Embed GetEmbed() =>
|
||||||
|
new EmbedBuilder().WithOkColor()
|
||||||
|
.WithTitle(Title)
|
||||||
|
.WithUrl($"http://www.imdb.com/title/{ImdbId}/")
|
||||||
|
.WithDescription(Plot)
|
||||||
|
.AddField(efb => efb.WithName("Rating").WithValue(ImdbRating).WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName("Genre").WithValue(Genre).WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName("Year").WithValue(Year).WithIsInline(true))
|
||||||
|
.WithImage(eib => eib.WithUrl(Poster))
|
||||||
|
.Build();
|
||||||
|
|
||||||
public override string ToString() =>
|
public override string ToString() =>
|
||||||
$@"`Title:` {Title}
|
$@"`Title:` {Title}
|
||||||
`Year:` {Year}
|
`Year:` {Year}
|
||||||
|
@ -18,9 +18,9 @@ namespace NadekoBot.Modules.Searches
|
|||||||
[Group]
|
[Group]
|
||||||
public class OsuCommands
|
public class OsuCommands
|
||||||
{
|
{
|
||||||
private Logger _log;
|
private static Logger _log { get; }
|
||||||
|
|
||||||
public OsuCommands()
|
static OsuCommands()
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ namespace NadekoBot.Modules.Searches
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 Failed retrieving osu signature :\\").ConfigureAwait(false);
|
await channel.SendErrorAsync("Failed retrieving osu signature.").ConfigureAwait(false);
|
||||||
_log.Warn(ex, "Osu command failed");
|
_log.Warn(ex, "Osu command failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,7 +66,7 @@ namespace NadekoBot.Modules.Searches
|
|||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.OsuApiKey))
|
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.OsuApiKey))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 An osu! API key is required.").ConfigureAwait(false);
|
await channel.SendErrorAsync("An osu! API key is required.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ namespace NadekoBot.Modules.Searches
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("Something went wrong.");
|
await channel.SendErrorAsync("Something went wrong.");
|
||||||
_log.Warn(ex, "Osub command failed");
|
_log.Warn(ex, "Osub command failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,13 +102,13 @@ namespace NadekoBot.Modules.Searches
|
|||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.OsuApiKey))
|
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.OsuApiKey))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 An osu! API key is required.").ConfigureAwait(false);
|
await channel.SendErrorAsync("An osu! API key is required.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(user))
|
if (string.IsNullOrWhiteSpace(user))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 Please provide a username.").ConfigureAwait(false);
|
await channel.SendErrorAsync("Please provide a username.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
using (var http = new HttpClient())
|
using (var http = new HttpClient())
|
||||||
@ -141,7 +141,7 @@ namespace NadekoBot.Modules.Searches
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("Something went wrong.");
|
await channel.SendErrorAsync("Something went wrong.");
|
||||||
_log.Warn(ex, "Osu5 command failed");
|
_log.Warn(ex, "Osu5 command failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
118
src/NadekoBot/Modules/Searches/Commands/OverwatchCommands.cs
Normal file
118
src/NadekoBot/Modules/Searches/Commands/OverwatchCommands.cs
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Modules.Searches.Models;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using NLog;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Searches
|
||||||
|
{
|
||||||
|
public partial class Searches
|
||||||
|
{
|
||||||
|
[Group]
|
||||||
|
public class OverwatchCommands
|
||||||
|
{
|
||||||
|
private Logger _log;
|
||||||
|
public OverwatchCommands()
|
||||||
|
{
|
||||||
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
}
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task Overwatch(IUserMessage umsg, string region, [Remainder] string query = null)
|
||||||
|
{
|
||||||
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
if (string.IsNullOrWhiteSpace(query))
|
||||||
|
return;
|
||||||
|
var battletag = Regex.Replace(query, "#", "-", RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
|
await channel.TriggerTypingAsync().ConfigureAwait(false);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var model = await GetProfile(region, battletag);
|
||||||
|
|
||||||
|
var rankimg = $"{model.Competitive.rank_img}";
|
||||||
|
var rank = $"{model.Competitive.rank}";
|
||||||
|
var competitiveplay = $"{model.Games.Competitive.played}";
|
||||||
|
if (string.IsNullOrWhiteSpace(rank))
|
||||||
|
{
|
||||||
|
var embed = new EmbedBuilder()
|
||||||
|
.WithAuthor(eau => eau.WithName($"{model.username}")
|
||||||
|
.WithUrl($"https://www.overbuff.com/players/pc/{battletag}")
|
||||||
|
.WithIconUrl($"{model.avatar}"))
|
||||||
|
.WithThumbnail(th => th.WithUrl("https://cdn.discordapp.com/attachments/155726317222887425/255653487512256512/YZ4w2ey.png"))
|
||||||
|
.AddField(fb => fb.WithName("**Level**").WithValue($"{model.level}").WithIsInline(true))
|
||||||
|
.AddField(fb => fb.WithName("**Quick Wins**").WithValue($"{model.Games.Quick.wins}").WithIsInline(true))
|
||||||
|
.AddField(fb => fb.WithName("**Current Competitive Wins**").WithValue($"{model.Games.Competitive.wins}").WithIsInline(true))
|
||||||
|
.AddField(fb => fb.WithName("**Current Competitive Loses**").WithValue($"{model.Games.Competitive.lost}").WithIsInline(true))
|
||||||
|
.AddField(fb => fb.WithName("**Current Competitive Played**").WithValue($"{model.Games.Competitive.played}").WithIsInline(true))
|
||||||
|
.AddField(fb => fb.WithName("**Competitive Rank**").WithValue("0").WithIsInline(true))
|
||||||
|
.AddField(fb => fb.WithName("**Competitive Playtime**").WithValue($"{model.Playtime.competitive}").WithIsInline(true))
|
||||||
|
.AddField(fb => fb.WithName("**Quick Playtime**").WithValue($"{model.Playtime.quick}").WithIsInline(true))
|
||||||
|
.WithOkColor();
|
||||||
|
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var embed = new EmbedBuilder()
|
||||||
|
.WithAuthor(eau => eau.WithName($"{model.username}")
|
||||||
|
.WithUrl($"https://www.overbuff.com/players/pc/{battletag}")
|
||||||
|
.WithIconUrl($"{model.avatar}"))
|
||||||
|
.WithThumbnail(th => th.WithUrl(rankimg))
|
||||||
|
.AddField(fb => fb.WithName("**Level**").WithValue($"{model.level}").WithIsInline(true))
|
||||||
|
.AddField(fb => fb.WithName("**Quick Wins**").WithValue($"{model.Games.Quick.wins}").WithIsInline(true))
|
||||||
|
.AddField(fb => fb.WithName("**Current Competitive Wins**").WithValue($"{model.Games.Competitive.wins}").WithIsInline(true))
|
||||||
|
.AddField(fb => fb.WithName("**Current Competitive Loses**").WithValue($"{model.Games.Competitive.lost}").WithIsInline(true))
|
||||||
|
.AddField(fb => fb.WithName("**Current Competitive Played**").WithValue($"{model.Games.Competitive.played}").WithIsInline(true))
|
||||||
|
.AddField(fb => fb.WithName("**Competitive Rank**").WithValue(rank).WithIsInline(true))
|
||||||
|
.AddField(fb => fb.WithName("**Competitive Playtime**").WithValue($"{model.Playtime.competitive}").WithIsInline(true))
|
||||||
|
.AddField(fb => fb.WithName("**Quick Playtime**").WithValue($"{model.Playtime.quick}").WithIsInline(true))
|
||||||
|
.WithOkColor();
|
||||||
|
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
if (string.IsNullOrWhiteSpace(competitiveplay))
|
||||||
|
{
|
||||||
|
var embed = new EmbedBuilder()
|
||||||
|
.WithAuthor(eau => eau.WithName($"{model.username}")
|
||||||
|
.WithUrl($"https://www.overbuff.com/players/pc/{battletag}")
|
||||||
|
.WithIconUrl($"{model.avatar}"))
|
||||||
|
.WithThumbnail(th => th.WithUrl("https://cdn.discordapp.com/attachments/155726317222887425/255653487512256512/YZ4w2ey.png"))
|
||||||
|
.AddField(fb => fb.WithName("**Level**").WithValue($"{model.level}").WithIsInline(true))
|
||||||
|
.AddField(fb => fb.WithName("**Quick Wins**").WithValue($"{model.Games.Quick.wins}").WithIsInline(true))
|
||||||
|
.AddField(fb => fb.WithName("**Competitive Playtime**").WithValue($"0 hour").WithIsInline(true))
|
||||||
|
.AddField(fb => fb.WithName("**Quick Playtime**").WithValue($"{model.Playtime.quick}").WithIsInline(true))
|
||||||
|
.WithOkColor();
|
||||||
|
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await channel.SendErrorAsync("Found no user! Please check the **Region** and **BattleTag** before trying again.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public async Task<OverwatchApiModel.OverwatchPlayer.Data> GetProfile(string region, string battletag)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var http = new HttpClient())
|
||||||
|
{
|
||||||
|
var Url = await http.GetStringAsync($"https://api.lootbox.eu/pc/{region.ToLower()}/{battletag}/profile");
|
||||||
|
var model = JsonConvert.DeserializeObject<OverwatchApiModel.OverwatchPlayer>(Url);
|
||||||
|
return model.data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -36,7 +37,7 @@ namespace NadekoBot.Modules.Searches
|
|||||||
{
|
{
|
||||||
var channel = (ITextChannel)imsg.Channel;
|
var channel = (ITextChannel)imsg.Channel;
|
||||||
|
|
||||||
await channel.SendMessageAsync(typesStr)
|
await channel.SendConfirmAsync(typesStr)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Modules.Searches.Models;
|
using NadekoBot.Modules.Searches.Models;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NLog;
|
using NLog;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Searches
|
namespace NadekoBot.Modules.Searches
|
||||||
@ -15,15 +17,15 @@ namespace NadekoBot.Modules.Searches
|
|||||||
[Group]
|
[Group]
|
||||||
public class PokemonSearchCommands
|
public class PokemonSearchCommands
|
||||||
{
|
{
|
||||||
private static Dictionary<string, SearchPokemon> pokemons = new Dictionary<string, SearchPokemon>();
|
private static Dictionary<string, SearchPokemon> pokemons { get; } = new Dictionary<string, SearchPokemon>();
|
||||||
private static Dictionary<string, SearchPokemonAbility> pokemonAbilities = new Dictionary<string, SearchPokemonAbility>();
|
private static Dictionary<string, SearchPokemonAbility> pokemonAbilities { get; } = new Dictionary<string, SearchPokemonAbility>();
|
||||||
|
|
||||||
public const string PokemonAbilitiesFile = "data/pokemon/pokemon_abilities.json";
|
public const string PokemonAbilitiesFile = "data/pokemon/pokemon_abilities7.json";
|
||||||
|
|
||||||
public const string PokemonListFile = "data/pokemon/pokemon_list.json";
|
public const string PokemonListFile = "data/pokemon/pokemon_list7.json";
|
||||||
private Logger _log;
|
private static Logger _log { get; }
|
||||||
|
|
||||||
public PokemonSearchCommands()
|
static PokemonSearchCommands()
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
if (File.Exists(PokemonListFile))
|
if (File.Exists(PokemonListFile))
|
||||||
@ -52,11 +54,18 @@ namespace NadekoBot.Modules.Searches
|
|||||||
{
|
{
|
||||||
if (kvp.Key.ToUpperInvariant() == pokemon.ToUpperInvariant())
|
if (kvp.Key.ToUpperInvariant() == pokemon.ToUpperInvariant())
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"`Stats for \"{kvp.Key}\" pokemon:`\n{kvp.Value}");
|
var p = kvp.Value;
|
||||||
|
await channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||||
|
.WithTitle(kvp.Key.ToTitleCase())
|
||||||
|
.WithDescription(p.BaseStats.ToString())
|
||||||
|
.AddField(efb => efb.WithName("Types").WithValue(string.Join(",\n", p.Types)).WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName("Height/Weight").WithValue($"{p.HeightM}m/{p.WeightKg}kg").WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName("Abilitities").WithValue(string.Join(",\n", p.Abilities.Select(a => a.Value))).WithIsInline(true))
|
||||||
|
.Build());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync("`No pokemon found.`");
|
await channel.SendErrorAsync("No pokemon found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -72,11 +81,15 @@ namespace NadekoBot.Modules.Searches
|
|||||||
{
|
{
|
||||||
if (kvp.Key.ToUpperInvariant() == ability)
|
if (kvp.Key.ToUpperInvariant() == ability)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"`Info for \"{kvp.Key}\" ability:`\n{kvp.Value}");
|
await channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||||
|
.WithTitle(kvp.Value.Name)
|
||||||
|
.WithDescription(kvp.Value.Desc)
|
||||||
|
.AddField(efb => efb.WithName("Rating").WithValue(kvp.Value.Rating.ToString()).WithIsInline(true))
|
||||||
|
.Build()).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync("`No ability found.`");
|
await channel.SendErrorAsync("No ability found.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,11 @@ using NadekoBot.Services.Database.Models;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using NLog;
|
||||||
|
using NadekoBot.Services.Database;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Searches
|
namespace NadekoBot.Modules.Searches
|
||||||
{
|
{
|
||||||
@ -19,128 +24,171 @@ namespace NadekoBot.Modules.Searches
|
|||||||
{
|
{
|
||||||
public class StreamStatus
|
public class StreamStatus
|
||||||
{
|
{
|
||||||
public StreamStatus(string link, bool isLive, string views)
|
|
||||||
{
|
|
||||||
Link = link;
|
|
||||||
IsLive = isLive;
|
|
||||||
Views = views;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsLive { get; set; }
|
public bool IsLive { get; set; }
|
||||||
public string Link { get; set; }
|
public string ApiLink { get; set; }
|
||||||
public string Views { get; set; }
|
public string Views { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class HitboxResponse {
|
||||||
|
public bool Success { get; set; } = true;
|
||||||
|
[JsonProperty("media_is_live")]
|
||||||
|
public string MediaIsLive { get; set; }
|
||||||
|
public bool IsLive => MediaIsLive == "1";
|
||||||
|
[JsonProperty("media_views")]
|
||||||
|
public string Views { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TwitchResponse
|
||||||
|
{
|
||||||
|
public string Error { get; set; } = null;
|
||||||
|
public bool IsLive => Stream != null;
|
||||||
|
public StreamInfo Stream { get; set; }
|
||||||
|
|
||||||
|
public class StreamInfo
|
||||||
|
{
|
||||||
|
public int Viewers { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BeamResponse
|
||||||
|
{
|
||||||
|
public string Error { get; set; } = null;
|
||||||
|
|
||||||
|
[JsonProperty("online")]
|
||||||
|
public bool IsLive { get; set; }
|
||||||
|
public int ViewersCurrent { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StreamNotFoundException : Exception
|
||||||
|
{
|
||||||
|
public StreamNotFoundException(string message) : base("Stream '" + message + "' not found.")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Group]
|
[Group]
|
||||||
public class StreamNotificationCommands
|
public class StreamNotificationCommands
|
||||||
{
|
{
|
||||||
private Timer checkTimer { get; }
|
private static Timer checkTimer { get; }
|
||||||
private ConcurrentDictionary<string, StreamStatus> oldCachedStatuses = new ConcurrentDictionary<string, StreamStatus>();
|
private static ConcurrentDictionary<string, StreamStatus> oldCachedStatuses = new ConcurrentDictionary<string, StreamStatus>();
|
||||||
private ConcurrentDictionary<string, StreamStatus> cachedStatuses = new ConcurrentDictionary<string, StreamStatus>();
|
private static ConcurrentDictionary<string, StreamStatus> cachedStatuses = new ConcurrentDictionary<string, StreamStatus>();
|
||||||
private bool FirstPass { get; set; } = true;
|
private static Logger _log { get; }
|
||||||
|
|
||||||
public StreamNotificationCommands()
|
private static bool FirstPass { get; set; } = true;
|
||||||
|
|
||||||
|
static StreamNotificationCommands()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
_log = NLog.LogManager.GetCurrentClassLogger();
|
||||||
checkTimer = new Timer(async (state) =>
|
checkTimer = new Timer(async (state) =>
|
||||||
{
|
{
|
||||||
oldCachedStatuses = new ConcurrentDictionary<string, StreamStatus>(cachedStatuses);
|
oldCachedStatuses = new ConcurrentDictionary<string, StreamStatus>(cachedStatuses);
|
||||||
cachedStatuses = new ConcurrentDictionary<string, StreamStatus>();
|
cachedStatuses.Clear();
|
||||||
try
|
|
||||||
{
|
|
||||||
IEnumerable<FollowedStream> streams;
|
IEnumerable<FollowedStream> streams;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
streams = uow.GuildConfigs.GetAllFollowedStreams();
|
streams = uow.GuildConfigs.GetAllFollowedStreams();
|
||||||
}
|
}
|
||||||
foreach (var stream in streams)
|
|
||||||
|
await Task.WhenAll(streams.Select(async fs =>
|
||||||
{
|
{
|
||||||
StreamStatus data;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
data = await GetStreamStatus(stream).ConfigureAwait(false);
|
var newStatus = await GetStreamStatus(fs).ConfigureAwait(false);
|
||||||
if (data == null)
|
if (FirstPass)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamStatus oldData;
|
StreamStatus oldStatus;
|
||||||
oldCachedStatuses.TryGetValue(data.Link, out oldData);
|
if (oldCachedStatuses.TryGetValue(newStatus.ApiLink, out oldStatus) &&
|
||||||
|
oldStatus.IsLive != newStatus.IsLive)
|
||||||
if (oldData == null || data.IsLive != oldData.IsLive)
|
|
||||||
{
|
{
|
||||||
if (FirstPass)
|
var server = NadekoBot.Client.GetGuild(fs.GuildId);
|
||||||
continue;
|
var channel = server?.GetTextChannel(fs.ChannelId);
|
||||||
var server = NadekoBot.Client.GetGuild(stream.GuildId);
|
|
||||||
var channel = server?.GetTextChannel(stream.ChannelId);
|
|
||||||
if (channel == null)
|
if (channel == null)
|
||||||
continue;
|
return;
|
||||||
var msg = $"`{stream.Username}`'s stream is now " +
|
try
|
||||||
$"**{(data.IsLive ? "ONLINE" : "OFFLINE")}** with " +
|
{
|
||||||
$"**{data.Views}** viewers.";
|
var msg = await channel.EmbedAsync(fs.GetEmbed(newStatus).Build()).ConfigureAwait(false);
|
||||||
if (data.IsLive)
|
if (!newStatus.IsLive)
|
||||||
if (stream.Type == FollowedStream.FollowedStreamType.Hitbox)
|
msg.DeleteAfter(60);
|
||||||
msg += $"\n`Here is the Link:`【 http://www.hitbox.tv/{stream.Username}/ 】";
|
|
||||||
else if (stream.Type == FollowedStream.FollowedStreamType.Twitch)
|
|
||||||
msg += $"\n`Here is the Link:`【 http://www.twitch.tv/{stream.Username}/ 】";
|
|
||||||
else if (stream.Type == FollowedStream.FollowedStreamType.Beam)
|
|
||||||
msg += $"\n`Here is the Link:`【 http://www.beam.pro/{stream.Username}/ 】";
|
|
||||||
try { await channel.SendMessageAsync(msg).ConfigureAwait(false); } catch { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FirstPass = false;
|
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}));
|
||||||
|
|
||||||
|
FirstPass = false;
|
||||||
}, null, TimeSpan.Zero, TimeSpan.FromSeconds(60));
|
}, null, TimeSpan.Zero, TimeSpan.FromSeconds(60));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<StreamStatus> GetStreamStatus(FollowedStream stream, bool checkCache = true)
|
private static async Task<StreamStatus> GetStreamStatus(FollowedStream stream, bool checkCache = true)
|
||||||
{
|
{
|
||||||
bool isLive;
|
|
||||||
string response;
|
string response;
|
||||||
JObject data;
|
|
||||||
StreamStatus result;
|
StreamStatus result;
|
||||||
switch (stream.Type)
|
switch (stream.Type)
|
||||||
{
|
{
|
||||||
case FollowedStream.FollowedStreamType.Hitbox:
|
case FollowedStream.FollowedStreamType.Hitbox:
|
||||||
var hitboxUrl = $"https://api.hitbox.tv/media/status/{stream.Username}";
|
var hitboxUrl = $"https://api.hitbox.tv/media/status/{stream.Username.ToLowerInvariant()}";
|
||||||
if (checkCache && cachedStatuses.TryGetValue(hitboxUrl, out result))
|
if (checkCache && cachedStatuses.TryGetValue(hitboxUrl, out result))
|
||||||
return result;
|
return result;
|
||||||
using (var http = new HttpClient())
|
using (var http = new HttpClient())
|
||||||
{
|
{
|
||||||
response = await http.GetStringAsync(hitboxUrl).ConfigureAwait(false);
|
response = await http.GetStringAsync(hitboxUrl).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
data = JObject.Parse(response);
|
var hbData = JsonConvert.DeserializeObject<HitboxResponse>(response);
|
||||||
isLive = data["media_is_live"].ToString() == "1";
|
if (!hbData.Success)
|
||||||
result = new StreamStatus(hitboxUrl, isLive, data["media_views"].ToString());
|
throw new StreamNotFoundException($"{stream.Username} [{stream.Type}]");
|
||||||
cachedStatuses.TryAdd(hitboxUrl, result);
|
result = new StreamStatus()
|
||||||
|
{
|
||||||
|
IsLive = hbData.IsLive,
|
||||||
|
ApiLink = hitboxUrl,
|
||||||
|
Views = hbData.Views
|
||||||
|
};
|
||||||
|
cachedStatuses.AddOrUpdate(hitboxUrl, result, (key, old) => result);
|
||||||
return result;
|
return result;
|
||||||
case FollowedStream.FollowedStreamType.Twitch:
|
case FollowedStream.FollowedStreamType.Twitch:
|
||||||
var twitchUrl = $"https://api.twitch.tv/kraken/streams/{Uri.EscapeUriString(stream.Username)}?client_id=67w6z9i09xv2uoojdm9l0wsyph4hxo6";
|
var twitchUrl = $"https://api.twitch.tv/kraken/streams/{Uri.EscapeUriString(stream.Username.ToLowerInvariant())}?client_id=67w6z9i09xv2uoojdm9l0wsyph4hxo6";
|
||||||
if (checkCache && cachedStatuses.TryGetValue(twitchUrl, out result))
|
if (checkCache && cachedStatuses.TryGetValue(twitchUrl, out result))
|
||||||
return result;
|
return result;
|
||||||
using (var http = new HttpClient())
|
using (var http = new HttpClient())
|
||||||
{
|
{
|
||||||
response = await http.GetStringAsync(twitchUrl).ConfigureAwait(false);
|
response = await http.GetStringAsync(twitchUrl).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
data = JObject.Parse(response);
|
var twData = JsonConvert.DeserializeObject<TwitchResponse>(response);
|
||||||
isLive = !string.IsNullOrWhiteSpace(data["stream"].ToString());
|
if (twData.Error != null)
|
||||||
result = new StreamStatus(twitchUrl, isLive, isLive ? data["stream"]["viewers"].ToString() : "0");
|
{
|
||||||
cachedStatuses.TryAdd(twitchUrl, result);
|
throw new StreamNotFoundException($"{stream.Username} [{stream.Type}]");
|
||||||
|
}
|
||||||
|
result = new StreamStatus()
|
||||||
|
{
|
||||||
|
IsLive = twData.IsLive,
|
||||||
|
ApiLink = twitchUrl,
|
||||||
|
Views = twData.Stream?.Viewers.ToString() ?? "0"
|
||||||
|
};
|
||||||
|
cachedStatuses.AddOrUpdate(twitchUrl, result, (key, old) => result);
|
||||||
return result;
|
return result;
|
||||||
case FollowedStream.FollowedStreamType.Beam:
|
case FollowedStream.FollowedStreamType.Beam:
|
||||||
var beamUrl = $"https://beam.pro/api/v1/channels/{stream.Username}";
|
var beamUrl = $"https://beam.pro/api/v1/channels/{stream.Username.ToLowerInvariant()}";
|
||||||
if (checkCache && cachedStatuses.TryGetValue(beamUrl, out result))
|
if (checkCache && cachedStatuses.TryGetValue(beamUrl, out result))
|
||||||
return result;
|
return result;
|
||||||
using (var http = new HttpClient())
|
using (var http = new HttpClient())
|
||||||
{
|
{
|
||||||
response = await http.GetStringAsync(beamUrl).ConfigureAwait(false);
|
response = await http.GetStringAsync(beamUrl).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
data = JObject.Parse(response);
|
|
||||||
isLive = data["online"].ToObject<bool>() == true;
|
var bmData = JsonConvert.DeserializeObject<BeamResponse>(response);
|
||||||
result = new StreamStatus(beamUrl, isLive, data["viewersCurrent"].ToString());
|
if (bmData.Error != null)
|
||||||
cachedStatuses.TryAdd(beamUrl, result);
|
throw new StreamNotFoundException($"{stream.Username} [{stream.Type}]");
|
||||||
|
result = new StreamStatus()
|
||||||
|
{
|
||||||
|
IsLive = bmData.IsLive,
|
||||||
|
ApiLink = beamUrl,
|
||||||
|
Views = bmData.ViewersCurrent.ToString()
|
||||||
|
};
|
||||||
|
cachedStatuses.AddOrUpdate(beamUrl, result, (key, old) => result);
|
||||||
return result;
|
return result;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -178,12 +226,15 @@ namespace NadekoBot.Modules.Searches
|
|||||||
IEnumerable<FollowedStream> streams;
|
IEnumerable<FollowedStream> streams;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
streams = uow.GuildConfigs.For(channel.Guild.Id).FollowedStreams;
|
streams = uow.GuildConfigs
|
||||||
|
.For(channel.Guild.Id,
|
||||||
|
set => set.Include(gc => gc.FollowedStreams))
|
||||||
|
.FollowedStreams;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!streams.Any())
|
if (!streams.Any())
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("You are not following any streams on this server.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("You are not following any streams on this server.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,36 +243,39 @@ namespace NadekoBot.Modules.Searches
|
|||||||
return $"`{snc.Username}`'s stream on **{channel.Guild.GetTextChannel(snc.ChannelId)?.Name}** channel. 【`{snc.Type.ToString()}`】";
|
return $"`{snc.Username}`'s stream on **{channel.Guild.GetTextChannel(snc.ChannelId)?.Name}** channel. 【`{snc.Type.ToString()}`】";
|
||||||
}));
|
}));
|
||||||
|
|
||||||
await channel.SendMessageAsync($"You are following **{streams.Count()}** streams on this server.\n\n" + text).ConfigureAwait(false);
|
await channel.SendConfirmAsync($"You are following **{streams.Count()}** streams on this server.\n\n" + text).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[RequirePermission(GuildPermission.ManageMessages)]
|
[RequirePermission(GuildPermission.ManageMessages)]
|
||||||
public async Task RemoveStream(IUserMessage msg, [Remainder] string username)
|
public async Task RemoveStream(IUserMessage msg, FollowedStream.FollowedStreamType type, [Remainder] string username)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)msg.Channel;
|
var channel = (ITextChannel)msg.Channel;
|
||||||
|
|
||||||
username = username.ToLowerInvariant().Trim();
|
username = username.ToLowerInvariant().Trim();
|
||||||
|
|
||||||
FollowedStream toRemove;
|
var fs = new FollowedStream()
|
||||||
|
{
|
||||||
|
ChannelId = channel.Id,
|
||||||
|
Username = username,
|
||||||
|
Type = type
|
||||||
|
};
|
||||||
|
|
||||||
|
bool removed;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var config = uow.GuildConfigs.For(channel.Guild.Id);
|
var config = uow.GuildConfigs.For(channel.Guild.Id, set => set.Include(gc => gc.FollowedStreams));
|
||||||
var streams = config.FollowedStreams;
|
removed = config.FollowedStreams.Remove(fs);
|
||||||
toRemove = streams.Where(fs => fs.ChannelId == channel.Id && fs.Username.ToLowerInvariant() == username).FirstOrDefault();
|
if (removed)
|
||||||
if (toRemove != null)
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
{
|
|
||||||
config.FollowedStreams = new HashSet<FollowedStream>(streams.Except(new[] { toRemove }));
|
|
||||||
await uow.CompleteAsync();
|
|
||||||
}
|
}
|
||||||
}
|
if (!removed)
|
||||||
if (toRemove == null)
|
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync(":anger: No such stream.").ConfigureAwait(false);
|
await channel.SendErrorAsync("No such stream.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync($":ok: Removed `{toRemove.Username}`'s stream ({toRemove.Type}) from notifications.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"Removed `{username}`'s stream ({type}) from notifications.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -238,69 +292,86 @@ namespace NadekoBot.Modules.Searches
|
|||||||
var streamStatus = (await GetStreamStatus(new FollowedStream
|
var streamStatus = (await GetStreamStatus(new FollowedStream
|
||||||
{
|
{
|
||||||
Username = stream,
|
Username = stream,
|
||||||
Type = platform
|
Type = platform,
|
||||||
}));
|
}));
|
||||||
if (streamStatus.IsLive)
|
if (streamStatus.IsLive)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"`Streamer {username} is online with {streamStatus.Views} viewers.`");
|
await channel.SendConfirmAsync($"Streamer {username} is online with {streamStatus.Views} viewers.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"`Streamer {username} is offline.`");
|
await channel.SendConfirmAsync($"Streamer {username} is offline.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("No channel found.");
|
await channel.SendErrorAsync("No channel found.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task TrackStream(ITextChannel channel, string username, FollowedStream.FollowedStreamType type)
|
private async Task TrackStream(ITextChannel channel, string username, FollowedStream.FollowedStreamType type)
|
||||||
{
|
{
|
||||||
username = username.ToLowerInvariant().Trim();
|
username = username.ToLowerInvariant().Trim();
|
||||||
var stream = new FollowedStream
|
var fs = new FollowedStream
|
||||||
{
|
{
|
||||||
GuildId = channel.Guild.Id,
|
GuildId = channel.Guild.Id,
|
||||||
ChannelId = channel.Id,
|
ChannelId = channel.Id,
|
||||||
Username = username,
|
Username = username,
|
||||||
Type = type,
|
Type = type,
|
||||||
};
|
};
|
||||||
bool exists;
|
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
StreamStatus status;
|
||||||
{
|
|
||||||
exists = uow.GuildConfigs.For(channel.Guild.Id).FollowedStreams.Where(fs => fs.ChannelId == channel.Id && fs.Username.ToLowerInvariant().Trim() == username).Any();
|
|
||||||
}
|
|
||||||
if (exists)
|
|
||||||
{
|
|
||||||
await channel.SendMessageAsync($":anger: I am already following `{username}` ({type}) stream on this channel.").ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
StreamStatus data;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
data = await GetStreamStatus(stream).ConfigureAwait(false);
|
status = await GetStreamStatus(fs).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync(":anger: Stream probably doesn't exist.").ConfigureAwait(false);
|
await channel.SendErrorAsync("Stream probably doesn't exist.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var msg = $"Stream is currently **{(data.IsLive ? "ONLINE" : "OFFLINE")}** with **{data.Views}** viewers";
|
|
||||||
if (data.IsLive)
|
|
||||||
if (type == FollowedStream.FollowedStreamType.Hitbox)
|
|
||||||
msg += $"\n`Here is the Link:`【 http://www.hitbox.tv/{stream.Username}/ 】";
|
|
||||||
else if (type == FollowedStream.FollowedStreamType.Twitch)
|
|
||||||
msg += $"\n`Here is the Link:`【 http://www.twitch.tv/{stream.Username}/ 】";
|
|
||||||
else if (type == FollowedStream.FollowedStreamType.Beam)
|
|
||||||
msg += $"\n`Here is the Link:`【 https://beam.pro/{stream.Username}/ 】";
|
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
uow.GuildConfigs.For(channel.Guild.Id).FollowedStreams.Add(stream);
|
uow.GuildConfigs.For(channel.Guild.Id, set => set.Include(gc => gc.FollowedStreams))
|
||||||
await uow.CompleteAsync();
|
.FollowedStreams
|
||||||
|
.Add(fs);
|
||||||
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
msg = $":ok: I will notify this channel when status changes.\n{msg}";
|
await channel.EmbedAsync(fs.GetEmbed(status).Build(), $"🆗 I will notify this channel when status changes.").ConfigureAwait(false);
|
||||||
await channel.SendMessageAsync(msg).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class FollowedStreamExtensions
|
||||||
|
{
|
||||||
|
public static EmbedBuilder GetEmbed(this FollowedStream fs, Searches.StreamStatus status)
|
||||||
|
{
|
||||||
|
var embed = new EmbedBuilder().WithTitle(fs.Username)
|
||||||
|
.WithUrl(fs.GetLink())
|
||||||
|
.AddField(efb => efb.WithName("Status")
|
||||||
|
.WithValue(status.IsLive ? "Online" : "Offline")
|
||||||
|
.WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName("Viewers")
|
||||||
|
.WithValue(status.IsLive ? status.Views : "-")
|
||||||
|
.WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName("Platform")
|
||||||
|
.WithValue(fs.Type.ToString())
|
||||||
|
.WithIsInline(true))
|
||||||
|
.WithColor(status.IsLive ? NadekoBot.OkColor : NadekoBot.ErrorColor);
|
||||||
|
|
||||||
|
return embed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetLink(this FollowedStream fs) {
|
||||||
|
if (fs.Type == FollowedStream.FollowedStreamType.Hitbox)
|
||||||
|
return $"http://www.hitbox.tv/{fs.Username}/";
|
||||||
|
else if (fs.Type == FollowedStream.FollowedStreamType.Twitch)
|
||||||
|
return $"http://www.twitch.tv/{fs.Username}/";
|
||||||
|
else if (fs.Type == FollowedStream.FollowedStreamType.Beam)
|
||||||
|
return $"https://beam.pro/{fs.Username}/";
|
||||||
|
else
|
||||||
|
return "??";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -28,18 +28,17 @@ namespace NadekoBot.Modules.Searches
|
|||||||
TranslatedChannels = new ConcurrentDictionary<ulong, bool>();
|
TranslatedChannels = new ConcurrentDictionary<ulong, bool>();
|
||||||
UserLanguages = new ConcurrentDictionary<UserChannelPair, string>();
|
UserLanguages = new ConcurrentDictionary<UserChannelPair, string>();
|
||||||
|
|
||||||
NadekoBot.Client.MessageReceived += (msg) =>
|
NadekoBot.Client.MessageReceived += async (msg) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var umsg = msg as IUserMessage;
|
var umsg = msg as IUserMessage;
|
||||||
if(umsg == null)
|
if (umsg == null)
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
|
|
||||||
bool autoDelete;
|
bool autoDelete;
|
||||||
if (!TranslatedChannels.TryGetValue(umsg.Channel.Id, out autoDelete))
|
if (!TranslatedChannels.TryGetValue(umsg.Channel.Id, out autoDelete))
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
|
|
||||||
var t = Task.Run(async () =>
|
|
||||||
{
|
|
||||||
var key = new UserChannelPair()
|
var key = new UserChannelPair()
|
||||||
{
|
{
|
||||||
UserId = umsg.Author.Id,
|
UserId = umsg.Author.Id,
|
||||||
@ -50,18 +49,13 @@ namespace NadekoBot.Modules.Searches
|
|||||||
if (!UserLanguages.TryGetValue(key, out langs))
|
if (!UserLanguages.TryGetValue(key, out langs))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var text = await TranslateInternal(umsg, langs, umsg.Resolve(UserMentionHandling.Ignore), true)
|
var text = await TranslateInternal(umsg, langs, umsg.Resolve(UserMentionHandling.Ignore), true)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
if (autoDelete)
|
if (autoDelete)
|
||||||
try { await umsg.DeleteAsync().ConfigureAwait(false); } catch { }
|
try { await umsg.DeleteAsync().ConfigureAwait(false); } catch { }
|
||||||
await umsg.Channel.SendMessageAsync($"{umsg.Author.Mention} `:` "+text.Replace("<@ ", "<@").Replace("<@! ", "<@!")).ConfigureAwait(false);
|
await umsg.Channel.SendConfirmAsync($"{umsg.Author.Mention} `:` " + text.Replace("<@ ", "<@").Replace("<@! ", "<@!")).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
|
|
||||||
});
|
|
||||||
return Task.CompletedTask;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,12 +69,11 @@ namespace NadekoBot.Modules.Searches
|
|||||||
{
|
{
|
||||||
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
|
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
|
||||||
var translation = await TranslateInternal(umsg, langs, text);
|
var translation = await TranslateInternal(umsg, langs, text);
|
||||||
await channel.SendMessageAsync(translation).ConfigureAwait(false);
|
await channel.SendConfirmAsync("Translation " + langs, translation).ConfigureAwait(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("Bad input format, or something went wrong...").ConfigureAwait(false);
|
await channel.SendErrorAsync("Bad input format, or something went wrong...").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +87,7 @@ namespace NadekoBot.Modules.Searches
|
|||||||
text = text?.Trim();
|
text = text?.Trim();
|
||||||
if (string.IsNullOrWhiteSpace(text))
|
if (string.IsNullOrWhiteSpace(text))
|
||||||
throw new ArgumentException();
|
throw new ArgumentException();
|
||||||
return await GoogleTranslator.Instance.Translate(text, from, to).ConfigureAwait(false);
|
return (await GoogleTranslator.Instance.Translate(text, from, to).ConfigureAwait(false)).SanitizeMentions();
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum AutoDeleteAutoTranslate
|
public enum AutoDeleteAutoTranslate
|
||||||
@ -114,19 +107,19 @@ namespace NadekoBot.Modules.Searches
|
|||||||
if (autoDelete == AutoDeleteAutoTranslate.Del)
|
if (autoDelete == AutoDeleteAutoTranslate.Del)
|
||||||
{
|
{
|
||||||
TranslatedChannels.AddOrUpdate(channel.Id, true, (key, val) => true);
|
TranslatedChannels.AddOrUpdate(channel.Id, true, (key, val) => true);
|
||||||
try { await channel.SendMessageAsync("`Started automatic translation of messages on this channel. User messages will be auto-deleted.`").ConfigureAwait(false); } catch { }
|
try { await channel.SendConfirmAsync("Started automatic translation of messages on this channel. User messages will be auto-deleted.").ConfigureAwait(false); } catch { }
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool throwaway;
|
bool throwaway;
|
||||||
if (TranslatedChannels.TryRemove(channel.Id, out throwaway))
|
if (TranslatedChannels.TryRemove(channel.Id, out throwaway))
|
||||||
{
|
{
|
||||||
try { await channel.SendMessageAsync("`Stopped automatic translation of messages on this channel.`").ConfigureAwait(false); } catch { }
|
try { await channel.SendConfirmAsync("Stopped automatic translation of messages on this channel.").ConfigureAwait(false); } catch { }
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (TranslatedChannels.TryAdd(channel.Id, autoDelete == AutoDeleteAutoTranslate.Del))
|
else if (TranslatedChannels.TryAdd(channel.Id, autoDelete == AutoDeleteAutoTranslate.Del))
|
||||||
{
|
{
|
||||||
try { await channel.SendMessageAsync("`Started automatic translation of messages on this channel.`").ConfigureAwait(false); } catch { }
|
try { await channel.SendConfirmAsync("Started automatic translation of messages on this channel.").ConfigureAwait(false); } catch { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +138,7 @@ namespace NadekoBot.Modules.Searches
|
|||||||
if (string.IsNullOrWhiteSpace(langs))
|
if (string.IsNullOrWhiteSpace(langs))
|
||||||
{
|
{
|
||||||
if (UserLanguages.TryRemove(ucp, out langs))
|
if (UserLanguages.TryRemove(ucp, out langs))
|
||||||
await channel.SendMessageAsync($"{msg.Author.Mention}'s auto-translate language has been removed.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"{msg.Author.Mention}'s auto-translate language has been removed.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,13 +150,13 @@ namespace NadekoBot.Modules.Searches
|
|||||||
|
|
||||||
if (!GoogleTranslator.Instance.Languages.Contains(from) || !GoogleTranslator.Instance.Languages.Contains(to))
|
if (!GoogleTranslator.Instance.Languages.Contains(from) || !GoogleTranslator.Instance.Languages.Contains(to))
|
||||||
{
|
{
|
||||||
try { await channel.SendMessageAsync("`Invalid source and/or target Language.`").ConfigureAwait(false); } catch { }
|
try { await channel.SendErrorAsync("Invalid source and/or target language.").ConfigureAwait(false); } catch { }
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UserLanguages.AddOrUpdate(ucp, langs, (key, val) => langs);
|
UserLanguages.AddOrUpdate(ucp, langs, (key, val) => langs);
|
||||||
|
|
||||||
await channel.SendMessageAsync(":ok:").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"Your auto-translate language has been set to {from}>{to}").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
@ -55,12 +56,17 @@ namespace NadekoBot.Modules.Searches
|
|||||||
var res = await http.GetStringAsync($"{xkcdUrl}/{num}/info.0.json").ConfigureAwait(false);
|
var res = await http.GetStringAsync($"{xkcdUrl}/{num}/info.0.json").ConfigureAwait(false);
|
||||||
|
|
||||||
var comic = JsonConvert.DeserializeObject<XkcdComic>(res);
|
var comic = JsonConvert.DeserializeObject<XkcdComic>(res);
|
||||||
var sent = await channel.SendMessageAsync($"{msg.Author.Mention} " + comic.ToString())
|
var embed = new EmbedBuilder().WithOkColor()
|
||||||
|
.WithImage(eib => eib.WithUrl(comic.ImageLink))
|
||||||
|
.WithAuthor(eab => eab.WithName(comic.Title).WithUrl($"{xkcdUrl}/{num}").WithIconUrl("http://xkcd.com/s/919f27.ico"))
|
||||||
|
.AddField(efb => efb.WithName("Comic#").WithValue(comic.Num.ToString()).WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName("Date").WithValue($"{comic.Month}/{comic.Year}").WithIsInline(true));
|
||||||
|
var sent = await channel.EmbedAsync(embed.Build())
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
await Task.Delay(10000).ConfigureAwait(false);
|
await Task.Delay(10000).ConfigureAwait(false);
|
||||||
|
|
||||||
await sent.ModifyAsync(m => m.Content = sent.Content + $"\n`Alt:` {comic.Alt}");
|
await sent.ModifyAsync(m => m.Embed = embed.AddField(efb => efb.WithName("Alt").WithValue(comic.Alt.ToString()).WithIsInline(false)).Build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,43 +17,45 @@ using ImageSharp;
|
|||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using NadekoBot.Modules.Searches.Commands.OMDB;
|
using NadekoBot.Modules.Searches.Commands.OMDB;
|
||||||
|
using NadekoBot.Modules.Searches.Commands.Models;
|
||||||
|
using AngleSharp.Parser.Html;
|
||||||
|
using AngleSharp;
|
||||||
|
using AngleSharp.Dom.Html;
|
||||||
|
using AngleSharp.Dom;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Searches
|
namespace NadekoBot.Modules.Searches
|
||||||
{
|
{
|
||||||
[NadekoModule("Searches", "~")]
|
[NadekoModule("Searches", "~")]
|
||||||
public partial class Searches : DiscordModule
|
public partial class Searches : DiscordModule
|
||||||
{
|
{
|
||||||
private IGoogleApiService _google { get; }
|
|
||||||
|
|
||||||
public Searches(ILocalization loc, CommandService cmds, ShardedDiscordClient client, IGoogleApiService youtube) : base(loc, cmds, client)
|
|
||||||
{
|
|
||||||
_google = youtube;
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task Weather(IUserMessage umsg, string city, string country)
|
public async Task Weather(IUserMessage umsg, [Remainder] string query)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
city = city.Replace(" ", "");
|
if (string.IsNullOrWhiteSpace(query))
|
||||||
country = city.Replace(" ", "");
|
return;
|
||||||
|
|
||||||
string response;
|
string response;
|
||||||
using (var http = new HttpClient())
|
using (var http = new HttpClient())
|
||||||
response = await http.GetStringAsync($"http://api.ninetales.us/nadekobot/weather/?city={city}&country={country}").ConfigureAwait(false);
|
response = await http.GetStringAsync($"http://api.openweathermap.org/data/2.5/weather?q={query}&appid=42cd627dd60debf25a5739e50a217d74&units=metric").ConfigureAwait(false);
|
||||||
|
|
||||||
var obj = JObject.Parse(response)["weather"];
|
var data = JsonConvert.DeserializeObject<WeatherData>(response);
|
||||||
|
|
||||||
var embed = new EmbedBuilder()
|
var embed = new EmbedBuilder()
|
||||||
.AddField(fb => fb.WithName("🌍 Location").WithValue($"{obj["target"]}").WithIsInline(true))
|
.AddField(fb => fb.WithName("🌍 **Location**").WithValue(data.name + ", " + data.sys.country).WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("📏 Lat,Long").WithValue($"{obj["latitude"]}, {obj["longitude"]}").WithIsInline(true))
|
.AddField(fb => fb.WithName("📏 **Lat,Long**").WithValue($"{data.coord.lat}, {data.coord.lon}").WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("☁ Condition").WithValue($"{obj["condition"]}").WithIsInline(true))
|
.AddField(fb => fb.WithName("☁ **Condition**").WithValue(String.Join(", ", data.weather.Select(w => w.main))).WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("😓 Humidity").WithValue($"{obj["humidity"]}%").WithIsInline(true))
|
.AddField(fb => fb.WithName("😓 **Humidity**").WithValue($"{data.main.humidity}%").WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("💨 Wind Speed").WithValue($"{obj["windspeedk"]}km/h / {obj["windspeedm"]}mph").WithIsInline(true))
|
.AddField(fb => fb.WithName("💨 **Wind Speed**").WithValue(data.wind.speed + " km/h").WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("🌡 Temperature").WithValue($"{obj["centigrade"]}°C / {obj["fahrenheit"]}°F").WithIsInline(true))
|
.AddField(fb => fb.WithName("🌡 **Temperature**").WithValue(data.main.temp + "°C").WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("🔆 Feels like").WithValue($"{obj["feelscentigrade"]}°C / {obj["feelsfahrenheit"]}°F").WithIsInline(true))
|
.AddField(fb => fb.WithName("🔆 **Min - Max**").WithValue($"{data.main.temp_min}°C - {data.main.temp_max}°C").WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("🌄 Sunrise").WithValue($"{obj["sunrise"]}").WithIsInline(true))
|
.AddField(fb => fb.WithName("🌄 **Sunrise (utc)**").WithValue($"{data.sys.sunrise.ToUnixTimestamp():HH:mm}").WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("🌇 Sunset").WithValue($"{obj["sunset"]}").WithIsInline(true))
|
.AddField(fb => fb.WithName("🌇 **Sunset (utc)**").WithValue($"{data.sys.sunset.ToUnixTimestamp():HH:mm}").WithIsInline(true))
|
||||||
.WithColor(NadekoBot.OkColor);
|
.WithOkColor()
|
||||||
|
.WithFooter(efb => efb.WithText("Powered by http://openweathermap.org"));
|
||||||
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,13 +65,16 @@ namespace NadekoBot.Modules.Searches
|
|||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
if (!(await ValidateQuery(channel, query).ConfigureAwait(false))) return;
|
if (!(await ValidateQuery(channel, query).ConfigureAwait(false))) return;
|
||||||
var result = (await _google.GetVideosByKeywordsAsync(query, 1)).FirstOrDefault();
|
var result = (await NadekoBot.Google.GetVideosByKeywordsAsync(query, 1)).FirstOrDefault();
|
||||||
if (string.IsNullOrWhiteSpace(result))
|
if (string.IsNullOrWhiteSpace(result))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("No results found for that query.");
|
await channel.SendErrorAsync("No results found for that query.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync(result).ConfigureAwait(false);
|
await channel.SendMessageAsync(result).ConfigureAwait(false);
|
||||||
|
|
||||||
|
//await channel.EmbedAsync(new Discord.API.Embed() { Video = new Discord.API.EmbedVideo() { Url = result.Replace("watch?v=", "embed/") }, Color = NadekoBot.OkColor }).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -84,10 +89,10 @@ namespace NadekoBot.Modules.Searches
|
|||||||
var movie = await OmdbProvider.FindMovie(query);
|
var movie = await OmdbProvider.FindMovie(query);
|
||||||
if (movie == null)
|
if (movie == null)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("Failed to find that movie.").ConfigureAwait(false);
|
await channel.SendErrorAsync("Failed to find that movie.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync(movie.ToString()).ConfigureAwait(false);
|
await channel.EmbedAsync(movie.GetEmbed()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -97,9 +102,8 @@ namespace NadekoBot.Modules.Searches
|
|||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
using (var http = new HttpClient())
|
using (var http = new HttpClient())
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync(JObject.Parse(
|
var res = JObject.Parse(await http.GetStringAsync("http://www.random.cat/meow").ConfigureAwait(false));
|
||||||
await http.GetStringAsync("http://www.random.cat/meow").ConfigureAwait(false))["file"].ToString())
|
await channel.SendMessageAsync(res["file"].ToString()).ConfigureAwait(false);
|
||||||
.ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +114,8 @@ namespace NadekoBot.Modules.Searches
|
|||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
using (var http = new HttpClient())
|
using (var http = new HttpClient())
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("http://random.dog/" + await http.GetStringAsync("http://random.dog/woof").ConfigureAwait(false)).ConfigureAwait(false);
|
await channel.SendMessageAsync("http://random.dog/" + await http.GetStringAsync("http://random.dog/woof")
|
||||||
|
.ConfigureAwait(false)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,11 +140,12 @@ namespace NadekoBot.Modules.Searches
|
|||||||
{
|
{
|
||||||
if (exception.Message.Contains("403 (Forbidden)"))
|
if (exception.Message.Contains("403 (Forbidden)"))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("Daily limit reached!");
|
await channel.SendErrorAsync("Daily limit reached!");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("Something went wrong.");
|
await channel.SendErrorAsync("Something went wrong.");
|
||||||
|
_log.Error(exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -167,11 +173,12 @@ namespace NadekoBot.Modules.Searches
|
|||||||
{
|
{
|
||||||
if (exception.Message.Contains("403 (Forbidden)"))
|
if (exception.Message.Contains("403 (Forbidden)"))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("Daily limit reached!");
|
await channel.SendErrorAsync("Daily limit reached!");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("Something went wrong.");
|
await channel.SendErrorAsync("Something went wrong.");
|
||||||
|
_log.Error(exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -186,7 +193,7 @@ namespace NadekoBot.Modules.Searches
|
|||||||
if (string.IsNullOrWhiteSpace(ffs))
|
if (string.IsNullOrWhiteSpace(ffs))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await channel.SendMessageAsync(await _google.ShortenUrl($"<http://lmgtfy.com/?q={ Uri.EscapeUriString(ffs) }>"))
|
await channel.SendConfirmAsync(await NadekoBot.Google.ShortenUrl($"<http://lmgtfy.com/?q={ Uri.EscapeUriString(ffs) }>"))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,21 +204,78 @@ namespace NadekoBot.Modules.Searches
|
|||||||
if (string.IsNullOrWhiteSpace(arg))
|
if (string.IsNullOrWhiteSpace(arg))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await msg.Channel.SendMessageAsync(await NadekoBot.Google.ShortenUrl(arg).ConfigureAwait(false));
|
var shortened = await NadekoBot.Google.ShortenUrl(arg).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (shortened == arg)
|
||||||
|
{
|
||||||
|
await msg.Channel.SendErrorAsync("Failed to shorten that url.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await msg.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||||
|
.AddField(efb => efb.WithName("Original Url")
|
||||||
|
.WithValue($"<{arg}>"))
|
||||||
|
.AddField(efb => efb.WithName("Short Url")
|
||||||
|
.WithValue($"<{shortened}>"))
|
||||||
|
.Build())
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//private readonly Regex googleSearchRegex = new Regex(@"<h3 class=""r""><a href=""(?:\/url?q=)?(?<link>.*?)"".*?>(?<title>.*?)<\/a>.*?class=""st"">(?<text>.*?)<\/span>", RegexOptions.Compiled);
|
||||||
|
//private readonly Regex htmlReplace = new Regex(@"(?:<b>(.*?)<\/b>|<em>(.*?)<\/em>)", RegexOptions.Compiled);
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task Google(IUserMessage umsg, [Remainder] string terms = null)
|
public async Task Google(IUserMessage umsg, [Remainder] string terms = null)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
|
|
||||||
terms = terms?.Trim();
|
terms = terms?.Trim();
|
||||||
if (string.IsNullOrWhiteSpace(terms))
|
if (string.IsNullOrWhiteSpace(terms))
|
||||||
return;
|
return;
|
||||||
await channel.SendMessageAsync($"https://google.com/search?q={ WebUtility.UrlEncode(terms).Replace(' ', '+') }")
|
|
||||||
|
terms = WebUtility.UrlEncode(terms).Replace(' ', '+');
|
||||||
|
|
||||||
|
var fullQueryLink = $"https://www.google.com/search?q={ terms }&gws_rd=cr,ssl";
|
||||||
|
var config = Configuration.Default.WithDefaultLoader();
|
||||||
|
var document = await BrowsingContext.New(config).OpenAsync(fullQueryLink);
|
||||||
|
|
||||||
|
var elems = document.QuerySelectorAll("div.g");
|
||||||
|
|
||||||
|
var resultsElem = document.QuerySelectorAll("#resultStats").FirstOrDefault();
|
||||||
|
var totalResults = resultsElem?.TextContent;
|
||||||
|
//var time = resultsElem.Children.FirstOrDefault()?.TextContent
|
||||||
|
//^ this doesn't work for some reason, <nobr> is completely missing in parsed collection
|
||||||
|
if (!elems.Any())
|
||||||
|
return;
|
||||||
|
|
||||||
|
var results = elems.Select<IElement, GoogleSearchResult?>(elem =>
|
||||||
|
{
|
||||||
|
var aTag = (elem.Children.FirstOrDefault().Children.FirstOrDefault() as IHtmlAnchorElement); // <h3> -> <a>
|
||||||
|
var href = aTag?.Href;
|
||||||
|
var name = aTag?.TextContent;
|
||||||
|
if (href == null || name == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var txt = elem.QuerySelectorAll(".st").FirstOrDefault()?.TextContent;
|
||||||
|
|
||||||
|
if (txt == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return new GoogleSearchResult(name, href, txt);
|
||||||
|
}).Where(x => x != null).Take(5);
|
||||||
|
|
||||||
|
var embed = new EmbedBuilder()
|
||||||
|
.WithOkColor()
|
||||||
|
.WithAuthor(eab => eab.WithName("Search For: " + terms.TrimTo(50))
|
||||||
|
.WithUrl(fullQueryLink)
|
||||||
|
.WithIconUrl("http://i.imgur.com/G46fm8J.png"))
|
||||||
|
.WithTitle(umsg.Author.Mention)
|
||||||
|
.WithFooter(efb => efb.WithText(totalResults));
|
||||||
|
|
||||||
|
var desc = await Task.WhenAll(results.Select(async res =>
|
||||||
|
$"[{Format.Bold(res?.Title)}]({(await NadekoBot.Google.ShortenUrl(res?.Link))})\n{res?.Text}\n\n"))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
await channel.EmbedAsync(embed.WithDescription(String.Concat(desc)).Build()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -222,7 +286,7 @@ namespace NadekoBot.Modules.Searches
|
|||||||
var arg = name;
|
var arg = name;
|
||||||
if (string.IsNullOrWhiteSpace(arg))
|
if (string.IsNullOrWhiteSpace(arg))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 `Please enter a card name to search for.`").ConfigureAwait(false);
|
await channel.SendErrorAsync("Please enter a card name to search for.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,18 +302,26 @@ namespace NadekoBot.Modules.Searches
|
|||||||
var items = JArray.Parse(response).Shuffle().ToList();
|
var items = JArray.Parse(response).Shuffle().ToList();
|
||||||
if (items == null)
|
if (items == null)
|
||||||
throw new KeyNotFoundException("Cannot find a card by that name");
|
throw new KeyNotFoundException("Cannot find a card by that name");
|
||||||
var msg = $@"```css
|
var item = items[0];
|
||||||
[☕ Magic The Gathering]: {items[0]["name"].ToString()}
|
var storeUrl = await NadekoBot.Google.ShortenUrl(item["store_url"].ToString());
|
||||||
[Store URL]: {await _google.ShortenUrl(items[0]["store_url"].ToString())}
|
var cost = item["cost"].ToString();
|
||||||
[Cost]: {items[0]["cost"].ToString()}
|
var desc = item["text"].ToString();
|
||||||
[Description]: {items[0]["text"].ToString()}
|
var types = String.Join(",\n", item["types"].ToObject<string[]>());
|
||||||
```
|
var img = item["editions"][0]["image_url"].ToString();
|
||||||
{items[0]["editions"][0]["image_url"].ToString()}";
|
var embed = new EmbedBuilder().WithOkColor()
|
||||||
await channel.SendMessageAsync(msg).ConfigureAwait(false);
|
.WithTitle(item["name"].ToString())
|
||||||
|
.WithDescription(desc)
|
||||||
|
.WithImage(eib => eib.WithUrl(img))
|
||||||
|
.AddField(efb => efb.WithName("Store Url").WithValue(storeUrl).WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName("Cost").WithValue(cost).WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName("Types").WithValue(types).WithIsInline(true));
|
||||||
|
//.AddField(efb => efb.WithName("Store Url").WithValue(await NadekoBot.Google.ShortenUrl(items[0]["store_url"].ToString())).WithIsInline(true));
|
||||||
|
|
||||||
|
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"💢 Error could not find the card {arg}").ConfigureAwait(false);
|
await channel.SendErrorAsync($"Error could not find the card '{arg}'.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -262,13 +334,13 @@ namespace NadekoBot.Modules.Searches
|
|||||||
var arg = name;
|
var arg = name;
|
||||||
if (string.IsNullOrWhiteSpace(arg))
|
if (string.IsNullOrWhiteSpace(arg))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 `Please enter a card name to search for.`").ConfigureAwait(false);
|
await channel.SendErrorAsync("Please enter a card name to search for.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.MashapeKey))
|
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.MashapeKey))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 `Bot owner didn't specify MashapeApiKey. You can't use this functionality.`").ConfigureAwait(false);
|
await channel.SendErrorAsync("Bot owner didn't specify MashapeApiKey. You can't use this functionality.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,7 +380,49 @@ namespace NadekoBot.Modules.Searches
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"💢 Error {ex.Message}").ConfigureAwait(false);
|
await channel.SendErrorAsync($"Error occured.").ConfigureAwait(false);
|
||||||
|
_log.Error(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task Yodify(IUserMessage umsg, [Remainder] string query = null)
|
||||||
|
{
|
||||||
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.MashapeKey))
|
||||||
|
{
|
||||||
|
await channel.SendErrorAsync("Bot owner didn't specify MashapeApiKey. You can't use this functionality.").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var arg = query;
|
||||||
|
if (string.IsNullOrWhiteSpace(arg))
|
||||||
|
{
|
||||||
|
await channel.SendErrorAsync("Please enter a sentence.").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
|
||||||
|
using (var http = new HttpClient())
|
||||||
|
{
|
||||||
|
http.DefaultRequestHeaders.Clear();
|
||||||
|
http.DefaultRequestHeaders.Add("X-Mashape-Key", NadekoBot.Credentials.MashapeKey);
|
||||||
|
http.DefaultRequestHeaders.Add("Accept", "text/plain");
|
||||||
|
var res = await http.GetStringAsync($"https://yoda.p.mashape.com/yoda?sentence={Uri.EscapeUriString(arg)}").ConfigureAwait(false);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var embed = new EmbedBuilder()
|
||||||
|
.WithUrl("http://www.yodaspeak.co.uk/")
|
||||||
|
.WithAuthor(au => au.WithName("Yoda").WithIconUrl("http://www.yodaspeak.co.uk/yoda-small1.gif"))
|
||||||
|
.WithDescription(res)
|
||||||
|
.WithOkColor();
|
||||||
|
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await channel.SendErrorAsync("Failed to yodify your sentence.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -321,38 +435,78 @@ namespace NadekoBot.Modules.Searches
|
|||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.MashapeKey))
|
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.MashapeKey))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 `Bot owner didn't specify MashapeApiKey. You can't use this functionality.`").ConfigureAwait(false);
|
await channel.SendErrorAsync("Bot owner didn't specify MashapeApiKey. You can't use this functionality.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var arg = query;
|
var arg = query;
|
||||||
if (string.IsNullOrWhiteSpace(arg))
|
if (string.IsNullOrWhiteSpace(arg))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 `Please enter a search term.`").ConfigureAwait(false);
|
await channel.SendErrorAsync("Please enter a search term.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
|
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
|
||||||
using (var http = new HttpClient())
|
using (var http = new HttpClient())
|
||||||
{
|
{
|
||||||
http.DefaultRequestHeaders.Clear();
|
http.DefaultRequestHeaders.Clear();
|
||||||
http.DefaultRequestHeaders.Add("X-Mashape-Key", NadekoBot.Credentials.MashapeKey);
|
http.DefaultRequestHeaders.Add("Accept", "application/json");
|
||||||
var res = await http.GetStringAsync($"https://mashape-community-urban-dictionary.p.mashape.com/define?term={Uri.EscapeUriString(arg)}").ConfigureAwait(false);
|
var res = await http.GetStringAsync($"http://api.urbandictionary.com/v0/define?term={Uri.EscapeUriString(arg)}").ConfigureAwait(false);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var items = JObject.Parse(res);
|
var items = JObject.Parse(res);
|
||||||
var sb = new StringBuilder();
|
var item = items["list"][0];
|
||||||
sb.AppendLine($"`Term:` {items["list"][0]["word"].ToString()}");
|
var word = item["word"].ToString();
|
||||||
sb.AppendLine($"`Definition:` {items["list"][0]["definition"].ToString()}");
|
var def = item["definition"].ToString();
|
||||||
sb.Append($"`Link:` <{await _google.ShortenUrl(items["list"][0]["permalink"].ToString()).ConfigureAwait(false)}>");
|
var link = item["permalink"].ToString();
|
||||||
await channel.SendMessageAsync(sb.ToString());
|
var embed = new EmbedBuilder().WithOkColor()
|
||||||
|
.WithUrl(link)
|
||||||
|
.WithAuthor(eab => eab.WithIconUrl("http://i.imgur.com/nwERwQE.jpg").WithName(word))
|
||||||
|
.WithDescription(def);
|
||||||
|
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 Failed finding a definition for that term.").ConfigureAwait(false);
|
await channel.SendErrorAsync("Failed finding a definition for that term.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task Define(IUserMessage msg, [Remainder] string word)
|
||||||
|
{
|
||||||
|
var channel = (ITextChannel)msg.Channel;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(word))
|
||||||
|
return;
|
||||||
|
|
||||||
|
using (var http = new HttpClient())
|
||||||
|
{
|
||||||
|
var res = await http.GetStringAsync("http://api.pearson.com/v2/dictionaries/entries?headword=" + WebUtility.UrlEncode(word.Trim())).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var data = JsonConvert.DeserializeObject<DefineModel>(res);
|
||||||
|
|
||||||
|
var sense = data.Results.Where(x => x.Senses != null && x.Senses[0].Definition != null).FirstOrDefault()?.Senses[0];
|
||||||
|
|
||||||
|
if (sense?.Definition == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
string definition = sense.Definition.ToString();
|
||||||
|
if (!(sense.Definition is string))
|
||||||
|
definition = ((JArray)JToken.Parse(sense.Definition.ToString())).First.ToString();
|
||||||
|
|
||||||
|
var embed = new EmbedBuilder().WithOkColor()
|
||||||
|
.WithTitle("Define: " + word)
|
||||||
|
.WithDescription(definition)
|
||||||
|
.WithFooter(efb => efb.WithText(sense.Gramatical_info?.type));
|
||||||
|
|
||||||
|
if (sense.Examples != null)
|
||||||
|
embed.AddField(efb => efb.WithName("Example").WithValue(sense.Examples.First().text));
|
||||||
|
|
||||||
|
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task Hashtag(IUserMessage umsg, [Remainder] string query = null)
|
public async Task Hashtag(IUserMessage umsg, [Remainder] string query = null)
|
||||||
@ -362,12 +516,12 @@ namespace NadekoBot.Modules.Searches
|
|||||||
var arg = query;
|
var arg = query;
|
||||||
if (string.IsNullOrWhiteSpace(arg))
|
if (string.IsNullOrWhiteSpace(arg))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 `Please enter a search term.`").ConfigureAwait(false);
|
await channel.SendErrorAsync("Please enter a search term.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.MashapeKey))
|
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.MashapeKey))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 `Bot owner didn't specify MashapeApiKey. You can't use this functionality.`").ConfigureAwait(false);
|
await channel.SendErrorAsync("Bot owner didn't specify MashapeApiKey. You can't use this functionality.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,14 +537,20 @@ namespace NadekoBot.Modules.Searches
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var items = JObject.Parse(res);
|
var items = JObject.Parse(res);
|
||||||
var str = $@"`Hashtag:` {items["defs"]["def"]["hashtag"].ToString()}
|
var item = items["defs"]["def"];
|
||||||
`Definition:` {items["defs"]["def"]["text"].ToString()}
|
var hashtag = item["hashtag"].ToString();
|
||||||
`Link:` <{await _google.ShortenUrl(items["defs"]["def"]["uri"].ToString()).ConfigureAwait(false)}>";
|
var link = item["uri"].ToString();
|
||||||
await channel.SendMessageAsync(str);
|
var desc = item["text"].ToString();
|
||||||
|
await channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||||
|
.WithAuthor(eab => eab.WithUrl(link)
|
||||||
|
.WithIconUrl("http://res.cloudinary.com/urbandictionary/image/upload/a_exif,c_fit,h_200,w_200/v1394975045/b8oszuu3tbq7ebyo7vo1.jpg")
|
||||||
|
.WithName(query))
|
||||||
|
.WithDescription(desc)
|
||||||
|
.Build());
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 Failed finding a definition for that tag.").ConfigureAwait(false);
|
await channel.SendErrorAsync("Failed finding a definition for that tag.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,7 +564,9 @@ namespace NadekoBot.Modules.Searches
|
|||||||
var response = await http.GetStringAsync("http://catfacts-api.appspot.com/api/facts").ConfigureAwait(false);
|
var response = await http.GetStringAsync("http://catfacts-api.appspot.com/api/facts").ConfigureAwait(false);
|
||||||
if (response == null)
|
if (response == null)
|
||||||
return;
|
return;
|
||||||
await channel.SendMessageAsync($"🐈 `{JObject.Parse(response)["facts"][0].ToString()}`").ConfigureAwait(false);
|
|
||||||
|
var fact = JObject.Parse(response)["facts"][0].ToString();
|
||||||
|
await channel.SendConfirmAsync("🐈fact", fact).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,7 +578,7 @@ namespace NadekoBot.Modules.Searches
|
|||||||
|
|
||||||
if (usr == null)
|
if (usr == null)
|
||||||
usr = umsg.Author;
|
usr = umsg.Author;
|
||||||
await channel.SendMessageAsync($"https://images.google.com/searchbyimage?image_url={usr.AvatarUrl}").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"https://images.google.com/searchbyimage?image_url={usr.AvatarUrl}").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -428,22 +590,13 @@ namespace NadekoBot.Modules.Searches
|
|||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(imageLink))
|
if (string.IsNullOrWhiteSpace(imageLink))
|
||||||
return;
|
return;
|
||||||
await channel.SendMessageAsync($"https://images.google.com/searchbyimage?image_url={imageLink}").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"https://images.google.com/searchbyimage?image_url={imageLink}").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task Safebooru(IUserMessage umsg, [Remainder] string tag = null)
|
public Task Safebooru(IUserMessage umsg, [Remainder] string tag = null)
|
||||||
{
|
=> InternalDapiCommand(umsg, tag, DapiSearchType.Safebooru);
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
|
|
||||||
tag = tag?.Trim() ?? "";
|
|
||||||
var link = await GetSafebooruImageLink(tag).ConfigureAwait(false);
|
|
||||||
if (link == null)
|
|
||||||
await channel.SendMessageAsync("`No results.`");
|
|
||||||
else
|
|
||||||
await channel.SendMessageAsync(link).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
@ -459,7 +612,7 @@ namespace NadekoBot.Modules.Searches
|
|||||||
var result = await http.GetStringAsync("https://en.wikipedia.org//w/api.php?action=query&format=json&prop=info&redirects=1&formatversion=2&inprop=url&titles=" + Uri.EscapeDataString(query));
|
var result = await http.GetStringAsync("https://en.wikipedia.org//w/api.php?action=query&format=json&prop=info&redirects=1&formatversion=2&inprop=url&titles=" + Uri.EscapeDataString(query));
|
||||||
var data = JsonConvert.DeserializeObject<WikipediaApiModel>(result);
|
var data = JsonConvert.DeserializeObject<WikipediaApiModel>(result);
|
||||||
if (data.Query.Pages[0].Missing)
|
if (data.Query.Pages[0].Missing)
|
||||||
await channel.SendMessageAsync("`That page could not be found.`");
|
await channel.SendErrorAsync("That page could not be found.");
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync(data.Query.Pages[0].FullUrl);
|
await channel.SendMessageAsync(data.Query.Pages[0].FullUrl);
|
||||||
}
|
}
|
||||||
@ -499,12 +652,12 @@ namespace NadekoBot.Modules.Searches
|
|||||||
str += new NadekoRandom().Next();
|
str += new NadekoRandom().Next();
|
||||||
foreach (var usr in allUsrsArray)
|
foreach (var usr in allUsrsArray)
|
||||||
{
|
{
|
||||||
await (await (usr as IGuildUser).CreateDMChannelAsync()).SendMessageAsync(str).ConfigureAwait(false);
|
await (await (usr as IGuildUser).CreateDMChannelAsync()).SendConfirmAsync(str).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine(ex);
|
_log.Error(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -517,180 +670,10 @@ namespace NadekoBot.Modules.Searches
|
|||||||
var usr = umsg.MentionedUsers.FirstOrDefault();
|
var usr = umsg.MentionedUsers.FirstOrDefault();
|
||||||
if (usr == null)
|
if (usr == null)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("Invalid user specified.").ConfigureAwait(false);
|
await channel.SendErrorAsync("Invalid user specified.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync(await _google.ShortenUrl(usr.AvatarUrl).ConfigureAwait(false)).ConfigureAwait(false);
|
await channel.SendMessageAsync(await NadekoBot.Google.ShortenUrl(usr.AvatarUrl).ConfigureAwait(false)).ConfigureAwait(false);
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<string> GetSafebooruImageLink(string tag)
|
|
||||||
{
|
|
||||||
var rng = new NadekoRandom();
|
|
||||||
var url =
|
|
||||||
$"http://safebooru.org/index.php?page=dapi&s=post&q=index&limit=100&tags={tag.Replace(" ", "_")}";
|
|
||||||
using (var http = new HttpClient())
|
|
||||||
{
|
|
||||||
var webpage = await http.GetStringAsync(url).ConfigureAwait(false);
|
|
||||||
var matches = Regex.Matches(webpage, "file_url=\"(?<url>.*?)\"");
|
|
||||||
if (matches.Count == 0)
|
|
||||||
return null;
|
|
||||||
var match = matches[rng.Next(0, matches.Count)];
|
|
||||||
return "http:" + matches[rng.Next(0, matches.Count)].Groups["url"].Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
public async Task BFO(IUserMessage umsg, [Remainder] string game = null)
|
|
||||||
{
|
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
if (string.IsNullOrWhiteSpace(game))
|
|
||||||
{
|
|
||||||
await channel.SendMessageAsync("💢 Please enter a game `(bf3, bf4)`").ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
|
|
||||||
using (var http = new HttpClient())
|
|
||||||
{
|
|
||||||
http.DefaultRequestHeaders.Clear();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (game.Equals("bf3", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
var res = await http.GetStringAsync($"http://api.bf3stats.com/global/onlinestats/").ConfigureAwait(false);
|
|
||||||
var items = JObject.Parse(res);
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
var status = items["status"];
|
|
||||||
var x360 = items["360"];
|
|
||||||
var ps3 = items["ps3"];
|
|
||||||
var pc = items["pc"];
|
|
||||||
|
|
||||||
var response = $@"```css
|
|
||||||
[☕ BF3 Status: {status.ToString().ToUpper()}]
|
|
||||||
XBOX360: ✔[{x360.ToString()}]
|
|
||||||
PS3: ✔[{ps3.ToString()}]
|
|
||||||
PC: ✔[{pc.ToString()}]
|
|
||||||
```";
|
|
||||||
await channel.SendMessageAsync(response);
|
|
||||||
}
|
|
||||||
else if (game.Equals("bf4", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
var res = await http.GetStringAsync($"http://api.bf4stats.com/api/onlinePlayers?output=json").ConfigureAwait(false);
|
|
||||||
var items = JObject.Parse(res);
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
var status = !string.IsNullOrEmpty(items.ToString()) ? "OK" : "BAD";
|
|
||||||
var pc = items["pc"];
|
|
||||||
var ps3 = items["ps3"];
|
|
||||||
var ps4 = items["ps4"];
|
|
||||||
var xbox = items["xbox"];
|
|
||||||
var xone = items["xone"];
|
|
||||||
|
|
||||||
sb.AppendLine("```css");
|
|
||||||
sb.AppendLine($"[☕ BF4 Status: {status}]");
|
|
||||||
|
|
||||||
foreach (var i in items) {
|
|
||||||
var plat = items[i.Key];
|
|
||||||
sb.AppendLine($"{plat["label"]}: ✔[{plat["count"]}] / ↑[{plat["peak24"]}]");
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.Append("```");
|
|
||||||
await channel.SendMessageAsync(sb.ToString());
|
|
||||||
}
|
|
||||||
} catch
|
|
||||||
{
|
|
||||||
await channel.SendMessageAsync($"💢 BF3/BF4 API is most likely not working at the moment or could not find {game}.").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
public async Task BFU(IUserMessage umsg, string platform, string game, [Remainder] string query = null)
|
|
||||||
{
|
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
|
||||||
if (string.IsNullOrWhiteSpace(platform) || string.IsNullOrWhiteSpace(game) || string.IsNullOrWhiteSpace(query))
|
|
||||||
{
|
|
||||||
await channel.SendMessageAsync("💢 Please enter a platform `(pc, xbox, ps3, xone, ps4)`, game `(bf3, bf4)`, followed by a search query.").ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
|
|
||||||
using (var http = new HttpClient())
|
|
||||||
{
|
|
||||||
http.DefaultRequestHeaders.Clear();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (game.Equals("bf3", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
var res = await http.GetStringAsync($"http://api.bf3stats.com/{Uri.EscapeUriString(platform)}/playerlist/players={Uri.EscapeUriString(query)}?output=json").ConfigureAwait(false);
|
|
||||||
var items = JObject.Parse(res);
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
var playerName = items["list"][query];
|
|
||||||
var playerTag = playerName["tag"];
|
|
||||||
var playerCountryName = playerName["country_name"];
|
|
||||||
var playerStats = playerName["stats"];
|
|
||||||
var playerRank = playerStats["rank"];
|
|
||||||
var playerRank_name = playerRank["name"];
|
|
||||||
var playerGlobal_Kills = playerStats["global"]["kills"];
|
|
||||||
var playerGlobal_Deaths = playerStats["global"]["deaths"];
|
|
||||||
var playerGlobal_KD = Math.Round(Double.Parse(playerGlobal_Kills.ToString()) / Double.Parse(playerGlobal_Deaths.ToString()), 2);
|
|
||||||
var playerGlobal_Wins = playerStats["global"]["wins"];
|
|
||||||
var playerGlobal_Losses = playerStats["global"]["losses"];
|
|
||||||
var playerGlobal_WL = Math.Round(Double.Parse(playerGlobal_Wins.ToString()) / Double.Parse(playerGlobal_Losses.ToString()), 2);
|
|
||||||
var playerGlobal_Shots = playerStats["global"]["shots"];
|
|
||||||
var playerGlobal_Hits = playerStats["global"]["hits"];
|
|
||||||
var playerGlobal_Accuracy = Math.Round(Double.Parse(playerGlobal_Hits.ToString()) / Double.Parse(playerGlobal_Shots.ToString()), 2);
|
|
||||||
var playerGlobal_ELO = playerStats["global"]["elo"];
|
|
||||||
|
|
||||||
var response = $@"```css
|
|
||||||
[☕ BF3 Player: {query}]
|
|
||||||
Platform: [{platform.ToUpper()}]
|
|
||||||
Tag: [{playerTag.ToString()}]
|
|
||||||
K/D: [{playerGlobal_KD.ToString()}]
|
|
||||||
W/L: [{playerGlobal_WL.ToString()}]
|
|
||||||
Accuracy: %[{playerGlobal_Accuracy.ToString()}]
|
|
||||||
ELO: [{playerGlobal_ELO.ToString()}]
|
|
||||||
```";
|
|
||||||
await channel.SendMessageAsync(response);
|
|
||||||
} else if (game.Equals("bf4", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
var res = await http.GetStringAsync($"http://api.bf4stats.com/api/playerInfo?plat={Uri.EscapeUriString(platform)}&name={Uri.EscapeUriString(query)}&output=json").ConfigureAwait(false);
|
|
||||||
var items = JObject.Parse(res);
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
|
|
||||||
var player = items["player"];
|
|
||||||
var playerStats = items["stats"];
|
|
||||||
|
|
||||||
var playerName = player["name"];
|
|
||||||
var playerTag = player["tag"];
|
|
||||||
var playerPlatform = player["plat"];
|
|
||||||
var playerKills = playerStats["kills"];
|
|
||||||
var playerDeaths = playerStats["deaths"];
|
|
||||||
var player_KD = Math.Round(Double.Parse(playerKills.ToString()) / Double.Parse(playerDeaths.ToString()), 2);
|
|
||||||
var playerWins = playerStats["numWins"];
|
|
||||||
var playerRounds = playerStats["numRounds"];
|
|
||||||
var player_WL = Math.Round(Double.Parse(playerWins.ToString()) / Double.Parse(playerRounds.ToString()), 2);
|
|
||||||
var shotsFired = playerStats["shotsFired"];
|
|
||||||
var shotsHit = playerStats["shotsHit"];
|
|
||||||
var accuracy = Math.Round(Double.Parse(shotsHit.ToString()) / Double.Parse(shotsFired.ToString()), 2);
|
|
||||||
var playerELO = playerStats["elo"];
|
|
||||||
|
|
||||||
var response = $@"```css
|
|
||||||
[☕ BF4 Player: {playerName.ToString()}]
|
|
||||||
Platform: [{playerPlatform.ToString().ToUpper()}]
|
|
||||||
Tag: [{playerTag.ToString()}]
|
|
||||||
K/D: [{player_KD.ToString()}]
|
|
||||||
W/L: [{player_WL.ToString()}]
|
|
||||||
Accuracy: %[{accuracy.ToString()}]
|
|
||||||
ELO: [{playerELO.ToString()}]
|
|
||||||
```";
|
|
||||||
await channel.SendMessageAsync(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
await channel.SendMessageAsync($"💢 BF3/BF4 API is most likely not working at the moment or could not find {query}.").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -700,7 +683,7 @@ ELO: [{playerELO.ToString()}]
|
|||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
if (string.IsNullOrWhiteSpace(target) || string.IsNullOrWhiteSpace(query))
|
if (string.IsNullOrWhiteSpace(target) || string.IsNullOrWhiteSpace(query))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 Please enter a target wikia, followed by search query.").ConfigureAwait(false);
|
await channel.SendErrorAsync("Please enter a target wikia, followed by search query.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
|
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
|
||||||
@ -719,7 +702,7 @@ ELO: [{playerELO.ToString()}]
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"💢 Failed finding `{query}`.").ConfigureAwait(false);
|
await channel.SendErrorAsync($"Failed finding `{query}`.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -732,7 +715,7 @@ ELO: [{playerELO.ToString()}]
|
|||||||
var arg = query;
|
var arg = query;
|
||||||
if (string.IsNullOrWhiteSpace(arg))
|
if (string.IsNullOrWhiteSpace(arg))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 Please enter a `ip:port`.").ConfigureAwait(false);
|
await channel.SendErrorAsync("💢 Please enter a `ip:port`.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
|
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
|
||||||
@ -756,7 +739,7 @@ ELO: [{playerELO.ToString()}]
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"💢 Failed finding `{arg}`.").ConfigureAwait(false);
|
await channel.SendErrorAsync($"Failed finding `{arg}`.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -769,7 +752,7 @@ ELO: [{playerELO.ToString()}]
|
|||||||
var arg = query;
|
var arg = query;
|
||||||
if (string.IsNullOrWhiteSpace(arg))
|
if (string.IsNullOrWhiteSpace(arg))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("💢 Please enter a `ip:port`.").ConfigureAwait(false);
|
await channel.SendErrorAsync("Please enter `ip:port`.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
|
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
|
||||||
@ -796,15 +779,86 @@ ELO: [{playerELO.ToString()}]
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"💢 Failed finding server `{arg}`.").ConfigureAwait(false);
|
await channel.SendErrorAsync($"Failed finding server `{arg}`.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum DapiSearchType
|
||||||
|
{
|
||||||
|
Safebooru,
|
||||||
|
Gelbooru,
|
||||||
|
Konachan,
|
||||||
|
Rule34,
|
||||||
|
Yandere
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task InternalDapiCommand(IUserMessage umsg, string tag, DapiSearchType type)
|
||||||
|
{
|
||||||
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
|
tag = tag?.Trim() ?? "";
|
||||||
|
|
||||||
|
var url = await InternalDapiSearch(tag, type).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (url == null)
|
||||||
|
await channel.SendErrorAsync(umsg.Author.Mention + " No results.");
|
||||||
|
else
|
||||||
|
await channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||||
|
.WithDescription(umsg.Author.Mention + " " + tag)
|
||||||
|
.WithImageUrl(url)
|
||||||
|
.WithFooter(efb => efb.WithText(type.ToString()))
|
||||||
|
.Build()).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<string> InternalDapiSearch(string tag, DapiSearchType type)
|
||||||
|
{
|
||||||
|
tag = tag?.Replace(" ", "_");
|
||||||
|
string website = "";
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case DapiSearchType.Safebooru:
|
||||||
|
website = $"https://safebooru.org/index.php?page=dapi&s=post&q=index&limit=100&tags={tag}";
|
||||||
|
break;
|
||||||
|
case DapiSearchType.Gelbooru:
|
||||||
|
website = $"http://gelbooru.com/index.php?page=dapi&s=post&q=index&limit=100&tags={tag}";
|
||||||
|
break;
|
||||||
|
case DapiSearchType.Rule34:
|
||||||
|
website = $"https://rule34.xxx/index.php?page=dapi&s=post&q=index&limit=100&tags={tag}";
|
||||||
|
break;
|
||||||
|
case DapiSearchType.Konachan:
|
||||||
|
website = $"https://konachan.com/post.xml?s=post&q=index&limit=100&tags={tag}";
|
||||||
|
break;
|
||||||
|
case DapiSearchType.Yandere:
|
||||||
|
website = $"https://yande.re/post.xml?limit=100&tags={tag}";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var http = new HttpClient())
|
||||||
|
{
|
||||||
|
http.AddFakeHeaders();
|
||||||
|
var data = await http.GetStreamAsync(website);
|
||||||
|
var doc = new XmlDocument();
|
||||||
|
doc.Load(data);
|
||||||
|
|
||||||
|
var node = doc.LastChild.ChildNodes[new NadekoRandom().Next(0, doc.LastChild.ChildNodes.Count)];
|
||||||
|
|
||||||
|
var url = node.Attributes["file_url"].Value;
|
||||||
|
if (!url.StartsWith("http"))
|
||||||
|
url = "https:" + url;
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
public static async Task<bool> ValidateQuery(ITextChannel ch, string query)
|
public static async Task<bool> ValidateQuery(ITextChannel ch, string query)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(query.Trim())) return true;
|
if (!string.IsNullOrEmpty(query.Trim())) return true;
|
||||||
await ch.SendMessageAsync("Please specify search parameters.").ConfigureAwait(false);
|
await ch.SendErrorAsync("Please specify search parameters.").ConfigureAwait(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@ using Discord.Commands;
|
|||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@ -10,24 +12,19 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.Utility
|
namespace NadekoBot.Modules.Utility
|
||||||
{
|
{
|
||||||
[Group]
|
|
||||||
public partial class Utility
|
public partial class Utility
|
||||||
{
|
{
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public static async Task Calculate(IUserMessage msg, [Remainder] string expression)
|
public static async Task Calculate(IUserMessage msg, [Remainder] string expression)
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var expr = new NCalc.Expression(expression, NCalc.EvaluateOptions.IgnoreCase);
|
var expr = new NCalc.Expression(expression, NCalc.EvaluateOptions.IgnoreCase);
|
||||||
expr.EvaluateParameter += Expr_EvaluateParameter;
|
expr.EvaluateParameter += Expr_EvaluateParameter;
|
||||||
var result = expr.Evaluate();
|
var result = expr.Evaluate();
|
||||||
await msg.Reply(string.Format("⚙ `{0}`", expr.Error ?? result));
|
if (expr.Error == null)
|
||||||
}
|
await msg.Channel.SendConfirmAsync("Result", $"{result}");
|
||||||
catch (Exception e)
|
else
|
||||||
{
|
await msg.Channel.SendErrorAsync($"⚙ Error", expr.Error);
|
||||||
await msg.Reply($"Failed to evaluate: {e.Message} ");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Expr_EvaluateParameter(string name, NCalc.ParameterArgs args)
|
private static void Expr_EvaluateParameter(string name, NCalc.ParameterArgs args)
|
||||||
@ -44,20 +41,25 @@ namespace NadekoBot.Modules.Utility
|
|||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task CalcOps(IUserMessage msg)
|
public async Task CalcOps(IUserMessage msg)
|
||||||
{
|
{
|
||||||
StringBuilder builder = new StringBuilder();
|
var selection = typeof(Math).GetTypeInfo().GetMethods().Except(typeof(object).GetTypeInfo().GetMethods()).Distinct(new MethodInfoEqualityComparer()).Select(x =>
|
||||||
var selection = typeof(Math).GetTypeInfo().GetMethods().Except(typeof(object).GetTypeInfo().GetMethods()).Select(x =>
|
|
||||||
{
|
{
|
||||||
var name = x.Name;
|
return x.Name;
|
||||||
if (x.GetParameters().Any())
|
})
|
||||||
|
.Except(new[] { "ToString",
|
||||||
|
"Equals",
|
||||||
|
"GetHashCode",
|
||||||
|
"GetType"});
|
||||||
|
await msg.Channel.SendConfirmAsync("Available functions in calc", string.Join(", ", selection));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MethodInfoEqualityComparer : IEqualityComparer<MethodInfo>
|
||||||
{
|
{
|
||||||
name += " (" + string.Join(", ", x.GetParameters().Select(y => y.IsOptional ? $"[{y.ParameterType.Name + " " + y.Name }]" : y.ParameterType.Name + " " + y.Name)) + ")";
|
public bool Equals(MethodInfo x, MethodInfo y) => x.Name == y.Name;
|
||||||
}
|
|
||||||
return name;
|
public int GetHashCode(MethodInfo obj) => obj.Name.GetHashCode();
|
||||||
});
|
|
||||||
foreach (var method in selection) builder.AppendLine(method);
|
|
||||||
await msg.ReplyLong(builder.ToString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExpressionContext
|
class ExpressionContext
|
||||||
{
|
{
|
||||||
public double Pi { get; set; } = Math.PI;
|
public double Pi { get; set; } = Math.PI;
|
||||||
|
@ -10,58 +10,46 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.Utility
|
namespace NadekoBot.Modules.Utility
|
||||||
{
|
{
|
||||||
partial class Utility : DiscordModule
|
public partial class Utility
|
||||||
{
|
{
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task TogetherTube(IUserMessage imsg)
|
public async Task ServerInfo(IUserMessage msg, string guildName = null)
|
||||||
{
|
|
||||||
var channel = (ITextChannel)imsg.Channel;
|
|
||||||
|
|
||||||
Uri target;
|
|
||||||
using (var http = new HttpClient())
|
|
||||||
{
|
|
||||||
var res = await http.GetAsync("https://togethertube.com/room/create").ConfigureAwait(false);
|
|
||||||
target = res.RequestMessage.RequestUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
await channel.SendMessageAsync($"🎞 {imsg.Author.Mention}, **Your new video room created. Join and invite to watch videos together with friends:** {target}")
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
public async Task ServerInfo(IUserMessage msg, string guild = null)
|
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)msg.Channel;
|
var channel = (ITextChannel)msg.Channel;
|
||||||
guild = guild?.ToUpperInvariant();
|
guildName = guildName?.ToUpperInvariant();
|
||||||
IGuild server;
|
IGuild guild;
|
||||||
if (guild == null)
|
if (string.IsNullOrWhiteSpace(guildName))
|
||||||
server = channel.Guild;
|
guild = channel.Guild;
|
||||||
else
|
else
|
||||||
server = _client.GetGuilds().Where(g => g.Name.ToUpperInvariant() == guild.ToUpperInvariant()).FirstOrDefault();
|
guild = NadekoBot.Client.GetGuilds().Where(g => g.Name.ToUpperInvariant() == guildName.ToUpperInvariant()).FirstOrDefault();
|
||||||
if (server == null)
|
if (guild == null)
|
||||||
return;
|
return;
|
||||||
|
var ownername = await guild.GetUserAsync(guild.OwnerId);
|
||||||
|
var textchn = (await guild.GetTextChannelsAsync()).Count();
|
||||||
|
var voicechn = (await guild.GetVoiceChannelsAsync()).Count();
|
||||||
|
|
||||||
var createdAt = new DateTime(2015, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(server.Id >> 22);
|
var createdAt = new DateTime(2015, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(guild.Id >> 22);
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
var users = await server.GetUsersAsync();
|
var users = await guild.GetUsersAsync().ConfigureAwait(false);
|
||||||
sb.AppendLine($@"__`Name:`__ **{server.Name}**
|
var embed = new EmbedBuilder()
|
||||||
__`Owner:`__ **{await server.GetUserAsync(server.OwnerId)}**
|
.WithAuthor(eab => eab.WithName("Server Info"))
|
||||||
__`ID:`__ **{server.Id}**
|
.WithTitle(guild.Name)
|
||||||
__`Icon URL:`__ { server.IconUrl}
|
.AddField(fb => fb.WithName("**ID**").WithValue(guild.Id.ToString()).WithIsInline(true))
|
||||||
__`TextChannels:`__ **{(await server.GetTextChannelsAsync()).Count()}** `VoiceChannels:` **{(await server.GetVoiceChannelsAsync()).Count()}**
|
.AddField(fb => fb.WithName("**Owner**").WithValue(ownername.ToString()).WithIsInline(true))
|
||||||
__`Members:`__ **{users.Count}** `-` {users.Count(u => u.Status == UserStatus.Online)}💚 {users.Count(u => u.Status == UserStatus.Idle)}🔶 {users.Count(u => u.Status == UserStatus.DoNotDisturb)}🔴 {users.Count(u=> u.Status == UserStatus.Offline || u.Status == UserStatus.Unknown)}⬛️
|
.AddField(fb => fb.WithName("**Members**").WithValue(users.Count.ToString()).WithIsInline(true))
|
||||||
__`Roles:`__ **{server.Roles.Count()}**
|
.AddField(fb => fb.WithName("**Text Channels**").WithValue(textchn.ToString()).WithIsInline(true))
|
||||||
__`Created At:`__ **{createdAt.ToString("dd.MM.yyyy HH:mm")}**
|
.AddField(fb => fb.WithName("**Voice Channels**").WithValue(voicechn.ToString()).WithIsInline(true))
|
||||||
");
|
.AddField(fb => fb.WithName("**Created At**").WithValue($"{createdAt.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
|
||||||
if (server.Emojis.Count() > 0)
|
.AddField(fb => fb.WithName("**Region**").WithValue(guild.VoiceRegionId.ToString()).WithIsInline(true))
|
||||||
sb.AppendLine($"__`Custom Emojis:`__ *{string.Join(", ", server.Emojis)}*");
|
.AddField(fb => fb.WithName("**Roles**").WithValue(guild.Roles.Count().ToString()).WithIsInline(true))
|
||||||
if (server.Features.Count() > 0)
|
.WithImage(tn => tn.WithUrl(guild.IconUrl))
|
||||||
sb.AppendLine($"__`Features:`__ **{string.Join(", ", server.Features)}**");
|
.WithOkColor();
|
||||||
if (!string.IsNullOrWhiteSpace(server.SplashUrl))
|
if (guild.Emojis.Count() > 0)
|
||||||
sb.AppendLine($"__`Region:`__ **{server.VoiceRegionId}**");
|
{
|
||||||
await msg.Reply(sb.ToString()).ConfigureAwait(false);
|
embed.AddField(fb => fb.WithName("**Custom Emojis**").WithValue(Format.Italics(string.Join(", ", guild.Emojis))).WithIsInline(true));
|
||||||
|
}
|
||||||
|
await msg.Channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -72,12 +60,15 @@ __`Created At:`__ **{createdAt.ToString("dd.MM.yyyy HH:mm")}**
|
|||||||
if (ch == null)
|
if (ch == null)
|
||||||
return;
|
return;
|
||||||
var createdAt = new DateTime(2015, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(ch.Id >> 22);
|
var createdAt = new DateTime(2015, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(ch.Id >> 22);
|
||||||
var toReturn = $@"__`Name:`__ **#{ch.Name}**
|
var usercount = (await ch.GetUsersAsync()).Count();
|
||||||
__`ID:`__ **{ch.Id}**
|
var embed = new EmbedBuilder()
|
||||||
__`Created At:`__ **{createdAt.ToString("dd.MM.yyyy HH:mm")}**
|
.WithTitle(ch.Name)
|
||||||
__`Topic:`__ {ch.Topic}
|
.WithDescription(ch.Topic?.SanitizeMentions())
|
||||||
__`Users:`__ **{(await ch.GetUsersAsync()).Count()}**";
|
.AddField(fb => fb.WithName("**ID**").WithValue(ch.Id.ToString()).WithIsInline(true))
|
||||||
await msg.Reply(toReturn).ConfigureAwait(false);
|
.AddField(fb => fb.WithName("**Created At**").WithValue($"{createdAt.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
|
||||||
|
.AddField(fb => fb.WithName("**Users**").WithValue(usercount.ToString()).WithIsInline(true))
|
||||||
|
.WithOkColor();
|
||||||
|
await msg.Channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -86,20 +77,49 @@ __`Users:`__ **{(await ch.GetUsersAsync()).Count()}**";
|
|||||||
{
|
{
|
||||||
var channel = (ITextChannel)msg.Channel;
|
var channel = (ITextChannel)msg.Channel;
|
||||||
var user = usr ?? msg.Author as IGuildUser;
|
var user = usr ?? msg.Author as IGuildUser;
|
||||||
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
return;
|
return;
|
||||||
var toReturn = $"👤 __`Name:`__ **{user.Username}#{user.Discriminator}**\n";
|
|
||||||
if (!string.IsNullOrWhiteSpace(user.Nickname))
|
var embed = new EmbedBuilder()
|
||||||
toReturn += $"🆕 __`Nickname:`__ **{user.Nickname}** ";
|
.AddField(fb => fb.WithName("**Name**").WithValue($"**{user.Username}**#{user.Discriminator}").WithIsInline(true));
|
||||||
toReturn += $@"🏷 __`ID:`__ **{user.Id}**
|
if (!string.IsNullOrWhiteSpace(user.Nickname)) {
|
||||||
🎮 __`Current Game:`__ **{(user.Game?.Name == null ? "-" : user.Game.Name)}**
|
embed.AddField(fb => fb.WithName("**Nickname**").WithValue(user.Nickname).WithIsInline(true));
|
||||||
📅 __`Joined Server:`__ **{user.JoinedAt?.ToString("dd.MM.yyyy HH:mm")}**
|
}
|
||||||
🗓 __`Joined Discord:`__ **{user.CreatedAt.ToString("dd.MM.yyyy HH:mm")}**
|
embed.AddField(fb => fb.WithName("**ID**").WithValue(user.Id.ToString()).WithIsInline(true))
|
||||||
⚔ __`Roles:`__ **({user.Roles.Count()}) - {string.Join(", ", user.Roles.Select(r => r.Name)).SanitizeMentions()}**";
|
.AddField(fb => fb.WithName("**Joined Server**").WithValue($"{user.JoinedAt?.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
|
||||||
if (!string.IsNullOrWhiteSpace(user.AvatarUrl))
|
.AddField(fb => fb.WithName("**Joined Discord**").WithValue($"{user.CreatedAt.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
|
||||||
toReturn += $@"
|
.AddField(fb => fb.WithName("**Current Game**").WithValue($"{(user.Game?.Name == null ? "-" : user.Game.Name)}").WithIsInline(true))
|
||||||
📷 __`Avatar URL:`__ **{await NadekoBot.Google.ShortenUrl(user.AvatarUrl).ConfigureAwait(false)}**";
|
.AddField(fb => fb.WithName("**Roles**").WithValue($"**({user.Roles.Count()})** - {string.Join(", ", user.Roles.Select(r => r.Name)).SanitizeMentions()}").WithIsInline(true))
|
||||||
await msg.Reply(toReturn).ConfigureAwait(false);
|
.WithThumbnail(tn => tn.WithUrl(user.AvatarUrl))
|
||||||
|
.WithOkColor();
|
||||||
|
await msg.Channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[OwnerOnly]
|
||||||
|
public async Task Activity(IUserMessage imsg, int page = 1)
|
||||||
|
{
|
||||||
|
const int activityPerPage = 15;
|
||||||
|
page -= 1;
|
||||||
|
|
||||||
|
if (page < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int startCount = page * activityPerPage;
|
||||||
|
|
||||||
|
StringBuilder str = new StringBuilder();
|
||||||
|
foreach (var kvp in NadekoBot.CommandHandler.UserMessagesSent.OrderByDescending(kvp => kvp.Value).Skip(page*activityPerPage).Take(activityPerPage))
|
||||||
|
{
|
||||||
|
str.AppendLine($"`{++startCount}.` **{kvp.Key}** [{kvp.Value/NadekoBot.Stats.GetUptime().TotalSeconds:F2}/s] - {kvp.Value} total");
|
||||||
|
}
|
||||||
|
|
||||||
|
await imsg.Channel.EmbedAsync(new EmbedBuilder().WithTitle($"Activity Page #{page}")
|
||||||
|
.WithOkColor()
|
||||||
|
.WithFooter(efb => efb.WithText($"{NadekoBot.CommandHandler.UserMessagesSent.Count} users total."))
|
||||||
|
.WithDescription(str.ToString())
|
||||||
|
.Build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,14 +27,14 @@ namespace NadekoBot.Modules.Utility
|
|||||||
IEnumerable<Quote> quotes;
|
IEnumerable<Quote> quotes;
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
quotes = uow.Quotes.GetGroup(page * 16, 16);
|
quotes = uow.Quotes.GetGroup(channel.Guild.Id, page * 16, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (quotes.Any())
|
if (quotes.Any())
|
||||||
await channel.SendMessageAsync($"💬 **Page {page + 1} of quotes:**\n```xl\n" + String.Join("\n", quotes.Select((q) => $"{q.Keyword,-20} by {q.AuthorName}")) + "\n```")
|
await channel.SendConfirmAsync($"💬 **Page {page + 1} of quotes:**\n```xl\n" + String.Join("\n", quotes.Select((q) => $"{q.Keyword,-20} by {q.AuthorName}")) + "\n```")
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync("ℹ️ **No quotes on this page.**").ConfigureAwait(false);
|
await channel.SendErrorAsync("No quotes on this page.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -83,7 +83,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
});
|
});
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync("✅ **Quote added.**").ConfigureAwait(false);
|
await channel.SendConfirmAsync("✅ Quote added.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -105,7 +105,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
|
|
||||||
if (qs==null || !qs.Any())
|
if (qs==null || !qs.Any())
|
||||||
{
|
{
|
||||||
response = "ℹ️ **No quotes found.**";
|
await channel.SendErrorAsync("No quotes found.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
response = "🗑 **Deleted a random quote.**";
|
response = "🗑 **Deleted a random quote.**";
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync(response);
|
await channel.SendConfirmAsync(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -139,7 +139,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
await uow.CompleteAsync();
|
await uow.CompleteAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync($"🗑 **Deleted all quotes** with **{keyword}** keyword.");
|
await channel.SendConfirmAsync($"🗑 **Deleted all quotes** with **{keyword}** keyword.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
|
|
||||||
if (ch == null)
|
if (ch == null)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"⚠️ {umsg.Author.Mention} Something went wrong (channel cannot be found) ;(").ConfigureAwait(false);
|
await channel.SendErrorAsync($"{umsg.Author.Mention} Something went wrong (channel cannot be found) ;(").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
|
|
||||||
if (m.Length == 0)
|
if (m.Length == 0)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("❎ **Not a valid time format.** type `-h .remind`").ConfigureAwait(false);
|
await channel.SendErrorAsync("Not a valid time format. Type `-h .remind`").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +157,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
(groupName == "hours" && value > 23) ||
|
(groupName == "hours" && value > 23) ||
|
||||||
(groupName == "minutes" && value > 59))
|
(groupName == "minutes" && value > 59))
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"⚠️ Invalid {groupName} value.").ConfigureAwait(false);
|
await channel.SendErrorAsync($"Invalid {groupName} value.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -187,7 +187,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
await uow.CompleteAsync();
|
await uow.CompleteAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
try { await channel.SendMessageAsync($"⏰ I will remind **\"{(ch is ITextChannel ? ((ITextChannel)ch).Name : umsg.Author.Username)}\"** to **\"{message.SanitizeMentions()}\"** in **{output}** `({time:d.M.yyyy.} at {time:HH:mm})`").ConfigureAwait(false); } catch { }
|
try { await channel.SendConfirmAsync($"⏰ I will remind **\"{(ch is ITextChannel ? ((ITextChannel)ch).Name : umsg.Author.Username)}\"** to **\"{message.SanitizeMentions()}\"** in **{output}** `({time:d.M.yyyy.} at {time:HH:mm})`").ConfigureAwait(false); } catch { }
|
||||||
await StartReminder(rem);
|
await StartReminder(rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,7 +206,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
uow.BotConfig.GetOrCreate().RemindMessageFormat = arg.Trim();
|
uow.BotConfig.GetOrCreate().RemindMessageFormat = arg.Trim();
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync("🆗 New remind template set.");
|
await channel.SendConfirmAsync("🆗 New remind template set.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
{
|
{
|
||||||
|
|
||||||
public static List<ConvertUnit> Units { get; set; } = new List<ConvertUnit>();
|
public static List<ConvertUnit> Units { get; set; } = new List<ConvertUnit>();
|
||||||
private static Logger _log;
|
private static Logger _log { get; }
|
||||||
private static Timer _timer;
|
private static Timer _timer;
|
||||||
private static TimeSpan updateInterval = new TimeSpan(12, 0, 0);
|
private static TimeSpan updateInterval = new TimeSpan(12, 0, 0);
|
||||||
|
|
||||||
@ -104,15 +104,14 @@ namespace NadekoBot.Modules.Utility
|
|||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task ConvertList(IUserMessage msg)
|
public async Task ConvertList(IUserMessage msg)
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder("Units that can be used by the converter: \n");
|
var res = Units.GroupBy(x => x.UnitType)
|
||||||
var res = Units.GroupBy(x => x.UnitType);
|
.Aggregate(new EmbedBuilder().WithTitle("__Units which can be used by the converter__")
|
||||||
foreach (var group in res)
|
.WithOkColor(),
|
||||||
{
|
(embed, g) => embed.AddField(efb =>
|
||||||
sb.AppendLine($"{group.Key}: ```xl");
|
efb.WithName(g.Key.ToTitleCase())
|
||||||
sb.AppendLine(string.Join(",", group.Select(x => x.Triggers.FirstOrDefault()).OrderBy(x => x)));
|
.WithValue(String.Join(", ", g.Select(x => x.Triggers.FirstOrDefault())
|
||||||
sb.AppendLine("```");
|
.OrderBy(x => x)))));
|
||||||
}
|
await msg.Channel.EmbedAsync(res.Build());
|
||||||
await msg.ReplyLong(sb.ToString(), breakOn: new[] { "```xl\n", "\n" });
|
|
||||||
}
|
}
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
public async Task Convert(IUserMessage msg, string origin, string target, decimal value)
|
public async Task Convert(IUserMessage msg, string origin, string target, decimal value)
|
||||||
@ -121,12 +120,12 @@ namespace NadekoBot.Modules.Utility
|
|||||||
var targetUnit = Units.Find(x => x.Triggers.Select(y => y.ToLowerInvariant()).Contains(target.ToLowerInvariant()));
|
var targetUnit = Units.Find(x => x.Triggers.Select(y => y.ToLowerInvariant()).Contains(target.ToLowerInvariant()));
|
||||||
if (originUnit == null || targetUnit == null)
|
if (originUnit == null || targetUnit == null)
|
||||||
{
|
{
|
||||||
await msg.Reply(string.Format("Cannot convert {0} to {1}: units not found", origin, target));
|
await msg.Channel.SendErrorAsync(string.Format("Cannot convert {0} to {1}: units not found", origin, target));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (originUnit.UnitType != targetUnit.UnitType)
|
if (originUnit.UnitType != targetUnit.UnitType)
|
||||||
{
|
{
|
||||||
await msg.Reply(string.Format("Cannot convert {0} to {1}: types of unit are not equal", originUnit.Triggers.First(), targetUnit.Triggers.First()));
|
await msg.Channel.SendErrorAsync(string.Format("Cannot convert {0} to {1}: types of unit are not equal", originUnit.Triggers.First(), targetUnit.Triggers.First()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
decimal res;
|
decimal res;
|
||||||
@ -170,7 +169,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
}
|
}
|
||||||
res = Math.Round(res, 4);
|
res = Math.Round(res, 4);
|
||||||
|
|
||||||
await msg.Reply(string.Format("{0} {1} is equal to {2} {3}", value, (originUnit.Triggers.First() + "s").SnPl(value.IsInteger() ? (int)value : 2), res, (targetUnit.Triggers.First() + "s").SnPl(res.IsInteger() ? (int)res : 2)));
|
await msg.Channel.SendConfirmAsync(string.Format("{0} {1} is equal to {2} {3}", value, (originUnit.Triggers.First() + "s").SnPl(value.IsInteger() ? (int)value : 2), res, (targetUnit.Triggers.First() + "s").SnPl(res.IsInteger() ? (int)res : 2)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ using Discord.API;
|
|||||||
using Embed = Discord.API.Embed;
|
using Embed = Discord.API.Embed;
|
||||||
using EmbedAuthor = Discord.API.EmbedAuthor;
|
using EmbedAuthor = Discord.API.EmbedAuthor;
|
||||||
using EmbedField = Discord.API.EmbedField;
|
using EmbedField = Discord.API.EmbedField;
|
||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Utility
|
namespace NadekoBot.Modules.Utility
|
||||||
{
|
{
|
||||||
@ -22,11 +23,32 @@ namespace NadekoBot.Modules.Utility
|
|||||||
[NadekoModule("Utility", ".")]
|
[NadekoModule("Utility", ".")]
|
||||||
public partial class Utility : DiscordModule
|
public partial class Utility : DiscordModule
|
||||||
{
|
{
|
||||||
public Utility(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
|
public Utility() : base()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task TogetherTube(IUserMessage imsg)
|
||||||
|
{
|
||||||
|
var channel = (ITextChannel)imsg.Channel;
|
||||||
|
|
||||||
|
Uri target;
|
||||||
|
using (var http = new HttpClient())
|
||||||
|
{
|
||||||
|
var res = await http.GetAsync("https://togethertube.com/room/create").ConfigureAwait(false);
|
||||||
|
target = res.RequestMessage.RequestUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
await channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||||
|
.WithAuthor(eab => eab.WithIconUrl("https://togethertube.com/assets/img/favicons/favicon-32x32.png")
|
||||||
|
.WithName("Together Tube")
|
||||||
|
.WithUrl("https://togethertube.com/"))
|
||||||
|
.WithDescription($"{imsg.Author.Mention} Here is your room link:\n{target}")
|
||||||
|
.Build());
|
||||||
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task WhosPlaying(IUserMessage umsg, [Remainder] string game = null)
|
public async Task WhosPlaying(IUserMessage umsg, [Remainder] string game = null)
|
||||||
@ -35,16 +57,18 @@ namespace NadekoBot.Modules.Utility
|
|||||||
game = game.Trim().ToUpperInvariant();
|
game = game.Trim().ToUpperInvariant();
|
||||||
if (string.IsNullOrWhiteSpace(game))
|
if (string.IsNullOrWhiteSpace(game))
|
||||||
return;
|
return;
|
||||||
var arr = (await (umsg.Channel as IGuildChannel).Guild.GetUsersAsync())
|
var usrs = (await (umsg.Channel as IGuildChannel).Guild.GetUsersAsync())
|
||||||
.Where(u => u.Game?.Name?.ToUpperInvariant() == game)
|
.Where(u => u.Game?.Name?.ToUpperInvariant() == game)
|
||||||
.Select(u => u.Username)
|
.Select(u => u.Username)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if (!arr.Any())
|
if (!usrs.Any())
|
||||||
await channel.SendErrorAsync("Nobody is playing that game.").ConfigureAwait(false);
|
await channel.SendErrorAsync("Nobody is playing that game.").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync("```css\n" + string.Join("\n", arr.GroupBy(item => (i++) / 3).Select(ig => string.Concat(ig.Select(el => $"• {el,-35}")))) + "\n```").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"List of users playing {game} game. Total {usrs.Count}.", "```css\n" + string.Join("\n", usrs.Take(30).GroupBy(item => (i++) / 2)
|
||||||
|
.Select(ig => string.Concat(ig.Select(el => $"• {el,-27}")))) + "\n```")
|
||||||
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -55,7 +79,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
return;
|
return;
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
var arg = roles.Split(',').Select(r => r.Trim().ToUpperInvariant());
|
var arg = roles.Split(',').Select(r => r.Trim().ToUpperInvariant());
|
||||||
string send = _l["ℹ️ **Here is a list of users in a specfic role:**"];
|
string send = "ℹ️ **Here is a list of users in those roles:**";
|
||||||
foreach (var roleStr in arg.Where(str => !string.IsNullOrWhiteSpace(str) && str != "@EVERYONE" && str != "EVERYONE"))
|
foreach (var roleStr in arg.Where(str => !string.IsNullOrWhiteSpace(str) && str != "@EVERYONE" && str != "EVERYONE"))
|
||||||
{
|
{
|
||||||
var role = channel.Guild.Roles.Where(r => r.Name.ToUpperInvariant() == roleStr).FirstOrDefault();
|
var role = channel.Guild.Roles.Where(r => r.Name.ToUpperInvariant() == roleStr).FirstOrDefault();
|
||||||
@ -69,16 +93,16 @@ namespace NadekoBot.Modules.Utility
|
|||||||
{
|
{
|
||||||
if (!usr.GetPermissions(channel).ManageMessages)
|
if (!usr.GetPermissions(channel).ManageMessages)
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync($"⚠️ {usr.Mention} **you are not allowed to use this command on roles with a lot of users in them to prevent abuse.**").ConfigureAwait(false);
|
await channel.SendErrorAsync($"⚠️ {usr.Mention} **you are not allowed to use this command on roles with a lot of users in them to prevent abuse.**").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var curstr = send.Substring(0, 2000);
|
var curstr = send.Substring(0, 2000);
|
||||||
await channel.SendMessageAsync(curstr.Substring(0,
|
await channel.SendConfirmAsync(curstr.Substring(0,
|
||||||
curstr.LastIndexOf(", ", StringComparison.Ordinal) + 1)).ConfigureAwait(false);
|
curstr.LastIndexOf(", ", StringComparison.Ordinal) + 1)).ConfigureAwait(false);
|
||||||
send = curstr.Substring(curstr.LastIndexOf(", ", StringComparison.Ordinal) + 1) +
|
send = curstr.Substring(curstr.LastIndexOf(", ", StringComparison.Ordinal) + 1) +
|
||||||
send.Substring(2000);
|
send.Substring(2000);
|
||||||
}
|
}
|
||||||
await channel.SendMessageAsync(send).ConfigureAwait(false);
|
await channel.SendConfirmAsync(send).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -95,7 +119,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
}
|
}
|
||||||
|
|
||||||
builder.Append("```");
|
builder.Append("```");
|
||||||
await msg.Reply(builder.ToString());
|
await msg.Channel.SendConfirmAsync(builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -103,20 +127,20 @@ namespace NadekoBot.Modules.Utility
|
|||||||
public async Task UserId(IUserMessage msg, IGuildUser target = null)
|
public async Task UserId(IUserMessage msg, IGuildUser target = null)
|
||||||
{
|
{
|
||||||
var usr = target ?? msg.Author;
|
var usr = target ?? msg.Author;
|
||||||
await msg.Reply($"🆔 of the user **{ usr.Username }** is `{ usr.Id }`").ConfigureAwait(false);
|
await msg.Channel.SendConfirmAsync($"🆔 of the user **{ usr.Username }** is `{ usr.Id }`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
public async Task ChannelId(IUserMessage msg)
|
public async Task ChannelId(IUserMessage msg)
|
||||||
{
|
{
|
||||||
await msg.Reply($"ℹ️ This **Channel's ID** is `{msg.Channel.Id}`").ConfigureAwait(false);
|
await msg.Channel.SendConfirmAsync($"🆔 of this channel is `{msg.Channel.Id}`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task ServerId(IUserMessage msg)
|
public async Task ServerId(IUserMessage msg)
|
||||||
{
|
{
|
||||||
await msg.Reply($"ℹ️ This **Server's ID** is `{((ITextChannel)msg.Channel).Guild.Id}`").ConfigureAwait(false);
|
await msg.Channel.SendConfirmAsync($"🆔 of this server is `{((ITextChannel)msg.Channel).Guild.Id}`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -130,13 +154,30 @@ namespace NadekoBot.Modules.Utility
|
|||||||
|
|
||||||
if (page < 1 || page > 100)
|
if (page < 1 || page > 100)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (target != null)
|
if (target != null)
|
||||||
{
|
{
|
||||||
await msg.Reply($"⚔ **Page #{page} of roles for {target.Username}:** ```css\n• " + string.Join("\n• ", target.Roles.Except(new[] { guild.EveryoneRole }).OrderBy(r => r.Position).Skip((page - 1) * RolesPerPage).Take(RolesPerPage)).SanitizeMentions() + "\n```");
|
var roles = target.Roles.Except(new[] { guild.EveryoneRole }).OrderBy(r => -r.Position).Skip((page - 1) * RolesPerPage).Take(RolesPerPage);
|
||||||
|
if (!roles.Any())
|
||||||
|
{
|
||||||
|
await channel.SendErrorAsync("No roles on this page.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await msg.Reply($"⚔ **Page #{page} of all roles on this server:** ```css\n• " + string.Join("\n• ", guild.Roles.Except(new[] { guild.EveryoneRole }).OrderBy(r => r.Position).Skip((page - 1) * RolesPerPage).Take(RolesPerPage)).SanitizeMentions() + "\n```");
|
await channel.SendConfirmAsync($"⚔ **Page #{page} of roles for {target.Username}**", $"```css\n• " + string.Join("\n• ", roles).SanitizeMentions() + "\n```").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var roles = guild.Roles.Except(new[] { guild.EveryoneRole }).OrderBy(r => -r.Position).Skip((page - 1) * RolesPerPage).Take(RolesPerPage);
|
||||||
|
if (!roles.Any())
|
||||||
|
{
|
||||||
|
await channel.SendErrorAsync("No roles on this page.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await channel.SendConfirmAsync($"⚔ **Page #{page} of all roles on this server:**", $"```css\n• " + string.Join("\n• ", roles).SanitizeMentions() + "\n```").ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,9 +194,9 @@ namespace NadekoBot.Modules.Utility
|
|||||||
|
|
||||||
var topic = channel.Topic;
|
var topic = channel.Topic;
|
||||||
if (string.IsNullOrWhiteSpace(topic))
|
if (string.IsNullOrWhiteSpace(topic))
|
||||||
await channel.SendMessageAsync("❎ **No topic set.**");
|
await channel.SendErrorAsync("No topic set.");
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync("ℹ️ **Topic:** " + topic);
|
await channel.SendConfirmAsync("Channel topic", topic);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -166,64 +207,23 @@ namespace NadekoBot.Modules.Utility
|
|||||||
var stats = NadekoBot.Stats;
|
var stats = NadekoBot.Stats;
|
||||||
|
|
||||||
await channel.EmbedAsync(
|
await channel.EmbedAsync(
|
||||||
new Embed()
|
new EmbedBuilder().WithOkColor()
|
||||||
{
|
.WithAuthor(eab => eab.WithName($"NadekoBot v{StatsService.BotVersion}")
|
||||||
Author = new EmbedAuthor()
|
.WithUrl("http://nadekobot.readthedocs.io/en/latest/")
|
||||||
{
|
.WithIconUrl("https://cdn.discordapp.com/avatars/116275390695079945/b21045e778ef21c96d175400e779f0fb.jpg"))
|
||||||
Name = $"NadekoBot v{StatsService.BotVersion}",
|
.AddField(efb => efb.WithName(Format.Bold("Author")).WithValue(stats.Author).WithIsInline(true))
|
||||||
Url = "http://nadekobot.readthedocs.io/en/latest/",
|
.AddField(efb => efb.WithName(Format.Bold("Library")).WithValue(stats.Library).WithIsInline(true))
|
||||||
IconUrl = "https://cdn.discordapp.com/avatars/116275390695079945/b21045e778ef21c96d175400e779f0fb.jpg"
|
.AddField(efb => efb.WithName(Format.Bold("Bot ID")).WithValue(NadekoBot.Client.GetCurrentUser().Id.ToString()).WithIsInline(true))
|
||||||
},
|
.AddField(efb => efb.WithName(Format.Bold("Commands Ran")).WithValue(stats.CommandsRan.ToString()).WithIsInline(true))
|
||||||
Fields = new[] {
|
.AddField(efb => efb.WithName(Format.Bold("Messages")).WithValue($"{stats.MessageCounter} ({stats.MessagesPerSecond:F2}/sec)").WithIsInline(true))
|
||||||
new EmbedField() {
|
.AddField(efb => efb.WithName(Format.Bold("Memory")).WithValue($"{stats.Heap} MB").WithIsInline(true))
|
||||||
Name = "Author",
|
.AddField(efb => efb.WithName(Format.Bold("Owner ID(s)")).WithValue(stats.OwnerIds).WithIsInline(true))
|
||||||
Value = stats.Author,
|
.AddField(efb => efb.WithName(Format.Bold("Uptime")).WithValue(stats.GetUptimeString("\n")).WithIsInline(true))
|
||||||
Inline = true
|
.AddField(efb => efb.WithName(Format.Bold("Presence")).WithValue($"{NadekoBot.Client.GetGuilds().Count} Servers\n{stats.TextChannels} Text Channels\n{stats.VoiceChannels} Voice Channels").WithIsInline(true))
|
||||||
},
|
#if !GLOBAL_NADEKO
|
||||||
new EmbedField() {
|
.WithFooter(efb => efb.WithText($"Playing {Music.Music.MusicPlayers.Where(mp => mp.Value.CurrentSong != null).Count()} songs, {Music.Music.MusicPlayers.Sum(mp => mp.Value.Playlist.Count)} queued."))
|
||||||
Name = "Library",
|
#endif
|
||||||
Value = stats.Library,
|
.Build());
|
||||||
Inline = true
|
|
||||||
},
|
|
||||||
new EmbedField() {
|
|
||||||
Name = "Bot ID",
|
|
||||||
Value = NadekoBot.Client.GetCurrentUser().Id.ToString(),
|
|
||||||
Inline = true
|
|
||||||
},
|
|
||||||
new EmbedField() {
|
|
||||||
Name = "Commands Ran",
|
|
||||||
Value = stats.CommandsRan.ToString(),
|
|
||||||
Inline = true
|
|
||||||
},
|
|
||||||
new EmbedField() {
|
|
||||||
Name = "Messages",
|
|
||||||
Value = $"{stats.MessageCounter} [{stats.MessagesPerSecond:F2}/sec]",
|
|
||||||
Inline = true
|
|
||||||
},
|
|
||||||
new EmbedField() {
|
|
||||||
Name = "Memory",
|
|
||||||
Value = $"{stats.Heap} MB",
|
|
||||||
Inline = true
|
|
||||||
},
|
|
||||||
new EmbedField() {
|
|
||||||
Name = "Owner ID(s)",
|
|
||||||
Value = stats.OwnerIds,
|
|
||||||
Inline = true
|
|
||||||
},
|
|
||||||
new EmbedField() {
|
|
||||||
Name = "Uptime",
|
|
||||||
Value = stats.GetUptimeString("\n"),
|
|
||||||
Inline = true
|
|
||||||
},
|
|
||||||
new EmbedField() {
|
|
||||||
Name = "Presence",
|
|
||||||
Value = $"{NadekoBot.Client.GetGuilds().Count} servers\n{stats.TextChannels} Text Channels\n{stats.VoiceChannels} Voice Channels",
|
|
||||||
Inline = true
|
|
||||||
},
|
|
||||||
|
|
||||||
},
|
|
||||||
Color = NadekoBot.OkColor
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Regex emojiFinder { get; } = new Regex(@"<:(?<name>.+?):(?<id>\d*)>", RegexOptions.Compiled);
|
private Regex emojiFinder { get; } = new Regex(@"<:(?<name>.+?):(?<id>\d*)>", RegexOptions.Compiled);
|
||||||
@ -235,6 +235,9 @@ namespace NadekoBot.Modules.Utility
|
|||||||
var result = string.Join("\n", matches.Cast<Match>()
|
var result = string.Join("\n", matches.Cast<Match>()
|
||||||
.Select(m => $"**Name:** {m.Groups["name"]} **Link:** http://discordapp.com/api/emojis/{m.Groups["id"]}.png"));
|
.Select(m => $"**Name:** {m.Groups["name"]} **Link:** http://discordapp.com/api/emojis/{m.Groups["id"]}.png"));
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(result))
|
||||||
|
await msg.Channel.SendErrorAsync("No special emojis found.");
|
||||||
|
else
|
||||||
await msg.Channel.SendMessageAsync(result).ConfigureAwait(false);
|
await msg.Channel.SendMessageAsync(result).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,43 +257,16 @@ namespace NadekoBot.Modules.Utility
|
|||||||
|
|
||||||
if (!guilds.Any())
|
if (!guilds.Any())
|
||||||
{
|
{
|
||||||
await channel.SendMessageAsync("❎ No servers found on that page.").ConfigureAwait(false);
|
await channel.SendErrorAsync("No servers found on that page.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.SendMessageAsync(String.Join("\n", guilds.Select(g => $"```css\nName: {g.Name} ID:{g.Id} Members:#{g.GetUsers().Count} OwnerID: {g.OwnerId} ```"))).ConfigureAwait(false);
|
await channel.EmbedAsync(guilds.Aggregate(new EmbedBuilder().WithOkColor(),
|
||||||
|
(embed, g) => embed.AddField(efb => efb.WithName(g.Name)
|
||||||
|
.WithValue($"```css\nID: {g.Id}\nMembers: {g.GetUsers().Count}\nOwnerID: {g.OwnerId} ```")
|
||||||
|
.WithIsInline(false)))
|
||||||
|
.Build())
|
||||||
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
//[RequireContext(ContextType.Guild)]
|
|
||||||
//public async Task TextToImage(IUserMessage msg, [Remainder] string arg)
|
|
||||||
//{
|
|
||||||
// var channel = (ITextChannel)msg.Channel;
|
|
||||||
|
|
||||||
// const string bgName = "xbiy3";
|
|
||||||
|
|
||||||
// if (string.IsNullOrWhiteSpace(arg))
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// using (var http = new HttpClient())
|
|
||||||
// {
|
|
||||||
// http.AddFakeHeaders();
|
|
||||||
|
|
||||||
// http.DefaultRequestHeaders.Add("Host", "www.tagsmaker.com");
|
|
||||||
// http.DefaultRequestHeaders.Add("Referer", "http://www.tagsmaker.com/");
|
|
||||||
// http.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
|
|
||||||
// http.DefaultRequestHeaders.Add("Alt-Used", "www.tagsmaker.com:443");
|
|
||||||
|
|
||||||
// var res = await http.GetAsync($"http://www.tagsmaker.com/tagsmaker.php?background_name=0011&tag_text={arg}&font_name=applejuiced&text_color=white&text_size=48&text_alignment=middle").ConfigureAwait(false);
|
|
||||||
|
|
||||||
// var img = res.RequestMessage.RequestUri.Segments[1].Replace("image-", "").Replace("tag-", "");
|
|
||||||
// var imgStream = await http.GetStreamAsync($"http://www.tagsmaker.com/upload/www.tagsmaker.com_{ img.ToString() }.png");
|
|
||||||
// var ms = new MemoryStream();
|
|
||||||
// await imgStream.CopyToAsync(ms).ConfigureAwait(false);
|
|
||||||
// ms.Position = 0;
|
|
||||||
// await channel.SendFileAsync(ms, arg+".png", "Provided by www.tagsmaker.com").ConfigureAwait(false);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ using NadekoBot.TypeReaders;
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using NadekoBot.Modules.Music;
|
using NadekoBot.Modules.Music;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using NadekoBot.Modules.Games.Commands.Hangman;
|
||||||
|
|
||||||
namespace NadekoBot
|
namespace NadekoBot
|
||||||
{
|
{
|
||||||
@ -24,13 +25,12 @@ namespace NadekoBot
|
|||||||
{
|
{
|
||||||
private Logger _log;
|
private Logger _log;
|
||||||
|
|
||||||
public static uint OkColor { get; } = 0x00ff00;
|
public static uint OkColor { get; } = 0x71cd40;
|
||||||
public static uint ErrorColor { get; } = 0xff0000;
|
public static uint ErrorColor { get; } = 0xee281f;
|
||||||
|
|
||||||
public static CommandService CommandService { get; private set; }
|
public static CommandService CommandService { get; private set; }
|
||||||
public static CommandHandler CommandHandler { get; private set; }
|
public static CommandHandler CommandHandler { get; private set; }
|
||||||
public static ShardedDiscordClient Client { get; private set; }
|
public static ShardedDiscordClient Client { get; private set; }
|
||||||
public static Localization Localizer { get; private set; }
|
|
||||||
public static BotCredentials Credentials { get; private set; }
|
public static BotCredentials Credentials { get; private set; }
|
||||||
|
|
||||||
public static GoogleApiService Google { get; private set; }
|
public static GoogleApiService Google { get; private set; }
|
||||||
@ -48,7 +48,7 @@ namespace NadekoBot
|
|||||||
|
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
AllGuildConfigs = uow.GuildConfigs.GetAll();
|
AllGuildConfigs = uow.GuildConfigs.GetAllGuildConfigs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,17 +70,16 @@ namespace NadekoBot
|
|||||||
|
|
||||||
//initialize Services
|
//initialize Services
|
||||||
CommandService = new CommandService();
|
CommandService = new CommandService();
|
||||||
Localizer = new Localization();
|
|
||||||
Google = new GoogleApiService();
|
Google = new GoogleApiService();
|
||||||
CommandHandler = new CommandHandler(Client, CommandService);
|
CommandHandler = new CommandHandler(Client, CommandService);
|
||||||
Stats = new StatsService(Client, CommandHandler);
|
Stats = new StatsService(Client, CommandHandler);
|
||||||
|
|
||||||
//setup DI
|
////setup DI
|
||||||
var depMap = new DependencyMap();
|
//var depMap = new DependencyMap();
|
||||||
depMap.Add<ILocalization>(Localizer);
|
//depMap.Add<ILocalization>(Localizer);
|
||||||
depMap.Add<ShardedDiscordClient>(Client);
|
//depMap.Add<ShardedDiscordClient>(Client);
|
||||||
depMap.Add<CommandService>(CommandService);
|
//depMap.Add<CommandService>(CommandService);
|
||||||
depMap.Add<IGoogleApiService>(Google);
|
//depMap.Add<IGoogleApiService>(Google);
|
||||||
|
|
||||||
|
|
||||||
//setup typereaders
|
//setup typereaders
|
||||||
@ -104,9 +103,9 @@ namespace NadekoBot
|
|||||||
// start handling messages received in commandhandler
|
// start handling messages received in commandhandler
|
||||||
await CommandHandler.StartHandling().ConfigureAwait(false);
|
await CommandHandler.StartHandling().ConfigureAwait(false);
|
||||||
|
|
||||||
await CommandService.LoadAssembly(this.GetType().GetTypeInfo().Assembly, depMap).ConfigureAwait(false);
|
await CommandService.LoadAssembly(this.GetType().GetTypeInfo().Assembly).ConfigureAwait(false);
|
||||||
#if !GLOBAL_NADEKO
|
#if !GLOBAL_NADEKO
|
||||||
await CommandService.Load(new Music(Localizer, CommandService, Client, Google)).ConfigureAwait(false);
|
await CommandService.Load(new Music()).ConfigureAwait(false);
|
||||||
#endif
|
#endif
|
||||||
Ready = true;
|
Ready = true;
|
||||||
Console.WriteLine(await Stats.Print().ConfigureAwait(false));
|
Console.WriteLine(await Stats.Print().ConfigureAwait(false));
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<DnxInvisibleContent Include="data\questions.json" />
|
<DnxInvisibleContent Include="data\questions.json" />
|
||||||
|
<DnxInvisibleContent Include="data\questions2.json" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||||
</Project>
|
</Project>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user