Merge branch 'Kwoth-dev' into delete

This commit is contained in:
Shikhir Arora 2017-04-02 15:39:37 -04:00
commit 78a3f1dc85
54 changed files with 10906 additions and 1046 deletions

View File

@ -1,6 +1,6 @@
You can support the project on patreon: <https://patreon.com/nadekobot> or paypal: <https://paypal.me/Kwoth> You can support the project on patreon: <https://patreon.com/nadekobot> or paypal: <https://paypal.me/Kwoth>
##Table Of Contents ##Table of contents
- [Help](#help) - [Help](#help)
- [Administration](#administration) - [Administration](#administration)
- [ClashOfClans](#clashofclans) - [ClashOfClans](#clashofclans)
@ -16,7 +16,7 @@ You can support the project on patreon: <https://patreon.com/nadekobot> or paypa
### Administration ### Administration
Command and aliases | Description | Usage Commands and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`.resetperms` | Resets the bot's permissions module on this server to the default value. **Requires Administrator server permission.** | `.resetperms` `.resetperms` | Resets the bot's permissions module on this server to the default value. **Requires Administrator server permission.** | `.resetperms`
`.delmsgoncmd` | Toggles the automatic deletion of the user's successful command message to prevent chat flood. **Requires Administrator server permission.** | `.delmsgoncmd` `.delmsgoncmd` | Toggles the automatic deletion of the user's successful command message to prevent chat flood. **Requires Administrator server permission.** | `.delmsgoncmd`
@ -26,9 +26,6 @@ Command and aliases | Description | Usage
`.removeallroles` `.rar` | Removes all roles from a mentioned user. **Requires ManageRoles server permission.** | `.rar @User` `.removeallroles` `.rar` | Removes all roles from a mentioned user. **Requires ManageRoles server permission.** | `.rar @User`
`.createrole` `.cr` | Creates a role with a given name. **Requires ManageRoles server permission.** | `.cr Awesome Role` `.createrole` `.cr` | Creates a role with a given name. **Requires ManageRoles server permission.** | `.cr Awesome Role`
`.rolecolor` `.rc` | Set a role's color to the hex or 0-255 rgb color value provided. **Requires ManageRoles server permission.** | `.rc Admin 255 200 100` or `.rc Admin ffba55` `.rolecolor` `.rc` | Set a role's color to the hex or 0-255 rgb color value provided. **Requires ManageRoles server permission.** | `.rc Admin 255 200 100` or `.rc Admin ffba55`
`.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.`
`.kick` `.k` | Kicks a mentioned user. **Requires KickMembers server permission.** | `.k "@some Guy" Your behaviour is toxic.`
`.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`
@ -40,27 +37,27 @@ Command and aliases | Description | Usage
`.prune` `.clr` | `.prune` removes all Nadeko's messages in the last 100 messages. `.prune X` removes last `X` number of messages from the channel (up to 100). `.prune @Someone` removes all Someone's messages in the last 100 messages. `.prune @Someone X` removes last `X` number of 'Someone's' messages in the channel. | `.prune` or `.prune 5` or `.prune @Someone` or `.prune @Someone X` `.prune` `.clr` | `.prune` removes all Nadeko's messages in the last 100 messages. `.prune X` removes last `X` number of messages from the channel (up to 100). `.prune @Someone` removes all Someone's messages in the last 100 messages. `.prune @Someone X` removes last `X` number of 'Someone's' messages in the channel. | `.prune` or `.prune 5` or `.prune @Someone` or `.prune @Someone X`
`.mentionrole` `.menro` | Mentions every person from the provided role or roles (separated by a ',') on this server. Requires you to have the mention everyone permission. **Requires MentionEveryone server permission.** | `.menro RoleName` `.mentionrole` `.menro` | Mentions every person from the provided role or roles (separated by a ',') on this server. Requires you to have the mention everyone permission. **Requires MentionEveryone server permission.** | `.menro RoleName`
`.donators` | List of the lovely people who donated to keep this project alive. | `.donators` `.donators` | List of the lovely people who donated to keep this project alive. | `.donators`
`.donadd` | Add a donator to the database. **Bot Owner Only** | `.donadd Donate Amount` `.donadd` | Add a donator to the database. **Bot owner only** | `.donadd Donate Amount`
`.autoassignrole` `.aar` | Automaticaly assigns a specified role to every user who joins the server. **Requires ManageRoles server permission.** | `.aar` to disable, `.aar Role Name` to enable `.autoassignrole` `.aar` | Automaticaly assigns a specified role to every user who joins the server. **Requires ManageRoles server permission.** | `.aar` to disable, `.aar Role Name` to enable
`.languageset` `.langset` | Sets this server's response language. If bot's response strings have been translated to that language, bot will use that language in this server. Reset by using `default` as the locale name. Provide no arguments to see currently set language. | `.langset de-DE ` or `.langset default` `.languageset` `.langset` | Sets this server's response language. If bot's response strings have been translated to that language, bot will use that language in this server. Reset by using `default` as the locale name. Provide no arguments to see currently set language. | `.langset de-DE ` or `.langset default`
`.langsetdefault` `.langsetd` | Sets the bot's default response language. All servers which use a default locale will use this one. Setting to `default` will use the host's current culture. Provide no arguments to see currently set language. | `.langsetd en-US` or `.langsetd default` `.langsetdefault` `.langsetd` | Sets the bot's default response language. All servers which use a default locale will use this one. Setting to `default` will use the host's current culture. Provide no arguments to see currently set language. | `.langsetd en-US` or `.langsetd default`
`.languageslist` `.langli` | List of languages for which translation (or part of it) exist atm. | `.langli` `.languageslist` `.langli` | List of languages for which translation (or part of it) exist atm. | `.langli`
`.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` `.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`
`.logevents` | Shows a list of all events you can subscribe to with `.log` **Requires Administrator server permission.** **Bot Owner Only** | `.logevents` `.logevents` | Shows a list of all events you can subscribe to with `.log` **Requires Administrator server permission.** **Bot owner only** | `.logevents`
`.log` | Toggles logging event. Disables it if it is active anywhere on the server. Enables if it isn't active. Use `.logevents` to see a list of all events you can subscribe to. **Requires Administrator server permission.** **Bot Owner Only** | `.log userpresence` or `.log userbanned` `.log` | Toggles logging event. Disables it if it is active anywhere on the server. Enables if it isn't active. Use `.logevents` to see a list of all events you can subscribe to. **Requires Administrator server permission.** **Bot owner only** | `.log userpresence` or `.log userbanned`
`.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` `.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` `.mute` | Mutes a mentioned user both from speaking and chatting. You can also specify time in minutes (up to 1440) for how long the user should be muted. **Requires ManageRoles server permission.** **Requires MuteMembers server permission.** | `.mute @Someone` or `.mute 30 @Someone`
`.unmute` | Unmutes a mentioned user previously muted with `.mute` command. **Requires ManageRoles server permission.** **Requires MuteMembers server permission.** | `.unmute @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` `.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` `.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` `.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` `.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%`, `%time%`, `%shardid%`, `%shardcount%`, `%shardguilds%`. **Bot Owner Only** | `.adpl` `.addplaying` `.adpl` | Adds a specified string to the list of playing strings to rotate. Supported placeholders: `%servers%`, `%users%`, `%playing%`, `%queued%`, `%time%`, `%shardid%`, `%shardcount%`, `%shardguilds%`. **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`
`.removeplaying` `.rmpl` `.repl` | Removes a playing string on a given number. **Bot Owner Only** | `.rmpl` `.removeplaying` `.rmpl` `.repl` | Removes a playing string on a given number. **Bot owner only** | `.rmpl`
`.antiraid` | Sets an anti-raid protection on the server. First argument is number of people which will trigger the protection. Second one is a time interval in which that number of people needs to join in order to trigger the protection, and third argument is punishment for those people (Kick, Ban, Mute) **Requires Administrator server permission.** | `.antiraid 5 20 Kick` `.antiraid` | Sets an anti-raid protection on the server. First argument is number of people which will trigger the protection. Second one is a time interval in which that number of people needs to join in order to trigger the protection, and third argument is punishment for those people (Kick, Ban, Mute) **Requires Administrator server permission.** | `.antiraid 5 20 Kick`
`.antispam` | Stops people from repeating same message X times in a row. You can specify to either mute, kick or ban the offenders. Max message count is 10. **Requires Administrator server permission.** | `.antispam 3 Mute` or `.antispam 4 Kick` or `.antispam 6 Ban` `.antispam` | Stops people from repeating same message X times in a row. You can specify to either mute, kick or ban the offenders. Max message count is 10. **Requires Administrator server permission.** | `.antispam 3 Mute` or `.antispam 4 Kick` or `.antispam 6 Ban`
`.antispamignore` | Toggles whether antispam ignores current channel. Antispam must be enabled. | `.antispamignore` `.antispamignore` | Toggles whether antispam ignores current channel. Antispam must be enabled. | `.antispamignore`
@ -73,19 +70,24 @@ Command and aliases | Description | Usage
`.togglexclsar` `.tesar` | Toggles whether the self-assigned roles are exclusive. (So that any person can have only one of the self assignable roles) **Requires ManageRoles server permission.** | `.tesar` `.togglexclsar` `.tesar` | Toggles whether the self-assigned roles are exclusive. (So that any person can have only one of the self assignable roles) **Requires ManageRoles server permission.** | `.tesar`
`.iam` | Adds a role to you that you choose. Role must be on a list of self-assignable roles. | `.iam Gamer` `.iam` | Adds a role to you that you choose. Role must be on a list of self-assignable roles. | `.iam Gamer`
`.iamnot` `.iamn` | Removes a role to you that you choose. Role must be on a list of self-assignable roles. | `.iamn Gamer` `.iamnot` `.iamn` | Removes a role to you that you choose. Role must be on a list of self-assignable roles. | `.iamn Gamer`
`.fwmsgs` | Toggles forwarding of non-command messages sent to bot's DM to the bot owners **Bot Owner Only** | `.fwmsgs` `.scadd` | Adds a command to the list of commands which will be executed automatically in the current channel, in the order they were added in, by the bot when it startups up. **Bot owner only** | `.scadd .stats`
`.fwtoall` | Toggles whether messages will be forwarded to all bot owners or only to the first one specified in the credentials.json file **Bot Owner Only** | `.fwtoall` `.sclist` | Lists all startup commands in the order they will be executed in. **Bot owner only** | `.sclist`
`.connectshard` | Try (re)connecting a shard with a certain shardid when it dies. No one knows will it work. Keep an eye on the console for errors. **Bot Owner Only** | `.connectshard 2` `.wait` | Used only as a startup command. Waits a certain number of miliseconds before continuing the execution of the following startup commands. **Bot owner only** | `.wait 3000`
`.leave` | Makes Nadeko leave the server. Either server name or server ID is required. **Bot Owner Only** | `.leave 123123123331` `.scrm` | Removes a startup command with the provided command text. **Bot owner only** | `.scrm .stats`
`.die` | Shuts the bot down. **Bot Owner Only** | `.die` `.scclr` | Removes all startup commands. **Bot owner only** | `.scclr`
`.setname` `.newnm` | Gives the bot a new name. **Bot Owner Only** | `.newnm BotName` `.fwmsgs` | Toggles forwarding of non-command messages sent to bot's DM to the bot owners **Bot owner only** | `.fwmsgs`
`.setstatus` | Sets the bot's status. (Online/Idle/Dnd/Invisible) **Bot Owner Only** | `.setstatus Idle` `.fwtoall` | Toggles whether messages will be forwarded to all bot owners or only to the first one specified in the credentials.json file **Bot owner only** | `.fwtoall`
`.setavatar` `.setav` | Sets a new avatar image for the NadekoBot. Argument is a direct link to an image. **Bot Owner Only** | `.setav http://i.imgur.com/xTG3a1I.jpg` `.connectshard` | Try (re)connecting a shard with a certain shardid when it dies. No one knows will it work. Keep an eye on the console for errors. **Bot owner only** | `.connectshard 2`
`.setgame` | Sets the bots game. **Bot Owner Only** | `.setgame with snakes` `.leave` | Makes Nadeko leave the server. Either server name or server ID is required. **Bot owner only** | `.leave 123123123331`
`.setstream` | Sets the bots stream. First argument is the twitch link, second argument is stream name. **Bot Owner Only** | `.setstream TWITCHLINK Hello` `.die` | Shuts the bot down. **Bot owner only** | `.die`
`.send` | Sends a message to someone on a different server through the bot. Separate server and channel/user ids with `|` and prefix the channel id with `c:` and the user id with `u:`. **Bot Owner Only** | `.send serverid|c:channelid message` or `.send serverid|u:userid message` `.setname` `.newnm` | Gives the bot a new name. **Bot owner only** | `.newnm BotName`
`.announce` | Sends a message to all servers' default channel that bot is connected to. **Bot Owner Only** | `.announce Useless spam` `.setstatus` | Sets the bot's status. (Online/Idle/Dnd/Invisible) **Bot owner only** | `.setstatus Idle`
`.reloadimages` | Reloads images bot is using. Safe to use even when bot is being used heavily. **Bot Owner Only** | `.reloadimages` `.setavatar` `.setav` | Sets a new avatar image for the NadekoBot. Argument is a direct link to an image. **Bot owner only** | `.setav http://i.imgur.com/xTG3a1I.jpg`
`.setgame` | Sets the bots game. **Bot owner only** | `.setgame with snakes`
`.setstream` | Sets the bots stream. First argument is the twitch link, second argument is stream name. **Bot owner only** | `.setstream TWITCHLINK Hello`
`.send` | Sends a message to someone on a different server through the bot. Separate server and channel/user ids with `|` and prefix the channel id with `c:` and the user id with `u:`. **Bot owner only** | `.send serverid|c:channelid message` or `.send serverid|u:userid message`
`.announce` | Sends a message to all servers' default channel that bot is connected to. **Bot owner only** | `.announce Useless spam`
`.reloadimages` | Reloads images bot is using. Safe to use even when bot is being used heavily. **Bot owner only** | `.reloadimages`
`.greetdel` `.grdel` | Sets the time it takes (in seconds) for greet messages to be auto-deleted. Set it to 0 to disable automatic deletion. **Requires ManageServer server permission.** | `.greetdel 0` or `.greetdel 30` `.greetdel` `.grdel` | Sets the time it takes (in seconds) for greet messages to be auto-deleted. Set it to 0 to disable automatic deletion. **Requires ManageServer server permission.** | `.greetdel 0` or `.greetdel 30`
`.greet` | Toggles anouncements on the current channel when someone joins the server. **Requires ManageServer server permission.** | `.greet` `.greet` | Toggles anouncements on the current channel when someone joins the server. **Requires ManageServer server permission.** | `.greet`
`.greetmsg` | Sets a new join announcement message which will be shown in the server's channel. Type `%user%` if you want to mention the new member. Using it with no message will show the current greet message. You can use embed json from <http://nadekobot.xyz/embedbuilder/> instead of a regular text, if you want the message to be embedded. **Requires ManageServer server permission.** | `.greetmsg Welcome, %user%.` `.greetmsg` | Sets a new join announcement message which will be shown in the server's channel. Type `%user%` if you want to mention the new member. Using it with no message will show the current greet message. You can use embed json from <http://nadekobot.xyz/embedbuilder/> instead of a regular text, if you want the message to be embedded. **Requires ManageServer server permission.** | `.greetmsg Welcome, %user%.`
@ -94,13 +96,24 @@ Command and aliases | Description | Usage
`.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 show the name the user who left. Type `%id%` to show id. Using this command with no message will show the current bye message. You can use embed json from <http://nadekobot.xyz/embedbuilder/> instead of a regular text, if you want the message to be embedded. **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. You can use embed json from <http://nadekobot.xyz/embedbuilder/> instead of a regular text, if you want the message to be embedded. **Requires ManageServer server permission.** | `.byemsg %user% has left.`
`.byedel` | Sets the time it takes (in seconds) for bye messages to be auto-deleted. Set it to `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 it to `0` to disable automatic deletion. **Requires ManageServer server permission.** | `.byedel 0` or `.byedel 30`
`.warn` | Warns a user. **Requires BanMembers server permission.** | `.warn @b1nzy`
`.warnlog` | See a list of warnings of a certain user. **Requires BanMembers server permission.** | `.warnlog @b1nzy`
`.warnclear` `.warnc` | Clears all warnings from a certain user. **Requires BanMembers server permission.** | `.warnclear @PoorDude`
`.warnpunish` `.warnp` | Sets a punishment for a certain number of warnings. Provide no punishment to remove. **Requires BanMembers server permission.** | `.warnpunish 5 Ban` or `.warnpunish 3`
`.warnpunishlist` `.warnpl` | Lists punishments for warnings. | `.warnpunishlist`
`.ban` `.b` | Bans a user by ID or name with an optional message. **Requires BanMembers server permission.** | `.b "@some Guy" Your behaviour is toxic.`
`.unban` | Unbans a user with the provided user#discrim or id. **Requires BanMembers server permission.** | `.unban kwoth#1234` or `.unban 123123123`
`.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.`
`.vcrole` | Sets or resets a role which will be given to users who join the voice channel you're in when you run this command. Provide no role name to disable. You must be in a voice channel to run this command. **Requires ManageRoles server permission.** **Requires ManageChannels server permission.** | `.vcrole SomeRole` or `.vcrole`
`.vcrolelist` | Shows a list of currently set voice channel roles. | `.vcrolelist`
`.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.** | `.v+t` `.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.** | `.v+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` `.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`
###### [Back to ToC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
### ClashOfClans ### ClashOfClans
Command and aliases | Description | Usage Commands and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`,createwar` `,cw` | Creates a new war by specifying a size (>10 and multiple of 5) and enemy clan name. **Requires ManageMessages server permission.** | `,cw 15 The Enemy Clan` `,createwar` `,cw` | Creates a new war by specifying a size (>10 and multiple of 5) and enemy clan name. **Requires ManageMessages server permission.** | `,cw 15 The Enemy Clan`
`,startwar` `,sw` | Starts a war with a given number. | `,sw 15` `,startwar` `,sw` | Starts a war with a given number. | `,sw 15`
@ -115,31 +128,33 @@ Command and aliases | Description | Usage
###### [Back to ToC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
### CustomReactions ### CustomReactions
Command and aliases | Description | Usage Commands and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`.addcustreact` `.acr` | Add a custom reaction with a trigger and a response. Running this command in server requires the Administration permission. Running this command in DM is Bot Owner only and adds a new global custom reaction. Guide here: <http://nadekobot.readthedocs.io/en/latest/Custom%20Reactions/> | `.acr "hello" Hi there %user%` `.addcustreact` `.acr` | Add a custom reaction with a trigger and a response. Running this command in server requires the Administration permission. Running this command in DM is Bot Owner only and adds a new global custom reaction. Guide here: <http://nadekobot.readthedocs.io/en/latest/Custom%20Reactions/> | `.acr "hello" Hi there %user%`
`.listcustreact` `.lcr` | Lists global or server custom reactions (20 commands per page). Running the command in DM will list global custom reactions, while running it in server will list that server's custom reactions. Specifying `all` argument instead of the number will DM you a text file with a list of all custom reactions. | `.lcr 1` or `.lcr all` `.listcustreact` `.lcr` | Lists global or server custom reactions (20 commands per page). Running the command in DM will list global custom reactions, while running it in server will list that server's custom reactions. Specifying `all` argument instead of the number will DM you a text file with a list of all custom reactions. | `.lcr 1` or `.lcr all`
`.listcustreactg` `.lcrg` | Lists global or server custom reactions (20 commands per page) grouped by trigger, and show a number of responses for each. Running the command in DM will list global custom reactions, while running it in server will list that server's custom reactions. | `.lcrg 1` `.listcustreactg` `.lcrg` | Lists global or server custom reactions (20 commands per page) grouped by trigger, and show a number of responses for each. Running the command in DM will list global custom reactions, while running it in server will list that server's custom reactions. | `.lcrg 1`
`.showcustreact` `.scr` | Shows a custom reaction's response on a given ID. | `.scr 1` `.showcustreact` `.scr` | Shows a custom reaction's response on a given ID. | `.scr 1`
`.delcustreact` `.dcr` | Deletes a custom reaction on a specific index. If ran in DM, it is bot owner only and deletes a global custom reaction. If ran in a server, it requires Administration privileges and removes server custom reaction. | `.dcr 5` `.delcustreact` `.dcr` | Deletes a custom reaction on a specific index. If ran in DM, it is bot owner only and deletes a global custom reaction. If ran in a server, it requires Administration privileges and removes server custom reaction. | `.dcr 5`
`.crstatsclear` | Resets the counters on `.crstats`. You can specify a trigger to clear stats only for that trigger. **Bot Owner Only** | `.crstatsclear` or `.crstatsclear rng` `.crdm` | Toggles whether the response message of the custom reaction will be sent as a direct message. | `.crad 44`
`.crad` | Toggles whether the message triggering the custom reaction will be automatically deleted. | `.crad 59`
`.crstatsclear` | Resets the counters on `.crstats`. You can specify a trigger to clear stats only for that trigger. **Bot owner only** | `.crstatsclear` or `.crstatsclear rng`
`.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` `.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)
### Gambling ### Gambling
Command and aliases | Description | Usage Commands and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`$raffle` | Prints a name and ID of a random user from the online list from the (optional) role. | `$raffle` or `$raffle RoleName` `$raffle` | Prints a name and ID of a random user from the online list from the (optional) role. | `$raffle` or `$raffle RoleName`
`$cash` `$$$` | Check how much currency a person has. (Defaults to yourself) | `$$$` or `$$$ @SomeGuy` `$cash` `$$$` | Check how much currency a person has. (Defaults to yourself) | `$$$` or `$$$ @SomeGuy`
`$give` | Give someone a certain amount of currency. | `$give 1 "@SomeGuy"` `$give` | Give someone a certain amount of currency. | `$give 1 "@SomeGuy"`
`$award` | Awards someone a certain amount of currency. You can also specify a role name to award currency to all users in a role. **Bot Owner Only** | `$award 100 @person` or `$award 5 Role Of Gamblers` `$award` | Awards someone a certain amount of currency. You can also specify a role name to award currency to all users in a role. **Bot owner only** | `$award 100 @person` or `$award 5 Role Of Gamblers`
`$take` | Takes a certain amount of currency from someone. **Bot Owner Only** | `$take 1 "@someguy"` `$take` | Takes a certain amount of currency from someone. **Bot owner only** | `$take 1 "@someguy"`
`$betroll` `$br` | Bets a certain amount of currency and rolls a dice. Rolling over 66 yields x2 of your currency, over 90 - x4 and 100 x10. | `$br 5` `$betroll` `$br` | Bets a certain amount of currency and rolls a dice. Rolling over 66 yields x2 of your currency, over 90 - x4 and 100 x10. | `$br 5`
`$leaderboard` `$lb` | Displays the bot's currency leaderboard. | `$lb` `$leaderboard` `$lb` | Displays the bot's 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`
`$startevent` | Starts one of the events seen on public nadeko. **Bot Owner Only** | `$startevent flowerreaction` `$startevent` | Starts one of the events seen on public nadeko. **Bot owner only** | `$startevent flowerreaction`
`$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` `$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`
@ -147,10 +162,10 @@ Command and aliases | Description | Usage
`$shuffle` `$sh` | Reshuffles all cards back into the deck. | `$sh` `$shuffle` `$sh` | Reshuffles all cards back into the deck. | `$sh`
`$flip` | Flips coin(s) - heads or tails, and shows an image. | `$flip` or `$flip 3` `$flip` | Flips coin(s) - heads or tails, and shows an image. | `$flip` or `$flip 3`
`$betflip` `$bf` | Bet to guess will the result be heads or tails. Guessing awards you 1.95x the currency you've bet (rounded up). Multiplier can be changed by the bot owner. | `$bf 5 heads` or `$bf 3 t` `$betflip` `$bf` | Bet to guess will the result be heads or tails. Guessing awards you 1.95x the currency you've bet (rounded up). Multiplier can be changed by the bot owner. | `$bf 5 heads` or `$bf 3 t`
`$slotstats` | Shows the total stats of the slot command for this bot's session. **Bot Owner Only** | `$slotstats` `$slotstats` | Shows the total stats of the slot command for this bot's session. **Bot owner only** | `$slotstats`
`$slottest` | Tests to see how much slots payout for X number of plays. **Bot Owner Only** | `$slottest 1000` `$slottest` | Tests to see how much slots payout for X number of plays. **Bot owner only** | `$slottest 1000`
`$slot` | Play Nadeko slots. Max bet is 999. 3 seconds cooldown per user. | `$slot 5` `$slot` | Play Nadeko slots. Max bet is 999. 3 seconds cooldown per user. | `$slot 5`
`$claimwaifu` `$claim` | Claim a waifu for yourself by spending currency. You must spend atleast 10% more than her current value unless she set `$affinity` towards you. | `$claim 50 @Himesama` `$claimwaifu` `$claim` | Claim a waifu for yourself by spending currency. You must spend at least 10% more than her current value unless she set `$affinity` towards you. | `$claim 50 @Himesama`
`$divorce` | Releases your claim on a specific waifu. You will get some of the money you've spent back unless that waifu has an affinity towards you. 6 hours cooldown. | `$divorce @CheatingSloot` `$divorce` | Releases your claim on a specific waifu. You will get some of the money you've spent back unless that waifu has an affinity towards you. 6 hours cooldown. | `$divorce @CheatingSloot`
`$affinity` | Sets your affinity towards someone you want to be claimed by. Setting affinity will reduce their `$claim` on you by 20%. You can leave second argument empty to clear your affinity. 30 minutes cooldown. | `$affinity @MyHusband` or `$affinity` `$affinity` | Sets your affinity towards someone you want to be claimed by. Setting affinity will reduce their `$claim` on you by 20%. You can leave second argument empty to clear your affinity. 30 minutes cooldown. | `$affinity @MyHusband` or `$affinity`
`$waifus` `$waifulb` | Shows top 9 waifus. | `$waifus` `$waifus` `$waifulb` | Shows top 9 waifus. | `$waifus`
@ -159,7 +174,7 @@ Command and aliases | Description | Usage
###### [Back to ToC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
### Games ### Games
Command and aliases | Description | Usage Commands and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`>choose` | Chooses a thing from a list of things | `>choose Get up;Sleep;Sleep more` `>choose` | Chooses a thing from a list of things | `>choose Get up;Sleep;Sleep more`
`>8ball` | Ask the 8ball a yes/no question. | `>8ball should I do something` `>8ball` | Ask the 8ball a yes/no question. | `>8ball should I do something`
@ -167,7 +182,7 @@ Command and aliases | Description | Usage
`>rategirl` | Use the universal hot-crazy wife zone matrix to determine the girl's worth. It is everything young men need to know about women. At any moment in time, any woman you have previously located on this chart can vanish from that location and appear anywhere else on the chart. | `>rategirl @SomeGurl` `>rategirl` | Use the universal hot-crazy wife zone matrix to determine the girl's worth. It is everything young men need to know about women. At any moment in time, any woman you have previously located on this chart can vanish from that location and appear anywhere else on the chart. | `>rategirl @SomeGurl`
`>linux` | Prints a customizable Linux interjection | `>linux Spyware Windows` `>linux` | Prints a customizable Linux interjection | `>linux Spyware Windows`
`>leet` | Converts a text to leetspeak with 6 (1-6) severity levels | `>leet 3 Hello` `>leet` | Converts a text to leetspeak with 6 (1-6) severity levels | `>leet 3 Hello`
`>acrophobia` `>acro` | Starts an Acrophobia game. Second argment is optional round length in seconds. (default is 60) | `>acro` or `>acro 30` `>acrophobia` `>acro` | Starts an Acrophobia game. Second argument is optional round length in seconds. (default is 60) | `>acro` or `>acro 30`
`>cleverbot` | Toggles cleverbot session. When enabled, the bot will reply to messages starting with bot mention in the server. Custom reactions starting with %mention% won't work if cleverbot is enabled. **Requires ManageMessages server permission.** | `>cleverbot` `>cleverbot` | Toggles cleverbot session. When enabled, the bot will reply to messages starting with bot mention in the server. Custom reactions starting with %mention% won't work if cleverbot is enabled. **Requires ManageMessages server permission.** | `>cleverbot`
`>hangmanlist` | Shows a list of hangman term types. | `> hangmanlist` `>hangmanlist` | Shows a list of hangman term types. | `> hangmanlist`
`>hangman` | Starts a game of hangman in the channel. Use `>hangmanlist` to see a list of available term types. Defaults to 'all'. | `>hangman` or `>hangman movies` `>hangman` | Starts a game of hangman in the channel. Use `>hangmanlist` to see a list of available term types. Defaults to 'all'. | `>hangman` or `>hangman movies`
@ -180,9 +195,9 @@ Command and aliases | Description | Usage
`>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`
`>typestart` | Starts a typing contest. | `>typestart` `>typestart` | Starts a typing contest. | `>typestart`
`>typestop` | Stops a typing contest on the current channel. | `>typestop` `>typestop` | Stops a typing contest on the current channel. | `>typestop`
`>typeadd` | Adds a new article to the typing contest. **Bot Owner Only** | `>typeadd wordswords` `>typeadd` | Adds a new article to the typing contest. **Bot owner only** | `>typeadd wordswords`
`>typelist` | Lists added typing articles with their IDs. 15 per page. | `>typelist` or `>typelist 3` `>typelist` | Lists added typing articles with their IDs. 15 per page. | `>typelist` or `>typelist 3`
`>typedel` | Deletes a typing article given the ID. **Bot Owner Only** | `>typedel 3` `>typedel` | Deletes a typing article given the ID. **Bot owner only** | `>typedel 3`
`>tictactoe` `>ttt` | Starts a game of tic tac toe. Another user must run the command in the same channel in order to accept the challenge. Use numbers 1-9 to play. 15 seconds per move. | >ttt `>tictactoe` `>ttt` | Starts a game of tic tac toe. Another user must run the command in the same channel in order to accept the challenge. Use numbers 1-9 to play. 15 seconds per move. | >ttt
`>trivia` `>t` | Starts a game of trivia. You can add `nohint` to prevent hints. First player to get to 10 points wins by default. You can specify a different number. 30 seconds per question. | `>t` or `>t 5 nohint` `>trivia` `>t` | Starts a game of trivia. You can add `nohint` to prevent hints. First player to get to 10 points wins by default. You can specify a different number. 30 seconds per question. | `>t` or `>t 5 nohint`
`>tl` | Shows a current trivia leaderboard. | `>tl` `>tl` | Shows a current trivia leaderboard. | `>tl`
@ -191,19 +206,19 @@ Command and aliases | Description | Usage
###### [Back to ToC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
### Help ### Help
Command and aliases | Description | Usage Commands and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`-modules` `-mdls` | Lists all bot modules. | `-modules` `-modules` `-mdls` | Lists all bot modules. | `-modules`
`-commands` `-cmds` | List all of the bot's commands from a certain module. You can either specify the full name or only the first few letters of the module name. | `-commands Administration` or `-cmds Admin` `-commands` `-cmds` | List all of the bot's commands from a certain module. You can either specify the full name or only the first few letters of the module name. | `-commands Administration` or `-cmds Admin`
`-help` `-h` | Either shows a help for a single command, or DMs you help link if no arguments are specified. | `-h -cmds` or `-h` `-help` `-h` | Either shows a help for a single command, or DMs you help link if no arguments are specified. | `-h -cmds` or `-h`
`-hgit` | Generates the commandlist.md file. **Bot Owner Only** | `-hgit` `-hgit` | Generates the commandlist.md file. **Bot owner only** | `-hgit`
`-readme` `-guide` | Sends a readme and a guide links to the channel. | `-readme` or `-guide` `-readme` `-guide` | Sends a readme and a guide links to the channel. | `-readme` or `-guide`
`-donate` | Instructions for helping the project financially. | `-donate` `-donate` | Instructions for helping the project financially. | `-donate`
###### [Back to ToC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
### Music ### Music
Command and aliases | Description | Usage Commands and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`!!next` `!!n` | Goes to the next song in the queue. You have to be in the same voice channel as the bot. You can skip multiple songs, but in that case songs will not be requeued if !!rcs or !!rpl is enabled. | `!!n` or `!!n 5` `!!next` `!!n` | Goes to the next song in the queue. You have to be in the same voice channel as the bot. You can skip multiple songs, but in that case songs will not be requeued if !!rcs or !!rpl is enabled. | `!!n` or `!!n 5`
`!!stop` `!!s` | Stops the music and clears the playlist. Stays in the channel. | `!!s` `!!stop` `!!s` | Stops the music and clears the playlist. Stays in the channel. | `!!s`
@ -219,9 +234,9 @@ Command and aliases | Description | Usage
`!!shuffle` `!!sh` | Shuffles the current playlist. | `!!sh` `!!shuffle` `!!sh` | Shuffles the current playlist. | `!!sh`
`!!playlist` `!!pl` | Queues up to 500 songs from a youtube playlist specified by a link, or keywords. | `!!pl playlist link or name` `!!playlist` `!!pl` | Queues up to 500 songs from a youtube playlist specified by a link, or keywords. | `!!pl playlist link or name`
`!!soundcloudpl` `!!scpl` | Queue a Soundcloud playlist using a link. | `!!scpl soundcloudseturl` `!!soundcloudpl` `!!scpl` | Queue a Soundcloud playlist using a link. | `!!scpl soundcloudseturl`
`!!localplaylst` `!!lopl` | Queues all songs from a directory. **Bot Owner Only** | `!!lopl C:/music/classical` `!!localplaylst` `!!lopl` | Queues all songs from a directory. **Bot owner only** | `!!lopl C:/music/classical`
`!!radio` `!!ra` | Queues a radio stream from a link. It can be a direct mp3 radio stream, .m3u, .pls .asx or .xspf (Usage Video: <https://streamable.com/al54>) | `!!ra radio link here` `!!radio` `!!ra` | Queues a radio stream from a link. It can be a direct mp3 radio stream, .m3u, .pls .asx or .xspf (Usage Video: <https://streamable.com/al54>) | `!!ra radio link here`
`!!local` `!!lo` | Queues a local file by specifying a full path. **Bot Owner Only** | `!!lo C:/music/mysong.mp3` `!!local` `!!lo` | Queues a local file by specifying a full path. **Bot owner only** | `!!lo C:/music/mysong.mp3`
`!!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`
@ -239,7 +254,7 @@ Command and aliases | Description | Usage
###### [Back to ToC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
### NSFW ### NSFW
Command and aliases | Description | Usage Commands 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`
`~autohentai` | Posts a hentai every X seconds with a random tag from the provided tags. Use `|` to separate tags. 20 seconds minimum. Provide no arguments to disable. **Requires ManageMessages channel permission.** | `~autohentai 30 yuri|tail|long_hair` or `~autohentai` `~autohentai` | Posts a hentai every X seconds with a random tag from the provided tags. Use `|` to separate tags. 20 seconds minimum. Provide no arguments to disable. **Requires ManageMessages channel permission.** | `~autohentai 30 yuri|tail|long_hair` or `~autohentai`
@ -257,7 +272,7 @@ Command and aliases | Description | Usage
###### [Back to ToC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
### Permissions ### Permissions
Command and aliases | Description | Usage Commands and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`;verbose` `;v` | Sets whether to show when a command/module is blocked. | `;verbose true` `;verbose` `;v` | Sets whether to show when a command/module is blocked. | `;verbose true`
`;permrole` `;pr` | Sets a role which can change permissions. Supply no parameters to see the current one. Default is 'Nadeko'. | `;pr role` `;permrole` `;pr` | Sets a role which can change permissions. Supply no parameters to see the current one. Default is 'Nadeko'. | `;pr role`
@ -276,9 +291,9 @@ Command and aliases | Description | Usage
`;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`
`;allsrvrmdls` `;asm` | Enable or disable all modules for your server. | `;asm [enable/disable]` `;allsrvrmdls` `;asm` | Enable or disable all modules for your server. | `;asm [enable/disable]`
`;ubl` | Either [add]s or [rem]oves a user specified by a Mention or an ID from a blacklist. **Bot Owner Only** | `;ubl add @SomeUser` or `;ubl rem 12312312313` `;ubl` | Either [add]s or [rem]oves a user specified by a Mention or an ID from a blacklist. **Bot owner only** | `;ubl add @SomeUser` or `;ubl rem 12312312313`
`;cbl` | Either [add]s or [rem]oves a channel specified by an ID from a blacklist. **Bot Owner Only** | `;cbl rem 12312312312` `;cbl` | Either [add]s or [rem]oves a channel specified by an ID from a blacklist. **Bot owner only** | `;cbl rem 12312312312`
`;sbl` | Either [add]s or [rem]oves a server specified by a Name or an ID from a blacklist. **Bot Owner Only** | `;sbl add 12312321312` or `;sbl rem SomeTrashServer` `;sbl` | Either [add]s or [rem]oves a server specified by a Name or an ID from a blacklist. **Bot owner only** | `;sbl add 12312321312` or `;sbl rem SomeTrashServer`
`;cmdcooldown` `;cmdcd` | Sets a cooldown per user for a command. Set it to 0 to remove the cooldown. | `;cmdcd "some cmd" 5` `;cmdcooldown` `;cmdcd` | Sets a cooldown per user for a command. Set it to 0 to remove the cooldown. | `;cmdcd "some cmd" 5`
`;allcmdcooldowns` `;acmdcds` | Shows a list of all commands and their respective cooldowns. | `;acmdcds` `;allcmdcooldowns` `;acmdcds` | Shows a list of all commands and their respective cooldowns. | `;acmdcds`
`;srvrfilterinv` `;sfi` | Toggles automatic deletion of invites posted in the server. Does not affect the Bot Owner. | `;sfi` `;srvrfilterinv` `;sfi` | Toggles automatic deletion of invites posted in the server. Does not affect the Bot Owner. | `;sfi`
@ -291,7 +306,7 @@ Command and aliases | Description | Usage
###### [Back to ToC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
### Pokemon ### Pokemon
Command and aliases | Description | Usage Commands 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` `>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` `>movelist` `>ml` | Lists the moves you are able to use | `>ml`
@ -302,7 +317,7 @@ Command and aliases | Description | Usage
###### [Back to ToC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
### Searches ### Searches
Command and aliases | Description | Usage Commands and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`~weather` `~we` | Shows weather data for a specified city. You can also specify a country after a comma. | `~we Moscow, RU` `~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`
@ -355,7 +370,7 @@ Command and aliases | Description | Usage
`~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` `~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`
`~autotranslang` `~atl` | Sets your source and target language to be used with `~at`. Specify no arguments to remove previously set value. | `~atl en>fr` `~autotranslang` `~atl` | Sets your source and target language to be used with `~at`. Specify no arguments to remove previously set value. | `~atl en>fr`
`~translangs` | Lists the valid languages for translation. | `~translangs` `~translangs` | Lists the valid languages for translation. | `~translangs`
`~xkcd` | Shows a XKCD comic. No arguments will retrieve random one. Number argument will retrieve a specific comic, and "latest" will get the latest one. | `~xkcd` or `~xkcd 1400` or `~xkcd latest` `~xkcd` | Shows a XKCD comic. No arguments will retrieve random one. Number argument will retrieve a specific comic, and "latest" will get the latest one. | `~xkcd` or `~xkcd 1400` or `~xkcd latest`
@ -363,12 +378,12 @@ Command and aliases | Description | Usage
###### [Back to ToC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
### Utility ### Utility
Command and aliases | Description | Usage Commands and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`.rotaterolecolor` `.rrc` | Rotates a roles color on an interval with a list of supplied colors. First argument is interval in seconds (Minimum 60). Second argument is a role, followed by a space-separated list of colors in hex. Provide a rolename with a 0 interval to disable. **Requires ManageRoles server permission.** **Bot Owner Only** | `.rrc 60 MyLsdRole #ff0000 #00ff00 #0000ff` or `.rrc 0 MyLsdRole` `.rotaterolecolor` `.rrc` | Rotates a roles color on an interval with a list of supplied colors. First argument is interval in seconds (Minimum 60). Second argument is a role, followed by a space-separated list of colors in hex. Provide a rolename with a 0 interval to disable. **Requires ManageRoles server permission.** **Bot owner only** | `.rrc 60 MyLsdRole #ff0000 #00ff00 #0000ff` or `.rrc 0 MyLsdRole`
`.togethertube` `.totube` | Creates a new room on <https://togethertube.com> and shows the link in the chat. | `.totube` `.togethertube` `.totube` | Creates a new room on <https://togethertube.com> and shows the link in the chat. | `.totube`
`.whosplaying` `.whpl` | Shows a list of users who are playing the specified game. | `.whpl Overwatch` `.whosplaying` `.whpl` | Shows a list of users who are playing the specified game. | `.whpl Overwatch`
`.inrole` | Lists every person from the provided role or roles, separated with space, on this server. You can use role IDs, role names (in quotes if it has multiple words), or role mention If the list is too long for 1 message, you must have Manage Messages permission. | `.inrole Role` or `.inrole Role1 "Role 2" @role3` `.inrole` | Lists every person from the specified role on this server. You can use role ID, role name. | `.inrole Some Role`
`.checkmyperms` | Checks your user-specific permissions on this channel. | `.checkmyperms` `.checkmyperms` | Checks your user-specific permissions on this channel. | `.checkmyperms`
`.userid` `.uid` | Shows user ID. | `.uid` or `.uid "@SomeGuy"` `.userid` `.uid` | Shows user ID. | `.uid` or `.uid "@SomeGuy"`
`.channelid` `.cid` | Shows current channel ID. | `.cid` `.channelid` `.cid` | Shows current channel ID. | `.cid`
@ -380,12 +395,14 @@ Command and aliases | Description | Usage
`.shardid` | Shows which shard is a certain guild on, by guildid. | `.shardid 117523346618318850` `.shardid` | Shows which shard is a certain guild on, by guildid. | `.shardid 117523346618318850`
`.stats` | Shows some basic stats for Nadeko. | `.stats` `.stats` | Shows some basic stats for Nadeko. | `.stats`
`.showemojis` `.se` | Shows a name and a link to every SPECIAL emoji in the message. | `.se A message full of SPECIAL emojis` `.showemojis` `.se` | Shows a name and a link to every SPECIAL emoji in the message. | `.se A message full of SPECIAL emojis`
`.listservers` | Lists servers the bot is on with some basic info. 15 per page. **Bot Owner Only** | `.listservers 3` `.listservers` | Lists servers the bot is on with some basic info. 15 per page. **Bot owner only** | `.listservers 3`
`.savechat` | Saves a number of messages to a text file and sends it to you. **Bot Owner Only** | `.savechat 150` `.savechat` | Saves a number of messages to a text file and sends it to you. **Bot owner only** | `.savechat 150`
`.activity` | Checks for spammers. **Bot Owner Only** | `.activity` `.activity` | Checks for spammers. **Bot owner only** | `.activity`
`.calculate` `.calc` | Evaluate a mathematical expression. | `.calc 1+1` `.calculate` `.calc` | Evaluate a mathematical expression. | `.calc 1+1`
`.calcops` | Shows all available operations in the `.calc` command | `.calcops` `.calcops` | Shows all available operations in the `.calc` command | `.calcops`
`.scsc` | Starts an instance of cross server channel. You will get a token as a DM that other people will use to tune in to the same instance. **Bot Owner Only** | `.scsc` `.alias` `.cmdmap` | Create a custom alias for a certain Nadeko command. Provide no alias to remove the existing one. **Requires Administrator server permission.** | `.alias allin $bf 100 h` or `.alias "linux thingy" >loonix Spyware Windows`
`.aliaslist` `.cmdmaplist` `.aliases` | Shows the list of currently set aliases. Paginated. | `.aliaslist` or `.aliaslist 3`
`.scsc` | Starts an instance of cross server channel. You will get a token as a DM that other people will use to tune in to the same instance. **Bot owner only** | `.scsc`
`.jcsc` | Joins current channel to an instance of cross server channel using the token. **Requires ManageServer server permission.** | `.jcsc TokenHere` `.jcsc` | Joins current channel to an instance of cross server channel using the token. **Requires ManageServer server permission.** | `.jcsc TokenHere`
`.lcsc` | Leaves a cross server channel instance from this channel. **Requires ManageServer server permission.** | `.lcsc` `.lcsc` | Leaves a cross server channel instance from this channel. **Requires ManageServer server permission.** | `.lcsc`
`.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`
@ -399,9 +416,9 @@ Command and aliases | Description | Usage
`...` | Shows a random quote with a specified name. | `... abc` `...` | Shows a random quote with a specified name. | `... abc`
`.qsearch` | Shows a random quote for a keyword that contains any text specified in the search. | `.qsearch keyword text` `.qsearch` | Shows a random quote for a keyword that contains any text specified in the search. | `.qsearch keyword text`
`..` | 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 quote with the specified ID. You have to be either server Administrator or the creator of the quote to delete it. | `.delq 123456`
`.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 1m 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`

View File

@ -6,6 +6,6 @@ namespace NadekoBot.Attributes
public class OwnerOnlyAttribute : PreconditionAttribute public class OwnerOnlyAttribute : PreconditionAttribute
{ {
public override Task<PreconditionResult> CheckPermissions(ICommandContext context, CommandInfo executingCommand,IDependencyMap depMap) => public override Task<PreconditionResult> CheckPermissions(ICommandContext context, CommandInfo executingCommand,IDependencyMap depMap) =>
Task.FromResult((NadekoBot.Credentials.IsOwner(context.User) ? PreconditionResult.FromSuccess() : PreconditionResult.FromError("Not owner"))); Task.FromResult((NadekoBot.Credentials.IsOwner(context.User) || NadekoBot.Client.CurrentUser.Id == context.User.Id ? PreconditionResult.FromSuccess() : PreconditionResult.FromError("Not owner")));
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class warningcommands : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "WarningsInitialized",
table: "GuildConfigs",
nullable: false,
defaultValue: false);
migrationBuilder.CreateTable(
name: "Warnings",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
DateAdded = table.Column<DateTime>(nullable: true),
Forgiven = table.Column<bool>(nullable: false),
ForgivenBy = table.Column<string>(nullable: true),
GuildId = table.Column<ulong>(nullable: false),
Moderator = table.Column<string>(nullable: true),
Reason = table.Column<string>(nullable: true),
UserId = table.Column<ulong>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Warnings", x => x.Id);
});
migrationBuilder.CreateTable(
name: "WarningPunishment",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Count = table.Column<int>(nullable: false),
DateAdded = table.Column<DateTime>(nullable: true),
GuildConfigId = table.Column<int>(nullable: true),
Punishment = table.Column<int>(nullable: false),
Time = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_WarningPunishment", x => x.Id);
table.ForeignKey(
name: "FK_WarningPunishment_GuildConfigs_GuildConfigId",
column: x => x.GuildConfigId,
principalTable: "GuildConfigs",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_WarningPunishment_GuildConfigId",
table: "WarningPunishment",
column: "GuildConfigId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Warnings");
migrationBuilder.DropTable(
name: "WarningPunishment");
migrationBuilder.DropColumn(
name: "WarningsInitialized",
table: "GuildConfigs");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class startupcommands : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "StartupCommand",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
BotConfigId = table.Column<int>(nullable: true),
ChannelId = table.Column<ulong>(nullable: false),
ChannelName = table.Column<string>(nullable: true),
CommandText = table.Column<string>(nullable: true),
DateAdded = table.Column<DateTime>(nullable: true),
GuildId = table.Column<ulong>(nullable: true),
GuildName = table.Column<string>(nullable: true),
Index = table.Column<int>(nullable: false),
VoiceChannelId = table.Column<ulong>(nullable: true),
VoiceChannelName = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_StartupCommand", x => x.Id);
table.ForeignKey(
name: "FK_StartupCommand_BotConfig_BotConfigId",
column: x => x.BotConfigId,
principalTable: "BotConfig",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_StartupCommand_BotConfigId",
table: "StartupCommand",
column: "BotConfigId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "StartupCommand");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class slowmodewhitelist : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "SlowmodeIgnoredRole",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
DateAdded = table.Column<DateTime>(nullable: true),
GuildConfigId = table.Column<int>(nullable: true),
RoleId = table.Column<ulong>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_SlowmodeIgnoredRole", x => x.Id);
table.ForeignKey(
name: "FK_SlowmodeIgnoredRole_GuildConfigs_GuildConfigId",
column: x => x.GuildConfigId,
principalTable: "GuildConfigs",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "SlowmodeIgnoredUser",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
DateAdded = table.Column<DateTime>(nullable: true),
GuildConfigId = table.Column<int>(nullable: true),
UserId = table.Column<ulong>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_SlowmodeIgnoredUser", x => x.Id);
table.ForeignKey(
name: "FK_SlowmodeIgnoredUser_GuildConfigs_GuildConfigId",
column: x => x.GuildConfigId,
principalTable: "GuildConfigs",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_SlowmodeIgnoredRole_GuildConfigId",
table: "SlowmodeIgnoredRole",
column: "GuildConfigId");
migrationBuilder.CreateIndex(
name: "IX_SlowmodeIgnoredUser_GuildConfigId",
table: "SlowmodeIgnoredUser",
column: "GuildConfigId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "SlowmodeIgnoredRole");
migrationBuilder.DropTable(
name: "SlowmodeIgnoredUser");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class patreonrewards : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "RewardedUsers",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
AmountRewardedThisMonth = table.Column<int>(nullable: false),
DateAdded = table.Column<DateTime>(nullable: true),
LastReward = table.Column<DateTime>(nullable: false),
UserId = table.Column<ulong>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_RewardedUsers", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_RewardedUsers_UserId",
table: "RewardedUsers",
column: "UserId",
unique: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "RewardedUsers");
}
}
}

View File

@ -559,6 +559,8 @@ namespace NadekoBot.Migrations
b.Property<bool>("VoicePlusTextEnabled"); b.Property<bool>("VoicePlusTextEnabled");
b.Property<bool>("WarningsInitialized");
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("GuildId") b.HasIndex("GuildId")
@ -929,6 +931,27 @@ namespace NadekoBot.Migrations
b.ToTable("Reminders"); b.ToTable("Reminders");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.RewardedUser", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("AmountRewardedThisMonth");
b.Property<DateTime?>("DateAdded");
b.Property<DateTime>("LastReward");
b.Property<ulong>("UserId");
b.HasKey("Id");
b.HasIndex("UserId")
.IsUnique();
b.ToTable("RewardedUsers");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -948,6 +971,74 @@ namespace NadekoBot.Migrations
b.ToTable("SelfAssignableRoles"); b.ToTable("SelfAssignableRoles");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime?>("DateAdded");
b.Property<int?>("GuildConfigId");
b.Property<ulong>("RoleId");
b.HasKey("Id");
b.HasIndex("GuildConfigId");
b.ToTable("SlowmodeIgnoredRole");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime?>("DateAdded");
b.Property<int?>("GuildConfigId");
b.Property<ulong>("UserId");
b.HasKey("Id");
b.HasIndex("GuildConfigId");
b.ToTable("SlowmodeIgnoredUser");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.StartupCommand", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int?>("BotConfigId");
b.Property<ulong>("ChannelId");
b.Property<string>("ChannelName");
b.Property<string>("CommandText");
b.Property<DateTime?>("DateAdded");
b.Property<ulong?>("GuildId");
b.Property<string>("GuildName");
b.Property<int>("Index");
b.Property<ulong?>("VoiceChannelId");
b.Property<string>("VoiceChannelName");
b.HasKey("Id");
b.HasIndex("BotConfigId");
b.ToTable("StartupCommand");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -1060,6 +1151,52 @@ namespace NadekoBot.Migrations
b.ToTable("WaifuUpdates"); b.ToTable("WaifuUpdates");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.Warning", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime?>("DateAdded");
b.Property<bool>("Forgiven");
b.Property<string>("ForgivenBy");
b.Property<ulong>("GuildId");
b.Property<string>("Moderator");
b.Property<string>("Reason");
b.Property<ulong>("UserId");
b.HasKey("Id");
b.ToTable("Warnings");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("Count");
b.Property<DateTime?>("DateAdded");
b.Property<int?>("GuildConfigId");
b.Property<int>("Punishment");
b.Property<int>("Time");
b.HasKey("Id");
b.HasIndex("GuildConfigId");
b.ToTable("WarningPunishment");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b =>
{ {
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig")
@ -1240,6 +1377,27 @@ namespace NadekoBot.Migrations
.HasForeignKey("BotConfigId"); .HasForeignKey("BotConfigId");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
.WithMany("SlowmodeIgnoredRoles")
.HasForeignKey("GuildConfigId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
.WithMany("SlowmodeIgnoredUsers")
.HasForeignKey("GuildConfigId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.StartupCommand", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
.WithMany("StartupCommands")
.HasForeignKey("BotConfigId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b =>
{ {
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
@ -1285,6 +1443,13 @@ namespace NadekoBot.Migrations
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade); .OnDelete(DeleteBehavior.Cascade);
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
.WithMany("WarnPunishments")
.HasForeignKey("GuildConfigId");
});
} }
} }
} }

View File

@ -32,7 +32,7 @@ namespace NadekoBot.Modules.Administration
} }
private static Task DelMsgOnCmd_Handler(SocketUserMessage msg, CommandInfo cmd) private static Task DelMsgOnCmd_Handler(IUserMessage msg, CommandInfo cmd)
{ {
var _ = Task.Run(async () => var _ = Task.Run(async () =>
{ {
@ -218,101 +218,6 @@ namespace NadekoBot.Modules.Administration
} }
} }
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.BanMembers)]
[RequireBotPermission(GuildPermission.BanMembers)]
public async Task Ban(IGuildUser user, [Remainder] string msg = null)
{
if (Context.User.Id != user.Guild.OwnerId && (user.GetRoles().Select(r => r.Position).Max() >= ((IGuildUser)Context.User).GetRoles().Select(r => r.Position).Max()))
{
await ReplyErrorLocalized("hierarchy").ConfigureAwait(false);
return;
}
if (!string.IsNullOrWhiteSpace(msg))
{
try
{
await user.SendErrorAsync(GetText("bandm", Format.Bold(Context.Guild.Name), msg));
}
catch
{
// ignored
}
}
await Context.Guild.AddBanAsync(user, 7).ConfigureAwait(false);
await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithTitle("⛔️ " + GetText("banned_user"))
.AddField(efb => efb.WithName(GetText("username")).WithValue(user.ToString()).WithIsInline(true))
.AddField(efb => efb.WithName("ID").WithValue(user.Id.ToString()).WithIsInline(true)))
.ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.KickMembers)]
[RequireUserPermission(GuildPermission.ManageMessages)]
[RequireBotPermission(GuildPermission.BanMembers)]
public async Task Softban(IGuildUser user, [Remainder] string msg = null)
{
if (Context.User.Id != user.Guild.OwnerId && user.GetRoles().Select(r => r.Position).Max() >= ((IGuildUser)Context.User).GetRoles().Select(r => r.Position).Max())
{
await ReplyErrorLocalized("hierarchy").ConfigureAwait(false);
return;
}
if (!string.IsNullOrWhiteSpace(msg))
{
try
{
await user.SendErrorAsync(GetText("sbdm", Format.Bold(Context.Guild.Name), msg));
}
catch
{
// ignored
}
}
await Context.Guild.AddBanAsync(user, 7).ConfigureAwait(false);
try { await Context.Guild.RemoveBanAsync(user).ConfigureAwait(false); }
catch { await Context.Guild.RemoveBanAsync(user).ConfigureAwait(false); }
await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithTitle("☣ " + GetText("sb_user"))
.AddField(efb => efb.WithName(GetText("username")).WithValue(user.ToString()).WithIsInline(true))
.AddField(efb => efb.WithName("ID").WithValue(user.Id.ToString()).WithIsInline(true)))
.ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.KickMembers)]
[RequireBotPermission(GuildPermission.KickMembers)]
public async Task Kick(IGuildUser user, [Remainder] string msg = null)
{
if (Context.Message.Author.Id != user.Guild.OwnerId && user.GetRoles().Select(r => r.Position).Max() >= ((IGuildUser)Context.User).GetRoles().Select(r => r.Position).Max())
{
await ReplyErrorLocalized("hierarchy").ConfigureAwait(false);
return;
}
if (!string.IsNullOrWhiteSpace(msg))
{
try
{
await user.SendErrorAsync(GetText("kickdm", Format.Bold(Context.Guild.Name), msg));
}
catch { }
}
await user.KickAsync().ConfigureAwait(false);
await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithTitle(GetText("kicked_user"))
.AddField(efb => efb.WithName(GetText("username")).WithValue(user.ToString()).WithIsInline(true))
.AddField(efb => efb.WithName("ID").WithValue(user.Id.ToString()).WithIsInline(true)))
.ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.DeafenMembers)] [RequireUserPermission(GuildPermission.DeafenMembers)]

View File

@ -16,26 +16,29 @@ namespace NadekoBot.Modules.Administration
[Group] [Group]
public class LocalizationCommands : NadekoSubmodule public class LocalizationCommands : NadekoSubmodule
{ {
//Română, România
//Bahasa Indonesia, Indonesia
private ImmutableDictionary<string, string> supportedLocales { get; } = new Dictionary<string, string>() private ImmutableDictionary<string, string> supportedLocales { get; } = new Dictionary<string, string>()
{ {
{"zh-TW", "Chinese (Traditional), China" }, {"zh-TW", "繁體中文, 台灣" },
{"zh-CN", "Chinese (Simplified), China"}, {"zh-CN", "简体中文, 中华人民共和国"},
{"nl-NL", "Dutch, Netherlands"}, {"nl-NL", "Nederlands, Nederland"},
{"en-US", "English, United States"}, {"en-US", "English, United States"},
{"fr-FR", "French, France"}, {"fr-FR", "Français, France"},
{"de-DE", "German, Germany"}, {"de-DE", "Deutsch, Deutschland"},
{"he-IL", "Hebrew, Israel" }, {"he-IL", "עברית, ישראל"},
{"it-IT", "Italian, Italy" }, {"id-ID", "Bahasa Indonesia, Indonesia" },
//{"ja-JP", "Japanese, Japan"}, {"it-IT", "Italiano, Italia" },
{"ko-KR", "Korean, Korea" }, //{"ja-JP", "日本語, 日本"},
{"nb-NO", "Norwegian (bokmål), Norway"}, {"ko-KR", "한국어, 대한민국" },
{"pl-PL", "Polish, Poland" }, {"nb-NO", "Norsk, Norge"},
{"pt-BR", "Portuguese, Brazil"}, {"pl-PL", "Polski, Polska" },
{"ru-RU", "Russian, Russia"}, {"pt-BR", "Português Brasileiro, Brasil"},
{"sr-Cyrl-RS", "Serbian, Serbia - Cyrillic"}, {"ru-RU", "Русский, Россия"},
{"es-ES", "Spanish, Spain"}, {"sr-Cyrl-RS", "Српски, Србија"},
{"sv-SE", "Swedish, Sweden"}, {"es-ES", "Español, España"},
{"tr-TR", "Turkish, Turkey" } {"sv-SE", "Svenska, Sverige"},
{"tr-TR", "Türkçe, Türkiye"}
}.ToImmutableDictionary(); }.ToImmutableDictionary();
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]

View File

@ -307,6 +307,9 @@ namespace NadekoBot.Modules.Administration
punishment = "🔇 " + logChannel.Guild.GetLogText("muted_pl").ToUpperInvariant(); punishment = "🔇 " + logChannel.Guild.GetLogText("muted_pl").ToUpperInvariant();
break; break;
case PunishmentAction.Kick: case PunishmentAction.Kick:
punishment = "👢 " + logChannel.Guild.GetLogText("kicked_pl").ToUpperInvariant();
break;
case PunishmentAction.Softban:
punishment = "☣ " + logChannel.Guild.GetLogText("soft_banned_pl").ToUpperInvariant(); punishment = "☣ " + logChannel.Guild.GetLogText("soft_banned_pl").ToUpperInvariant();
break; break;
case PunishmentAction.Ban: case PunishmentAction.Ban:

View File

@ -188,6 +188,13 @@ namespace NadekoBot.Modules.Administration
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
{
await gu.KickAsync().ConfigureAwait(false);
}
catch (Exception ex) { _log.Warn(ex, "I can't apply punishement"); }
break;
case PunishmentAction.Softban:
try try
{ {
await gu.Guild.AddBanAsync(gu, 7).ConfigureAwait(false); await gu.Guild.AddBanAsync(gu, 7).ConfigureAwait(false);

View File

@ -1,10 +1,16 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket;
using Microsoft.EntityFrameworkCore;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
using NLog; using NLog;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -13,9 +19,12 @@ namespace NadekoBot.Modules.Administration
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class RatelimitCommand : NadekoSubmodule public class RatelimitCommands : NadekoSubmodule
{ {
public static ConcurrentDictionary<ulong, Ratelimiter> RatelimitingChannels = new ConcurrentDictionary<ulong, Ratelimiter>(); public static ConcurrentDictionary<ulong, Ratelimiter> RatelimitingChannels = new ConcurrentDictionary<ulong, Ratelimiter>();
public static ConcurrentDictionary<ulong, HashSet<ulong>> IgnoredRoles = new ConcurrentDictionary<ulong, HashSet<ulong>>();
public static ConcurrentDictionary<ulong, HashSet<ulong>> IgnoredUsers = new ConcurrentDictionary<ulong, HashSet<ulong>>();
private new static readonly Logger _log; private new static readonly Logger _log;
public class Ratelimiter public class Ratelimiter
@ -35,10 +44,17 @@ namespace NadekoBot.Modules.Administration
public ConcurrentDictionary<ulong, RatelimitedUser> Users { get; set; } = new ConcurrentDictionary<ulong, RatelimitedUser>(); public ConcurrentDictionary<ulong, RatelimitedUser> Users { get; set; } = new ConcurrentDictionary<ulong, RatelimitedUser>();
public bool CheckUserRatelimit(ulong id) public bool CheckUserRatelimit(ulong id, ulong guildId, SocketGuildUser optUser)
{ {
HashSet<ulong> ignoreUsers;
HashSet<ulong> ignoreRoles;
if ((IgnoredUsers.TryGetValue(guildId, out ignoreUsers) && ignoreUsers.Contains(id)) ||
(optUser != null && IgnoredRoles.TryGetValue(guildId, out ignoreRoles) && optUser.RoleIds.Any(x => ignoreRoles.Contains(x))))
return false;
var usr = Users.GetOrAdd(id, (key) => new RatelimitedUser() { UserId = id }); var usr = Users.GetOrAdd(id, (key) => new RatelimitedUser() { UserId = id });
if (usr.MessageCount == MaxMessages) if (usr.MessageCount >= MaxMessages)
{ {
return true; return true;
} }
@ -56,16 +72,26 @@ namespace NadekoBot.Modules.Administration
} }
} }
static RatelimitCommand() static RatelimitCommands()
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
IgnoredRoles = new ConcurrentDictionary<ulong, HashSet<ulong>>(
NadekoBot.AllGuildConfigs
.ToDictionary(x => x.GuildId,
x => new HashSet<ulong>(x.SlowmodeIgnoredRoles.Select(y => y.RoleId))));
IgnoredUsers = new ConcurrentDictionary<ulong, HashSet<ulong>>(
NadekoBot.AllGuildConfigs
.ToDictionary(x => x.GuildId,
x => new HashSet<ulong>(x.SlowmodeIgnoredUsers.Select(y => y.UserId))));
NadekoBot.Client.MessageReceived += async (umsg) => NadekoBot.Client.MessageReceived += async (umsg) =>
{ {
try try
{ {
var usrMsg = umsg as IUserMessage; var usrMsg = umsg as SocketUserMessage;
var channel = usrMsg?.Channel as ITextChannel; var channel = usrMsg?.Channel as SocketTextChannel;
if (channel == null || usrMsg.IsAuthor()) if (channel == null || usrMsg.IsAuthor())
return; return;
@ -73,7 +99,7 @@ namespace NadekoBot.Modules.Administration
if (!RatelimitingChannels.TryGetValue(channel.Id, out limiter)) if (!RatelimitingChannels.TryGetValue(channel.Id, out limiter))
return; return;
if (limiter.CheckUserRatelimit(usrMsg.Author.Id)) if (limiter.CheckUserRatelimit(usrMsg.Author.Id, channel.Guild.Id, usrMsg.Author as SocketGuildUser))
await usrMsg.DeleteAsync(); await usrMsg.DeleteAsync();
} }
catch (Exception ex) { _log.Warn(ex); } catch (Exception ex) { _log.Warn(ex); }
@ -118,6 +144,70 @@ namespace NadekoBot.Modules.Administration
.ConfigureAwait(false); .ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageMessages)]
[Priority(1)]
public async Task SlowmodeWhitelist(IUser user)
{
var siu = new SlowmodeIgnoredUser
{
UserId = user.Id
};
HashSet<SlowmodeIgnoredUser> usrs;
bool removed;
using (var uow = DbHandler.UnitOfWork())
{
usrs = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.SlowmodeIgnoredUsers))
.SlowmodeIgnoredUsers;
if (!(removed = usrs.Remove(siu)))
usrs.Add(siu);
await uow.CompleteAsync().ConfigureAwait(false);
}
IgnoredUsers.AddOrUpdate(Context.Guild.Id, new HashSet<ulong>(usrs.Select(x => x.UserId)), (key, old) => new HashSet<ulong>(usrs.Select(x => x.UserId)));
if(removed)
await ReplyConfirmLocalized("slowmodewl_user_stop", Format.Bold(user.ToString())).ConfigureAwait(false);
else
await ReplyConfirmLocalized("slowmodewl_user_start", Format.Bold(user.ToString())).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageMessages)]
[Priority(0)]
public async Task SlowmodeWhitelist(IRole role)
{
var sir = new SlowmodeIgnoredRole
{
RoleId = role.Id
};
HashSet<SlowmodeIgnoredRole> roles;
bool removed;
using (var uow = DbHandler.UnitOfWork())
{
roles = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.SlowmodeIgnoredRoles))
.SlowmodeIgnoredRoles;
if (!(removed = roles.Remove(sir)))
roles.Add(sir);
await uow.CompleteAsync().ConfigureAwait(false);
}
IgnoredRoles.AddOrUpdate(Context.Guild.Id, new HashSet<ulong>(roles.Select(x => x.RoleId)), (key, old) => new HashSet<ulong>(roles.Select(x => x.RoleId)));
if (removed)
await ReplyConfirmLocalized("slowmodewl_role_stop", Format.Bold(role.ToString())).ConfigureAwait(false);
else
await ReplyConfirmLocalized("slowmodewl_role_start", Format.Bold(role.ToString())).ConfigureAwait(false);
}
} }
} }
} }

View File

@ -10,6 +10,8 @@ using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.WebSocket; using Discord.WebSocket;
using NadekoBot.Services; using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
using Microsoft.EntityFrameworkCore;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
{ {
@ -31,6 +33,166 @@ namespace NadekoBot.Modules.Administration
_forwardDMs = config.ForwardMessages; _forwardDMs = config.ForwardMessages;
_forwardDMsToAllOwners = config.ForwardToAllOwners; _forwardDMsToAllOwners = config.ForwardToAllOwners;
} }
var _ = Task.Run(async () =>
{
while(!NadekoBot.Ready)
await Task.Delay(1000);
foreach (var cmd in NadekoBot.BotConfig.StartupCommands)
{
if (cmd.GuildId != null)
{
var guild = NadekoBot.Client.GetGuild(cmd.GuildId.Value);
var channel = guild?.GetChannel(cmd.ChannelId) as SocketTextChannel;
if (channel == null)
continue;
try
{
IUserMessage msg = await channel.SendMessageAsync(cmd.CommandText).ConfigureAwait(false);
msg = (IUserMessage)await channel.GetMessageAsync(msg.Id).ConfigureAwait(false);
await NadekoBot.CommandHandler.TryRunCommand(guild, channel, msg).ConfigureAwait(false);
//msg.DeleteAfter(5);
}
catch { }
}
await Task.Delay(400).ConfigureAwait(false);
}
});
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[OwnerOnly]
public async Task StartupCommandAdd([Remainder] string cmdText)
{
var guser = ((IGuildUser)Context.User);
var cmd = new StartupCommand()
{
CommandText = cmdText,
ChannelId = Context.Channel.Id,
ChannelName = Context.Channel.Name,
GuildId = Context.Guild?.Id,
GuildName = Context.Guild?.Name,
VoiceChannelId = guser.VoiceChannel?.Id,
VoiceChannelName = guser.VoiceChannel?.Name,
};
using (var uow = DbHandler.UnitOfWork())
{
uow.BotConfig
.GetOrCreate(set => set.Include(x => x.StartupCommands))
.StartupCommands.Add(cmd);
await uow.CompleteAsync().ConfigureAwait(false);
}
await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithTitle(GetText("scadd"))
.AddField(efb => efb.WithName(GetText("server"))
.WithValue(cmd.GuildId == null ? $"-" : $"{cmd.GuildName}/{cmd.GuildId}").WithIsInline(true))
.AddField(efb => efb.WithName(GetText("channel"))
.WithValue($"{cmd.ChannelName}/{cmd.ChannelId}").WithIsInline(true))
.AddField(efb => efb.WithName(GetText("command_text"))
.WithValue(cmdText).WithIsInline(false)));
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[OwnerOnly]
public async Task StartupCommands(int page = 1)
{
if (page < 1)
return;
page -= 1;
IEnumerable<StartupCommand> scmds;
using (var uow = DbHandler.UnitOfWork())
{
scmds = uow.BotConfig
.GetOrCreate(set => set.Include(x => x.StartupCommands))
.StartupCommands
.OrderBy(x => x.Id)
.ToArray();
}
scmds = scmds.Skip(page * 5).Take(5);
if (!scmds.Any())
{
await ReplyErrorLocalized("startcmdlist_none").ConfigureAwait(false);
}
else
{
await Context.Channel.SendConfirmAsync("", string.Join("\n--\n", scmds.Select(x =>
{
string str = Format.Code(GetText("server")) + ": " + (x.GuildId == null ? "-" : x.GuildName + "/" + x.GuildId);
str += $@"
{Format.Code(GetText("channel"))}: {x.ChannelName}/{x.ChannelId}
{Format.Code(GetText("command_text"))}: {x.CommandText}";
return str;
})),footer: GetText("page", page + 1))
.ConfigureAwait(false);
}
}
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task Wait(int miliseconds)
{
if (miliseconds <= 0)
return;
Context.Message.DeleteAfter(0);
try
{
var msg = await Context.Channel.SendConfirmAsync($"⏲ {miliseconds}ms")
.ConfigureAwait(false);
msg.DeleteAfter(miliseconds / 1000);
}
catch { }
await Task.Delay(miliseconds);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[OwnerOnly]
public async Task StartupCommandRemove([Remainder] string cmdText)
{
StartupCommand cmd;
using (var uow = DbHandler.UnitOfWork())
{
var cmds = uow.BotConfig
.GetOrCreate(set => set.Include(x => x.StartupCommands))
.StartupCommands;
cmd = cmds
.FirstOrDefault(x => x.CommandText.ToLowerInvariant() == cmdText.ToLowerInvariant());
if (cmd != null)
{
cmds.Remove(cmd);
await uow.CompleteAsync().ConfigureAwait(false);
}
}
if(cmd == null)
await ReplyErrorLocalized("scrm_fail").ConfigureAwait(false);
else
await ReplyConfirmLocalized("scrm").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[OwnerOnly]
public async Task StartupCommandsClear()
{
using (var uow = DbHandler.UnitOfWork())
{
uow.BotConfig
.GetOrCreate(set => set.Include(x => x.StartupCommands))
.StartupCommands
.Clear();
uow.Complete();
}
await ReplyConfirmLocalized("startcmds_cleared").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
@ -68,7 +230,7 @@ namespace NadekoBot.Modules.Administration
} }
public static async Task HandleDmForwarding(SocketMessage msg, List<IDMChannel> ownerChannels) public static async Task HandleDmForwarding(IUserMessage msg, List<IDMChannel> ownerChannels)
{ {
if (_forwardDMs && ownerChannels.Any()) if (_forwardDMs && ownerChannels.Any())
{ {
@ -157,7 +319,7 @@ namespace NadekoBot.Modules.Administration
else else
{ {
await server.DeleteAsync().ConfigureAwait(false); await server.DeleteAsync().ConfigureAwait(false);
await ReplyConfirmLocalized("deleted_server",Format.Bold(server.Name)).ConfigureAwait(false); await ReplyConfirmLocalized("deleted_server", Format.Bold(server.Name)).ConfigureAwait(false);
} }
} }

View File

@ -0,0 +1,436 @@
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.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Administration
{
public partial class Administration
{
[Group]
public class UserPunishCommands : NadekoSubmodule
{
private async Task<PunishmentAction?> InternalWarn(IGuild guild, ulong userId, string modName, string reason)
{
if (string.IsNullOrWhiteSpace(reason))
reason = "-";
var guildId = guild.Id;
var warn = new Warning()
{
UserId = userId,
GuildId = guildId,
Forgiven = false,
Reason = reason,
Moderator = modName,
};
int warnings = 1;
List<WarningPunishment> ps;
using (var uow = DbHandler.UnitOfWork())
{
ps = uow.GuildConfigs.For(guildId, set => set.Include(x => x.WarnPunishments))
.WarnPunishments;
warnings += uow.Warnings
.For(guildId, userId)
.Where(w => !w.Forgiven && w.UserId == userId)
.Count();
uow.Warnings.Add(warn);
uow.Complete();
}
var p = ps.FirstOrDefault(x => x.Count == warnings);
if (p != null)
{
var user = await guild.GetUserAsync(userId);
if (user == null)
return null;
switch (p.Punishment)
{
case PunishmentAction.Mute:
if (p.Time == 0)
await MuteCommands.MuteUser(user).ConfigureAwait(false);
else
await MuteCommands.TimedMute(user, TimeSpan.FromMinutes(p.Time)).ConfigureAwait(false);
break;
case PunishmentAction.Kick:
await user.KickAsync().ConfigureAwait(false);
break;
case PunishmentAction.Ban:
await guild.AddBanAsync(user).ConfigureAwait(false);
break;
case PunishmentAction.Softban:
await guild.AddBanAsync(user).ConfigureAwait(false);
try
{
await guild.RemoveBanAsync(user).ConfigureAwait(false);
}
catch
{
await guild.RemoveBanAsync(user).ConfigureAwait(false);
}
break;
default:
break;
}
return p.Punishment;
}
return null;
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.BanMembers)]
public async Task Warn(IGuildUser user, [Remainder] string reason = null)
{
try
{
await (await user.CreateDMChannelAsync()).EmbedAsync(new EmbedBuilder().WithErrorColor()
.WithDescription(GetText("warned_on", Context.Guild.ToString()))
.AddField(efb => efb.WithName(GetText("moderator")).WithValue(Context.User.ToString()))
.AddField(efb => efb.WithName(GetText("reason")).WithValue(reason ?? "-")))
.ConfigureAwait(false);
}
catch { }
var punishment = await InternalWarn(Context.Guild, user.Id, Context.User.ToString(), reason).ConfigureAwait(false);
if (punishment == null)
{
await ReplyConfirmLocalized("user_warned", Format.Bold(user.ToString())).ConfigureAwait(false);
}
else
{
await ReplyConfirmLocalized("user_warned_and_punished", Format.Bold(user.ToString()), Format.Bold(punishment.ToString())).ConfigureAwait(false);
}
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.BanMembers)]
public Task Warnlog(int page, IGuildUser user)
=> Warnlog(page, user.Id);
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.BanMembers)]
public Task Warnlog(IGuildUser user)
=> Warnlog(user.Id);
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.BanMembers)]
public Task Warnlog(int page, ulong userId)
=> InternalWarnlog(userId, page - 1);
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.BanMembers)]
public Task Warnlog(ulong userId)
=> InternalWarnlog(userId, 0);
private async Task InternalWarnlog(ulong userId, int page)
{
if (page < 0)
return;
Warning[] warnings;
using (var uow = DbHandler.UnitOfWork())
{
warnings = uow.Warnings.For(Context.Guild.Id, userId);
}
warnings = warnings.Skip(page * 9)
.Take(9)
.ToArray();
var embed = new EmbedBuilder().WithOkColor()
.WithTitle(GetText("warnlog_for", (Context.Guild as SocketGuild)?.GetUser(userId)?.ToString() ?? userId.ToString()))
.WithFooter(efb => efb.WithText(GetText("page", page + 1)));
if (!warnings.Any())
{
embed.WithDescription(GetText("warnings_none"));
}
else
{
foreach (var w in warnings)
{
var name = GetText("warned_on_by", w.DateAdded.Value.ToString("dd.MM.yyy"), w.DateAdded.Value.ToString("HH:mm"), w.Moderator);
if (w.Forgiven)
name = Format.Strikethrough(name) + " " + GetText("warn_cleared_by", w.ForgivenBy);
embed.AddField(x => x
.WithName(name)
.WithValue(w.Reason));
}
}
await Context.Channel.EmbedAsync(embed);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.BanMembers)]
public Task Warnclear(IGuildUser user)
=> Warnclear(user.Id);
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.BanMembers)]
public async Task Warnclear(ulong userId)
{
using (var uow = DbHandler.UnitOfWork())
{
await uow.Warnings.ForgiveAll(Context.Guild.Id, userId, Context.User.ToString()).ConfigureAwait(false);
uow.Complete();
}
await ReplyConfirmLocalized("warnings_cleared",
Format.Bold((Context.Guild as SocketGuild)?.GetUser(userId)?.ToString() ?? userId.ToString())).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.BanMembers)]
public async Task WarnPunish(int number, PunishmentAction punish, int time = 0)
{
if (punish != PunishmentAction.Mute && time != 0)
return;
if (number <= 0)
return;
using (var uow = DbHandler.UnitOfWork())
{
var ps = uow.GuildConfigs.For(Context.Guild.Id).WarnPunishments;
var p = ps.FirstOrDefault(x => x.Count == number);
if (p == null)
{
ps.Add(new WarningPunishment()
{
Count = number,
Punishment = punish,
Time = time,
});
}
else
{
p.Count = number;
p.Punishment = punish;
p.Time = time;
uow._context.Update(p);
}
uow.Complete();
}
await ReplyConfirmLocalized("warn_punish_set",
Format.Bold(punish.ToString()),
Format.Bold(number.ToString())).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.BanMembers)]
public async Task WarnPunish(int number)
{
if (number <= 0)
return;
using (var uow = DbHandler.UnitOfWork())
{
var ps = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.WarnPunishments)).WarnPunishments;
var p = ps.FirstOrDefault(x => x.Count == number);
if (p != null)
{
uow._context.Remove(p);
uow.Complete();
}
}
await ReplyConfirmLocalized("warn_punish_rem",
Format.Bold(number.ToString())).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task WarnPunishList()
{
WarningPunishment[] ps;
using (var uow = DbHandler.UnitOfWork())
{
ps = uow.GuildConfigs.For(Context.Guild.Id, gc => gc.Include(x => x.WarnPunishments))
.WarnPunishments
.OrderBy(x => x.Count)
.ToArray();
}
string list;
if (ps.Any())
{
list = string.Join("\n", ps.Select(x => $"{x.Count} -> {x.Punishment}"));
}
else
{
list = GetText("warnpl_none");
}
await Context.Channel.SendConfirmAsync(
GetText("warn_punish_list"),
list).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.BanMembers)]
[RequireBotPermission(GuildPermission.BanMembers)]
public async Task Ban(IGuildUser user, [Remainder] string msg = null)
{
if (Context.User.Id != user.Guild.OwnerId && (user.GetRoles().Select(r => r.Position).Max() >= ((IGuildUser)Context.User).GetRoles().Select(r => r.Position).Max()))
{
await ReplyErrorLocalized("hierarchy").ConfigureAwait(false);
return;
}
if (!string.IsNullOrWhiteSpace(msg))
{
try
{
await user.SendErrorAsync(GetText("bandm", Format.Bold(Context.Guild.Name), msg));
}
catch
{
// ignored
}
}
await Context.Guild.AddBanAsync(user, 7).ConfigureAwait(false);
await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithTitle("⛔️ " + GetText("banned_user"))
.AddField(efb => efb.WithName(GetText("username")).WithValue(user.ToString()).WithIsInline(true))
.AddField(efb => efb.WithName("ID").WithValue(user.Id.ToString()).WithIsInline(true)))
.ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.BanMembers)]
[RequireBotPermission(GuildPermission.BanMembers)]
public async Task Unban([Remainder]string user)
{
var bans = await Context.Guild.GetBansAsync();
var bun = bans.FirstOrDefault(x => x.User.ToString().ToLowerInvariant() == user.ToLowerInvariant());
if (bun == null)
{
await ReplyErrorLocalized("user_not_found").ConfigureAwait(false);
return;
}
await UnbanInternal(bun.User).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.BanMembers)]
[RequireBotPermission(GuildPermission.BanMembers)]
public async Task Unban(ulong userId)
{
var bans = await Context.Guild.GetBansAsync();
var bun = bans.FirstOrDefault(x => x.User.Id == userId);
if (bun == null)
{
await ReplyErrorLocalized("user_not_found").ConfigureAwait(false);
return;
}
await UnbanInternal(bun.User).ConfigureAwait(false);
}
private async Task UnbanInternal(IUser user)
{
await Context.Guild.RemoveBanAsync(user).ConfigureAwait(false);
await ReplyConfirmLocalized("unbanned_user", Format.Bold(user.ToString())).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.KickMembers)]
[RequireUserPermission(GuildPermission.ManageMessages)]
[RequireBotPermission(GuildPermission.BanMembers)]
public async Task Softban(IGuildUser user, [Remainder] string msg = null)
{
if (Context.User.Id != user.Guild.OwnerId && user.GetRoles().Select(r => r.Position).Max() >= ((IGuildUser)Context.User).GetRoles().Select(r => r.Position).Max())
{
await ReplyErrorLocalized("hierarchy").ConfigureAwait(false);
return;
}
if (!string.IsNullOrWhiteSpace(msg))
{
try
{
await user.SendErrorAsync(GetText("sbdm", Format.Bold(Context.Guild.Name), msg));
}
catch
{
// ignored
}
}
await Context.Guild.AddBanAsync(user, 7).ConfigureAwait(false);
try { await Context.Guild.RemoveBanAsync(user).ConfigureAwait(false); }
catch { await Context.Guild.RemoveBanAsync(user).ConfigureAwait(false); }
await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithTitle("☣ " + GetText("sb_user"))
.AddField(efb => efb.WithName(GetText("username")).WithValue(user.ToString()).WithIsInline(true))
.AddField(efb => efb.WithName("ID").WithValue(user.Id.ToString()).WithIsInline(true)))
.ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.KickMembers)]
[RequireBotPermission(GuildPermission.KickMembers)]
public async Task Kick(IGuildUser user, [Remainder] string msg = null)
{
if (Context.Message.Author.Id != user.Guild.OwnerId && user.GetRoles().Select(r => r.Position).Max() >= ((IGuildUser)Context.User).GetRoles().Select(r => r.Position).Max())
{
await ReplyErrorLocalized("hierarchy").ConfigureAwait(false);
return;
}
if (!string.IsNullOrWhiteSpace(msg))
{
try
{
await user.SendErrorAsync(GetText("kickdm", Format.Bold(Context.Guild.Name), msg));
}
catch { }
}
await user.KickAsync().ConfigureAwait(false);
await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithTitle(GetText("kicked_user"))
.AddField(efb => efb.WithName(GetText("username")).WithValue(user.ToString()).WithIsInline(true))
.AddField(efb => efb.WithName("ID").WithValue(user.Id.ToString()).WithIsInline(true)))
.ConfigureAwait(false);
}
}
}
}

View File

@ -59,7 +59,7 @@ namespace NadekoBot.Modules.CustomReactions
public void ClearStats() => ReactionStats.Clear(); public void ClearStats() => ReactionStats.Clear();
public static CustomReaction TryGetCustomReaction(SocketUserMessage umsg) public static CustomReaction TryGetCustomReaction(IUserMessage umsg)
{ {
var channel = umsg.Channel as SocketTextChannel; var channel = umsg.Channel as SocketTextChannel;
if (channel == null) if (channel == null)

View File

@ -246,6 +246,9 @@ namespace NadekoBot.Modules.Gambling
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task Leaderboard(int page = 1) public async Task Leaderboard(int page = 1)
{ {
if (page < 1)
return;
List<Currency> richest; List<Currency> richest;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {

View File

@ -40,7 +40,7 @@ namespace NadekoBot.Modules.Games
_log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s"); _log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
} }
public static async Task<bool> TryAsk(SocketUserMessage msg) public static async Task<bool> TryAsk(IUserMessage msg)
{ {
var channel = msg.Channel as ITextChannel; var channel = msg.Channel as ITextChannel;

View File

@ -15,7 +15,7 @@ namespace NadekoBot.Modules.Games.Hangman
{ {
public class HangmanTermPool public class HangmanTermPool
{ {
const string termsPath = "data/hangman.json"; const string termsPath = "data/hangman2.json";
public static IReadOnlyDictionary<string, HangmanObject[]> data { get; } public static IReadOnlyDictionary<string, HangmanObject[]> data { get; }
static HangmanTermPool() static HangmanTermPool()
{ {

View File

@ -151,7 +151,7 @@ namespace NadekoBot.Modules.Games
{ {
public static List<TypingArticle> TypingArticles { get; } = new List<TypingArticle>(); public static List<TypingArticle> TypingArticles { get; } = new List<TypingArticle>();
private const string _typingArticlesPath = "data/typing_articles.json"; private const string _typingArticlesPath = "data/typing_articles2.json";
static SpeedTypingCommands() static SpeedTypingCommands()
{ {

View File

@ -55,8 +55,14 @@ namespace NadekoBot.Modules.Help
await ReplyErrorLocalized("module_not_found").ConfigureAwait(false); await ReplyErrorLocalized("module_not_found").ConfigureAwait(false);
return; return;
} }
var j = 0;
var groups = cmdsArray.GroupBy(x => j++ / 48).ToArray();
for (int i = 0; i < groups.Count(); i++)
{
await channel.SendTableAsync(i == 0 ? $"📃 **{GetText("list_of_commands")}**\n" : "", groups.ElementAt(i), el => $"{el.Aliases.First(),-15} {"[" + el.Aliases.Skip(1).FirstOrDefault() + "]",-8}").ConfigureAwait(false);
}
await channel.SendTableAsync($"📃 **{GetText("list_of_commands")}**\n", cmdsArray, el => $"{el.Aliases.First(),-15} {"["+el.Aliases.Skip(1).FirstOrDefault()+"]",-8}").ConfigureAwait(false);
await ConfirmLocalized("commands_instr", Prefix).ConfigureAwait(false); await ConfirmLocalized("commands_instr", Prefix).ConfigureAwait(false);
} }

View File

@ -69,7 +69,7 @@ namespace NadekoBot.Modules
LogManager.GetCurrentClassLogger().Warn(lowerModuleTypeName + "_" + key + " key is missing from " + cultureInfo + " response strings. PLEASE REPORT THIS."); LogManager.GetCurrentClassLogger().Warn(lowerModuleTypeName + "_" + key + " key is missing from " + cultureInfo + " response strings. PLEASE REPORT THIS.");
text = NadekoBot.ResponsesResourceManager.GetString(lowerModuleTypeName + "_" + key, _usCultureInfo) ?? $"Error: dkey {lowerModuleTypeName + "_" + key} not found!"; text = NadekoBot.ResponsesResourceManager.GetString(lowerModuleTypeName + "_" + key, _usCultureInfo) ?? $"Error: dkey {lowerModuleTypeName + "_" + key} not found!";
if (string.IsNullOrWhiteSpace(text)) if (string.IsNullOrWhiteSpace(text))
return "I can't tell you is the command executed, because there was an error printing out the response. Key '" + return "I can't tell you if the command is executed, because there was an error printing out the response. Key '" +
lowerModuleTypeName + "_" + key + "' " + "is missing from resources. Please report this."; lowerModuleTypeName + "_" + key + "' " + "is missing from resources. Please report this.";
} }
return text; return text;
@ -84,7 +84,7 @@ namespace NadekoBot.Modules
} }
catch (FormatException) catch (FormatException)
{ {
return "I cant tell if you command is executed, because there was an error printing out the response. Key '" + return "I can't tell you if the command is executed, because there was an error printing out the response. Key '" +
lowerModuleTypeName + "_" + key + "' " + "is not properly formatted. Please report this."; lowerModuleTypeName + "_" + key + "' " + "is not properly formatted. Please report this.";
} }
} }

View File

@ -3,76 +3,196 @@ using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.Commands; using Discord.Commands;
using Discord;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Modules.Utility.Models; using NadekoBot.Modules.Utility.Models;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Threading;
using System;
using System.Collections.Immutable;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
using NadekoBot.Extensions;
using Discord;
namespace NadekoBot.Modules.Utility namespace NadekoBot.Modules.Utility
{ {
public partial class Utility public partial class Utility
{ {
//[Group] [Group]
//public class PatreonCommands : NadekoSubmodule public class PatreonCommands : NadekoSubmodule
//{ {
// [NadekoCommand, Usage, Description, Aliases] private static readonly PatreonThingy patreon;
// [RequireContext(ContextType.Guild)]
// public async Task ClaimPatreonRewards([Remainder] string arg)
// {
// var pledges = await GetPledges2();
// }
// private static async Task<Pledge[]> GetPledges() static PatreonCommands()
// { {
// var pledges = new List<Pledge>(); patreon = PatreonThingy.Instance;
// using (var http = new HttpClient()) }
// { [NadekoCommand, Usage, Description, Aliases]
// http.DefaultRequestHeaders.Clear(); public async Task ClaimPatreonRewards()
// http.DefaultRequestHeaders.Add("Authorization", "Bearer " + NadekoBot.Credentials.PatreonAccessToken); {
// var data = new PatreonData() if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.PatreonAccessToken))
// { return;
// Links = new Links() if (DateTime.UtcNow.Day < 5)
// { {
// Next = "https://api.patreon.com/oauth2/api/campaigns/334038/pledges" await ReplyErrorLocalized("clpa_too_early").ConfigureAwait(false);
// } return;
// }; }
// do int amount = 0;
// { try
// var res = {
// await http.GetStringAsync(data.Links.Next) amount = await patreon.ClaimReward(Context.User.Id).ConfigureAwait(false);
// .ConfigureAwait(false); }
// data = JsonConvert.DeserializeObject<PatreonData>(res); catch (Exception ex)
// pledges.AddRange(data.Data); {
// } while (!string.IsNullOrWhiteSpace(data.Links.Next)); _log.Warn(ex);
// } }
// return pledges.Where(x => string.IsNullOrWhiteSpace(x.Attributes.declined_since)).ToArray();
// }
// private static async Task<Pledge[]> GetPledges2() if (amount > 0)
// { {
// var pledges = new List<Pledge>(); await ReplyConfirmLocalized("clpa_success", amount + NadekoBot.BotConfig.CurrencySign).ConfigureAwait(false);
// using (var http = new HttpClient()) return;
// { }
// http.DefaultRequestHeaders.Clear(); var helpcmd = Format.Code(NadekoBot.ModulePrefixes[typeof(Help.Help).Name] + "donate");
// http.DefaultRequestHeaders.Add("Authorization", "Bearer " + NadekoBot.Credentials.PatreonAccessToken); await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
// var data = new PatreonData() .WithDescription(GetText("clpa_fail"))
// { .AddField(efb => efb.WithName(GetText("clpa_fail_already_title")).WithValue(GetText("clpa_fail_already")))
// Links = new Links() .AddField(efb => efb.WithName(GetText("clpa_fail_wait_title")).WithValue(GetText("clpa_fail_wait")))
// { .AddField(efb => efb.WithName(GetText("clpa_fail_conn_title")).WithValue(GetText("clpa_fail_conn")))
// Next = "https://api.patreon.com/oauth2/api/current_user/campaigns?include=pledges" .AddField(efb => efb.WithName(GetText("clpa_fail_sup_title")).WithValue(GetText("clpa_fail_sup", helpcmd))))
// } .ConfigureAwait(false);
// }; }
// do }
// {
// var res = public class PatreonThingy
// await http.GetStringAsync(data.Links.Next) {
// .ConfigureAwait(false); public static PatreonThingy _instance = new PatreonThingy();
// data = JsonConvert.DeserializeObject<PatreonData>(res); public static PatreonThingy Instance => _instance;
// pledges.AddRange(data.Data);
// } while (!string.IsNullOrWhiteSpace(data.Links.Next)); private readonly SemaphoreSlim getPledgesLocker = new SemaphoreSlim(1, 1);
// }
// return pledges.Where(x => string.IsNullOrWhiteSpace(x.Attributes.declined_since)).ToArray(); public ImmutableArray<PatreonUserAndReward> Pledges { get; private set; }
// }
//} private readonly Timer update;
private readonly SemaphoreSlim claimLockJustInCase = new SemaphoreSlim(1, 1);
private PatreonThingy()
{
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.PatreonAccessToken))
return;
update = new Timer(async (_) => await LoadPledges(), null, TimeSpan.Zero, TimeSpan.FromHours(3));
}
public async Task LoadPledges()
{
await getPledgesLocker.WaitAsync(1000).ConfigureAwait(false);
try
{
var rewards = new List<PatreonPledge>();
var users = new List<PatreonUser>();
using (var http = new HttpClient())
{
http.DefaultRequestHeaders.Clear();
http.DefaultRequestHeaders.Add("Authorization", "Bearer " + NadekoBot.Credentials.PatreonAccessToken);
var data = new PatreonData()
{
Links = new PatreonDataLinks()
{
next = "https://api.patreon.com/oauth2/api/campaigns/334038/pledges"
}
};
do
{
var res = await http.GetStringAsync(data.Links.next)
.ConfigureAwait(false);
data = JsonConvert.DeserializeObject<PatreonData>(res);
var pledgers = data.Data.Where(x => x["type"].ToString() == "pledge");
rewards.AddRange(pledgers.Select(x => JsonConvert.DeserializeObject<PatreonPledge>(x.ToString()))
.Where(x => x.attributes.declined_since == null));
users.AddRange(data.Included
.Where(x => x["type"].ToString() == "user")
.Select(x => JsonConvert.DeserializeObject<PatreonUser>(x.ToString())));
} while (!string.IsNullOrWhiteSpace(data.Links.next));
}
Pledges = rewards.Join(users, (r) => r.relationships?.patron?.data?.id, (u) => u.id, (x, y) => new PatreonUserAndReward()
{
User = y,
Reward = x,
}).ToImmutableArray();
}
finally
{
var _ = Task.Run(async () =>
{
await Task.Delay(TimeSpan.FromMinutes(5)).ConfigureAwait(false);
getPledgesLocker.Release();
});
}
}
public async Task<int> ClaimReward(ulong userId)
{
await claimLockJustInCase.WaitAsync();
var now = DateTime.UtcNow;
try
{
var data = Pledges.FirstOrDefault(x => x.User.attributes?.social_connections?.discord?.user_id == userId.ToString());
if (data == null)
return 0;
var amount = data.Reward.attributes.amount_cents;
using (var uow = DbHandler.UnitOfWork())
{
var users = uow._context.Set<RewardedUser>();
var usr = users.FirstOrDefault(x => x.UserId == userId);
if (usr == null)
{
users.Add(new RewardedUser()
{
UserId = userId,
LastReward = now,
AmountRewardedThisMonth = amount,
});
await CurrencyHandler.AddCurrencyAsync(userId, "Patreon reward - new", amount, uow).ConfigureAwait(false);
await uow.CompleteAsync().ConfigureAwait(false);
return amount;
}
if (usr.LastReward.Month != now.Month)
{
usr.LastReward = now;
usr.AmountRewardedThisMonth = amount;
await CurrencyHandler.AddCurrencyAsync(userId, "Patreon reward - recurring", amount, uow).ConfigureAwait(false);
await uow.CompleteAsync().ConfigureAwait(false);
return amount;
}
if ( usr.AmountRewardedThisMonth < amount)
{
var toAward = amount - usr.AmountRewardedThisMonth;
usr.LastReward = now;
usr.AmountRewardedThisMonth = amount;
await CurrencyHandler.AddCurrencyAsync(usr.UserId, "Patreon reward - update", toAward, uow).ConfigureAwait(false);
await uow.CompleteAsync().ConfigureAwait(false);
return toAward;
}
}
return 0;
}
finally
{
claimLockJustInCase.Release();
}
}
}
} }
} }

View File

@ -1,4 +1,5 @@
using System; using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -6,32 +7,22 @@ using System.Threading.Tasks;
namespace NadekoBot.Modules.Utility.Models namespace NadekoBot.Modules.Utility.Models
{ {
public class PatreonData public class PatreonData
{ {
public Pledge[] Data { get; set; } public JObject[] Included { get; set; }
public Links Links { get; set; } public JObject[] Data { get; set; }
public PatreonDataLinks Links { get; set; }
} }
public class Attributes public class PatreonDataLinks
{ {
public int amount_cents { get; set; } public string first { get; set; }
public string created_at { get; set; } public string next { get; set; }
public string declined_since { get; set; }
public bool is_twitch_pledge { get; set; }
public bool patron_pays_fees { get; set; }
public int pledge_cap_cents { get; set; }
} }
public class Pledge public class PatreonUserAndReward
{ {
public Attributes Attributes { get; set; } public PatreonUser User { get; set; }
public int Id { get; set; } public PatreonPledge Reward { get; set; }
}
public class Links
{
public string First { get; set; }
public string Next { get; set; }
} }
} }

View File

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Utility.Models
{
public class Attributes
{
public int amount_cents { get; set; }
public string created_at { get; set; }
public object declined_since { get; set; }
public bool is_twitch_pledge { get; set; }
public bool patron_pays_fees { get; set; }
public int pledge_cap_cents { get; set; }
}
public class Address
{
public object data { get; set; }
}
public class Data
{
public string id { get; set; }
public string type { get; set; }
}
public class Links
{
public string related { get; set; }
}
public class Creator
{
public Data data { get; set; }
public Links links { get; set; }
}
public class Patron
{
public Data data { get; set; }
public Links links { get; set; }
}
public class Reward
{
public Data data { get; set; }
public Links links { get; set; }
}
public class Relationships
{
public Address address { get; set; }
public Creator creator { get; set; }
public Patron patron { get; set; }
public Reward reward { get; set; }
}
public class PatreonPledge
{
public Attributes attributes { get; set; }
public string id { get; set; }
public Relationships relationships { get; set; }
public string type { get; set; }
}
}

View File

@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Utility.Models
{
public class DiscordConnection
{
public string user_id { get; set; }
}
public class SocialConnections
{
public object deviantart { get; set; }
public DiscordConnection discord { get; set; }
public object facebook { get; set; }
public object spotify { get; set; }
public object twitch { get; set; }
public object twitter { get; set; }
public object youtube { get; set; }
}
public class UserAttributes
{
public string about { get; set; }
public string created { get; set; }
public object discord_id { get; set; }
public string email { get; set; }
public object facebook { get; set; }
public object facebook_id { get; set; }
public string first_name { get; set; }
public string full_name { get; set; }
public int gender { get; set; }
public bool has_password { get; set; }
public string image_url { get; set; }
public bool is_deleted { get; set; }
public bool is_nuked { get; set; }
public bool is_suspended { get; set; }
public string last_name { get; set; }
public SocialConnections social_connections { get; set; }
public int status { get; set; }
public string thumb_url { get; set; }
public object twitch { get; set; }
public string twitter { get; set; }
public string url { get; set; }
public string vanity { get; set; }
public object youtube { get; set; }
}
public class Campaign
{
public Data data { get; set; }
public Links links { get; set; }
}
public class UserRelationships
{
public Campaign campaign { get; set; }
}
public class PatreonUser
{
public UserAttributes attributes { get; set; }
public string id { get; set; }
public UserRelationships relationships { get; set; }
public string type { get; set; }
}
}

View File

@ -1706,6 +1706,33 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to clparew.
/// </summary>
public static string claimpatreonrewards_cmd {
get {
return ResourceManager.GetString("claimpatreonrewards_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Claim patreon rewards. If you&apos;re subscribed to bot owner&apos;s patreon you can user this command to claim your rewards - assuming bot owner did setup has their patreon key..
/// </summary>
public static string claimpatreonrewards_desc {
get {
return ResourceManager.GetString("claimpatreonrewards_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}claimpatreonrewards`.
/// </summary>
public static string claimpatreonrewards_usage {
get {
return ResourceManager.GetString("claimpatreonrewards_usage", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to cleanup. /// Looks up a localized string similar to cleanup.
/// </summary> /// </summary>
@ -7673,6 +7700,33 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to slowmodewl.
/// </summary>
public static string slowmodewhitelist_cmd {
get {
return ResourceManager.GetString("slowmodewhitelist_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Ignores a role or a user from the slowmode feature..
/// </summary>
public static string slowmodewhitelist_desc {
get {
return ResourceManager.GetString("slowmodewhitelist_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}slowmodewl SomeRole` or `{0}slowmodewl AdminDude`.
/// </summary>
public static string slowmodewhitelist_usage {
get {
return ResourceManager.GetString("slowmodewhitelist_usage", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to softban sb. /// Looks up a localized string similar to softban sb.
/// </summary> /// </summary>
@ -7889,6 +7943,114 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to scadd.
/// </summary>
public static string startupcommandadd_cmd {
get {
return ResourceManager.GetString("startupcommandadd_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Adds a command to the list of commands which will be executed automatically in the current channel, in the order they were added in, by the bot when it startups up..
/// </summary>
public static string startupcommandadd_desc {
get {
return ResourceManager.GetString("startupcommandadd_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}scadd .stats`.
/// </summary>
public static string startupcommandadd_usage {
get {
return ResourceManager.GetString("startupcommandadd_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to scrm.
/// </summary>
public static string startupcommandremove_cmd {
get {
return ResourceManager.GetString("startupcommandremove_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Removes a startup command with the provided command text..
/// </summary>
public static string startupcommandremove_desc {
get {
return ResourceManager.GetString("startupcommandremove_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}scrm .stats`.
/// </summary>
public static string startupcommandremove_usage {
get {
return ResourceManager.GetString("startupcommandremove_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to sclist.
/// </summary>
public static string startupcommands_cmd {
get {
return ResourceManager.GetString("startupcommands_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Lists all startup commands in the order they will be executed in..
/// </summary>
public static string startupcommands_desc {
get {
return ResourceManager.GetString("startupcommands_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}sclist`.
/// </summary>
public static string startupcommands_usage {
get {
return ResourceManager.GetString("startupcommands_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to scclr.
/// </summary>
public static string startupcommandsclear_cmd {
get {
return ResourceManager.GetString("startupcommandsclear_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Removes all startup commands..
/// </summary>
public static string startupcommandsclear_desc {
get {
return ResourceManager.GetString("startupcommandsclear_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}scclr`.
/// </summary>
public static string startupcommandsclear_usage {
get {
return ResourceManager.GetString("startupcommandsclear_usage", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to startwar sw. /// Looks up a localized string similar to startwar sw.
/// </summary> /// </summary>
@ -8456,6 +8618,33 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to unban.
/// </summary>
public static string unban_cmd {
get {
return ResourceManager.GetString("unban_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Unbans a user with the provided user#discrim or id..
/// </summary>
public static string unban_desc {
get {
return ResourceManager.GetString("unban_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}unban kwoth#1234` or `{0}unban 123123123`.
/// </summary>
public static string unban_usage {
get {
return ResourceManager.GetString("unban_usage", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to unclaim ucall uc. /// Looks up a localized string similar to unclaim ucall uc.
/// </summary> /// </summary>
@ -9104,6 +9293,168 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to wait.
/// </summary>
public static string wait_cmd {
get {
return ResourceManager.GetString("wait_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Used only as a startup command. Waits a certain number of miliseconds before continuing the execution of the following startup commands..
/// </summary>
public static string wait_desc {
get {
return ResourceManager.GetString("wait_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}wait 3000`.
/// </summary>
public static string wait_usage {
get {
return ResourceManager.GetString("wait_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to warn.
/// </summary>
public static string warn_cmd {
get {
return ResourceManager.GetString("warn_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Warns a user..
/// </summary>
public static string warn_desc {
get {
return ResourceManager.GetString("warn_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}warn @b1nzy`.
/// </summary>
public static string warn_usage {
get {
return ResourceManager.GetString("warn_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to warnclear warnc.
/// </summary>
public static string warnclear_cmd {
get {
return ResourceManager.GetString("warnclear_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Clears all warnings from a certain user..
/// </summary>
public static string warnclear_desc {
get {
return ResourceManager.GetString("warnclear_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}warnclear @PoorDude`.
/// </summary>
public static string warnclear_usage {
get {
return ResourceManager.GetString("warnclear_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to warnlog.
/// </summary>
public static string warnlog_cmd {
get {
return ResourceManager.GetString("warnlog_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to See a list of warnings of a certain user..
/// </summary>
public static string warnlog_desc {
get {
return ResourceManager.GetString("warnlog_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}warnlog @b1nzy`.
/// </summary>
public static string warnlog_usage {
get {
return ResourceManager.GetString("warnlog_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to warnpunish warnp.
/// </summary>
public static string warnpunish_cmd {
get {
return ResourceManager.GetString("warnpunish_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Sets a punishment for a certain number of warnings. Provide no punishment to remove..
/// </summary>
public static string warnpunish_desc {
get {
return ResourceManager.GetString("warnpunish_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}warnpunish 5 Ban` or `{0}warnpunish 3`.
/// </summary>
public static string warnpunish_usage {
get {
return ResourceManager.GetString("warnpunish_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to warnpunishlist warnpl.
/// </summary>
public static string warnpunishlist_cmd {
get {
return ResourceManager.GetString("warnpunishlist_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Lists punishments for warnings..
/// </summary>
public static string warnpunishlist_desc {
get {
return ResourceManager.GetString("warnpunishlist_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}warnpunishlist`.
/// </summary>
public static string warnpunishlist_usage {
get {
return ResourceManager.GetString("warnpunishlist_usage", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to weather we. /// Looks up a localized string similar to weather we.
/// </summary> /// </summary>

View File

@ -3222,4 +3222,121 @@
<data name="alias_usage" xml:space="preserve"> <data name="alias_usage" xml:space="preserve">
<value>`{0}alias allin $bf 100 h` or `{0}alias "linux thingy" &gt;loonix Spyware Windows`</value> <value>`{0}alias allin $bf 100 h` or `{0}alias "linux thingy" &gt;loonix Spyware Windows`</value>
</data> </data>
<data name="warnlog_cmd" xml:space="preserve">
<value>warnlog</value>
</data>
<data name="warnlog_desc" xml:space="preserve">
<value>See a list of warnings of a certain user.</value>
</data>
<data name="warnlog_usage" xml:space="preserve">
<value>`{0}warnlog @b1nzy`</value>
</data>
<data name="warn_cmd" xml:space="preserve">
<value>warn</value>
</data>
<data name="warn_desc" xml:space="preserve">
<value>Warns a user.</value>
</data>
<data name="warn_usage" xml:space="preserve">
<value>`{0}warn @b1nzy`</value>
</data>
<data name="startupcommandadd_cmd" xml:space="preserve">
<value>scadd</value>
</data>
<data name="startupcommandadd_desc" xml:space="preserve">
<value>Adds a command to the list of commands which will be executed automatically in the current channel, in the order they were added in, by the bot when it startups up.</value>
</data>
<data name="startupcommandadd_usage" xml:space="preserve">
<value>`{0}scadd .stats`</value>
</data>
<data name="startupcommandremove_cmd" xml:space="preserve">
<value>scrm</value>
</data>
<data name="startupcommandremove_desc" xml:space="preserve">
<value>Removes a startup command with the provided command text.</value>
</data>
<data name="startupcommandremove_usage" xml:space="preserve">
<value>`{0}scrm .stats`</value>
</data>
<data name="startupcommandsclear_cmd" xml:space="preserve">
<value>scclr</value>
</data>
<data name="startupcommandsclear_desc" xml:space="preserve">
<value>Removes all startup commands.</value>
</data>
<data name="startupcommandsclear_usage" xml:space="preserve">
<value>`{0}scclr`</value>
</data>
<data name="startupcommands_cmd" xml:space="preserve">
<value>sclist</value>
</data>
<data name="startupcommands_desc" xml:space="preserve">
<value>Lists all startup commands in the order they will be executed in.</value>
</data>
<data name="startupcommands_usage" xml:space="preserve">
<value>`{0}sclist`</value>
</data>
<data name="unban_cmd" xml:space="preserve">
<value>unban</value>
</data>
<data name="unban_desc" xml:space="preserve">
<value>Unbans a user with the provided user#discrim or id.</value>
</data>
<data name="unban_usage" xml:space="preserve">
<value>`{0}unban kwoth#1234` or `{0}unban 123123123`</value>
</data>
<data name="wait_cmd" xml:space="preserve">
<value>wait</value>
</data>
<data name="wait_desc" xml:space="preserve">
<value>Used only as a startup command. Waits a certain number of miliseconds before continuing the execution of the following startup commands.</value>
</data>
<data name="wait_usage" xml:space="preserve">
<value>`{0}wait 3000`</value>
</data>
<data name="warnclear_cmd" xml:space="preserve">
<value>warnclear warnc</value>
</data>
<data name="warnclear_desc" xml:space="preserve">
<value>Clears all warnings from a certain user.</value>
</data>
<data name="warnclear_usage" xml:space="preserve">
<value>`{0}warnclear @PoorDude`</value>
</data>
<data name="warnpunishlist_cmd" xml:space="preserve">
<value>warnpunishlist warnpl</value>
</data>
<data name="warnpunishlist_desc" xml:space="preserve">
<value>Lists punishments for warnings.</value>
</data>
<data name="warnpunishlist_usage" xml:space="preserve">
<value>`{0}warnpunishlist`</value>
</data>
<data name="warnpunish_cmd" xml:space="preserve">
<value>warnpunish warnp</value>
</data>
<data name="warnpunish_desc" xml:space="preserve">
<value>Sets a punishment for a certain number of warnings. Provide no punishment to remove.</value>
</data>
<data name="warnpunish_usage" xml:space="preserve">
<value>`{0}warnpunish 5 Ban` or `{0}warnpunish 3`</value>
</data>
<data name="claimpatreonrewards_cmd" xml:space="preserve">
<value>clparew</value>
</data>
<data name="claimpatreonrewards_desc" xml:space="preserve">
<value>Claim patreon rewards. If you're subscribed to bot owner's patreon you can user this command to claim your rewards - assuming bot owner did setup has their patreon key.</value>
</data>
<data name="claimpatreonrewards_usage" xml:space="preserve">
<value>`{0}claimpatreonrewards`</value>
</data>
<data name="slowmodewhitelist_cmd" xml:space="preserve">
<value>slowmodewl</value>
</data>
<data name="slowmodewhitelist_desc" xml:space="preserve">
<value>Ignores a role or a user from the slowmode feature.</value>
</data>
<data name="slowmodewhitelist_usage" xml:space="preserve">
<value>`{0}slowmodewl SomeRole` or `{0}slowmodewl AdminDude`</value>
</data>
</root> </root>

View File

@ -231,6 +231,15 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Channel.
/// </summary>
public static string administration_channel {
get {
return ResourceManager.GetString("administration_channel", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Cleaned up.. /// Looks up a localized string similar to Cleaned up..
/// </summary> /// </summary>
@ -240,6 +249,15 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Command Text.
/// </summary>
public static string administration_command_text {
get {
return ResourceManager.GetString("administration_command_text", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Content. /// Looks up a localized string similar to Content.
/// </summary> /// </summary>
@ -556,6 +574,15 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Kicked.
/// </summary>
public static string administration_kicked_pl {
get {
return ResourceManager.GetString("administration_kicked_pl", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to User kicked. /// Looks up a localized string similar to User kicked.
/// </summary> /// </summary>
@ -736,6 +763,15 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Moderator.
/// </summary>
public static string administration_moderator {
get {
return ResourceManager.GetString("administration_moderator", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to {0} moved from {1} to {2}. /// Looks up a localized string similar to {0} moved from {1} to {2}.
/// </summary> /// </summary>
@ -907,6 +943,15 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to page {0}.
/// </summary>
public static string administration_page {
get {
return ResourceManager.GetString("administration_page", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Error. Most likely I don&apos;t have sufficient permissions.. /// Looks up a localized string similar to Error. Most likely I don&apos;t have sufficient permissions..
/// </summary> /// </summary>
@ -1060,6 +1105,15 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Reason.
/// </summary>
public static string administration_reason {
get {
return ResourceManager.GetString("administration_reason", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Successfully removed role {0} from user {1}. /// Looks up a localized string similar to Successfully removed role {0} from user {1}.
/// </summary> /// </summary>
@ -1206,6 +1260,33 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to New startup command added..
/// </summary>
public static string administration_scadd {
get {
return ResourceManager.GetString("administration_scadd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Startup command successfully removed..
/// </summary>
public static string administration_scrm {
get {
return ResourceManager.GetString("administration_scrm", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Startup command not found..
/// </summary>
public static string administration_scrm_fail {
get {
return ResourceManager.GetString("administration_scrm_fail", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to You already have {0} role.. /// Looks up a localized string similar to You already have {0} role..
/// </summary> /// </summary>
@ -1305,6 +1386,15 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Server.
/// </summary>
public static string administration_server {
get {
return ResourceManager.GetString("administration_server", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to New avatar set!. /// Looks up a localized string similar to New avatar set!.
/// </summary> /// </summary>
@ -1423,7 +1513,43 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to soft-banned (kicked). /// Looks up a localized string similar to Slowmode will now ignore {0} role..
/// </summary>
public static string administration_slowmodewl_role_start {
get {
return ResourceManager.GetString("administration_slowmodewl_role_start", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Slowmode will no longer ignore {0} role..
/// </summary>
public static string administration_slowmodewl_role_stop {
get {
return ResourceManager.GetString("administration_slowmodewl_role_stop", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Slowmode will now ignore user {0}..
/// </summary>
public static string administration_slowmodewl_user_start {
get {
return ResourceManager.GetString("administration_slowmodewl_user_start", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Slowmode will no longer ignore user {0}..
/// </summary>
public static string administration_slowmodewl_user_stop {
get {
return ResourceManager.GetString("administration_slowmodewl_user_stop", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to soft-banned.
/// </summary> /// </summary>
public static string administration_soft_banned_pl { public static string administration_soft_banned_pl {
get { get {
@ -1459,6 +1585,24 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to No startup commands on this page..
/// </summary>
public static string administration_startcmdlist_none {
get {
return ResourceManager.GetString("administration_startcmdlist_none", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cleared all startup commands..
/// </summary>
public static string administration_startcmds_cleared {
get {
return ResourceManager.GetString("administration_startcmds_cleared", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Text channel created.. /// Looks up a localized string similar to Text channel created..
/// </summary> /// </summary>
@ -1477,6 +1621,15 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to User {0} has been unbanned..
/// </summary>
public static string administration_unbanned_user {
get {
return ResourceManager.GetString("administration_unbanned_user", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Undeafen successful.. /// Looks up a localized string similar to Undeafen successful..
/// </summary> /// </summary>
@ -1558,6 +1711,15 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to User not found..
/// </summary>
public static string administration_user_not_found {
get {
return ResourceManager.GetString("administration_user_not_found", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to User&apos;s role added. /// Looks up a localized string similar to User&apos;s role added.
/// </summary> /// </summary>
@ -1648,6 +1810,24 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to User {0} has been warned..
/// </summary>
public static string administration_user_warned {
get {
return ResourceManager.GetString("administration_user_warned", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to User {0} has been warned and {1} punishment has been applied..
/// </summary>
public static string administration_user_warned_and_punished {
get {
return ResourceManager.GetString("administration_user_warned_and_punished", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Username. /// Looks up a localized string similar to Username.
/// </summary> /// </summary>
@ -1765,6 +1945,96 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to cleared by {0}.
/// </summary>
public static string administration_warn_cleared_by {
get {
return ResourceManager.GetString("administration_warn_cleared_by", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Warning punishment list.
/// </summary>
public static string administration_warn_punish_list {
get {
return ResourceManager.GetString("administration_warn_punish_list", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Having {0} warnings will no longer trigger a punishment..
/// </summary>
public static string administration_warn_punish_rem {
get {
return ResourceManager.GetString("administration_warn_punish_rem", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to I will apply {0} punishment to users with {1} warnings..
/// </summary>
public static string administration_warn_punish_set {
get {
return ResourceManager.GetString("administration_warn_punish_set", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Warned on {0} server.
/// </summary>
public static string administration_warned_on {
get {
return ResourceManager.GetString("administration_warned_on", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to On {0} at {1} by {2}.
/// </summary>
public static string administration_warned_on_by {
get {
return ResourceManager.GetString("administration_warned_on_by", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to All warnings have been cleared for {0}..
/// </summary>
public static string administration_warnings_cleared {
get {
return ResourceManager.GetString("administration_warnings_cleared", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to No warning on this page..
/// </summary>
public static string administration_warnings_none {
get {
return ResourceManager.GetString("administration_warnings_none", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Warnlog for {0}.
/// </summary>
public static string administration_warnlog_for {
get {
return ResourceManager.GetString("administration_warnlog_for", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to No punishments set..
/// </summary>
public static string administration_warnpl_none {
get {
return ResourceManager.GetString("administration_warnpl_none", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to User {0} from text chat. /// Looks up a localized string similar to User {0} from text chat.
/// </summary> /// </summary>
@ -5755,6 +6025,105 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Failed claiming rewards due to one of the following reasons:.
/// </summary>
public static string utility_clpa_fail {
get {
return ResourceManager.GetString("utility_clpa_fail", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Maybe you&apos;ve already received your reward for this month. You can receive rewards only once a month unless you increase your pledge..
/// </summary>
public static string utility_clpa_fail_already {
get {
return ResourceManager.GetString("utility_clpa_fail_already", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Already rewarded.
/// </summary>
public static string utility_clpa_fail_already_title {
get {
return ResourceManager.GetString("utility_clpa_fail_already_title", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Your discord account might not be connected to Patreon.. If you are unsure what that means, or don&apos;t know how to connect it - you have to go to [Patreon account settings page](https://patreon.com/settings/account) and click &apos;Connect to discord&apos; button..
/// </summary>
public static string utility_clpa_fail_conn {
get {
return ResourceManager.GetString("utility_clpa_fail_conn", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Discord account not connected.
/// </summary>
public static string utility_clpa_fail_conn_title {
get {
return ResourceManager.GetString("utility_clpa_fail_conn_title", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to In order to be eligible for the reward, you must support the project on patreon. You can use {0} command to get the link..
/// </summary>
public static string utility_clpa_fail_sup {
get {
return ResourceManager.GetString("utility_clpa_fail_sup", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Not supporting.
/// </summary>
public static string utility_clpa_fail_sup_title {
get {
return ResourceManager.GetString("utility_clpa_fail_sup_title", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You have to wait a few hours after making your pledge, if you didn&apos;t, try again later..
/// </summary>
public static string utility_clpa_fail_wait {
get {
return ResourceManager.GetString("utility_clpa_fail_wait", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Wait some time.
/// </summary>
public static string utility_clpa_fail_wait_title {
get {
return ResourceManager.GetString("utility_clpa_fail_wait_title", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You&apos;ve received {0} Thanks for supporting the project!.
/// </summary>
public static string utility_clpa_success {
get {
return ResourceManager.GetString("utility_clpa_success", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Rewards can be claimed on or after 5th of each month..
/// </summary>
public static string utility_clpa_too_early {
get {
return ResourceManager.GetString("utility_clpa_too_early", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Commands ran. /// Looks up a localized string similar to Commands ran.
/// </summary> /// </summary>

View File

@ -740,7 +740,7 @@ Reason: {1}</value>
<value>Slow mode initiated</value> <value>Slow mode initiated</value>
</data> </data>
<data name="administration_soft_banned_pl" xml:space="preserve"> <data name="administration_soft_banned_pl" xml:space="preserve">
<value>soft-banned (kicked)</value> <value>soft-banned</value>
<comment>PLURAL</comment> <comment>PLURAL</comment>
</data> </data>
<data name="administration_spam_ignore" xml:space="preserve"> <data name="administration_spam_ignore" xml:space="preserve">
@ -2278,5 +2278,129 @@ Owner ID: {2}</value>
<data name="searches_compet_playtime" xml:space="preserve"> <data name="searches_compet_playtime" xml:space="preserve">
<value>Competitive playtime</value> <value>Competitive playtime</value>
</data> </data>
<data name="administration_channel" xml:space="preserve">
<value>Channel</value>
</data>
<data name="administration_command_text" xml:space="preserve">
<value>Command Text</value>
</data>
<data name="administration_kicked_pl" xml:space="preserve">
<value>Kicked</value>
<comment>PLURAL</comment>
</data>
<data name="administration_moderator" xml:space="preserve">
<value>Moderator</value>
</data>
<data name="administration_page" xml:space="preserve">
<value>page {0}</value>
</data>
<data name="administration_reason" xml:space="preserve">
<value>Reason</value>
</data>
<data name="administration_scadd" xml:space="preserve">
<value>New startup command added.</value>
</data>
<data name="administration_scrm" xml:space="preserve">
<value>Startup command successfully removed.</value>
</data>
<data name="administration_scrm_fail" xml:space="preserve">
<value>Startup command not found.</value>
</data>
<data name="administration_server" xml:space="preserve">
<value>Server</value>
</data>
<data name="administration_startcmdlist_none" xml:space="preserve">
<value>No startup commands on this page.</value>
</data>
<data name="administration_startcmds_cleared" xml:space="preserve">
<value>Cleared all startup commands.</value>
</data>
<data name="administration_unbanned_user" xml:space="preserve">
<value>User {0} has been unbanned.</value>
</data>
<data name="administration_user_not_found" xml:space="preserve">
<value>User not found.</value>
</data>
<data name="administration_user_warned" xml:space="preserve">
<value>User {0} has been warned.</value>
</data>
<data name="administration_user_warned_and_punished" xml:space="preserve">
<value>User {0} has been warned and {1} punishment has been applied.</value>
</data>
<data name="administration_warned_on" xml:space="preserve">
<value>Warned on {0} server</value>
</data>
<data name="administration_warned_on_by" xml:space="preserve">
<value>On {0} at {1} by {2}</value>
</data>
<data name="administration_warnings_cleared" xml:space="preserve">
<value>All warnings have been cleared for {0}.</value>
</data>
<data name="administration_warnings_none" xml:space="preserve">
<value>No warning on this page.</value>
</data>
<data name="administration_warnlog_for" xml:space="preserve">
<value>Warnlog for {0}</value>
</data>
<data name="administration_warnpl_none" xml:space="preserve">
<value>No punishments set.</value>
</data>
<data name="administration_warn_cleared_by" xml:space="preserve">
<value>cleared by {0}</value>
</data>
<data name="administration_warn_punish_list" xml:space="preserve">
<value>Warning punishment list</value>
</data>
<data name="administration_warn_punish_rem" xml:space="preserve">
<value>Having {0} warnings will no longer trigger a punishment.</value>
</data>
<data name="administration_warn_punish_set" xml:space="preserve">
<value>I will apply {0} punishment to users with {1} warnings.</value>
</data>
<data name="administration_slowmodewl_role_start" xml:space="preserve">
<value>Slowmode will now ignore {0} role.</value>
</data>
<data name="administration_slowmodewl_role_stop" xml:space="preserve">
<value>Slowmode will no longer ignore {0} role.</value>
</data>
<data name="administration_slowmodewl_user_start" xml:space="preserve">
<value>Slowmode will now ignore user {0}.</value>
</data>
<data name="administration_slowmodewl_user_stop" xml:space="preserve">
<value>Slowmode will no longer ignore user {0}.</value>
</data>
<data name="utility_clpa_fail" xml:space="preserve">
<value>Failed claiming rewards due to one of the following reasons:</value>
</data>
<data name="utility_clpa_fail_already" xml:space="preserve">
<value>Maybe you&apos;ve already received your reward for this month. You can receive rewards only once a month unless you increase your pledge.</value>
</data>
<data name="utility_clpa_fail_already_title" xml:space="preserve">
<value>Already rewarded</value>
</data>
<data name="utility_clpa_fail_conn" xml:space="preserve">
<value>Your discord account might not be connected to Patreon. If you are unsure what that means, or don&apos;t know how to connect it - you have to go to [Patreon account settings page](https://patreon.com/settings/account) and click &apos;Connect to discord&apos; button.</value>
</data>
<data name="utility_clpa_fail_conn_title" xml:space="preserve">
<value>Discord account not connected</value>
</data>
<data name="utility_clpa_fail_sup" xml:space="preserve">
<value>In order to be eligible for the reward, you must support the project on patreon. You can use {0} command to get the link.</value>
</data>
<data name="utility_clpa_fail_sup_title" xml:space="preserve">
<value>Not supporting</value>
</data>
<data name="utility_clpa_fail_wait" xml:space="preserve">
<value>You have to wait a few hours after making your pledge, if you didn&apos;t, try again later.</value>
</data>
<data name="utility_clpa_fail_wait_title" xml:space="preserve">
<value>Wait some time</value>
</data>
<data name="utility_clpa_success" xml:space="preserve">
<value>You&apos;ve received {0} Thanks for supporting the project!</value>
</data>
<data name="utility_clpa_too_early" xml:space="preserve">
<value>Rewards can be claimed on or after 5th of each month.</value>
</data>
</root> </root>

File diff suppressed because it is too large Load Diff

View File

@ -740,7 +740,7 @@ Reason: {1}</value>
<value>Slow mode initiated</value> <value>Slow mode initiated</value>
</data> </data>
<data name="administration_soft_banned_pl" xml:space="preserve"> <data name="administration_soft_banned_pl" xml:space="preserve">
<value>soft-banned (kicked)</value> <value>soft-banned</value>
<comment>PLURAL</comment> <comment>PLURAL</comment>
</data> </data>
<data name="administration_spam_ignore" xml:space="preserve"> <data name="administration_spam_ignore" xml:space="preserve">
@ -2278,4 +2278,128 @@ Owner ID: {2}</value>
<data name="searches_compet_playtime" xml:space="preserve"> <data name="searches_compet_playtime" xml:space="preserve">
<value>Competitive playtime</value> <value>Competitive playtime</value>
</data> </data>
<data name="administration_channel" xml:space="preserve">
<value>Channel</value>
</data>
<data name="administration_command_text" xml:space="preserve">
<value>Command Text</value>
</data>
<data name="administration_kicked_pl" xml:space="preserve">
<value>Kicked</value>
<comment>PLURAL</comment>
</data>
<data name="administration_moderator" xml:space="preserve">
<value>Moderator</value>
</data>
<data name="administration_page" xml:space="preserve">
<value>page {0}</value>
</data>
<data name="administration_reason" xml:space="preserve">
<value>Reason</value>
</data>
<data name="administration_scadd" xml:space="preserve">
<value>New startup command added.</value>
</data>
<data name="administration_scrm" xml:space="preserve">
<value>Startup command successfully removed.</value>
</data>
<data name="administration_scrm_fail" xml:space="preserve">
<value>Startup command not found.</value>
</data>
<data name="administration_server" xml:space="preserve">
<value>Server</value>
</data>
<data name="administration_startcmdlist_none" xml:space="preserve">
<value>No startup commands on this page.</value>
</data>
<data name="administration_startcmds_cleared" xml:space="preserve">
<value>Cleared all startup commands.</value>
</data>
<data name="administration_unbanned_user" xml:space="preserve">
<value>User {0} has been unbanned.</value>
</data>
<data name="administration_user_not_found" xml:space="preserve">
<value>User not found.</value>
</data>
<data name="administration_user_warned" xml:space="preserve">
<value>User {0} has been warned.</value>
</data>
<data name="administration_user_warned_and_punished" xml:space="preserve">
<value>User {0} has been warned and {1} punishment has been applied.</value>
</data>
<data name="administration_warned_on" xml:space="preserve">
<value>Warned on {0} server</value>
</data>
<data name="administration_warned_on_by" xml:space="preserve">
<value>On {0} at {1} by {2}</value>
</data>
<data name="administration_warnings_cleared" xml:space="preserve">
<value>All warnings have been cleared for {0}.</value>
</data>
<data name="administration_warnings_none" xml:space="preserve">
<value>No warning on this page.</value>
</data>
<data name="administration_warnlog_for" xml:space="preserve">
<value>Warnlog for {0}</value>
</data>
<data name="administration_warnpl_none" xml:space="preserve">
<value>No punishments set.</value>
</data>
<data name="administration_warn_cleared_by" xml:space="preserve">
<value>cleared by {0}</value>
</data>
<data name="administration_warn_punish_list" xml:space="preserve">
<value>Warning punishment list</value>
</data>
<data name="administration_warn_punish_rem" xml:space="preserve">
<value>Having {0} warnings will no longer trigger a punishment.</value>
</data>
<data name="administration_warn_punish_set" xml:space="preserve">
<value>I will apply {0} punishment to users with {1} warnings.</value>
</data>
<data name="administration_slowmodewl_role_start" xml:space="preserve">
<value>Slowmode will now ignore {0} role.</value>
</data>
<data name="administration_slowmodewl_role_stop" xml:space="preserve">
<value>Slowmode will no longer ignore {0} role.</value>
</data>
<data name="administration_slowmodewl_user_start" xml:space="preserve">
<value>Slowmode will now ignore user {0}.</value>
</data>
<data name="administration_slowmodewl_user_stop" xml:space="preserve">
<value>Slowmode will no longer ignore user {0}.</value>
</data>
<data name="utility_clpa_fail" xml:space="preserve">
<value>Failed claiming rewards due to one of the following reasons:</value>
</data>
<data name="utility_clpa_fail_already" xml:space="preserve">
<value>Maybe you've already received your reward for this month. You can receive rewards only once a month unless you increase your pledge.</value>
</data>
<data name="utility_clpa_fail_already_title" xml:space="preserve">
<value>Already rewarded</value>
</data>
<data name="utility_clpa_fail_conn" xml:space="preserve">
<value>Your discord account might not be connected to Patreon.. If you are unsure what that means, or don't know how to connect it - you have to go to [Patreon account settings page](https://patreon.com/settings/account) and click 'Connect to discord' button.</value>
</data>
<data name="utility_clpa_fail_conn_title" xml:space="preserve">
<value>Discord account not connected</value>
</data>
<data name="utility_clpa_fail_sup" xml:space="preserve">
<value>In order to be eligible for the reward, you must support the project on patreon. You can use {0} command to get the link.</value>
</data>
<data name="utility_clpa_fail_sup_title" xml:space="preserve">
<value>Not supporting</value>
</data>
<data name="utility_clpa_fail_wait" xml:space="preserve">
<value>You have to wait a few hours after making your pledge, if you didn't, try again later.</value>
</data>
<data name="utility_clpa_fail_wait_title" xml:space="preserve">
<value>Wait some time</value>
</data>
<data name="utility_clpa_success" xml:space="preserve">
<value>You've received {0} Thanks for supporting the project!</value>
</data>
<data name="utility_clpa_too_early" xml:space="preserve">
<value>Rewards can be claimed on or after 5th of each month.</value>
</data>
</root> </root>

View File

@ -1,260 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace NadekoBot.Resources {
using System;
using System.Reflection;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class ResponseStrings_sr_SP {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
internal ResponseStrings_sr_SP() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NadekoBot.Resources.ResponseStrings-sr-SP", typeof(ResponseStrings_sr_SP).GetTypeInfo().Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to {0} has already fainted..
/// </summary>
public static string pokemon_already_fainted {
get {
return ResourceManager.GetString("pokemon_already_fainted", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0} already has full HP..
/// </summary>
public static string pokemon_already_full {
get {
return ResourceManager.GetString("pokemon_already_full", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Your type is already {0}.
/// </summary>
public static string pokemon_already_that_type {
get {
return ResourceManager.GetString("pokemon_already_that_type", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to used {0}{1} on {2}{3} for {4} damage..
/// </summary>
public static string pokemon_attack {
get {
return ResourceManager.GetString("pokemon_attack", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You can&apos;t attack again without retaliation!.
/// </summary>
public static string pokemon_cant_attack_again {
get {
return ResourceManager.GetString("pokemon_cant_attack_again", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You can&apos;t attack yourself..
/// </summary>
public static string pokemon_cant_attack_yourself {
get {
return ResourceManager.GetString("pokemon_cant_attack_yourself", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0} has fainted!.
/// </summary>
public static string pokemon_fainted {
get {
return ResourceManager.GetString("pokemon_fainted", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to healed {0} with one {1}.
/// </summary>
public static string pokemon_healed {
get {
return ResourceManager.GetString("pokemon_healed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0} has {1} HP remaining..
/// </summary>
public static string pokemon_hp_remaining {
get {
return ResourceManager.GetString("pokemon_hp_remaining", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You can&apos;t use {0}. Type `{1}ml` to see a list of moves you can use..
/// </summary>
public static string pokemon_invalid_move {
get {
return ResourceManager.GetString("pokemon_invalid_move", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Movelist for {0} type.
/// </summary>
public static string pokemon_moves {
get {
return ResourceManager.GetString("pokemon_moves", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You don&apos;t have enough {0}.
/// </summary>
public static string pokemon_no_currency {
get {
return ResourceManager.GetString("pokemon_no_currency", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to It&apos;s not effective..
/// </summary>
public static string pokemon_not_effective {
get {
return ResourceManager.GetString("pokemon_not_effective", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to revived {0} with one {1}.
/// </summary>
public static string pokemon_revive_other {
get {
return ResourceManager.GetString("pokemon_revive_other", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You revived yourself with one {0}.
/// </summary>
public static string pokemon_revive_yourself {
get {
return ResourceManager.GetString("pokemon_revive_yourself", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Your type has been changed to {0} for a {1}.
/// </summary>
public static string pokemon_settype_success {
get {
return ResourceManager.GetString("pokemon_settype_success", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to It&apos;s somewhat effective..
/// </summary>
public static string pokemon_somewhat_effective {
get {
return ResourceManager.GetString("pokemon_somewhat_effective", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to It&apos;s super effective!.
/// </summary>
public static string pokemon_super_effective {
get {
return ResourceManager.GetString("pokemon_super_effective", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You used too many moves in a row, so you can&apos;t move!.
/// </summary>
public static string pokemon_too_many_moves {
get {
return ResourceManager.GetString("pokemon_too_many_moves", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Type of {0} is {1}.
/// </summary>
public static string pokemon_type_of_user {
get {
return ResourceManager.GetString("pokemon_type_of_user", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to User not found..
/// </summary>
public static string pokemon_user_not_found {
get {
return ResourceManager.GetString("pokemon_user_not_found", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You fainted, so you are not able to move!.
/// </summary>
public static string pokemon_you_fainted {
get {
return ResourceManager.GetString("pokemon_you_fainted", resourceCulture);
}
}
}
}

View File

@ -37,7 +37,7 @@ namespace NadekoBot.Services
private List<IDMChannel> ownerChannels { get; set; } = new List<IDMChannel>(); private List<IDMChannel> ownerChannels { get; set; } = new List<IDMChannel>();
public event Func<SocketUserMessage, CommandInfo, Task> CommandExecuted = delegate { return Task.CompletedTask; }; public event Func<IUserMessage, CommandInfo, Task> CommandExecuted = delegate { return Task.CompletedTask; };
//userid/msg count //userid/msg count
public ConcurrentDictionary<ulong, uint> UserMessagesSent { get; } = new ConcurrentDictionary<ulong, uint>(); public ConcurrentDictionary<ulong, uint> UserMessagesSent { get; } = new ConcurrentDictionary<ulong, uint>();
@ -109,7 +109,7 @@ namespace NadekoBot.Services
return Task.CompletedTask; return Task.CompletedTask;
} }
private async Task<bool> TryRunCleverbot(SocketUserMessage usrMsg, IGuild guild) private async Task<bool> TryRunCleverbot(IUserMessage usrMsg, IGuild guild)
{ {
if (guild == null) if (guild == null)
return false; return false;
@ -130,14 +130,13 @@ namespace NadekoBot.Services
return false; return false;
} }
private bool IsBlacklisted(IGuild guild, SocketUserMessage usrMsg) => private bool IsBlacklisted(IGuild guild, IUserMessage usrMsg) =>
usrMsg.Author?.Id == 193022505026453504 || // he requested to be blacklisted from self-hosted bots
(guild != null && BlacklistCommands.BlacklistedGuilds.Contains(guild.Id)) || (guild != null && BlacklistCommands.BlacklistedGuilds.Contains(guild.Id)) ||
BlacklistCommands.BlacklistedChannels.Contains(usrMsg.Channel.Id) || BlacklistCommands.BlacklistedChannels.Contains(usrMsg.Channel.Id) ||
BlacklistCommands.BlacklistedUsers.Contains(usrMsg.Author.Id); BlacklistCommands.BlacklistedUsers.Contains(usrMsg.Author.Id);
private const float _oneThousandth = 1.0f / 1000; private const float _oneThousandth = 1.0f / 1000;
private Task LogSuccessfulExecution(SocketUserMessage usrMsg, ExecuteCommandResult exec, SocketTextChannel channel, int exec1, int exec2, int exec3, int total) private Task LogSuccessfulExecution(IUserMessage usrMsg, ExecuteCommandResult exec, ITextChannel channel, int exec1, int exec2, int exec3, int total)
{ {
_log.Info("Command Executed after {4}/{5}/{6}/{7}s\n\t" + _log.Info("Command Executed after {4}/{5}/{6}/{7}s\n\t" +
"User: {0}\n\t" + "User: {0}\n\t" +
@ -156,7 +155,7 @@ namespace NadekoBot.Services
return Task.CompletedTask; return Task.CompletedTask;
} }
private void LogErroredExecution(SocketUserMessage usrMsg, ExecuteCommandResult exec, SocketTextChannel channel, int exec1, int exec2, int exec3, int total) private void LogErroredExecution(IUserMessage usrMsg, ExecuteCommandResult exec, ITextChannel channel, int exec1, int exec2, int exec3, int total)
{ {
_log.Warn("Command Errored after {5}/{6}/{7}/{8}s\n\t" + _log.Warn("Command Errored after {5}/{6}/{7}/{8}s\n\t" +
"User: {0}\n\t" + "User: {0}\n\t" +
@ -176,7 +175,7 @@ namespace NadekoBot.Services
); );
} }
private async Task<bool> InviteFiltered(IGuild guild, SocketUserMessage usrMsg) private async Task<bool> InviteFiltered(IGuild guild, IUserMessage usrMsg)
{ {
if ((Permissions.FilterCommands.InviteFilteringChannels.Contains(usrMsg.Channel.Id) || if ((Permissions.FilterCommands.InviteFilteringChannels.Contains(usrMsg.Channel.Id) ||
Permissions.FilterCommands.InviteFilteringServers.Contains(guild.Id)) && Permissions.FilterCommands.InviteFilteringServers.Contains(guild.Id)) &&
@ -196,7 +195,7 @@ namespace NadekoBot.Services
return false; return false;
} }
private async Task<bool> WordFiltered(IGuild guild, SocketUserMessage usrMsg) private async Task<bool> WordFiltered(IGuild guild, IUserMessage usrMsg)
{ {
var filteredChannelWords = Permissions.FilterCommands.FilteredWordsForChannel(usrMsg.Channel.Id, guild.Id) ?? new ConcurrentHashSet<string>(); var filteredChannelWords = Permissions.FilterCommands.FilteredWordsForChannel(usrMsg.Channel.Id, guild.Id) ?? new ConcurrentHashSet<string>();
var filteredServerWords = Permissions.FilterCommands.FilteredWordsForServer(guild.Id) ?? new ConcurrentHashSet<string>(); var filteredServerWords = Permissions.FilterCommands.FilteredWordsForServer(guild.Id) ?? new ConcurrentHashSet<string>();
@ -232,8 +231,6 @@ namespace NadekoBot.Services
if (msg.Author.IsBot || !NadekoBot.Ready) //no bots, wait until bot connected and initialized if (msg.Author.IsBot || !NadekoBot.Ready) //no bots, wait until bot connected and initialized
return; return;
var execTime = Environment.TickCount;
var usrMsg = msg as SocketUserMessage; var usrMsg = msg as SocketUserMessage;
if (usrMsg == null) //has to be an user message, not system/other messages. if (usrMsg == null) //has to be an user message, not system/other messages.
return; return;
@ -248,7 +245,27 @@ namespace NadekoBot.Services
var channel = msg.Channel as SocketTextChannel; var channel = msg.Channel as SocketTextChannel;
var guild = channel?.Guild; var guild = channel?.Guild;
if (guild != null && guild.OwnerId != msg.Author.Id) await TryRunCommand(guild, channel, usrMsg);
}
catch (Exception ex)
{
_log.Warn("Error in CommandHandler");
_log.Warn(ex);
if (ex.InnerException != null)
{
_log.Warn("Inner Exception of the error in CommandHandler");
_log.Warn(ex.InnerException);
}
}
});
return Task.CompletedTask;
}
public async Task TryRunCommand(SocketGuild guild, ITextChannel channel, IUserMessage usrMsg)
{
var execTime = Environment.TickCount;
if (guild != null && guild.OwnerId != usrMsg.Author.Id)
{ {
if (await InviteFiltered(guild, usrMsg).ConfigureAwait(false)) if (await InviteFiltered(guild, usrMsg).ConfigureAwait(false))
return; return;
@ -306,7 +323,7 @@ namespace NadekoBot.Services
if (cr.AutoDeleteTrigger) if (cr.AutoDeleteTrigger)
{ {
try { await msg.DeleteAsync().ConfigureAwait(false); } catch { } try { await usrMsg.DeleteAsync().ConfigureAwait(false); } catch { }
} }
} }
catch (Exception ex) catch (Exception ex)
@ -356,37 +373,24 @@ namespace NadekoBot.Services
if (guild != null && exec.CommandInfo != null && exec.Result.Error == CommandError.Exception) if (guild != null && exec.CommandInfo != null && exec.Result.Error == CommandError.Exception)
{ {
if (exec.PermissionCache != null && exec.PermissionCache.Verbose) if (exec.PermissionCache != null && exec.PermissionCache.Verbose)
try { await msg.Channel.SendMessageAsync("⚠️ " + exec.Result.ErrorReason).ConfigureAwait(false); } catch { } try { await usrMsg.Channel.SendMessageAsync("⚠️ " + exec.Result.ErrorReason).ConfigureAwait(false); } catch { }
} }
} }
else else
{ {
if (msg.Channel is IPrivateChannel) if (usrMsg.Channel is IPrivateChannel)
{ {
// rofl, gotta do this to prevent dm help message being sent to // rofl, gotta do this to prevent dm help message being sent to
// users who are voting on private polls (sending a number in a DM) // users who are voting on private polls (sending a number in a DM)
int vote; int vote;
if (int.TryParse(msg.Content, out vote)) return; if (int.TryParse(usrMsg.Content, out vote)) return;
await msg.Channel.SendMessageAsync(Help.DMHelpString).ConfigureAwait(false); await usrMsg.Channel.SendMessageAsync(Help.DMHelpString).ConfigureAwait(false);
await SelfCommands.HandleDmForwarding(msg, ownerChannels).ConfigureAwait(false); await SelfCommands.HandleDmForwarding(usrMsg, ownerChannels).ConfigureAwait(false);
} }
} }
} }
catch (Exception ex)
{
_log.Warn("Error in CommandHandler");
_log.Warn(ex);
if (ex.InnerException != null)
{
_log.Warn("Inner Exception of the error in CommandHandler");
_log.Warn(ex.InnerException);
}
}
});
return Task.CompletedTask;
}
public Task<ExecuteCommandResult> ExecuteCommandAsync(CommandContext context, int argPos, IDependencyMap dependencyMap = null, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception) public Task<ExecuteCommandResult> ExecuteCommandAsync(CommandContext context, int argPos, IDependencyMap dependencyMap = null, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
=> ExecuteCommand(context, context.Message.Content.Substring(argPos), dependencyMap, multiMatchHandling); => ExecuteCommand(context, context.Message.Content.Substring(argPos), dependencyMap, multiMatchHandling);

View File

@ -23,6 +23,7 @@ namespace NadekoBot.Services.Database
IPokeGameRepository PokeGame { get; } IPokeGameRepository PokeGame { get; }
IWaifuRepository Waifus { get; } IWaifuRepository Waifus { get; }
IDiscordUserRepository DiscordUsers { get; } IDiscordUserRepository DiscordUsers { get; }
IWarningsRepository Warnings { get; }
int Complete(); int Complete();
Task<int> CompleteAsync(); Task<int> CompleteAsync();

View File

@ -31,6 +31,7 @@ namespace NadekoBot.Services.Database.Models
Mute, Mute,
Kick, Kick,
Ban, Ban,
Softban
} }
public class AntiSpamIgnore : DbEntity public class AntiSpamIgnore : DbEntity

View File

@ -61,6 +61,19 @@ Nadeko Support Server: https://discord.gg/nadekobot";
public string OkColor { get; set; } = "71cd40"; public string OkColor { get; set; } = "71cd40";
public string ErrorColor { get; set; } = "ee281f"; public string ErrorColor { get; set; } = "ee281f";
public string Locale { get; set; } = null; public string Locale { get; set; } = null;
public List<StartupCommand> StartupCommands { get; set; }
}
public class StartupCommand : DbEntity, IIndexed
{
public int Index { get; set; }
public string CommandText { get; set; }
public ulong ChannelId { get; set; }
public string ChannelName { get; set; }
public ulong? GuildId { get; set; }
public string GuildName { get; set; }
public ulong? VoiceChannelId { get; set; }
public string VoiceChannelName { get; set; }
} }
public class PlayingStatus :DbEntity public class PlayingStatus :DbEntity

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using static NadekoBot.Modules.Administration.Administration;
namespace NadekoBot.Services.Database.Models namespace NadekoBot.Services.Database.Models
{ {
@ -72,10 +71,65 @@ namespace NadekoBot.Services.Database.Models
public HashSet<UnmuteTimer> UnmuteTimers { get; set; } = new HashSet<UnmuteTimer>(); public HashSet<UnmuteTimer> UnmuteTimers { get; set; } = new HashSet<UnmuteTimer>();
public HashSet<VcRoleInfo> VcRoleInfos { get; set; } public HashSet<VcRoleInfo> VcRoleInfos { get; set; }
public HashSet<CommandAlias> CommandAliases { get; set; } = new HashSet<CommandAlias>(); public HashSet<CommandAlias> CommandAliases { get; set; } = new HashSet<CommandAlias>();
public List<WarningPunishment> WarnPunishments { get; set; } = new List<WarningPunishment>();
public bool WarningsInitialized { get; set; }
public HashSet<SlowmodeIgnoredUser> SlowmodeIgnoredUsers { get; set; }
public HashSet<SlowmodeIgnoredRole> SlowmodeIgnoredRoles { get; set; }
//public List<ProtectionIgnoredChannel> ProtectionIgnoredChannels { get; set; } = new List<ProtectionIgnoredChannel>(); //public List<ProtectionIgnoredChannel> ProtectionIgnoredChannels { get; set; } = new List<ProtectionIgnoredChannel>();
} }
public class SlowmodeIgnoredUser : DbEntity
{
public ulong UserId { get; set; }
// override object.Equals
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
return ((SlowmodeIgnoredUser)obj).UserId == UserId;
}
// override object.GetHashCode
public override int GetHashCode()
{
return UserId.GetHashCode();
}
}
public class SlowmodeIgnoredRole : DbEntity
{
public ulong RoleId { get; set; }
// override object.Equals
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
return ((SlowmodeIgnoredRole)obj).RoleId == RoleId;
}
// override object.GetHashCode
public override int GetHashCode()
{
return RoleId.GetHashCode();
}
}
public class WarningPunishment : DbEntity
{
public int Count { get; set; }
public PunishmentAction Punishment { get; set; }
public int Time { get; set; }
}
public class CommandAlias : DbEntity public class CommandAlias : DbEntity
{ {
public string Trigger { get; set; } public string Trigger { get; set; }

View File

@ -0,0 +1,11 @@
using System;
namespace NadekoBot.Services.Database.Models
{
public class RewardedUser : DbEntity
{
public ulong UserId { get; set; }
public int AmountRewardedThisMonth { get; set; }
public DateTime LastReward { get; set; }
}
}

View File

@ -0,0 +1,12 @@
namespace NadekoBot.Services.Database.Models
{
public class Warning : DbEntity
{
public ulong GuildId { get; set; }
public ulong UserId { get; set; }
public string Reason { get; set; }
public bool Forgiven { get; set; }
public string ForgivenBy { get; set; }
public string Moderator { get; set; }
}
}

View File

@ -40,6 +40,7 @@ namespace NadekoBot.Services.Database
public DbSet<CurrencyTransaction> CurrencyTransactions { get; set; } public DbSet<CurrencyTransaction> CurrencyTransactions { get; set; }
public DbSet<UserPokeTypes> PokeGame { get; set; } public DbSet<UserPokeTypes> PokeGame { get; set; }
public DbSet<WaifuUpdate> WaifuUpdates { get; set; } public DbSet<WaifuUpdate> WaifuUpdates { get; set; }
public DbSet<Warning> Warnings { get; set; }
//logging //logging
public DbSet<LogSetting> LogSettings { get; set; } public DbSet<LogSetting> LogSettings { get; set; }
@ -50,6 +51,7 @@ namespace NadekoBot.Services.Database
public DbSet<EightBallResponse> EightBallResponses { get; set; } public DbSet<EightBallResponse> EightBallResponses { get; set; }
public DbSet<RaceAnimal> RaceAnimals { get; set; } public DbSet<RaceAnimal> RaceAnimals { get; set; }
public DbSet<ModulePrefix> ModulePrefixes { get; set; } public DbSet<ModulePrefix> ModulePrefixes { get; set; }
public DbSet<RewardedUser> RewardedUsers { get; set; }
public NadekoContext() : base() public NadekoContext() : base()
{ {
@ -272,6 +274,16 @@ namespace NadekoBot.Services.Database
du.HasAlternateKey(w => w.UserId); du.HasAlternateKey(w => w.UserId);
#endregion #endregion
#region Warnings
var warn = modelBuilder.Entity<Warning>();
#endregion
#region PatreonRewards
var pr = modelBuilder.Entity<RewardedUser>();
pr.HasIndex(x => x.UserId)
.IsUnique();
#endregion
} }
} }
} }

View File

@ -1,9 +1,12 @@
using NadekoBot.Services.Database.Models; using Microsoft.EntityFrameworkCore;
using NadekoBot.Services.Database.Models;
using System;
using System.Linq;
namespace NadekoBot.Services.Database.Repositories namespace NadekoBot.Services.Database.Repositories
{ {
public interface IBotConfigRepository : IRepository<BotConfig> public interface IBotConfigRepository : IRepository<BotConfig>
{ {
BotConfig GetOrCreate(); BotConfig GetOrCreate(Func<DbSet<BotConfig>, IQueryable<BotConfig>> includes = null);
} }
} }

View File

@ -0,0 +1,11 @@
using NadekoBot.Services.Database.Models;
using System.Threading.Tasks;
namespace NadekoBot.Services.Database.Repositories
{
public interface IWarningsRepository : IRepository<Warning>
{
Warning[] For(ulong guildId, ulong userId);
Task ForgiveAll(ulong guildId, ulong userId, string mod);
}
}

View File

@ -1,6 +1,7 @@
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System.Linq; using System.Linq;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using System;
namespace NadekoBot.Services.Database.Repositories.Impl namespace NadekoBot.Services.Database.Repositories.Impl
{ {
@ -10,15 +11,21 @@ namespace NadekoBot.Services.Database.Repositories.Impl
{ {
} }
public BotConfig GetOrCreate() public BotConfig GetOrCreate(Func<DbSet<BotConfig>, IQueryable<BotConfig>> includes = null)
{ {
var config = _set.Include(bc => bc.RotatingStatusMessages) BotConfig config;
if (includes == null)
config = _set.Include(bc => bc.RotatingStatusMessages)
.Include(bc => bc.RaceAnimals) .Include(bc => bc.RaceAnimals)
.Include(bc => bc.Blacklist) .Include(bc => bc.Blacklist)
.Include(bc => bc.EightBallResponses) .Include(bc => bc.EightBallResponses)
.Include(bc => bc.ModulePrefixes) .Include(bc => bc.ModulePrefixes)
.Include(bc => bc.StartupCommands)
//.Include(bc => bc.CommandCosts) //.Include(bc => bc.CommandCosts)
.FirstOrDefault(); .FirstOrDefault();
else
config = includes(_set).FirstOrDefault();
if (config == null) if (config == null)
{ {

View File

@ -12,6 +12,18 @@ namespace NadekoBot.Services.Database.Repositories.Impl
{ {
} }
private List<WarningPunishment> DefaultWarnPunishments =>
new List<WarningPunishment>() {
new WarningPunishment() {
Count = 3,
Punishment = PunishmentAction.Kick
},
new WarningPunishment() {
Count = 5,
Punishment = PunishmentAction.Ban
}
};
public IEnumerable<GuildConfig> GetAllGuildConfigs() => public IEnumerable<GuildConfig> GetAllGuildConfigs() =>
_set.Include(gc => gc.LogSetting) _set.Include(gc => gc.LogSetting)
.ThenInclude(ls => ls.IgnoredChannels) .ThenInclude(ls => ls.IgnoredChannels)
@ -26,6 +38,8 @@ namespace NadekoBot.Services.Database.Repositories.Impl
.Include(gc => gc.CommandCooldowns) .Include(gc => gc.CommandCooldowns)
.Include(gc => gc.GuildRepeaters) .Include(gc => gc.GuildRepeaters)
.Include(gc => gc.AntiRaidSetting) .Include(gc => gc.AntiRaidSetting)
.Include(gc => gc.SlowmodeIgnoredRoles)
.Include(gc => gc.SlowmodeIgnoredUsers)
.Include(gc => gc.AntiSpamSetting) .Include(gc => gc.AntiSpamSetting)
.ThenInclude(x => x.IgnoredChannels) .ThenInclude(x => x.IgnoredChannels)
.ToList(); .ToList();
@ -64,10 +78,19 @@ namespace NadekoBot.Services.Database.Repositories.Impl
_set.Add((config = new GuildConfig _set.Add((config = new GuildConfig
{ {
GuildId = guildId, GuildId = guildId,
Permissions = Permissionv2.GetDefaultPermlist Permissions = Permissionv2.GetDefaultPermlist,
WarningsInitialized = true,
WarnPunishments = DefaultWarnPunishments,
})); }));
_context.SaveChanges(); _context.SaveChanges();
} }
if (!config.WarningsInitialized)
{
config.WarningsInitialized = true;
config.WarnPunishments = DefaultWarnPunishments;
}
return config; return config;
} }
@ -82,10 +105,18 @@ namespace NadekoBot.Services.Database.Repositories.Impl
_set.Add((config = new GuildConfig _set.Add((config = new GuildConfig
{ {
GuildId = guildId, GuildId = guildId,
Permissions = Permissionv2.GetDefaultPermlist Permissions = Permissionv2.GetDefaultPermlist,
WarningsInitialized = true,
WarnPunishments = DefaultWarnPunishments,
})); }));
_context.SaveChanges(); _context.SaveChanges();
} }
if (!config.WarningsInitialized)
{
config.WarningsInitialized = true;
config.WarnPunishments = DefaultWarnPunishments;
}
return config; return config;
} }

View File

@ -0,0 +1,37 @@
using NadekoBot.Services.Database.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace NadekoBot.Services.Database.Repositories.Impl
{
public class WarningsRepository : Repository<Warning>, IWarningsRepository
{
public WarningsRepository(DbContext context) : base(context)
{
}
public Warning[] For(ulong guildId, ulong userId)
{
var query = _set.Where(x => x.GuildId == guildId && x.UserId == userId)
.OrderByDescending(x => x.DateAdded);
return query.ToArray();
}
public async Task ForgiveAll(ulong guildId, ulong userId, string mod)
{
await _set.Where(x => x.GuildId == guildId && x.UserId == userId)
.ForEachAsync(x =>
{
if (x.Forgiven != true)
{
x.Forgiven = true;
x.ForgivenBy = mod;
}
})
.ConfigureAwait(false);
}
}
}

View File

@ -54,6 +54,9 @@ namespace NadekoBot.Services.Database
private IDiscordUserRepository _discordUsers; private IDiscordUserRepository _discordUsers;
public IDiscordUserRepository DiscordUsers => _discordUsers ?? (_discordUsers = new DiscordUserRepository(_context)); public IDiscordUserRepository DiscordUsers => _discordUsers ?? (_discordUsers = new DiscordUserRepository(_context));
private IWarningsRepository _warnings;
public IWarningsRepository Warnings => _warnings ?? (_warnings = new WarningsRepository(_context));
public UnitOfWork(NadekoContext context) public UnitOfWork(NadekoContext context)
{ {
_context = context; _context = context;

View File

@ -16,7 +16,7 @@ namespace NadekoBot.Services.Impl
private readonly DiscordShardedClient _client; private readonly DiscordShardedClient _client;
private readonly DateTime _started; private readonly DateTime _started;
public const string BotVersion = "1.26"; public const string BotVersion = "1.26a";
public string Author => "Kwoth#2560"; public string Author => "Kwoth#2560";
public string Library => "Discord.Net"; public string Library => "Discord.Net";

View File

@ -3023,7 +3023,7 @@
"ImageUrl": "https://www.randomlists.com/img/things/tv.jpg" "ImageUrl": "https://www.randomlists.com/img/things/tv.jpg"
}, },
{ {
"Word": "twezzers", "Word": "tweezers",
"ImageUrl": "https://www.randomlists.com/img/things/twezzers.jpg" "ImageUrl": "https://www.randomlists.com/img/things/twezzers.jpg"
}, },
{ {

View File

@ -1,361 +0,0 @@
[
{
"Title":"The Gender of Psychology",
"Text":"This book addresses the diversity of psychological knowledge and practice through the lens of gender."
},
{
"Title":"Unto Others: The Evolution and Psychology of Unselfish",
"Text":"In Unto Others philosopher Elliott Sober and biologist David Sloan Wilson demonstrate once and for all that unselfish behavior is in fact an important feature of both biological and human nature."
},
{
"Title":"Forensic and Legal Psychology",
"Text":"Using research in clinical, cognitive, developmental, and social psychology, Forensic and Legal Psychology shows how psychological science can enhance the gathering and presentation of evidence, improve legal decision-making, prevent crime,"
},
{
"Title":"International Handbook of Psychology in Education",
"Text":"Suitable for researchers, practitioners and advisers working in the fields of psychology and education, this title presents an overview of the research within the domain of psychology of education."
},
{
"Title":"Handbook of Personality Psychology",
"Text":"This comprehensive reference work on personality psychology discusses the development and measurement of personality, biological and social determinants, dynamic personality processes, the personality's relation to the self, and personality"
},
{
"Title":"Dictionary of Theories, Laws, and Concepts in Psychology",
"Text":"A fully cross-referenced and source-referenced dictionary which gives definitions of psychological terms as well as the history, critique, and relevant references for the terms."
},
{
"Title":"Essays on Plato's Psychology",
"Text":"With a comprehensive introduction to the major issues of Plato's psychology and an up-to-date bibliography of work on the relevant issues, this much-needed text makes the study of Plato's psychology accessible to scholars in ancient Greek"
},
{
"Title":"Psychology Statistics For Dummies",
"Text":"As an alternative to typical, lead-heavy statistics texts or supplements to assigned course reading, this is one book psychology students won't want to be without."
},
{
"Title":"Doing Psychology Experiments",
"Text":"David W. Martin’s unique blend of informality, humor, clear instruction, and solid scholarship make this concise text a popular choice for research methods courses in psychology."
},
{
"Title":"A Handbook of Research Methods for Clinical and Health",
"Text":"For both undergraduate and postgraduate students, the book will be essential in making them aware of the full range of techniques available to them, helping them to design scientifically rigorous experiments."
},
{
"Title":"A History of Psychology",
"Text":"First published in 2002. Routledge is an imprint of Taylor & Francis, an informa company."
},
{
"Title":"An Introduction to the Psychology of Religion",
"Text":"The third edition of this successful book, which applies the science of psychology to problems of religion. Dr Thouless explores such questions as: why do people believe? Why are their beliefs often held with irrational strength?"
},
{
"Title":"Psychology of Champions: How to Win at Sports and Life",
"Text":"In this unprecedented book, two psychologist researchers interview sports legends and super-athletes across sports to explain the thinking that powers stellar performers, pushing them to amazing and historic successes."
},
{
"Title":"The Psychology of Humor: An Integrative Approach",
"Text":"This is a singly authored monograph that provides in one source, a summary of information researchers might wish to know about research into the psychology of humor."
},
{
"Title":"Psychology and Deterrence",
"Text":"Now available in paperback, Psychology and Deterrence reveals deterrence strategy's hidden and generally simplistic assumptions about the nature of power and aggression, threat and response, and calculation and behavior in the international"
},
{
"Title":"Psychology: An International Perspective",
"Text":"Unlike typical American texts, this book provides an international approach to introductory psychology, providing comprehensive and lively coverage of current research from a global perspective, including the UK, Germany, Scandinavia,"
},
{
"Title":"Psychology, Briefer Course",
"Text":"Despite its title, 'Psychology: Briefer Course' is more than a simple condensation of the great 'Principles of Psychology."
},
{
"Title":"Psychology, Seventh Edition (High School)",
"Text":"This new edition continues the story of psychology with added research and enhanced content from the most dynamic areas of the field—cognition, gender and diversity studies, neuroscience and more, while at the same time using the most"
},
{
"Title":"Psychology of Russia: Past, Present, Future",
"Text":"This book is for all psychologists and for readers whose interest in Russia exceeds their interest in psychology. Readers of this book will quickly discover a new world of thought."
},
{
"Title":"Barron's AP Psychology",
"Text":"Provides information on scoring and structure of the test, offers tips on test-taking strategies, and includes practice examinations and subject review."
},
{
"Title":"Psychology for Inclusive Education: New Directions in",
"Text":"International in focus and at the very cutting edge of the field, this is essential reading for all those interested in the development of inclusive education."
},
{
"Title":"Applied Psychology: Putting Theory Into Practice",
"Text":"Applied Psychology: Putting theory into practice demonstrates how psychology theory is applied in the real world."
},
{
"Title":"The Psychology of Science: A Reconnaissance",
"Text":"' This eBook edition contains the complete 168 page text of the original 1966 hardcover edition. Contents: Preface by Abraham H. Maslow Acknowledgments 1. Mechanistic and Humanistic Science 2."
},
{
"Title":"Filipino American Psychology: A Handbook of Theory,",
"Text":"This book is the first of its kind and aims to promote visibility of this invisible group, so that 2.4 million Filipino Americans will have their voices heard."
},
{
"Title":"The Psychology of Visual Illusion",
"Text":"Well-rounded perspective on the ambiguities of visual display emphasizes geometrical optical illusions: framing and contrast effects, distortion of angles and direction, and apparent 'movement' of images. 240 drawings. 1972 edition."
},
{
"Title":"The Psychology of Women",
"Text":"This highly respected text offers students an enjoyable, extraordinarily well-written introduction to the psychology of women with an up-to-date examination of the field and comprehensive coverage of topics."
},
{
"Title":"Psychology and Race",
"Text":"' Psychology and Race is divided into two major parts. The first half of the book looks at the interracial situation itself."
},
{
"Title":"Psychology for A-Level",
"Text":"'Precisely targeted at AQA A Level Psychology, specification A. It will also be of interest to those who are new to psychology, and who want to get a flavour of the kinds of topics in which psychologists are interested'--Preface, p. vii."
},
{
"Title":"Biological Psychology",
"Text":"Updated with new topics, examples, and recent research findings--and supported by new online bio-labs, part of the strongest media package yet--this text speaks to today’s students and instructors."
},
{
"Title":"Psychology: Concepts & Connections",
"Text":"The theme of this book is applying theories and research to learning and to contemporary life."
},
{
"Title":"The Psychology of Adoption",
"Text":"In this volume David Brodzinsky, who has conducted one of the nation's largest studies of adopted children, and Marshall Schechter, a noted child psychiatrist who has been involved with adoption related issues for over forty years, have"
},
{
"Title":"Psychology and Adult Learning",
"Text":"This new edition is thoroughly revised and updated in light of the impact of globalising processes and the application of new information technologies, and the influence of postmodernism on psychology."
},
{
"Title":"Gestalt Psychology: An Introduction to New Concepts in",
"Text":"The general reader, if he looks to psychology for something more than entertainment or practical advice, will discover in this book a storehouse of searching criticism and brilliant suggestions from the pen of a rare thinker, and one who"
},
{
"Title":"The Psychology of Goals",
"Text":"Bringing together leading authorities, this tightly edited volume reviews the breadth of current knowledge about goals and their key role in human behavior."
},
{
"Title":"Metaphors in the History of Psychology",
"Text":"Through the identification of these metaphors, the contributors to this volume have provided a remarkably useful guide to the history, current orientations, and future prospects of modern psychology."
},
{
"Title":"Abnormal Psychology: An Integrative Approach",
"Text":"ABNORMAL PSYCHOLOGY: AN INTEGRATIVE APPROACH, Seventh Edition, is the perfect book to help you succeed in your abnormal psychology course!"
},
{
"Title":"Art and Visual Perception: A Psychology of the Creative Eye",
"Text":"Gestalt theory and the psychology of visual perception form the basis for an analysis of art and its basic elements"
},
{
"Title":"Psychology & Christianity: Five Views",
"Text":"This revised edition of a widely appreciated text now presents five models for understanding the relationship between psychology and Christianity."
},
{
"Title":"The Psychology of Hope: You Can Get There from Here",
"Text":"Why do some people lead positive, hope-filled lives, while others wallow in pessimism? In The Psychology of Hope, a professor of psychology reveals the specific character traits that produce highly hopeful individuals."
},
{
"Title":"Perspectives on Psychology",
"Text":"This is a title in the modular 'Principles in Psychology Series', designed for A-level and other introductory courses, aiming to provide students embarking on psychology courses with the necessary background and context."
},
{
"Title":"Psychology the Easy Way",
"Text":"Material is presented in a way that makes these books ideal as self-teaching guides, but Easy Way titles are also preferred by many teachers as supplements to classroom textbooks."
},
{
"Title":"Ethics in Psychology: Professional Standards and Cases",
"Text":"In this book, their main intent is to present the full range of contemporary ethical issues in psychology as not only relevant and intriguing, but also as integral and unavoidable aspects of the profession."
},
{
"Title":"Psychology Gets in the Game: Sport, Mind, and Behavior,",
"Text":"The essays collected in this volume tell the stories not only of these psychologists and their subjects but of the social and academic context that surrounded them, shaping and being shaped by their ideas'--Provided by publisher."
},
{
"Title":"Psychology for Physical Educators: Student in Focus",
"Text":"This updated edition focuses on attitude and motivation as important aspects of the physical education curriculum, illustrating practical ideas and pedagogical solutions for any PE setting."
},
{
"Title":"The Psychology of Leadership: New Perspectives and Research",
"Text":"In this book, some of the world's leading scholars come together to describe their thinking and research on the topic of the psychology of leadership."
},
{
"Title":"The Psychology of Interpersonal Relations",
"Text":"As the title suggests, this book examines the psychology of interpersonal relations. In the context of this book, the term 'interpersonal relations' denotes relations between a few, usually between two, people."
},
{
"Title":"Applied Psychology",
"Text":"The chapters on Counselling Psychology and Teaching Psychology are available online via the Student Companion Site at: http://tinyurl.com/c3ztvtj The text is written to be accessible to Level 1 Introductory Psychology students, and also to"
},
{
"Title":"Psychology",
"Text":"An exciting read for anyone interested in psychology and research; because of its comprehensive appendix, glossary, and reference section, this book is a must-have desk reference for psychologists and others in the field."
},
{
"Title":"The Psychology of Music",
"Text":"On interpreting musical phenomena in terms of mental function"
},
{
"Title":"Abnormal Psychology",
"Text":"Ron Comer's Abnormal Psychology continues to captivate students with its integrated coverage of theory, diagnosis, and treatment, its inclusive wide-ranging cross-cultural perspective, and its compassionate emphasis on the real impact of"
},
{
"Title":"The Psychology of Food Choice",
"Text":"This book brings together theory, research and applications from psychology and behavioural sciences applied to dietary behaviour."
},
{
"Title":"Psychology: brain, behavior, & culture",
"Text":"Rather than present psychological science as a series of facts for memorization, this book takes readers on a psychological journey that uncovers things they didn't know or new ways of thinking about things they did know."
},
{
"Title":"A Brief History of Psychology",
"Text":"Due to its brevity and engaging style, the book is often used in introductory courses to introduce students to the field. The enormous index and substantial glossary make this volume a useful desk reference for the entire field."
},
{
"Title":"Psychology AS: The Complete Companion",
"Text":"Presented in double-page spreads this book written to the average AS ability level, provides information on psychology in bite-sized chunks with learning and revision features."
},
{
"Title":"The Psychology Book: From Shamanism to Cutting-Edge",
"Text":"Lavishly illustrated, this new addition in the Sterling's Milestones series chronicles the history of psychology through 250 groundbreaking events, theories, publications, experiments and discoveries."
},
{
"Title":"The Psychology Book",
"Text":"All the big ideas, simply explained - an innovative and accessible guide to the study of human nature The Psychology Book clearly explains more than 100 groundbreaking ideas in this fascinating field of science."
},
{
"Title":"Handbook of Positive Psychology",
"Text":"' The Handbook of Positive Psychology provides a forum for a more positive view of the human condition. In its pages, readers are treated to an analysis of what the foremost experts believe to be the fundamental strengths of humankind."
},
{
"Title":"Psychology of Sustainable Development",
"Text":"With contributions from an international team of policy shapers and makers, the book will be an important reference for environmental, developmental, social, and organizational psychologists, in addition to other social scientists concerned"
},
{
"Title":"An Introduction to the History of Psychology",
"Text":"In this Fifth Edition, B.R. Hergenhahn demonstrates that most of the concerns of contemporary psychologists are manifestations of themes that have been part of psychology for hundreds-or even thousands-of years."
},
{
"Title":"Careers in Psychology: Opportunities in a Changing World",
"Text":"This text addresses the growing need among students and faculty for information about the careers available in psychology at the bachelors and graduate level."
},
{
"Title":"Philosophy of Psychology",
"Text":"This is the story of the clattering of elevated subways and the cacophony of crowded neighborhoods, the heady optimism of industrial progress and the despair of economic recession, and the vibrancy of ethnic cultures and the resilience of"
},
{
"Title":"The Psychology of Risk Taking Behavior",
"Text":"This book aims to help the reader to understand what motivates people to engage in risk taking behavior, such as participating in traffic, sports, financial investments, or courtship."
},
{
"Title":"The Nazi Doctors: Medical Killing and the Psychology of",
"Text":"This book explores the psychological conditions that promote the human potential for evil, relating medical killing to broader principles of doubling and genocide"
},
{
"Title":"The Body and Psychology",
"Text":"The material in this volume was previously published as a Special Issue of th"
},
{
"Title":"Introduction to Psychology: Gateways to Mind and Behavior",
"Text":"Important Notice: Media content referenced within the product description or the product text may not be available in the ebook version."
},
{
"Title":"Psychology of Time",
"Text":"Basic Structure The book would contain 14 or 15 chapters of roughly 12 000 words. The exact final number of chapters would depend on further discussions with you about the book's basic structure."
},
{
"Title":"Handbook of Psychology, Experimental Psychology",
"Text":"Includes established theories and cutting-edge developments. Presents the work of an international group of experts. Presents the nature, origin, implications, and future course of major unresolved issues in the area."
},
{
"Title":"Study Guide for Psychology, Seventh Edition",
"Text":"This new edition continues the story of psychology with added research and enhanced content from the most dynamic areas of the field--cognition, gender and diversity studies, neuroscience and more, while at the same time using the most"
},
{
"Title":"Culture and Psychology",
"Text":"In addition, the text encourages students to question traditionally held beliefs and theories as and their relevance to different cultural groups today."
},
{
"Title":"Exploring the Psychology of Interest",
"Text":"The most comprehensive work of its kind, Exploring the Psychology of Interest will be a valuable resource for student and professional researchers in cognitive, social, and developmental psychology."
},
{
"Title":"Handbook of Adolescent Psychology",
"Text":"The study of adolescence in the field of psychology has grown tremendously over the last two decades, necessitating a comprehensive and up-to-date revision of this seminal work."
},
{
"Title":"The Psychology of Diplomacy",
"Text":"World class clinicians, researchers, and activists present the psychological dimensions to diplomacy drawn from examples set in the United Nations, Camp David, the Middle East, Japan, South Africa, and elsewhere."
},
{
"Title":"The Psychology of Social Class",
"Text":"By addressing differences in social class, the book broadens the perspective of social psychological research to examine such topics as the effect of achievement motivation and other personality variables on social mobility and the effect"
},
{
"Title":"Applied Psychology: Current Issues and New Directions",
"Text":"Key features of this book: - Consistently pedagogical throughout - chapter summaries, questions for reflection and discussion and annotated further reading in every chapter - Comprehensive coverage - all areas of applied psychology included"
},
{
"Title":"Popular Psychology: An Encyclopedia",
"Text":"Entries cover a variety of topics in the field of popular psychology, including acupuncture, emotional intelligence, brainwashing, chemical inbalance, and seasonal affective disorder."
},
{
"Title":"Advanced Psychology: Applications, Issues and Perspectives",
"Text":"The second of two books, Advanced Psychology covers units 4 to 6 for the second year at Advanced Level."
},
{
"Title":"Mindset: The New Psychology of Success",
"Text":"This is a book that can change your life, as its ideas have changed mine.”—Robert J. Sternberg, IBM Professor of Education and Psychology at Yale University, director of the PACE Center of Yale University, and author of Successful"
},
{
"Title":"E-Z Psychology",
"Text":"This book covers material as it is taught on a college-101 level."
},
{
"Title":"Myers' Psychology for AP*",
"Text":"Already The Bestselling AP* Psychology Author, Myers Writes His First Exclusive AP* Psych Text Watch Dave G. Myers introduce this new text here."
},
{
"Title":"Psychology and Health",
"Text":"Part of a series of textbooks which have been written to support A levels in psychology. The books use real life applications to make theories come alive for students and teach them what they need to know."
},
{
"Title":"Applying Psychology in Business: The Handbook for Managers",
"Text":"To learn more about Rowman & Littlefield titles please visit us at www.rowmanlittlefield.com."
},
{
"Title":"Influence",
"Text":"Influence, the classic book on persuasion, explains the psychology of why people say 'yes'—and how to apply these understandings. Dr. Robert Cialdini is the seminal expert in the rapidly expanding field of influence and persuasion."
},
{
"Title":"Psychology and Policing",
"Text":"The book should draw attention to the often unrecognized and valuable contribution that mainstream psychology can make to the knowledge base underpinning a wide variety of policing practices."
},
{
"Title":"Applied Psychology: New Frontiers and Rewarding Careers",
"Text":"This book examines how psychological science is, and can be, used to prevent and ameliorate pressing human problems to promote positive social change."
},
{
"Title":"Psychology: Concepts and Applications",
"Text":"Nevid developed the effective teaching devices in this text based on a comprehensive system derived from research on learning and memory as well as his own research on textbook pedagogy."
},
{
"Title":"Foundations of Sport and Exercise Psychology, 6E: ",
"Text":"This text offers both students and new practitioners a comprehensive view of sport and exercise psychology, drawing connections between research and practice and capturing the excitement of the world of sport and exercise."
},
{
"Title":"Biographical Dictionary of Psychology",
"Text":"This Dictionary provides biographical and bibliographical information on over 500 psychologists from all over the world from 1850 to the present day. All branches of psychology and its related disciplines are featured."
},
{
"Title":"Psychology: A Self-Teaching Guide",
"Text":"Frank Bruno explains all the major psychological theories and terms in this book, covering perception, motivation, thinking, personality, sensation, intelligence, research methods, and much more."
},
{
"Title":"A Dictionary of Psychology",
"Text":"Entries are extensively cross-referenced for ease of use, and cover word origins and derivations as well as definitions. Over 80 illustrations complement the text."
},
{
"Title":"An Intellectual History of Psychology",
"Text":"Invaluable as a text for students and as a stimulating and insightful overview for scholars and practicing psychologists, this volume can be read either as a history of psychology in both its philosophical and aspiring scientific periods or"
}]

File diff suppressed because one or more lines are too long