Merge pull request #1140 from Kwoth/dev

1.25
This commit is contained in:
Master Kwoth 2017-03-21 05:01:52 +01:00 committed by GitHub
commit 38f149c1e5
93 changed files with 29794 additions and 3639 deletions

View File

@ -1,4 +1,4 @@
You can support the project on patreon: <https://patreon.com/nadekobot> or paypal: <https://www.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)
@ -18,11 +18,11 @@ You can support the project on patreon: <https://patreon.com/nadekobot> or paypa
### Administration ### Administration
Command and aliases | Description | Usage Command and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`.resetperms` | Resets 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 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`
`.setrole` `.sr` | Sets a role for a given user. **Requires ManageRoles server permission.** | `.sr @User Guest` `.setrole` `.sr` | Sets a role for a given user. **Requires ManageRoles server permission.** | `.sr @User Guest`
`.removerole` `.rr` | Removes a role from a given user. **Requires ManageRoles server permission.** | `.rr @User Admin` `.removerole` `.rr` | Removes a role from a given user. **Requires ManageRoles server permission.** | `.rr @User Admin`
`.renamerole` `.renr` | Renames a role. Roles you are renaming must be lower than bot's highest role. **Requires ManageRoles server permission.** | `.renr "First role" SecondRole` `.renamerole` `.renr` | Renames a role. The role you are renaming must be lower than bot's highest role. **Requires ManageRoles server permission.** | `.renr "First role" SecondRole`
`.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`
@ -37,18 +37,19 @@ Command and aliases | Description | Usage
`.creatxtchanl` `.ctch` | Creates a new text channel with a given name. **Requires ManageChannels server permission.** | `.ctch TextChannelName` `.creatxtchanl` `.ctch` | Creates a new text channel with a given name. **Requires ManageChannels server permission.** | `.ctch TextChannelName`
`.settopic` `.st` | Sets a topic on the current channel. **Requires ManageChannels server permission.** | `.st My new topic` `.settopic` `.st` | Sets a topic on the current channel. **Requires ManageChannels server permission.** | `.st My new topic`
`.setchanlname` `.schn` | Changes the name of the current channel. **Requires ManageChannels server permission.** | `.schn NewName` `.setchanlname` `.schn` | Changes the name of the current channel. **Requires ManageChannels server permission.** | `.schn NewName`
`.prune` `.clr` | `.prune` removes all nadeko's messages in the last 100 messages.`.prune X` removes last X 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 '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 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 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
`.fwmsgs` | Toggles forwarding of non-command messages sent to bot's DM to the bot owners **Bot Owner only.** | `.fwmsgs` `.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`
`.fwtoall` | Toggles whether messages will be forwarded to all bot owners or only to the first one specified in the credentials.json **Bot Owner only.** | `.fwtoall` `.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`
`.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` `.languageslist` `.langli` | List of languages for which translation (or part of it) exist atm. | `.langli`
`.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` `.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`
`.logevents` | Shows a list of all events you can subscribe to with `.log` **Requires Administrator server permission.** **Bot Owner only.** | `.logevents` `.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`
`.log` | Toggles logging event. Disables it if it's active anywhere on the server. Enables if it's not active. Use `.logevents` to see a list of all events you can subscribe to. **Requires Administrator server permission.** **Bot Owner only.** | `.log userpresence` or `.log userbanned` `.logevents` | Shows a list of all events you can subscribe to with `.log` **Requires Administrator server permission.** **Bot Owner Only** | `.logevents`
`.migratedata` | Migrate data from old bot configuration **Bot Owner only.** | `.migratedata` `.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`
`.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. **Requires ManageRoles server permission.** **Requires MuteMembers server permission.** | `.mute @Someone`
`.unmute` | Unmutes a mentioned user previously muted with `.mute` command. **Requires ManageRoles server permission.** **Requires MuteMembers server permission.** | `.unmute @Someone` `.unmute` | Unmutes a mentioned user previously muted with `.mute` command. **Requires ManageRoles server permission.** **Requires MuteMembers server permission.** | `.unmute @Someone`
@ -56,51 +57,54 @@ Command and aliases | Description | Usage
`.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. **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`
`.antilist` `.antilst` | Shows currently enabled protection features. | `.antilist` `.antilist` `.antilst` | Shows currently enabled protection features. | `.antilist`
`.slowmode` | Toggles slowmode. Disable by specifying no parameters. To enable, specify a number of messages each user can send, and an interval in seconds. For example 1 message every 5 seconds. **Requires ManageMessages server permission.** | `.slowmode 1 5` or `.slowmode` `.slowmode` | Toggles slowmode. Disable by specifying no parameters. To enable, specify a number of messages each user can send, and an interval in seconds. For example 1 message every 5 seconds. **Requires ManageMessages server permission.** | `.slowmode 1 5` or `.slowmode`
`.adsarm` | Toggles the automatic deletion of confirmations for .iam and .iamn commands. **Requires ManageMessages server permission.** | `.adsarm` `.adsarm` | Toggles the automatic deletion of confirmations for `.iam` and `.iamn` commands. **Requires ManageMessages server permission.** | `.adsarm`
`.asar` | Adds a role to the list of self-assignable roles. **Requires ManageRoles server permission.** | `.asar Gamer` `.asar` | Adds a role to the list of self-assignable roles. **Requires ManageRoles server permission.** | `.asar Gamer`
`.rsar` | Removes a specified role from the list of self-assignable roles. **Requires ManageRoles server permission.** | `.rsar` `.rsar` | Removes a specified role from the list of self-assignable roles. **Requires ManageRoles server permission.** | `.rsar`
`.lsar` | Lists all self-assignable roles. | `.lsar` `.lsar` | Lists all self-assignable roles. | `.lsar`
`.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`
`.leave` | Makes Nadeko leave the server. Either name or id required. **Bot Owner only.** | `.leave 123123123331` `.fwmsgs` | Toggles forwarding of non-command messages sent to bot's DM to the bot owners **Bot Owner Only** | `.fwmsgs`
`.die` | Shuts the bot down. **Bot Owner only.** | `.die` `.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`
`.setname` `.newnm` | Gives the bot a new name. **Bot Owner only.** | `.newnm BotName` `.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`
`.setstatus` | Sets the bot's status. (Online/Idle/Dnd/Invisible) **Bot Owner only.** | `.setstatus Idle` `.leave` | Makes Nadeko leave the server. Either server name or server ID is required. **Bot Owner Only** | `.leave 123123123331`
`.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` `.die` | Shuts the bot down. **Bot Owner Only** | `.die`
`.setgame` | Sets the bots game. **Bot Owner only.** | `.setgame with snakes` `.setname` `.newnm` | Gives the bot a new name. **Bot Owner Only** | `.newnm BotName`
`.setstream` | Sets the bots stream. First argument is the twitch link, second argument is stream name. **Bot Owner only.** | `.setstream TWITCHLINK Hello` `.setstatus` | Sets the bot's status. (Online/Idle/Dnd/Invisible) **Bot Owner Only** | `.setstatus Idle`
`.send` | Sends a message to someone on a different server through the bot. Separate server and channel/user ids with `|` and prepend channel id with `c:` and user id with `u:`. **Bot Owner only.** | `.send serverid|c:channelid message` or `.send serverid|u:userid message` `.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`
`.announce` | Sends a message to all servers' general channel bot is connected to. **Bot Owner only.** | `.announce Useless spam` `.setgame` | Sets the bots game. **Bot Owner Only** | `.setgame with snakes`
`.reloadimages` | Reloads images bot is using. Safe to use even when bot is being used heavily. **Bot Owner only.** | `.reloadimages` `.setstream` | Sets the bots stream. First argument is the twitch link, second argument is stream name. **Bot Owner Only** | `.setstream TWITCHLINK Hello`
`.greetdel` `.grdel` | Sets the time it takes (in seconds) for greet messages to be auto-deleted. Set 0 to disable automatic deletion. **Requires ManageServer server permission.** | `.greetdel 0` or `.greetdel 30` `.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`
`.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. **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%.`
`.greetdm` | Toggles whether the greet messages will be sent in a DM (This is separate from greet - you can have both, any or neither enabled). **Requires ManageServer server permission.** | `.greetdm` `.greetdm` | Toggles whether the greet messages will be sent in a DM (This is separate from greet - you can have both, any or neither enabled). **Requires ManageServer server permission.** | `.greetdm`
`.greetdmmsg` | Sets a new join announcement message which will be sent to the user who joined. Type %user% if you want to mention the new member. Using it with no message will show the current DM greet message. **Requires ManageServer server permission.** | `.greetdmmsg Welcome to the server, %user%`. `.greetdmmsg` | Sets a new join announcement message which will be sent to the user who joined. Type `%user%` if you want to mention the new member. Using it with no message will show the current DM greet message. 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.** | `.greetdmmsg Welcome to the server, %user%`.
`.bye` | Toggles anouncements on the current channel when someone leaves the server. **Requires ManageServer server permission.** | `.bye` `.bye` | Toggles anouncements on the current channel when someone leaves the server. **Requires ManageServer server permission.** | `.bye`
`.byemsg` | Sets a new leave announcement message. Type %user% if you want to show the name the user who left. Type %id% to show id. Using this command with no message will show the current bye message. **Requires ManageServer server permission.** | `.byemsg %user% has left.` `.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 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`
`.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 Command and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`,createwar` `,cw` | Creates a new war by specifying a size (>10 and multiple of 5) and enemy clan name. | `,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`
`,listwar` `,lw` | Shows the active war claims by a number. Shows all wars in a short way if no number is specified. | `,lw [war_number] or ,lw` `,listwar` `,lw` | Shows the active war claims by a number. Shows all wars in a short way if no number is specified. | `,lw [war_number]` or `,lw`
`,claim` `,call` `,c` | Claims a certain base from a certain war. You can supply a name in the third optional argument to claim in someone else's place. | `,call [war_number] [base_number] [optional_other_name]` `,claim` `,call` `,c` | Claims a certain base from a certain war. You can supply a name in the third optional argument to claim in someone else's place. | `,call [war_number] [base_number] [optional_other_name]`
`,claimfinish1` `,cf1` | Finish your claim with 1 star if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. | `,cf1 1` or `,cf1 1 5` `,claimfinish1` `,cf1` | Finish your claim with 1 star if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. | `,cf1 1` or `,cf1 1 5`
`,claimfinish2` `,cf2` | Finish your claim with 2 stars if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. | `,cf2 1` or `,cf2 1 5` `,claimfinish2` `,cf2` | Finish your claim with 2 stars if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. | `,cf2 1` or `,cf2 1 5`
@ -108,20 +112,20 @@ Command and aliases | Description | Usage
`,endwar` `,ew` | Ends the war with a given index. | `,ew [war_number]` `,endwar` `,ew` | Ends the war with a given index. | `,ew [war_number]`
`,unclaim` `,ucall` `,uc` | Removes your claim from a certain war. Optional second argument denotes a person in whose place to unclaim | `,uc [war_number] [optional_other_name]` `,unclaim` `,ucall` `,uc` | Removes your claim from a certain war. Optional second argument denotes a person in whose place to unclaim | `,uc [war_number] [optional_other_name]`
###### [Back to TOC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
### CustomReactions ### CustomReactions
Command and aliases | Description | Usage Command and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`.addcustreact` `.acr` | Add a custom reaction with a trigger and a response. Running this command in server requires 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 priviledges and removes server custom reaction. | `.dcr 5` `.delcustreact` `.dcr` | Deletes a custom reaction on a specific index. If ran in DM, it is bot owner only and deletes a global custom reaction. If ran in a server, it requires Administration 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` `.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 Command and aliases | Description | Usage
@ -129,22 +133,22 @@ Command 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 - x3 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 bot 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`
`$draw` | Draws a card from the deck.If you supply number X, she draws up to 5 cards from the deck. | `$draw` or `$draw 5` `$draw` | Draws a card from the deck.If you supply number X, she draws up to 5 cards from the deck. | `$draw` or `$draw 5`
`$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 atleast 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`
@ -152,14 +156,15 @@ Command and aliases | Description | Usage
`$waifus` `$waifulb` | Shows top 9 waifus. | `$waifus` `$waifus` `$waifulb` | Shows top 9 waifus. | `$waifus`
`$waifuinfo` `$waifustats` | Shows waifu stats for a target person. Defaults to you if no user is provided. | `$waifuinfo @MyCrush` or `$waifuinfo` `$waifuinfo` `$waifustats` | Shows waifu stats for a target person. Defaults to you if no user is provided. | `$waifuinfo @MyCrush` or `$waifuinfo`
###### [Back to TOC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
### Games ### Games
Command and aliases | Description | Usage Command 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`
`>rps` | Play a game of rocket paperclip scissors with Nadeko. | `>rps scissors` `>rps` | Play a game of Rocket-Paperclip-Scissors with Nadeko. | `>rps scissors`
`>rategirl` | Use the universal hot-crazy wife zone matrix to determine the girl's worth. It is everything young men need to know about women. At any moment in time, any woman you have previously located on this chart can vanish from that location and appear anywhere else on the chart. | `>rategirl @SomeGurl`
`>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 argment is optional round length in seconds. (default is 60) | `>acro` or `>acro 30`
@ -175,26 +180,27 @@ 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`
`>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` `>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`
`>tl` | Shows a current trivia leaderboard. | `>tl` `>tl` | Shows a current trivia leaderboard. | `>tl`
`>tq` | Quits current trivia after current question. | `>tq` `>tq` | Quits current trivia after current question. | `>tq`
###### [Back to TOC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
### Help ### Help
Command and aliases | Description | Usage Command 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 full, or only 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 !!q` 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 Command and aliases | Description | Usage
@ -203,34 +209,34 @@ Command and aliases | Description | Usage
`!!stop` `!!s` | Stops the music and clears the playlist. Stays in the channel. | `!!s` `!!stop` `!!s` | Stops the music and clears the playlist. Stays in the channel. | `!!s`
`!!destroy` `!!d` | Completely stops the music and unbinds the bot from the channel. (may cause weird behaviour) | `!!d` `!!destroy` `!!d` | Completely stops the music and unbinds the bot from the channel. (may cause weird behaviour) | `!!d`
`!!pause` `!!p` | Pauses or Unpauses the song. | `!!p` `!!pause` `!!p` | Pauses or Unpauses the song. | `!!p`
`!!fairplay` `!!fp` | Toggles fairplay. While enabled, music player will prioritize songs from users who didn't have their song recently played instead of the song's position in the queue. | `!!fp` `!!fairplay` `!!fp` | Toggles fairplay. While enabled, the bot will prioritize songs from users who didn't have their song recently played instead of the song's position in the queue. | `!!fp`
`!!queue` `!!q` `!!yq` | Queue a song using keywords or a link. Bot will join your voice channel. **You must be in a voice channel**. | `!!q Dream Of Venice` `!!queue` `!!q` `!!yq` | Queue a song using keywords or a link. Bot will join your voice channel. **You must be in a voice channel**. | `!!q Dream Of Venice`
`!!soundcloudqueue` `!!sq` | Queue a soundcloud song using keywords. Bot will join your voice channel. **You must be in a voice channel**. | `!!sq Dream Of Venice` `!!soundcloudqueue` `!!sq` | Queue a soundcloud song using keywords. Bot will join your voice channel. **You must be in a voice channel**. | `!!sq Dream Of Venice`
`!!listqueue` `!!lq` | Lists 15 currently queued songs per page. Default page is 1. | `!!lq` or `!!lq 2` `!!listqueue` `!!lq` | Lists 15 currently queued songs per page. Default page is 1. | `!!lq` or `!!lq 2`
`!!nowplaying` `!!np` | Shows the song currently playing. | `!!np` `!!nowplaying` `!!np` | Shows the song that the bot is currently playing. | `!!np`
`!!volume` `!!vol` | Sets the music volume 0-100% | `!!vol 50` `!!volume` `!!vol` | Sets the music playback volume (0-100%) | `!!vol 50`
`!!defvol` `!!dv` | Sets the default music volume when music playback is started (0-100). Persists through restarts. | `!!dv 80` `!!defvol` `!!dv` | Sets the default music volume when music playback is started (0-100). Persists through restarts. | `!!dv 80`
`!!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`
`!!setmaxplaytime` `!!smp` | Sets a maximum number of seconds (>14) a song can run before being skipped automatically. Set 0 to have no limit. | `!!smp 0` or `!!smp 270` `!!setmaxplaytime` `!!smp` | Sets a maximum number of seconds (>14) a song can run before being skipped automatically. Set 0 to have no limit. | `!!smp 0` or `!!smp 270`
`!!reptcursong` `!!rcs` | Toggles repeat of current song. | `!!rcs` `!!reptcursong` `!!rcs` | Toggles repeat of current song. | `!!rcs`
`!!rpeatplaylst` `!!rpl` | Toggles repeat of all songs in the queue (every song that finishes is added to the end of the queue). | `!!rpl` `!!rpeatplaylst` `!!rpl` | Toggles repeat of all songs in the queue (every song that finishes is added to the end of the queue). | `!!rpl`
`!!save` | Saves a playlist under a certain name. Name must be no longer than 20 characters and mustn't contain dashes. | `!!save classical1` `!!save` | Saves a playlist under a certain name. Playlist name must be no longer than 20 characters and must not contain dashes. | `!!save classical1`
`!!load` | Loads a saved playlist using it's ID. Use `!!pls` to list all saved playlists and !!save to save new ones. | `!!load 5` `!!load` | Loads a saved playlist using its ID. Use `!!pls` to list all saved playlists and `!!save` to save new ones. | `!!load 5`
`!!playlists` `!!pls` | Lists all playlists. Paginated. 20 per page. Default page is 0. | `!!pls 1` `!!playlists` `!!pls` | Lists all playlists. Paginated, 20 per page. Default page is 0. | `!!pls 1`
`!!deleteplaylist` `!!delpls` | Deletes a saved playlist. Only if you made it or if you are the bot owner. | `!!delpls animu-5` `!!deleteplaylist` `!!delpls` | Deletes a saved playlist. Works only if you made it or if you are the bot owner. | `!!delpls animu-5`
`!!goto` | Goes to a specific time in seconds in a song. | `!!goto 30` `!!goto` | Goes to a specific time in seconds in a song. | `!!goto 30`
`!!autoplay` `!!ap` | Toggles autoplay - When the song is finished, automatically queue a related youtube song. (Works only for youtube songs and when queue is empty) | `!!ap` `!!autoplay` `!!ap` | Toggles autoplay - When the song is finished, automatically queue a related Youtube song. (Works only for Youtube songs and when queue is empty) | `!!ap`
`!!setmusicchannel` `!!smch` | Sets the current channel as the default music output channel. This will output playing, finished, paused and removed songs to that channel instead of the channel where the first song was queued in. **Requires ManageMessages server permission.** | `!!smch` `!!setmusicchannel` `!!smch` | Sets the current channel as the default music output channel. This will output playing, finished, paused and removed songs to that channel instead of the channel where the first song was queued in. **Requires ManageMessages server permission.** | `!!smch`
###### [Back to TOC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
### NSFW ### NSFW
Command and aliases | Description | Usage Command and aliases | Description | Usage
@ -240,24 +246,24 @@ Command and aliases | Description | Usage
`~hentaibomb` | Shows a total 5 images (from gelbooru, danbooru, konachan, yandere and atfbooru). Tag is optional but preferred. | `~hentaibomb yuri` `~hentaibomb` | Shows a total 5 images (from gelbooru, danbooru, konachan, yandere and atfbooru). Tag is optional but preferred. | `~hentaibomb yuri`
`~yandere` | Shows a random image from yandere with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~yandere tag1+tag2` `~yandere` | Shows a random image from yandere with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~yandere tag1+tag2`
`~konachan` | Shows a random hentai image from konachan with a given tag. Tag is optional but preferred. | `~konachan yuri` `~konachan` | Shows a random hentai image from konachan with a given tag. Tag is optional but preferred. | `~konachan yuri`
`~rule34` | Shows a random image from rule34.xx with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~rule34 yuri+kissing`
`~e621` | Shows a random hentai image from e621.net with a given tag. Tag is optional but preferred. Use spaces for multiple tags. | `~e621 yuri kissing` `~e621` | Shows a random hentai image from e621.net with a given tag. Tag is optional but preferred. Use spaces for multiple tags. | `~e621 yuri kissing`
`~rule34` | Shows a random image from rule34.xx with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~rule34 yuri+kissing`
`~danbooru` | Shows a random hentai image from danbooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~danbooru yuri+kissing` `~danbooru` | Shows a random hentai image from danbooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~danbooru yuri+kissing`
`~gelbooru` | Shows a random hentai image from gelbooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~gelbooru yuri+kissing` `~gelbooru` | Shows a random hentai image from gelbooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~gelbooru yuri+kissing`
`~cp` | We all know where this will lead you to. | `~cp` `~cp` | We all know where this will lead you to. | `~cp`
`~boobs` | Real adult content. | `~boobs` `~boobs` | Real adult content. | `~boobs`
`~butts` `~ass` `~butt` | Real adult content. | `~butts` or `~ass` `~butts` `~ass` `~butt` | Real adult content. | `~butts` or `~ass`
###### [Back to TOC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
### Permissions ### Permissions
Command and aliases | Description | Usage Command 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. Or supply no parameters to find out the current one. Default one 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`
`;listperms` `;lp` | Lists whole permission chain with their indexes. You can specify an optional page number if there are a lot of permissions. | `;lp` or `;lp 3` `;listperms` `;lp` | Lists whole permission chain with their indexes. You can specify an optional page number if there are a lot of permissions. | `;lp` or `;lp 3`
`;removeperm` `;rp` | Removes a permission from a given position in Permissions list. | `;rp 1` `;removeperm` `;rp` | Removes a permission from a given position in the Permissions list. | `;rp 1`
`;moveperm` `;mp` | Moves permission from one position to another in Permissions list. | `;mp 2 4` `;moveperm` `;mp` | Moves permission from one position to another in the Permissions list. | `;mp 2 4`
`;srvrcmd` `;sc` | Sets a command's permission at the server level. | `;sc "command name" disable` `;srvrcmd` `;sc` | Sets a command's permission at the server level. | `;sc "command name" disable`
`;srvrmdl` `;sm` | Sets a module's permission at the server level. | `;sm ModuleName enable` `;srvrmdl` `;sm` | Sets a module's permission at the server level. | `;sm ModuleName enable`
`;usrcmd` `;uc` | Sets a command's permission at the user level. | `;uc "command name" enable SomeUsername` `;usrcmd` `;uc` | Sets a command's permission at the user level. | `;uc "command name" enable SomeUsername`
@ -270,31 +276,30 @@ 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 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 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 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`
`;cmdcosts` | Shows a list of command costs. Paginated with 9 command per page. | `;cmdcosts` or `;cmdcosts 2` `;srvrfilterinv` `;sfi` | Toggles automatic deletion of invites posted in the server. Does not affect the Bot Owner. | `;sfi`
`;srvrfilterinv` `;sfi` | Toggles automatic deleting of invites posted in the server. Does not affect Bot Owner. | `;sfi` `;chnlfilterinv` `;cfi` | Toggles automatic deletion of invites posted in the channel. Does not negate the `;srvrfilterinv` enabled setting. Does not affect the Bot Owner. | `;cfi`
`;chnlfilterinv` `;cfi` | Toggles automatic deleting of invites posted in the channel. Does not negate the ;srvrfilterinv enabled setting. Does not affect Bot Owner. | `;cfi` `;srvrfilterwords` `;sfw` | Toggles automatic deletion of messages containing filtered words on the server. Does not affect the Bot Owner. | `;sfw`
`;srvrfilterwords` `;sfw` | Toggles automatic deleting of messages containing forbidden words on the server. Does not affect Bot Owner. | `;sfw` `;chnlfilterwords` `;cfw` | Toggles automatic deletion of messages containing filtered words on the channel. Does not negate the `;srvrfilterwords` enabled setting. Does not affect the Bot Owner. | `;cfw`
`;chnlfilterwords` `;cfw` | Toggles automatic deleting of messages containing banned words on the channel. Does not negate the ;srvrfilterwords enabled setting. Does not affect bot owner. | `;cfw`
`;fw` | Adds or removes (if it exists) a word from the list of filtered words. Use`;sfw` or `;cfw` to toggle filtering. | `;fw poop` `;fw` | Adds or removes (if it exists) a word from the list of filtered words. Use`;sfw` or `;cfw` to toggle filtering. | `;fw poop`
`;lstfilterwords` `;lfw` | Shows a list of filtered words. | `;lfw` `;lstfilterwords` `;lfw` | Shows a list of filtered words. | `;lfw`
###### [Back to TOC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
### Pokemon ### Pokemon
Command and aliases | Description | Usage Command and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`>attack` | Attacks a target with the given move. Use `>movelist` to see a list of moves your type can use. | `>attack "vine whip" @someguy` `>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`
`>heal` | Heals someone. Revives those who fainted. Costs a NadekoFlower | `>heal @someone` `>heal` | Heals someone. Revives those who fainted. Costs a NadekoFlower. | `>heal @someone`
`>type` | Get the poketype of the target. | `>type @someone` `>type` | Get the poketype of the target. | `>type @someone`
`>settype` | Set your poketype. Costs a NadekoFlower. Provide no arguments to see a list of available types. | `>settype fire` or `>settype` `>settype` | Set your poketype. Costs a NadekoFlower. Provide no arguments to see a list of available types. | `>settype fire` or `>settype`
###### [Back to TOC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
### Searches ### Searches
Command and aliases | Description | Usage Command and aliases | Description | Usage
@ -304,39 +309,37 @@ Command and aliases | Description | Usage
`~imdb` `~omdb` | Queries omdb for movies or series, show first result. | `~imdb Batman vs Superman` `~imdb` `~omdb` | Queries omdb for movies or series, show first result. | `~imdb Batman vs Superman`
`~randomcat` `~meow` | Shows a random cat image. | `~meow` `~randomcat` `~meow` | Shows a random cat image. | `~meow`
`~randomdog` `~woof` | Shows a random dog image. | `~woof` `~randomdog` `~woof` | Shows a random dog image. | `~woof`
`~image` `~img` | Pulls the first image found using a search parameter. Use ~rimg for different results. | `~img cute kitten` `~image` `~img` | Pulls the first image found using a search parameter. Use `~rimg` for different results. | `~img cute kitten`
`~randomimage` `~rimg` | Pulls a random image using a search parameter. | `~rimg cute kitten` `~randomimage` `~rimg` | Pulls a random image using a search parameter. | `~rimg cute kitten`
`~lmgtfy` | Google something for an idiot. | `~lmgtfy query` `~lmgtfy` | Google something for an idiot. | `~lmgtfy query`
`~shorten` | Attempts to shorten an URL, if it fails, returns the input URL. | `~shorten https://google.com` `~shorten` | Attempts to shorten an URL, if it fails, returns the input URL. | `~shorten https://google.com`
`~google` `~g` | Get a google search link for some terms. | `~google query` `~google` `~g` | Get a Google search link for some terms. | `~google query`
`~magicthegathering` `~mtg` | Searches for a Magic The Gathering card. | `~magicthegathering about face` or `~mtg about face` `~magicthegathering` `~mtg` | Searches for a Magic The Gathering card. | `~magicthegathering about face` or `~mtg about face`
`~hearthstone` `~hs` | Searches for a Hearthstone card and shows its image. Takes a while to complete. | `~hs Ysera` `~hearthstone` `~hs` | Searches for a Hearthstone card and shows its image. Takes a while to complete. | `~hs Ysera`
`~yodify` `~yoda` | Translates your normal sentences into Yoda styled sentences! | ~yodify I was once an adventurer like you` or `~yoda my feelings hurt` `~yodify` `~yoda` | Translates your normal sentences into Yoda styled sentences! | `~yoda my feelings hurt`
`~urbandict` `~ud` | Searches Urban Dictionary for a word. | `~ud Pineapple` `~urbandict` `~ud` | Searches Urban Dictionary for a word. | `~ud Pineapple`
`~define` `~def` | Finds a definition of a word. | `~def heresy` `~define` `~def` | Finds a definition of a word. | `~def heresy`
`~#` | Searches Tagdef.com for a hashtag. | `~# ff` `~#` | Searches Tagdef.com for a hashtag. | `~# ff`
`~catfact` | Shows a random catfact from <http://catfacts-api.appspot.com/api/facts> | `~catfact` `~catfact` | Shows a random catfact from <http://catfacts-api.appspot.com/api/facts> | `~catfact`
`~revav` | Returns a google reverse image search for someone's avatar. | `~revav "@SomeGuy"` `~revav` | Returns a Google reverse image search for someone's avatar. | `~revav "@SomeGuy"`
`~revimg` | Returns a google reverse image search for an image from a link. | `~revimg Image link` `~revimg` | Returns a Google reverse image search for an image from a link. | `~revimg Image link`
`~safebooru` | Shows a random image from safebooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~safebooru yuri+kissing` `~safebooru` | Shows a random image from safebooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~safebooru yuri+kissing`
`~wikipedia` `~wiki` | Gives you back a wikipedia link | `~wiki query` `~wikipedia` `~wiki` | Gives you back a wikipedia link | `~wiki query`
`~color` `~clr` | Shows you what color corresponds to that hex. | `~clr 00ff00` `~color` `~clr` | Shows you what color corresponds to that hex. | `~clr 00ff00`
`~videocall` | Creates a private <http://www.appear.in> video call link for you and other mentioned people. The link is sent to mentioned people via a private message. | `~videocall "@SomeGuy"` `~videocall` | Creates a private <http://www.appear.in> video call link for you and other mentioned people. The link is sent to mentioned people via a private message. | `~videocall "@SomeGuy"`
`~avatar` `~av` | Shows a mentioned person's avatar. | `~av "@SomeGuy"` `~avatar` `~av` | Shows a mentioned person's avatar. | `~av "@SomeGuy"`
`~wikia` | Gives you back a wikia link | `~wikia mtg Vigilance` or `~wikia mlp Dashy` `~wikia` | Gives you back a wikia link | `~wikia mtg Vigilance` or `~wikia mlp Dashy`
`~minecraftping` `~mcping` | Pings a minecraft server. | `~mcping 127.0.0.1:25565`
`~minecraftquery` `~mcq` | Finds information about a minecraft server. | `~mcq server:ip`
`~lolban` | Shows top banned champions ordered by ban rate. | `~lolban` `~lolban` | Shows top banned champions ordered by ban rate. | `~lolban`
`~memelist` | Pulls a list of memes you can use with `~memegen` from http://memegen.link/templates/ | `~memelist` `~mal` | Shows basic info from a MyAnimeList profile. | `~mal straysocks`
`~memegen` | Generates a meme from memelist with top and bottom text. | `~memegen biw "gets iced coffee" "in the winter"`
`~mal` | Shows basic info from myanimelist profile. | `~mal straysocks`
`~anime` `~ani` `~aq` | Queries anilist for an anime and shows the first result. | `~ani aquarion evol` `~anime` `~ani` `~aq` | Queries anilist for an anime and shows the first result. | `~ani aquarion evol`
`~manga` `~mang` `~mq` | Queries anilist for a manga and shows the first result. | `~mq Shingeki no kyojin` `~manga` `~mang` `~mq` | Queries anilist for a manga and shows the first result. | `~mq Shingeki no kyojin`
`~yomama` `~ym` | Shows a random joke from <http://api.yomomma.info/> | `~ym` `~yomama` `~ym` | Shows a random joke from <http://api.yomomma.info/> | `~ym`
`~randjoke` `~rj` | Shows a random joke from <http://tambal.azurewebsites.net/joke/random> | `~rj` `~randjoke` `~rj` | Shows a random joke from <http://tambal.azurewebsites.net/joke/random> | `~rj`
`~chucknorris` `~cn` | Shows a random chucknorris joke from <http://tambal.azurewebsites.net/joke/random> | `~cn` `~chucknorris` `~cn` | Shows a random Chuck Norris joke from <http://tambal.azurewebsites.net/joke/random> | `~cn`
`~wowjoke` | Get one of Kwoth's penultimate WoW jokes. | `~wowjoke` `~wowjoke` | Get one of Kwoth's penultimate WoW jokes. | `~wowjoke`
`~magicitem` `~mi` | Shows a random magic item from <https://1d4chan.org/wiki/List_of_/tg/%27s_magic_items> | `~mi` `~magicitem` `~mi` | Shows a random magic item from <https://1d4chan.org/wiki/List_of_/tg/%27s_magic_items> | `~mi`
`~memelist` | Pulls a list of memes you can use with `~memegen` from http://memegen.link/templates/ | `~memelist`
`~memegen` | Generates a meme from memelist with top and bottom text. | `~memegen biw "gets iced coffee" "in the winter"`
`~osu` | Shows osu stats for a player. | `~osu Name` or `~osu Name taiko` `~osu` | Shows osu stats for a player. | `~osu Name` or `~osu Name taiko`
`~osub` | Shows information about an osu beatmap. | `~osub https://osu.ppy.sh/s/127712` `~osub` | Shows information about an osu beatmap. | `~osub https://osu.ppy.sh/s/127712`
`~osu5` | Displays a user's top 5 plays. | `~osu5 Name` `~osu5` | Displays a user's top 5 plays. | `~osu5 Name`
@ -352,50 +355,53 @@ 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` | `~atl en>fr` | Sets your source and target language to be used with `~at`. Specify no arguments to remove previously set value. `~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`
###### [Back to TOC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
### Utility ### Utility
Command and aliases | Description | Usage Command 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 by a ',') on this server. If the list is too long for 1 message, you must have Manage Messages permission. | `.inrole Role` `.inrole` | Lists every person from the provided role or roles, separated 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`
`.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`
`.serverid` `.sid` | Shows current server ID. | `.sid` `.serverid` `.sid` | Shows current server ID. | `.sid`
`.roles` | List roles on this server or a roles of a specific user if specified. Paginated. 20 roles per page. | `.roles 2` or `.roles @Someone` `.roles` | List roles on this server or a roles of a specific user if specified. Paginated, 20 roles per page. | `.roles 2` or `.roles @Someone`
`.channeltopic` `.ct` | Sends current channel's topic as a message. | `.ct` `.channeltopic` `.ct` | Sends current channel's topic as a message. | `.ct`
`.createinvite` `.crinv` | Creates a new invite which has infinite max uses and never expires. **Requires CreateInstantInvite channel permission.** | `.crinv` `.createinvite` `.crinv` | Creates a new invite which has infinite max uses and never expires. **Requires CreateInstantInvite channel permission.** | `.crinv`
`.shardstats` | Stats for shards. Paginated with 25 shards per page. | `.shardstats` or `.shardstats 2`
`.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 .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` `.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 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`
`.channelinfo` `.cinfo` | Shows info about the channel. If no channel is supplied, it defaults to current one. | `.cinfo #some-channel` `.channelinfo` `.cinfo` | Shows info about the channel. If no channel is supplied, it defaults to current one. | `.cinfo #some-channel`
`.userinfo` `.uinfo` | Shows info about the user. If no user is supplied, it defaults a user running the command. | `.uinfo @SomeUser` `.userinfo` `.uinfo` | Shows info about the user. If no user is supplied, it defaults a user running the command. | `.uinfo @SomeUser`
`.repeatinvoke` `.repinv` | Immediately shows the repeat message on a certain index and restarts its timer. **Requires ManageMessages server permission.** | `.repinv 1` `.repeatinvoke` `.repinv` | Immediately shows the repeat message on a certain index and restarts its timer. **Requires ManageMessages server permission.** | `.repinv 1`
`.repeatremove` `.reprm` | Removes a repeating message on a specified index. Use `.repeatlist` to see indexes. **Requires ManageMessages server permission.** | `.reprm 2` `.repeatremove` `.reprm` | Removes a repeating message on a specified index. Use `.repeatlist` to see indexes. **Requires ManageMessages server permission.** | `.reprm 2`
`.repeat` | Repeat a message every X minutes in the current channel. You can have up to 5 repeating messages on the server in total. **Requires ManageMessages server permission.** | `.repeat 5 Hello there` `.repeat` | Repeat a message every `X` minutes in the current channel. You can have up to 5 repeating messages on the server in total. **Requires ManageMessages server permission.** | `.repeat 5 Hello there`
`.repeatlist` `.replst` | Shows currently repeating messages and their indexes. **Requires ManageMessages server permission.** | `.repeatlist` `.repeatlist` `.replst` | Shows currently repeating messages and their indexes. **Requires ManageMessages server permission.** | `.repeatlist`
`.listquotes` `.liqu` | `.liqu` or `.liqu 3` | Lists all quotes on the server ordered alphabetically. 15 Per page. `.listquotes` `.liqu` | `.liqu` or `.liqu 3` | Lists all quotes on the server ordered alphabetically. 15 Per page.
`...` | 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`
`..` | Adds a new quote with the specified name and message. | `.. sayhi Hi` `..` | Adds a new quote with the specified name and message. | `.. sayhi Hi`
`.deletequote` `.delq` | Deletes a random quote with the specified keyword. You have to either be server Administrator or the creator of the quote to delete it. | `.delq abc` `.deletequote` `.delq` | Deletes a random quote with the specified keyword. You have to either be server Administrator or the creator of the quote to delete it. | `.delq abc`
`.delallq` `.daq` | Deletes all quotes on a specified keyword. **Requires Administrator server permission.** | `.delallq kek` `.delallq` `.daq` | Deletes all quotes on a specified keyword. **Requires Administrator server permission.** | `.delallq kek`
`.remind` | Sends a message to you or a channel after certain amount of time. First argument is me/here/'channelname'. Second argument is time in a descending order (mo>w>d>h>m) example: 1w5d3h10m. Third argument is a (multiword)message. | `.remind me 1d5h Do something` or `.remind #general 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

@ -198,17 +198,49 @@ CentOS:
![img2](https://cdn.discordapp.com/attachments/251504306010849280/251504746987388938/dotnet.gif) ![img2](https://cdn.discordapp.com/attachments/251504306010849280/251504746987388938/dotnet.gif)
Go to [this link](https://www.microsoft.com/net/core#ubuntu) (for Ubuntu) or to [this link](https://www.microsoft.com/net/core#linuxcentos) (for CentOS) provided by microsoft for instructions on how to get the most up to date version of the dotnet core sdk! Go to [this link](https://www.microsoft.com/net/core#ubuntu) (for Ubuntu) or to [this link](https://www.microsoft.com/net/core#linuxcentos) (for CentOS) provided by microsoft for instructions on how to get the most up to date version of the dotnet core sdk!
Make sure that you're on the correct page for your distribution of linux as the guides are different for the various distributions Make sure that you're on the correct page for your distribution of linux as the guides are different for the various distributions.
Install the **currently supported version** `1.0.0-preview2-1-003177`.
You can find it [here](https://github.com/dotnet/core/blob/master/release-notes/download-archives/1.1-preview2.1-download.md) if you prefer manual installing `dpkg` files.
We'll go over the steps here for Ubuntu 16.04 anyway (these will **only** work on Ubuntu 16.04), accurate as of 3/2/2017 We'll go over the steps here for few linux distributions, accurate as of March 08, 2017:
**NOTE:** .NET CORE SDK only supports 64-bit Linux Operating Systems (Raspberry Pis are not supported because of this)
**Ubuntu x64 17.04 & 16.10**
```sh
sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/ yakkety main" > /etc/apt/sources.list.d/dotnetdev.list'
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 417A0893
sudo apt-get update && sudo apt-get install dotnet-dev-1.0.0-preview2.1-003177 -y
``` ```
**Ubuntu x64 16.04**
```sh
sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/ xenial main" > /etc/apt/sources.list.d/dotnetdev.list' sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/ xenial main" > /etc/apt/sources.list.d/dotnetdev.list'
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 417A0893 sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 417A0893
sudo apt-get update && sudo apt-get install dotnet-dev-1.0.0-preview2.1-003177 -y sudo apt-get update && sudo apt-get install dotnet-dev-1.0.0-preview2.1-003177 -y
``` ```
**NOTE:** .NET CORE SDK only supports 64-bit Linux Operating Systems (Raspberry Pis are not supported because of this) **Ubuntu x64 14.04**
```sh
sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/ trusty main" > /etc/apt/sources.list.d/dotnetdev.list'
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 417A0893
sudo apt-get update && sudo apt-get install dotnet-dev-1.0.0-preview2.1-003177 -y
```
**Debian 8 x64**
```sh
sudo apt-get install curl libunwind8 gettext -y
curl -sSL -o dotnet.tar.gz https://go.microsoft.com/fwlink/?LinkID=835021
sudo mkdir -p /opt/dotnet && sudo tar zxf dotnet.tar.gz -C /opt/dotnet
sudo ln -s /opt/dotnet/dotnet /usr/local/bin
```
**CentOS 7 x64**
```sh
sudo yum install libunwind libicu -y
curl -sSL -o dotnet.tar.gz https://go.microsoft.com/fwlink/?LinkID=835019
sudo mkdir -p /opt/dotnet && sudo tar zxf dotnet.tar.gz -C /opt/dotnet
sudo ln -s /opt/dotnet/dotnet /usr/local/bin
```
#####Installing Opus Voice Codec and libsodium #####Installing Opus Voice Codec and libsodium
@ -232,14 +264,14 @@ Ubuntu:
Centos: Centos:
``` ```sh
yum -y install http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm epel-release yum -y install http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm epel-release
yum -y install ffmpeg yum -y install ffmpeg
``` ```
**NOTE:** If you are running **UBUNTU 14.04**, you must run these first: **NOTE:** If you are running **UBUNTU 14.04**, you must run these first:
``` ```sh
sudo add-apt-repository ppa:mc3man/trusty-media sudo add-apt-repository ppa:mc3man/trusty-media
sudo apt-get update sudo apt-get update
sudo apt-get dist-upgrade sudo apt-get dist-upgrade
@ -250,7 +282,7 @@ sudo apt-get dist-upgrade
**NOTE:** If you are running **Debian 8 Jessie**, please, follow these steps: **NOTE:** If you are running **Debian 8 Jessie**, please, follow these steps:
``` ```sh
sudo apt-get update sudo apt-get update
echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/debian-backports.list echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/debian-backports.list
sudo apt-get update && sudo apt-get install ffmpeg -y sudo apt-get update && sudo apt-get install ffmpeg -y
@ -330,14 +362,14 @@ If the [Nadeko installer](http://nadekobot.readthedocs.io/en/latest/guides/Linux
**OR** **OR**
``` ```sh
cd ~ && git clone -b dev --recursive --depth 1 https://github.com/Kwoth/NadekoBot.git cd ~ && git clone -b dev --recursive --depth 1 https://github.com/Kwoth/NadekoBot.git
cd ~/NadekoBot/discord.net/src/Discord.Net && dotnet restore && cd ../Discord.Net.Commands && dotnet restore && cd ../../../src/NadekoBot/ && dotnet restore && dotnet build --configuration Release cd ~/NadekoBot/discord.net/src/Discord.Net && dotnet restore && cd ../Discord.Net.Commands && dotnet restore && cd ../../../src/NadekoBot/ && dotnet restore && dotnet build --configuration Release
``` ```
If you are getting error using the above steps try: If you are getting error using the above steps try:
``` ```sh
cd ~/NadekoBot/discord.net && dotnet restore -s https://dotnet.myget.org/F/dotnet-core/api/v3/index.json && dotnet restore cd ~/NadekoBot/discord.net && dotnet restore -s https://dotnet.myget.org/F/dotnet-core/api/v3/index.json && dotnet restore
cd ~/NadekoBot/src/NadekoBot/ && dotnet restore && dotnet build --configuration Release cd ~/NadekoBot/src/NadekoBot/ && dotnet restore && dotnet build --configuration Release
``` ```

View File

@ -30,7 +30,7 @@ brew install tmux
- `ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/` - `ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/`
- `ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/` - `ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/`
- Download the [.NET Core SDK](https://www.microsoft.com/net/core#macos), found [here.](https://go.microsoft.com/fwlink/?LinkID=835011) - Download the [.NET Core SDK][.NET Core SDK]
- Open the `.pkg` file you downloaded and install it. - Open the `.pkg` file you downloaded and install it.
- `ln -s /usr/local/share/dotnet/dotnet /usr/local/bin` - `ln -s /usr/local/share/dotnet/dotnet /usr/local/bin`
@ -166,6 +166,7 @@ If you used Screen press CTRL+A+D (this will detach the nadeko screen)
- `dotnet build --configuration Release` - `dotnet build --configuration Release`
[Homebrew]: http://brew.sh/ [Homebrew]: http://brew.sh/
[.NET Core SDK]: https://github.com/dotnet/core/blob/master/release-notes/download-archives/1.1-preview2.1-download.md
[DiscordApp]: https://discordapp.com/developers/applications/me [DiscordApp]: https://discordapp.com/developers/applications/me
[Atom]: https://atom.io/ [Atom]: https://atom.io/
[Invite Guide]: http://discord.kongslien.net/guide.html [Invite Guide]: http://discord.kongslien.net/guide.html

View File

@ -120,7 +120,7 @@ In order to have a functioning music module, you need to install ffmpeg and setu
[.NET Core SDK]: https://www.microsoft.com/net/core#windowscmd [.NET Core SDK]: https://github.com/dotnet/core/blob/master/release-notes/download-archives/1.1-preview2.1-download.md
[Git]: https://git-scm.com/download/win [Git]: https://git-scm.com/download/win
[7zip]: http://www.7-zip.org/download.html [7zip]: http://www.7-zip.org/download.html
[DiscordApp]: https://discordapp.com/developers/applications/me [DiscordApp]: https://discordapp.com/developers/applications/me

View File

@ -1,24 +1,25 @@
@ECHO off @ECHO off
TITLE Downloading Latest Build of NadekoBot... TITLE Downloading Latest Build of NadekoBot...
::Setting convenient to read variables which don't delete the windows temp folder ::Setting convenient to read variables which don't delete the windows temp folder
SET root=%~dp0 SET "root=%~dp0"
CD /D %root% CD /D "%root%"
SET rootdir=%cd% SET "rootdir=%cd%"
SET build1=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Core\ SET "build1=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Core\"
SET build2=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Rest\ SET "build2=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Rest\"
SET build3=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.WebSocket\ SET "build3=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.WebSocket\"
SET build4=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Commands\ SET "build4=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Commands\"
SET build5=%root%NadekoInstall_Temp\NadekoBot\src\NadekoBot\ SET "build5=%root%NadekoInstall_Temp\NadekoBot\src\NadekoBot\"
SET installtemp=%root%NadekoInstall_Temp\ SET "installtemp=%root%NadekoInstall_Temp\"
::Deleting traces of last setup for the sake of clean folders, if by some miracle it still exists ::Deleting traces of last setup for the sake of clean folders, if by some miracle it still exists
IF EXIST %installtemp% ( RMDIR %installtemp% /S /Q >nul 2>&1) IF EXIST "%installtemp%" ( RMDIR "%installtemp%" /S /Q >nul 2>&1)
timeout /t 5
::Checks that both git and dotnet are installed ::Checks that both git and dotnet are installed
dotnet --version >nul 2>&1 || GOTO :dotnet dotnet --version >nul 2>&1 || GOTO :dotnet
git --version >nul 2>&1 || GOTO :git git --version >nul 2>&1 || GOTO :git
::Creates the install directory to work in and get the current directory because spaces ruins everything otherwise ::Creates the install directory to work in and get the current directory because spaces ruins everything otherwise
:start :start
MKDIR NadekoInstall_Temp MKDIR "%root%NadekoInstall_Temp"
CD /D %installtemp% CD /D "%installtemp%"
::Downloads the latest version of Nadeko ::Downloads the latest version of Nadeko
ECHO Downloading Nadeko... ECHO Downloading Nadeko...
ECHO. ECHO.
@ -28,28 +29,28 @@ TITLE Installing NadekoBot, please wait...
ECHO. ECHO.
ECHO Installing Discord.Net(1/4)... ECHO Installing Discord.Net(1/4)...
::Building Nadeko ::Building Nadeko
CD /D %build1% CD /D "%build1%"
dotnet restore >nul 2>&1 dotnet restore >nul 2>&1
ECHO Installing Discord.Net(2/4)... ECHO Installing Discord.Net(2/4)...
CD /D %build2% CD /D "%build2%"
dotnet restore >nul 2>&1 dotnet restore >nul 2>&1
ECHO Installing Discord.Net(3/4)... ECHO Installing Discord.Net(3/4)...
CD /D %build3% CD /D "%build3%"
dotnet restore >nul 2>&1 dotnet restore >nul 2>&1
ECHO Installing Discord.Net(4/4)... ECHO Installing Discord.Net(4/4)...
CD /D %build4% CD /D "%build4%"
dotnet restore >nul 2>&1 dotnet restore >nul 2>&1
ECHO. ECHO.
ECHO Discord.Net installation completed successfully... ECHO Discord.Net installation completed successfully...
ECHO. ECHO.
ECHO Installing NadekoBot... ECHO Installing NadekoBot...
CD /D %build5% CD /D "%build5%"
dotnet restore >nul 2>&1 dotnet restore >nul 2>&1
dotnet build --configuration Release >nul 2>&1 dotnet build --configuration Release >nul 2>&1
ECHO. ECHO.
ECHO NadekoBot installation completed successfully... ECHO NadekoBot installation completed successfully...
::Attempts to backup old files if they currently exist in the same folder as the batch file ::Attempts to backup old files if they currently exist in the same folder as the batch file
IF EXIST "%root%NadekoBot\" (GOTO :backupinstall) IF EXIST "%root%NadekoBot\" (GOTO :backupinstall) ELSE (GOTO :freshinstall)
:freshinstall :freshinstall
::Moves the NadekoBot folder to keep things tidy ::Moves the NadekoBot folder to keep things tidy
ECHO. ECHO.
@ -65,20 +66,23 @@ IF EXIST "%root%NadekoBot\" (GOTO :backupinstall)
ROBOCOPY "%root%NadekoBot" "%root%NadekoBot_Old" /MIR >nul 2>&1 ROBOCOPY "%root%NadekoBot" "%root%NadekoBot_Old" /MIR >nul 2>&1
IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror) IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror)
ECHO. ECHO.
ECHO Old files backed up to NadekoBot_Old ECHO Old files backed up to NadekoBot_Old...
::Copies the credentials and database from the backed up data to the new folder ::Copies the credentials and database from the backed up data to the new folder
COPY "%root%NadekoBot_Old\src\NadekoBot\credentials.json" "%installtemp%NadekoBot\src\NadekoBot\credentials.json" >nul 2>&1 COPY "%root%NadekoBot_Old\src\NadekoBot\credentials.json" "%installtemp%NadekoBot\src\NadekoBot\credentials.json" >nul 2>&1
IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror) IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror)
ECHO. ECHO.
ECHO credentials.json copied to new folder ECHO credentials.json copied...
ROBOCOPY "%root%NadekoBot_Old\src\NadekoBot\bin" "%installtemp%NadekoBot\src\NadekoBot\bin" /E >nul 2>&1 ROBOCOPY "%root%NadekoBot_Old\src\NadekoBot\bin" "%installtemp%NadekoBot\src\NadekoBot\bin" /E >nul 2>&1
IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror) IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror)
ECHO. ECHO.
ECHO Old bin folder copied to new folder ECHO bin folder copied...
RD /S /Q "%root%NadekoBot_Old\src\NadekoBot\data\musicdata"
ECHO.
ECHO music cache cleared...
ROBOCOPY "%root%NadekoBot_Old\src\NadekoBot\data" "%installtemp%NadekoBot\src\NadekoBot\data" /E >nul 2>&1 ROBOCOPY "%root%NadekoBot_Old\src\NadekoBot\data" "%installtemp%NadekoBot\src\NadekoBot\data" /E >nul 2>&1
IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror) IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror)
ECHO. ECHO.
ECHO Old data folder copied to new folder ECHO Old data folder copied...
::Moves the setup Nadeko folder ::Moves the setup Nadeko folder
RMDIR "%root%NadekoBot\" /S /Q >nul 2>&1 RMDIR "%root%NadekoBot\" /S /Q >nul 2>&1
ROBOCOPY "%root%NadekoInstall_Temp" "%rootdir%" /E /MOVE >nul 2>&1 ROBOCOPY "%root%NadekoInstall_Temp" "%rootdir%" /E /MOVE >nul 2>&1
@ -103,7 +107,7 @@ IF EXIST "%root%NadekoBot\" (GOTO :backupinstall)
:giterror :giterror
ECHO. ECHO.
ECHO Git clone failed, trying again ECHO Git clone failed, trying again
RMDIR %installtemp% /S /Q >nul 2>&1 RMDIR "%installtemp%" /S /Q >nul 2>&1
GOTO :start GOTO :start
:copyerror :copyerror
::If at any point a copy error is encountered ::If at any point a copy error is encountered
@ -124,22 +128,39 @@ ECHO.
ECHO Your System Architecture is 32bit... ECHO Your System Architecture is 32bit...
timeout /t 5 timeout /t 5
ECHO. ECHO.
ECHO Downloading libsodium.dll and opus.dll... ECHO Getting 32bit libsodium.dll and opus.dll...
IF EXIST "%root%NadekoBot\src\NadekoBot\_libs\32\libsodium.dll" (GOTO copysodium) ELSE (GOTO downloadsodium)
:copysodium
del "%root%NadekoBot\src\NadekoBot\libsodium.dll"
copy "%root%NadekoBot\src\NadekoBot\_libs\32\libsodium.dll" "%root%NadekoBot\src\NadekoBot\libsodium.dll"
ECHO libsodium.dll copied.
ECHO.
timeout /t 5
IF EXIST "%root%NadekoBot\src\NadekoBot\_libs\32\opus.dll" (GOTO copyopus) ELSE (GOTO downloadopus)
:downloadsodium
SET "FILENAME=%~dp0\NadekoBot\src\NadekoBot\libsodium.dll" SET "FILENAME=%~dp0\NadekoBot\src\NadekoBot\libsodium.dll"
bitsadmin.exe /transfer "Downloading libsodium.dll" /priority high https://github.com/Kwoth/NadekoBot/raw/dev/src/NadekoBot/_libs/32/libsodium.dll "%FILENAME%" powershell -Command "Invoke-WebRequest https://github.com/Kwoth/NadekoBot/raw/dev/src/NadekoBot/_libs/32/libsodium.dll -OutFile '%FILENAME%'"
ECHO libsodium.dll downloaded. ECHO libsodium.dll downloaded.
ECHO. ECHO.
timeout /t 5 timeout /t 5
IF EXIST "%root%NadekoBot\src\NadekoBot\_libs\32\opus.dll" (GOTO copyopus) ELSE (GOTO downloadopus)
:copyopus
del "%root%NadekoBot\src\NadekoBot\opus.dll"
copy "%root%NadekoBot\src\NadekoBot\_libs\32\opus.dll" "%root%NadekoBot\src\NadekoBot\opus.dll"
ECHO opus.dll copied.
GOTO end
:downloadopus
SET "FILENAME=%~dp0\NadekoBot\src\NadekoBot\opus.dll" SET "FILENAME=%~dp0\NadekoBot\src\NadekoBot\opus.dll"
bitsadmin.exe /transfer "Downloading opus.dll" /priority high https://github.com/Kwoth/NadekoBot/raw/dev/src/NadekoBot/_libs/32/opus.dll "%FILENAME%" powershell -Command "Invoke-WebRequest https://github.com/Kwoth/NadekoBot/raw/dev/src/NadekoBot/_libs/32/opus.dll -OutFile '%FILENAME%'"
ECHO opus.dll downloaded. ECHO opus.dll downloaded.
GOTO end GOTO end
:end :end
::Normal execution of end of script ::Normal execution of end of script
TITLE Installation complete! TITLE NadekoBot Installation complete!
CD /D "%root%" CD /D "%root%"
RMDIR /S /Q "%installtemp%" >nul 2>&1 RMDIR /S /Q "%installtemp%" >nul 2>&1
ECHO. ECHO.
ECHO Installation complete, press any key to close this window! ECHO Installation complete!
timeout /t 5 ECHO.
PAUSE
del Latest.bat del Latest.bat

View File

@ -2,8 +2,8 @@
@TITLE NadekoBot @TITLE NadekoBot
SET root=%~dp0 SET "root=%~dp0"
CD /D %root% CD /D "%root%"
CLS CLS
ECHO Welcome to NadekoBot Auto Restart and Update! ECHO Welcome to NadekoBot Auto Restart and Update!
@ -25,32 +25,28 @@ IF ERRORLEVEL 1 GOTO latestar
:latestar :latestar
ECHO Auto Restart and Update with Dev Build (latest) ECHO Auto Restart and Update with Dev Build (latest)
ECHO Bot will auto update on every restart! ECHO Bot will auto update on every restart!
timeout /t 3 CD /D "%~dp0NadekoBot\src\NadekoBot"
CD /D %~dp0NadekoBot\src\NadekoBot
dotnet run --configuration Release dotnet run --configuration Release
ECHO Updating... ECHO Updating...
timeout /t 3
SET "FILENAME=%~dp0\Latest.bat" SET "FILENAME=%~dp0\Latest.bat"
bitsadmin.exe /transfer "Downloading Nadeko (Latest)" /priority high https://github.com/Kwoth/NadekoBot/raw/master/scripts/Latest.bat "%FILENAME%" powershell -Command "Invoke-WebRequest https://github.com/Kwoth/NadekoBot/raw/dev/scripts/Latest.bat -OutFile '%FILENAME%'"
ECHO NadekoBot Dev Build (latest) downloaded. ECHO NadekoBot Dev Build (latest) downloaded.
SET root=%~dp0 SET "root=%~dp0"
CD /D %root% CD /D "%root%"
CALL Latest.bat CALL Latest.bat
GOTO latestar GOTO latestar
:stablear :stablear
ECHO Auto Restart and Update with Stable Build ECHO Auto Restart and Update with Stable Build
ECHO Bot will auto update on every restart! ECHO Bot will auto update on every restart!
timeout /t 3 CD /D "%~dp0NadekoBot\src\NadekoBot"
CD /D %~dp0NadekoBot\src\NadekoBot
dotnet run --configuration Release dotnet run --configuration Release
ECHO Updating... ECHO Updating...
timeout /t 3
SET "FILENAME=%~dp0\Stable.bat" SET "FILENAME=%~dp0\Stable.bat"
bitsadmin.exe /transfer "Downloading Nadeko (Stable)" /priority high https://github.com/Kwoth/NadekoBot/raw/master/scripts/Stable.bat "%FILENAME%" powershell -Command "Invoke-WebRequest https://github.com/Kwoth/NadekoBot/raw/dev/scripts/Stable.bat -OutFile '%FILENAME%'"
ECHO NadekoBot Stable build downloaded. ECHO NadekoBot Stable build downloaded.
SET root=%~dp0 SET "root=%~dp0"
CD /D %root% CD /D "%root%"
CALL Stable.bat CALL Stable.bat
GOTO stablear GOTO stablear
@ -58,12 +54,12 @@ GOTO stablear
ECHO Normal Auto Restart ECHO Normal Auto Restart
ECHO Bot will not auto update on every restart! ECHO Bot will not auto update on every restart!
timeout /t 3 timeout /t 3
CD /D %~dp0NadekoBot\src\NadekoBot CD /D "%~dp0NadekoBot\src\NadekoBot"
dotnet run --configuration Release dotnet run --configuration Release
goto autorun goto autorun
:Exit :Exit
SET root=%~dp0 SET "root=%~dp0"
CD /D %root% CD /D "%root%"
del NadekoAutoRun.bat del NadekoAutoRun.bat
CALL NadekoInstaller.bat CALL NadekoInstaller.bat

View File

@ -1,9 +1,9 @@
@ECHO off @ECHO off
@TITLE NadekoBot @TITLE NadekoBot
CD /D %~dp0NadekoBot\src\NadekoBot CD /D "%~dp0NadekoBot\src\NadekoBot"
dotnet run --configuration Release dotnet run --configuration Release
ECHO NadekoBot has been succesfully stopped, press any key to close this window. ECHO NadekoBot has been succesfully stopped, press any key to close this window.
TITLE NadekoBot - Stopped TITLE NadekoBot - Stopped
CD /D %~dp0 CD /D "%~dp0"
PAUSE >nul 2>&1 PAUSE >nul 2>&1
del NadekoRunNormal.bat del NadekoRunNormal.bat

View File

@ -1,24 +1,25 @@
@ECHO off @ECHO off
TITLE Downloading Stable Build of NadekoBot... TITLE Downloading Stable Build of NadekoBot...
::Setting convenient to read variables which don't delete the windows temp folder ::Setting convenient to read variables which don't delete the windows temp folder
SET root=%~dp0 SET "root=%~dp0"
CD /D %root% CD /D "%root%"
SET rootdir=%cd% SET "rootdir=%cd%"
SET build1=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Core\ SET "build1=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Core\"
SET build2=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Rest\ SET "build2=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Rest\"
SET build3=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.WebSocket\ SET "build3=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.WebSocket\"
SET build4=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Commands\ SET "build4=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Commands\"
SET build5=%root%NadekoInstall_Temp\NadekoBot\src\NadekoBot\ SET "build5=%root%NadekoInstall_Temp\NadekoBot\src\NadekoBot\"
SET installtemp=%root%NadekoInstall_Temp\ SET "installtemp=%root%NadekoInstall_Temp\"
::Deleting traces of last setup for the sake of clean folders, if by some miracle it still exists ::Deleting traces of last setup for the sake of clean folders, if by some miracle it still exists
IF EXIST %installtemp% ( RMDIR %installtemp% /S /Q >nul 2>&1) IF EXIST "%installtemp%" ( RMDIR "%installtemp%" /S /Q >nul 2>&1)
timeout /t 5
::Checks that both git and dotnet are installed ::Checks that both git and dotnet are installed
dotnet --version >nul 2>&1 || GOTO :dotnet dotnet --version >nul 2>&1 || GOTO :dotnet
git --version >nul 2>&1 || GOTO :git git --version >nul 2>&1 || GOTO :git
::Creates the install directory to work in and get the current directory because spaces ruins everything otherwise ::Creates the install directory to work in and get the current directory because spaces ruins everything otherwise
:start :start
MKDIR NadekoInstall_Temp MKDIR "%root%NadekoInstall_Temp"
CD /D %installtemp% CD /D "%installtemp%"
::Downloads the latest version of Nadeko ::Downloads the latest version of Nadeko
ECHO Downloading Nadeko... ECHO Downloading Nadeko...
ECHO. ECHO.
@ -28,28 +29,28 @@ TITLE Installing NadekoBot, please wait...
ECHO. ECHO.
ECHO Installing Discord.Net(1/4)... ECHO Installing Discord.Net(1/4)...
::Building Nadeko ::Building Nadeko
CD /D %build1% CD /D "%build1%"
dotnet restore >nul 2>&1 dotnet restore >nul 2>&1
ECHO Installing Discord.Net(2/4)... ECHO Installing Discord.Net(2/4)...
CD /D %build2% CD /D "%build2%"
dotnet restore >nul 2>&1 dotnet restore >nul 2>&1
ECHO Installing Discord.Net(3/4)... ECHO Installing Discord.Net(3/4)...
CD /D %build3% CD /D "%build3%"
dotnet restore >nul 2>&1 dotnet restore >nul 2>&1
ECHO Installing Discord.Net(4/4)... ECHO Installing Discord.Net(4/4)...
CD /D %build4% CD /D "%build4%"
dotnet restore >nul 2>&1 dotnet restore >nul 2>&1
ECHO. ECHO.
ECHO Discord.Net installation completed successfully... ECHO Discord.Net installation completed successfully...
ECHO. ECHO.
ECHO Installing NadekoBot... ECHO Installing NadekoBot...
CD /D %build5% CD /D "%build5%"
dotnet restore >nul 2>&1 dotnet restore >nul 2>&1
dotnet build --configuration Release >nul 2>&1 dotnet build --configuration Release >nul 2>&1
ECHO. ECHO.
ECHO NadekoBot installation completed successfully... ECHO NadekoBot installation completed successfully...
::Attempts to backup old files if they currently exist in the same folder as the batch file ::Attempts to backup old files if they currently exist in the same folder as the batch file
IF EXIST "%root%NadekoBot\" (GOTO :backupinstall) IF EXIST "%root%NadekoBot\" (GOTO :backupinstall) ELSE (GOTO :freshinstall)
:freshinstall :freshinstall
::Moves the NadekoBot folder to keep things tidy ::Moves the NadekoBot folder to keep things tidy
ECHO. ECHO.
@ -65,20 +66,23 @@ IF EXIST "%root%NadekoBot\" (GOTO :backupinstall)
ROBOCOPY "%root%NadekoBot" "%root%NadekoBot_Old" /MIR >nul 2>&1 ROBOCOPY "%root%NadekoBot" "%root%NadekoBot_Old" /MIR >nul 2>&1
IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror) IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror)
ECHO. ECHO.
ECHO Old files backed up to NadekoBot_Old ECHO Old files backed up to NadekoBot_Old...
::Copies the credentials and database from the backed up data to the new folder ::Copies the credentials and database from the backed up data to the new folder
COPY "%root%NadekoBot_Old\src\NadekoBot\credentials.json" "%installtemp%NadekoBot\src\NadekoBot\credentials.json" >nul 2>&1 COPY "%root%NadekoBot_Old\src\NadekoBot\credentials.json" "%installtemp%NadekoBot\src\NadekoBot\credentials.json" >nul 2>&1
IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror) IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror)
ECHO. ECHO.
ECHO credentials.json copied to new folder ECHO credentials.json copied...
ROBOCOPY "%root%NadekoBot_Old\src\NadekoBot\bin" "%installtemp%NadekoBot\src\NadekoBot\bin" /E >nul 2>&1 ROBOCOPY "%root%NadekoBot_Old\src\NadekoBot\bin" "%installtemp%NadekoBot\src\NadekoBot\bin" /E >nul 2>&1
IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror) IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror)
ECHO. ECHO.
ECHO Old bin folder copied to new folder ECHO bin folder copied...
RD /S /Q "%root%NadekoBot_Old\src\NadekoBot\data\musicdata"
ECHO.
ECHO music cache cleared...
ROBOCOPY "%root%NadekoBot_Old\src\NadekoBot\data" "%installtemp%NadekoBot\src\NadekoBot\data" /E >nul 2>&1 ROBOCOPY "%root%NadekoBot_Old\src\NadekoBot\data" "%installtemp%NadekoBot\src\NadekoBot\data" /E >nul 2>&1
IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror) IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror)
ECHO. ECHO.
ECHO Old data folder copied to new folder ECHO Old data folder copied...
::Moves the setup Nadeko folder ::Moves the setup Nadeko folder
RMDIR "%root%NadekoBot\" /S /Q >nul 2>&1 RMDIR "%root%NadekoBot\" /S /Q >nul 2>&1
ROBOCOPY "%root%NadekoInstall_Temp" "%rootdir%" /E /MOVE >nul 2>&1 ROBOCOPY "%root%NadekoInstall_Temp" "%rootdir%" /E /MOVE >nul 2>&1
@ -103,7 +107,7 @@ IF EXIST "%root%NadekoBot\" (GOTO :backupinstall)
:giterror :giterror
ECHO. ECHO.
ECHO Git clone failed, trying again ECHO Git clone failed, trying again
RMDIR %installtemp% /S /Q >nul 2>&1 RMDIR "%installtemp%" /S /Q >nul 2>&1
GOTO :start GOTO :start
:copyerror :copyerror
::If at any point a copy error is encountered ::If at any point a copy error is encountered
@ -124,22 +128,39 @@ ECHO.
ECHO Your System Architecture is 32bit... ECHO Your System Architecture is 32bit...
timeout /t 5 timeout /t 5
ECHO. ECHO.
ECHO Downloading libsodium.dll and opus.dll... ECHO Getting 32bit libsodium.dll and opus.dll...
IF EXIST "%root%NadekoBot\src\NadekoBot\_libs\32\libsodium.dll" (GOTO copysodium) ELSE (GOTO downloadsodium)
:copysodium
del "%root%NadekoBot\src\NadekoBot\libsodium.dll"
copy "%root%NadekoBot\src\NadekoBot\_libs\32\libsodium.dll" "%root%NadekoBot\src\NadekoBot\libsodium.dll"
ECHO libsodium.dll copied.
ECHO.
timeout /t 5
IF EXIST "%root%NadekoBot\src\NadekoBot\_libs\32\opus.dll" (GOTO copyopus) ELSE (GOTO downloadopus)
:downloadsodium
SET "FILENAME=%~dp0\NadekoBot\src\NadekoBot\libsodium.dll" SET "FILENAME=%~dp0\NadekoBot\src\NadekoBot\libsodium.dll"
bitsadmin.exe /transfer "Downloading libsodium.dll" /priority high https://github.com/Kwoth/NadekoBot/raw/dev/src/NadekoBot/_libs/32/libsodium.dll "%FILENAME%" powershell -Command "Invoke-WebRequest https://github.com/Kwoth/NadekoBot/raw/dev/src/NadekoBot/_libs/32/libsodium.dll -OutFile '%FILENAME%'"
ECHO libsodium.dll downloaded. ECHO libsodium.dll downloaded.
ECHO. ECHO.
timeout /t 5 timeout /t 5
IF EXIST "%root%NadekoBot\src\NadekoBot\_libs\32\opus.dll" (GOTO copyopus) ELSE (GOTO downloadopus)
:copyopus
del "%root%NadekoBot\src\NadekoBot\opus.dll"
copy "%root%NadekoBot\src\NadekoBot\_libs\32\opus.dll" "%root%NadekoBot\src\NadekoBot\opus.dll"
ECHO opus.dll copied.
GOTO end
:downloadopus
SET "FILENAME=%~dp0\NadekoBot\src\NadekoBot\opus.dll" SET "FILENAME=%~dp0\NadekoBot\src\NadekoBot\opus.dll"
bitsadmin.exe /transfer "Downloading opus.dll" /priority high https://github.com/Kwoth/NadekoBot/raw/dev/src/NadekoBot/_libs/32/opus.dll "%FILENAME%" powershell -Command "Invoke-WebRequest https://github.com/Kwoth/NadekoBot/raw/dev/src/NadekoBot/_libs/32/opus.dll -OutFile '%FILENAME%'"
ECHO opus.dll downloaded. ECHO opus.dll downloaded.
GOTO end GOTO end
:end :end
::Normal execution of end of script ::Normal execution of end of script
TITLE Installation complete! TITLE NadekoBot Installation complete!
CD /D "%root%" CD /D "%root%"
RMDIR /S /Q "%installtemp%" >nul 2>&1 RMDIR /S /Q "%installtemp%" >nul 2>&1
ECHO. ECHO.
ECHO Installation complete, press any key to close this window! ECHO Installation complete!
timeout /t 5 ECHO.
PAUSE
del Stable.bat del Stable.bat

View File

@ -0,0 +1,140 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using NadekoBot.Services.Database.Models;
namespace NadekoBot.DataStructures
{
public class PermissionsCollection<T> : IList<T> where T : IIndexed
{
public List<T> Source { get; }
private readonly object _locker = new object();
public PermissionsCollection(IEnumerable<T> source)
{
lock (_locker)
{
Source = source.OrderBy(x => x.Index).ToList();
for (var i = 0; i < Source.Count; i++)
{
if(Source[i].Index != i)
Source[i].Index = i;
}
}
}
public static implicit operator List<T>(PermissionsCollection<T> x) =>
x.Source;
public IEnumerator<T> GetEnumerator() =>
Source.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() =>
Source.GetEnumerator();
public void Add(T item)
{
lock (_locker)
{
item.Index = Source.Count;
Source.Add(item);
}
}
public void Clear()
{
lock (_locker)
{
var first = Source[0];
Source.Clear();
Source[0] = first;
}
}
public bool Contains(T item)
{
lock (_locker)
{
return Source.Contains(item);
}
}
public void CopyTo(T[] array, int arrayIndex)
{
lock (_locker)
{
Source.CopyTo(array, arrayIndex);
}
}
public bool Remove(T item)
{
bool removed;
lock (_locker)
{
if(Source.IndexOf(item) == 0)
throw new ArgumentException("You can't remove first permsission (allow all)");
if (removed = Source.Remove(item))
{
for (int i = 0; i < Source.Count; i++)
{
// hm, no idea how ef works, so I don't want to set if it's not changed,
// maybe it will try to update db?
// But most likely it just compares old to new values, meh.
if (Source[i].Index != i)
Source[i].Index = i;
}
}
}
return removed;
}
public int Count => Source.Count;
public bool IsReadOnly => false;
public int IndexOf(T item) => item.Index;
public void Insert(int index, T item)
{
lock (_locker)
{
if(index == 0) // can't insert on first place. Last item is always allow all.
throw new IndexOutOfRangeException(nameof(index));
Source.Insert(index, item);
for (int i = index; i < Source.Count; i++)
{
Source[i].Index = i;
}
}
}
public void RemoveAt(int index)
{
lock (_locker)
{
if(index == 0) // you can't remove first permission (allow all)
throw new IndexOutOfRangeException(nameof(index));
Source.RemoveAt(index);
for (int i = index; i < Source.Count; i++)
{
Source[i].Index = i;
}
}
}
public T this[int index] {
get { return Source[index]; }
set {
lock (_locker)
{
if(index == 0) // can't set first element. It's always allow all
throw new IndexOutOfRangeException(nameof(index));
value.Index = index;
Source[index] = value;
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class permsv2 : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Permissionv2",
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),
Index = table.Column<int>(nullable: false),
PrimaryTarget = table.Column<int>(nullable: false),
PrimaryTargetId = table.Column<ulong>(nullable: false),
SecondaryTarget = table.Column<int>(nullable: false),
SecondaryTargetName = table.Column<string>(nullable: true),
State = table.Column<bool>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Permissionv2", x => x.Id);
table.ForeignKey(
name: "FK_Permissionv2_GuildConfigs_GuildConfigId",
column: x => x.GuildConfigId,
principalTable: "GuildConfigs",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_Permissionv2_GuildConfigId",
table: "Permissionv2",
column: "GuildConfigId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Permissionv2");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class unmutetimers : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "UnmuteTimer",
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),
UnmuteAt = table.Column<DateTime>(nullable: false),
UserId = table.Column<ulong>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_UnmuteTimer", x => x.Id);
table.ForeignKey(
name: "FK_UnmuteTimer_GuildConfigs_GuildConfigId",
column: x => x.GuildConfigId,
principalTable: "GuildConfigs",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_UnmuteTimer_GuildConfigId",
table: "UnmuteTimer",
column: "GuildConfigId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "UnmuteTimer");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class vcrole : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "VcRoleInfo",
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),
VoiceChannelId = table.Column<ulong>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_VcRoleInfo", x => x.Id);
table.ForeignKey(
name: "FK_VcRoleInfo_GuildConfigs_GuildConfigId",
column: x => x.GuildConfigId,
principalTable: "GuildConfigs",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_VcRoleInfo_GuildConfigId",
table: "VcRoleInfo",
column: "GuildConfigId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "VcRoleInfo");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class cradandcrdm : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "AutoDeleteTrigger",
table: "CustomReactions",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<bool>(
name: "DmResponse",
table: "CustomReactions",
nullable: false,
defaultValue: false);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "AutoDeleteTrigger",
table: "CustomReactions");
migrationBuilder.DropColumn(
name: "DmResponse",
table: "CustomReactions");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class commandaliasing : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "CommandAlias",
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),
Mapping = table.Column<string>(nullable: true),
Trigger = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_CommandAlias", x => x.Id);
table.ForeignKey(
name: "FK_CommandAlias_GuildConfigs_GuildConfigId",
column: x => x.GuildConfigId,
principalTable: "GuildConfigs",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_CommandAlias_GuildConfigId",
table: "CommandAlias",
column: "GuildConfigId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "CommandAlias");
}
}
}

View File

@ -207,6 +207,26 @@ namespace NadekoBot.Migrations
b.ToTable("ClashOfClans"); b.ToTable("ClashOfClans");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime?>("DateAdded");
b.Property<int?>("GuildConfigId");
b.Property<string>("Mapping");
b.Property<string>("Trigger");
b.HasKey("Id");
b.HasIndex("GuildConfigId");
b.ToTable("CommandAlias");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -310,8 +330,12 @@ namespace NadekoBot.Migrations
b.Property<int>("Id") b.Property<int>("Id")
.ValueGeneratedOnAdd(); .ValueGeneratedOnAdd();
b.Property<bool>("AutoDeleteTrigger");
b.Property<DateTime?>("DateAdded"); b.Property<DateTime?>("DateAdded");
b.Property<bool>("DmResponse");
b.Property<ulong?>("GuildId"); b.Property<ulong?>("GuildId");
b.Property<bool>("IsRegex"); b.Property<bool>("IsRegex");
@ -764,6 +788,34 @@ namespace NadekoBot.Migrations
b.ToTable("Permission"); b.ToTable("Permission");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime?>("DateAdded");
b.Property<int?>("GuildConfigId");
b.Property<int>("Index");
b.Property<int>("PrimaryTarget");
b.Property<ulong>("PrimaryTargetId");
b.Property<int>("SecondaryTarget");
b.Property<string>("SecondaryTargetName");
b.Property<bool>("State");
b.HasKey("Id");
b.HasIndex("GuildConfigId");
b.ToTable("Permissionv2");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -896,6 +948,26 @@ namespace NadekoBot.Migrations
b.ToTable("SelfAssignableRoles"); b.ToTable("SelfAssignableRoles");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime?>("DateAdded");
b.Property<int?>("GuildConfigId");
b.Property<DateTime>("UnmuteAt");
b.Property<ulong>("UserId");
b.HasKey("Id");
b.HasIndex("GuildConfigId");
b.ToTable("UnmuteTimer");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.UserPokeTypes", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.UserPokeTypes", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -915,6 +987,26 @@ namespace NadekoBot.Migrations
b.ToTable("PokeGame"); b.ToTable("PokeGame");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime?>("DateAdded");
b.Property<int?>("GuildConfigId");
b.Property<ulong>("RoleId");
b.Property<ulong>("VoiceChannelId");
b.HasKey("Id");
b.HasIndex("GuildConfigId");
b.ToTable("VcRoleInfo");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -1006,6 +1098,13 @@ namespace NadekoBot.Migrations
.OnDelete(DeleteBehavior.Cascade); .OnDelete(DeleteBehavior.Cascade);
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
.WithMany("CommandAliases")
.HasForeignKey("GuildConfigId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b =>
{ {
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
@ -1112,6 +1211,13 @@ namespace NadekoBot.Migrations
.HasForeignKey("NadekoBot.Services.Database.Models.Permission", "NextId"); .HasForeignKey("NadekoBot.Services.Database.Models.Permission", "NextId");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
.WithMany("Permissions")
.HasForeignKey("GuildConfigId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b =>
{ {
b.HasOne("NadekoBot.Services.Database.Models.BotConfig") b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
@ -1134,6 +1240,20 @@ namespace NadekoBot.Migrations
.HasForeignKey("BotConfigId"); .HasForeignKey("BotConfigId");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
.WithMany("UnmuteTimers")
.HasForeignKey("GuildConfigId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
.WithMany("VcRoleInfos")
.HasForeignKey("GuildConfigId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b =>
{ {
b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "Affinity") b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "Affinity")

View File

@ -11,6 +11,7 @@ using Discord.WebSocket;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using static NadekoBot.Modules.Permissions.Permissions; using static NadekoBot.Modules.Permissions.Permissions;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using Microsoft.EntityFrameworkCore;
using NLog; using NLog;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
@ -56,20 +57,12 @@ namespace NadekoBot.Modules.Administration
[RequireUserPermission(GuildPermission.Administrator)] [RequireUserPermission(GuildPermission.Administrator)]
public async Task ResetPermissions() public async Task ResetPermissions()
{ {
var channel = (ITextChannel)Context.Channel;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.PermissionsFor(Context.Guild.Id); var config = uow.GuildConfigs.GcWithPermissionsv2For(Context.Guild.Id);
config.RootPermission = Permission.GetDefaultRoot(); config.Permissions = Permissionv2.GetDefaultPermlist;
var toAdd = new PermissionCache()
{
RootPermission = config.RootPermission,
PermRole = config.PermissionRole,
Verbose = config.VerbosePermissions,
};
Cache.AddOrUpdate(channel.Guild.Id,
toAdd, (id, old) => toAdd);
await uow.CompleteAsync(); await uow.CompleteAsync();
UpdateCache(config);
} }
await ReplyConfirmLocalized("perms_reset").ConfigureAwait(false); await ReplyConfirmLocalized("perms_reset").ConfigureAwait(false);
} }

View File

@ -18,14 +18,21 @@ namespace NadekoBot.Modules.Administration
{ {
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-CN", "Chinese (Simplified), China"},
{"nl-NL", "Dutch, Netherlands"},
{"en-US", "English, United States"}, {"en-US", "English, United States"},
{"fr-FR", "French, France"}, {"fr-FR", "French, France"},
{"ru-RU", "Russian, Russia"},
{"de-DE", "German, Germany"}, {"de-DE", "German, Germany"},
//{"nl-NL", "Dutch, Netherlands"},
//{"ja-JP", "Japanese, Japan"}, //{"ja-JP", "Japanese, Japan"},
{"nb-NO", "Norwegian (bokmål), Norway"},
{"pl-PL", "Polish, Poland" },
{"pt-BR", "Portuguese, Brazil"}, {"pt-BR", "Portuguese, Brazil"},
//{"sr-Cyrl-RS", "Serbian, Serbia - Cyrillic"} {"ru-RU", "Russian, Russia"},
{"sr-Cyrl-RS", "Serbian, Serbia - Cyrillic"},
{"es-ES", "Spanish, Spain"},
{"sv-SE", "Swedish, Sweden"},
{"tr-TR", "Turkish, Turkey" }
}.ToImmutableDictionary(); }.ToImmutableDictionary();
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
@ -97,11 +104,10 @@ namespace NadekoBot.Modules.Administration
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task LanguagesList() public async Task LanguagesList()
{ {
await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor() await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithTitle(GetText("lang_list", "")) .WithTitle(GetText("lang_list"))
.WithDescription(string.Join("\n", .WithDescription(string.Join("\n",
supportedLocales.Select(x => $"{Format.Code(x.Key), -10} => {x.Value}")))); supportedLocales.Select(x => $"{Format.Code(x.Key), -10} => {x.Value}"))));
} }

View File

@ -2,13 +2,13 @@
using Discord.Commands; using Discord.Commands;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using NLog; using NLog;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
@ -20,6 +20,8 @@ namespace NadekoBot.Modules.Administration
{ {
private static ConcurrentDictionary<ulong, string> guildMuteRoles { get; } private static ConcurrentDictionary<ulong, string> guildMuteRoles { get; }
private static ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>> mutedUsers { get; } private static ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>> mutedUsers { get; }
private static ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, Timer>> unmuteTimers { get; }
= new ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, Timer>>();
public static event Action<IGuildUser, MuteType> UserMuted = delegate { }; public static event Action<IGuildUser, MuteType> UserMuted = delegate { };
public static event Action<IGuildUser, MuteType> UserUnmuted = delegate { }; public static event Action<IGuildUser, MuteType> UserUnmuted = delegate { };
@ -43,6 +45,23 @@ namespace NadekoBot.Modules.Administration
v => new ConcurrentHashSet<ulong>(v.MutedUsers.Select(m => m.UserId)) v => new ConcurrentHashSet<ulong>(v.MutedUsers.Select(m => m.UserId))
)); ));
foreach (var conf in configs)
{
foreach (var x in conf.UnmuteTimers)
{
TimeSpan after;
if (x.UnmuteAt - TimeSpan.FromMinutes(2) <= DateTime.UtcNow)
{
after = TimeSpan.FromMinutes(2);
}
else
{
after = x.UnmuteAt - DateTime.UtcNow;
}
StartUnmuteTimer(conf.GuildId, x.UserId, after);
}
}
NadekoBot.Client.UserJoined += Client_UserJoined; NadekoBot.Client.UserJoined += Client_UserJoined;
} }
@ -67,10 +86,15 @@ namespace NadekoBot.Modules.Administration
public static async Task MuteUser(IGuildUser usr) public static async Task MuteUser(IGuildUser usr)
{ {
await usr.ModifyAsync(x => x.Mute = true).ConfigureAwait(false); await usr.ModifyAsync(x => x.Mute = true).ConfigureAwait(false);
await usr.AddRolesAsync(await GetMuteRole(usr.Guild)).ConfigureAwait(false); var muteRole = await GetMuteRole(usr.Guild);
if (!usr.RoleIds.Contains(muteRole.Id))
await usr.AddRolesAsync(muteRole).ConfigureAwait(false);
StopUnmuteTimer(usr.GuildId, usr.Id);
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.For(usr.Guild.Id, set => set.Include(gc => gc.MutedUsers)); var config = uow.GuildConfigs.For(usr.Guild.Id,
set => set.Include(gc => gc.MutedUsers)
.Include(gc => gc.UnmuteTimers));
config.MutedUsers.Add(new MutedUserId() config.MutedUsers.Add(new MutedUserId()
{ {
UserId = usr.Id UserId = usr.Id
@ -79,6 +103,8 @@ namespace NadekoBot.Modules.Administration
if (mutedUsers.TryGetValue(usr.Guild.Id, out muted)) if (mutedUsers.TryGetValue(usr.Guild.Id, out muted))
muted.Add(usr.Id); muted.Add(usr.Id);
config.UnmuteTimers.RemoveWhere(x => x.UserId == usr.Id);
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
UserMuted(usr, MuteType.All); UserMuted(usr, MuteType.All);
@ -86,11 +112,13 @@ namespace NadekoBot.Modules.Administration
public static async Task UnmuteUser(IGuildUser usr) public static async Task UnmuteUser(IGuildUser usr)
{ {
await usr.ModifyAsync(x => x.Mute = false).ConfigureAwait(false); StopUnmuteTimer(usr.GuildId, usr.Id);
await usr.RemoveRolesAsync(await GetMuteRole(usr.Guild)).ConfigureAwait(false); try { await usr.ModifyAsync(x => x.Mute = false).ConfigureAwait(false); } catch { }
try { await usr.RemoveRolesAsync(await GetMuteRole(usr.Guild)).ConfigureAwait(false); } catch { /*ignore*/ }
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.For(usr.Guild.Id, set => set.Include(gc => gc.MutedUsers)); var config = uow.GuildConfigs.For(usr.Guild.Id, set => set.Include(gc => gc.MutedUsers)
.Include(gc => gc.UnmuteTimers));
config.MutedUsers.Remove(new MutedUserId() config.MutedUsers.Remove(new MutedUserId()
{ {
UserId = usr.Id UserId = usr.Id
@ -98,6 +126,9 @@ namespace NadekoBot.Modules.Administration
ConcurrentHashSet<ulong> muted; ConcurrentHashSet<ulong> muted;
if (mutedUsers.TryGetValue(usr.Guild.Id, out muted)) if (mutedUsers.TryGetValue(usr.Guild.Id, out muted))
muted.TryRemove(usr.Id); muted.TryRemove(usr.Id);
config.UnmuteTimers.RemoveWhere(x => x.UserId == usr.Id);
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
UserUnmuted(usr, MuteType.All); UserUnmuted(usr, MuteType.All);
@ -139,6 +170,79 @@ namespace NadekoBot.Modules.Administration
return muteRole; return muteRole;
} }
public static async Task TimedMute(IGuildUser user, TimeSpan after)
{
await MuteUser(user).ConfigureAwait(false); // mute the user. This will also remove any previous unmute timers
using (var uow = DbHandler.UnitOfWork())
{
var config = uow.GuildConfigs.For(user.GuildId, set => set.Include(x => x.UnmuteTimers));
config.UnmuteTimers.Add(new UnmuteTimer()
{
UserId = user.Id,
UnmuteAt = DateTime.UtcNow + after,
}); // add teh unmute timer to the database
uow.Complete();
}
StartUnmuteTimer(user.GuildId, user.Id, after); // start the timer
}
public static void StartUnmuteTimer(ulong guildId, ulong userId, TimeSpan after)
{
//load the unmute timers for this guild
var userUnmuteTimers = unmuteTimers.GetOrAdd(guildId, new ConcurrentDictionary<ulong, Timer>());
//unmute timer to be added
var toAdd = new Timer(async _ =>
{
try
{
var guild = NadekoBot.Client.GetGuild(guildId); // load the guild
if (guild == null)
{
RemoveUnmuteTimerFromDb(guildId, userId);
return; // if guild can't be found, just remove the timer from db
}
// unmute the user, this will also remove the timer from the db
await UnmuteUser(guild.GetUser(userId)).ConfigureAwait(false);
}
catch (Exception ex)
{
RemoveUnmuteTimerFromDb(guildId, userId); // if unmute errored, just remove unmute from db
Administration._log.Warn("Couldn't unmute user {0} in guild {1}", userId, guildId);
Administration._log.Warn(ex);
}
}, null, after, Timeout.InfiniteTimeSpan);
//add it, or stop the old one and add this one
userUnmuteTimers.AddOrUpdate(userId, (key) => toAdd, (key, old) =>
{
old.Change(Timeout.Infinite, Timeout.Infinite);
return toAdd;
});
}
public static void StopUnmuteTimer(ulong guildId, ulong userId)
{
ConcurrentDictionary<ulong, Timer> userUnmuteTimers;
if (!unmuteTimers.TryGetValue(guildId, out userUnmuteTimers)) return;
Timer removed;
if(userUnmuteTimers.TryRemove(userId, out removed))
{
removed.Change(Timeout.Infinite, Timeout.Infinite);
}
}
private static void RemoveUnmuteTimerFromDb(ulong guildId, ulong userId)
{
using (var uow = DbHandler.UnitOfWork())
{
var config = uow.GuildConfigs.For(guildId, set => set.Include(x => x.UnmuteTimers));
config.UnmuteTimers.RemoveWhere(x => x.UserId == userId);
uow.Complete();
}
}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
@ -170,6 +274,7 @@ namespace NadekoBot.Modules.Administration
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
[RequireUserPermission(GuildPermission.MuteMembers)] [RequireUserPermission(GuildPermission.MuteMembers)]
[Priority(1)]
public async Task Mute(IGuildUser user) public async Task Mute(IGuildUser user)
{ {
try try
@ -183,6 +288,27 @@ namespace NadekoBot.Modules.Administration
} }
} }
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageRoles)]
[RequireUserPermission(GuildPermission.MuteMembers)]
[Priority(0)]
public async Task Mute(int minutes, IGuildUser user)
{
if (minutes < 1 || minutes > 1440)
return;
try
{
await TimedMute(user, TimeSpan.FromMinutes(minutes)).ConfigureAwait(false);
await ReplyConfirmLocalized("user_muted_time", Format.Bold(user.ToString()), minutes).ConfigureAwait(false);
}
catch (Exception ex)
{
_log.Warn(ex);
await ReplyErrorLocalized("mute_error").ConfigureAwait(false);
}
}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]

View File

@ -46,16 +46,18 @@ namespace NadekoBot.Modules.Administration
LastMessage = msg.ToUpperInvariant(); LastMessage = msg.ToUpperInvariant();
} }
public void ApplyNextMessage(string message) public void ApplyNextMessage(IUserMessage message)
{ {
var upperMsg = message.ToUpperInvariant(); var upperMsg = message.Content.ToUpperInvariant();
if (upperMsg == LastMessage) if (upperMsg != LastMessage || (string.IsNullOrWhiteSpace(upperMsg) && message.Attachments.Any()))
Count++;
else
{ {
LastMessage = upperMsg; LastMessage = upperMsg;
Count = 0; Count = 0;
} }
else
{
Count++;
}
} }
} }
@ -113,7 +115,7 @@ namespace NadekoBot.Modules.Administration
var stats = spamSettings.UserStats.AddOrUpdate(msg.Author.Id, new UserSpamStats(msg.Content), var stats = spamSettings.UserStats.AddOrUpdate(msg.Author.Id, new UserSpamStats(msg.Content),
(id, old) => (id, old) =>
{ {
old.ApplyNextMessage(msg.Content); return old; old.ApplyNextMessage(msg); return old;
}); });
if (stats.Count >= spamSettings.AntiSpamSettings.MessageThreshold) if (stats.Count >= spamSettings.AntiSpamSettings.MessageThreshold)

View File

@ -150,11 +150,11 @@ namespace NadekoBot.Modules.Administration
var guildUser = (IGuildUser)Context.User; var guildUser = (IGuildUser)Context.User;
GuildConfig conf; GuildConfig conf;
IEnumerable<SelfAssignedRole> roles; SelfAssignedRole[] roles;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
conf = uow.GuildConfigs.For(Context.Guild.Id, set => set); conf = uow.GuildConfigs.For(Context.Guild.Id, set => set);
roles = uow.SelfAssignedRoles.GetFromGuild(Context.Guild.Id); roles = uow.SelfAssignedRoles.GetFromGuild(Context.Guild.Id).ToArray();
} }
if (roles.FirstOrDefault(r=>r.RoleId == role.Id) == null) if (roles.FirstOrDefault(r=>r.RoleId == role.Id) == null)
{ {
@ -167,14 +167,21 @@ namespace NadekoBot.Modules.Administration
return; return;
} }
var roleIds = roles.Select(x => x.RoleId).ToArray();
if (conf.ExclusiveSelfAssignedRoles) if (conf.ExclusiveSelfAssignedRoles)
{ {
var sameRoleId = guildUser.RoleIds.FirstOrDefault(r => roles.Select(sar => sar.RoleId).Contains(r)); var sameRoleId = guildUser.RoleIds.FirstOrDefault(r => roleIds.Contains(r));
var sameRole = Context.Guild.GetRole(sameRoleId);
if (sameRoleId != default(ulong)) if (sameRoleId != default(ulong))
{ {
await ReplyErrorLocalized("self_assign_already_excl", Format.Bold(sameRole?.Name)).ConfigureAwait(false); var sameRole = Context.Guild.GetRole(sameRoleId);
return; if (sameRole != null)
{
await guildUser.RemoveRolesAsync(sameRole).ConfigureAwait(false);
await Task.Delay(500).ConfigureAwait(false);
}
//await ReplyErrorLocalized("self_assign_already_excl", Format.Bold(sameRole?.Name)).ConfigureAwait(false);
//return;
} }
} }
try try

View File

@ -0,0 +1,186 @@
using System;
using System.Collections.Concurrent;
using System.Linq;
using Discord;
using Discord.Commands;
using NadekoBot.Attributes;
using System.Threading.Tasks;
using Discord.WebSocket;
using Microsoft.EntityFrameworkCore;
using NadekoBot.Extensions;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
namespace NadekoBot.Modules.Administration
{
public partial class Administration
{
[Group]
public class VcRoleCommands : NadekoSubmodule
{
private static ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, IRole>> vcRoles { get; }
static VcRoleCommands()
{
NadekoBot.Client.UserVoiceStateUpdated += ClientOnUserVoiceStateUpdated;
vcRoles = new ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, IRole>>();
foreach (var gconf in NadekoBot.AllGuildConfigs)
{
var g = NadekoBot.Client.GetGuild(gconf.GuildId);
if (g == null)
continue; //todo delete everything from db if guild doesn't exist?
var infos = new ConcurrentDictionary<ulong, IRole>();
vcRoles.TryAdd(gconf.GuildId, infos);
foreach (var ri in gconf.VcRoleInfos)
{
var role = g.GetRole(ri.RoleId);
if (role == null)
continue; //todo remove this entry from db
infos.TryAdd(ri.VoiceChannelId, role);
}
}
}
private static Task ClientOnUserVoiceStateUpdated(SocketUser usr, SocketVoiceState oldState,
SocketVoiceState newState)
{
var gusr = usr as SocketGuildUser;
if (gusr == null)
return Task.CompletedTask;
var oldVc = oldState.VoiceChannel;
var newVc = newState.VoiceChannel;
var _ = Task.Run(async () =>
{
try
{
if (oldVc != newVc)
{
ulong guildId;
guildId = newVc?.Guild.Id ?? oldVc.Guild.Id;
ConcurrentDictionary<ulong, IRole> guildVcRoles;
if (vcRoles.TryGetValue(guildId, out guildVcRoles))
{
IRole role;
//remove old
if (oldVc != null && guildVcRoles.TryGetValue(oldVc.Id, out role))
{
if (gusr.RoleIds.Contains(role.Id))
{
try
{
await gusr.RemoveRolesAsync(role).ConfigureAwait(false);
await Task.Delay(500).ConfigureAwait(false);
}
catch
{
await Task.Delay(200).ConfigureAwait(false);
await gusr.RemoveRolesAsync(role).ConfigureAwait(false);
await Task.Delay(500).ConfigureAwait(false);
}
}
}
//add new
if (newVc != null && guildVcRoles.TryGetValue(newVc.Id, out role))
{
if (!gusr.RoleIds.Contains(role.Id))
await gusr.AddRolesAsync(role).ConfigureAwait(false);
}
}
}
}
catch (Exception ex)
{
Administration._log.Warn(ex);
}
});
return Task.CompletedTask;
}
[NadekoCommand, Usage, Description, Aliases]
[RequireUserPermission(GuildPermission.ManageRoles)]
[RequireUserPermission(GuildPermission.ManageChannels)]
[RequireBotPermission(GuildPermission.ManageRoles)]
// todo wait for the fix [RequireBotPermission(GuildPermission.ManageChannels)]
[RequireContext(ContextType.Guild)]
public async Task VcRole([Remainder]IRole role = null)
{
var user = (IGuildUser) Context.User;
var vc = user.VoiceChannel;
if (vc == null || vc.GuildId != user.GuildId)
{
await ReplyErrorLocalized("must_be_in_voice").ConfigureAwait(false);
return;
}
var guildVcRoles = vcRoles.GetOrAdd(user.GuildId, new ConcurrentDictionary<ulong, IRole>());
if (role == null)
{
if (guildVcRoles.TryRemove(vc.Id, out role))
{
await ReplyConfirmLocalized("vcrole_removed", Format.Bold(vc.Name)).ConfigureAwait(false);
using (var uow = DbHandler.UnitOfWork())
{
var conf = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.VcRoleInfos));
conf.VcRoleInfos.RemoveWhere(x => x.VoiceChannelId == vc.Id);
uow.Complete();
}
}
}
else
{
guildVcRoles.AddOrUpdate(vc.Id, role, (key, old) => role);
using (var uow = DbHandler.UnitOfWork())
{
var conf = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.VcRoleInfos));
conf.VcRoleInfos.RemoveWhere(x => x.VoiceChannelId == vc.Id); // remove old one
conf.VcRoleInfos.Add(new VcRoleInfo()
{
VoiceChannelId = vc.Id,
RoleId = role.Id,
}); // add new one
uow.Complete();
}
await ReplyConfirmLocalized("vcrole_added", Format.Bold(vc.Name), Format.Bold(role.Name)).ConfigureAwait(false);
}
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task VcRoleList()
{
var guild = (SocketGuild) Context.Guild;
string text;
ConcurrentDictionary<ulong, IRole> roles;
if (vcRoles.TryGetValue(Context.Guild.Id, out roles))
{
if (!roles.Any())
{
text = GetText("no_vcroles");
}
else
{
text = string.Join("\n", roles.Select(x =>
$"{Format.Bold(guild.GetVoiceChannel(x.Key)?.Name ?? x.Key.ToString())} => {x.Value}"));
}
}
else
{
text = GetText("no_vcroles");
}
await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithTitle(GetText("vc_role_list"))
.WithDescription(text))
.ConfigureAwait(false);
}
}
}
}

View File

@ -166,7 +166,7 @@ namespace NadekoBot.Modules.Administration
var botUser = await guild.GetCurrentUserAsync().ConfigureAwait(false); var botUser = await guild.GetCurrentUserAsync().ConfigureAwait(false);
if (!botUser.GuildPermissions.ManageRoles || !botUser.GuildPermissions.ManageChannels) if (!botUser.GuildPermissions.ManageRoles || !botUser.GuildPermissions.ManageChannels)
{ {
await ReplyErrorLocalized("vt_no_perms").ConfigureAwait(false); await ReplyErrorLocalized("vt_perms").ConfigureAwait(false);
return; return;
} }

View File

@ -11,11 +11,27 @@ using NLog;
using System.Diagnostics; using System.Diagnostics;
using Discord.WebSocket; using Discord.WebSocket;
using System; using System;
using Newtonsoft.Json;
using NadekoBot.DataStructures; using NadekoBot.DataStructures;
namespace NadekoBot.Modules.CustomReactions namespace NadekoBot.Modules.CustomReactions
{ {
public static class CustomReactionExtensions
{
public static async Task<IUserMessage> Send(this CustomReaction cr, IUserMessage context)
{
var channel = cr.DmResponse ? await context.Author.CreateDMChannelAsync() : context.Channel;
CustomReactions.ReactionStats.AddOrUpdate(cr.Trigger, 1, (k, old) => ++old);
CREmbed crembed;
if (CREmbed.TryParse(cr.Response, out crembed))
{
return await channel.EmbedAsync(crembed.ToEmbed(), crembed.PlainText ?? "");
}
return await channel.SendMessageAsync(cr.ResponseWithContext(context));
}
}
[NadekoModule("CustomReactions", ".")] [NadekoModule("CustomReactions", ".")]
public class CustomReactions : NadekoTopLevelModule public class CustomReactions : NadekoTopLevelModule
{ {
@ -25,7 +41,7 @@ namespace NadekoBot.Modules.CustomReactions
public static ConcurrentDictionary<string, uint> ReactionStats { get; } = new ConcurrentDictionary<string, uint>(); public static ConcurrentDictionary<string, uint> ReactionStats { get; } = new ConcurrentDictionary<string, uint>();
private static new readonly Logger _log; private new static readonly Logger _log;
static CustomReactions() static CustomReactions()
{ {
@ -43,11 +59,11 @@ namespace NadekoBot.Modules.CustomReactions
public void ClearStats() => ReactionStats.Clear(); public void ClearStats() => ReactionStats.Clear();
public static async Task<bool> TryExecuteCustomReaction(SocketUserMessage umsg) public static CustomReaction TryGetCustomReaction(SocketUserMessage umsg)
{ {
var channel = umsg.Channel as SocketTextChannel; var channel = umsg.Channel as SocketTextChannel;
if (channel == null) if (channel == null)
return false; return null;
var content = umsg.Content.Trim().ToLowerInvariant(); var content = umsg.Content.Trim().ToLowerInvariant();
CustomReaction[] reactions; CustomReaction[] reactions;
@ -70,26 +86,9 @@ namespace NadekoBot.Modules.CustomReactions
var reaction = rs[new NadekoRandom().Next(0, rs.Length)]; var reaction = rs[new NadekoRandom().Next(0, rs.Length)];
if (reaction != null) if (reaction != null)
{ {
if (reaction.Response != "-") if (reaction.Response == "-")
{ return null;
CREmbed crembed; return reaction;
if (CREmbed.TryParse(reaction.Response, out crembed))
{
try { await channel.EmbedAsync(crembed.ToEmbed(), crembed.PlainText ?? "").ConfigureAwait(false); }
catch (Exception ex)
{
_log.Warn("Sending CREmbed failed");
_log.Warn(ex);
}
}
else
{
try { await channel.SendMessageAsync(reaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { }
}
}
ReactionStats.AddOrUpdate(reaction.Trigger, 1, (k, old) => ++old);
return true;
} }
} }
} }
@ -103,29 +102,10 @@ namespace NadekoBot.Modules.CustomReactions
return ((hasTarget && content.StartsWith(trigger + " ")) || content == trigger); return ((hasTarget && content.StartsWith(trigger + " ")) || content == trigger);
}).ToArray(); }).ToArray();
if (grs.Length == 0) if (grs.Length == 0)
return false; return null;
var greaction = grs[new NadekoRandom().Next(0, grs.Length)]; var greaction = grs[new NadekoRandom().Next(0, grs.Length)];
if (greaction != null) return greaction;
{
CREmbed crembed;
if (CREmbed.TryParse(greaction.Response, out crembed))
{
try { await channel.EmbedAsync(crembed.ToEmbed(), crembed.PlainText ?? "").ConfigureAwait(false); }
catch (Exception ex)
{
_log.Warn("Sending CREmbed failed");
_log.Warn(ex);
}
}
else
{
try { await channel.SendMessageAsync(greaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { }
}
ReactionStats.AddOrUpdate(greaction.Trigger, 1, (k, old) => ++old);
return true;
}
return false;
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
@ -359,6 +339,108 @@ namespace NadekoBot.Modules.CustomReactions
} }
} }
[NadekoCommand, Usage, Description, Aliases]
public async Task CrDm(int id)
{
if ((Context.Guild == null && !NadekoBot.Credentials.IsOwner(Context.User)) ||
(Context.Guild != null && !((IGuildUser)Context.User).GuildPermissions.Administrator))
{
await ReplyErrorLocalized("insuff_perms").ConfigureAwait(false);
return;
}
CustomReaction[] reactions = new CustomReaction[0];
if (Context.Guild == null)
reactions = GlobalReactions;
else
{
GuildReactions.TryGetValue(Context.Guild.Id, out reactions);
}
if (reactions.Any())
{
var reaction = reactions.FirstOrDefault(x => x.Id == id);
if (reaction == null)
{
await ReplyErrorLocalized("no_found_id").ConfigureAwait(false);
return;
}
var setValue = reaction.DmResponse = !reaction.DmResponse;
using (var uow = DbHandler.UnitOfWork())
{
uow.CustomReactions.Get(id).DmResponse = setValue;
uow.Complete();
}
if (setValue)
{
await ReplyConfirmLocalized("crdm_enabled", Format.Code(reaction.Id.ToString())).ConfigureAwait(false);
}
else
{
await ReplyConfirmLocalized("crdm_disabled", Format.Code(reaction.Id.ToString())).ConfigureAwait(false);
}
}
else
{
await ReplyErrorLocalized("no_found").ConfigureAwait(false);
}
}
[NadekoCommand, Usage, Description, Aliases]
public async Task CrAd(int id)
{
if ((Context.Guild == null && !NadekoBot.Credentials.IsOwner(Context.User)) ||
(Context.Guild != null && !((IGuildUser)Context.User).GuildPermissions.Administrator))
{
await ReplyErrorLocalized("insuff_perms").ConfigureAwait(false);
return;
}
CustomReaction[] reactions = new CustomReaction[0];
if (Context.Guild == null)
reactions = GlobalReactions;
else
{
GuildReactions.TryGetValue(Context.Guild.Id, out reactions);
}
if (reactions.Any())
{
var reaction = reactions.FirstOrDefault(x => x.Id == id);
if (reaction == null)
{
await ReplyErrorLocalized("no_found_id").ConfigureAwait(false);
return;
}
var setValue = reaction.AutoDeleteTrigger = !reaction.AutoDeleteTrigger;
using (var uow = DbHandler.UnitOfWork())
{
uow.CustomReactions.Get(id).AutoDeleteTrigger = setValue;
uow.Complete();
}
if (setValue)
{
await ReplyConfirmLocalized("crad_enabled", Format.Code(reaction.Id.ToString())).ConfigureAwait(false);
}
else
{
await ReplyConfirmLocalized("crad_disabled", Format.Code(reaction.Id.ToString())).ConfigureAwait(false);
}
}
else
{
await ReplyErrorLocalized("no_found").ConfigureAwait(false);
}
}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[OwnerOnly] [OwnerOnly]
public async Task CrStatsClear(string trigger = null) public async Task CrStatsClear(string trigger = null)

View File

@ -0,0 +1,197 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord.Commands;
using Discord;
using NadekoBot.Attributes;
using NadekoBot.Extensions;
using NadekoBot.Services;
namespace NadekoBot.Modules.Gambling
{
//public partial class Gambling
//{
// [Group]
// public class Lucky7Commands : NadekoSubmodule
// {
// [NadekoCommand, Usage, Description, Aliases]
// [RequireContext(ContextType.Guild)]
// [OwnerOnly]
// public async Task Lucky7Test(uint tests)
// {
// if (tests <= 0)
// return;
// var dict = new Dictionary<float, int>();
// var totalWon = 0;
// for (var i = 0; i < tests; i++)
// {
// var g = new Lucky7Game(10);
// while (!g.Ended)
// {
// if (g.CurrentPosition == 0)
// g.Stay();
// else
// g.Move();
// }
// totalWon += (int)(g.CurrentMultiplier * g.Bet);
// if (!dict.ContainsKey(g.CurrentMultiplier))
// dict.Add(g.CurrentMultiplier, 0);
// dict[g.CurrentMultiplier] ++;
// }
// await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
// .WithTitle("Move Or Stay test")
// .WithDescription(string.Join("\n",
// dict.Select(x => $"x{x.Key} occured {x.Value} times {x.Value * 1.0f / tests * 100:F2}%")))
// .WithFooter(
// efb => efb.WithText($"Total Bet: {tests * 10} | Payout: {totalWon} | {totalWon *1.0f / tests * 10}%")));
// }
// private static readonly ConcurrentDictionary<ulong, Lucky7Game> _games =
// new ConcurrentDictionary<ulong, Lucky7Game>();
// [NadekoCommand, Usage, Description, Aliases]
// [RequireContext(ContextType.Guild)]
// public async Task Lucky7(int bet)
// {
// if (bet < 4)
// return;
// var game = new Lucky7Game(bet);
// if (!_games.TryAdd(Context.User.Id, game))
// {
// await ReplyAsync("You're already betting on move or stay.").ConfigureAwait(false);
// return;
// }
// if (!await CurrencyHandler.RemoveCurrencyAsync(Context.User, "MoveOrStay bet", bet, false))
// {
// _games.TryRemove(Context.User.Id, out game);
// await ReplyConfirmLocalized("not_enough", CurrencySign).ConfigureAwait(false);
// return;
// }
// await Context.Channel.EmbedAsync(GetGameState(game),
// string.Format("{0} rolled {1}.", Context.User, game.Rolled)).ConfigureAwait(false);
// }
// public enum MoveOrStay
// {
// Move = 1,
// M = 1,
// Stay = 2,
// S = 2
// }
// [NadekoCommand, Usage, Description, Aliases]
// [RequireContext(ContextType.Guild)]
// public async Task Lucky7(MoveOrStay action)
// {
// Lucky7Game game;
// if (!_games.TryGetValue(Context.User.Id, out game))
// {
// await ReplyAsync("You're not betting on move or stay.").ConfigureAwait(false);
// return;
// }
// if (action == MoveOrStay.Move)
// {
// game.Move();
// await Context.Channel.EmbedAsync(GetGameState(game),
// string.Format("{0} rolled {1}.", Context.User, game.Rolled)).ConfigureAwait(false);
// if (game.Ended)
// _games.TryRemove(Context.User.Id, out game);
// }
// else if (action == MoveOrStay.Stay)
// {
// var won = game.Stay();
// await CurrencyHandler.AddCurrencyAsync(Context.User, "MoveOrStay stay", won, false)
// .ConfigureAwait(false);
// _games.TryRemove(Context.User.Id, out game);
// await ReplyAsync(string.Format("You've finished with {0}",
// won + CurrencySign))
// .ConfigureAwait(false);
// }
// }
// private EmbedBuilder GetGameState(Lucky7Game game)
// {
// var arr = Lucky7Game.Winnings.ToArray();
// var sb = new StringBuilder();
// for (var i = 0; i < arr.Length; i++)
// {
// if (i == game.CurrentPosition)
// {
// sb.Append("[" + arr[i] + "]");
// }
// else
// {
// sb.Append(arr[i].ToString());
// }
// if (i != arr.Length - 1)
// sb.Append(' ');
// }
// return new EmbedBuilder().WithOkColor()
// .WithTitle("Lucky7")
// .WithDescription(sb.ToString())
// .AddField(efb => efb.WithName("Bet")
// .WithValue(game.Bet.ToString())
// .WithIsInline(true))
// .AddField(efb => efb.WithName("Current Value")
// .WithValue((game.CurrentMultiplier * game.Bet).ToString(_cultureInfo))
// .WithIsInline(true));
// }
// }
// public class Lucky7Game
// {
// public int Bet { get; }
// public bool Ended { get; private set; }
// public int PreviousPosition { get; private set; }
// public int CurrentPosition { get; private set; } = -1;
// public int Rolled { get; private set; }
// public float CurrentMultiplier => Winnings[CurrentPosition];
// private readonly NadekoRandom _rng = new NadekoRandom();
// public static readonly ImmutableArray<float> Winnings = new[]
// {
// 1.2f, 0.8f, 0.75f, 0.90f, 0.7f, 0.5f, 1.8f, 0f, 0f
// }.ToImmutableArray();
// public Lucky7Game(int bet)
// {
// Bet = bet;
// Move();
// }
// public void Move()
// {
// if (Ended)
// return;
// PreviousPosition = CurrentPosition;
// Rolled = _rng.Next(1, 4);
// CurrentPosition += Rolled;
// if (CurrentPosition >= 6)
// Ended = true;
// }
// public int Stay()
// {
// if (Ended)
// return 0;
// Ended = true;
// return (int) (CurrentMultiplier * Bet);
// }
// }
//}
}

View File

@ -223,7 +223,7 @@ namespace NadekoBot.Modules.Gambling
{ {
var _ = Task.Run(async () => var _ = Task.Run(async () =>
{ {
await Task.Delay(2000); await Task.Delay(1500);
_runningUsers.Remove(Context.User.Id); _runningUsers.Remove(Context.User.Id);
}); });
} }

View File

@ -395,7 +395,7 @@ namespace NadekoBot.Modules.Gambling
target = Context.User; target = Context.User;
WaifuInfo w; WaifuInfo w;
IList<WaifuInfo> claims; IList<WaifuInfo> claims;
int divorces = 0; int divorces;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
w = uow.Waifus.ByWaifuUserId(target.Id); w = uow.Waifus.ByWaifuUserId(target.Id);
@ -434,7 +434,7 @@ namespace NadekoBot.Modules.Gambling
.AddField(efb => efb.WithName(GetText("likes")).WithValue(w.Affinity?.ToString() ?? nobody).WithIsInline(true)) .AddField(efb => efb.WithName(GetText("likes")).WithValue(w.Affinity?.ToString() ?? nobody).WithIsInline(true))
.AddField(efb => efb.WithName(GetText("changes_of_heart")).WithValue($"{affInfo.Count} - \"the {affInfo.Title}\"").WithIsInline(true)) .AddField(efb => efb.WithName(GetText("changes_of_heart")).WithValue($"{affInfo.Count} - \"the {affInfo.Title}\"").WithIsInline(true))
.AddField(efb => efb.WithName(GetText("divorces")).WithValue(divorces.ToString()).WithIsInline(true)) .AddField(efb => efb.WithName(GetText("divorces")).WithValue(divorces.ToString()).WithIsInline(true))
.AddField(efb => efb.WithName($"Waifus ({claims.Count})").WithValue(claims.Count == 0 ? nobody : string.Join("\n", claims.OrderBy(x => rng.Next()).Take(40).Select(x => x.Waifu))).WithIsInline(true)); .AddField(efb => efb.WithName($"Waifus ({claims.Count})").WithValue(claims.Count == 0 ? nobody : string.Join("\n", claims.OrderBy(x => rng.Next()).Take(30).Select(x => x.Waifu))).WithIsInline(true));
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
} }
@ -494,7 +494,10 @@ namespace NadekoBot.Modules.Gambling
int count; int count;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
count = uow._context.WaifuUpdates.Count(w => w.User.UserId == userId && w.UpdateType == WaifuUpdateType.AffinityChanged); count = uow._context.WaifuUpdates
.Where(w => w.User.UserId == userId && w.UpdateType == WaifuUpdateType.AffinityChanged && w.New != null)
.GroupBy(x => x.New)
.Count();
} }
AffinityTitles title; AffinityTitles title;

View File

@ -244,19 +244,26 @@ namespace NadekoBot.Modules.Gambling
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task Leaderboard() public async Task Leaderboard(int page = 1)
{ {
List<Currency> richest; List<Currency> richest;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
richest = uow.Currency.GetTopRichest(9).ToList(); richest = uow.Currency.GetTopRichest(9, 9 * (page - 1)).ToList();
} }
if (!richest.Any())
return;
var embed = new EmbedBuilder() var embed = new EmbedBuilder()
.WithOkColor() .WithOkColor()
.WithTitle(NadekoBot.BotConfig.CurrencySign + " " + GetText("leaderboard")); .WithTitle(NadekoBot.BotConfig.CurrencySign +
" " + GetText("leaderboard"))
.WithFooter(efb => efb.WithText(GetText("page", page)));
if (!richest.Any())
{
embed.WithDescription(GetText("no_users_found"));
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
return;
}
for (var i = 0; i < richest.Count; i++) for (var i = 0; i < richest.Count; i++)
{ {
@ -267,7 +274,7 @@ namespace NadekoBot.Modules.Gambling
: usr.Username?.TrimTo(20, true); : usr.Username?.TrimTo(20, true);
var j = i; var j = i;
embed.AddField(efb => efb.WithName("#" + (j + 1) + " " + usrStr) embed.AddField(efb => efb.WithName("#" + (9 * (page - 1) + j + 1) + " " + usrStr)
.WithValue(x.Amount.ToString() + " " + NadekoBot.BotConfig.CurrencySign) .WithValue(x.Amount.ToString() + " " + NadekoBot.BotConfig.CurrencySign)
.WithIsInline(true)); .WithIsInline(true));
} }

View File

@ -5,12 +5,15 @@ using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
using NLog; using NLog;
using Services.CleverBotApi; //using Services.CleverBotApi;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json;
using Services.CleverBotApi;
namespace NadekoBot.Modules.Games namespace NadekoBot.Modules.Games
{ {
@ -28,12 +31,10 @@ namespace NadekoBot.Modules.Games
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
var sw = Stopwatch.StartNew(); var sw = Stopwatch.StartNew();
var bot = ChatterBotFactory.Create(ChatterBotType.CLEVERBOT);
CleverbotGuilds = new ConcurrentDictionary<ulong, Lazy<ChatterBotSession>>( CleverbotGuilds = new ConcurrentDictionary<ulong, Lazy<ChatterBotSession>>(
NadekoBot.AllGuildConfigs NadekoBot.AllGuildConfigs
.Where(gc => gc.CleverbotEnabled) .Where(gc => gc.CleverbotEnabled)
.ToDictionary(gc => gc.GuildId, gc => new Lazy<ChatterBotSession>(() => bot.CreateSession(), true))); .ToDictionary(gc => gc.GuildId, gc => new Lazy<ChatterBotSession>(() => new ChatterBotSession(gc.GuildId), true)));
sw.Stop(); sw.Stop();
_log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s"); _log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
@ -100,9 +101,7 @@ namespace NadekoBot.Modules.Games
return; return;
} }
var cleverbot = ChatterBotFactory.Create(ChatterBotType.CLEVERBOT); CleverbotGuilds.TryAdd(channel.Guild.Id, new Lazy<ChatterBotSession>(() => new ChatterBotSession(Context.Guild.Id), true));
CleverbotGuilds.TryAdd(channel.Guild.Id, new Lazy<ChatterBotSession>(() => cleverbot.CreateSession(), true));
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
@ -113,5 +112,42 @@ namespace NadekoBot.Modules.Games
await ReplyConfirmLocalized("cleverbot_enabled").ConfigureAwait(false); await ReplyConfirmLocalized("cleverbot_enabled").ConfigureAwait(false);
} }
} }
public class ChatterBotSession
{
private static NadekoRandom rng { get; } = new NadekoRandom();
public string ChatterbotId { get; }
public string ChannelId { get; }
private int _botId = 6;
public ChatterBotSession(ulong channelId)
{
ChannelId = channelId.ToString().ToBase64();
ChatterbotId = rng.Next(0, 1000000).ToString().ToBase64();
}
private string apiEndpoint => "http://api.program-o.com/v2/chatbot/" +
$"?bot_id={_botId}&" +
"say={0}&" +
$"convo_id=nadekobot_{ChatterbotId}_{ChannelId}&" +
"format=json";
public async Task<string> Think(string message)
{
using (var http = new HttpClient())
{
var res = await http.GetStringAsync(string.Format(apiEndpoint, message)).ConfigureAwait(false);
var cbr = JsonConvert.DeserializeObject<ChatterBotResponse>(res);
//Console.WriteLine(cbr.Convo_id);
return cbr.BotSay.Replace("<br/>", "\n");
}
}
}
public class ChatterBotResponse
{
public string Convo_id { get; set; }
public string BotSay { get; set; }
}
} }
} }

View File

@ -81,8 +81,10 @@ namespace NadekoBot.Modules.Games
var msgs = new IUserMessage[dropAmount]; var msgs = new IUserMessage[dropAmount];
var prefix = NadekoBot.ModulePrefixes[typeof(Games).Name]; var prefix = NadekoBot.ModulePrefixes[typeof(Games).Name];
var toSend = dropAmount == 1 var toSend = dropAmount == 1
? GetLocalText(channel, "curgen_sn", NadekoBot.BotConfig.CurrencySign, prefix) ? GetLocalText(channel, "curgen_sn", NadekoBot.BotConfig.CurrencySign)
: GetLocalText(channel, "curgen_pl", dropAmount, NadekoBot.BotConfig.CurrencySign, prefix); + GetLocalText(channel, "pick_sn", prefix)
: GetLocalText(channel, "curgen_pl", dropAmount, NadekoBot.BotConfig.CurrencySign)
+ GetLocalText(channel, "pick_pl", prefix);
var file = GetRandomCurrencyImage(); var file = GetRandomCurrencyImage();
using (var fileStream = file.Value.ToStream()) using (var fileStream = file.Value.ToStream())
{ {
@ -159,6 +161,11 @@ namespace NadekoBot.Modules.Games
amount + NadekoBot.BotConfig.CurrencySign, amount + NadekoBot.BotConfig.CurrencySign,
Prefix); Prefix);
if (amount > 1)
msgToSend += " " + GetText("pick_pl", Prefix);
else
msgToSend += " " + GetText("pick_sn", Prefix);
IUserMessage msg; IUserMessage msg;
using (var toSend = imgData.Value.ToStream()) using (var toSend = imgData.Value.ToStream())
{ {

View File

@ -1,4 +1,5 @@
using Discord; using System;
using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using NadekoBot.Attributes; using NadekoBot.Attributes;
@ -8,6 +9,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using ImageSharp.Processing;
namespace NadekoBot.Modules.Games namespace NadekoBot.Modules.Games
{ {
@ -39,7 +41,7 @@ namespace NadekoBot.Modules.Games
if (!ActivePolls.TryGetValue(Context.Guild.Id, out poll)) if (!ActivePolls.TryGetValue(Context.Guild.Id, out poll))
return; return;
await Context.Channel.EmbedAsync(poll.GetStats("Current Poll Results")); await Context.Channel.EmbedAsync(poll.GetStats(GetText("current_poll_results")));
} }
private async Task InternalStartPoll(string arg, bool isPublic = false) private async Task InternalStartPoll(string arg, bool isPublic = false)
@ -58,7 +60,7 @@ namespace NadekoBot.Modules.Games
await poll.StartPoll().ConfigureAwait(false); await poll.StartPoll().ConfigureAwait(false);
} }
else else
await channel.SendErrorAsync("Poll is already running on this server.").ConfigureAwait(false); await ReplyErrorLocalized("poll_already_running").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
@ -108,21 +110,24 @@ namespace NadekoBot.Modules.Games
var totalVotesCast = 0; var totalVotesCast = 0;
if (results.Length == 0) if (results.Length == 0)
{ {
sb.AppendLine("No votes cast."); sb.AppendLine(GetText("no_votes_cast"));
} }
else else
{ {
for (int i = 0; i < results.Length; i++) for (int i = 0; i < results.Length; i++)
{ {
var result = results[i]; var result = results[i];
sb.AppendLine($"`{i + 1}.` {Format.Bold(answers[result.Key - 1])} with {Format.Bold(result.Value.ToString())} votes."); sb.AppendLine(GetText("poll_result",
result.Key,
Format.Bold(answers[result.Key - 1]),
Format.Bold(result.Value.ToString())));
totalVotesCast += result.Value; totalVotesCast += result.Value;
} }
} }
eb.WithDescription(sb.ToString()) eb.WithDescription(sb.ToString())
.WithFooter(efb => efb.WithText(totalVotesCast + " total votes cast.")); .WithFooter(efb => efb.WithText(GetText("x_votes_cast", totalVotesCast)));
return eb; return eb;
} }
@ -130,13 +135,13 @@ namespace NadekoBot.Modules.Games
public async Task StartPoll() public async Task StartPoll()
{ {
NadekoBot.Client.MessageReceived += Vote; NadekoBot.Client.MessageReceived += Vote;
var msgToSend = $"📃**{_originalMessage.Author.Username}** has created a poll which requires your attention:\n\n**{_question}**\n"; var msgToSend = GetText("poll_created", Format.Bold(_originalMessage.Author.Username)) + "\n\n" + Format.Bold(_question) + "\n";
var num = 1; var num = 1;
msgToSend = answers.Aggregate(msgToSend, (current, answ) => current + $"`{num++}.` **{answ}**\n"); msgToSend = answers.Aggregate(msgToSend, (current, answ) => current + $"`{num++}.` **{answ}**\n");
if (!IsPublic) if (!IsPublic)
msgToSend += "\n**Private Message me with the corresponding number of the answer.**"; msgToSend += "\n" + Format.Bold(GetText("poll_vote_private"));
else else
msgToSend += "\n**Send a Message here with the corresponding number of the answer.**"; msgToSend += "\n" + Format.Bold(GetText("poll_vote_public"));
await _originalMessage.Channel.SendConfirmAsync(msgToSend).ConfigureAwait(false); await _originalMessage.Channel.SendConfirmAsync(msgToSend).ConfigureAwait(false);
} }
@ -187,17 +192,23 @@ namespace NadekoBot.Modules.Games
{ {
if (!IsPublic) if (!IsPublic)
{ {
await ch.SendConfirmAsync($"Thanks for voting **{msg.Author.Username}**.").ConfigureAwait(false); await ch.SendConfirmAsync(GetText("thanks_for_voting", Format.Bold(msg.Author.Username))).ConfigureAwait(false);
} }
else else
{ {
var toDelete = await ch.SendConfirmAsync($"{msg.Author.Mention} cast their vote.").ConfigureAwait(false); var toDelete = await ch.SendConfirmAsync(GetText("poll_voted", Format.Bold(msg.Author.ToString()))).ConfigureAwait(false);
toDelete.DeleteAfter(5); toDelete.DeleteAfter(5);
} }
} }
} }
catch { } catch { }
} }
private string GetText(string key, params object[] replacements)
=> NadekoTopLevelModule.GetTextStatic(key,
NadekoBot.Localization.GetCultureInfo(_guild.Id),
typeof(Games).Name.ToLowerInvariant(),
replacements);
} }
} }
} }

View File

@ -236,7 +236,7 @@ namespace NadekoBot.Modules.Games
{ {
hot = NextDouble(8, 10); hot = NextDouble(8, 10);
crazy = NextDouble(5, 7); crazy = NextDouble(5, 7);
advice = "Above an 8 hot, and between about 7 and a 5 crazy - this is WIFE ZONE. You you meet this girl, you should consider long-term " + advice = "Above an 8 hot, and between about 7 and a 5 crazy - this is WIFE ZONE. If you meet this girl, you should consider long-term " +
"relationship. Rare."; "relationship. Rare.";
} }
else if (roll < 999) else if (roll < 999)
@ -244,7 +244,7 @@ namespace NadekoBot.Modules.Games
hot = NextDouble(8, 10); hot = NextDouble(8, 10);
crazy = NextDouble(2, 3.99d); crazy = NextDouble(2, 3.99d);
advice = "You've met a girl she's above 8 hot, and not crazy at all (below 4)... totally cool?" + advice = "You've met a girl she's above 8 hot, and not crazy at all (below 4)... totally cool?" +
" You should be careful. That's a dude. It's a tranny."; " You should be careful. That's a dude. You're talking to a tranny!";
} }
else else
{ {

View File

@ -347,10 +347,8 @@ namespace NadekoBot.Modules.Music
return; return;
} }
var count = ids.Count(); var count = ids.Count();
var msg = await Context.Channel.SendMessageAsync("🎵 " + GetText("attempting_to_queue",
var msg = await Context.Channel.SendMessageAsync(GetText("attempting_to_queue", Format.Bold(count.ToString()))).ConfigureAwait(false);
Format.Bold(count.ToString())))
.ConfigureAwait(false);
var cancelSource = new CancellationTokenSource(); var cancelSource = new CancellationTokenSource();
@ -374,7 +372,7 @@ namespace NadekoBot.Modules.Music
ids = ids.Skip(5); ids = ids.Skip(5);
} }
await msg.ModifyAsync(m => m.Content = GetText("playlist_queue_complete")).ConfigureAwait(false); await msg.ModifyAsync(m => m.Content = "✅ " + Format.Bold(GetText("playlist_queue_complete"))).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
@ -722,7 +720,7 @@ namespace NadekoBot.Modules.Music
var embed = new EmbedBuilder() var embed = new EmbedBuilder()
.WithAuthor(eab => eab.WithName(GetText("playlists_page", num)).WithMusicIcon()) .WithAuthor(eab => eab.WithName(GetText("playlists_page", num)).WithMusicIcon())
.WithDescription(string.Join("\n", playlists.Select(r => .WithDescription(string.Join("\n", playlists.Select(r =>
GetText("playlists", "#" + r.Id, r.Name, r.Author, r.Songs.Count)))) GetText("playlists", r.Id, r.Name, r.Author, r.Songs.Count))))
.WithOkColor(); .WithOkColor();
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);

View File

@ -142,11 +142,11 @@ namespace NadekoBot.Modules.NSFW
#endif #endif
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public Task Yandere([Remainder] string tag = null) public Task Yandere([Remainder] string tag = null)
=> InternalDapiCommand(Context.Message, tag, Searches.Searches.DapiSearchType.Yandere); => InternalDapiCommand(tag, Searches.Searches.DapiSearchType.Yandere);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public Task Konachan([Remainder] string tag = null) public Task Konachan([Remainder] string tag = null)
=> InternalDapiCommand(Context.Message, tag, Searches.Searches.DapiSearchType.Konachan); => InternalDapiCommand(tag, Searches.Searches.DapiSearchType.Konachan);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task E621([Remainder] string tag = null) public async Task E621([Remainder] string tag = null)
@ -167,7 +167,7 @@ namespace NadekoBot.Modules.NSFW
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public Task Rule34([Remainder] string tag = null) public Task Rule34([Remainder] string tag = null)
=> InternalDapiCommand(Context.Message, tag, Searches.Searches.DapiSearchType.Rule34); => InternalDapiCommand(tag, Searches.Searches.DapiSearchType.Rule34);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task Danbooru([Remainder] string tag = null) public async Task Danbooru([Remainder] string tag = null)
@ -210,7 +210,7 @@ namespace NadekoBot.Modules.NSFW
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public Task Gelbooru([Remainder] string tag = null) public Task Gelbooru([Remainder] string tag = null)
=> InternalDapiCommand(Context.Message, tag, Searches.Searches.DapiSearchType.Gelbooru); => InternalDapiCommand(tag, Searches.Searches.DapiSearchType.Gelbooru);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task Cp() public async Task Cp()
@ -288,19 +288,17 @@ namespace NadekoBot.Modules.NSFW
public static Task<string> GetGelbooruImageLink(string tag) => public static Task<string> GetGelbooruImageLink(string tag) =>
Searches.Searches.InternalDapiSearch(tag, Searches.Searches.DapiSearchType.Gelbooru); Searches.Searches.InternalDapiSearch(tag, Searches.Searches.DapiSearchType.Gelbooru);
public async Task InternalDapiCommand(IUserMessage umsg, string tag, Searches.Searches.DapiSearchType type) public async Task InternalDapiCommand(string tag, Searches.Searches.DapiSearchType type)
{ {
var channel = umsg.Channel;
tag = tag?.Trim() ?? ""; tag = tag?.Trim() ?? "";
var url = await Searches.Searches.InternalDapiSearch(tag, type).ConfigureAwait(false); var url = await Searches.Searches.InternalDapiSearch(tag, type).ConfigureAwait(false);
if (url == null) if (url == null)
await channel.SendErrorAsync(umsg.Author.Mention + " " + GetText("no_results")); await ReplyErrorLocalized("not_found").ConfigureAwait(false);
else else
await channel.EmbedAsync(new EmbedBuilder().WithOkColor() await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithDescription(umsg.Author.Mention + " " + tag) .WithDescription(Context.User + " " + tag)
.WithImageUrl(url) .WithImageUrl(url)
.WithFooter(efb => efb.WithText(type.ToString()))).ConfigureAwait(false); .WithFooter(efb => efb.WithText(type.ToString()))).ConfigureAwait(false);
} }

View File

@ -10,25 +10,12 @@ namespace NadekoBot.Modules.Permissions
{ {
public static class PermissionExtensions public static class PermissionExtensions
{ {
public static bool CheckPermissions(this IEnumerable<Permission> permsEnumerable, IUserMessage message, CommandInfo command) public static bool CheckPermissions(this IEnumerable<Permissionv2> permsEnumerable, IUserMessage message,
string commandName, string moduleName, out int permIndex)
{ {
var perms = permsEnumerable as List<Permission> ?? permsEnumerable.ToList(); var perms = permsEnumerable as List<Permissionv2> ?? permsEnumerable.ToList();
int throwaway;
return perms.CheckPermissions(message, command.Name, command.Module.Name, out throwaway);
}
public static bool CheckPermissions(this IEnumerable<Permission> permsEnumerable, IUserMessage message, string commandName, string moduleName) for (int i = perms.Count - 1; i >= 0; i--)
{
var perms = permsEnumerable as List<Permission> ?? permsEnumerable.ToList();
int throwaway;
return perms.CheckPermissions(message, commandName, moduleName, out throwaway);
}
public static bool CheckPermissions(this IEnumerable<Permission> permsEnumerable, IUserMessage message, string commandName, string moduleName, out int permIndex)
{
var perms = permsEnumerable as List<Permission> ?? permsEnumerable.ToList();
for (int i = 0; i < perms.Count; i++)
{ {
var perm = perms[i]; var perm = perms[i];
@ -38,12 +25,9 @@ namespace NadekoBot.Modules.Permissions
{ {
continue; continue;
} }
else
{
permIndex = i; permIndex = i;
return result.Value; return result.Value;
} }
}
permIndex = -1; //defaut behaviour permIndex = -1; //defaut behaviour
return true; return true;
} }
@ -51,7 +35,7 @@ namespace NadekoBot.Modules.Permissions
//null = not applicable //null = not applicable
//true = applicable, allowed //true = applicable, allowed
//false = applicable, not allowed //false = applicable, not allowed
public static bool? CheckPermission(this Permission perm, IUserMessage message, string commandName, string moduleName) public static bool? CheckPermission(this Permissionv2 perm, IUserMessage message, string commandName, string moduleName)
{ {
if (!((perm.SecondaryTarget == SecondaryPermissionType.Command && if (!((perm.SecondaryTarget == SecondaryPermissionType.Command &&
perm.SecondaryTargetName.ToLowerInvariant() == commandName.ToLowerInvariant()) || perm.SecondaryTargetName.ToLowerInvariant() == commandName.ToLowerInvariant()) ||
@ -86,7 +70,7 @@ namespace NadekoBot.Modules.Permissions
return null; return null;
} }
public static string GetCommand(this Permission perm, SocketGuild guild = null) public static string GetCommand(this Permissionv2 perm, SocketGuild guild = null)
{ {
var com = ""; var com = "";
switch (perm.PrimaryTarget) switch (perm.PrimaryTarget)
@ -143,98 +127,10 @@ namespace NadekoBot.Modules.Permissions
return NadekoBot.ModulePrefixes[typeof(Permissions).Name] + com; return NadekoBot.ModulePrefixes[typeof(Permissions).Name] + com;
} }
public static void Prepend(this Permission perm, Permission toAdd)
{
perm = perm.GetRoot();
perm.Previous = toAdd;
toAdd.Next = perm;
}
/* /this can't work if index < 0 and perm isn't roo
public static void Insert(this Permission perm, int index, Permission toAdd)
{
if (index < 0)
throw new IndexOutOfRangeException();
if (index == 0)
{
perm.Prepend(toAdd);
return;
}
var atIndex = perm;
var i = 0;
while (i != index)
{
atIndex = atIndex.Next;
i++;
if (atIndex == null)
throw new IndexOutOfRangeException();
}
var previous = atIndex.Previous;
//connect right side
atIndex.Previous = toAdd;
toAdd.Next = atIndex;
//connect left side
toAdd.Previous = previous;
previous.Next = toAdd;
}
*/
public static Permission RemoveAt(this Permission perm, int index)
{
if (index <= 0) //can't really remove at 0, that means deleting the element right now. Just use perm.Next if its 0
throw new IndexOutOfRangeException();
var toRemove = perm;
var i = 0;
while (i != index)
{
toRemove = toRemove.Next;
i++;
if (toRemove == null)
throw new IndexOutOfRangeException();
}
toRemove.Previous.Next = toRemove.Next;
if (toRemove.Next != null)
toRemove.Next.Previous = toRemove.Previous;
return toRemove;
}
public static Permission GetAt(this Permission perm, int index)
{
if (index < 0)
throw new IndexOutOfRangeException();
var temp = perm;
while (index > 0) { temp = temp?.Next; index--; }
if (temp == null)
throw new IndexOutOfRangeException();
return temp;
}
public static int Count(this Permission perm)
{
var i = 1;
var temp = perm;
while ((temp = temp.Next) != null) { i++; }
return i;
}
public static IEnumerable<Permission> AsEnumerable(this Permission perm) public static IEnumerable<Permission> AsEnumerable(this Permission perm)
{ {
do yield return perm; do yield return perm;
while ((perm = perm.Next) != null); while ((perm = perm.Next) != null);
} }
public static Permission GetRoot(this Permission perm)
{
Permission toReturn;
do toReturn = perm;
while ((perm = perm.Previous) != null);
return toReturn;
}
} }
} }

View File

@ -7,9 +7,12 @@ using NadekoBot.Services;
using Discord; using Discord;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using NadekoBot.Extensions; using System.Collections.Generic;
using Discord.WebSocket; using Discord.WebSocket;
using System.Diagnostics; using System.Diagnostics;
using Microsoft.EntityFrameworkCore;
using NadekoBot.DataStructures;
using NadekoBot.TypeReaders;
using NLog; using NLog;
namespace NadekoBot.Modules.Permissions namespace NadekoBot.Modules.Permissions
@ -17,36 +20,139 @@ namespace NadekoBot.Modules.Permissions
[NadekoModule("Permissions", ";")] [NadekoModule("Permissions", ";")]
public partial class Permissions : NadekoTopLevelModule public partial class Permissions : NadekoTopLevelModule
{ {
public class PermissionCache public class OldPermissionCache
{ {
public string PermRole { get; set; } public string PermRole { get; set; }
public bool Verbose { get; set; } = true; public bool Verbose { get; set; } = true;
public Permission RootPermission { get; set; } public Permission RootPermission { get; set; }
} }
public class PermissionCache
{
public string PermRole { get; set; }
public bool Verbose { get; set; } = true;
public PermissionsCollection<Permissionv2> Permissions { get; set; }
}
//guildid, root permission //guildid, root permission
public static ConcurrentDictionary<ulong, PermissionCache> Cache { get; } public static ConcurrentDictionary<ulong, PermissionCache> Cache { get; } =
new ConcurrentDictionary<ulong, PermissionCache>();
static Permissions() static Permissions()
{ {
var log = LogManager.GetCurrentClassLogger(); var log = LogManager.GetCurrentClassLogger();
var sw = Stopwatch.StartNew(); var sw = Stopwatch.StartNew();
TryMigratePermissions();
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
Cache = new ConcurrentDictionary<ulong, PermissionCache>(uow.GuildConfigs foreach (var x in uow.GuildConfigs.Permissionsv2ForAll())
.PermissionsForAll() {
Cache.TryAdd(x.GuildId, new PermissionCache()
{
Verbose = x.VerbosePermissions,
PermRole = x.PermissionRole,
Permissions = new PermissionsCollection<Permissionv2>(x.Permissions)
});
}
}
sw.Stop();
log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
}
private static void TryMigratePermissions()
{
var log = LogManager.GetCurrentClassLogger();
using (var uow = DbHandler.UnitOfWork())
{
var oldCache = new ConcurrentDictionary<ulong, OldPermissionCache>(uow.GuildConfigs
.OldPermissionsForAll()
.Where(x => x.RootPermission != null) // there is a check inside already, but just in case
.ToDictionary(k => k.GuildId, .ToDictionary(k => k.GuildId,
v => new PermissionCache() v => new OldPermissionCache()
{ {
RootPermission = v.RootPermission, RootPermission = v.RootPermission,
Verbose = v.VerbosePermissions, Verbose = v.VerbosePermissions,
PermRole = v.PermissionRole PermRole = v.PermissionRole
})); }));
if (oldCache.Any())
{
log.Info("Old permissions found. Performing one-time migration to v2.");
var i = 0;
foreach (var oc in oldCache)
{
if (i % 3 == 0)
log.Info("Migrating Permissions #" + i + " - GuildId: " + oc.Key);
i++;
var gc = uow.GuildConfigs.GcWithPermissionsv2For(oc.Key);
var oldPerms = oc.Value.RootPermission.AsEnumerable().Reverse().ToList();
uow._context.Set<Permission>().RemoveRange(oldPerms);
gc.RootPermission = null;
if (oldPerms.Count > 2)
{
var newPerms = oldPerms.Take(oldPerms.Count - 1)
.Select(x => x.Tov2())
.ToList();
var allowPerm = Permissionv2.AllowAllPerm;
var firstPerm = newPerms[0];
if (allowPerm.State != firstPerm.State ||
allowPerm.PrimaryTarget != firstPerm.PrimaryTarget ||
allowPerm.SecondaryTarget != firstPerm.SecondaryTarget ||
allowPerm.PrimaryTargetId != firstPerm.PrimaryTargetId ||
allowPerm.SecondaryTargetName != firstPerm.SecondaryTargetName)
newPerms.Insert(0, Permissionv2.AllowAllPerm);
Cache.TryAdd(oc.Key, new PermissionCache
{
Permissions = new PermissionsCollection<Permissionv2>(newPerms),
Verbose = gc.VerbosePermissions,
PermRole = gc.PermissionRole,
});
gc.Permissions = newPerms;
}
}
log.Info("Permission migration to v2 is done.");
uow.Complete();
}
}
} }
sw.Stop(); private static async Task AddPermissions(ulong guildId, params Permissionv2[] perms)
log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s"); {
using (var uow = DbHandler.UnitOfWork())
{
var config = uow.GuildConfigs.GcWithPermissionsv2For(guildId);
//var orderedPerms = new PermissionsCollection<Permissionv2>(config.Permissions);
var max = config.Permissions.Max(x => x.Index); //have to set its index to be the highest
foreach (var perm in perms)
{
perm.Index = ++max;
config.Permissions.Add(perm);
}
await uow.CompleteAsync().ConfigureAwait(false);
UpdateCache(config);
}
}
public static void UpdateCache(GuildConfig config)
{
Cache.AddOrUpdate(config.GuildId, new PermissionCache()
{
Permissions = new PermissionsCollection<Permissionv2>(config.Permissions),
PermRole = config.PermissionRole,
Verbose = config.VerbosePermissions
}, (id, old) =>
{
old.Permissions = new PermissionsCollection<Permissionv2>(config.Permissions);
old.PermRole = config.PermissionRole;
old.Verbose = config.VerbosePermissions;
return old;
});
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
@ -55,15 +161,10 @@ namespace NadekoBot.Modules.Permissions
{ {
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.For(Context.Guild.Id, set => set); var config = uow.GuildConfigs.GcWithPermissionsv2For(Context.Guild.Id);
config.VerbosePermissions = action.Value; config.VerbosePermissions = action.Value;
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = Permission.GetDefaultRoot(),
Verbose = config.VerbosePermissions
}, (id, old) => { old.Verbose = config.VerbosePermissions; return old; });
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
UpdateCache(config);
} }
if (action.Value) if (action.Value)
{ {
@ -84,20 +185,15 @@ namespace NadekoBot.Modules.Permissions
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.For(Context.Guild.Id, set => set); var config = uow.GuildConfigs.GcWithPermissionsv2For(Context.Guild.Id);
if (role == null) if (role == null)
{ {
await ReplyConfirmLocalized("permrole", Format.Bold(config.PermissionRole)).ConfigureAwait(false); await ReplyConfirmLocalized("permrole", Format.Bold(config.PermissionRole)).ConfigureAwait(false);
return; return;
} }
config.PermissionRole = role.Name.Trim(); config.PermissionRole = role.Name.Trim();
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = Permission.GetDefaultRoot(),
Verbose = config.VerbosePermissions
}, (id, old) => { old.PermRole = role.Name.Trim(); return old; });
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
UpdateCache(config);
} }
await ReplyConfirmLocalized("permrole_changed", Format.Bold(role.Name)).ConfigureAwait(false); await ReplyConfirmLocalized("permrole_changed", Format.Bold(role.Name)).ConfigureAwait(false);
@ -109,19 +205,32 @@ namespace NadekoBot.Modules.Permissions
{ {
if (page < 1 || page > 4) if (page < 1 || page > 4)
return; return;
string toSend;
using (var uow = DbHandler.UnitOfWork()) PermissionCache permCache;
IList<Permissionv2> perms;
if (Cache.TryGetValue(Context.Guild.Id, out permCache))
{ {
var perms = uow.GuildConfigs.PermissionsFor(Context.Guild.Id).RootPermission; perms = permCache.Permissions.Source.ToList();
var i = 1 + 20 * (page - 1);
toSend = Format.Bold(GetText("page", page)) + "\n\n" + string.Join("\n",
perms.AsEnumerable()
.Skip((page - 1) * 20)
.Take(20)
.Select(
p =>
$"`{(i++)}.` {(p.Next == null ? Format.Bold(p.GetCommand((SocketGuild) Context.Guild) + $" [{GetText("uneditable")}]") : (p.GetCommand((SocketGuild) Context.Guild)))}"));
} }
else
{
perms = Permissionv2.GetDefaultPermlist;
}
var startPos = 20 * (page - 1);
var toSend = Format.Bold(GetText("page", page)) + "\n\n" + string.Join("\n",
perms.Reverse()
.Skip(startPos)
.Take(20)
.Select(p =>
{
var str =
$"`{p.Index + 1}.` {Format.Bold(p.GetCommand((SocketGuild) Context.Guild))}";
if (p.Index == 0)
str += $" [{GetText("uneditable")}]";
return str;
}));
await Context.Channel.SendMessageAsync(toSend).ConfigureAwait(false); await Context.Channel.SendMessageAsync(toSend).ConfigureAwait(false);
} }
@ -131,39 +240,20 @@ namespace NadekoBot.Modules.Permissions
public async Task RemovePerm(int index) public async Task RemovePerm(int index)
{ {
index -= 1; index -= 1;
if (index < 0)
return;
try try
{ {
Permission p; Permissionv2 p;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.PermissionsFor(Context.Guild.Id); var config = uow.GuildConfigs.GcWithPermissionsv2For(Context.Guild.Id);
var perms = config.RootPermission; var permsCol = new PermissionsCollection<Permissionv2>(config.Permissions);
if (index == perms.Count() - 1) p = permsCol[index];
{ permsCol.RemoveAt(index);
return; uow._context.Remove(p);
}
if (index == 0)
{
p = perms;
config.RootPermission = perms.Next;
}
else
{
p = perms.RemoveAt(index);
}
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} UpdateCache(config);
using (var uow2 = DbHandler.UnitOfWork())
{
uow2._context.Remove<Permission>(p);
uow2._context.SaveChanges();
} }
await ReplyConfirmLocalized("removed", await ReplyConfirmLocalized("removed",
index + 1, index + 1,
@ -185,36 +275,15 @@ namespace NadekoBot.Modules.Permissions
{ {
try try
{ {
Permission fromPerm = null; Permissionv2 fromPerm;
Permission toPerm = null;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.PermissionsFor(Context.Guild.Id); var config = uow.GuildConfigs.GcWithPermissionsv2For(Context.Guild.Id);
var perms = config.RootPermission; var permsCol = new PermissionsCollection<Permissionv2>(config.Permissions);
var index = 0;
var fromFound = false; var fromFound = from < permsCol.Count;
var toFound = false; var toFound = to < permsCol.Count;
while ((!toFound || !fromFound) && perms != null)
{
if (index == from)
{
fromPerm = perms;
fromFound = true;
}
if (index == to)
{
toPerm = perms;
toFound = true;
}
if (!toFound)
{
toPerm = perms; //In case of to > size
}
perms = perms.Next;
index++;
}
if (perms == null)
{
if (!fromFound) if (!fromFound)
{ {
await ReplyErrorLocalized("not_found", ++from).ConfigureAwait(false); await ReplyErrorLocalized("not_found", ++from).ConfigureAwait(false);
@ -226,51 +295,12 @@ namespace NadekoBot.Modules.Permissions
await ReplyErrorLocalized("not_found", ++to).ConfigureAwait(false); await ReplyErrorLocalized("not_found", ++to).ConfigureAwait(false);
return; return;
} }
} fromPerm = permsCol[from];
//Change chain for from indx permsCol.RemoveAt(from);
var next = fromPerm.Next; permsCol.Insert(to, fromPerm);
var pre = fromPerm.Previous;
if (pre != null)
pre.Next = next;
if (fromPerm.Next == null || toPerm.Next == null)
{
throw new IndexOutOfRangeException();
}
next.Previous = pre;
if (from == 0)
{
}
await uow.CompleteAsync().ConfigureAwait(false);
//Inserting
if (to > from)
{
fromPerm.Previous = toPerm;
fromPerm.Next = toPerm.Next;
toPerm.Next.Previous = fromPerm;
toPerm.Next = fromPerm;
}
else
{
pre = toPerm.Previous;
fromPerm.Next = toPerm;
fromPerm.Previous = pre;
toPerm.Previous = fromPerm;
if (pre != null)
pre.Next = fromPerm;
}
config.RootPermission = fromPerm.GetRoot();
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
UpdateCache(config);
} }
await ReplyConfirmLocalized("moved_permission", await ReplyConfirmLocalized("moved_permission",
Format.Code(fromPerm.GetCommand((SocketGuild) Context.Guild)), Format.Code(fromPerm.GetCommand((SocketGuild) Context.Guild)),
@ -288,39 +318,27 @@ namespace NadekoBot.Modules.Permissions
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task SrvrCmd(CommandInfo command, PermissionAction action) public async Task SrvrCmd(CommandOrCrInfo command, PermissionAction action)
{ {
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.Server, PrimaryTarget = PrimaryPermissionType.Server,
PrimaryTargetId = 0, PrimaryTargetId = 0,
SecondaryTarget = SecondaryPermissionType.Command, SecondaryTarget = SecondaryPermissionType.Command,
SecondaryTargetName = command.Aliases.First().ToLowerInvariant(), SecondaryTargetName = command.Name.ToLowerInvariant(),
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {
await ReplyConfirmLocalized("sx_enable", await ReplyConfirmLocalized("sx_enable",
Format.Code(command.Aliases.First()), Format.Code(command.Name),
GetText("of_command")).ConfigureAwait(false); GetText("of_command")).ConfigureAwait(false);
} }
else else
{ {
await ReplyConfirmLocalized("sx_disable", await ReplyConfirmLocalized("sx_disable",
Format.Code(command.Aliases.First()), Format.Code(command.Name),
GetText("of_command")).ConfigureAwait(false); GetText("of_command")).ConfigureAwait(false);
} }
} }
@ -329,25 +347,14 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task SrvrMdl(ModuleInfo module, PermissionAction action) public async Task SrvrMdl(ModuleInfo module, PermissionAction action)
{ {
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.Server, PrimaryTarget = PrimaryPermissionType.Server,
PrimaryTargetId = 0, PrimaryTargetId = 0,
SecondaryTarget = SecondaryPermissionType.Module, SecondaryTarget = SecondaryPermissionType.Module,
SecondaryTargetName = module.Name.ToLowerInvariant(), SecondaryTargetName = module.Name.ToLowerInvariant(),
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {
@ -365,39 +372,28 @@ namespace NadekoBot.Modules.Permissions
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task UsrCmd(CommandInfo command, PermissionAction action, [Remainder] IGuildUser user) public async Task UsrCmd(CommandOrCrInfo command, PermissionAction action, [Remainder] IGuildUser user)
{ {
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.User, PrimaryTarget = PrimaryPermissionType.User,
PrimaryTargetId = user.Id, PrimaryTargetId = user.Id,
SecondaryTarget = SecondaryPermissionType.Command, SecondaryTarget = SecondaryPermissionType.Command,
SecondaryTargetName = command.Aliases.First().ToLowerInvariant(), SecondaryTargetName = command.Name.ToLowerInvariant(),
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {
await ReplyConfirmLocalized("ux_enable", await ReplyConfirmLocalized("ux_enable",
Format.Code(command.Aliases.First()), Format.Code(command.Name),
GetText("of_command"), GetText("of_command"),
Format.Code(user.ToString())).ConfigureAwait(false); Format.Code(user.ToString())).ConfigureAwait(false);
} }
else else
{ {
await ReplyConfirmLocalized("ux_disable", await ReplyConfirmLocalized("ux_disable",
Format.Code(command.Aliases.First()), Format.Code(command.Name),
GetText("of_command"), GetText("of_command"),
Format.Code(user.ToString())).ConfigureAwait(false); Format.Code(user.ToString())).ConfigureAwait(false);
} }
@ -407,25 +403,14 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task UsrMdl(ModuleInfo module, PermissionAction action, [Remainder] IGuildUser user) public async Task UsrMdl(ModuleInfo module, PermissionAction action, [Remainder] IGuildUser user)
{ {
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.User, PrimaryTarget = PrimaryPermissionType.User,
PrimaryTargetId = user.Id, PrimaryTargetId = user.Id,
SecondaryTarget = SecondaryPermissionType.Module, SecondaryTarget = SecondaryPermissionType.Module,
SecondaryTargetName = module.Name.ToLowerInvariant(), SecondaryTargetName = module.Name.ToLowerInvariant(),
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {
@ -445,42 +430,31 @@ namespace NadekoBot.Modules.Permissions
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task RoleCmd(CommandInfo command, PermissionAction action, [Remainder] IRole role) public async Task RoleCmd(CommandOrCrInfo command, PermissionAction action, [Remainder] IRole role)
{ {
if (role == role.Guild.EveryoneRole) if (role == role.Guild.EveryoneRole)
return; return;
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.Role, PrimaryTarget = PrimaryPermissionType.Role,
PrimaryTargetId = role.Id, PrimaryTargetId = role.Id,
SecondaryTarget = SecondaryPermissionType.Command, SecondaryTarget = SecondaryPermissionType.Command,
SecondaryTargetName = command.Aliases.First().ToLowerInvariant(), SecondaryTargetName = command.Name.ToLowerInvariant(),
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {
await ReplyConfirmLocalized("rx_enable", await ReplyConfirmLocalized("rx_enable",
Format.Code(command.Aliases.First()), Format.Code(command.Name),
GetText("of_command"), GetText("of_command"),
Format.Code(role.Name)).ConfigureAwait(false); Format.Code(role.Name)).ConfigureAwait(false);
} }
else else
{ {
await ReplyConfirmLocalized("rx_disable", await ReplyConfirmLocalized("rx_disable",
Format.Code(command.Aliases.First()), Format.Code(command.Name),
GetText("of_command"), GetText("of_command"),
Format.Code(role.Name)).ConfigureAwait(false); Format.Code(role.Name)).ConfigureAwait(false);
} }
@ -493,25 +467,14 @@ namespace NadekoBot.Modules.Permissions
if (role == role.Guild.EveryoneRole) if (role == role.Guild.EveryoneRole)
return; return;
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.Role, PrimaryTarget = PrimaryPermissionType.Role,
PrimaryTargetId = role.Id, PrimaryTargetId = role.Id,
SecondaryTarget = SecondaryPermissionType.Module, SecondaryTarget = SecondaryPermissionType.Module,
SecondaryTargetName = module.Name.ToLowerInvariant(), SecondaryTargetName = module.Name.ToLowerInvariant(),
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
@ -532,39 +495,28 @@ namespace NadekoBot.Modules.Permissions
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ChnlCmd(CommandInfo command, PermissionAction action, [Remainder] ITextChannel chnl) public async Task ChnlCmd(CommandOrCrInfo command, PermissionAction action, [Remainder] ITextChannel chnl)
{ {
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.Channel, PrimaryTarget = PrimaryPermissionType.Channel,
PrimaryTargetId = chnl.Id, PrimaryTargetId = chnl.Id,
SecondaryTarget = SecondaryPermissionType.Command, SecondaryTarget = SecondaryPermissionType.Command,
SecondaryTargetName = command.Aliases.First().ToLowerInvariant(), SecondaryTargetName = command.Name.ToLowerInvariant(),
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {
await ReplyConfirmLocalized("cx_enable", await ReplyConfirmLocalized("cx_enable",
Format.Code(command.Aliases.First()), Format.Code(command.Name),
GetText("of_command"), GetText("of_command"),
Format.Code(chnl.Name)).ConfigureAwait(false); Format.Code(chnl.Name)).ConfigureAwait(false);
} }
else else
{ {
await ReplyConfirmLocalized("cx_disable", await ReplyConfirmLocalized("cx_disable",
Format.Code(command.Aliases.First()), Format.Code(command.Name),
GetText("of_command"), GetText("of_command"),
Format.Code(chnl.Name)).ConfigureAwait(false); Format.Code(chnl.Name)).ConfigureAwait(false);
} }
@ -574,25 +526,14 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ChnlMdl(ModuleInfo module, PermissionAction action, [Remainder] ITextChannel chnl) public async Task ChnlMdl(ModuleInfo module, PermissionAction action, [Remainder] ITextChannel chnl)
{ {
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.Channel, PrimaryTarget = PrimaryPermissionType.Channel,
PrimaryTargetId = chnl.Id, PrimaryTargetId = chnl.Id,
SecondaryTarget = SecondaryPermissionType.Module, SecondaryTarget = SecondaryPermissionType.Module,
SecondaryTargetName = module.Name.ToLowerInvariant(), SecondaryTargetName = module.Name.ToLowerInvariant(),
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {
@ -614,25 +555,14 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task AllChnlMdls(PermissionAction action, [Remainder] ITextChannel chnl) public async Task AllChnlMdls(PermissionAction action, [Remainder] ITextChannel chnl)
{ {
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.Channel, PrimaryTarget = PrimaryPermissionType.Channel,
PrimaryTargetId = chnl.Id, PrimaryTargetId = chnl.Id,
SecondaryTarget = SecondaryPermissionType.AllModules, SecondaryTarget = SecondaryPermissionType.AllModules,
SecondaryTargetName = "*", SecondaryTargetName = "*",
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {
@ -653,25 +583,14 @@ namespace NadekoBot.Modules.Permissions
if (role == role.Guild.EveryoneRole) if (role == role.Guild.EveryoneRole)
return; return;
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.Role, PrimaryTarget = PrimaryPermissionType.Role,
PrimaryTargetId = role.Id, PrimaryTargetId = role.Id,
SecondaryTarget = SecondaryPermissionType.AllModules, SecondaryTarget = SecondaryPermissionType.AllModules,
SecondaryTargetName = "*", SecondaryTargetName = "*",
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {
@ -689,25 +608,14 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task AllUsrMdls(PermissionAction action, [Remainder] IUser user) public async Task AllUsrMdls(PermissionAction action, [Remainder] IUser user)
{ {
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.User, PrimaryTarget = PrimaryPermissionType.User,
PrimaryTargetId = user.Id, PrimaryTargetId = user.Id,
SecondaryTarget = SecondaryPermissionType.AllModules, SecondaryTarget = SecondaryPermissionType.AllModules,
SecondaryTargetName = "*", SecondaryTargetName = "*",
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {
@ -725,9 +633,7 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task AllSrvrMdls(PermissionAction action) public async Task AllSrvrMdls(PermissionAction action)
{ {
using (var uow = DbHandler.UnitOfWork()) var newPerm = new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.Server, PrimaryTarget = PrimaryPermissionType.Server,
PrimaryTargetId = 0, PrimaryTargetId = 0,
@ -735,9 +641,8 @@ namespace NadekoBot.Modules.Permissions
SecondaryTargetName = "*", SecondaryTargetName = "*",
State = action.Value, State = action.Value,
}; };
uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
var allowUser = new Permission var allowUser = new Permissionv2
{ {
PrimaryTarget = PrimaryPermissionType.User, PrimaryTarget = PrimaryPermissionType.User,
PrimaryTargetId = Context.User.Id, PrimaryTargetId = Context.User.Id,
@ -746,15 +651,9 @@ namespace NadekoBot.Modules.Permissions
State = true, State = true,
}; };
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, allowUser); await AddPermissions(Context.Guild.Id,
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache() newPerm,
{ allowUser);
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {

View File

@ -1,11 +1,11 @@
using Discord; using System;
using Discord;
using Discord.Commands; using Discord.Commands;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Modules.Searches.Models; using NadekoBot.Modules.Searches.Models;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Net.Http; using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace NadekoBot.Modules.Searches namespace NadekoBot.Modules.Searches
@ -20,7 +20,7 @@ namespace NadekoBot.Modules.Searches
{ {
if (string.IsNullOrWhiteSpace(query)) if (string.IsNullOrWhiteSpace(query))
return; return;
var battletag = Regex.Replace(query, "#", "-", RegexOptions.IgnoreCase); var battletag = query.Replace("#", "-");
await Context.Channel.TriggerTypingAsync().ConfigureAwait(false); await Context.Channel.TriggerTypingAsync().ConfigureAwait(false);
try try
@ -55,10 +55,10 @@ namespace NadekoBot.Modules.Searches
.AddField(fb => fb.WithName(GetText("level")).WithValue($"{model.level}").WithIsInline(true)) .AddField(fb => fb.WithName(GetText("level")).WithValue($"{model.level}").WithIsInline(true))
.AddField(fb => fb.WithName(GetText("quick_wins")).WithValue($"{model.Games.Quick.wins}").WithIsInline(true)) .AddField(fb => fb.WithName(GetText("quick_wins")).WithValue($"{model.Games.Quick.wins}").WithIsInline(true))
.AddField(fb => fb.WithName(GetText("compet_wins")).WithValue($"{model.Games.Competitive.wins}").WithIsInline(true)) .AddField(fb => fb.WithName(GetText("compet_wins")).WithValue($"{model.Games.Competitive.wins}").WithIsInline(true))
.AddField(fb => fb.WithName(GetText("compet_losses")).WithValue($"{model.Games.Competitive.lost}").WithIsInline(true)) .AddField(fb => fb.WithName(GetText("compet_loses")).WithValue($"{model.Games.Competitive.lost}").WithIsInline(true))
.AddField(fb => fb.WithName(GetText("compet_played")).WithValue($"{model.Games.Competitive.played}").WithIsInline(true)) .AddField(fb => fb.WithName(GetText("compet_played")).WithValue($"{model.Games.Competitive.played}").WithIsInline(true))
.AddField(fb => fb.WithName(GetText("compet_rank")).WithValue(rank).WithIsInline(true)) .AddField(fb => fb.WithName(GetText("compet_rank")).WithValue(rank).WithIsInline(true))
.AddField(fb => fb.WithName(GetText("compet_played")).WithValue($"{model.Playtime.competitive}").WithIsInline(true)) .AddField(fb => fb.WithName(GetText("compet_playtime")).WithValue($"{model.Playtime.competitive}").WithIsInline(true))
.AddField(fb => fb.WithName(GetText("quick_playtime")).WithValue($"{model.Playtime.quick}").WithIsInline(true)) .AddField(fb => fb.WithName(GetText("quick_playtime")).WithValue($"{model.Playtime.quick}").WithIsInline(true))
.WithColor(NadekoBot.OkColor); .WithColor(NadekoBot.OkColor);
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
@ -73,15 +73,22 @@ namespace NadekoBot.Modules.Searches
{ {
try try
{ {
using (var http = new HttpClient()) using (var handler = new HttpClientHandler())
{ {
var url = await http.GetStringAsync($"https://api.lootbox.eu/pc/{region.ToLower()}/{battletag}/profile"); handler.ServerCertificateCustomValidationCallback = (x, y, z, e) => true;
using (var http = new HttpClient(handler))
{
var url =
await http.GetStringAsync(
$"https://api.lootbox.eu/pc/{region.ToLower()}/{battletag}/profile");
var model = JsonConvert.DeserializeObject<OverwatchApiModel.OverwatchPlayer>(url); var model = JsonConvert.DeserializeObject<OverwatchApiModel.OverwatchPlayer>(url);
return model.data; return model.data;
} }
} }
catch }
catch (Exception ex)
{ {
_log.Warn(ex);
return null; return null;
} }
} }

View File

@ -26,12 +26,17 @@ namespace NadekoBot.Modules.Searches
{ {
var res = await http.GetStringAsync($"{_xkcdUrl}/info.0.json").ConfigureAwait(false); var res = await http.GetStringAsync($"{_xkcdUrl}/info.0.json").ConfigureAwait(false);
var comic = JsonConvert.DeserializeObject<XkcdComic>(res); var comic = JsonConvert.DeserializeObject<XkcdComic>(res);
var sent = await Context.Channel.SendMessageAsync($"{Context.User.Mention} " + comic) var embed = new EmbedBuilder().WithColor(NadekoBot.OkColor)
.WithImageUrl(comic.ImageLink)
.WithAuthor(eab => eab.WithName(comic.Title).WithUrl($"{_xkcdUrl}/{comic.Num}").WithIconUrl("http://xkcd.com/s/919f27.ico"))
.AddField(efb => efb.WithName(GetText("comic_number")).WithValue(comic.Num.ToString()).WithIsInline(true))
.AddField(efb => efb.WithName(GetText("date")).WithValue($"{comic.Month}/{comic.Year}").WithIsInline(true));
var sent = await Context.Channel.EmbedAsync(embed)
.ConfigureAwait(false); .ConfigureAwait(false);
await Task.Delay(10000).ConfigureAwait(false); await Task.Delay(10000).ConfigureAwait(false);
await sent.ModifyAsync(m => m.Content = sent.Content + $"\n`Alt:` {comic.Alt}"); await sent.ModifyAsync(m => m.Embed = embed.AddField(efb => efb.WithName("Alt").WithValue(comic.Alt.ToString()).WithIsInline(false)).Build());
} }
return; return;
} }

View File

@ -22,6 +22,7 @@ using Configuration = AngleSharp.Configuration;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using Discord.Commands; using Discord.Commands;
using ImageSharp.Processing.Processors; using ImageSharp.Processing.Processors;
using ImageSharp;
namespace NadekoBot.Modules.Searches namespace NadekoBot.Modules.Searches
{ {
@ -41,17 +42,17 @@ namespace NadekoBot.Modules.Searches
var data = JsonConvert.DeserializeObject<WeatherData>(response); var data = JsonConvert.DeserializeObject<WeatherData>(response);
var embed = new EmbedBuilder() var embed = new EmbedBuilder()
.AddField(fb => fb.WithName("🌍 " + GetText("location")).WithValue(data.name + ", " + data.sys.country).WithIsInline(true)) .AddField(fb => fb.WithName("🌍 " + Format.Bold(GetText("location"))).WithValue($"[{data.name + ", " + data.sys.country}](https://openweathermap.org/city/{data.id})").WithIsInline(true))
.AddField(fb => fb.WithName("📏 " + GetText("latlong")).WithValue($"{data.coord.lat}, {data.coord.lon}").WithIsInline(true)) .AddField(fb => fb.WithName("📏 " + Format.Bold(GetText("latlong"))).WithValue($"{data.coord.lat}, {data.coord.lon}").WithIsInline(true))
.AddField(fb => fb.WithName("☁ " + GetText("condition")).WithValue(string.Join(", ", data.weather.Select(w => w.main))).WithIsInline(true)) .AddField(fb => fb.WithName("☁ " + Format.Bold(GetText("condition"))).WithValue(string.Join(", ", data.weather.Select(w => w.main))).WithIsInline(true))
.AddField(fb => fb.WithName("😓 " + GetText("humidity")).WithValue($"{data.main.humidity}%").WithIsInline(true)) .AddField(fb => fb.WithName("😓 " + Format.Bold(GetText("humidity"))).WithValue($"{data.main.humidity}%").WithIsInline(true))
.AddField(fb => fb.WithName("💨 " + GetText("wind_speed")).WithValue(data.wind.speed + " km/h").WithIsInline(true)) .AddField(fb => fb.WithName("💨 " + Format.Bold(GetText("wind_speed"))).WithValue(data.wind.speed + " m/s").WithIsInline(true))
.AddField(fb => fb.WithName("🌡 " + GetText("temperature")).WithValue(data.main.temp + "°C").WithIsInline(true)) .AddField(fb => fb.WithName("🌡 " + Format.Bold(GetText("temperature"))).WithValue(data.main.temp + "°C").WithIsInline(true))
.AddField(fb => fb.WithName("🔆 " + GetText("min_max")).WithValue($"{data.main.temp_min}°C - {data.main.temp_max}°C").WithIsInline(true)) .AddField(fb => fb.WithName("🔆 " + Format.Bold(GetText("min_max"))).WithValue($"{data.main.temp_min}°C - {data.main.temp_max}°C").WithIsInline(true))
.AddField(fb => fb.WithName("🌄 " + GetText("sunrise")).WithValue($"{data.sys.sunrise.ToUnixTimestamp():HH:mm}").WithIsInline(true)) .AddField(fb => fb.WithName("🌄 " + Format.Bold(GetText("sunrise"))).WithValue($"{data.sys.sunrise.ToUnixTimestamp():HH:mm} UTC").WithIsInline(true))
.AddField(fb => fb.WithName("🌇 " + GetText("sunset")).WithValue($"{data.sys.sunset.ToUnixTimestamp():HH:mm}").WithIsInline(true)) .AddField(fb => fb.WithName("🌇 " + Format.Bold(GetText("sunset"))).WithValue($"{data.sys.sunset.ToUnixTimestamp():HH:mm} UTC").WithIsInline(true))
.WithOkColor() .WithOkColor()
.WithFooter(efb => efb.WithText("Powered by http://openweathermap.org")); .WithFooter(efb => efb.WithText("Powered by openweathermap.org").WithIconUrl($"http://openweathermap.org/img/w/{data.weather[0].icon}.png"));
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
} }
@ -217,7 +218,7 @@ namespace NadekoBot.Modules.Searches
if (string.IsNullOrWhiteSpace(ffs)) if (string.IsNullOrWhiteSpace(ffs))
return; return;
await Context.Channel.SendConfirmAsync(await NadekoBot.Google.ShortenUrl($"<http://lmgtfy.com/?q={ Uri.EscapeUriString(ffs) }>")) await Context.Channel.SendConfirmAsync("<" + await NadekoBot.Google.ShortenUrl($"http://lmgtfy.com/?q={ Uri.EscapeUriString(ffs) }") + ">")
.ConfigureAwait(false); .ConfigureAwait(false);
} }
@ -605,7 +606,7 @@ namespace NadekoBot.Modules.Searches
return; return;
var img = new ImageSharp.Image(50, 50); var img = new ImageSharp.Image(50, 50);
img.ApplyProcessor(new BackgroundColorProcessor<ImageSharp.Color>(ImageSharp.Color.FromHex(color)), img.Bounds); img.BackgroundColor(ImageSharp.Color.FromHex(color));
await Context.Channel.SendFileAsync(img.ToStream(), $"{color}.png").ConfigureAwait(false); await Context.Channel.SendFileAsync(img.ToStream(), $"{color}.png").ConfigureAwait(false);
} }

View File

@ -53,7 +53,7 @@ namespace NadekoBot.Modules.Utility
"GetHashCode", "GetHashCode",
"GetType" "GetType"
}); });
await Context.Channel.SendConfirmAsync(GetText("utility_calcops", Prefix), string.Join(", ", selection)); await Context.Channel.SendConfirmAsync(GetText("calcops", Prefix), string.Join(", ", selection));
} }
} }

View File

@ -0,0 +1,149 @@
using Discord;
using Discord.Commands;
using Microsoft.EntityFrameworkCore;
using NadekoBot.Attributes;
using NadekoBot.Extensions;
using NadekoBot.Services;
using NadekoBot.Services.Database;
using NadekoBot.Services.Database.Models;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System;
namespace NadekoBot.Modules.Utility
{
public partial class Utility
{
public class CommandAliasEqualityComparer : IEqualityComparer<CommandAlias>
{
public bool Equals(CommandAlias x, CommandAlias y) => x.Trigger == y.Trigger;
public int GetHashCode(CommandAlias obj) => obj.Trigger.GetHashCode();
}
[Group]
public class CommandMapCommands : NadekoSubmodule
{
//guildId, (trigger, mapping)
public static ConcurrentDictionary<ulong, ConcurrentDictionary<string, string>> AliasMaps { get; } = new ConcurrentDictionary<ulong, ConcurrentDictionary<string, string>>();
static CommandMapCommands()
{
var eq = new CommandAliasEqualityComparer();
AliasMaps = new ConcurrentDictionary<ulong, ConcurrentDictionary<string, string>>(
NadekoBot.AllGuildConfigs.ToDictionary(
x => x.GuildId,
x => new ConcurrentDictionary<string, string>(x.CommandAliases
.Distinct(eq)
.ToDictionary(ca => ca.Trigger, ca => ca.Mapping))));
}
[NadekoCommand, Usage, Description, Aliases]
[RequireUserPermission(GuildPermission.Administrator)]
[RequireContext(ContextType.Guild)]
public async Task Alias(string trigger, [Remainder] string mapping = null)
{
var channel = (ITextChannel)Context.Channel;
if (string.IsNullOrWhiteSpace(trigger))
return;
trigger = trigger.Trim().ToLowerInvariant();
if (string.IsNullOrWhiteSpace(mapping))
{
ConcurrentDictionary<string, string> maps;
string throwaway;
if (!AliasMaps.TryGetValue(Context.Guild.Id, out maps) ||
!maps.TryRemove(trigger, out throwaway))
{
await ReplyErrorLocalized("alias_remove_fail", Format.Code(trigger)).ConfigureAwait(false);
return;
}
using (var uow = DbHandler.UnitOfWork())
{
var config = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.CommandAliases));
var toAdd = new CommandAlias()
{
Mapping = mapping,
Trigger = trigger
};
config.CommandAliases.RemoveWhere(x => x.Trigger == trigger);
uow.Complete();
}
await ReplyConfirmLocalized("alias_removed", Format.Code(trigger)).ConfigureAwait(false);
return;
}
AliasMaps.AddOrUpdate(Context.Guild.Id, (_) =>
{
using (var uow = DbHandler.UnitOfWork())
{
var config = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.CommandAliases));
config.CommandAliases.Add(new CommandAlias()
{
Mapping = mapping,
Trigger = trigger
});
uow.Complete();
}
return new ConcurrentDictionary<string, string>(new Dictionary<string, string>() {
{trigger.Trim().ToLowerInvariant(), mapping.ToLowerInvariant() },
});
}, (_, map) =>
{
using (var uow = DbHandler.UnitOfWork())
{
var config = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.CommandAliases));
var toAdd = new CommandAlias()
{
Mapping = mapping,
Trigger = trigger
};
config.CommandAliases.RemoveWhere(x => x.Trigger == trigger);
config.CommandAliases.Add(toAdd);
uow.Complete();
}
map.AddOrUpdate(trigger, mapping, (key, old) => mapping);
return map;
});
await ReplyConfirmLocalized("alias_added", Format.Code(trigger), Format.Code(mapping)).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task AliasList(int page = 1)
{
var channel = (ITextChannel)Context.Channel;
page -= 1;
if (page < 0)
return;
ConcurrentDictionary<string, string> maps;
if (!AliasMaps.TryGetValue(Context.Guild.Id, out maps) || !maps.Any())
{
await ReplyErrorLocalized("aliases_none").ConfigureAwait(false);
return;
}
var arr = maps.ToArray();
await Context.Channel.SendPaginatedConfirmAsync(page + 1, (curPage) =>
{
return new EmbedBuilder().WithOkColor()
.WithTitle(GetText("alias_list"))
.WithDescription(string.Join("\n",
arr.Skip((curPage - 1) * 10).Take(10).Select(x => $"`{x.Key}` => `{x.Value}`")));
}, arr.Length / 10).ConfigureAwait(false);
}
}
}
}

View File

@ -114,11 +114,10 @@ namespace NadekoBot.Modules.Utility
source.Cancel(); source.Cancel();
} }
public override string ToString() public override string ToString() =>
{ $"{Channel?.Mention ?? $"<#{Repeater.ChannelId}>" } " +
return $"| {(int) Repeater.Interval.TotalHours}:{Repeater.Interval:mm} " +
$"{Channel.Mention} | {(int) Repeater.Interval.TotalHours}:{Repeater.Interval:mm} | {Repeater.Message.TrimTo(33)}"; $"| {Repeater.Message.TrimTo(33)}";
}
} }
static RepeatCommands() static RepeatCommands()
@ -247,7 +246,7 @@ namespace NadekoBot.Modules.Utility
await Context.Channel.SendConfirmAsync( await Context.Channel.SendConfirmAsync(
"🔁 " + GetText("repeater", "🔁 " + GetText("repeater",
Format.Bold(rep.Repeater.Message), Format.Bold(((IGuildUser)Context.User).GuildPermissions.MentionEveryone ? rep.Repeater.Message : rep.Repeater.Message.SanitizeMentions()),
Format.Bold(rep.Repeater.Interval.Days.ToString()), Format.Bold(rep.Repeater.Interval.Days.ToString()),
Format.Bold(rep.Repeater.Interval.Hours.ToString()), Format.Bold(rep.Repeater.Interval.Hours.ToString()),
Format.Bold(rep.Repeater.Interval.Minutes.ToString()))).ConfigureAwait(false); Format.Bold(rep.Repeater.Interval.Minutes.ToString()))).ConfigureAwait(false);

View File

@ -0,0 +1,78 @@
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Discord.Commands;
using Discord;
using NadekoBot.Attributes;
using NadekoBot.Modules.Utility.Models;
using Newtonsoft.Json;
namespace NadekoBot.Modules.Utility
{
public partial class Utility
{
//[Group]
//public class PatreonCommands : NadekoSubmodule
//{
// [NadekoCommand, Usage, Description, Aliases]
// [RequireContext(ContextType.Guild)]
// public async Task ClaimPatreonRewards([Remainder] string arg)
// {
// var pledges = await GetPledges2();
// }
// private static async Task<Pledge[]> GetPledges()
// {
// var pledges = new List<Pledge>();
// using (var http = new HttpClient())
// {
// http.DefaultRequestHeaders.Clear();
// http.DefaultRequestHeaders.Add("Authorization", "Bearer " + NadekoBot.Credentials.PatreonAccessToken);
// var data = new PatreonData()
// {
// Links = new Links()
// {
// 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);
// pledges.AddRange(data.Data);
// } while (!string.IsNullOrWhiteSpace(data.Links.Next));
// }
// return pledges.Where(x => string.IsNullOrWhiteSpace(x.Attributes.declined_since)).ToArray();
// }
// private static async Task<Pledge[]> GetPledges2()
// {
// var pledges = new List<Pledge>();
// using (var http = new HttpClient())
// {
// http.DefaultRequestHeaders.Clear();
// http.DefaultRequestHeaders.Add("Authorization", "Bearer " + NadekoBot.Credentials.PatreonAccessToken);
// var data = new PatreonData()
// {
// Links = new Links()
// {
// Next = "https://api.patreon.com/oauth2/api/current_user/campaigns?include=pledges"
// }
// };
// do
// {
// var res =
// await http.GetStringAsync(data.Links.Next)
// .ConfigureAwait(false);
// data = JsonConvert.DeserializeObject<PatreonData>(res);
// pledges.AddRange(data.Data);
// } while (!string.IsNullOrWhiteSpace(data.Links.Next));
// }
// return pledges.Where(x => string.IsNullOrWhiteSpace(x.Attributes.declined_since)).ToArray();
// }
//}
}
}

View File

@ -34,7 +34,7 @@ namespace NadekoBot.Modules.Utility
if (quotes.Any()) if (quotes.Any())
await Context.Channel.SendConfirmAsync(GetText("quotes_page", page + 1), await Context.Channel.SendConfirmAsync(GetText("quotes_page", page + 1),
string.Join("\n", quotes.Select(q => $"{q.Keyword,-20} by {q.AuthorName}"))) string.Join("\n", quotes.Select(q => $"`#{q.Id}` {Format.Bold(q.Keyword),-20} by {q.AuthorName}")))
.ConfigureAwait(false); .ConfigureAwait(false);
else else
await ReplyErrorLocalized("quotes_page_none").ConfigureAwait(false); await ReplyErrorLocalized("quotes_page_none").ConfigureAwait(false);
@ -52,7 +52,8 @@ namespace NadekoBot.Modules.Utility
Quote quote; Quote quote;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
quote = await uow.Quotes.GetRandomQuoteByKeywordAsync(Context.Guild.Id, keyword).ConfigureAwait(false); quote =
await uow.Quotes.GetRandomQuoteByKeywordAsync(Context.Guild.Id, keyword).ConfigureAwait(false);
} }
if (quote == null) if (quote == null)
@ -61,7 +62,11 @@ namespace NadekoBot.Modules.Utility
CREmbed crembed; CREmbed crembed;
if (CREmbed.TryParse(quote.Text, out crembed)) if (CREmbed.TryParse(quote.Text, out crembed))
{ {
try { await Context.Channel.EmbedAsync(crembed.ToEmbed(), crembed.PlainText ?? "").ConfigureAwait(false); } try
{
await Context.Channel.EmbedAsync(crembed.ToEmbed(), crembed.PlainText ?? "")
.ConfigureAwait(false);
}
catch (Exception ex) catch (Exception ex)
{ {
_log.Warn("Sending CREmbed failed"); _log.Warn("Sending CREmbed failed");
@ -69,7 +74,7 @@ namespace NadekoBot.Modules.Utility
} }
return; return;
} }
await Context.Channel.SendMessageAsync("📣 " + quote.Text.SanitizeMentions()); await Context.Channel.SendMessageAsync($"`#{quote.Id}` 📣 " + quote.Text.SanitizeMentions());
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
@ -84,13 +89,16 @@ namespace NadekoBot.Modules.Utility
Quote keywordquote; Quote keywordquote;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
keywordquote = await uow.Quotes.SearchQuoteKeywordTextAsync(Context.Guild.Id, keyword, text).ConfigureAwait(false); keywordquote =
await uow.Quotes.SearchQuoteKeywordTextAsync(Context.Guild.Id, keyword, text)
.ConfigureAwait(false);
} }
if (keywordquote == null) if (keywordquote == null)
return; return;
await Context.Channel.SendMessageAsync("💬 " + keyword + ": " + keywordquote.Text.SanitizeMentions()); await Context.Channel.SendMessageAsync("💬 " + keyword.ToLowerInvariant() + ": " +
keywordquote.Text.SanitizeMentions());
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
@ -119,33 +127,26 @@ namespace NadekoBot.Modules.Utility
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task DeleteQuote([Remainder] string keyword) public async Task DeleteQuote(int id)
{ {
if (string.IsNullOrWhiteSpace(keyword))
return;
var isAdmin = ((IGuildUser) Context.Message.Author).GuildPermissions.Administrator; var isAdmin = ((IGuildUser) Context.Message.Author).GuildPermissions.Administrator;
keyword = keyword.ToUpperInvariant();
var sucess = false; var sucess = false;
string response; string response;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var qs = uow.Quotes.GetAllQuotesByKeyword(Context.Guild.Id, keyword)?.Where(elem => isAdmin || elem.AuthorId == Context.Message.Author.Id).ToArray(); var q = uow.Quotes.Get(id);
if (qs == null || !qs.Any()) if (q == null || (!isAdmin && q.AuthorId != Context.Message.Author.Id))
{ {
sucess = false;
response = GetText("quotes_remove_none"); response = GetText("quotes_remove_none");
} }
else else
{ {
var q = qs[new NadekoRandom().Next(0, qs.Length)];
uow.Quotes.Remove(q); uow.Quotes.Remove(q);
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
sucess = true; sucess = true;
response = GetText("quote_deleted"); response = GetText("quote_deleted", id);
} }
} }
if (sucess) if (sucess)
@ -166,9 +167,7 @@ namespace NadekoBot.Modules.Utility
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var quotes = uow.Quotes.GetAllQuotesByKeyword(Context.Guild.Id, keyword); uow.Quotes.RemoveAllByKeyword(Context.Guild.Id, keyword.ToUpperInvariant());
//todo kwoth please don't be complete retard
uow.Quotes.RemoveRange(quotes.ToArray());//wtf?!
await uow.CompleteAsync(); await uow.CompleteAsync();
} }

View File

@ -64,7 +64,10 @@ namespace NadekoBot.Modules.Utility
IMessageChannel ch; IMessageChannel ch;
if (r.IsPrivate) if (r.IsPrivate)
{ {
ch = await NadekoBot.Client.GetDMChannelAsync(r.ChannelId).ConfigureAwait(false); var user = NadekoBot.Client.GetGuild(r.ServerId).GetUser(r.ChannelId);
if(user == null)
return;
ch = await user.CreateDMChannelAsync().ConfigureAwait(false);
} }
else else
{ {
@ -100,25 +103,20 @@ namespace NadekoBot.Modules.Utility
[Priority(1)] [Priority(1)]
public async Task Remind(MeOrHere meorhere, string timeStr, [Remainder] string message) public async Task Remind(MeOrHere meorhere, string timeStr, [Remainder] string message)
{ {
IMessageChannel target; ulong target;
if (meorhere == MeOrHere.Me) target = meorhere == MeOrHere.Me ? Context.User.Id : Context.Channel.Id;
{ await RemindInternal(target, meorhere == MeOrHere.Me, timeStr, message).ConfigureAwait(false);
target = await ((IGuildUser)Context.User).CreateDMChannelAsync().ConfigureAwait(false);
}
else
{
target = Context.Channel;
}
await Remind(target, timeStr, message).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageMessages)]
[Priority(0)] [Priority(0)]
public async Task Remind(IMessageChannel ch, string timeStr, [Remainder] string message) public Task Remind(ITextChannel channel, string timeStr, [Remainder] string message) =>
{ RemindInternal(channel.Id, false, timeStr, message);
var channel = (ITextChannel)Context.Channel;
public async Task RemindInternal(ulong targetId, bool isPrivate, string timeStr, [Remainder] string message)
{
var m = _regex.Match(timeStr); var m = _regex.Match(timeStr);
if (m.Length == 0) if (m.Length == 0)
@ -148,7 +146,7 @@ namespace NadekoBot.Modules.Utility
(groupName == "hours" && value > 23) || (groupName == "hours" && value > 23) ||
(groupName == "minutes" && value > 59)) (groupName == "minutes" && value > 59))
{ {
await channel.SendErrorAsync($"Invalid {groupName} value.").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"Invalid {groupName} value.").ConfigureAwait(false);
return; return;
} }
namesAndValues[groupName] = value; namesAndValues[groupName] = value;
@ -163,12 +161,12 @@ namespace NadekoBot.Modules.Utility
var rem = new Reminder var rem = new Reminder
{ {
ChannelId = ch.Id, ChannelId = targetId,
IsPrivate = ch is IDMChannel, IsPrivate = isPrivate,
When = time, When = time,
Message = message, Message = message,
UserId = Context.User.Id, UserId = Context.User.Id,
ServerId = channel.Guild.Id ServerId = Context.Guild.Id
}; };
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
@ -179,9 +177,9 @@ namespace NadekoBot.Modules.Utility
try try
{ {
await channel.SendConfirmAsync( await Context.Channel.SendConfirmAsync(
"⏰ " + GetText("remind", "⏰ " + GetText("remind",
Format.Bold(ch is ITextChannel ? ((ITextChannel) ch).Name : Context.User.Username), Format.Bold(!isPrivate ? $"<#{targetId}>" : Context.User.Username),
Format.Bold(message.SanitizeMentions()), Format.Bold(message.SanitizeMentions()),
Format.Bold(output), Format.Bold(output),
time, time)).ConfigureAwait(false); time, time)).ConfigureAwait(false);

View File

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Utility.Models
{
public class PatreonData
{
public Pledge[] Data { get; set; }
public Links Links { get; set; }
}
public class Attributes
{
public int amount_cents { get; set; }
public string created_at { 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 Attributes Attributes { get; set; }
public int Id { get; set; }
}
public class Links
{
public string First { get; set; }
public string Next { get; set; }
}
}

View File

@ -22,7 +22,7 @@ namespace NadekoBot.Modules.Utility
[NadekoModule("Utility", ".")] [NadekoModule("Utility", ".")]
public partial class Utility : NadekoTopLevelModule public partial class Utility : NadekoTopLevelModule
{ {
private static ConcurrentDictionary<ulong, Timer> rotatingRoleColors = new ConcurrentDictionary<ulong, Timer>(); private static ConcurrentDictionary<ulong, Timer> _rotatingRoleColors = new ConcurrentDictionary<ulong, Timer>();
//[NadekoCommand, Usage, Description, Aliases] //[NadekoCommand, Usage, Description, Aliases]
//[RequireContext(ContextType.Guild)] //[RequireContext(ContextType.Guild)]
@ -114,7 +114,7 @@ namespace NadekoBot.Modules.Utility
Timer t; Timer t;
if (timeout == 0 || hexes.Length == 0) if (timeout == 0 || hexes.Length == 0)
{ {
if (rotatingRoleColors.TryRemove(role.Id, out t)) if (_rotatingRoleColors.TryRemove(role.Id, out t))
{ {
t.Change(Timeout.Infinite, Timeout.Infinite); t.Change(Timeout.Infinite, Timeout.Infinite);
await ReplyConfirmLocalized("rrc_stop", Format.Bold(role.Name)).ConfigureAwait(false); await ReplyConfirmLocalized("rrc_stop", Format.Bold(role.Name)).ConfigureAwait(false);
@ -157,7 +157,7 @@ namespace NadekoBot.Modules.Utility
catch { } catch { }
}, null, 0, timeout * 1000); }, null, 0, timeout * 1000);
rotatingRoleColors.AddOrUpdate(role.Id, t, (key, old) => _rotatingRoleColors.AddOrUpdate(role.Id, t, (key, old) =>
{ {
old.Change(Timeout.Infinite, Timeout.Infinite); old.Change(Timeout.Infinite, Timeout.Infinite);
return t; return t;
@ -217,33 +217,18 @@ namespace NadekoBot.Modules.Utility
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task InRole(params IRole[] roles) public async Task InRole([Remainder] IRole role)
{ {
if (roles.Length == 0) var rng = new NadekoRandom();
return;
var send = " " + Format.Bold(GetText("inrole_list"));
var usrs = (await Context.Guild.GetUsersAsync()).ToArray(); var usrs = (await Context.Guild.GetUsersAsync()).ToArray();
foreach (var role in roles.Where(r => r.Id != Context.Guild.Id)) var roleUsers = usrs.Where(u => u.RoleIds.Contains(role.Id)).Select(u => u.ToString())
{ .ToArray();
send += $"```css\n[{role.Name}]\n"; var embed = new EmbedBuilder().WithOkColor()
send += string.Join(", ", usrs.Where(u => u.RoleIds.Contains(role.Id)).Select(u => u.ToString())); .WithTitle(" " + Format.Bold(GetText("inrole_list", Format.Bold(role.Name))) + $" - {roleUsers.Length}")
send += "\n```"; .WithDescription(string.Join(", ", roleUsers
} .OrderBy(x => rng.Next())
var usr = (IGuildUser)Context.User; .Take(50)));
while (send.Length > 2000) await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
{
if (!usr.GetPermissions((ITextChannel)Context.Channel).ManageMessages)
{
await ReplyErrorLocalized("inrole_not_allowed").ConfigureAwait(false);
return;
}
var curstr = send.Substring(0, 2000);
await Context.Channel.SendConfirmAsync(curstr.Substring(0,
curstr.LastIndexOf(", ", StringComparison.Ordinal) + 1)).ConfigureAwait(false);
send = curstr.Substring(curstr.LastIndexOf(", ", StringComparison.Ordinal) + 1) +
send.Substring(2000);
}
await Context.Channel.SendConfirmAsync(send).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
@ -481,7 +466,31 @@ namespace NadekoBot.Modules.Utility
var title = $"Chatlog-{Context.Guild.Name}/#{Context.Channel.Name}-{DateTime.Now}.txt"; var title = $"Chatlog-{Context.Guild.Name}/#{Context.Channel.Name}-{DateTime.Now}.txt";
var grouping = msgs.GroupBy(x => $"{x.CreatedAt.Date:dd.MM.yyyy}") var grouping = msgs.GroupBy(x => $"{x.CreatedAt.Date:dd.MM.yyyy}")
.Select(g => new { date = g.Key, messages = g.OrderBy(x => x.CreatedAt).Select(s => $"【{s.Timestamp:HH:mm:ss}】{s.Author}:" + s.ToString()) }); .Select(g => new
{
date = g.Key,
messages = g.OrderBy(x => x.CreatedAt).Select(s =>
{
var msg = $"【{s.Timestamp:HH:mm:ss}】{s.Author}:";
if (string.IsNullOrWhiteSpace(s.ToString()))
{
if (s.Attachments.Any())
{
msg += "FILES_UPLOADED: " + string.Join("\n", s.Attachments.Select(x => x.Url));
}
else if (s.Embeds.Any())
{
//todo probably just go through all properties and check if they are set, if they are, add them
msg += "EMBEDS: " + string.Join("\n--------\n", s.Embeds.Select(x => $"Description: {x.Description}"));
}
}
else
{
msg += s.ToString();
}
return msg;
})
});
await Context.User.SendFileAsync( await Context.User.SendFileAsync(
await JsonConvert.SerializeObject(grouping, Formatting.Indented).ToStream().ConfigureAwait(false), title, title).ConfigureAwait(false); await JsonConvert.SerializeObject(grouping, Formatting.Indented).ToStream().ConfigureAwait(false), title, title).ConfigureAwait(false);
} }

View File

@ -110,6 +110,7 @@ namespace NadekoBot
//setup typereaders //setup typereaders
CommandService.AddTypeReader<PermissionAction>(new PermissionActionTypeReader()); CommandService.AddTypeReader<PermissionAction>(new PermissionActionTypeReader());
CommandService.AddTypeReader<CommandInfo>(new CommandTypeReader()); CommandService.AddTypeReader<CommandInfo>(new CommandTypeReader());
CommandService.AddTypeReader<CommandOrCrInfo>(new CommandOrCrTypeReader());
CommandService.AddTypeReader<ModuleInfo>(new ModuleTypeReader()); CommandService.AddTypeReader<ModuleInfo>(new ModuleTypeReader());
CommandService.AddTypeReader<IGuild>(new GuildTypeReader()); CommandService.AddTypeReader<IGuild>(new GuildTypeReader());

View File

@ -96,7 +96,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Starts an Acrophobia game. Second argment is optional round length in seconds. (default is 60). /// Looks up a localized string similar to Starts an Acrophobia game. Second argument is optional round length in seconds. (default is 60).
/// </summary> /// </summary>
public static string acro_desc { public static string acro_desc {
get { get {
@ -150,7 +150,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Add a custom reaction with a trigger and a response. Running this command in server requires Administration permission. Running this command in DM is Bot Owner only and adds a new global custom reaction. Guide here: &lt;http://nadekobot.readthedocs.io/en/latest/Custom%20Reactions/&gt;. /// Looks up a localized string similar to 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: &lt;http://nadekobot.readthedocs.io/en/latest/Custom%20Reactions/&gt;.
/// </summary> /// </summary>
public static string addcustreact_desc { public static string addcustreact_desc {
get { get {
@ -177,7 +177,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Adds a specified string to the list of playing strings to rotate. Supported placeholders: %servers%, %users%, %playing%, %queued%, %time%,%shardid%,%shardcount%, %shardguilds%. /// Looks up a localized string similar to Adds a specified string to the list of playing strings to rotate. Supported placeholders: `%servers%`, `%users%`, `%playing%`, `%queued%`, `%time%`, `%shardid%`, `%shardcount%`, `%shardguilds%`..
/// </summary> /// </summary>
public static string addplaying_desc { public static string addplaying_desc {
get { get {
@ -231,7 +231,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Toggles the automatic deletion of confirmations for {0}iam and {0}iamn commands.. /// Looks up a localized string similar to Toggles the automatic deletion of confirmations for `{0}iam` and `{0}iamn` commands..
/// </summary> /// </summary>
public static string adsarm_desc { public static string adsarm_desc {
get { get {
@ -248,6 +248,60 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to alias cmdmap.
/// </summary>
public static string alias_cmd {
get {
return ResourceManager.GetString("alias_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Create a custom alias for a certain Nadeko command. Provide no alias to remove the existing one..
/// </summary>
public static string alias_desc {
get {
return ResourceManager.GetString("alias_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}alias allin $bf 100 h` or `{0}alias &quot;linux thingy&quot; &gt;loonix Spyware Windows`.
/// </summary>
public static string alias_usage {
get {
return ResourceManager.GetString("alias_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to aliaslist cmdmaplist aliases.
/// </summary>
public static string aliaslist_cmd {
get {
return ResourceManager.GetString("aliaslist_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Shows the list of currently set aliases. Paginated..
/// </summary>
public static string aliaslist_desc {
get {
return ResourceManager.GetString("aliaslist_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}aliaslist` or `{0}aliaslist 3`.
/// </summary>
public static string aliaslist_usage {
get {
return ResourceManager.GetString("aliaslist_usage", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to allchnlmdls acm. /// Looks up a localized string similar to allchnlmdls acm.
/// </summary> /// </summary>
@ -420,7 +474,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Sends a message to all servers&apos; general channel bot is connected to.. /// Looks up a localized string similar to Sends a message to all servers&apos; default channel that bot is connected to..
/// </summary> /// </summary>
public static string announce_desc { public static string announce_desc {
get { get {
@ -690,7 +744,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Toggles autoplay - When the song is finished, automatically queue a related youtube song. (Works only for youtube songs and when queue is empty). /// Looks up a localized string similar to Toggles autoplay - When the song is finished, automatically queue a related Youtube song. (Works only for Youtube songs and when queue is empty).
/// </summary> /// </summary>
public static string autoplay_desc { public static string autoplay_desc {
get { get {
@ -1014,7 +1068,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Sets the time it takes (in seconds) for bye messages to be auto-deleted. Set 0 to disable automatic deletion.. /// Looks up a localized string similar to Sets the time it takes (in seconds) for bye messages to be auto-deleted. Set it to `0` to disable automatic deletion..
/// </summary> /// </summary>
public static string byedel_desc { public static string byedel_desc {
get { get {
@ -1041,7 +1095,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to 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 &lt;http://nadekobot.xyz/embedbuilder/&gt; instead of a regular text, if you want the message to be embedded.. /// Looks up a localized string similar to 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 &lt;http://nadekobot.xyz/embedbuilder/&gt; instead of a regular text, if you want the message to be embedded..
/// </summary> /// </summary>
public static string byemsg_desc { public static string byemsg_desc {
get { get {
@ -1068,7 +1122,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Shows all available operations in {0}calc command. /// Looks up a localized string similar to Shows all available operations in the `{0}calc` command.
/// </summary> /// </summary>
public static string calcops_desc { public static string calcops_desc {
get { get {
@ -1419,7 +1473,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Toggles automatic deleting of invites posted in the channel. Does not negate the {0}srvrfilterinv enabled setting. Does not affect Bot Owner.. /// Looks up a localized string similar to Toggles automatic deletion of invites posted in the channel. Does not negate the `{0}srvrfilterinv` enabled setting. Does not affect the Bot Owner..
/// </summary> /// </summary>
public static string chnlfilterinv_desc { public static string chnlfilterinv_desc {
get { get {
@ -1446,7 +1500,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Toggles automatic deleting of messages containing banned words on the channel. Does not negate the {0}srvrfilterwords enabled setting. Does not affect bot owner.. /// Looks up a localized string similar to Toggles automatic deletion of messages containing filtered words on the channel. Does not negate the `{0}srvrfilterwords` enabled setting. Does not affect the Bot Owner..
/// </summary> /// </summary>
public static string chnlfilterwords_desc { public static string chnlfilterwords_desc {
get { get {
@ -1527,7 +1581,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Shows a random chucknorris joke from &lt;http://tambal.azurewebsites.net/joke/random&gt;. /// Looks up a localized string similar to Shows a random Chuck Norris joke from &lt;http://tambal.azurewebsites.net/joke/random&gt;.
/// </summary> /// </summary>
public static string chucknorris_desc { public static string chucknorris_desc {
get { get {
@ -1743,7 +1797,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Sets a cooldown per user for a command. Set to 0 to remove the cooldown.. /// Looks up a localized string similar to Sets a cooldown per user for a command. Set it to 0 to remove the cooldown..
/// </summary> /// </summary>
public static string cmdcooldown_desc { public static string cmdcooldown_desc {
get { get {
@ -1770,7 +1824,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Shows a list of command costs. Paginated with 9 command per page.. /// Looks up a localized string similar to Shows a list of command costs. Paginated with 9 commands per page..
/// </summary> /// </summary>
public static string cmdcosts_desc { public static string cmdcosts_desc {
get { get {
@ -1851,7 +1905,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to List all of the bot&apos;s commands from a certain module. You can either specify full, or only first few letters of the module name.. /// Looks up a localized string similar to List all of the bot&apos;s commands from a certain module. You can either specify the full name or only the first few letters of the module name..
/// </summary> /// </summary>
public static string commands_desc { public static string commands_desc {
get { get {
@ -1976,6 +2030,60 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to crad.
/// </summary>
public static string crad_cmd {
get {
return ResourceManager.GetString("crad_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Toggles whether the message triggering the custom reaction will be automatically deleted..
/// </summary>
public static string crad_desc {
get {
return ResourceManager.GetString("crad_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}crad 59`.
/// </summary>
public static string crad_usage {
get {
return ResourceManager.GetString("crad_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to crdm.
/// </summary>
public static string crdm_cmd {
get {
return ResourceManager.GetString("crdm_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Toggles whether the response message of the custom reaction will be sent as a direct message..
/// </summary>
public static string crdm_desc {
get {
return ResourceManager.GetString("crdm_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}crad 44`.
/// </summary>
public static string crdm_usage {
get {
return ResourceManager.GetString("crdm_usage", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to createinvite crinv. /// Looks up a localized string similar to createinvite crinv.
/// </summary> /// </summary>
@ -2310,7 +2418,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Deletes a custom reaction on a specific index. If ran in DM, it is bot owner only and deletes a global custom reaction. If ran in a server, it requires Administration priviledges and removes server custom reaction.. /// Looks up a localized string similar to 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..
/// </summary> /// </summary>
public static string delcustreact_desc { public static string delcustreact_desc {
get { get {
@ -2337,7 +2445,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Deletes a saved playlist. Only if you made it or if you are the bot owner.. /// Looks up a localized string similar to Deletes a saved playlist. Works only if you made it or if you are the bot owner..
/// </summary> /// </summary>
public static string deleteplaylist_desc { public static string deleteplaylist_desc {
get { get {
@ -2364,7 +2472,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Deletes a random quote with the specified keyword. You have to either be server Administrator or the creator of the quote to delete it.. /// Looks up a localized string similar to Deletes a quote with the specified ID. You have to be either server Administrator or the creator of the quote to delete it..
/// </summary> /// </summary>
public static string deletequote_desc { public static string deletequote_desc {
get { get {
@ -2373,7 +2481,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to `{0}delq abc`. /// Looks up a localized string similar to `{0}delq 123456`.
/// </summary> /// </summary>
public static string deletequote_usage { public static string deletequote_usage {
get { get {
@ -2391,7 +2499,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Toggles the automatic deletion of user&apos;s successful command message to prevent chat flood.. /// Looks up a localized string similar to Toggles the automatic deletion of the user&apos;s successful command message to prevent chat flood..
/// </summary> /// </summary>
public static string delmsgoncmd_desc { public static string delmsgoncmd_desc {
get { get {
@ -2607,7 +2715,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to List of lovely people who donated to keep this project alive.. /// Looks up a localized string similar to List of the lovely people who donated to keep this project alive..
/// </summary> /// </summary>
public static string donators_desc { public static string donators_desc {
get { get {
@ -2715,7 +2823,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Toggles fairplay. While enabled, music player will prioritize songs from users who didn&apos;t have their song recently played instead of the song&apos;s position in the queue.. /// Looks up a localized string similar to Toggles fairplay. While enabled, the bot will prioritize songs from users who didn&apos;t have their song recently played instead of the song&apos;s position in the queue..
/// </summary> /// </summary>
public static string fairplay_desc { public static string fairplay_desc {
get { get {
@ -2823,7 +2931,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Toggles whether messages will be forwarded to all bot owners or only to the first one specified in the credentials.json. /// Looks up a localized string similar to Toggles whether messages will be forwarded to all bot owners or only to the first one specified in the credentials.json file.
/// </summary> /// </summary>
public static string forwardtoall_desc { public static string forwardtoall_desc {
get { get {
@ -2931,7 +3039,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Get a google search link for some terms.. /// Looks up a localized string similar to Get a Google search link for some terms..
/// </summary> /// </summary>
public static string google_desc { public static string google_desc {
get { get {
@ -3012,7 +3120,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Sets the time it takes (in seconds) for greet messages to be auto-deleted. Set 0 to disable automatic deletion.. /// Looks up a localized string similar to Sets the time it takes (in seconds) for greet messages to be auto-deleted. Set it to 0 to disable automatic deletion..
/// </summary> /// </summary>
public static string greetdel_desc { public static string greetdel_desc {
get { get {
@ -3066,7 +3174,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Sets a new join announcement message which will be sent to the user who joined. Type %user% if you want to mention the new member. Using it with no message will show the current DM greet message. You can use embed json from &lt;http://nadekobot.xyz/embedbuilder/&gt; instead of a regular text, if you want the message to be embedded.. /// Looks up a localized string similar to Sets a new join announcement message which will be sent to the user who joined. Type `%user%` if you want to mention the new member. Using it with no message will show the current DM greet message. You can use embed json from &lt;http://nadekobot.xyz/embedbuilder/&gt; instead of a regular text, if you want the message to be embedded..
/// </summary> /// </summary>
public static string greetdmmsg_desc { public static string greetdmmsg_desc {
get { get {
@ -3093,7 +3201,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Sets a new join announcement message which will be shown in the server&apos;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 &lt;http://nadekobot.xyz/embedbuilder/&gt; instead of a regular text, if you want the message to be embedded.. /// Looks up a localized string similar to Sets a new join announcement message which will be shown in the server&apos;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 &lt;http://nadekobot.xyz/embedbuilder/&gt; instead of a regular text, if you want the message to be embedded..
/// </summary> /// </summary>
public static string greetmsg_desc { public static string greetmsg_desc {
get { get {
@ -3156,7 +3264,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to `{0}h !!q` or `{0}h`. /// Looks up a localized string similar to `{0}h {0}cmds` or `{0}h`.
/// </summary> /// </summary>
public static string h_usage { public static string h_usage {
get { get {
@ -3174,7 +3282,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Sets the music volume to 50%.. /// Looks up a localized string similar to Sets the music playback volume to 50%..
/// </summary> /// </summary>
public static string half_desc { public static string half_desc {
get { get {
@ -3282,7 +3390,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Heals someone. Revives those who fainted. Costs a NadekoFlower. /// Looks up a localized string similar to Heals someone. Revives those who fainted. Costs a NadekoFlower. .
/// </summary> /// </summary>
public static string heal_desc { public static string heal_desc {
get { get {
@ -3498,7 +3606,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Pulls the first image found using a search parameter. Use {0}rimg for different results.. /// Looks up a localized string similar to Pulls the first image found using a search parameter. Use `{0}rimg` for different results..
/// </summary> /// </summary>
public static string image_desc { public static string image_desc {
get { get {
@ -3552,7 +3660,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to 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.. /// Looks up a localized string similar to Lists every person from the specified role on this server. You can use role ID, role name..
/// </summary> /// </summary>
public static string inrole_desc { public static string inrole_desc {
get { get {
@ -3561,7 +3669,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to `{0}inrole Role` or `{0}inrole Role1 &quot;Role 2&quot; @role3`. /// Looks up a localized string similar to `{0}inrole Some Role`.
/// </summary> /// </summary>
public static string inrole_usage { public static string inrole_usage {
get { get {
@ -3687,7 +3795,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Sets this server&apos;s response language If bot&apos;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.. /// Looks up a localized string similar to Sets this server&apos;s response language. If bot&apos;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..
/// </summary> /// </summary>
public static string languageset_desc { public static string languageset_desc {
get { get {
@ -3768,7 +3876,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Leaves Cross server channel instance from this channel.. /// Looks up a localized string similar to Leaves a cross server channel instance from this channel..
/// </summary> /// </summary>
public static string lcsc_desc { public static string lcsc_desc {
get { get {
@ -3795,7 +3903,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Displays bot currency leaderboard.. /// Looks up a localized string similar to Displays the bot&apos;s currency leaderboard..
/// </summary> /// </summary>
public static string leaderboard_desc { public static string leaderboard_desc {
get { get {
@ -3822,7 +3930,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Makes Nadeko leave the server. Either name or id required.. /// Looks up a localized string similar to Makes Nadeko leave the server. Either server name or server ID is required..
/// </summary> /// </summary>
public static string leave_desc { public static string leave_desc {
get { get {
@ -4128,7 +4236,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to `{0}lw [war_number] or {0}lw`. /// Looks up a localized string similar to `{0}lw [war_number]` or `{0}lw`.
/// </summary> /// </summary>
public static string listwar_usage { public static string listwar_usage {
get { get {
@ -4173,7 +4281,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Loads a saved playlist using it&apos;s ID. Use `{0}pls` to list all saved playlists and {0}save to save new ones.. /// Looks up a localized string similar to Loads a saved playlist using its ID. Use `{0}pls` to list all saved playlists and `{0}save` to save new ones..
/// </summary> /// </summary>
public static string load_desc { public static string load_desc {
get { get {
@ -4254,7 +4362,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Toggles logging event. Disables it if it&apos;s active anywhere on the server. Enables if it&apos;s not active. Use `{0}logevents` to see a list of all events you can subscribe to.. /// Looks up a localized string similar to Toggles logging event. Disables it if it is active anywhere on the server. Enables if it isn&apos;t active. Use `{0}logevents` to see a list of all events you can subscribe to..
/// </summary> /// </summary>
public static string log_desc { public static string log_desc {
get { get {
@ -4308,7 +4416,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Toggles whether the .logserver command ignores this channel. Useful if you have hidden admin channel and public log channel.. /// Looks up a localized string similar to Toggles whether the `.logserver` command ignores this channel. Useful if you have hidden admin channel and public log channel..
/// </summary> /// </summary>
public static string logignore_desc { public static string logignore_desc {
get { get {
@ -4460,6 +4568,60 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to lucky7 l7.
/// </summary>
public static string lucky7_cmd {
get {
return ResourceManager.GetString("lucky7_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Bet currency on the game and start rolling 3 sided dice. At any point you can choose to [m]ove (roll again) or [s]tay (get the amount bet times the current multiplier)..
/// </summary>
public static string lucky7_desc {
get {
return ResourceManager.GetString("lucky7_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}l7 10` or `{0}l7 move` or `{0}l7 s`.
/// </summary>
public static string lucky7_usage {
get {
return ResourceManager.GetString("lucky7_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to lucky7test l7t.
/// </summary>
public static string lucky7test_cmd {
get {
return ResourceManager.GetString("lucky7test_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Tests the l7 command..
/// </summary>
public static string lucky7test_desc {
get {
return ResourceManager.GetString("lucky7test_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}l7t 10000`.
/// </summary>
public static string lucky7test_usage {
get {
return ResourceManager.GetString("lucky7test_usage", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to magicitem mi. /// Looks up a localized string similar to magicitem mi.
/// </summary> /// </summary>
@ -4524,7 +4686,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Shows basic info from myanimelist profile.. /// Looks up a localized string similar to Shows basic info from a MyAnimeList profile..
/// </summary> /// </summary>
public static string mal_desc { public static string mal_desc {
get { get {
@ -4578,7 +4740,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Sets the music volume to 100%.. /// Looks up a localized string similar to Sets the music playback volume to 100%..
/// </summary> /// </summary>
public static string max_desc { public static string max_desc {
get { get {
@ -4713,7 +4875,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Mentions every person from the provided role or roles (separated by a &apos;,&apos;) on this server. Requires you to have mention everyone permission.. /// Looks up a localized string similar to Mentions every person from the provided role or roles (separated by a &apos;,&apos;) on this server. Requires you to have the mention everyone permission..
/// </summary> /// </summary>
public static string mentionrole_desc { public static string mentionrole_desc {
get { get {
@ -4848,7 +5010,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Moves permission from one position to another in Permissions list.. /// Looks up a localized string similar to Moves permission from one position to another in the Permissions list..
/// </summary> /// </summary>
public static string moveperm_desc { public static string moveperm_desc {
get { get {
@ -4902,7 +5064,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Mutes a mentioned user both from speaking and chatting.. /// Looks up a localized string similar to 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..
/// </summary> /// </summary>
public static string mute_desc { public static string mute_desc {
get { get {
@ -4911,7 +5073,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to `{0}mute @Someone`. /// Looks up a localized string similar to `{0}mute @Someone` or `{0}mute 30 @Someone`.
/// </summary> /// </summary>
public static string mute_usage { public static string mute_usage {
get { get {
@ -4956,7 +5118,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Shows the song currently playing.. /// Looks up a localized string similar to Shows the song that the bot is currently playing..
/// </summary> /// </summary>
public static string nowplaying_desc { public static string nowplaying_desc {
get { get {
@ -5145,7 +5307,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Sets a role which can change permissions. Or supply no parameters to find out the current one. Default one is &apos;Nadeko&apos;.. /// Looks up a localized string similar to Sets a role which can change permissions. Supply no parameters to see the current one. Default is &apos;Nadeko&apos;..
/// </summary> /// </summary>
public static string permrole_desc { public static string permrole_desc {
get { get {
@ -5307,7 +5469,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Lists all playlists. Paginated. 20 per page. Default page is 0.. /// Looks up a localized string similar to Lists all playlists. Paginated, 20 per page. Default page is 0..
/// </summary> /// </summary>
public static string playlists_desc { public static string playlists_desc {
get { get {
@ -5469,7 +5631,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to `{0}prune` removes all nadeko&apos;s messages in the last 100 messages.`{0}prune X` removes last X messages from the channel (up to 100)`{0}prune @Someone` removes all Someone&apos;s messages in the last 100 messages.`{0}prune @Someone X` removes last X &apos;Someone&apos;s&apos; messages in the channel.. /// Looks up a localized string similar to `{0}prune` removes all Nadeko&apos;s messages in the last 100 messages. `{0}prune X` removes last `X` number of messages from the channel (up to 100). `{0}prune @Someone` removes all Someone&apos;s messages in the last 100 messages. `{0}prune @Someone X` removes last `X` number of &apos;Someone&apos;s&apos; messages in the channel..
/// </summary> /// </summary>
public static string prune_desc { public static string prune_desc {
get { get {
@ -5793,7 +5955,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Sends a message to you or a channel after certain amount of time. First argument is me/here/&apos;channelname&apos;. Second argument is time in a descending order (mo&gt;w&gt;d&gt;h&gt;m) example: 1w5d3h10m. Third argument is a (multiword)message.. /// Looks up a localized string similar to Sends a message to you or a channel after certain amount of time. First argument is `me`/`here`/&apos;channelname&apos;. Second argument is time in a descending order (mo&gt;w&gt;d&gt;h&gt;m) example: 1w5d3h10m. Third argument is a (multiword) message..
/// </summary> /// </summary>
public static string remind_desc { public static string remind_desc {
get { get {
@ -5820,7 +5982,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to 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.. /// Looks up a localized string similar to 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..
/// </summary> /// </summary>
public static string remindtemplate_desc { public static string remindtemplate_desc {
get { get {
@ -5901,7 +6063,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Removes a permission from a given position in Permissions list.. /// Looks up a localized string similar to Removes a permission from a given position in the Permissions list..
/// </summary> /// </summary>
public static string removeperm_desc { public static string removeperm_desc {
get { get {
@ -6009,7 +6171,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Renames a role. Roles you are renaming must be lower than bot&apos;s highest role.. /// Looks up a localized string similar to Renames a role. The role you are renaming must be lower than bot&apos;s highest role..
/// </summary> /// </summary>
public static string renamerole_desc { public static string renamerole_desc {
get { get {
@ -6036,7 +6198,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Repeat a message every X minutes in the current channel. You can have up to 5 repeating messages on the server in total.. /// Looks up a localized string similar to Repeat a message every `X` minutes in the current channel. You can have up to 5 repeating messages on the server in total..
/// </summary> /// </summary>
public static string repeat_desc { public static string repeat_desc {
get { get {
@ -6198,7 +6360,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Resets BOT&apos;s permissions module on this server to the default value.. /// Looks up a localized string similar to Resets the bot&apos;s permissions module on this server to the default value..
/// </summary> /// </summary>
public static string resetpermissions_desc { public static string resetpermissions_desc {
get { get {
@ -6252,7 +6414,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Returns a google reverse image search for someone&apos;s avatar.. /// Looks up a localized string similar to Returns a Google reverse image search for someone&apos;s avatar..
/// </summary> /// </summary>
public static string revav_desc { public static string revav_desc {
get { get {
@ -6279,7 +6441,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Returns a google reverse image search for an image from a link.. /// Looks up a localized string similar to Returns a Google reverse image search for an image from a link..
/// </summary> /// </summary>
public static string revimg_desc { public static string revimg_desc {
get { get {
@ -6387,7 +6549,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to List roles on this server or a roles of a specific user if specified. Paginated. 20 roles per page.. /// Looks up a localized string similar to List roles on this server or a roles of a specific user if specified. Paginated, 20 roles per page..
/// </summary> /// </summary>
public static string roles_desc { public static string roles_desc {
get { get {
@ -6414,7 +6576,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to 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 &apos;F&apos; if you want to roll fate dice instead of dnd.. /// Looks up a localized string similar to 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 &apos;F&apos; if you want to roll fate dice instead of dnd..
/// </summary> /// </summary>
public static string roll_desc { public static string roll_desc {
get { get {
@ -6441,7 +6603,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to 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.. /// Looks up a localized string similar to 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`..
/// </summary> /// </summary>
public static string rolluo_desc { public static string rolluo_desc {
get { get {
@ -6522,7 +6684,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Play a game of rocket paperclip scissors with Nadeko.. /// Looks up a localized string similar to Play a game of Rocket-Paperclip-Scissors with Nadeko..
/// </summary> /// </summary>
public static string rps_desc { public static string rps_desc {
get { get {
@ -6630,7 +6792,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Saves a playlist under a certain name. Name must be no longer than 20 characters and mustn&apos;t contain dashes.. /// Looks up a localized string similar to Saves a playlist under a certain name. Playlist name must be no longer than 20 characters and must not contain dashes..
/// </summary> /// </summary>
public static string save_desc { public static string save_desc {
get { get {
@ -6738,7 +6900,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Sends a message to someone on a different server through the bot. Separate server and channel/user ids with `|` and prepend channel id with `c:` and user id with `u:`.. /// Looks up a localized string similar to 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:`..
/// </summary> /// </summary>
public static string send_desc { public static string send_desc {
get { get {
@ -6765,7 +6927,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Either [add]s or [rem]oves a server specified by a Name or ID from a blacklist.. /// Looks up a localized string similar to Either [add]s or [rem]oves a server specified by a Name or an ID from a blacklist..
/// </summary> /// </summary>
public static string serverblacklist_desc { public static string serverblacklist_desc {
get { get {
@ -7548,7 +7710,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Queue a soundcloud playlist using a link.. /// Looks up a localized string similar to Queue a Soundcloud playlist using a link..
/// </summary> /// </summary>
public static string soundcloudpl_desc { public static string soundcloudpl_desc {
get { get {
@ -7629,7 +7791,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Toggles automatic deleting of invites posted in the server. Does not affect Bot Owner.. /// Looks up a localized string similar to Toggles automatic deletion of invites posted in the server. Does not affect the Bot Owner..
/// </summary> /// </summary>
public static string srvrfilterinv_desc { public static string srvrfilterinv_desc {
get { get {
@ -7656,7 +7818,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Toggles automatic deleting of messages containing forbidden words on the server. Does not affect Bot Owner.. /// Looks up a localized string similar to Toggles automatic deletion of messages containing filtered words on the server. Does not affect the Bot Owner..
/// </summary> /// </summary>
public static string srvrfilterwords_desc { public static string srvrfilterwords_desc {
get { get {
@ -8088,7 +8250,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to 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.. /// Looks up a localized string similar to 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..
/// </summary> /// </summary>
public static string trivia_desc { public static string trivia_desc {
get { get {
@ -8439,7 +8601,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Either [add]s or [rem]oves a user specified by a mention or ID from a blacklist.. /// Looks up a localized string similar to Either [add]s or [rem]oves a user specified by a Mention or an ID from a blacklist..
/// </summary> /// </summary>
public static string userblacklist_desc { public static string userblacklist_desc {
get { get {
@ -8591,6 +8753,60 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to vcrole.
/// </summary>
public static string vcrole_cmd {
get {
return ResourceManager.GetString("vcrole_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Sets or resets a role which will be given to users who join the voice channel you&apos;re in when you run this command. Provide no role name to disable. You must be in a voice channel to run this command..
/// </summary>
public static string vcrole_desc {
get {
return ResourceManager.GetString("vcrole_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}vcrole SomeRole` or `{0}vcrole`.
/// </summary>
public static string vcrole_usage {
get {
return ResourceManager.GetString("vcrole_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to vcrolelist.
/// </summary>
public static string vcrolelist_cmd {
get {
return ResourceManager.GetString("vcrolelist_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Shows a list of currently set voice channel roles..
/// </summary>
public static string vcrolelist_desc {
get {
return ResourceManager.GetString("vcrolelist_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}vcrolelist`.
/// </summary>
public static string vcrolelist_usage {
get {
return ResourceManager.GetString("vcrolelist_usage", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to verbose v. /// Looks up a localized string similar to verbose v.
/// </summary> /// </summary>
@ -8763,7 +8979,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Sets the music volume 0-100%. /// Looks up a localized string similar to Sets the music playback volume (0-100%).
/// </summary> /// </summary>
public static string volume_desc { public static string volume_desc {
get { get {

View File

@ -124,7 +124,7 @@
<value>Either shows a help for a single command, or DMs you help link if no arguments are specified.</value> <value>Either shows a help for a single command, or DMs you help link if no arguments are specified.</value>
</data> </data>
<data name="h_usage" xml:space="preserve"> <data name="h_usage" xml:space="preserve">
<value>`{0}h !!q` or `{0}h`</value> <value>`{0}h {0}cmds` or `{0}h`</value>
</data> </data>
<data name="hgit_cmd" xml:space="preserve"> <data name="hgit_cmd" xml:space="preserve">
<value>hgit</value> <value>hgit</value>
@ -157,7 +157,7 @@
<value>commands cmds</value> <value>commands cmds</value>
</data> </data>
<data name="commands_desc" xml:space="preserve"> <data name="commands_desc" xml:space="preserve">
<value>List all of the bot's commands from a certain module. You can either specify full, or only first few letters of the module name.</value> <value>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.</value>
</data> </data>
<data name="commands_usage" xml:space="preserve"> <data name="commands_usage" xml:space="preserve">
<value>`{0}commands Administration` or `{0}cmds Admin`</value> <value>`{0}commands Administration` or `{0}cmds Admin`</value>
@ -166,7 +166,7 @@
<value>greetdel grdel</value> <value>greetdel grdel</value>
</data> </data>
<data name="greetdel_desc" xml:space="preserve"> <data name="greetdel_desc" xml:space="preserve">
<value>Sets the time it takes (in seconds) for greet messages to be auto-deleted. Set 0 to disable automatic deletion.</value> <value>Sets the time it takes (in seconds) for greet messages to be auto-deleted. Set it to 0 to disable automatic deletion.</value>
</data> </data>
<data name="greetdel_usage" xml:space="preserve"> <data name="greetdel_usage" xml:space="preserve">
<value>`{0}greetdel 0` or `{0}greetdel 30`</value> <value>`{0}greetdel 0` or `{0}greetdel 30`</value>
@ -184,7 +184,7 @@
<value>greetmsg</value> <value>greetmsg</value>
</data> </data>
<data name="greetmsg_desc" xml:space="preserve"> <data name="greetmsg_desc" xml:space="preserve">
<value>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 &lt;http://nadekobot.xyz/embedbuilder/&gt; instead of a regular text, if you want the message to be embedded.</value> <value>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 &lt;http://nadekobot.xyz/embedbuilder/&gt; instead of a regular text, if you want the message to be embedded.</value>
</data> </data>
<data name="greetmsg_usage" xml:space="preserve"> <data name="greetmsg_usage" xml:space="preserve">
<value>`{0}greetmsg Welcome, %user%.`</value> <value>`{0}greetmsg Welcome, %user%.`</value>
@ -202,7 +202,7 @@
<value>byemsg</value> <value>byemsg</value>
</data> </data>
<data name="byemsg_desc" xml:space="preserve"> <data name="byemsg_desc" xml:space="preserve">
<value>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 &lt;http://nadekobot.xyz/embedbuilder/&gt; instead of a regular text, if you want the message to be embedded.</value> <value>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 &lt;http://nadekobot.xyz/embedbuilder/&gt; instead of a regular text, if you want the message to be embedded.</value>
</data> </data>
<data name="byemsg_usage" xml:space="preserve"> <data name="byemsg_usage" xml:space="preserve">
<value>`{0}byemsg %user% has left.`</value> <value>`{0}byemsg %user% has left.`</value>
@ -211,7 +211,7 @@
<value>byedel</value> <value>byedel</value>
</data> </data>
<data name="byedel_desc" xml:space="preserve"> <data name="byedel_desc" xml:space="preserve">
<value>Sets the time it takes (in seconds) for bye messages to be auto-deleted. Set 0 to disable automatic deletion.</value> <value>Sets the time it takes (in seconds) for bye messages to be auto-deleted. Set it to `0` to disable automatic deletion.</value>
</data> </data>
<data name="byedel_usage" xml:space="preserve"> <data name="byedel_usage" xml:space="preserve">
<value>`{0}byedel 0` or `{0}byedel 30`</value> <value>`{0}byedel 0` or `{0}byedel 30`</value>
@ -238,7 +238,7 @@
<value>logignore</value> <value>logignore</value>
</data> </data>
<data name="logignore_desc" xml:space="preserve"> <data name="logignore_desc" xml:space="preserve">
<value>Toggles whether the .logserver command ignores this channel. Useful if you have hidden admin channel and public log channel.</value> <value>Toggles whether the `.logserver` command ignores this channel. Useful if you have hidden admin channel and public log channel.</value>
</data> </data>
<data name="logignore_usage" xml:space="preserve"> <data name="logignore_usage" xml:space="preserve">
<value>`{0}logignore`</value> <value>`{0}logignore`</value>
@ -274,7 +274,7 @@
<value>repeat</value> <value>repeat</value>
</data> </data>
<data name="repeat_desc" xml:space="preserve"> <data name="repeat_desc" xml:space="preserve">
<value>Repeat a message every X minutes in the current channel. You can have up to 5 repeating messages on the server in total.</value> <value>Repeat a message every `X` minutes in the current channel. You can have up to 5 repeating messages on the server in total.</value>
</data> </data>
<data name="repeat_usage" xml:space="preserve"> <data name="repeat_usage" xml:space="preserve">
<value>`{0}repeat 5 Hello there`</value> <value>`{0}repeat 5 Hello there`</value>
@ -292,7 +292,7 @@
<value>addplaying adpl</value> <value>addplaying adpl</value>
</data> </data>
<data name="addplaying_desc" xml:space="preserve"> <data name="addplaying_desc" xml:space="preserve">
<value>Adds a specified string to the list of playing strings to rotate. Supported placeholders: %servers%, %users%, %playing%, %queued%, %time%,%shardid%,%shardcount%, %shardguilds%</value> <value>Adds a specified string to the list of playing strings to rotate. Supported placeholders: `%servers%`, `%users%`, `%playing%`, `%queued%`, `%time%`, `%shardid%`, `%shardcount%`, `%shardguilds%`.</value>
</data> </data>
<data name="addplaying_usage" xml:space="preserve"> <data name="addplaying_usage" xml:space="preserve">
<value>`{0}adpl`</value> <value>`{0}adpl`</value>
@ -364,7 +364,7 @@
<value>lcsc</value> <value>lcsc</value>
</data> </data>
<data name="lcsc_desc" xml:space="preserve"> <data name="lcsc_desc" xml:space="preserve">
<value>Leaves Cross server channel instance from this channel.</value> <value>Leaves a cross server channel instance from this channel.</value>
</data> </data>
<data name="lcsc_usage" xml:space="preserve"> <data name="lcsc_usage" xml:space="preserve">
<value>`{0}lcsc`</value> <value>`{0}lcsc`</value>
@ -427,7 +427,7 @@
<value>addcustreact acr</value> <value>addcustreact acr</value>
</data> </data>
<data name="addcustreact_desc" xml:space="preserve"> <data name="addcustreact_desc" xml:space="preserve">
<value>Add a custom reaction with a trigger and a response. Running this command in server requires Administration permission. Running this command in DM is Bot Owner only and adds a new global custom reaction. Guide here: &lt;http://nadekobot.readthedocs.io/en/latest/Custom%20Reactions/&gt;</value> <value>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: &lt;http://nadekobot.readthedocs.io/en/latest/Custom%20Reactions/&gt;</value>
</data> </data>
<data name="addcustreact_usage" xml:space="preserve"> <data name="addcustreact_usage" xml:space="preserve">
<value>`{0}acr "hello" Hi there %user%`</value> <value>`{0}acr "hello" Hi there %user%`</value>
@ -463,7 +463,7 @@
<value>delcustreact dcr</value> <value>delcustreact dcr</value>
</data> </data>
<data name="delcustreact_desc" xml:space="preserve"> <data name="delcustreact_desc" xml:space="preserve">
<value>Deletes a custom reaction on a specific index. If ran in DM, it is bot owner only and deletes a global custom reaction. If ran in a server, it requires Administration priviledges and removes server custom reaction.</value> <value>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.</value>
</data> </data>
<data name="delcustreact_usage" xml:space="preserve"> <data name="delcustreact_usage" xml:space="preserve">
<value>`{0}dcr 5`</value> <value>`{0}dcr 5`</value>
@ -481,7 +481,7 @@
<value>leave</value> <value>leave</value>
</data> </data>
<data name="leave_desc" xml:space="preserve"> <data name="leave_desc" xml:space="preserve">
<value>Makes Nadeko leave the server. Either name or id required.</value> <value>Makes Nadeko leave the server. Either server name or server ID is required.</value>
</data> </data>
<data name="leave_usage" xml:space="preserve"> <data name="leave_usage" xml:space="preserve">
<value>`{0}leave 123123123331`</value> <value>`{0}leave 123123123331`</value>
@ -490,7 +490,7 @@
<value>delmsgoncmd</value> <value>delmsgoncmd</value>
</data> </data>
<data name="delmsgoncmd_desc" xml:space="preserve"> <data name="delmsgoncmd_desc" xml:space="preserve">
<value>Toggles the automatic deletion of user's successful command message to prevent chat flood.</value> <value>Toggles the automatic deletion of the user's successful command message to prevent chat flood.</value>
</data> </data>
<data name="delmsgoncmd_usage" xml:space="preserve"> <data name="delmsgoncmd_usage" xml:space="preserve">
<value>`{0}delmsgoncmd`</value> <value>`{0}delmsgoncmd`</value>
@ -526,7 +526,7 @@
<value>renamerole renr</value> <value>renamerole renr</value>
</data> </data>
<data name="renamerole_desc" xml:space="preserve"> <data name="renamerole_desc" xml:space="preserve">
<value>Renames a role. Roles you are renaming must be lower than bot's highest role.</value> <value>Renames a role. The role you are renaming must be lower than bot's highest role.</value>
</data> </data>
<data name="renamerole_usage" xml:space="preserve"> <data name="renamerole_usage" xml:space="preserve">
<value>`{0}renr "First role" SecondRole`</value> <value>`{0}renr "First role" SecondRole`</value>
@ -589,10 +589,10 @@
<value>mute</value> <value>mute</value>
</data> </data>
<data name="mute_desc" xml:space="preserve"> <data name="mute_desc" xml:space="preserve">
<value>Mutes a mentioned user both from speaking and chatting.</value> <value>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.</value>
</data> </data>
<data name="mute_usage" xml:space="preserve"> <data name="mute_usage" xml:space="preserve">
<value>`{0}mute @Someone`</value> <value>`{0}mute @Someone` or `{0}mute 30 @Someone`</value>
</data> </data>
<data name="voiceunmute_cmd" xml:space="preserve"> <data name="voiceunmute_cmd" xml:space="preserve">
<value>voiceunmute</value> <value>voiceunmute</value>
@ -679,7 +679,7 @@
<value>prune clr</value> <value>prune clr</value>
</data> </data>
<data name="prune_desc" xml:space="preserve"> <data name="prune_desc" xml:space="preserve">
<value>`{0}prune` removes all nadeko's messages in the last 100 messages.`{0}prune X` removes last X messages from the channel (up to 100)`{0}prune @Someone` removes all Someone's messages in the last 100 messages.`{0}prune @Someone X` removes last X 'Someone's' messages in the channel.</value> <value>`{0}prune` removes all Nadeko's messages in the last 100 messages. `{0}prune X` removes last `X` number of messages from the channel (up to 100). `{0}prune @Someone` removes all Someone's messages in the last 100 messages. `{0}prune @Someone X` removes last `X` number of 'Someone's' messages in the channel.</value>
</data> </data>
<data name="prune_usage" xml:space="preserve"> <data name="prune_usage" xml:space="preserve">
<value>`{0}prune` or `{0}prune 5` or `{0}prune @Someone` or `{0}prune @Someone X`</value> <value>`{0}prune` or `{0}prune 5` or `{0}prune @Someone` or `{0}prune @Someone X`</value>
@ -724,7 +724,7 @@
<value>send</value> <value>send</value>
</data> </data>
<data name="send_desc" xml:space="preserve"> <data name="send_desc" xml:space="preserve">
<value>Sends a message to someone on a different server through the bot. Separate server and channel/user ids with `|` and prepend channel id with `c:` and user id with `u:`.</value> <value>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:`.</value>
</data> </data>
<data name="send_usage" xml:space="preserve"> <data name="send_usage" xml:space="preserve">
<value>`{0}send serverid|c:channelid message` or `{0}send serverid|u:userid message`</value> <value>`{0}send serverid|c:channelid message` or `{0}send serverid|u:userid message`</value>
@ -733,7 +733,7 @@
<value>mentionrole menro</value> <value>mentionrole menro</value>
</data> </data>
<data name="mentionrole_desc" xml:space="preserve"> <data name="mentionrole_desc" xml:space="preserve">
<value>Mentions every person from the provided role or roles (separated by a ',') on this server. Requires you to have mention everyone permission.</value> <value>Mentions every person from the provided role or roles (separated by a ',') on this server. Requires you to have the mention everyone permission.</value>
</data> </data>
<data name="mentionrole_usage" xml:space="preserve"> <data name="mentionrole_usage" xml:space="preserve">
<value>`{0}menro RoleName`</value> <value>`{0}menro RoleName`</value>
@ -751,7 +751,7 @@
<value>donators</value> <value>donators</value>
</data> </data>
<data name="donators_desc" xml:space="preserve"> <data name="donators_desc" xml:space="preserve">
<value>List of lovely people who donated to keep this project alive.</value> <value>List of the lovely people who donated to keep this project alive.</value>
</data> </data>
<data name="donators_usage" xml:space="preserve"> <data name="donators_usage" xml:space="preserve">
<value>`{0}donators`</value> <value>`{0}donators`</value>
@ -769,7 +769,7 @@
<value>announce</value> <value>announce</value>
</data> </data>
<data name="announce_desc" xml:space="preserve"> <data name="announce_desc" xml:space="preserve">
<value>Sends a message to all servers' general channel bot is connected to.</value> <value>Sends a message to all servers' default channel that bot is connected to.</value>
</data> </data>
<data name="announce_usage" xml:space="preserve"> <data name="announce_usage" xml:space="preserve">
<value>`{0}announce Useless spam`</value> <value>`{0}announce Useless spam`</value>
@ -787,7 +787,7 @@
<value>remind</value> <value>remind</value>
</data> </data>
<data name="remind_desc" xml:space="preserve"> <data name="remind_desc" xml:space="preserve">
<value>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&gt;w&gt;d&gt;h&gt;m) example: 1w5d3h10m. Third argument is a (multiword)message.</value> <value>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&gt;w&gt;d&gt;h&gt;m) example: 1w5d3h10m. Third argument is a (multiword) message.</value>
</data> </data>
<data name="remind_usage" xml:space="preserve"> <data name="remind_usage" xml:space="preserve">
<value>`{0}remind me 1d5h Do something` or `{0}remind #general 1m Start now!`</value> <value>`{0}remind me 1d5h Do something` or `{0}remind #general 1m Start now!`</value>
@ -796,7 +796,7 @@
<value>remindtemplate</value> <value>remindtemplate</value>
</data> </data>
<data name="remindtemplate_desc" xml:space="preserve"> <data name="remindtemplate_desc" xml:space="preserve">
<value>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.</value> <value>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.</value>
</data> </data>
<data name="remindtemplate_usage" xml:space="preserve"> <data name="remindtemplate_usage" xml:space="preserve">
<value>`{0}remindtemplate %user%, do %message%!`</value> <value>`{0}remindtemplate %user%, do %message%!`</value>
@ -841,10 +841,10 @@
<value>inrole</value> <value>inrole</value>
</data> </data>
<data name="inrole_desc" xml:space="preserve"> <data name="inrole_desc" xml:space="preserve">
<value>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.</value> <value>Lists every person from the specified role on this server. You can use role ID, role name.</value>
</data> </data>
<data name="inrole_usage" xml:space="preserve"> <data name="inrole_usage" xml:space="preserve">
<value>`{0}inrole Role` or `{0}inrole Role1 "Role 2" @role3`</value> <value>`{0}inrole Some Role`</value>
</data> </data>
<data name="checkmyperms_cmd" xml:space="preserve"> <data name="checkmyperms_cmd" xml:space="preserve">
<value>checkmyperms</value> <value>checkmyperms</value>
@ -895,7 +895,7 @@
<value>roles</value> <value>roles</value>
</data> </data>
<data name="roles_desc" xml:space="preserve"> <data name="roles_desc" xml:space="preserve">
<value>List roles on this server or a roles of a specific user if specified. Paginated. 20 roles per page.</value> <value>List roles on this server or a roles of a specific user if specified. Paginated, 20 roles per page.</value>
</data> </data>
<data name="roles_usage" xml:space="preserve"> <data name="roles_usage" xml:space="preserve">
<value>`{0}roles 2` or `{0}roles @Someone`</value> <value>`{0}roles 2` or `{0}roles @Someone`</value>
@ -913,7 +913,7 @@
<value>chnlfilterinv cfi</value> <value>chnlfilterinv cfi</value>
</data> </data>
<data name="chnlfilterinv_desc" xml:space="preserve"> <data name="chnlfilterinv_desc" xml:space="preserve">
<value>Toggles automatic deleting of invites posted in the channel. Does not negate the {0}srvrfilterinv enabled setting. Does not affect Bot Owner.</value> <value>Toggles automatic deletion of invites posted in the channel. Does not negate the `{0}srvrfilterinv` enabled setting. Does not affect the Bot Owner.</value>
</data> </data>
<data name="chnlfilterinv_usage" xml:space="preserve"> <data name="chnlfilterinv_usage" xml:space="preserve">
<value>`{0}cfi`</value> <value>`{0}cfi`</value>
@ -922,7 +922,7 @@
<value>srvrfilterinv sfi</value> <value>srvrfilterinv sfi</value>
</data> </data>
<data name="srvrfilterinv_desc" xml:space="preserve"> <data name="srvrfilterinv_desc" xml:space="preserve">
<value>Toggles automatic deleting of invites posted in the server. Does not affect Bot Owner.</value> <value>Toggles automatic deletion of invites posted in the server. Does not affect the Bot Owner.</value>
</data> </data>
<data name="srvrfilterinv_usage" xml:space="preserve"> <data name="srvrfilterinv_usage" xml:space="preserve">
<value>`{0}sfi`</value> <value>`{0}sfi`</value>
@ -931,7 +931,7 @@
<value>chnlfilterwords cfw</value> <value>chnlfilterwords cfw</value>
</data> </data>
<data name="chnlfilterwords_desc" xml:space="preserve"> <data name="chnlfilterwords_desc" xml:space="preserve">
<value>Toggles automatic deleting of messages containing banned words on the channel. Does not negate the {0}srvrfilterwords enabled setting. Does not affect bot owner.</value> <value>Toggles automatic deletion of messages containing filtered words on the channel. Does not negate the `{0}srvrfilterwords` enabled setting. Does not affect the Bot Owner.</value>
</data> </data>
<data name="chnlfilterwords_usage" xml:space="preserve"> <data name="chnlfilterwords_usage" xml:space="preserve">
<value>`{0}cfw`</value> <value>`{0}cfw`</value>
@ -958,7 +958,7 @@
<value>srvrfilterwords sfw</value> <value>srvrfilterwords sfw</value>
</data> </data>
<data name="srvrfilterwords_desc" xml:space="preserve"> <data name="srvrfilterwords_desc" xml:space="preserve">
<value>Toggles automatic deleting of messages containing forbidden words on the server. Does not affect Bot Owner.</value> <value>Toggles automatic deletion of messages containing filtered words on the server. Does not affect the Bot Owner.</value>
</data> </data>
<data name="srvrfilterwords_usage" xml:space="preserve"> <data name="srvrfilterwords_usage" xml:space="preserve">
<value>`{0}sfw`</value> <value>`{0}sfw`</value>
@ -967,7 +967,7 @@
<value>permrole pr</value> <value>permrole pr</value>
</data> </data>
<data name="permrole_desc" xml:space="preserve"> <data name="permrole_desc" xml:space="preserve">
<value>Sets a role which can change permissions. Or supply no parameters to find out the current one. Default one is 'Nadeko'.</value> <value>Sets a role which can change permissions. Supply no parameters to see the current one. Default is 'Nadeko'.</value>
</data> </data>
<data name="permrole_usage" xml:space="preserve"> <data name="permrole_usage" xml:space="preserve">
<value>`{0}pr role`</value> <value>`{0}pr role`</value>
@ -1084,7 +1084,7 @@
<value>ubl</value> <value>ubl</value>
</data> </data>
<data name="userblacklist_desc" xml:space="preserve"> <data name="userblacklist_desc" xml:space="preserve">
<value>Either [add]s or [rem]oves a user specified by a mention or ID from a blacklist.</value> <value>Either [add]s or [rem]oves a user specified by a Mention or an ID from a blacklist.</value>
</data> </data>
<data name="userblacklist_usage" xml:space="preserve"> <data name="userblacklist_usage" xml:space="preserve">
<value>`{0}ubl add @SomeUser` or `{0}ubl rem 12312312313`</value> <value>`{0}ubl add @SomeUser` or `{0}ubl rem 12312312313`</value>
@ -1102,7 +1102,7 @@
<value>sbl</value> <value>sbl</value>
</data> </data>
<data name="serverblacklist_desc" xml:space="preserve"> <data name="serverblacklist_desc" xml:space="preserve">
<value>Either [add]s or [rem]oves a server specified by a Name or ID from a blacklist.</value> <value>Either [add]s or [rem]oves a server specified by a Name or an ID from a blacklist.</value>
</data> </data>
<data name="serverblacklist_usage" xml:space="preserve"> <data name="serverblacklist_usage" xml:space="preserve">
<value>`{0}sbl add 12312321312` or `{0}sbl rem SomeTrashServer`</value> <value>`{0}sbl add 12312321312` or `{0}sbl rem SomeTrashServer`</value>
@ -1111,7 +1111,7 @@
<value>cmdcooldown cmdcd</value> <value>cmdcooldown cmdcd</value>
</data> </data>
<data name="cmdcooldown_desc" xml:space="preserve"> <data name="cmdcooldown_desc" xml:space="preserve">
<value>Sets a cooldown per user for a command. Set to 0 to remove the cooldown.</value> <value>Sets a cooldown per user for a command. Set it to 0 to remove the cooldown.</value>
</data> </data>
<data name="cmdcooldown_usage" xml:space="preserve"> <data name="cmdcooldown_usage" xml:space="preserve">
<value>`{0}cmdcd "some cmd" 5`</value> <value>`{0}cmdcd "some cmd" 5`</value>
@ -1156,10 +1156,10 @@
<value>deletequote delq</value> <value>deletequote delq</value>
</data> </data>
<data name="deletequote_desc" xml:space="preserve"> <data name="deletequote_desc" xml:space="preserve">
<value>Deletes a random quote with the specified keyword. You have to either be server Administrator or the creator of the quote to delete it.</value> <value>Deletes a quote with the specified ID. You have to be either server Administrator or the creator of the quote to delete it.</value>
</data> </data>
<data name="deletequote_usage" xml:space="preserve"> <data name="deletequote_usage" xml:space="preserve">
<value>`{0}delq abc`</value> <value>`{0}delq 123456`</value>
</data> </data>
<data name="draw_cmd" xml:space="preserve"> <data name="draw_cmd" xml:space="preserve">
<value>draw</value> <value>draw</value>
@ -1201,7 +1201,7 @@
<value>roll</value> <value>roll</value>
</data> </data>
<data name="roll_desc" xml:space="preserve"> <data name="roll_desc" xml:space="preserve">
<value>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.</value> <value>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.</value>
</data> </data>
<data name="roll_usage" xml:space="preserve"> <data name="roll_usage" xml:space="preserve">
<value>`{0}roll` or `{0}roll 7` or `{0}roll 3d5` or `{0}roll 5dF`</value> <value>`{0}roll` or `{0}roll 7` or `{0}roll 3d5` or `{0}roll 5dF`</value>
@ -1210,7 +1210,7 @@
<value>rolluo</value> <value>rolluo</value>
</data> </data>
<data name="rolluo_desc" xml:space="preserve"> <data name="rolluo_desc" xml:space="preserve">
<value>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.</value> <value>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`.</value>
</data> </data>
<data name="rolluo_usage" xml:space="preserve"> <data name="rolluo_usage" xml:space="preserve">
<value>`{0}rolluo` or `{0}rolluo 7` or `{0}rolluo 3d5`</value> <value>`{0}rolluo` or `{0}rolluo 7` or `{0}rolluo 3d5`</value>
@ -1291,7 +1291,7 @@
<value>leaderboard lb</value> <value>leaderboard lb</value>
</data> </data>
<data name="leaderboard_desc" xml:space="preserve"> <data name="leaderboard_desc" xml:space="preserve">
<value>Displays bot currency leaderboard.</value> <value>Displays the bot's currency leaderboard.</value>
</data> </data>
<data name="leaderboard_usage" xml:space="preserve"> <data name="leaderboard_usage" xml:space="preserve">
<value>`{0}lb`</value> <value>`{0}lb`</value>
@ -1300,7 +1300,7 @@
<value>trivia t</value> <value>trivia t</value>
</data> </data>
<data name="trivia_desc" xml:space="preserve"> <data name="trivia_desc" xml:space="preserve">
<value>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.</value> <value>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.</value>
</data> </data>
<data name="trivia_usage" xml:space="preserve"> <data name="trivia_usage" xml:space="preserve">
<value>`{0}t` or `{0}t 5 nohint`</value> <value>`{0}t` or `{0}t 5 nohint`</value>
@ -1426,7 +1426,7 @@
<value>rps</value> <value>rps</value>
</data> </data>
<data name="rps_desc" xml:space="preserve"> <data name="rps_desc" xml:space="preserve">
<value>Play a game of rocket paperclip scissors with Nadeko.</value> <value>Play a game of Rocket-Paperclip-Scissors with Nadeko.</value>
</data> </data>
<data name="rps_usage" xml:space="preserve"> <data name="rps_usage" xml:space="preserve">
<value>`{0}rps scissors`</value> <value>`{0}rps scissors`</value>
@ -1507,7 +1507,7 @@
<value>nowplaying np</value> <value>nowplaying np</value>
</data> </data>
<data name="nowplaying_desc" xml:space="preserve"> <data name="nowplaying_desc" xml:space="preserve">
<value>Shows the song currently playing.</value> <value>Shows the song that the bot is currently playing.</value>
</data> </data>
<data name="nowplaying_usage" xml:space="preserve"> <data name="nowplaying_usage" xml:space="preserve">
<value>`{0}np`</value> <value>`{0}np`</value>
@ -1516,7 +1516,7 @@
<value>volume vol</value> <value>volume vol</value>
</data> </data>
<data name="volume_desc" xml:space="preserve"> <data name="volume_desc" xml:space="preserve">
<value>Sets the music volume 0-100%</value> <value>Sets the music playback volume (0-100%)</value>
</data> </data>
<data name="volume_usage" xml:space="preserve"> <data name="volume_usage" xml:space="preserve">
<value>`{0}vol 50`</value> <value>`{0}vol 50`</value>
@ -1534,7 +1534,7 @@
<value>max</value> <value>max</value>
</data> </data>
<data name="max_desc" xml:space="preserve"> <data name="max_desc" xml:space="preserve">
<value>Sets the music volume to 100%.</value> <value>Sets the music playback volume to 100%.</value>
</data> </data>
<data name="max_usage" xml:space="preserve"> <data name="max_usage" xml:space="preserve">
<value>`{0}max`</value> <value>`{0}max`</value>
@ -1543,7 +1543,7 @@
<value>half</value> <value>half</value>
</data> </data>
<data name="half_desc" xml:space="preserve"> <data name="half_desc" xml:space="preserve">
<value>Sets the music volume to 50%.</value> <value>Sets the music playback volume to 50%.</value>
</data> </data>
<data name="half_usage" xml:space="preserve"> <data name="half_usage" xml:space="preserve">
<value>`{0}half`</value> <value>`{0}half`</value>
@ -1561,7 +1561,7 @@
<value>soundcloudpl scpl</value> <value>soundcloudpl scpl</value>
</data> </data>
<data name="soundcloudpl_desc" xml:space="preserve"> <data name="soundcloudpl_desc" xml:space="preserve">
<value>Queue a soundcloud playlist using a link.</value> <value>Queue a Soundcloud playlist using a link.</value>
</data> </data>
<data name="soundcloudpl_usage" xml:space="preserve"> <data name="soundcloudpl_usage" xml:space="preserve">
<value>`{0}scpl soundcloudseturl`</value> <value>`{0}scpl soundcloudseturl`</value>
@ -1660,7 +1660,7 @@
<value>save</value> <value>save</value>
</data> </data>
<data name="save_desc" xml:space="preserve"> <data name="save_desc" xml:space="preserve">
<value>Saves a playlist under a certain name. Name must be no longer than 20 characters and mustn't contain dashes.</value> <value>Saves a playlist under a certain name. Playlist name must be no longer than 20 characters and must not contain dashes.</value>
</data> </data>
<data name="save_usage" xml:space="preserve"> <data name="save_usage" xml:space="preserve">
<value>`{0}save classical1`</value> <value>`{0}save classical1`</value>
@ -1669,7 +1669,7 @@
<value>load</value> <value>load</value>
</data> </data>
<data name="load_desc" xml:space="preserve"> <data name="load_desc" xml:space="preserve">
<value>Loads a saved playlist using it's ID. Use `{0}pls` to list all saved playlists and {0}save to save new ones.</value> <value>Loads a saved playlist using its ID. Use `{0}pls` to list all saved playlists and `{0}save` to save new ones.</value>
</data> </data>
<data name="load_usage" xml:space="preserve"> <data name="load_usage" xml:space="preserve">
<value>`{0}load 5`</value> <value>`{0}load 5`</value>
@ -1678,7 +1678,7 @@
<value>playlists pls</value> <value>playlists pls</value>
</data> </data>
<data name="playlists_desc" xml:space="preserve"> <data name="playlists_desc" xml:space="preserve">
<value>Lists all playlists. Paginated. 20 per page. Default page is 0.</value> <value>Lists all playlists. Paginated, 20 per page. Default page is 0.</value>
</data> </data>
<data name="playlists_usage" xml:space="preserve"> <data name="playlists_usage" xml:space="preserve">
<value>`{0}pls 1`</value> <value>`{0}pls 1`</value>
@ -1687,7 +1687,7 @@
<value>deleteplaylist delpls</value> <value>deleteplaylist delpls</value>
</data> </data>
<data name="deleteplaylist_desc" xml:space="preserve"> <data name="deleteplaylist_desc" xml:space="preserve">
<value>Deletes a saved playlist. Only if you made it or if you are the bot owner.</value> <value>Deletes a saved playlist. Works only if you made it or if you are the bot owner.</value>
</data> </data>
<data name="deleteplaylist_usage" xml:space="preserve"> <data name="deleteplaylist_usage" xml:space="preserve">
<value>`{0}delpls animu-5`</value> <value>`{0}delpls animu-5`</value>
@ -1705,7 +1705,7 @@
<value>autoplay ap</value> <value>autoplay ap</value>
</data> </data>
<data name="autoplay_desc" xml:space="preserve"> <data name="autoplay_desc" xml:space="preserve">
<value>Toggles autoplay - When the song is finished, automatically queue a related youtube song. (Works only for youtube songs and when queue is empty)</value> <value>Toggles autoplay - When the song is finished, automatically queue a related Youtube song. (Works only for Youtube songs and when queue is empty)</value>
</data> </data>
<data name="autoplay_usage" xml:space="preserve"> <data name="autoplay_usage" xml:space="preserve">
<value>`{0}ap`</value> <value>`{0}ap`</value>
@ -1939,7 +1939,7 @@
<value>image img</value> <value>image img</value>
</data> </data>
<data name="image_desc" xml:space="preserve"> <data name="image_desc" xml:space="preserve">
<value>Pulls the first image found using a search parameter. Use {0}rimg for different results.</value> <value>Pulls the first image found using a search parameter. Use `{0}rimg` for different results.</value>
</data> </data>
<data name="image_usage" xml:space="preserve"> <data name="image_usage" xml:space="preserve">
<value>`{0}img cute kitten`</value> <value>`{0}img cute kitten`</value>
@ -1966,7 +1966,7 @@
<value>google g</value> <value>google g</value>
</data> </data>
<data name="google_desc" xml:space="preserve"> <data name="google_desc" xml:space="preserve">
<value>Get a google search link for some terms.</value> <value>Get a Google search link for some terms.</value>
</data> </data>
<data name="google_usage" xml:space="preserve"> <data name="google_usage" xml:space="preserve">
<value>`{0}google query`</value> <value>`{0}google query`</value>
@ -2029,7 +2029,7 @@
<value>chucknorris cn</value> <value>chucknorris cn</value>
</data> </data>
<data name="chucknorris_desc" xml:space="preserve"> <data name="chucknorris_desc" xml:space="preserve">
<value>Shows a random chucknorris joke from &lt;http://tambal.azurewebsites.net/joke/random&gt;</value> <value>Shows a random Chuck Norris joke from &lt;http://tambal.azurewebsites.net/joke/random&gt;</value>
</data> </data>
<data name="chucknorris_usage" xml:space="preserve"> <data name="chucknorris_usage" xml:space="preserve">
<value>`{0}cn`</value> <value>`{0}cn`</value>
@ -2047,7 +2047,7 @@
<value>revav</value> <value>revav</value>
</data> </data>
<data name="revav_desc" xml:space="preserve"> <data name="revav_desc" xml:space="preserve">
<value>Returns a google reverse image search for someone's avatar.</value> <value>Returns a Google reverse image search for someone's avatar.</value>
</data> </data>
<data name="revav_usage" xml:space="preserve"> <data name="revav_usage" xml:space="preserve">
<value>`{0}revav "@SomeGuy"`</value> <value>`{0}revav "@SomeGuy"`</value>
@ -2056,7 +2056,7 @@
<value>revimg</value> <value>revimg</value>
</data> </data>
<data name="revimg_desc" xml:space="preserve"> <data name="revimg_desc" xml:space="preserve">
<value>Returns a google reverse image search for an image from a link.</value> <value>Returns a Google reverse image search for an image from a link.</value>
</data> </data>
<data name="revimg_usage" xml:space="preserve"> <data name="revimg_usage" xml:space="preserve">
<value>`{0}revimg Image link`</value> <value>`{0}revimg Image link`</value>
@ -2212,7 +2212,7 @@
<value>Shows the active war claims by a number. Shows all wars in a short way if no number is specified.</value> <value>Shows the active war claims by a number. Shows all wars in a short way if no number is specified.</value>
</data> </data>
<data name="listwar_usage" xml:space="preserve"> <data name="listwar_usage" xml:space="preserve">
<value>`{0}lw [war_number] or {0}lw`</value> <value>`{0}lw [war_number]` or `{0}lw`</value>
</data> </data>
<data name="claim_cmd" xml:space="preserve"> <data name="claim_cmd" xml:space="preserve">
<value>claim call c</value> <value>claim call c</value>
@ -2296,7 +2296,7 @@
<value>readme guide</value> <value>readme guide</value>
</data> </data>
<data name="calcops_desc" xml:space="preserve"> <data name="calcops_desc" xml:space="preserve">
<value>Shows all available operations in {0}calc command</value> <value>Shows all available operations in the `{0}calc` command</value>
</data> </data>
<data name="calcops_usage" xml:space="preserve"> <data name="calcops_usage" xml:space="preserve">
<value>`{0}calcops`</value> <value>`{0}calcops`</value>
@ -2320,7 +2320,7 @@
<value>`{0}greetdmmsg Welcome to the server, %user%`.</value> <value>`{0}greetdmmsg Welcome to the server, %user%`.</value>
</data> </data>
<data name="greetdmmsg_desc" xml:space="preserve"> <data name="greetdmmsg_desc" xml:space="preserve">
<value>Sets a new join announcement message which will be sent to the user who joined. Type %user% if you want to mention the new member. Using it with no message will show the current DM greet message. You can use embed json from &lt;http://nadekobot.xyz/embedbuilder/&gt; instead of a regular text, if you want the message to be embedded.</value> <value>Sets a new join announcement message which will be sent to the user who joined. Type `%user%` if you want to mention the new member. Using it with no message will show the current DM greet message. You can use embed json from &lt;http://nadekobot.xyz/embedbuilder/&gt; instead of a regular text, if you want the message to be embedded.</value>
</data> </data>
<data name="cash_desc" xml:space="preserve"> <data name="cash_desc" xml:space="preserve">
<value>Check how much currency a person has. (Defaults to yourself)</value> <value>Check how much currency a person has. (Defaults to yourself)</value>
@ -2350,7 +2350,7 @@
<value>allusrmdls aum</value> <value>allusrmdls aum</value>
</data> </data>
<data name="moveperm_desc" xml:space="preserve"> <data name="moveperm_desc" xml:space="preserve">
<value>Moves permission from one position to another in Permissions list.</value> <value>Moves permission from one position to another in the Permissions list.</value>
</data> </data>
<data name="moveperm_usage" xml:space="preserve"> <data name="moveperm_usage" xml:space="preserve">
<value>`{0}mp 2 4`</value> <value>`{0}mp 2 4`</value>
@ -2359,7 +2359,7 @@
<value>moveperm mp</value> <value>moveperm mp</value>
</data> </data>
<data name="removeperm_desc" xml:space="preserve"> <data name="removeperm_desc" xml:space="preserve">
<value>Removes a permission from a given position in Permissions list.</value> <value>Removes a permission from a given position in the Permissions list.</value>
</data> </data>
<data name="removeperm_usage" xml:space="preserve"> <data name="removeperm_usage" xml:space="preserve">
<value>`{0}rp 1`</value> <value>`{0}rp 1`</value>
@ -2416,7 +2416,7 @@
<value>fwtoall</value> <value>fwtoall</value>
</data> </data>
<data name="forwardtoall_desc" xml:space="preserve"> <data name="forwardtoall_desc" xml:space="preserve">
<value>Toggles whether messages will be forwarded to all bot owners or only to the first one specified in the credentials.json</value> <value>Toggles whether messages will be forwarded to all bot owners or only to the first one specified in the credentials.json file</value>
</data> </data>
<data name="forwardtoall_usage" xml:space="preserve"> <data name="forwardtoall_usage" xml:space="preserve">
<value>`{0}fwtoall`</value> <value>`{0}fwtoall`</value>
@ -2425,7 +2425,7 @@
<value>resetperms</value> <value>resetperms</value>
</data> </data>
<data name="resetpermissions_desc" xml:space="preserve"> <data name="resetpermissions_desc" xml:space="preserve">
<value>Resets BOT's permissions module on this server to the default value.</value> <value>Resets the bot's permissions module on this server to the default value.</value>
</data> </data>
<data name="resetpermissions_usage" xml:space="preserve"> <data name="resetpermissions_usage" xml:space="preserve">
<value>`{0}resetperms`</value> <value>`{0}resetperms`</value>
@ -2488,7 +2488,7 @@
<value>adsarm</value> <value>adsarm</value>
</data> </data>
<data name="adsarm_desc" xml:space="preserve"> <data name="adsarm_desc" xml:space="preserve">
<value>Toggles the automatic deletion of confirmations for {0}iam and {0}iamn commands.</value> <value>Toggles the automatic deletion of confirmations for `{0}iam` and `{0}iamn` commands.</value>
</data> </data>
<data name="adsarm_usage" xml:space="preserve"> <data name="adsarm_usage" xml:space="preserve">
<value>`{0}adsarm`</value> <value>`{0}adsarm`</value>
@ -2713,7 +2713,7 @@
<value>heal</value> <value>heal</value>
</data> </data>
<data name="heal_desc" xml:space="preserve"> <data name="heal_desc" xml:space="preserve">
<value>Heals someone. Revives those who fainted. Costs a NadekoFlower</value> <value>Heals someone. Revives those who fainted. Costs a NadekoFlower. </value>
</data> </data>
<data name="heal_usage" xml:space="preserve"> <data name="heal_usage" xml:space="preserve">
<value>`{0}heal @someone`</value> <value>`{0}heal @someone`</value>
@ -2794,7 +2794,7 @@
<value>acrophobia acro</value> <value>acrophobia acro</value>
</data> </data>
<data name="acro_desc" xml:space="preserve"> <data name="acro_desc" xml:space="preserve">
<value>Starts an Acrophobia game. Second argment is optional round length in seconds. (default is 60)</value> <value>Starts an Acrophobia game. Second argument is optional round length in seconds. (default is 60)</value>
</data> </data>
<data name="acro_usage" xml:space="preserve"> <data name="acro_usage" xml:space="preserve">
<value>`{0}acro` or `{0}acro 30`</value> <value>`{0}acro` or `{0}acro 30`</value>
@ -2812,7 +2812,7 @@
<value>log</value> <value>log</value>
</data> </data>
<data name="log_desc" xml:space="preserve"> <data name="log_desc" xml:space="preserve">
<value>Toggles logging event. Disables it if it's active anywhere on the server. Enables if it's not active. Use `{0}logevents` to see a list of all events you can subscribe to.</value> <value>Toggles logging event. Disables it if it is active anywhere on the server. Enables if it isn't active. Use `{0}logevents` to see a list of all events you can subscribe to.</value>
</data> </data>
<data name="log_usage" xml:space="preserve"> <data name="log_usage" xml:space="preserve">
<value>`{0}log userpresence` or `{0}log userbanned`</value> <value>`{0}log userpresence` or `{0}log userbanned`</value>
@ -2821,7 +2821,7 @@
<value>fairplay fp</value> <value>fairplay fp</value>
</data> </data>
<data name="fairplay_desc" xml:space="preserve"> <data name="fairplay_desc" xml:space="preserve">
<value>Toggles fairplay. While enabled, music player will prioritize songs from users who didn't have their song recently played instead of the song's position in the queue.</value> <value>Toggles fairplay. While enabled, the bot will prioritize songs from users who didn't have their song recently played instead of the song's position in the queue.</value>
</data> </data>
<data name="fairplay_usage" xml:space="preserve"> <data name="fairplay_usage" xml:space="preserve">
<value>`{0}fp`</value> <value>`{0}fp`</value>
@ -2938,7 +2938,7 @@
<value>cmdcosts</value> <value>cmdcosts</value>
</data> </data>
<data name="cmdcosts_desc" xml:space="preserve"> <data name="cmdcosts_desc" xml:space="preserve">
<value>Shows a list of command costs. Paginated with 9 command per page.</value> <value>Shows a list of command costs. Paginated with 9 commands per page.</value>
</data> </data>
<data name="cmdcosts_usage" xml:space="preserve"> <data name="cmdcosts_usage" xml:space="preserve">
<value>`{0}cmdcosts` or `{0}cmdcosts 2`</value> <value>`{0}cmdcosts` or `{0}cmdcosts 2`</value>
@ -3037,7 +3037,7 @@
<value>mal</value> <value>mal</value>
</data> </data>
<data name="mal_desc" xml:space="preserve"> <data name="mal_desc" xml:space="preserve">
<value>Shows basic info from myanimelist profile.</value> <value>Shows basic info from a MyAnimeList profile.</value>
</data> </data>
<data name="mal_usage" xml:space="preserve"> <data name="mal_usage" xml:space="preserve">
<value>`{0}mal straysocks`</value> <value>`{0}mal straysocks`</value>
@ -3127,7 +3127,7 @@
<value>languageset langset</value> <value>languageset langset</value>
</data> </data>
<data name="languageset_desc" xml:space="preserve"> <data name="languageset_desc" xml:space="preserve">
<value>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.</value> <value>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.</value>
</data> </data>
<data name="languageset_usage" xml:space="preserve"> <data name="languageset_usage" xml:space="preserve">
<value>`{0}langset de-DE ` or `{0}langset default`</value> <value>`{0}langset de-DE ` or `{0}langset default`</value>
@ -3150,4 +3150,76 @@
<data name="rategirl_usage" xml:space="preserve"> <data name="rategirl_usage" xml:space="preserve">
<value>`{0}rategirl @SomeGurl`</value> <value>`{0}rategirl @SomeGurl`</value>
</data> </data>
<data name="lucky7test_cmd" xml:space="preserve">
<value>lucky7test l7t</value>
</data>
<data name="lucky7test_desc" xml:space="preserve">
<value>Tests the l7 command.</value>
</data>
<data name="lucky7test_usage" xml:space="preserve">
<value>`{0}l7t 10000`</value>
</data>
<data name="lucky7_cmd" xml:space="preserve">
<value>lucky7 l7</value>
</data>
<data name="lucky7_desc" xml:space="preserve">
<value>Bet currency on the game and start rolling 3 sided dice. At any point you can choose to [m]ove (roll again) or [s]tay (get the amount bet times the current multiplier).</value>
</data>
<data name="lucky7_usage" xml:space="preserve">
<value>`{0}l7 10` or `{0}l7 move` or `{0}l7 s`</value>
</data>
<data name="vcrolelist_cmd" xml:space="preserve">
<value>vcrolelist</value>
</data>
<data name="vcrolelist_desc" xml:space="preserve">
<value>Shows a list of currently set voice channel roles.</value>
</data>
<data name="vcrolelist_usage" xml:space="preserve">
<value>`{0}vcrolelist`</value>
</data>
<data name="vcrole_cmd" xml:space="preserve">
<value>vcrole</value>
</data>
<data name="vcrole_desc" xml:space="preserve">
<value>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.</value>
</data>
<data name="vcrole_usage" xml:space="preserve">
<value>`{0}vcrole SomeRole` or `{0}vcrole`</value>
</data>
<data name="crad_cmd" xml:space="preserve">
<value>crad</value>
</data>
<data name="crad_desc" xml:space="preserve">
<value>Toggles whether the message triggering the custom reaction will be automatically deleted.</value>
</data>
<data name="crad_usage" xml:space="preserve">
<value>`{0}crad 59`</value>
</data>
<data name="crdm_cmd" xml:space="preserve">
<value>crdm</value>
</data>
<data name="crdm_desc" xml:space="preserve">
<value>Toggles whether the response message of the custom reaction will be sent as a direct message.</value>
</data>
<data name="crdm_usage" xml:space="preserve">
<value>`{0}crad 44`</value>
</data>
<data name="aliaslist_cmd" xml:space="preserve">
<value>aliaslist cmdmaplist aliases</value>
</data>
<data name="aliaslist_desc" xml:space="preserve">
<value>Shows the list of currently set aliases. Paginated.</value>
</data>
<data name="aliaslist_usage" xml:space="preserve">
<value>`{0}aliaslist` or `{0}aliaslist 3`</value>
</data>
<data name="alias_cmd" xml:space="preserve">
<value>alias cmdmap</value>
</data>
<data name="alias_desc" xml:space="preserve">
<value>Create a custom alias for a certain Nadeko command. Provide no alias to remove the existing one.</value>
</data>
<data name="alias_usage" xml:space="preserve">
<value>`{0}alias allin $bf 100 h` or `{0}alias "linux thingy" &gt;loonix Spyware Windows`</value>
</data>
</root> </root>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -140,6 +140,7 @@
</data> </data>
<data name="clashofclans_claim_expired" xml:space="preserve"> <data name="clashofclans_claim_expired" xml:space="preserve">
<value>O pedido de guerra de @{0} contra {1} expirou.</value> <value>O pedido de guerra de @{0} contra {1} expirou.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="clashofclans_enemy" xml:space="preserve"> <data name="clashofclans_enemy" xml:space="preserve">
<value>Inimigo <value>Inimigo
@ -153,9 +154,11 @@
</data> </data>
<data name="clashofclans_invalid_size" xml:space="preserve"> <data name="clashofclans_invalid_size" xml:space="preserve">
<value>Não é um tamanho de guerra válido.</value> <value>Não é um tamanho de guerra válido.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="clashofclans_list_active_wars" xml:space="preserve"> <data name="clashofclans_list_active_wars" xml:space="preserve">
<value>Lista de guerras ativas</value> <value>Lista de guerras ativas</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="clashofclans_not_claimed" xml:space="preserve"> <data name="clashofclans_not_claimed" xml:space="preserve">
<value>não reivindicado</value> <value>não reivindicado</value>
@ -168,6 +171,7 @@
</data> </data>
<data name="clashofclans_no_active_wars" xml:space="preserve"> <data name="clashofclans_no_active_wars" xml:space="preserve">
<value>Nenhuma guerra ativa.</value> <value>Nenhuma guerra ativa.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="clashofclans_size" xml:space="preserve"> <data name="clashofclans_size" xml:space="preserve">
<value>Tamanho</value> <value>Tamanho</value>
@ -207,6 +211,7 @@
</data> </data>
<data name="customreactions_no_found" xml:space="preserve"> <data name="customreactions_no_found" xml:space="preserve">
<value>Nenhuma reação personalizada encontrada.</value> <value>Nenhuma reação personalizada encontrada.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="customreactions_no_found_id" xml:space="preserve"> <data name="customreactions_no_found_id" xml:space="preserve">
<value>Nenhuma reação personalizada encontrada com este id.</value> <value>Nenhuma reação personalizada encontrada com este id.</value>
@ -279,7 +284,7 @@
<value>Você reviveu a si mesmo com uma {0}</value> <value>Você reviveu a si mesmo com uma {0}</value>
</data> </data>
<data name="pokemon_settype_success" xml:space="preserve"> <data name="pokemon_settype_success" xml:space="preserve">
<value>Seu tipo foi mudado de {0} para {1}</value> <value>Seu tipo foi mudado para {0} por uma {1}</value>
</data> </data>
<data name="pokemon_somewhat_effective" xml:space="preserve"> <data name="pokemon_somewhat_effective" xml:space="preserve">
<value>É mais ou menos efetivo.</value> <value>É mais ou menos efetivo.</value>
@ -469,10 +474,12 @@ Razão: {1}</value>
</data> </data>
<data name="administration_kicked_user" xml:space="preserve"> <data name="administration_kicked_user" xml:space="preserve">
<value>Usuário Kickado</value> <value>Usuário Kickado</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_lang_list" xml:space="preserve"> <data name="administration_lang_list" xml:space="preserve">
<value>Lista de Linguagens <value>Lista de Linguagens
{0}</value> {0}</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_lang_set" xml:space="preserve"> <data name="administration_lang_set" xml:space="preserve">
<value>A região do seu servidor agora é {0} - {1}</value> <value>A região do seu servidor agora é {0} - {1}</value>
@ -530,9 +537,11 @@ Razão: {1}</value>
</data> </data>
<data name="administration_msg_del" xml:space="preserve"> <data name="administration_msg_del" xml:space="preserve">
<value>Mensagem deletada em #{0}</value> <value>Mensagem deletada em #{0}</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_msg_update" xml:space="preserve"> <data name="administration_msg_update" xml:space="preserve">
<value>Mensagem atualizada em #{0}</value> <value>Mensagem atualizada em #{0}</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_muted_pl" xml:space="preserve"> <data name="administration_muted_pl" xml:space="preserve">
<value>Mutados</value> <value>Mutados</value>
@ -553,15 +562,19 @@ Razão: {1}</value>
</data> </data>
<data name="administration_new_msg" xml:space="preserve"> <data name="administration_new_msg" xml:space="preserve">
<value>Nova mensagem</value> <value>Nova mensagem</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_new_nick" xml:space="preserve"> <data name="administration_new_nick" xml:space="preserve">
<value>Novo Apelido</value> <value>Novo Apelido</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_new_topic" xml:space="preserve"> <data name="administration_new_topic" xml:space="preserve">
<value>Novo Tópico</value> <value>Novo Tópico</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_nick_change" xml:space="preserve"> <data name="administration_nick_change" xml:space="preserve">
<value>Apelido Alterado</value> <value>Apelido Alterado</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_no_server" xml:space="preserve"> <data name="administration_no_server" xml:space="preserve">
<value>Não posso encontrar esse servidor</value> <value>Não posso encontrar esse servidor</value>
@ -571,12 +584,15 @@ Razão: {1}</value>
</data> </data>
<data name="administration_old_msg" xml:space="preserve"> <data name="administration_old_msg" xml:space="preserve">
<value>Mensagem Antiga</value> <value>Mensagem Antiga</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_old_nick" xml:space="preserve"> <data name="administration_old_nick" xml:space="preserve">
<value>Apelido Antigo</value> <value>Apelido Antigo</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_old_topic" xml:space="preserve"> <data name="administration_old_topic" xml:space="preserve">
<value>Tópico Antigo</value> <value>Tópico Antigo</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_perms" xml:space="preserve"> <data name="administration_perms" xml:space="preserve">
<value>Erro. Não tenho permissões suficientes.</value> <value>Erro. Não tenho permissões suficientes.</value>
@ -586,6 +602,7 @@ Razão: {1}</value>
</data> </data>
<data name="administration_prot_active" xml:space="preserve"> <data name="administration_prot_active" xml:space="preserve">
<value>Proteções ativadas</value> <value>Proteções ativadas</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_prot_disable" xml:space="preserve"> <data name="administration_prot_disable" xml:space="preserve">
<value>{0} foi **desativado** neste servidor.</value> <value>{0} foi **desativado** neste servidor.</value>
@ -598,6 +615,7 @@ Razão: {1}</value>
</data> </data>
<data name="administration_prot_none" xml:space="preserve"> <data name="administration_prot_none" xml:space="preserve">
<value>Nenhuma proteção ativa.</value> <value>Nenhuma proteção ativa.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_raid_cnt" xml:space="preserve"> <data name="administration_raid_cnt" xml:space="preserve">
<value>O limite de usuários deve ser entre {0} e {1}.</value> <value>O limite de usuários deve ser entre {0} e {1}.</value>
@ -758,9 +776,11 @@ __Canais Ignorados__: {2}</value>
</data> </data>
<data name="administration_text_chan_created" xml:space="preserve"> <data name="administration_text_chan_created" xml:space="preserve">
<value>Canal de Texto Criado</value> <value>Canal de Texto Criado</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_text_chan_destroyed" xml:space="preserve"> <data name="administration_text_chan_destroyed" xml:space="preserve">
<value>Canal de Texto Destruído</value> <value>Canal de Texto Destruído</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_undeafen" xml:space="preserve"> <data name="administration_undeafen" xml:space="preserve">
<value>Desensurdecido com sucesso.</value> <value>Desensurdecido com sucesso.</value>
@ -774,12 +794,14 @@ __Canais Ignorados__: {2}</value>
</data> </data>
<data name="administration_username_changed" xml:space="preserve"> <data name="administration_username_changed" xml:space="preserve">
<value>Nome de usuário alterado</value> <value>Nome de usuário alterado</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_users" xml:space="preserve"> <data name="administration_users" xml:space="preserve">
<value>Usuários</value> <value>Usuários</value>
</data> </data>
<data name="administration_user_banned" xml:space="preserve"> <data name="administration_user_banned" xml:space="preserve">
<value>Usuário Banido</value> <value>Usuário Banido</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_user_chat_mute" xml:space="preserve"> <data name="administration_user_chat_mute" xml:space="preserve">
<value>{0} foi **mutado**</value> <value>{0} foi **mutado**</value>
@ -789,18 +811,22 @@ __Canais Ignorados__: {2}</value>
</data> </data>
<data name="administration_user_joined" xml:space="preserve"> <data name="administration_user_joined" xml:space="preserve">
<value>Usuário juntou-se</value> <value>Usuário juntou-se</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_user_left" xml:space="preserve"> <data name="administration_user_left" xml:space="preserve">
<value>Usuário saiu</value> <value>Usuário saiu</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_user_muted" xml:space="preserve"> <data name="administration_user_muted" xml:space="preserve">
<value>{0} foi **mutado** nos chats de voz e texto.</value> <value>{0} foi **mutado** nos chats de voz e texto.</value>
</data> </data>
<data name="administration_user_role_add" xml:space="preserve"> <data name="administration_user_role_add" xml:space="preserve">
<value>Cargo do usuário adicionado</value> <value>Cargo do usuário adicionado</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_user_role_rem" xml:space="preserve"> <data name="administration_user_role_rem" xml:space="preserve">
<value>Cargo do usuário removido</value> <value>Cargo do usuário removido</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_user_status_change" xml:space="preserve"> <data name="administration_user_status_change" xml:space="preserve">
<value>{0} agora está {1}</value> <value>{0} agora está {1}</value>
@ -825,9 +851,11 @@ __Canais Ignorados__: {2}</value>
</data> </data>
<data name="administration_voice_chan_created" xml:space="preserve"> <data name="administration_voice_chan_created" xml:space="preserve">
<value>Canal de voz criado</value> <value>Canal de voz criado</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_voice_chan_destroyed" xml:space="preserve"> <data name="administration_voice_chan_destroyed" xml:space="preserve">
<value>Canal de voz destruído</value> <value>Canal de voz destruído</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_vt_disabled" xml:space="preserve"> <data name="administration_vt_disabled" xml:space="preserve">
<value>Atributo voz + texto desabilitado.</value> <value>Atributo voz + texto desabilitado.</value>
@ -859,6 +887,7 @@ Motivo: {1}</value>
</data> </data>
<data name="administration_user_unbanned" xml:space="preserve"> <data name="administration_user_unbanned" xml:space="preserve">
<value>Usuário desbanido</value> <value>Usuário desbanido</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_migration_done" xml:space="preserve"> <data name="administration_migration_done" xml:space="preserve">
<value>Migração concluída!</value> <value>Migração concluída!</value>
@ -868,9 +897,11 @@ Motivo: {1}</value>
</data> </data>
<data name="administration_presence_updates" xml:space="preserve"> <data name="administration_presence_updates" xml:space="preserve">
<value>Atualizações de Presença</value> <value>Atualizações de Presença</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_sb_user" xml:space="preserve"> <data name="administration_sb_user" xml:space="preserve">
<value>Usuário Banido Temporariamente</value> <value>Usuário Banido Temporariamente</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="gambling_awarded" xml:space="preserve"> <data name="gambling_awarded" xml:space="preserve">
<value>concedeu {0} para {1}</value> <value>concedeu {0} para {1}</value>
@ -889,7 +920,7 @@ Motivo: {1}</value>
<comment>User flipped tails.</comment> <comment>User flipped tails.</comment>
</data> </data>
<data name="gambling_flip_guess" xml:space="preserve"> <data name="gambling_flip_guess" xml:space="preserve">
<value>Você Adivinhou! Você ganhou {0}</value> <value>Você adivinhou! Você ganhou {0}</value>
</data> </data>
<data name="gambling_flip_invalid" xml:space="preserve"> <data name="gambling_flip_invalid" xml:space="preserve">
<value>O número especificado é inválido. Você pode girar de 1 a {0} moedas.</value> <value>O número especificado é inválido. Você pode girar de 1 a {0} moedas.</value>
@ -913,6 +944,7 @@ Motivo: {1}</value>
</data> </data>
<data name="gambling_heads" xml:space="preserve"> <data name="gambling_heads" xml:space="preserve">
<value>Cara</value> <value>Cara</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="gambling_leaderboard" xml:space="preserve"> <data name="gambling_leaderboard" xml:space="preserve">
<value>Placar de Líderes</value> <value>Placar de Líderes</value>
@ -934,6 +966,7 @@ Motivo: {1}</value>
</data> </data>
<data name="gambling_raffled_user" xml:space="preserve"> <data name="gambling_raffled_user" xml:space="preserve">
<value>Usuário sorteado</value> <value>Usuário sorteado</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="gambling_roll" xml:space="preserve"> <data name="gambling_roll" xml:space="preserve">
<value>Você rolou {0}.</value> <value>Você rolou {0}.</value>
@ -968,6 +1001,7 @@ Dura {1} segundos. Não diga a ninguém. Shhh.</value>
</data> </data>
<data name="gambling_tails" xml:space="preserve"> <data name="gambling_tails" xml:space="preserve">
<value>Coroa</value> <value>Coroa</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="gambling_take" xml:space="preserve"> <data name="gambling_take" xml:space="preserve">
<value>Tomou {0} de {1} com sucesso</value> <value>Tomou {0} de {1} com sucesso</value>
@ -980,6 +1014,7 @@ Dura {1} segundos. Não diga a ninguém. Shhh.</value>
</data> </data>
<data name="help_bot_owner_only" xml:space="preserve"> <data name="help_bot_owner_only" xml:space="preserve">
<value>Proprietário do bot apenas.</value> <value>Proprietário do bot apenas.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="help_channel_permission" xml:space="preserve"> <data name="help_channel_permission" xml:space="preserve">
<value>Requer a permissão {0} do canal.</value> <value>Requer a permissão {0} do canal.</value>
@ -989,9 +1024,11 @@ Dura {1} segundos. Não diga a ninguém. Shhh.</value>
</data> </data>
<data name="help_cmd_and_alias" xml:space="preserve"> <data name="help_cmd_and_alias" xml:space="preserve">
<value>Comandos e abreviações</value> <value>Comandos e abreviações</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="help_commandlist_regen" xml:space="preserve"> <data name="help_commandlist_regen" xml:space="preserve">
<value>Lista de Comandos Regenerada.</value> <value>Lista de Comandos Regenerada.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="help_commands_instr" xml:space="preserve"> <data name="help_commands_instr" xml:space="preserve">
<value>Digite `{0}h NomeDoComando` para ver a ajuda para o comando especificado. Ex: `{0}h &gt;8ball`</value> <value>Digite `{0}h NomeDoComando` para ver a ajuda para o comando especificado. Ex: `{0}h &gt;8ball`</value>
@ -1012,12 +1049,15 @@ Não esqueça de deixar seu nome ou id do discord na mensagem.
<data name="help_guide" xml:space="preserve"> <data name="help_guide" xml:space="preserve">
<value>**Lista de Comandos**. &lt;{0}&gt; <value>**Lista de Comandos**. &lt;{0}&gt;
**Guias de hosteamento e documentos podem ser encontrados aqui**. &lt;{1}&gt;</value> **Guias de hosteamento e documentos podem ser encontrados aqui**. &lt;{1}&gt;</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="help_list_of_commands" xml:space="preserve"> <data name="help_list_of_commands" xml:space="preserve">
<value>Lista de Comandos</value> <value>Lista de Comandos</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="help_list_of_modules" xml:space="preserve"> <data name="help_list_of_modules" xml:space="preserve">
<value>Lista de Módulos</value> <value>Lista de Módulos</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="help_modules_footer" xml:space="preserve"> <data name="help_modules_footer" xml:space="preserve">
<value>Digite `{0}cmds NomeDoMódulo` para receber uma lista de comandos deste módulo. Ex: `{0}cmds games`</value> <value>Digite `{0}cmds NomeDoMódulo` para receber uma lista de comandos deste módulo. Ex: `{0}cmds games`</value>
@ -1030,6 +1070,7 @@ Não esqueça de deixar seu nome ou id do discord na mensagem.
</data> </data>
<data name="help_table_of_contents" xml:space="preserve"> <data name="help_table_of_contents" xml:space="preserve">
<value>Tabela de Conteúdo</value> <value>Tabela de Conteúdo</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="help_usage" xml:space="preserve"> <data name="help_usage" xml:space="preserve">
<value>Modo de uso</value> <value>Modo de uso</value>
@ -1043,6 +1084,7 @@ Não esqueça de deixar seu nome ou id do discord na mensagem.
</data> </data>
<data name="gambling_animal_race" xml:space="preserve"> <data name="gambling_animal_race" xml:space="preserve">
<value>Corrida de Animais</value> <value>Corrida de Animais</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="gambling_animal_race_failed" xml:space="preserve"> <data name="gambling_animal_race_failed" xml:space="preserve">
<value>Falha ao iniciar, não houve participantes suficientes.</value> <value>Falha ao iniciar, não houve participantes suficientes.</value>
@ -1093,9 +1135,11 @@ Não esqueça de deixar seu nome ou id do discord na mensagem.
</data> </data>
<data name="gambling_changes_of_heart" xml:space="preserve"> <data name="gambling_changes_of_heart" xml:space="preserve">
<value>Mudanças no Coração</value> <value>Mudanças no Coração</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="gambling_claimed_by" xml:space="preserve"> <data name="gambling_claimed_by" xml:space="preserve">
<value>Reivindicado por</value> <value>Reivindicado por</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="gambling_divorces" xml:space="preserve"> <data name="gambling_divorces" xml:space="preserve">
<value>Divórcios</value> <value>Divórcios</value>
@ -1215,6 +1259,7 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="games_submissions_closed" xml:space="preserve"> <data name="games_submissions_closed" xml:space="preserve">
<value>Submissões Encerradas</value> <value>Submissões Encerradas</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="gambling_animal_race_already_started" xml:space="preserve"> <data name="gambling_animal_race_already_started" xml:space="preserve">
<value>A Corrida de Animais já está em andamento</value> <value>A Corrida de Animais já está em andamento</value>
@ -1239,16 +1284,19 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="games_curgen_pl" xml:space="preserve"> <data name="games_curgen_pl" xml:space="preserve">
<value>{0} {1} aleatórios aparecem! Capture-os digitando `{2}pick`</value> <value>{0} {1} aleatórios aparecem! Capture-os digitando `{2}pick`</value>
<comment>plural</comment> <comment>plural
Fuzzy</comment>
</data> </data>
<data name="games_curgen_sn" xml:space="preserve"> <data name="games_curgen_sn" xml:space="preserve">
<value>Um {0} aleatório apareceu! Capture-o digitando `{1}pick`</value> <value>Um {0} aleatório apareceu! Capture-o digitando `{1}pick`</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="games_failed_loading_question" xml:space="preserve"> <data name="games_failed_loading_question" xml:space="preserve">
<value>Falha ao carregar a questão.</value> <value>Falha ao carregar a questão.</value>
</data> </data>
<data name="games_game_started" xml:space="preserve"> <data name="games_game_started" xml:space="preserve">
<value>Jogo Iniciado</value> <value>Jogo Iniciado</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="games_hangman_game_started" xml:space="preserve"> <data name="games_hangman_game_started" xml:space="preserve">
<value>Jogo da Forca iniciado</value> <value>Jogo da Forca iniciado</value>
@ -1317,15 +1365,18 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="games_ttt_has_won" xml:space="preserve"> <data name="games_ttt_has_won" xml:space="preserve">
<value>{0} venceu!</value> <value>{0} venceu!</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="games_ttt_matched_three" xml:space="preserve"> <data name="games_ttt_matched_three" xml:space="preserve">
<value>Combinou três</value> <value>Combinou três</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="games_ttt_no_moves" xml:space="preserve"> <data name="games_ttt_no_moves" xml:space="preserve">
<value>Nenhum movimento restante!</value> <value>Nenhum movimento restante!</value>
</data> </data>
<data name="games_ttt_time_expired" xml:space="preserve"> <data name="games_ttt_time_expired" xml:space="preserve">
<value>Tempo Esgotado!</value> <value>Tempo Esgotado!</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="games_ttt_users_move" xml:space="preserve"> <data name="games_ttt_users_move" xml:space="preserve">
<value>É a vez de {0}</value> <value>É a vez de {0}</value>
@ -1353,6 +1404,7 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="music_finished_song" xml:space="preserve"> <data name="music_finished_song" xml:space="preserve">
<value>Música concluída.</value> <value>Música concluída.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="music_fp_disabled" xml:space="preserve"> <data name="music_fp_disabled" xml:space="preserve">
<value>Fair play desativado.</value> <value>Fair play desativado.</value>
@ -1389,6 +1441,7 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="music_now_playing" xml:space="preserve"> <data name="music_now_playing" xml:space="preserve">
<value>Tocando agora</value> <value>Tocando agora</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="music_no_player" xml:space="preserve"> <data name="music_no_player" xml:space="preserve">
<value>Nenhum player de música ativo.</value> <value>Nenhum player de música ativo.</value>
@ -1401,15 +1454,18 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="music_player_queue" xml:space="preserve"> <data name="music_player_queue" xml:space="preserve">
<value>Fila de Músicas - Página {0}/{1}</value> <value>Fila de Músicas - Página {0}/{1}</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="music_playing_song" xml:space="preserve"> <data name="music_playing_song" xml:space="preserve">
<value>Tocando Musica</value> <value>Tocando Musica</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="music_playlists" xml:space="preserve"> <data name="music_playlists" xml:space="preserve">
<value>`#{0}` - **{1}** by *{2}* ({3} músicas)</value> <value>`#{0}` - **{1}** by *{2}* ({3} músicas)</value>
</data> </data>
<data name="music_playlists_page" xml:space="preserve"> <data name="music_playlists_page" xml:space="preserve">
<value>Página {0} de Playlists Salvas</value> <value>Página {0} de Playlists Salvas</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="music_playlist_deleted" xml:space="preserve"> <data name="music_playlist_deleted" xml:space="preserve">
<value>Playlist deletada.</value> <value>Playlist deletada.</value>
@ -1425,6 +1481,7 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="music_playlist_saved" xml:space="preserve"> <data name="music_playlist_saved" xml:space="preserve">
<value>Playlist Salva</value> <value>Playlist Salva</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="music_play_limit" xml:space="preserve"> <data name="music_play_limit" xml:space="preserve">
<value>Limite de {0}s</value> <value>Limite de {0}s</value>
@ -1434,6 +1491,7 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="music_queued_song" xml:space="preserve"> <data name="music_queued_song" xml:space="preserve">
<value>Músicas em fila</value> <value>Músicas em fila</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="music_queue_cleared" xml:space="preserve"> <data name="music_queue_cleared" xml:space="preserve">
<value>Fila de músicas limpa.</value> <value>Fila de músicas limpa.</value>
@ -1447,12 +1505,15 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="music_repeating_cur_song" xml:space="preserve"> <data name="music_repeating_cur_song" xml:space="preserve">
<value>Repetindo a Música Atual</value> <value>Repetindo a Música Atual</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="music_repeating_playlist" xml:space="preserve"> <data name="music_repeating_playlist" xml:space="preserve">
<value>Repetindo Playlist</value> <value>Repetindo Playlist</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="music_repeating_track" xml:space="preserve"> <data name="music_repeating_track" xml:space="preserve">
<value>Repetindo Faixa</value> <value>Repetindo Faixa</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="music_repeating_track_stopped" xml:space="preserve"> <data name="music_repeating_track_stopped" xml:space="preserve">
<value>A repetição da faixa atual parou.</value> <value>A repetição da faixa atual parou.</value>
@ -1474,9 +1535,11 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="music_songs_shuffled" xml:space="preserve"> <data name="music_songs_shuffled" xml:space="preserve">
<value>Músicas embaralhadas.</value> <value>Músicas embaralhadas.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="music_song_moved" xml:space="preserve"> <data name="music_song_moved" xml:space="preserve">
<value>Música movida</value> <value>Música movida</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="music_time_format" xml:space="preserve"> <data name="music_time_format" xml:space="preserve">
<value>{0}h {1}m {2}s</value> <value>{0}h {1}m {2}s</value>
@ -1495,18 +1558,22 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="permissions_acm_disable" xml:space="preserve"> <data name="permissions_acm_disable" xml:space="preserve">
<value>O uso de TODOS OS MÓDULOS foi desabilitado no canal {0}.</value> <value>O uso de TODOS OS MÓDULOS foi desabilitado no canal {0}.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="permissions_acm_enable" xml:space="preserve"> <data name="permissions_acm_enable" xml:space="preserve">
<value>O uso de TODOS OS MÓDULOS foi habilitado no canal {0}.</value> <value>O uso de TODOS OS MÓDULOS foi habilitado no canal {0}.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="permissions_allowed" xml:space="preserve"> <data name="permissions_allowed" xml:space="preserve">
<value>Permitido</value> <value>Permitido</value>
</data> </data>
<data name="permissions_arm_disable" xml:space="preserve"> <data name="permissions_arm_disable" xml:space="preserve">
<value>O uso de TODOS OS MÓDULOS foi desabilitado para o cargo {0}.</value> <value>O uso de TODOS OS MÓDULOS foi desabilitado para o cargo {0}.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="permissions_arm_enable" xml:space="preserve"> <data name="permissions_arm_enable" xml:space="preserve">
<value>O uso de TODOS OS MÓDULOS foi habilitado para o cargo {0}.</value> <value>O uso de TODOS OS MÓDULOS foi habilitado para o cargo {0}.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="permissions_asm_disable" xml:space="preserve"> <data name="permissions_asm_disable" xml:space="preserve">
<value>O uso de TODOS OS MÓDULOS foi desabilitado neste servidor.</value> <value>O uso de TODOS OS MÓDULOS foi desabilitado neste servidor.</value>
@ -1516,9 +1583,11 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="permissions_aum_disable" xml:space="preserve"> <data name="permissions_aum_disable" xml:space="preserve">
<value>O uso de TODOS OS MÓDULOS foi desabilitado para o usuário {0}.</value> <value>O uso de TODOS OS MÓDULOS foi desabilitado para o usuário {0}.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="permissions_aum_enable" xml:space="preserve"> <data name="permissions_aum_enable" xml:space="preserve">
<value>O uso de TODOS OS MÓDULOS foi habilitado para o usuário {0}.</value> <value>O uso de TODOS OS MÓDULOS foi habilitado para o usuário {0}.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="permissions_blacklisted" xml:space="preserve"> <data name="permissions_blacklisted" xml:space="preserve">
<value>{0} entrou na Lista Negra com o ID {1}</value> <value>{0} entrou na Lista Negra com o ID {1}</value>
@ -1528,18 +1597,22 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="permissions_cmdcd_cleared" xml:space="preserve"> <data name="permissions_cmdcd_cleared" xml:space="preserve">
<value>O comando {0} não possui nenhum cooldown agora e todos os cooldowns existentes foram limpos.</value> <value>O comando {0} não possui nenhum cooldown agora e todos os cooldowns existentes foram limpos.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="permissions_cmdcd_none" xml:space="preserve"> <data name="permissions_cmdcd_none" xml:space="preserve">
<value>Nenhum cooldown de comando definido.</value> <value>Nenhum cooldown de comando definido.</value>
</data> </data>
<data name="permissions_command_costs" xml:space="preserve"> <data name="permissions_command_costs" xml:space="preserve">
<value>Custos de Comando</value> <value>Custos de Comando</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="permissions_cx_disable" xml:space="preserve"> <data name="permissions_cx_disable" xml:space="preserve">
<value>Desabilitado o uso de {0} {1} no canal {2}.</value> <value>Desabilitado o uso de {0} {1} no canal {2}.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="permissions_cx_enable" xml:space="preserve"> <data name="permissions_cx_enable" xml:space="preserve">
<value>Habilitado o uso de {0} {1} no canal {2}.</value> <value>Habilitado o uso de {0} {1} no canal {2}.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="permissions_denied" xml:space="preserve"> <data name="permissions_denied" xml:space="preserve">
<value>Negado</value> <value>Negado</value>
@ -1549,6 +1622,7 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="permissions_filter_word_list" xml:space="preserve"> <data name="permissions_filter_word_list" xml:space="preserve">
<value>Lista de Palavras Filtradas</value> <value>Lista de Palavras Filtradas</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="permissions_filter_word_remove" xml:space="preserve"> <data name="permissions_filter_word_remove" xml:space="preserve">
<value>A palavra {0} foi removida da lista de palavras filtradas.</value> <value>A palavra {0} foi removida da lista de palavras filtradas.</value>
@ -1685,12 +1759,15 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="searches_compet_loses" xml:space="preserve"> <data name="searches_compet_loses" xml:space="preserve">
<value>Derrotas Competitivas</value> <value>Derrotas Competitivas</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="searches_compet_played" xml:space="preserve"> <data name="searches_compet_played" xml:space="preserve">
<value>Partidas Competitivas jogadas</value> <value>Partidas Competitivas jogadas</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="searches_compet_rank" xml:space="preserve"> <data name="searches_compet_rank" xml:space="preserve">
<value>Rank Competitivo</value> <value>Rank Competitivo</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="searches_compet_wins" xml:space="preserve"> <data name="searches_compet_wins" xml:space="preserve">
<value>Vitórias Competitivas</value> <value>Vitórias Competitivas</value>
@ -1744,7 +1821,8 @@ O novo valor de {0} é {1}!</value>
<value>Humidade</value> <value>Humidade</value>
</data> </data>
<data name="searches_image_search_for" xml:space="preserve"> <data name="searches_image_search_for" xml:space="preserve">
<value>Busca de Imagens para:</value> <value>Busca de imagem para:</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="searches_imdb_fail" xml:space="preserve"> <data name="searches_imdb_fail" xml:space="preserve">
<value>Falha ao encontrar este filme.</value> <value>Falha ao encontrar este filme.</value>
@ -1788,9 +1866,11 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="searches_on_hold" xml:space="preserve"> <data name="searches_on_hold" xml:space="preserve">
<value>Em espera</value> <value>Em espera</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="searches_original_url" xml:space="preserve"> <data name="searches_original_url" xml:space="preserve">
<value>Url Original</value> <value>Url Original</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="searches_osu_api_key" xml:space="preserve"> <data name="searches_osu_api_key" xml:space="preserve">
<value>Requer uma API key de osu!</value> <value>Requer uma API key de osu!</value>
@ -1818,15 +1898,18 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="searches_profile_link" xml:space="preserve"> <data name="searches_profile_link" xml:space="preserve">
<value>Link do Perfil:</value> <value>Link do Perfil:</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="searches_quality" xml:space="preserve"> <data name="searches_quality" xml:space="preserve">
<value>Qualidade:</value> <value>Qualidade:</value>
</data> </data>
<data name="searches_quick_playtime" xml:space="preserve"> <data name="searches_quick_playtime" xml:space="preserve">
<value>Tempo em Partida Rápida</value> <value>Tempo em Partida Rápida</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="searches_quick_wins" xml:space="preserve"> <data name="searches_quick_wins" xml:space="preserve">
<value>Vitórias em Partida Rápida</value> <value>Vitórias em Partida Rápida</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="searches_rating" xml:space="preserve"> <data name="searches_rating" xml:space="preserve">
<value>Avaliação</value> <value>Avaliação</value>
@ -1836,12 +1919,14 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="searches_search_for" xml:space="preserve"> <data name="searches_search_for" xml:space="preserve">
<value>Busca Por:</value> <value>Busca Por:</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="searches_shorten_fail" xml:space="preserve"> <data name="searches_shorten_fail" xml:space="preserve">
<value>Falha ao encurtar esse url.</value> <value>Falha ao encurtar esse url.</value>
</data> </data>
<data name="searches_short_url" xml:space="preserve"> <data name="searches_short_url" xml:space="preserve">
<value>Url Curta</value> <value>Url Curta</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="searches_something_went_wrong" xml:space="preserve"> <data name="searches_something_went_wrong" xml:space="preserve">
<value>Alguma coisa deu errado.</value> <value>Alguma coisa deu errado.</value>
@ -1854,6 +1939,7 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="searches_store_url" xml:space="preserve"> <data name="searches_store_url" xml:space="preserve">
<value>Url da Loja</value> <value>Url da Loja</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="searches_streamer_offline" xml:space="preserve"> <data name="searches_streamer_offline" xml:space="preserve">
<value>Streamer {0} está offline.</value> <value>Streamer {0} está offline.</value>
@ -1923,6 +2009,7 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="searches_wind_speed" xml:space="preserve"> <data name="searches_wind_speed" xml:space="preserve">
<value>Velocidade do Vento</value> <value>Velocidade do Vento</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="searches_x_most_banned_champs" xml:space="preserve"> <data name="searches_x_most_banned_champs" xml:space="preserve">
<value>Os {0} campeões mais banidos</value> <value>Os {0} campeões mais banidos</value>
@ -1940,6 +2027,7 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="utility_activity_page" xml:space="preserve"> <data name="utility_activity_page" xml:space="preserve">
<value>Página de Atividade #{0}</value> <value>Página de Atividade #{0}</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="utility_activity_users_total" xml:space="preserve"> <data name="utility_activity_users_total" xml:space="preserve">
<value>{0} usuários no total.</value> <value>{0} usuários no total.</value>
@ -1958,9 +2046,11 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="utility_channel_topic" xml:space="preserve"> <data name="utility_channel_topic" xml:space="preserve">
<value>Tópico do Canal</value> <value>Tópico do Canal</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="utility_commands_ran" xml:space="preserve"> <data name="utility_commands_ran" xml:space="preserve">
<value>Comandos Utilizados</value> <value>Comandos Utilizados</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="utility_convert" xml:space="preserve"> <data name="utility_convert" xml:space="preserve">
<value>{0} {1} é igual a {2} {3}</value> <value>{0} {1} é igual a {2} {3}</value>
@ -1976,6 +2066,7 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="utility_created_at" xml:space="preserve"> <data name="utility_created_at" xml:space="preserve">
<value>Criado em</value> <value>Criado em</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="utility_csc_join" xml:space="preserve"> <data name="utility_csc_join" xml:space="preserve">
<value>Juntou-se ao canal de servidor cruzado.</value> <value>Juntou-se ao canal de servidor cruzado.</value>
@ -1988,6 +2079,7 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="utility_custom_emojis" xml:space="preserve"> <data name="utility_custom_emojis" xml:space="preserve">
<value>Emojis Personalizados</value> <value>Emojis Personalizados</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="utility_error" xml:space="preserve"> <data name="utility_error" xml:space="preserve">
<value>Erro</value> <value>Erro</value>
@ -2003,9 +2095,11 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="utility_inrole_list" xml:space="preserve"> <data name="utility_inrole_list" xml:space="preserve">
<value>Aqui está uma lista de usuários nestes cargos:</value> <value>Aqui está uma lista de usuários nestes cargos:</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="utility_inrole_not_allowed" xml:space="preserve"> <data name="utility_inrole_not_allowed" xml:space="preserve">
<value>você não tem permissão de usar esse comando em cargos com muitos usuários para prevenir abuso.</value> <value>você não tem permissão de usar esse comando em cargos com muitos usuários para prevenir abuso.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="utility_invalid_value" xml:space="preserve"> <data name="utility_invalid_value" xml:space="preserve">
<value>Valor {0} inválido.</value> <value>Valor {0} inválido.</value>
@ -2016,17 +2110,20 @@ O novo valor de {0} é {1}!</value>
</data> </data>
<data name="utility_joined_server" xml:space="preserve"> <data name="utility_joined_server" xml:space="preserve">
<value>Juntou-se ao Servidor</value> <value>Juntou-se ao Servidor</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="utility_listservers" xml:space="preserve"> <data name="utility_listservers" xml:space="preserve">
<value>ID: {0} <value>ID: {0}
Membros: {1} Membros: {1}
OwnerID: {2}</value> OwnerID: {2}</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="utility_listservers_none" xml:space="preserve"> <data name="utility_listservers_none" xml:space="preserve">
<value>Nenhum servidor encontrado nessa página.</value> <value>Nenhum servidor encontrado nessa página.</value>
</data> </data>
<data name="utility_list_of_repeaters" xml:space="preserve"> <data name="utility_list_of_repeaters" xml:space="preserve">
<value>Lista de Repetidores</value> <value>Lista de Repetidores</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="utility_members" xml:space="preserve"> <data name="utility_members" xml:space="preserve">
<value>Membros</value> <value>Membros</value>
@ -2039,6 +2136,7 @@ OwnerID: {2}</value>
</data> </data>
<data name="utility_message_repeater" xml:space="preserve"> <data name="utility_message_repeater" xml:space="preserve">
<value>Repetidor de Mensagem</value> <value>Repetidor de Mensagem</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="utility_name" xml:space="preserve"> <data name="utility_name" xml:space="preserve">
<value>Nome</value> <value>Nome</value>
@ -2092,12 +2190,14 @@ OwnerID: {2}</value>
</data> </data>
<data name="utility_quote_deleted" xml:space="preserve"> <data name="utility_quote_deleted" xml:space="preserve">
<value>Uma citação aleatória foi removida.</value> <value>Uma citação aleatória foi removida.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="utility_region" xml:space="preserve"> <data name="utility_region" xml:space="preserve">
<value>Região</value> <value>Região</value>
</data> </data>
<data name="utility_registered_on" xml:space="preserve"> <data name="utility_registered_on" xml:space="preserve">
<value>Registrado em</value> <value>Registrado em</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="utility_remind" xml:space="preserve"> <data name="utility_remind" xml:space="preserve">
<value>Eu lembrarei {0} de {1} em {2} `({3:d.M.yyyy.} at {4:HH:mm})`</value> <value>Eu lembrarei {0} de {1} em {2} `({3:d.M.yyyy.} at {4:HH:mm})`</value>
@ -2113,6 +2213,7 @@ OwnerID: {2}</value>
</data> </data>
<data name="utility_repeaters_list" xml:space="preserve"> <data name="utility_repeaters_list" xml:space="preserve">
<value>Lista de Repetidores</value> <value>Lista de Repetidores</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="utility_repeaters_none" xml:space="preserve"> <data name="utility_repeaters_none" xml:space="preserve">
<value>Nenhum repetidor neste servidor.</value> <value>Nenhum repetidor neste servidor.</value>
@ -2149,12 +2250,14 @@ OwnerID: {2}</value>
</data> </data>
<data name="utility_server_info" xml:space="preserve"> <data name="utility_server_info" xml:space="preserve">
<value>Informações do Servidor</value> <value>Informações do Servidor</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="utility_shard" xml:space="preserve"> <data name="utility_shard" xml:space="preserve">
<value>Shard</value> <value>Shard</value>
</data> </data>
<data name="utility_shard_stats" xml:space="preserve"> <data name="utility_shard_stats" xml:space="preserve">
<value>Status do Shard</value> <value>Status do Shard</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="utility_shard_stats_txt" xml:space="preserve"> <data name="utility_shard_stats_txt" xml:space="preserve">
<value>Shard **#{0}** está no estado {1} com {2} servidores</value> <value>Shard **#{0}** está no estado {1} com {2} servidores</value>
@ -2170,6 +2273,7 @@ OwnerID: {2}</value>
</data> </data>
<data name="utility_text_channels" xml:space="preserve"> <data name="utility_text_channels" xml:space="preserve">
<value>Canais de Texto</value> <value>Canais de Texto</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="utility_togtub_room_link" xml:space="preserve"> <data name="utility_togtub_room_link" xml:space="preserve">
<value>Aqui está o link da sala:</value> <value>Aqui está o link da sala:</value>
@ -2186,6 +2290,101 @@ OwnerID: {2}</value>
</data> </data>
<data name="utility_voice_channels" xml:space="preserve"> <data name="utility_voice_channels" xml:space="preserve">
<value>Canais de Voz</value> <value>Canais de Voz</value>
<comment>Fuzzy</comment>
</data>
<data name="gambling_animal_race_already_in" xml:space="preserve">
<value>Você já entrou nesta corrida!</value>
</data>
<data name="games_current_poll_results" xml:space="preserve">
<value>Resultado atual da votação</value>
</data>
<data name="games_no_votes_cast" xml:space="preserve">
<value>Nenhum voto proferido.</value>
</data>
<data name="games_poll_already_running" xml:space="preserve">
<value>Uma votação já está ocorrendo neste servidor.</value>
</data>
<data name="games_poll_created" xml:space="preserve">
<value>📃 {0} criou uma votação que requer sua atenção:</value>
</data>
<data name="games_poll_result" xml:space="preserve">
<value>`{0}.` {1} com {2} votos.</value>
</data>
<data name="games_poll_voted" xml:space="preserve">
<value>{0} votou.</value>
<comment>Kwoth voted.</comment>
</data>
<data name="games_poll_vote_private" xml:space="preserve">
<value>Mande uma Mensagem Direta para mim com o número que corresponde à resposta.</value>
</data>
<data name="games_poll_vote_public" xml:space="preserve">
<value>Mande uma Mensagem aqui com o número que corresponde à resposta.</value>
</data>
<data name="games_thanks_for_voting" xml:space="preserve">
<value>Obrigado por votar, {0}</value>
</data>
<data name="games_x_votes_cast" xml:space="preserve">
<value>Total de {0} votos proferidos.</value>
</data>
<data name="games_pick_pl" xml:space="preserve">
<value>Pegue digitando `{0}pick`</value>
</data>
<data name="games_pick_sn" xml:space="preserve">
<value>Pegue digitando `{0}pick`</value>
</data>
<data name="gambling_no_users_found" xml:space="preserve">
<value>Nenhum usuário encontrado.</value>
</data>
<data name="gambling_page" xml:space="preserve">
<value>Página {0}</value>
</data>
<data name="administration_must_be_in_voice" xml:space="preserve">
<value>Você deve estar em um canal de voz neste servidor.</value>
</data>
<data name="administration_no_vcroles" xml:space="preserve">
<value>Não há cargos de canais de voz.</value>
</data>
<data name="administration_user_muted_time" xml:space="preserve">
<value>{0} foi **mutado** nos chats de texto e voz por {1} minutos.</value>
</data>
<data name="administration_vcrole_added" xml:space="preserve">
<value>Usuários que entrarem no canal de voz {0} receberão o cargo {1}.</value>
</data>
<data name="administration_vcrole_removed" xml:space="preserve">
<value>Usuários que entrarem no canal de voz {0} não irão mais receber um cargo.</value>
</data>
<data name="administration_vc_role_list" xml:space="preserve">
<value>Cargos de canais de voz</value>
</data>
<data name="customreactions_crad_disabled" xml:space="preserve">
<value>A mensagem que ativa a reação personalizada com id {0} não será deletada automaticamente.</value>
</data>
<data name="customreactions_crad_enabled" xml:space="preserve">
<value>A mensagem que ativa a reação personalizada com id {0} será deletada automaticamente.</value>
</data>
<data name="customreactions_crdm_disabled" xml:space="preserve">
<value>A resposta para a reação personalizada com o id {0} não será enviada como mensagem direta.</value>
</data>
<data name="customreactions_crdm_enabled" xml:space="preserve">
<value>A resposta para a reação personalizada com o id {0} será enviada como mensagem direta.</value>
</data>
<data name="utility_aliases_none" xml:space="preserve">
<value></value>
</data>
<data name="utility_alias_added" xml:space="preserve">
<value></value>
</data>
<data name="utility_alias_list" xml:space="preserve">
<value></value>
</data>
<data name="utility_alias_removed" xml:space="preserve">
<value></value>
</data>
<data name="utility_alias_remove_fail" xml:space="preserve">
<value></value>
</data>
<data name="searches_compet_playtime" xml:space="preserve">
<value></value>
</data> </data>
</root> </root>

View File

@ -139,7 +139,7 @@
<value>@{0} You already claimed base #{1}. You can't claim a new one.</value> <value>@{0} You already claimed base #{1}. You can't claim a new one.</value>
</data> </data>
<data name="clashofclans_claim_expired" xml:space="preserve"> <data name="clashofclans_claim_expired" xml:space="preserve">
<value>Claim from @{0} for a war against {1} has expired.</value> <value>Claim from @{0} in a war against {1} has expired.</value>
</data> </data>
<data name="clashofclans_enemy" xml:space="preserve"> <data name="clashofclans_enemy" xml:space="preserve">
<value>Enemy</value> <value>Enemy</value>
@ -151,10 +151,10 @@
<value>Invalid base number.</value> <value>Invalid base number.</value>
</data> </data>
<data name="clashofclans_invalid_size" xml:space="preserve"> <data name="clashofclans_invalid_size" xml:space="preserve">
<value>Not a Valid war size.</value> <value>Not a valid war size.</value>
</data> </data>
<data name="clashofclans_list_active_wars" xml:space="preserve"> <data name="clashofclans_list_active_wars" xml:space="preserve">
<value>List Of Active Wars</value> <value>List of active wars</value>
</data> </data>
<data name="clashofclans_not_claimed" xml:space="preserve"> <data name="clashofclans_not_claimed" xml:space="preserve">
<value>not claimed</value> <value>not claimed</value>
@ -166,7 +166,7 @@
<value>@{0} You are either not participating in that war, or that base is already destroyed.</value> <value>@{0} You are either not participating in that war, or that base is already destroyed.</value>
</data> </data>
<data name="clashofclans_no_active_wars" xml:space="preserve"> <data name="clashofclans_no_active_wars" xml:space="preserve">
<value>No active wars.</value> <value>No active war.</value>
</data> </data>
<data name="clashofclans_size" xml:space="preserve"> <data name="clashofclans_size" xml:space="preserve">
<value>Size</value> <value>Size</value>
@ -205,7 +205,7 @@
<value>New Custom Reaction</value> <value>New Custom Reaction</value>
</data> </data>
<data name="customreactions_no_found" xml:space="preserve"> <data name="customreactions_no_found" xml:space="preserve">
<value>No custom reactions found.</value> <value>No custom reaction found.</value>
</data> </data>
<data name="customreactions_no_found_id" xml:space="preserve"> <data name="customreactions_no_found_id" xml:space="preserve">
<value>No custom reaction found with that id.</value> <value>No custom reaction found with that id.</value>
@ -467,11 +467,10 @@ Reason: {1}</value>
Reason: {1}</value> Reason: {1}</value>
</data> </data>
<data name="administration_kicked_user" xml:space="preserve"> <data name="administration_kicked_user" xml:space="preserve">
<value>User Kicked</value> <value>User kicked</value>
</data> </data>
<data name="administration_lang_list" xml:space="preserve"> <data name="administration_lang_list" xml:space="preserve">
<value>List Of Languages <value>List of languages</value>
{0}</value>
</data> </data>
<data name="administration_lang_set" xml:space="preserve"> <data name="administration_lang_set" xml:space="preserve">
<value>Your server's locale is now {0} - {1}</value> <value>Your server's locale is now {0} - {1}</value>
@ -528,10 +527,10 @@ Reason: {1}</value>
<value>{0} moved from {1} to {2}</value> <value>{0} moved from {1} to {2}</value>
</data> </data>
<data name="administration_msg_del" xml:space="preserve"> <data name="administration_msg_del" xml:space="preserve">
<value>Message Deleted in #{0}</value> <value>Message deleted in #{0}</value>
</data> </data>
<data name="administration_msg_update" xml:space="preserve"> <data name="administration_msg_update" xml:space="preserve">
<value>Message Updated in #{0}</value> <value>Message updated in #{0}</value>
</data> </data>
<data name="administration_muted_pl" xml:space="preserve"> <data name="administration_muted_pl" xml:space="preserve">
<value>Muted</value> <value>Muted</value>
@ -551,16 +550,16 @@ Reason: {1}</value>
<value>I need **Administration** permission to do that.</value> <value>I need **Administration** permission to do that.</value>
</data> </data>
<data name="administration_new_msg" xml:space="preserve"> <data name="administration_new_msg" xml:space="preserve">
<value>New Message</value> <value>New message</value>
</data> </data>
<data name="administration_new_nick" xml:space="preserve"> <data name="administration_new_nick" xml:space="preserve">
<value>New Nickname</value> <value>New nickname</value>
</data> </data>
<data name="administration_new_topic" xml:space="preserve"> <data name="administration_new_topic" xml:space="preserve">
<value>New Topic</value> <value>New topic</value>
</data> </data>
<data name="administration_nick_change" xml:space="preserve"> <data name="administration_nick_change" xml:space="preserve">
<value>Nickname Changed</value> <value>Nickname changed</value>
</data> </data>
<data name="administration_no_server" xml:space="preserve"> <data name="administration_no_server" xml:space="preserve">
<value>Can't find that server</value> <value>Can't find that server</value>
@ -569,13 +568,13 @@ Reason: {1}</value>
<value>No shard with that ID found.</value> <value>No shard with that ID found.</value>
</data> </data>
<data name="administration_old_msg" xml:space="preserve"> <data name="administration_old_msg" xml:space="preserve">
<value>Old Message</value> <value>Old message</value>
</data> </data>
<data name="administration_old_nick" xml:space="preserve"> <data name="administration_old_nick" xml:space="preserve">
<value>Old Nickname</value> <value>Old nickname</value>
</data> </data>
<data name="administration_old_topic" xml:space="preserve"> <data name="administration_old_topic" xml:space="preserve">
<value>Old Topic</value> <value>Old topic</value>
</data> </data>
<data name="administration_perms" xml:space="preserve"> <data name="administration_perms" xml:space="preserve">
<value>Error. Most likely I don't have sufficient permissions.</value> <value>Error. Most likely I don't have sufficient permissions.</value>
@ -584,7 +583,7 @@ Reason: {1}</value>
<value>Permissions for this server are reset.</value> <value>Permissions for this server are reset.</value>
</data> </data>
<data name="administration_prot_active" xml:space="preserve"> <data name="administration_prot_active" xml:space="preserve">
<value>Active Protections</value> <value>Active protections</value>
</data> </data>
<data name="administration_prot_disable" xml:space="preserve"> <data name="administration_prot_disable" xml:space="preserve">
<value>{0} has been **disabled** on this server.</value> <value>{0} has been **disabled** on this server.</value>
@ -596,7 +595,7 @@ Reason: {1}</value>
<value>Error. I need ManageRoles permission</value> <value>Error. I need ManageRoles permission</value>
</data> </data>
<data name="administration_prot_none" xml:space="preserve"> <data name="administration_prot_none" xml:space="preserve">
<value>No protections enabled.</value> <value>No protection enabled.</value>
</data> </data>
<data name="administration_raid_cnt" xml:space="preserve"> <data name="administration_raid_cnt" xml:space="preserve">
<value>User threshold must be between {0} and {1}.</value> <value>User threshold must be between {0} and {1}.</value>
@ -755,10 +754,10 @@ Reason: {1}</value>
__IgnoredChannels__: {2}</value> __IgnoredChannels__: {2}</value>
</data> </data>
<data name="administration_text_chan_created" xml:space="preserve"> <data name="administration_text_chan_created" xml:space="preserve">
<value>Text Channel Created</value> <value>Text channel created.</value>
</data> </data>
<data name="administration_text_chan_destroyed" xml:space="preserve"> <data name="administration_text_chan_destroyed" xml:space="preserve">
<value>Text Channel Destroyed </value> <value>Text channel destroyed.</value>
</data> </data>
<data name="administration_undeafen" xml:space="preserve"> <data name="administration_undeafen" xml:space="preserve">
<value>Undeafen successful.</value> <value>Undeafen successful.</value>
@ -771,13 +770,13 @@ Reason: {1}</value>
<value>Username</value> <value>Username</value>
</data> </data>
<data name="administration_username_changed" xml:space="preserve"> <data name="administration_username_changed" xml:space="preserve">
<value>Username Changed</value> <value>Username changed</value>
</data> </data>
<data name="administration_users" xml:space="preserve"> <data name="administration_users" xml:space="preserve">
<value>Users</value> <value>Users</value>
</data> </data>
<data name="administration_user_banned" xml:space="preserve"> <data name="administration_user_banned" xml:space="preserve">
<value>User Banned</value> <value>User banned</value>
</data> </data>
<data name="administration_user_chat_mute" xml:space="preserve"> <data name="administration_user_chat_mute" xml:space="preserve">
<value>{0} has been **muted** from chatting.</value> <value>{0} has been **muted** from chatting.</value>
@ -786,19 +785,19 @@ Reason: {1}</value>
<value>{0} has been **unmuted** from chatting.</value> <value>{0} has been **unmuted** from chatting.</value>
</data> </data>
<data name="administration_user_joined" xml:space="preserve"> <data name="administration_user_joined" xml:space="preserve">
<value>User Joined</value> <value>User joined</value>
</data> </data>
<data name="administration_user_left" xml:space="preserve"> <data name="administration_user_left" xml:space="preserve">
<value>User Left</value> <value>User left</value>
</data> </data>
<data name="administration_user_muted" xml:space="preserve"> <data name="administration_user_muted" xml:space="preserve">
<value>{0} has been **muted** from text and voice chat.</value> <value>{0} has been **muted** from text and voice chat.</value>
</data> </data>
<data name="administration_user_role_add" xml:space="preserve"> <data name="administration_user_role_add" xml:space="preserve">
<value>User's Role Added</value> <value>User's role added</value>
</data> </data>
<data name="administration_user_role_rem" xml:space="preserve"> <data name="administration_user_role_rem" xml:space="preserve">
<value>User's Role Removed</value> <value>User's role removed</value>
</data> </data>
<data name="administration_user_status_change" xml:space="preserve"> <data name="administration_user_status_change" xml:space="preserve">
<value>{0} is now {1}</value> <value>{0} is now {1}</value>
@ -822,10 +821,10 @@ Reason: {1}</value>
<value>{0} has been **voice unmuted**.</value> <value>{0} has been **voice unmuted**.</value>
</data> </data>
<data name="administration_voice_chan_created" xml:space="preserve"> <data name="administration_voice_chan_created" xml:space="preserve">
<value>Voice Channel Created</value> <value>Voice channel created</value>
</data> </data>
<data name="administration_voice_chan_destroyed" xml:space="preserve"> <data name="administration_voice_chan_destroyed" xml:space="preserve">
<value>Voice Channel Destroyed</value> <value>Voice channel destroyed</value>
</data> </data>
<data name="administration_vt_disabled" xml:space="preserve"> <data name="administration_vt_disabled" xml:space="preserve">
<value>Disabled voice + text feature.</value> <value>Disabled voice + text feature.</value>
@ -856,7 +855,7 @@ Reason: {1}</value>
Reason: {1}</value> Reason: {1}</value>
</data> </data>
<data name="administration_user_unbanned" xml:space="preserve"> <data name="administration_user_unbanned" xml:space="preserve">
<value>User Unbanned</value> <value>User unbanned</value>
</data> </data>
<data name="administration_migration_done" xml:space="preserve"> <data name="administration_migration_done" xml:space="preserve">
<value>Migration done!</value> <value>Migration done!</value>
@ -865,10 +864,10 @@ Reason: {1}</value>
<value>Error while migrating, check bot's console for more information.</value> <value>Error while migrating, check bot's console for more information.</value>
</data> </data>
<data name="administration_presence_updates" xml:space="preserve"> <data name="administration_presence_updates" xml:space="preserve">
<value>Presence Updates</value> <value>Presence updates</value>
</data> </data>
<data name="administration_sb_user" xml:space="preserve"> <data name="administration_sb_user" xml:space="preserve">
<value>User Soft-Banned</value> <value>User soft-banned</value>
</data> </data>
<data name="gambling_awarded" xml:space="preserve"> <data name="gambling_awarded" xml:space="preserve">
<value>has awarded {0} to {1}</value> <value>has awarded {0} to {1}</value>
@ -910,7 +909,7 @@ Reason: {1}</value>
<comment>X has Y flowers</comment> <comment>X has Y flowers</comment>
</data> </data>
<data name="gambling_heads" xml:space="preserve"> <data name="gambling_heads" xml:space="preserve">
<value>Heads</value> <value>Head</value>
</data> </data>
<data name="gambling_leaderboard" xml:space="preserve"> <data name="gambling_leaderboard" xml:space="preserve">
<value>Leaderboard</value> <value>Leaderboard</value>
@ -931,7 +930,7 @@ Reason: {1}</value>
<value>No more cards in the deck.</value> <value>No more cards in the deck.</value>
</data> </data>
<data name="gambling_raffled_user" xml:space="preserve"> <data name="gambling_raffled_user" xml:space="preserve">
<value>Raffled User</value> <value>Raffled user</value>
</data> </data>
<data name="gambling_roll" xml:space="preserve"> <data name="gambling_roll" xml:space="preserve">
<value>You rolled {0}.</value> <value>You rolled {0}.</value>
@ -965,7 +964,7 @@ Lasts {1} seconds. Don't tell anyone. Shhh.</value>
<value>SneakyGameStatus event started</value> <value>SneakyGameStatus event started</value>
</data> </data>
<data name="gambling_tails" xml:space="preserve"> <data name="gambling_tails" xml:space="preserve">
<value>Tails</value> <value>Tail</value>
</data> </data>
<data name="gambling_take" xml:space="preserve"> <data name="gambling_take" xml:space="preserve">
<value>successfully took {0} from {1}</value> <value>successfully took {0} from {1}</value>
@ -977,7 +976,7 @@ Lasts {1} seconds. Don't tell anyone. Shhh.</value>
<value>Back to ToC</value> <value>Back to ToC</value>
</data> </data>
<data name="help_bot_owner_only" xml:space="preserve"> <data name="help_bot_owner_only" xml:space="preserve">
<value>Bot Owner Only</value> <value>Bot owner only</value>
</data> </data>
<data name="help_channel_permission" xml:space="preserve"> <data name="help_channel_permission" xml:space="preserve">
<value>Requires {0} channel permission.</value> <value>Requires {0} channel permission.</value>
@ -986,10 +985,10 @@ Lasts {1} seconds. Don't tell anyone. Shhh.</value>
<value>You can support the project on patreon: &lt;{0}&gt; or paypal: &lt;{1}&gt;</value> <value>You can support the project on patreon: &lt;{0}&gt; or paypal: &lt;{1}&gt;</value>
</data> </data>
<data name="help_cmd_and_alias" xml:space="preserve"> <data name="help_cmd_and_alias" xml:space="preserve">
<value>Command and aliases</value> <value>Commands and aliases</value>
</data> </data>
<data name="help_commandlist_regen" xml:space="preserve"> <data name="help_commandlist_regen" xml:space="preserve">
<value>Commandlist Regenerated.</value> <value>Commandlist regenerated.</value>
</data> </data>
<data name="help_commands_instr" xml:space="preserve"> <data name="help_commands_instr" xml:space="preserve">
<value>Type `{0}h CommandName` to see the help for that specified command. e.g. `{0}h &gt;8ball`</value> <value>Type `{0}h CommandName` to see the help for that specified command. e.g. `{0}h &gt;8ball`</value>
@ -1009,14 +1008,14 @@ Don't forget to leave your discord name or id in the message.
**Thank you** ♥️</value> **Thank you** ♥️</value>
</data> </data>
<data name="help_guide" xml:space="preserve"> <data name="help_guide" xml:space="preserve">
<value>**List of Commands**: &lt;{0}&gt; <value>**List of commands**: &lt;{0}&gt;
**Hosting Guides and docs can be found here**: &lt;{1}&gt;</value> **Hosting guides and docs can be found here**: &lt;{1}&gt;</value>
</data> </data>
<data name="help_list_of_commands" xml:space="preserve"> <data name="help_list_of_commands" xml:space="preserve">
<value>List Of Commands</value> <value>List of commands</value>
</data> </data>
<data name="help_list_of_modules" xml:space="preserve"> <data name="help_list_of_modules" xml:space="preserve">
<value>List Of Modules</value> <value>List of modules</value>
</data> </data>
<data name="help_modules_footer" xml:space="preserve"> <data name="help_modules_footer" xml:space="preserve">
<value>Type `{0}cmds ModuleName` to get a list of commands in that module. eg `{0}cmds games`</value> <value>Type `{0}cmds ModuleName` to get a list of commands in that module. eg `{0}cmds games`</value>
@ -1028,7 +1027,7 @@ Don't forget to leave your discord name or id in the message.
<value>Requires {0} server permission.</value> <value>Requires {0} server permission.</value>
</data> </data>
<data name="help_table_of_contents" xml:space="preserve"> <data name="help_table_of_contents" xml:space="preserve">
<value>Table Of Contents</value> <value>Table of contents</value>
</data> </data>
<data name="help_usage" xml:space="preserve"> <data name="help_usage" xml:space="preserve">
<value>Usage</value> <value>Usage</value>
@ -1041,7 +1040,7 @@ Don't forget to leave your discord name or id in the message.
<value>Tag</value> <value>Tag</value>
</data> </data>
<data name="gambling_animal_race" xml:space="preserve"> <data name="gambling_animal_race" xml:space="preserve">
<value>Animal Race</value> <value>Animal race</value>
</data> </data>
<data name="gambling_animal_race_failed" xml:space="preserve"> <data name="gambling_animal_race_failed" xml:space="preserve">
<value>Failed to start since there was not enough participants.</value> <value>Failed to start since there was not enough participants.</value>
@ -1091,10 +1090,10 @@ Don't forget to leave your discord name or id in the message.
<value>Second number must be larger than the first one.</value> <value>Second number must be larger than the first one.</value>
</data> </data>
<data name="gambling_changes_of_heart" xml:space="preserve"> <data name="gambling_changes_of_heart" xml:space="preserve">
<value>Changes Of Heart</value> <value>Changes of heart</value>
</data> </data>
<data name="gambling_claimed_by" xml:space="preserve"> <data name="gambling_claimed_by" xml:space="preserve">
<value>Claimed By</value> <value>Claimed by</value>
</data> </data>
<data name="gambling_divorces" xml:space="preserve"> <data name="gambling_divorces" xml:space="preserve">
<value>Divorces</value> <value>Divorces</value>
@ -1213,11 +1212,14 @@ Don't forget to leave your discord name or id in the message.
<value>{0} won! {1} beats {2}</value> <value>{0} won! {1} beats {2}</value>
</data> </data>
<data name="games_submissions_closed" xml:space="preserve"> <data name="games_submissions_closed" xml:space="preserve">
<value>Submissions Closed</value> <value>Submissions closed</value>
</data> </data>
<data name="gambling_animal_race_already_started" xml:space="preserve"> <data name="gambling_animal_race_already_started" xml:space="preserve">
<value>Animal Race is already running.</value> <value>Animal Race is already running.</value>
</data> </data>
<data name="gambling_animal_race_already_in" xml:space="preserve">
<value>You've already joined this race!</value>
</data>
<data name="gambling_total_average" xml:space="preserve"> <data name="gambling_total_average" xml:space="preserve">
<value>Total: {0} Average: {1}</value> <value>Total: {0} Average: {1}</value>
</data> </data>
@ -1237,17 +1239,17 @@ Don't forget to leave your discord name or id in the message.
<value>Currency generation has been enabled on this channel.</value> <value>Currency generation has been enabled on this channel.</value>
</data> </data>
<data name="games_curgen_pl" xml:space="preserve"> <data name="games_curgen_pl" xml:space="preserve">
<value>{0} random {1} appeared! Pick them up by typing `{2}pick`</value> <value>{0} random {1} appeared!</value>
<comment>plural</comment> <comment>plural</comment>
</data> </data>
<data name="games_curgen_sn" xml:space="preserve"> <data name="games_curgen_sn" xml:space="preserve">
<value>A random {0} appeared! Pick it up by typing `{1}pick`</value> <value>A random {0} appeared!</value>
</data> </data>
<data name="games_failed_loading_question" xml:space="preserve"> <data name="games_failed_loading_question" xml:space="preserve">
<value>Failed loading a question.</value> <value>Failed loading a question.</value>
</data> </data>
<data name="games_game_started" xml:space="preserve"> <data name="games_game_started" xml:space="preserve">
<value>Game Started</value> <value>Game started</value>
</data> </data>
<data name="games_hangman_game_started" xml:space="preserve"> <data name="games_hangman_game_started" xml:space="preserve">
<value>Hangman game started</value> <value>Hangman game started</value>
@ -1315,16 +1317,16 @@ Don't forget to leave your discord name or id in the message.
<value>has created a game of TicTacToe.</value> <value>has created a game of TicTacToe.</value>
</data> </data>
<data name="games_ttt_has_won" xml:space="preserve"> <data name="games_ttt_has_won" xml:space="preserve">
<value>{0} has Won!</value> <value>{0} has won!</value>
</data> </data>
<data name="games_ttt_matched_three" xml:space="preserve"> <data name="games_ttt_matched_three" xml:space="preserve">
<value>Matched Three</value> <value>Matched three</value>
</data> </data>
<data name="games_ttt_no_moves" xml:space="preserve"> <data name="games_ttt_no_moves" xml:space="preserve">
<value>No moves left!</value> <value>No moves left!</value>
</data> </data>
<data name="games_ttt_time_expired" xml:space="preserve"> <data name="games_ttt_time_expired" xml:space="preserve">
<value>Time Expired!</value> <value>Time expired!</value>
</data> </data>
<data name="games_ttt_users_move" xml:space="preserve"> <data name="games_ttt_users_move" xml:space="preserve">
<value>{0}'s move</value> <value>{0}'s move</value>
@ -1351,7 +1353,7 @@ Don't forget to leave your discord name or id in the message.
<value>fairplay</value> <value>fairplay</value>
</data> </data>
<data name="music_finished_song" xml:space="preserve"> <data name="music_finished_song" xml:space="preserve">
<value>Finished Song</value> <value>Finished song</value>
</data> </data>
<data name="music_fp_disabled" xml:space="preserve"> <data name="music_fp_disabled" xml:space="preserve">
<value>Fair play disabled.</value> <value>Fair play disabled.</value>
@ -1387,7 +1389,7 @@ Don't forget to leave your discord name or id in the message.
<value>Name</value> <value>Name</value>
</data> </data>
<data name="music_now_playing" xml:space="preserve"> <data name="music_now_playing" xml:space="preserve">
<value>Now Playing</value> <value>Now playing</value>
</data> </data>
<data name="music_no_player" xml:space="preserve"> <data name="music_no_player" xml:space="preserve">
<value>No active music player.</value> <value>No active music player.</value>
@ -1399,16 +1401,16 @@ Don't forget to leave your discord name or id in the message.
<value>Music playback paused.</value> <value>Music playback paused.</value>
</data> </data>
<data name="music_player_queue" xml:space="preserve"> <data name="music_player_queue" xml:space="preserve">
<value>Player Queue - Page {0}/{1}</value> <value>Player queue - Page {0}/{1}</value>
</data> </data>
<data name="music_playing_song" xml:space="preserve"> <data name="music_playing_song" xml:space="preserve">
<value>Playing Song</value> <value>Playing song</value>
</data> </data>
<data name="music_playlists" xml:space="preserve"> <data name="music_playlists" xml:space="preserve">
<value>`#{0}` - **{1}** by *{2}* ({3} songs)</value> <value>`#{0}` - **{1}** by *{2}* ({3} songs)</value>
</data> </data>
<data name="music_playlists_page" xml:space="preserve"> <data name="music_playlists_page" xml:space="preserve">
<value>Page {0} of Saved Playlists</value> <value>Page {0} of saved playlists</value>
</data> </data>
<data name="music_playlist_deleted" xml:space="preserve"> <data name="music_playlist_deleted" xml:space="preserve">
<value>Playlist deleted.</value> <value>Playlist deleted.</value>
@ -1423,7 +1425,7 @@ Don't forget to leave your discord name or id in the message.
<value>Playlist queue complete.</value> <value>Playlist queue complete.</value>
</data> </data>
<data name="music_playlist_saved" xml:space="preserve"> <data name="music_playlist_saved" xml:space="preserve">
<value>Playlist Saved</value> <value>Playlist saved</value>
</data> </data>
<data name="music_play_limit" xml:space="preserve"> <data name="music_play_limit" xml:space="preserve">
<value>{0}s limit</value> <value>{0}s limit</value>
@ -1432,7 +1434,7 @@ Don't forget to leave your discord name or id in the message.
<value>Queue</value> <value>Queue</value>
</data> </data>
<data name="music_queued_song" xml:space="preserve"> <data name="music_queued_song" xml:space="preserve">
<value>Queued Song</value> <value>Queued song</value>
</data> </data>
<data name="music_queue_cleared" xml:space="preserve"> <data name="music_queue_cleared" xml:space="preserve">
<value>Music queue cleared.</value> <value>Music queue cleared.</value>
@ -1445,13 +1447,13 @@ Don't forget to leave your discord name or id in the message.
<comment>context: "removed song #5"</comment> <comment>context: "removed song #5"</comment>
</data> </data>
<data name="music_repeating_cur_song" xml:space="preserve"> <data name="music_repeating_cur_song" xml:space="preserve">
<value>Repeating Current Song</value> <value>Repeating current song</value>
</data> </data>
<data name="music_repeating_playlist" xml:space="preserve"> <data name="music_repeating_playlist" xml:space="preserve">
<value>Repeating Playlist</value> <value>Repeating playlist</value>
</data> </data>
<data name="music_repeating_track" xml:space="preserve"> <data name="music_repeating_track" xml:space="preserve">
<value>Repeating Track</value> <value>Repeating track</value>
</data> </data>
<data name="music_repeating_track_stopped" xml:space="preserve"> <data name="music_repeating_track_stopped" xml:space="preserve">
<value>Current track repeat stopped.</value> <value>Current track repeat stopped.</value>
@ -1472,10 +1474,10 @@ Don't forget to leave your discord name or id in the message.
<value>Skipped to `{0}:{1}`</value> <value>Skipped to `{0}:{1}`</value>
</data> </data>
<data name="music_songs_shuffled" xml:space="preserve"> <data name="music_songs_shuffled" xml:space="preserve">
<value>Songs shuffled.</value> <value>Songs shuffled</value>
</data> </data>
<data name="music_song_moved" xml:space="preserve"> <data name="music_song_moved" xml:space="preserve">
<value>Song Moved</value> <value>Song moved</value>
</data> </data>
<data name="music_time_format" xml:space="preserve"> <data name="music_time_format" xml:space="preserve">
<value>{0}h {1}m {2}s</value> <value>{0}h {1}m {2}s</value>
@ -1493,19 +1495,19 @@ Don't forget to leave your discord name or id in the message.
<value>Volume set to {0}%</value> <value>Volume set to {0}%</value>
</data> </data>
<data name="permissions_acm_disable" xml:space="preserve"> <data name="permissions_acm_disable" xml:space="preserve">
<value>Disabled usage of ALL MODULES on {0} channel.</value> <value>Disabled usage of ALL MODULES on channel {0}.</value>
</data> </data>
<data name="permissions_acm_enable" xml:space="preserve"> <data name="permissions_acm_enable" xml:space="preserve">
<value>Enabled usage of ALL MODULES on {0} channel.</value> <value>Enabled usage of ALL MODULES on channel {0}.</value>
</data> </data>
<data name="permissions_allowed" xml:space="preserve"> <data name="permissions_allowed" xml:space="preserve">
<value>Allowed</value> <value>Allowed</value>
</data> </data>
<data name="permissions_arm_disable" xml:space="preserve"> <data name="permissions_arm_disable" xml:space="preserve">
<value>Disabled usage of ALL MODULES for {0} role.</value> <value>Disabled usage of ALL MODULES for role {0}.</value>
</data> </data>
<data name="permissions_arm_enable" xml:space="preserve"> <data name="permissions_arm_enable" xml:space="preserve">
<value>Enabled usage of ALL MODULES for {0} role.</value> <value>Enabled usage of ALL MODULES for role {0}.</value>
</data> </data>
<data name="permissions_asm_disable" xml:space="preserve"> <data name="permissions_asm_disable" xml:space="preserve">
<value>Disabled usage of ALL MODULES on this server.</value> <value>Disabled usage of ALL MODULES on this server.</value>
@ -1514,10 +1516,10 @@ Don't forget to leave your discord name or id in the message.
<value>Enabled usage of ALL MODULES on this server.</value> <value>Enabled usage of ALL MODULES on this server.</value>
</data> </data>
<data name="permissions_aum_disable" xml:space="preserve"> <data name="permissions_aum_disable" xml:space="preserve">
<value>Disabled usage of ALL MODULES for {0} user.</value> <value>Disabled usage of ALL MODULES for user {0}.</value>
</data> </data>
<data name="permissions_aum_enable" xml:space="preserve"> <data name="permissions_aum_enable" xml:space="preserve">
<value>Enabled usage of ALL MODULES for {0} user.</value> <value>Enabled usage of ALL MODULES for user {0}.</value>
</data> </data>
<data name="permissions_blacklisted" xml:space="preserve"> <data name="permissions_blacklisted" xml:space="preserve">
<value>Blacklisted {0} with ID {1}</value> <value>Blacklisted {0} with ID {1}</value>
@ -1526,19 +1528,19 @@ Don't forget to leave your discord name or id in the message.
<value>Command {0} now has a {1}s cooldown.</value> <value>Command {0} now has a {1}s cooldown.</value>
</data> </data>
<data name="permissions_cmdcd_cleared" xml:space="preserve"> <data name="permissions_cmdcd_cleared" xml:space="preserve">
<value>Command {0} has no coooldown now and all existing cooldowns have been cleared.</value> <value>Command {0} has no cooldown now and all existing cooldowns have been cleared.</value>
</data> </data>
<data name="permissions_cmdcd_none" xml:space="preserve"> <data name="permissions_cmdcd_none" xml:space="preserve">
<value>No command cooldowns set.</value> <value>No command cooldowns set.</value>
</data> </data>
<data name="permissions_command_costs" xml:space="preserve"> <data name="permissions_command_costs" xml:space="preserve">
<value>Command Costs</value> <value>Command costs</value>
</data> </data>
<data name="permissions_cx_disable" xml:space="preserve"> <data name="permissions_cx_disable" xml:space="preserve">
<value>Disabled usage of {0} {1} on {2} channel.</value> <value>Disabled usage of {0} {1} on channel {2}.</value>
</data> </data>
<data name="permissions_cx_enable" xml:space="preserve"> <data name="permissions_cx_enable" xml:space="preserve">
<value>Enabled usage of {0} {1} on {2} channel.</value> <value>Enabled usage of {0} {1} on channel {2}.</value>
</data> </data>
<data name="permissions_denied" xml:space="preserve"> <data name="permissions_denied" xml:space="preserve">
<value>Denied</value> <value>Denied</value>
@ -1547,7 +1549,7 @@ Don't forget to leave your discord name or id in the message.
<value>Added word {0} to the list of filtered words.</value> <value>Added word {0} to the list of filtered words.</value>
</data> </data>
<data name="permissions_filter_word_list" xml:space="preserve"> <data name="permissions_filter_word_list" xml:space="preserve">
<value>List Of Filtered Words</value> <value>List of filtered words</value>
</data> </data>
<data name="permissions_filter_word_remove" xml:space="preserve"> <data name="permissions_filter_word_remove" xml:space="preserve">
<value>Removed word {0} from the list of filtered words.</value> <value>Removed word {0} from the list of filtered words.</value>
@ -1578,7 +1580,7 @@ Don't forget to leave your discord name or id in the message.
</data> </data>
<data name="permissions_of_command" xml:space="preserve"> <data name="permissions_of_command" xml:space="preserve">
<value>command</value> <value>command</value>
<comment>Gen (of command)</comment> <comment>Gen. (of command)</comment>
</data> </data>
<data name="permissions_of_module" xml:space="preserve"> <data name="permissions_of_module" xml:space="preserve">
<value>module</value> <value>module</value>
@ -1682,13 +1684,13 @@ Don't forget to leave your discord name or id in the message.
<value>Comic #</value> <value>Comic #</value>
</data> </data>
<data name="searches_compet_loses" xml:space="preserve"> <data name="searches_compet_loses" xml:space="preserve">
<value>Competitive Loses</value> <value>Competitive losses</value>
</data> </data>
<data name="searches_compet_played" xml:space="preserve"> <data name="searches_compet_played" xml:space="preserve">
<value>Competitive Played</value> <value>Competitive played</value>
</data> </data>
<data name="searches_compet_rank" xml:space="preserve"> <data name="searches_compet_rank" xml:space="preserve">
<value>Competitive Rank</value> <value>Competitive rank</value>
</data> </data>
<data name="searches_compet_wins" xml:space="preserve"> <data name="searches_compet_wins" xml:space="preserve">
<value>Competitive Wins</value> <value>Competitive Wins</value>
@ -1742,7 +1744,7 @@ Don't forget to leave your discord name or id in the message.
<value>Humidity</value> <value>Humidity</value>
</data> </data>
<data name="searches_image_search_for" xml:space="preserve"> <data name="searches_image_search_for" xml:space="preserve">
<value>Image Search For:</value> <value>Image search for:</value>
</data> </data>
<data name="searches_imdb_fail" xml:space="preserve"> <data name="searches_imdb_fail" xml:space="preserve">
<value>Failed to find that movie.</value> <value>Failed to find that movie.</value>
@ -1785,10 +1787,10 @@ Don't forget to leave your discord name or id in the message.
<value>No results found.</value> <value>No results found.</value>
</data> </data>
<data name="searches_on_hold" xml:space="preserve"> <data name="searches_on_hold" xml:space="preserve">
<value>On-Hold</value> <value>On-hold</value>
</data> </data>
<data name="searches_original_url" xml:space="preserve"> <data name="searches_original_url" xml:space="preserve">
<value>Original Url</value> <value>Original url</value>
</data> </data>
<data name="searches_osu_api_key" xml:space="preserve"> <data name="searches_osu_api_key" xml:space="preserve">
<value>An osu! API key is required.</value> <value>An osu! API key is required.</value>
@ -1815,16 +1817,16 @@ Don't forget to leave your discord name or id in the message.
<value>No pokemon found.</value> <value>No pokemon found.</value>
</data> </data>
<data name="searches_profile_link" xml:space="preserve"> <data name="searches_profile_link" xml:space="preserve">
<value>Profile Link:</value> <value>Profile link:</value>
</data> </data>
<data name="searches_quality" xml:space="preserve"> <data name="searches_quality" xml:space="preserve">
<value>Quality:</value> <value>Quality:</value>
</data> </data>
<data name="searches_quick_playtime" xml:space="preserve"> <data name="searches_quick_playtime" xml:space="preserve">
<value>Quick Playtime</value> <value>Quick playtime</value>
</data> </data>
<data name="searches_quick_wins" xml:space="preserve"> <data name="searches_quick_wins" xml:space="preserve">
<value>Quick Wins</value> <value>Quick wins</value>
</data> </data>
<data name="searches_rating" xml:space="preserve"> <data name="searches_rating" xml:space="preserve">
<value>Rating</value> <value>Rating</value>
@ -1833,13 +1835,13 @@ Don't forget to leave your discord name or id in the message.
<value>Score:</value> <value>Score:</value>
</data> </data>
<data name="searches_search_for" xml:space="preserve"> <data name="searches_search_for" xml:space="preserve">
<value>Search For:</value> <value>Search for:</value>
</data> </data>
<data name="searches_shorten_fail" xml:space="preserve"> <data name="searches_shorten_fail" xml:space="preserve">
<value>Failed to shorten that url.</value> <value>Failed to shorten that url.</value>
</data> </data>
<data name="searches_short_url" xml:space="preserve"> <data name="searches_short_url" xml:space="preserve">
<value>Short Url</value> <value>Short url</value>
</data> </data>
<data name="searches_something_went_wrong" xml:space="preserve"> <data name="searches_something_went_wrong" xml:space="preserve">
<value>Something went wrong.</value> <value>Something went wrong.</value>
@ -1851,7 +1853,7 @@ Don't forget to leave your discord name or id in the message.
<value>Status</value> <value>Status</value>
</data> </data>
<data name="searches_store_url" xml:space="preserve"> <data name="searches_store_url" xml:space="preserve">
<value>Store Url</value> <value>Store url</value>
</data> </data>
<data name="searches_streamer_offline" xml:space="preserve"> <data name="searches_streamer_offline" xml:space="preserve">
<value>Streamer {0} is offline.</value> <value>Streamer {0} is offline.</value>
@ -1920,7 +1922,7 @@ Don't forget to leave your discord name or id in the message.
<value>Page not found.</value> <value>Page not found.</value>
</data> </data>
<data name="searches_wind_speed" xml:space="preserve"> <data name="searches_wind_speed" xml:space="preserve">
<value>Wind Speed</value> <value>Wind speed</value>
</data> </data>
<data name="searches_x_most_banned_champs" xml:space="preserve"> <data name="searches_x_most_banned_champs" xml:space="preserve">
<value>The {0} most banned champions</value> <value>The {0} most banned champions</value>
@ -1937,7 +1939,7 @@ Don't forget to leave your discord name or id in the message.
`1.` </comment> `1.` </comment>
</data> </data>
<data name="utility_activity_page" xml:space="preserve"> <data name="utility_activity_page" xml:space="preserve">
<value>Activity Page #{0}</value> <value>Activity page #{0}</value>
</data> </data>
<data name="utility_activity_users_total" xml:space="preserve"> <data name="utility_activity_users_total" xml:space="preserve">
<value>{0} users total.</value> <value>{0} users total.</value>
@ -1955,10 +1957,10 @@ Don't forget to leave your discord name or id in the message.
<value>{0} of this channel is {1}</value> <value>{0} of this channel is {1}</value>
</data> </data>
<data name="utility_channel_topic" xml:space="preserve"> <data name="utility_channel_topic" xml:space="preserve">
<value>Channel Topic</value> <value>Channel topic</value>
</data> </data>
<data name="utility_commands_ran" xml:space="preserve"> <data name="utility_commands_ran" xml:space="preserve">
<value>Commands Ran</value> <value>Commands ran</value>
</data> </data>
<data name="utility_convert" xml:space="preserve"> <data name="utility_convert" xml:space="preserve">
<value>{0} {1} is equal to {2} {3}</value> <value>{0} {1} is equal to {2} {3}</value>
@ -1973,7 +1975,7 @@ Don't forget to leave your discord name or id in the message.
<value>Cannot convert {0} to {1}: types of unit are not equal</value> <value>Cannot convert {0} to {1}: types of unit are not equal</value>
</data> </data>
<data name="utility_created_at" xml:space="preserve"> <data name="utility_created_at" xml:space="preserve">
<value>Created At</value> <value>Created at</value>
</data> </data>
<data name="utility_csc_join" xml:space="preserve"> <data name="utility_csc_join" xml:space="preserve">
<value>Joined cross server channel.</value> <value>Joined cross server channel.</value>
@ -1985,7 +1987,7 @@ Don't forget to leave your discord name or id in the message.
<value>This is your CSC token</value> <value>This is your CSC token</value>
</data> </data>
<data name="utility_custom_emojis" xml:space="preserve"> <data name="utility_custom_emojis" xml:space="preserve">
<value>Custom Emojis</value> <value>Custom emojis</value>
</data> </data>
<data name="utility_error" xml:space="preserve"> <data name="utility_error" xml:space="preserve">
<value>Error</value> <value>Error</value>
@ -2000,10 +2002,10 @@ Don't forget to leave your discord name or id in the message.
<value>Index out of range.</value> <value>Index out of range.</value>
</data> </data>
<data name="utility_inrole_list" xml:space="preserve"> <data name="utility_inrole_list" xml:space="preserve">
<value>Here is a list of users in those roles:</value> <value>List of users in {0} role</value>
</data> </data>
<data name="utility_inrole_not_allowed" xml:space="preserve"> <data name="utility_inrole_not_allowed" xml:space="preserve">
<value>you are not allowed to use this command on roles with a lot of users in them to prevent abuse.</value> <value>You are not allowed to use this command on roles with a lot of users in them to prevent abuse.</value>
</data> </data>
<data name="utility_invalid_value" xml:space="preserve"> <data name="utility_invalid_value" xml:space="preserve">
<value>Invalid {0} value.</value> <value>Invalid {0} value.</value>
@ -2013,7 +2015,7 @@ Don't forget to leave your discord name or id in the message.
<value>Joined Discord</value> <value>Joined Discord</value>
</data> </data>
<data name="utility_joined_server" xml:space="preserve"> <data name="utility_joined_server" xml:space="preserve">
<value>Joined Server</value> <value>Joined server</value>
</data> </data>
<data name="utility_listservers" xml:space="preserve"> <data name="utility_listservers" xml:space="preserve">
<value>ID: {0} <value>ID: {0}
@ -2024,7 +2026,7 @@ OwnerID: {2}</value>
<value>No servers found on that page.</value> <value>No servers found on that page.</value>
</data> </data>
<data name="utility_list_of_repeaters" xml:space="preserve"> <data name="utility_list_of_repeaters" xml:space="preserve">
<value>List of Repeaters</value> <value>List of repeater</value>
</data> </data>
<data name="utility_members" xml:space="preserve"> <data name="utility_members" xml:space="preserve">
<value>Members</value> <value>Members</value>
@ -2036,7 +2038,7 @@ OwnerID: {2}</value>
<value>Messages</value> <value>Messages</value>
</data> </data>
<data name="utility_message_repeater" xml:space="preserve"> <data name="utility_message_repeater" xml:space="preserve">
<value>Message Repeater</value> <value>Message repeater</value>
</data> </data>
<data name="utility_name" xml:space="preserve"> <data name="utility_name" xml:space="preserve">
<value>Name</value> <value>Name</value>
@ -2089,13 +2091,13 @@ OwnerID: {2}</value>
<value>Quote Added</value> <value>Quote Added</value>
</data> </data>
<data name="utility_quote_deleted" xml:space="preserve"> <data name="utility_quote_deleted" xml:space="preserve">
<value>Deleted a random quote.</value> <value>Quote #{0} deleted.</value>
</data> </data>
<data name="utility_region" xml:space="preserve"> <data name="utility_region" xml:space="preserve">
<value>Region</value> <value>Region</value>
</data> </data>
<data name="utility_registered_on" xml:space="preserve"> <data name="utility_registered_on" xml:space="preserve">
<value>Registered On</value> <value>Registered on</value>
</data> </data>
<data name="utility_remind" xml:space="preserve"> <data name="utility_remind" xml:space="preserve">
<value>I will remind {0} to {1} in {2} `({3:d.M.yyyy.} at {4:HH:mm})`</value> <value>I will remind {0} to {1} in {2} `({3:d.M.yyyy.} at {4:HH:mm})`</value>
@ -2110,7 +2112,7 @@ OwnerID: {2}</value>
<value>Repeating {0} every {1} day(s), {2} hour(s) and {3} minute(s).</value> <value>Repeating {0} every {1} day(s), {2} hour(s) and {3} minute(s).</value>
</data> </data>
<data name="utility_repeaters_list" xml:space="preserve"> <data name="utility_repeaters_list" xml:space="preserve">
<value>List Of Repeaters</value> <value>List of repeaters</value>
</data> </data>
<data name="utility_repeaters_none" xml:space="preserve"> <data name="utility_repeaters_none" xml:space="preserve">
<value>No repeaters running on this server.</value> <value>No repeaters running on this server.</value>
@ -2146,13 +2148,13 @@ OwnerID: {2}</value>
<value>{0} of this server is {1}</value> <value>{0} of this server is {1}</value>
</data> </data>
<data name="utility_server_info" xml:space="preserve"> <data name="utility_server_info" xml:space="preserve">
<value>Server Info</value> <value>Server info</value>
</data> </data>
<data name="utility_shard" xml:space="preserve"> <data name="utility_shard" xml:space="preserve">
<value>Shard</value> <value>Shard</value>
</data> </data>
<data name="utility_shard_stats" xml:space="preserve"> <data name="utility_shard_stats" xml:space="preserve">
<value>Shard Stats</value> <value>Shard stats</value>
</data> </data>
<data name="utility_shard_stats_txt" xml:space="preserve"> <data name="utility_shard_stats_txt" xml:space="preserve">
<value>Shard **#{0}** is in {1} state with {2} servers</value> <value>Shard **#{0}** is in {1} state with {2} servers</value>
@ -2167,7 +2169,7 @@ OwnerID: {2}</value>
<value>Playing {0} songs, {1} queued.</value> <value>Playing {0} songs, {1} queued.</value>
</data> </data>
<data name="utility_text_channels" xml:space="preserve"> <data name="utility_text_channels" xml:space="preserve">
<value>Text Channels</value> <value>Text channels</value>
</data> </data>
<data name="utility_togtub_room_link" xml:space="preserve"> <data name="utility_togtub_room_link" xml:space="preserve">
<value>Here is your room link:</value> <value>Here is your room link:</value>
@ -2183,6 +2185,97 @@ OwnerID: {2}</value>
<value>Users</value> <value>Users</value>
</data> </data>
<data name="utility_voice_channels" xml:space="preserve"> <data name="utility_voice_channels" xml:space="preserve">
<value>Voice Channels</value> <value>Voice channels</value>
</data>
<data name="games_current_poll_results" xml:space="preserve">
<value>Current poll results</value>
</data>
<data name="games_no_votes_cast" xml:space="preserve">
<value>No votes cast.</value>
</data>
<data name="games_poll_already_running" xml:space="preserve">
<value>Poll is already running on this server.</value>
</data>
<data name="games_poll_created" xml:space="preserve">
<value>📃 {0} has created a poll which requires your attention:</value>
</data>
<data name="games_poll_result" xml:space="preserve">
<value>`{0}.` {1} with {2} votes.</value>
</data>
<data name="games_poll_voted" xml:space="preserve">
<value>{0} voted.</value>
<comment>Kwoth voted.</comment>
</data>
<data name="games_poll_vote_private" xml:space="preserve">
<value>Private Message me with the corresponding number of the answer.</value>
</data>
<data name="games_poll_vote_public" xml:space="preserve">
<value>Send a Message here with the corresponding number of the answer.</value>
</data>
<data name="games_thanks_for_voting" xml:space="preserve">
<value>Thank you for voting, {0}</value>
</data>
<data name="games_x_votes_cast" xml:space="preserve">
<value>{0} total votes cast.</value>
</data>
<data name="games_pick_pl" xml:space="preserve">
<value>Pick them up by typing `{0}pick`</value>
</data>
<data name="games_pick_sn" xml:space="preserve">
<value>Pick it up by typing `{0}pick`</value>
</data>
<data name="gambling_no_users_found" xml:space="preserve">
<value>No user found.</value>
</data>
<data name="gambling_page" xml:space="preserve">
<value>page {0}</value>
</data>
<data name="administration_must_be_in_voice" xml:space="preserve">
<value>You must be in a voice channel on this server.</value>
</data>
<data name="administration_no_vcroles" xml:space="preserve">
<value>There are no voice channel roles.</value>
</data>
<data name="administration_user_muted_time" xml:space="preserve">
<value>{0} has been **muted** from text and voice chat for {1} minutes.</value>
</data>
<data name="administration_vcrole_added" xml:space="preserve">
<value>Users who join {0} voice channel will get {1} role.</value>
</data>
<data name="administration_vcrole_removed" xml:space="preserve">
<value>Users who join {0} voice channel will no longer get a role.</value>
</data>
<data name="administration_vc_role_list" xml:space="preserve">
<value>Voice channel roles</value>
</data>
<data name="customreactions_crad_disabled" xml:space="preserve">
<value>Message triggering the custom reaction with id {0} won't get automatically deleted.</value>
</data>
<data name="customreactions_crad_enabled" xml:space="preserve">
<value>Message triggering the custom reaction with id {0} will get automatically deleted.</value>
</data>
<data name="customreactions_crdm_disabled" xml:space="preserve">
<value>Response message for the custom reaction with id {0} won't be sent as a DM.</value>
</data>
<data name="customreactions_crdm_enabled" xml:space="preserve">
<value>Response message for the custom reaction with id {0} will be sent as a DM.</value>
</data>
<data name="utility_aliases_none" xml:space="preserve">
<value>No alias found</value>
</data>
<data name="utility_alias_added" xml:space="preserve">
<value>Typing {0} will now be an alias of {1}.</value>
</data>
<data name="utility_alias_list" xml:space="preserve">
<value>List of aliases</value>
</data>
<data name="utility_alias_removed" xml:space="preserve">
<value>Trigger {0} no longer has an alias.</value>
</data>
<data name="utility_alias_remove_fail" xml:space="preserve">
<value>Trigger {0} didn't have an alias.</value>
</data>
<data name="searches_compet_playtime" xml:space="preserve">
<value>Competitive playtime</value>
</data> </data>
</root> </root>

View File

@ -139,7 +139,7 @@
<value>@{0} Вы уже захватили базу #{1}. Вы не можете захватить новую базу.</value> <value>@{0} Вы уже захватили базу #{1}. Вы не можете захватить новую базу.</value>
</data> </data>
<data name="clashofclans_claim_expired" xml:space="preserve"> <data name="clashofclans_claim_expired" xml:space="preserve">
<value>Время действия запроса от @{0} на войну против {1} истёкло.</value> <value>Время действия запроса от @{0} на войну против {1} истекло.</value>
</data> </data>
<data name="clashofclans_enemy" xml:space="preserve"> <data name="clashofclans_enemy" xml:space="preserve">
<value>Враг</value> <value>Враг</value>
@ -163,7 +163,7 @@
<value>Вы не участвуете в этой войне.</value> <value>Вы не участвуете в этой войне.</value>
</data> </data>
<data name="clashofclans_not_partic_or_destroyed" xml:space="preserve"> <data name="clashofclans_not_partic_or_destroyed" xml:space="preserve">
<value>@{0} Вы либо не участвуете в этой войне, либо эта база разрушена.</value> <value>@{0} Вы либо не участвуете в этой войне, либо эта база уже разрушена.</value>
</data> </data>
<data name="clashofclans_no_active_wars" xml:space="preserve"> <data name="clashofclans_no_active_wars" xml:space="preserve">
<value>Нет активных войн.</value> <value>Нет активных войн.</value>
@ -175,13 +175,13 @@
<value>Война против {0} уже началась.</value> <value>Война против {0} уже началась.</value>
</data> </data>
<data name="clashofclans_war_created" xml:space="preserve"> <data name="clashofclans_war_created" xml:space="preserve">
<value>Война против {0} была начата.</value> <value>Война против {0} начата.</value>
</data> </data>
<data name="clashofclans_war_ended" xml:space="preserve"> <data name="clashofclans_war_ended" xml:space="preserve">
<value>Закончилась война против {0}.</value> <value>Война против {0} закончилась.</value>
</data> </data>
<data name="clashofclans_war_not_exist" xml:space="preserve"> <data name="clashofclans_war_not_exist" xml:space="preserve">
<value>Эта война не существует.</value> <value>Этой войны не существует.</value>
</data> </data>
<data name="clashofclans_war_started" xml:space="preserve"> <data name="clashofclans_war_started" xml:space="preserve">
<value>Война против {0} началась!</value> <value>Война против {0} началась!</value>
@ -193,7 +193,7 @@
<value>Настраиваемая реакция удалена</value> <value>Настраиваемая реакция удалена</value>
</data> </data>
<data name="customreactions_insuff_perms" xml:space="preserve"> <data name="customreactions_insuff_perms" xml:space="preserve">
<value>Недостаточно прав. Необходимо владеть Бот-ом для глобальных настраиваемых реакций или быть Администратором для реакций по серверу.</value> <value>Недостаточно прав. Необходимо иметь права владельца бота для глобальных настраиваемых реакций, и права Администратора для реакций по серверу.</value>
</data> </data>
<data name="customreactions_list_all" xml:space="preserve"> <data name="customreactions_list_all" xml:space="preserve">
<value>Список всех настраиваемых реакций</value> <value>Список всех настраиваемых реакций</value>
@ -217,7 +217,7 @@
<value>Статистика настраеваемых реакций</value> <value>Статистика настраеваемых реакций</value>
</data> </data>
<data name="customreactions_stats_cleared" xml:space="preserve"> <data name="customreactions_stats_cleared" xml:space="preserve">
<value>Статистика удалена для настраеваемой реакции {0}.</value> <value>Статистика для настраиваемой реакции {0} очищена.</value>
</data> </data>
<data name="customreactions_stats_not_found" xml:space="preserve"> <data name="customreactions_stats_not_found" xml:space="preserve">
<value>Не найдено статистики для этого активатора, никаких действий не применено.</value> <value>Не найдено статистики для этого активатора, никаких действий не применено.</value>
@ -226,10 +226,10 @@
<value>Активатор</value> <value>Активатор</value>
</data> </data>
<data name="nsfw_autohentai_stopped" xml:space="preserve"> <data name="nsfw_autohentai_stopped" xml:space="preserve">
<value>Авто-хентай остановлен :(</value> <value>Авто-хентай остановлен.</value>
</data> </data>
<data name="nsfw_not_found" xml:space="preserve"> <data name="nsfw_not_found" xml:space="preserve">
<value>Запрос не найден.</value> <value>Результатов не найдено.</value>
</data> </data>
<data name="pokemon_already_fainted" xml:space="preserve"> <data name="pokemon_already_fainted" xml:space="preserve">
<value>{0} уже потерял сознание.</value> <value>{0} уже потерял сознание.</value>
@ -245,10 +245,10 @@
<comment>Kwoth used punch:type_icon: on Sanity:type_icon: for 50 damage.</comment> <comment>Kwoth used punch:type_icon: on Sanity:type_icon: for 50 damage.</comment>
</data> </data>
<data name="pokemon_cant_attack_again" xml:space="preserve"> <data name="pokemon_cant_attack_again" xml:space="preserve">
<value>Нельзя атаковать два раза подряд.</value> <value>Вы не можете атаковать два раза подряд.</value>
</data> </data>
<data name="pokemon_cant_attack_yourself" xml:space="preserve"> <data name="pokemon_cant_attack_yourself" xml:space="preserve">
<value>Нельзя атаковать самого себя.</value> <value>Вы не можете атаковать самого себя.</value>
</data> </data>
<data name="pokemon_fainted" xml:space="preserve"> <data name="pokemon_fainted" xml:space="preserve">
<value>{0} потерял сознание!</value> <value>{0} потерял сознание!</value>
@ -287,7 +287,7 @@
<value>Эта атака очень эффективна!</value> <value>Эта атака очень эффективна!</value>
</data> </data>
<data name="pokemon_too_many_moves" xml:space="preserve"> <data name="pokemon_too_many_moves" xml:space="preserve">
<value>Вы использовали слишком много приёмов подряд и не можете двигаться!</value> <value>Вы использовали слишком много приёмов подряд, поэтому вы не можете двигаться!</value>
</data> </data>
<data name="pokemon_type_of_user" xml:space="preserve"> <data name="pokemon_type_of_user" xml:space="preserve">
<value>Тип {0} — {1}</value> <value>Тип {0} — {1}</value>
@ -296,7 +296,7 @@
<value>Пользователь не найден.</value> <value>Пользователь не найден.</value>
</data> </data>
<data name="pokemon_you_fainted" xml:space="preserve"> <data name="pokemon_you_fainted" xml:space="preserve">
<value>Вы не можете использовать приёмы потому-что ваш покемон потерял сознание!</value> <value>Вы потеряли сознание, поэтому вы не можете двигаться!</value>
</data> </data>
<data name="administration_aar_disabled" xml:space="preserve"> <data name="administration_aar_disabled" xml:space="preserve">
<value>***Авто выдача роли*** каждому новому пользователю **отключена**</value> <value>***Авто выдача роли*** каждому новому пользователю **отключена**</value>
@ -305,13 +305,13 @@
<value>***Авто выдача роли*** каждому новому пользователю **включена**</value> <value>***Авто выдача роли*** каждому новому пользователю **включена**</value>
</data> </data>
<data name="administration_attachments" xml:space="preserve"> <data name="administration_attachments" xml:space="preserve">
<value>Приложения</value> <value>Вложения</value>
</data> </data>
<data name="administration_avatar_changed" xml:space="preserve"> <data name="administration_avatar_changed" xml:space="preserve">
<value>Аватар изменён</value> <value>Аватар изменён</value>
</data> </data>
<data name="administration_bandm" xml:space="preserve"> <data name="administration_bandm" xml:space="preserve">
<value>Вас забанили с сервера {0}. Причина бана: {1}.</value> <value>Вы были забанены на сервере {0}. Причина бана: {1}.</value>
</data> </data>
<data name="administration_banned_pl" xml:space="preserve"> <data name="administration_banned_pl" xml:space="preserve">
<value>забанены</value> <value>забанены</value>
@ -321,10 +321,10 @@
<value>Пользователь забанен.</value> <value>Пользователь забанен.</value>
</data> </data>
<data name="administration_bot_name" xml:space="preserve"> <data name="administration_bot_name" xml:space="preserve">
<value>Имя Бот-а сменено на {0}</value> <value>Имя бота изменено на {0}</value>
</data> </data>
<data name="administration_bot_status" xml:space="preserve"> <data name="administration_bot_status" xml:space="preserve">
<value>Статус Бот-а сменён на {0}</value> <value>Статус бота изменен на {0}</value>
</data> </data>
<data name="administration_byedel_off" xml:space="preserve"> <data name="administration_byedel_off" xml:space="preserve">
<value>Автоматическое удаление прощальных сообщений отключено.</value> <value>Автоматическое удаление прощальных сообщений отключено.</value>
@ -339,7 +339,7 @@
<value>Чтобы включить прощальные сообщения введите {0}</value> <value>Чтобы включить прощальные сообщения введите {0}</value>
</data> </data>
<data name="administration_byemsg_new" xml:space="preserve"> <data name="administration_byemsg_new" xml:space="preserve">
<value>Установлено новое прощальное сообщение.</value> <value>Новое прощальное сообщение было установлено.</value>
</data> </data>
<data name="administration_bye_off" xml:space="preserve"> <data name="administration_bye_off" xml:space="preserve">
<value>Прощальные сообщения выключены.</value> <value>Прощальные сообщения выключены.</value>
@ -348,13 +348,13 @@
<value>Прощальные сообщения включены на этом канале.</value> <value>Прощальные сообщения включены на этом канале.</value>
</data> </data>
<data name="administration_ch_name_change" xml:space="preserve"> <data name="administration_ch_name_change" xml:space="preserve">
<value>Имя канал изменено.</value> <value>Имя канала изменено</value>
</data> </data>
<data name="administration_ch_old_name" xml:space="preserve"> <data name="administration_ch_old_name" xml:space="preserve">
<value>Старое имя.</value> <value>Старое имя.</value>
</data> </data>
<data name="administration_ch_topic_change" xml:space="preserve"> <data name="administration_ch_topic_change" xml:space="preserve">
<value>Тема канала сменена.</value> <value>Тема канала изменена</value>
</data> </data>
<data name="administration_cleaned_up" xml:space="preserve"> <data name="administration_cleaned_up" xml:space="preserve">
<value>Чат очищен.</value> <value>Чат очищен.</value>
@ -363,13 +363,13 @@
<value>Содержание</value> <value>Содержание</value>
</data> </data>
<data name="administration_cr" xml:space="preserve"> <data name="administration_cr" xml:space="preserve">
<value>Успешно создана роль {0}.</value> <value>Роль {0} создана успешно</value>
</data> </data>
<data name="administration_createtextchan" xml:space="preserve"> <data name="administration_createtextchan" xml:space="preserve">
<value>Создан текстовый канал {0}.</value> <value>Текстовый канал {0} создан.</value>
</data> </data>
<data name="administration_createvoich" xml:space="preserve"> <data name="administration_createvoich" xml:space="preserve">
<value>Создан голосовой канал {0}.</value> <value>Голосовой канал {0} создан.</value>
</data> </data>
<data name="administration_deafen" xml:space="preserve"> <data name="administration_deafen" xml:space="preserve">
<value>Успешное оглушение.</value> <value>Успешное оглушение.</value>
@ -381,22 +381,22 @@
<value>Отключено автоматическое удаление успешно выполненных команд.</value> <value>Отключено автоматическое удаление успешно выполненных команд.</value>
</data> </data>
<data name="administration_delmsg_on" xml:space="preserve"> <data name="administration_delmsg_on" xml:space="preserve">
<value>Включено автоматическое удаление успешно выполненных команд.</value> <value>Включено автоматическое удаление сообщений для успешно выполненных команд.</value>
</data> </data>
<data name="administration_deltextchan" xml:space="preserve"> <data name="administration_deltextchan" xml:space="preserve">
<value>Удалён текстовый канал {0}.</value> <value>Текстовый канал {0} удален.</value>
</data> </data>
<data name="administration_delvoich" xml:space="preserve"> <data name="administration_delvoich" xml:space="preserve">
<value>Удален голосовой канал {0}.</value> <value>Голосовой канал {0} удален.</value>
</data> </data>
<data name="administration_dm_from" xml:space="preserve"> <data name="administration_dm_from" xml:space="preserve">
<value>ПМ от</value> <value>ЛС от</value>
</data> </data>
<data name="administration_donadd" xml:space="preserve"> <data name="administration_donadd" xml:space="preserve">
<value>Успешно добавлен новый донатор. Общее количество пожертвований от этого пользователя: {0} 👑</value> <value>Успешно добавлен новый донатор. Общее количество пожертвований от этого пользователя: {0} 👑</value>
</data> </data>
<data name="administration_donators" xml:space="preserve"> <data name="administration_donators" xml:space="preserve">
<value>Спасибо всем, указанным ниже, что помогли этому проекту!</value> <value>Спасибо ниже перечисленным людям за помощь в развитии этого проекта!</value>
</data> </data>
<data name="administration_fwall_start" xml:space="preserve"> <data name="administration_fwall_start" xml:space="preserve">
<value>Я буду перенаправлять личные сообщения всем владельцам.</value> <value>Я буду перенаправлять личные сообщения всем владельцам.</value>
@ -405,10 +405,10 @@
<value>Я буду перенаправлять личные сообщения только первому владельцу.</value> <value>Я буду перенаправлять личные сообщения только первому владельцу.</value>
</data> </data>
<data name="administration_fwdm_start" xml:space="preserve"> <data name="administration_fwdm_start" xml:space="preserve">
<value>Я буду перенаправлять личные сообщения.</value> <value>Теперь я буду перенаправлять ЛС.</value>
</data> </data>
<data name="administration_fwdm_stop" xml:space="preserve"> <data name="administration_fwdm_stop" xml:space="preserve">
<value>Я прекращаю перенаправление личных сообщений.</value> <value>Теперь я прекращу перенаправлять ЛС.</value>
</data> </data>
<data name="administration_greetdel_off" xml:space="preserve"> <data name="administration_greetdel_off" xml:space="preserve">
<value>Автоматическое удаление приветственных сообщений выключено.</value> <value>Автоматическое удаление приветственных сообщений выключено.</value>
@ -417,10 +417,10 @@
<value>Приветственные сообщения будут удаляться через {0} секунд.</value> <value>Приветственные сообщения будут удаляться через {0} секунд.</value>
</data> </data>
<data name="administration_greetdmmsg_cur" xml:space="preserve"> <data name="administration_greetdmmsg_cur" xml:space="preserve">
<value>Приветственное ЛС, используемое в настоящий момент: {0}</value> <value>Текущее приветственное ЛС: {0}</value>
</data> </data>
<data name="administration_greetdmmsg_enable" xml:space="preserve"> <data name="administration_greetdmmsg_enable" xml:space="preserve">
<value>Чтобы включить приветственное ЛС, напишите {0}</value> <value>Включите приветственные ЛС, написав {0}</value>
</data> </data>
<data name="administration_greetdmmsg_new" xml:space="preserve"> <data name="administration_greetdmmsg_new" xml:space="preserve">
<value>Новое приветственное ЛС установлено.</value> <value>Новое приветственное ЛС установлено.</value>
@ -432,19 +432,19 @@
<value>Приветственные ЛС включены.</value> <value>Приветственные ЛС включены.</value>
</data> </data>
<data name="administration_greetmsg_cur" xml:space="preserve"> <data name="administration_greetmsg_cur" xml:space="preserve">
<value>Текущее привественное сообщение: {0}</value> <value>Текущее приветственное сообщение: {0}</value>
</data> </data>
<data name="administration_greetmsg_enable" xml:space="preserve"> <data name="administration_greetmsg_enable" xml:space="preserve">
<value>Чтобы включить привественные сообщения введите {0}</value> <value>Чтобы включить приветственные сообщения введите {0}</value>
</data> </data>
<data name="administration_greetmsg_new" xml:space="preserve"> <data name="administration_greetmsg_new" xml:space="preserve">
<value>Установлено новое приветствие.</value> <value>Новое приветственное сообщение установлено.</value>
</data> </data>
<data name="administration_greet_off" xml:space="preserve"> <data name="administration_greet_off" xml:space="preserve">
<value>Привественные сообщения выключены.</value> <value>Приветственные сообщения выключены.</value>
</data> </data>
<data name="administration_greet_on" xml:space="preserve"> <data name="administration_greet_on" xml:space="preserve">
<value>Привественные сообщения включены на этом канале.</value> <value>Приветственные сообщения включены на этом канале.</value>
</data> </data>
<data name="administration_hierarchy" xml:space="preserve"> <data name="administration_hierarchy" xml:space="preserve">
<value>Вы не можете использовать эту команду на пользователях равным или более высоким в иерархии ролей.</value> <value>Вы не можете использовать эту команду на пользователях равным или более высоким в иерархии ролей.</value>
@ -463,29 +463,28 @@
</data> </data>
<data name="administration_kickdm" xml:space="preserve"> <data name="administration_kickdm" xml:space="preserve">
<value>Вы были выгнаны с сервера {0}. <value>Вы были выгнаны с сервера {0}.
По причине: {1}</value> Причина: {1}</value>
</data> </data>
<data name="administration_kicked_user" xml:space="preserve"> <data name="administration_kicked_user" xml:space="preserve">
<value>Пользователь выгнан</value> <value>Пользователь выгнан</value>
</data> </data>
<data name="administration_lang_list" xml:space="preserve"> <data name="administration_lang_list" xml:space="preserve">
<value>Список языков <value>Список языков</value>
{0}</value>
</data> </data>
<data name="administration_lang_set" xml:space="preserve"> <data name="administration_lang_set" xml:space="preserve">
<value>Язык вашего сервера теперь {0} - {1}</value> <value>Язык вашего сервера теперь {0} - {1}</value>
</data> </data>
<data name="administration_lang_set_bot" xml:space="preserve"> <data name="administration_lang_set_bot" xml:space="preserve">
<value>Язык Бот-а по умолчанию теперь {0} - {1}</value> <value>Язык бота по умолчанию теперь {0} - {1}</value>
</data> </data>
<data name="administration_lang_set_bot_show" xml:space="preserve"> <data name="administration_lang_set_bot_show" xml:space="preserve">
<value>Язык Бот-а теперь установлен как {0} - {1}</value> <value>Язык бота установлен как {0} - {1}</value>
</data> </data>
<data name="administration_lang_set_fail" xml:space="preserve"> <data name="administration_lang_set_fail" xml:space="preserve">
<value>Не удалось выставить язык. Проверьте справку к этой команде.</value> <value>Не удалось выставить язык. Проверьте справку к этой команде.</value>
</data> </data>
<data name="administration_lang_set_show" xml:space="preserve"> <data name="administration_lang_set_show" xml:space="preserve">
<value>Язык этого сервера теперь установлен как {00} - {1}</value> <value>Язык этого сервера установлен как {0} - {1}</value>
</data> </data>
<data name="administration_left" xml:space="preserve"> <data name="administration_left" xml:space="preserve">
<value>{0} покинул {1}</value> <value>{0} покинул {1}</value>
@ -506,10 +505,10 @@
<value>Регистрируйте события, на которые Вы можете подписаться:</value> <value>Регистрируйте события, на которые Вы можете подписаться:</value>
</data> </data>
<data name="administration_log_ignore" xml:space="preserve"> <data name="administration_log_ignore" xml:space="preserve">
<value>Регистрация будет пропускать {0}.</value> <value>Регистрация будет игнорировать {0}.</value>
</data> </data>
<data name="administration_log_not_ignore" xml:space="preserve"> <data name="administration_log_not_ignore" xml:space="preserve">
<value>Регистрация не будет пропускать {0}.</value> <value>Регистрация не будет игнорировать {0}.</value>
</data> </data>
<data name="administration_log_stop" xml:space="preserve"> <data name="administration_log_stop" xml:space="preserve">
<value>Прекращена регистрация события {0}.</value> <value>Прекращена регистрация события {0}.</value>
@ -541,7 +540,7 @@
<comment>singular &quot;User muted.&quot;</comment> <comment>singular &quot;User muted.&quot;</comment>
</data> </data>
<data name="administration_mute_error" xml:space="preserve"> <data name="administration_mute_error" xml:space="preserve">
<value>Скорее всего, у меня нет необходимых прав.</value> <value>Похоже, у меня нет необходимых прав.</value>
</data> </data>
<data name="administration_mute_role_set" xml:space="preserve"> <data name="administration_mute_role_set" xml:space="preserve">
<value>Новая роль заглушения установлена.</value> <value>Новая роль заглушения установлена.</value>
@ -562,7 +561,7 @@
<value>Имя изменено</value> <value>Имя изменено</value>
</data> </data>
<data name="administration_no_server" xml:space="preserve"> <data name="administration_no_server" xml:space="preserve">
<value>Сервер не найден</value> <value>Не могу найти этот сервер</value>
</data> </data>
<data name="administration_no_shard_id" xml:space="preserve"> <data name="administration_no_shard_id" xml:space="preserve">
<value>Не найдено Shard-а с таким ID.</value> <value>Не найдено Shard-а с таким ID.</value>
@ -580,7 +579,7 @@
<value>Ошибка. Скорее всего мне не хватает прав.</value> <value>Ошибка. Скорее всего мне не хватает прав.</value>
</data> </data>
<data name="administration_perms_reset" xml:space="preserve"> <data name="administration_perms_reset" xml:space="preserve">
<value>Права для этого сервера </value> <value>Права для этого сервера были сброшены.</value>
</data> </data>
<data name="administration_prot_active" xml:space="preserve"> <data name="administration_prot_active" xml:space="preserve">
<value>Активные защиты от рейдов</value> <value>Активные защиты от рейдов</value>
@ -589,13 +588,13 @@
<value>{0} был **отключён** на этом сервере.</value> <value>{0} был **отключён** на этом сервере.</value>
</data> </data>
<data name="administration_prot_enable" xml:space="preserve"> <data name="administration_prot_enable" xml:space="preserve">
<value>{0} влючён</value> <value>{0} включен</value>
</data> </data>
<data name="administration_prot_error" xml:space="preserve"> <data name="administration_prot_error" xml:space="preserve">
<value>Ошибка. Требуется право на управление ролями.</value> <value>Ошибка. Требуется право на управление ролями.</value>
</data> </data>
<data name="administration_prot_none" xml:space="preserve"> <data name="administration_prot_none" xml:space="preserve">
<value>Нет защит от рейдов</value> <value>Защита от рейдов отключена.</value>
</data> </data>
<data name="administration_raid_cnt" xml:space="preserve"> <data name="administration_raid_cnt" xml:space="preserve">
<value>Порог пользователей должен лежать между {0} и {1}.</value> <value>Порог пользователей должен лежать между {0} и {1}.</value>
@ -607,7 +606,8 @@
<value>Время должно быть между {0} и {1} секунд.</value> <value>Время должно быть между {0} и {1} секунд.</value>
</data> </data>
<data name="administration_rar" xml:space="preserve"> <data name="administration_rar" xml:space="preserve">
<value>Успешно убраны все роли пользователя {0}.</value> <value>Все роли пользователя {0} были успешно убраны с него</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_rar_err" xml:space="preserve"> <data name="administration_rar_err" xml:space="preserve">
<value>Не удалось убрать роли. Отсутвуют требуемые разрешения.</value> <value>Не удалось убрать роли. Отсутвуют требуемые разрешения.</value>
@ -641,12 +641,13 @@
</data> </data>
<data name="administration_reprm" xml:space="preserve"> <data name="administration_reprm" xml:space="preserve">
<value>Удалено повторяющееся сообщение: {0}</value> <value>Удалено повторяющееся сообщение: {0}</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="administration_role_added" xml:space="preserve"> <data name="administration_role_added" xml:space="preserve">
<value>Роль {0} добавлена в лист.</value> <value>Роль {0} добавлена в лист.</value>
</data> </data>
<data name="administration_role_clean" xml:space="preserve"> <data name="administration_role_clean" xml:space="preserve">
<value>{0} не найдена. Чат очищен.</value> <value>Роль {0} не найдена. Чат очищен.</value>
</data> </data>
<data name="administration_role_in_list" xml:space="preserve"> <data name="administration_role_in_list" xml:space="preserve">
<value>Роль {0} уже есть в списке.</value> <value>Роль {0} уже есть в списке.</value>
@ -655,10 +656,10 @@
<value>Добавлено.</value> <value>Добавлено.</value>
</data> </data>
<data name="administration_ropl_disabled" xml:space="preserve"> <data name="administration_ropl_disabled" xml:space="preserve">
<value>Отключены чередующиеся статусы.</value> <value>Чередующиеся статусы отключены.</value>
</data> </data>
<data name="administration_ropl_enabled" xml:space="preserve"> <data name="administration_ropl_enabled" xml:space="preserve">
<value>Чередующиеся статусы отключены.</value> <value>Чередующиеся статусы включены.</value>
</data> </data>
<data name="administration_ropl_list" xml:space="preserve"> <data name="administration_ropl_list" xml:space="preserve">
<value>Список чередующихся статусов: <value>Список чередующихся статусов:
@ -671,7 +672,8 @@
<value>У вас уже есть роль {0}</value> <value>У вас уже есть роль {0}</value>
</data> </data>
<data name="administration_self_assign_already_excl" xml:space="preserve"> <data name="administration_self_assign_already_excl" xml:space="preserve">
<value>У Вас уже есть исключающая самоназначенная роль {0}.</value> <value>У Вас уже есть исключенная самоназначенная роль {0}.</value>
<comment>Я не понял что значит &quot;исключающая&quot;, заменил на &quot;исключенная&quot;.</comment>
</data> </data>
<data name="administration_self_assign_excl" xml:space="preserve"> <data name="administration_self_assign_excl" xml:space="preserve">
<value>Самоназначенные роли теперь взаимоисключающие!</value> <value>Самоназначенные роли теперь взаимоисключающие!</value>
@ -692,10 +694,10 @@
<value>Не удалось добавить Вам эту роль. &apos;Нельзя добавлять роли владельцам или другим ролям, находящимся выше моей роли в ролевой иерархии&apos;</value> <value>Не удалось добавить Вам эту роль. &apos;Нельзя добавлять роли владельцам или другим ролям, находящимся выше моей роли в ролевой иерархии&apos;</value>
</data> </data>
<data name="administration_self_assign_rem" xml:space="preserve"> <data name="administration_self_assign_rem" xml:space="preserve">
<value>{0} убрана из списка самоназначенных ролей.</value> <value>Роль {0} убрана из списка самоназначаемых ролей.</value>
</data> </data>
<data name="administration_self_assign_remove" xml:space="preserve"> <data name="administration_self_assign_remove" xml:space="preserve">
<value>У вас больше нету роли {0}</value> <value>У вас больше нет роли {0}</value>
</data> </data>
<data name="administration_self_assign_success" xml:space="preserve"> <data name="administration_self_assign_success" xml:space="preserve">
<value>Теперь у вас есть роль {0}</value> <value>Теперь у вас есть роль {0}</value>
@ -704,7 +706,7 @@
<value>Успешно добавлена роль {0} пользователю {1}</value> <value>Успешно добавлена роль {0} пользователю {1}</value>
</data> </data>
<data name="administration_setrole_err" xml:space="preserve"> <data name="administration_setrole_err" xml:space="preserve">
<value>Не удалось добавить роль. Нет достаточных разрешений.</value> <value>Не удалось добавить роль. Недостаточно прав.</value>
</data> </data>
<data name="administration_set_avatar" xml:space="preserve"> <data name="administration_set_avatar" xml:space="preserve">
<value>Новый аватар установлен!</value> <value>Новый аватар установлен!</value>
@ -716,7 +718,7 @@
<value>Новая игра установлена!</value> <value>Новая игра установлена!</value>
</data> </data>
<data name="administration_set_stream" xml:space="preserve"> <data name="administration_set_stream" xml:space="preserve">
<value>Новый стрим установлен!</value> <value>Новая трансляция установлена!</value>
</data> </data>
<data name="administration_set_topic" xml:space="preserve"> <data name="administration_set_topic" xml:space="preserve">
<value>Новая тема канала установлена.</value> <value>Новая тема канала установлена.</value>
@ -731,13 +733,13 @@
<value>Выключение</value> <value>Выключение</value>
</data> </data>
<data name="administration_slowmode_desc" xml:space="preserve"> <data name="administration_slowmode_desc" xml:space="preserve">
<value>Пользователи не могут посылать более {0} сообщений в {1} секунд.</value> <value>Пользователи не могут писать более {0} сообщений в {1} секунд.</value>
</data> </data>
<data name="administration_slowmode_disabled" xml:space="preserve"> <data name="administration_slowmode_disabled" xml:space="preserve">
<value>Медленный режим выключен.</value> <value>Медленный режим выключен.</value>
</data> </data>
<data name="administration_slowmode_init" xml:space="preserve"> <data name="administration_slowmode_init" xml:space="preserve">
<value>Медленный режим включен.</value> <value>Медленный режим включен</value>
</data> </data>
<data name="administration_soft_banned_pl" xml:space="preserve"> <data name="administration_soft_banned_pl" xml:space="preserve">
<value>выгнаны</value> <value>выгнаны</value>
@ -753,7 +755,7 @@
<value>Если пользователь пишет {0} одинаковых сообщений подряд, я {} их. __Игнорируемые каналы__: {2}</value> <value>Если пользователь пишет {0} одинаковых сообщений подряд, я {} их. __Игнорируемые каналы__: {2}</value>
</data> </data>
<data name="administration_text_chan_created" xml:space="preserve"> <data name="administration_text_chan_created" xml:space="preserve">
<value>Создан текстовый канал</value> <value>Создан текстовый канал.</value>
</data> </data>
<data name="administration_text_chan_destroyed" xml:space="preserve"> <data name="administration_text_chan_destroyed" xml:space="preserve">
<value>Уничтожен текстовый канал.</value> <value>Уничтожен текстовый канал.</value>
@ -763,8 +765,7 @@
</data> </data>
<data name="administration_unmuted_sn" xml:space="preserve"> <data name="administration_unmuted_sn" xml:space="preserve">
<value>Вернут звук</value> <value>Вернут звук</value>
<comment>singular <comment>singular</comment>
Fuzzy</comment>
</data> </data>
<data name="administration_username" xml:space="preserve"> <data name="administration_username" xml:space="preserve">
<value>Имя</value> <value>Имя</value>
@ -791,7 +792,7 @@ Fuzzy</comment>
<value>Пользователь вышел</value> <value>Пользователь вышел</value>
</data> </data>
<data name="administration_user_muted" xml:space="preserve"> <data name="administration_user_muted" xml:space="preserve">
<value>{0} получил **запрет** на разговор в текстовых и голосовых каналах</value> <value>{0} получил **запрет** на разговор в текстовых и голосовых каналах.</value>
</data> </data>
<data name="administration_user_role_add" xml:space="preserve"> <data name="administration_user_role_add" xml:space="preserve">
<value>Добавлена роль пользователя</value> <value>Добавлена роль пользователя</value>
@ -812,7 +813,8 @@ Fuzzy</comment>
<value>{0} покинул голосовой канал {1}.</value> <value>{0} покинул голосовой канал {1}.</value>
</data> </data>
<data name="administration_user_vmoved" xml:space="preserve"> <data name="administration_user_vmoved" xml:space="preserve">
<value>{0} переместил из голосового канала {1} в {2}.</value> <value>{0} переместился из голосового канала {1} в {2}.</value>
<comment>Забыли &quot;ся&quot; в &quot;переместил&quot;</comment>
</data> </data>
<data name="administration_user_voice_mute" xml:space="preserve"> <data name="administration_user_voice_mute" xml:space="preserve">
<value>**Выключен микрофон** у {0}.</value> <value>**Выключен микрофон** у {0}.</value>
@ -833,10 +835,10 @@ Fuzzy</comment>
<value>Включены голосовые + текстовые функции.</value> <value>Включены голосовые + текстовые функции.</value>
</data> </data>
<data name="administration_vt_exit" xml:space="preserve"> <data name="administration_vt_exit" xml:space="preserve">
<value>Нет разрешений **Управление ролями** и/или **Управление каналами**, поэтому нельзя использовать команду &apos;voice+text&apos; на сервере {0}.</value> <value>Нет разрешения на **Управление ролями** и/или **Управление каналами**, поэтому нельзя использовать команду &apos;voice+text&apos; на сервере {0}.</value>
</data> </data>
<data name="administration_vt_no_admin" xml:space="preserve"> <data name="administration_vt_no_admin" xml:space="preserve">
<value>Вы пытаетесь включить/отключить это свойство и **отсутвует разрешение АДМИНИСТРАТОР**. Это может вызвать ошибки, и Вам придётся удалять текст в текстовых каналах самостоятельно.</value> <value>Вы пытаетесь включить/отключить это свойство и **отсутствует разрешение АДМИНИСТРАТОР**. Это может вызвать ошибки, и вам придётся удалять текст в текстовых каналах самостоятельно.</value>
</data> </data>
<data name="administration_vt_perms" xml:space="preserve"> <data name="administration_vt_perms" xml:space="preserve">
<value>Для этого свойства требуются как минимум разрешения **управление ролями** и **управление каналами**. (Рекомендуется разрешение Администратор)</value> <value>Для этого свойства требуются как минимум разрешения **управление ролями** и **управление каналами**. (Рекомендуется разрешение Администратор)</value>
@ -908,7 +910,7 @@ Fuzzy</comment>
<comment>X has Y flowers</comment> <comment>X has Y flowers</comment>
</data> </data>
<data name="gambling_heads" xml:space="preserve"> <data name="gambling_heads" xml:space="preserve">
<value>Орёл</value> <value>Решка</value>
</data> </data>
<data name="gambling_leaderboard" xml:space="preserve"> <data name="gambling_leaderboard" xml:space="preserve">
<value>Таблица рекордов</value> <value>Таблица рекордов</value>
@ -930,6 +932,7 @@ Fuzzy</comment>
</data> </data>
<data name="gambling_raffled_user" xml:space="preserve"> <data name="gambling_raffled_user" xml:space="preserve">
<value>Победитель лотереи</value> <value>Победитель лотереи</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="gambling_roll" xml:space="preserve"> <data name="gambling_roll" xml:space="preserve">
<value>Вам выпало {0}.</value> <value>Вам выпало {0}.</value>
@ -962,7 +965,7 @@ Fuzzy</comment>
<value>Началось событие SneakyGameStatus</value> <value>Началось событие SneakyGameStatus</value>
</data> </data>
<data name="gambling_tails" xml:space="preserve"> <data name="gambling_tails" xml:space="preserve">
<value>Решка</value> <value>Орёл</value>
</data> </data>
<data name="gambling_take" xml:space="preserve"> <data name="gambling_take" xml:space="preserve">
<value>успешно забрал {0} у {1}</value> <value>успешно забрал {0} у {1}</value>
@ -984,6 +987,7 @@ Fuzzy</comment>
</data> </data>
<data name="help_cmd_and_alias" xml:space="preserve"> <data name="help_cmd_and_alias" xml:space="preserve">
<value>Команды и альтернативные имена команд</value> <value>Команды и альтернативные имена команд</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="help_commandlist_regen" xml:space="preserve"> <data name="help_commandlist_regen" xml:space="preserve">
<value>Список команд создан.</value> <value>Список команд создан.</value>
@ -1089,10 +1093,10 @@ Paypal &lt;{1}&gt;
</data> </data>
<data name="gambling_changes_of_heart" xml:space="preserve"> <data name="gambling_changes_of_heart" xml:space="preserve">
<value>Смены чувств</value> <value>Смены чувств</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="gambling_claimed_by" xml:space="preserve"> <data name="gambling_claimed_by" xml:space="preserve">
<value>Является мужем</value> <value>Является мужем</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="gambling_divorces" xml:space="preserve"> <data name="gambling_divorces" xml:space="preserve">
<value>Разводы</value> <value>Разводы</value>
@ -1115,7 +1119,7 @@ Paypal &lt;{1}&gt;
<data name="gambling_waifu_affinity_changed" xml:space="preserve"> <data name="gambling_waifu_affinity_changed" xml:space="preserve">
<value>сменил свою предрасположенность с {0} на {1}. <value>сменил свою предрасположенность с {0} на {1}.
*Это сомнительно с точки зрения морали* :thinking:</value> *Это сомнительно с моральной точки зрения* :thinking:</value>
<comment>Make sure to get the formatting right, and leave the thinking emoji</comment> <comment>Make sure to get the formatting right, and leave the thinking emoji</comment>
</data> </data>
<data name="gambling_waifu_affinity_cooldown" xml:space="preserve"> <data name="gambling_waifu_affinity_cooldown" xml:space="preserve">
@ -1234,11 +1238,11 @@ Paypal &lt;{1}&gt;
<value>В этом канале включено появление валюты.</value> <value>В этом канале включено появление валюты.</value>
</data> </data>
<data name="games_curgen_pl" xml:space="preserve"> <data name="games_curgen_pl" xml:space="preserve">
<value>{0} случайных {1} появились! Напишите &apos;{2}pick&apos;, чтобы собрать их.</value> <value>{0} случайных {1} появились!</value>
<comment>plural</comment> <comment>plural</comment>
</data> </data>
<data name="games_curgen_sn" xml:space="preserve"> <data name="games_curgen_sn" xml:space="preserve">
<value>Случайный {0} появился! Напишите &apos;{1}pick&apos;, чтобы собрать его.</value> <value>Случайный {0} появился!</value>
</data> </data>
<data name="games_failed_loading_question" xml:space="preserve"> <data name="games_failed_loading_question" xml:space="preserve">
<value>Не удалось загрузить вопрос.</value> <value>Не удалось загрузить вопрос.</value>
@ -1352,7 +1356,8 @@ Paypal &lt;{1}&gt;
</data> </data>
<data name="music_fp_disabled" xml:space="preserve"> <data name="music_fp_disabled" xml:space="preserve">
<value>Отключено справедливое воспроизведение.</value> <value>Отключено справедливое воспроизведение.</value>
<comment>Fuzzy</comment> <comment>&quot;Честное воспроизведение&quot; не подойдет?
Fuzzy</comment>
</data> </data>
<data name="music_fp_enabled" xml:space="preserve"> <data name="music_fp_enabled" xml:space="preserve">
<value>Включено справедливое воспроизведение.</value> <value>Включено справедливое воспроизведение.</value>
@ -1447,10 +1452,10 @@ Paypal &lt;{1}&gt;
<value>Повторяется текущая песня.</value> <value>Повторяется текущая песня.</value>
</data> </data>
<data name="music_repeating_playlist" xml:space="preserve"> <data name="music_repeating_playlist" xml:space="preserve">
<value>Повторяется плейлист.</value> <value>Повторяется плейлист</value>
</data> </data>
<data name="music_repeating_track" xml:space="preserve"> <data name="music_repeating_track" xml:space="preserve">
<value>Повторяется песня.</value> <value>Повторяется песня</value>
</data> </data>
<data name="music_repeating_track_stopped" xml:space="preserve"> <data name="music_repeating_track_stopped" xml:space="preserve">
<value>Повтор текущей песни приостановлен.</value> <value>Повтор текущей песни приостановлен.</value>
@ -1471,10 +1476,10 @@ Paypal &lt;{1}&gt;
<value>Пропускаю до &apos;{0}:{1}&apos;</value> <value>Пропускаю до &apos;{0}:{1}&apos;</value>
</data> </data>
<data name="music_songs_shuffled" xml:space="preserve"> <data name="music_songs_shuffled" xml:space="preserve">
<value>Песни перемешаны.</value> <value>Песни перемешаны</value>
</data> </data>
<data name="music_song_moved" xml:space="preserve"> <data name="music_song_moved" xml:space="preserve">
<value>Песня перемещена.</value> <value>Песня перемещена</value>
</data> </data>
<data name="music_time_format" xml:space="preserve"> <data name="music_time_format" xml:space="preserve">
<value>{0}ч {1}м {2}с</value> <value>{0}ч {1}м {2}с</value>
@ -1526,18 +1531,19 @@ Paypal &lt;{1}&gt;
</data> </data>
<data name="permissions_cmdcd_cleared" xml:space="preserve"> <data name="permissions_cmdcd_cleared" xml:space="preserve">
<value>У команды {0} больше нет времени перезарядки и все существующие времена перезадки были сброшены.</value> <value>У команды {0} больше нет времени перезарядки и все существующие времена перезадки были сброшены.</value>
<comment>Fuzzy</comment>
</data> </data>
<data name="permissions_cmdcd_none" xml:space="preserve"> <data name="permissions_cmdcd_none" xml:space="preserve">
<value>У команды не установлено время перезарядки.</value> <value>У команды не установлено время перезарядки.</value>
</data> </data>
<data name="permissions_command_costs" xml:space="preserve"> <data name="permissions_command_costs" xml:space="preserve">
<value>Стоимость команды</value> <value>Стоимость команд</value>
</data> </data>
<data name="permissions_cx_disable" xml:space="preserve"> <data name="permissions_cx_disable" xml:space="preserve">
<value>Отключено использование {0} {1} в канале {2}</value> <value>Отключено использование {0} {1} в канале {2}.</value>
</data> </data>
<data name="permissions_cx_enable" xml:space="preserve"> <data name="permissions_cx_enable" xml:space="preserve">
<value>Включено использование {0} {1} в канале {2}</value> <value>Включено использование {0} {1} в канале {2}.</value>
</data> </data>
<data name="permissions_denied" xml:space="preserve"> <data name="permissions_denied" xml:space="preserve">
<value>Отказано</value> <value>Отказано</value>
@ -1681,10 +1687,10 @@ Paypal &lt;{1}&gt;
<value>Комикс #</value> <value>Комикс #</value>
</data> </data>
<data name="searches_compet_loses" xml:space="preserve"> <data name="searches_compet_loses" xml:space="preserve">
<value>Поражения в соревновательном режиме</value> <value>Поражений в соревновательном режиме</value>
</data> </data>
<data name="searches_compet_played" xml:space="preserve"> <data name="searches_compet_played" xml:space="preserve">
<value>Матчи в соревновательном режиме</value> <value>Матчей в соревновательном режиме</value>
</data> </data>
<data name="searches_compet_rank" xml:space="preserve"> <data name="searches_compet_rank" xml:space="preserve">
<value>Соревновательный ранг</value> <value>Соревновательный ранг</value>
@ -1820,7 +1826,7 @@ Paypal &lt;{1}&gt;
<value>Качество:</value> <value>Качество:</value>
</data> </data>
<data name="searches_quick_playtime" xml:space="preserve"> <data name="searches_quick_playtime" xml:space="preserve">
<value>Время игры в Быстрой Игре</value> <value>Время в Быстрой игре</value>
<comment>Is this supposed to be Overwatch Quick Play stats?</comment> <comment>Is this supposed to be Overwatch Quick Play stats?</comment>
</data> </data>
<data name="searches_quick_wins" xml:space="preserve"> <data name="searches_quick_wins" xml:space="preserve">
@ -1851,7 +1857,7 @@ Paypal &lt;{1}&gt;
<value>Состояние</value> <value>Состояние</value>
</data> </data>
<data name="searches_store_url" xml:space="preserve"> <data name="searches_store_url" xml:space="preserve">
<value>Url Магазина</value> <value>URL Магазина</value>
</data> </data>
<data name="searches_streamer_offline" xml:space="preserve"> <data name="searches_streamer_offline" xml:space="preserve">
<value>Стример {0} в оффлане.</value> <value>Стример {0} в оффлане.</value>
@ -1920,7 +1926,7 @@ Paypal &lt;{1}&gt;
<value>Страница не найдена.</value> <value>Страница не найдена.</value>
</data> </data>
<data name="searches_wind_speed" xml:space="preserve"> <data name="searches_wind_speed" xml:space="preserve">
<value>Скорость ветра.</value> <value>Скорость ветра</value>
</data> </data>
<data name="searches_x_most_banned_champs" xml:space="preserve"> <data name="searches_x_most_banned_champs" xml:space="preserve">
<value>{0} наиболее часто забаненных чемпионов.</value> <value>{0} наиболее часто забаненных чемпионов.</value>
@ -2000,10 +2006,10 @@ Paypal &lt;{1}&gt;
<value>Указатель вышел за пределы диапазона.</value> <value>Указатель вышел за пределы диапазона.</value>
</data> </data>
<data name="utility_inrole_list" xml:space="preserve"> <data name="utility_inrole_list" xml:space="preserve">
<value>Список пользователей с этими ролями:</value> <value>Список пользователей с ролью {0}:</value>
</data> </data>
<data name="utility_inrole_not_allowed" xml:space="preserve"> <data name="utility_inrole_not_allowed" xml:space="preserve">
<value>Вам запрещено использовать эту комманду в отношении ролей с большим числом пользователей для предотвращения</value> <value>Вам запрещено использовать эту комманду в отношении ролей с большим числом пользователей для предотвращения чрезмерного использования.</value>
</data> </data>
<data name="utility_invalid_value" xml:space="preserve"> <data name="utility_invalid_value" xml:space="preserve">
<value>Неправильное значение {0}.</value> <value>Неправильное значение {0}.</value>
@ -2036,7 +2042,7 @@ IDВладельца: {2}</value>
<value>Сообщения</value> <value>Сообщения</value>
</data> </data>
<data name="utility_message_repeater" xml:space="preserve"> <data name="utility_message_repeater" xml:space="preserve">
<value>Повторяемое сообщения</value> <value>Повторяемые сообщения</value>
</data> </data>
<data name="utility_name" xml:space="preserve"> <data name="utility_name" xml:space="preserve">
<value>Имя</value> <value>Имя</value>
@ -2089,7 +2095,7 @@ IDВладельца: {2}</value>
<value>Цитата добавлена</value> <value>Цитата добавлена</value>
</data> </data>
<data name="utility_quote_deleted" xml:space="preserve"> <data name="utility_quote_deleted" xml:space="preserve">
<value>Случайно выбранная цитата удалена.</value> <value>Цитата #{0} удалена.</value>
</data> </data>
<data name="utility_region" xml:space="preserve"> <data name="utility_region" xml:space="preserve">
<value>Регион</value> <value>Регион</value>
@ -2152,7 +2158,7 @@ IDВладельца: {2}</value>
<value>Shard</value> <value>Shard</value>
</data> </data>
<data name="utility_shard_stats" xml:space="preserve"> <data name="utility_shard_stats" xml:space="preserve">
<value>Статискика Shard-а</value> <value>Статистика Shard-а</value>
</data> </data>
<data name="utility_shard_stats_txt" xml:space="preserve"> <data name="utility_shard_stats_txt" xml:space="preserve">
<value>Shard **#{0}** находится в состоянии {1} с {2} серверами.</value> <value>Shard **#{0}** находится в состоянии {1} с {2} серверами.</value>
@ -2185,5 +2191,105 @@ IDВладельца: {2}</value>
<data name="utility_voice_channels" xml:space="preserve"> <data name="utility_voice_channels" xml:space="preserve">
<value>Голосовые каналы</value> <value>Голосовые каналы</value>
</data> </data>
<data name="gambling_animal_race_already_in" xml:space="preserve">
<value>Вы уже участвуете в этой гонке!</value>
</data>
<data name="games_current_poll_results" xml:space="preserve">
<value>Результаты опроса</value>
</data>
<data name="games_no_votes_cast" xml:space="preserve">
<value>Не получено ни одного ответа.</value>
</data>
<data name="games_poll_already_running" xml:space="preserve">
<value>На данном сервере уже идёт опрос.</value>
</data>
<data name="games_poll_created" xml:space="preserve">
<value>{0} создал опрос, требующий Вашего внимания:</value>
</data>
<data name="games_poll_result" xml:space="preserve">
<value>&apos;{0}.&apos; У {1} {2} голосов.</value>
</data>
<data name="games_poll_voted" xml:space="preserve">
<value>{0} проголосовал.</value>
<comment>Kwoth voted.</comment>
</data>
<data name="games_poll_vote_private" xml:space="preserve">
<value>Отправьте сообщение в этом текстовом канале с номером, соответствующему Вашему ответу.</value>
</data>
<data name="games_poll_vote_public" xml:space="preserve">
<value>Отправьте сообщение в этом текстовом канале с номером, соответствующему Вашему ответу.</value>
</data>
<data name="games_thanks_for_voting" xml:space="preserve">
<value>Спасибо за Ваш ответ, {0}.</value>
</data>
<data name="games_x_votes_cast" xml:space="preserve">
<value>Всего получено {0} ответов.</value>
</data>
<data name="games_pick_pl" xml:space="preserve">
<value>Напишите &apos;{0}pick&apos;, чтобы собрать их</value>
</data>
<data name="games_pick_sn" xml:space="preserve">
<value>Напишите &apos;{0}pick&apos;, чтобы собрать его</value>
</data>
<data name="gambling_no_users_found" xml:space="preserve">
<value>Пользователи не найдены.</value>
</data>
<data name="gambling_page" xml:space="preserve">
<value>Страница {0}</value>
</data>
<data name="administration_must_be_in_voice" xml:space="preserve">
<value>Вы должны быть в голосовом канале на этом сервере.</value>
</data>
<data name="administration_no_vcroles" xml:space="preserve">
<value>Нет ролей для голосовых каналов.</value>
</data>
<data name="administration_user_muted_time" xml:space="preserve">
<value>{0} получил **запрет** на разговор в текстовых и голосовых каналах на {1} минут.</value>
</data>
<data name="administration_vcrole_added" xml:space="preserve">
<value>Пользователи, присоединяющиеся к голосовому каналу {0}, получат роль {1}.</value>
</data>
<data name="administration_vcrole_removed" xml:space="preserve">
<value>Пользователи, присоединяющиеся к голосовому каналу {0}, больше не будут получать роль.</value>
</data>
<data name="administration_vc_role_list" xml:space="preserve">
<value>Роли голосовых каналов</value>
</data>
<data name="customreactions_crad_disabled" xml:space="preserve">
<value>Сообщение, инициирующее настраеваемую реакцию с ИД {0}, не будет автоматически удалено.</value>
<comment>Fuzzy</comment>
</data>
<data name="customreactions_crad_enabled" xml:space="preserve">
<value>Сообщение, инициирующее настраеваемую реакцию с ИД {0}, будет автоматически удалено.</value>
</data>
<data name="customreactions_crdm_disabled" xml:space="preserve">
<value>Ответное сообщение для настраеваемой реакцией с ИД {0} не будет отправлено в ЛС.</value>
</data>
<data name="customreactions_crdm_enabled" xml:space="preserve">
<value>Ответное сообщение для настраиваемой реакцией с ИД {0} будет отправлено в ЛС.</value>
</data>
<data name="utility_aliases_none" xml:space="preserve">
<value>Альтернативная команда не найдена</value>
<comment>Fuzzy</comment>
</data>
<data name="utility_alias_added" xml:space="preserve">
<value>{0} будет теперь альтернативной командой для {1}.</value>
<comment>Fuzzy</comment>
</data>
<data name="utility_alias_list" xml:space="preserve">
<value>Список альтернативных команд</value>
<comment>Fuzzy</comment>
</data>
<data name="utility_alias_removed" xml:space="preserve">
<value>У триггера {0} больше нет альтернативных команд.</value>
<comment>Fuzzy</comment>
</data>
<data name="utility_alias_remove_fail" xml:space="preserve">
<value>У триггера {0} не было альтернативных команд.</value>
<comment>Fuzzy</comment>
</data>
<data name="searches_compet_playtime" xml:space="preserve">
<value>Время в игре</value>
</data>
</root> </root>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,7 @@ using NadekoBot.Modules.CustomReactions;
using NadekoBot.Modules.Games; using NadekoBot.Modules.Games;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Threading; using System.Threading;
using Microsoft.EntityFrameworkCore;
using NadekoBot.DataStructures; using NadekoBot.DataStructures;
namespace NadekoBot.Services namespace NadekoBot.Services
@ -28,11 +29,7 @@ namespace NadekoBot.Services
} }
public class CommandHandler public class CommandHandler
{ {
#if GLOBAL_NADEKO
public const int GlobalCommandsCooldown = 1500;
#else
public const int GlobalCommandsCooldown = 750; public const int GlobalCommandsCooldown = 750;
#endif
private readonly DiscordShardedClient _client; private readonly DiscordShardedClient _client;
private readonly CommandService _commandService; private readonly CommandService _commandService;
@ -273,13 +270,76 @@ namespace NadekoBot.Services
// maybe this message is a custom reaction // maybe this message is a custom reaction
// todo log custom reaction executions. return struct with info // todo log custom reaction executions. return struct with info
var crExecuted = await Task.Run(() => CustomReactions.TryExecuteCustomReaction(usrMsg)).ConfigureAwait(false); var cr = await Task.Run(() => CustomReactions.TryGetCustomReaction(usrMsg)).ConfigureAwait(false);
if (crExecuted) //if it was, don't execute the command if (cr != null) //if it was, don't execute the command
{
try
{
if (guild != null)
{
PermissionCache pc;
if (!Permissions.Cache.TryGetValue(guild.Id, out pc))
{
using (var uow = DbHandler.UnitOfWork())
{
var config = uow.GuildConfigs.For(guild.Id,
set => set.Include(x => x.Permissions));
Permissions.UpdateCache(config);
}
Permissions.Cache.TryGetValue(guild.Id, out pc);
if (pc == null)
throw new Exception("Cache is null.");
}
int index;
if (
!pc.Permissions.CheckPermissions(usrMsg, cr.Trigger, "ActualCustomReactions",
out index))
{
//todo print in guild actually
var returnMsg =
$"Permission number #{index + 1} **{pc.Permissions[index].GetCommand(guild)}** is preventing this action.";
_log.Info(returnMsg);
return; return;
}
}
await cr.Send(usrMsg).ConfigureAwait(false);
if (cr.AutoDeleteTrigger)
{
try { await msg.DeleteAsync().ConfigureAwait(false); } catch { }
}
}
catch (Exception ex)
{
_log.Warn("Sending CREmbed failed");
_log.Warn(ex);
}
return;
}
var exec3 = Environment.TickCount - execTime; var exec3 = Environment.TickCount - execTime;
string messageContent = usrMsg.Content; string messageContent = usrMsg.Content;
if (guild != null)
{
ConcurrentDictionary<string, string> maps;
if (Modules.Utility.Utility.CommandMapCommands.AliasMaps.TryGetValue(guild.Id, out maps))
{
string newMessageContent;
if (maps.TryGetValue(messageContent.Trim().ToLowerInvariant(), out newMessageContent))
{
_log.Info(@"--Mapping Command--
GuildId: {0}
Trigger: {1}
Mapping: {2}", guild.Id, messageContent, newMessageContent);
var oldMessageContent = messageContent;
messageContent = newMessageContent;
try { await usrMsg.Channel.SendConfirmAsync($"{oldMessageContent} => {newMessageContent}").ConfigureAwait(false); } catch { }
}
}
}
// execute the command and measure the time it took // execute the command and measure the time it took
var exec = await Task.Run(() => ExecuteCommand(new CommandContext(_client, usrMsg), messageContent, DependencyMap.Empty, MultiMatchHandling.Best)).ConfigureAwait(false); var exec = await Task.Run(() => ExecuteCommand(new CommandContext(_client, usrMsg), messageContent, DependencyMap.Empty, MultiMatchHandling.Best)).ConfigureAwait(false);
@ -378,28 +438,27 @@ namespace NadekoBot.Services
} }
var cmd = commands[i].Command; var cmd = commands[i].Command;
bool resetCommand = cmd.Name == "resetperms"; var resetCommand = cmd.Name == "resetperms";
var module = cmd.Module.GetTopLevelModule(); var module = cmd.Module.GetTopLevelModule();
PermissionCache pc; PermissionCache pc;
if (context.Guild != null) if (context.Guild != null)
{ {
pc = Permissions.Cache.GetOrAdd(context.Guild.Id, (id) => //todo move to permissions module?
if (!Permissions.Cache.TryGetValue(context.Guild.Id, out pc))
{ {
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.PermissionsFor(context.Guild.Id); var config = uow.GuildConfigs.GcWithPermissionsv2For(context.Guild.Id);
return new PermissionCache() Permissions.UpdateCache(config);
{ }
Verbose = config.VerbosePermissions, Permissions.Cache.TryGetValue(context.Guild.Id, out pc);
RootPermission = config.RootPermission, if(pc == null)
PermRole = config.PermissionRole.Trim().ToLowerInvariant(), throw new Exception("Cache is null.");
};
} }
});
int index; int index;
if (!resetCommand && !pc.RootPermission.AsEnumerable().CheckPermissions(context.Message, cmd.Aliases.First(), module.Name, out index)) if (!resetCommand && !pc.Permissions.CheckPermissions(context.Message, cmd.Aliases.First(), module.Name, out index))
{ {
var returnMsg = $"Permission number #{index + 1} **{pc.RootPermission.GetAt(index).GetCommand((SocketGuild)context.Guild)}** is preventing this action."; var returnMsg = $"Permission number #{index + 1} **{pc.Permissions[index].GetCommand((SocketGuild)context.Guild)}** is preventing this action.";
return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, returnMsg)); return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, returnMsg));
} }

View File

@ -10,8 +10,13 @@ namespace NadekoBot.Services.Database.Models
public Regex Regex { get; set; } public Regex Regex { get; set; }
public string Response { get; set; } public string Response { get; set; }
public string Trigger { get; set; } public string Trigger { get; set; }
public bool IsRegex { get; set; } public bool IsRegex { get; set; }
public bool OwnerOnly { get; set; } public bool OwnerOnly { get; set; }
public bool AutoDeleteTrigger { get; set; }
public bool DmResponse { get; set; }
public bool IsGlobal => !GuildId.HasValue;
} }
public class ReactionResponse : DbEntity public class ReactionResponse : DbEntity

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using static NadekoBot.Modules.Administration.Administration; using static NadekoBot.Modules.Administration.Administration;
namespace NadekoBot.Services.Database.Models namespace NadekoBot.Services.Database.Models
@ -41,7 +42,8 @@ namespace NadekoBot.Services.Database.Models
public HashSet<GCChannelId> GenerateCurrencyChannelIds { get; set; } = new HashSet<GCChannelId>(); public HashSet<GCChannelId> GenerateCurrencyChannelIds { get; set; } = new HashSet<GCChannelId>();
//permissions //permissions
public Permission RootPermission { get; set; } public Permission RootPermission { get; set; } = null;
public List<Permissionv2> Permissions { get; set; }
public bool VerbosePermissions { get; set; } = true; public bool VerbosePermissions { get; set; } = true;
public string PermissionRole { get; set; } = "Nadeko"; public string PermissionRole { get; set; } = "Nadeko";
@ -67,9 +69,59 @@ namespace NadekoBot.Services.Database.Models
public string Locale { get; set; } = null; public string Locale { get; set; } = null;
public string TimeZoneId { get; set; } = null; public string TimeZoneId { get; set; } = null;
public HashSet<UnmuteTimer> UnmuteTimers { get; set; } = new HashSet<UnmuteTimer>();
public HashSet<VcRoleInfo> VcRoleInfos { get; set; }
public HashSet<CommandAlias> CommandAliases { get; set; } = new HashSet<CommandAlias>();
//public List<ProtectionIgnoredChannel> ProtectionIgnoredChannels { get; set; } = new List<ProtectionIgnoredChannel>(); //public List<ProtectionIgnoredChannel> ProtectionIgnoredChannels { get; set; } = new List<ProtectionIgnoredChannel>();
} }
public class CommandAlias : DbEntity
{
public string Trigger { get; set; }
public string Mapping { get; set; }
//// override object.Equals
//public override bool Equals(object obj)
//{
// if (obj == null || GetType() != obj.GetType())
// {
// return false;
// }
// return ((CommandAlias)obj).Trigger.Trim().ToLowerInvariant() == Trigger.Trim().ToLowerInvariant();
//}
//// override object.GetHashCode
//public override int GetHashCode()
//{
// return Trigger.Trim().ToLowerInvariant().GetHashCode();
//}
}
public class VcRoleInfo : DbEntity
{
public ulong VoiceChannelId { get; set; }
public ulong RoleId { get; set; }
}
public class UnmuteTimer : DbEntity
{
public ulong UserId { get; set; }
public DateTime UnmuteAt { get; set; }
public override int GetHashCode() =>
UserId.GetHashCode();
public override bool Equals(object obj)
{
var ut = obj as UnmuteTimer;
if (ut == null)
return false;
return ut.UserId == UserId;
}
}
public class FilterChannelId : DbEntity public class FilterChannelId : DbEntity
{ {
public ulong ChannelId { get; set; } public ulong ChannelId { get; set; }

View File

@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations.Schema; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics; using System.Diagnostics;
namespace NadekoBot.Services.Database.Models namespace NadekoBot.Services.Database.Models
@ -17,46 +18,101 @@ namespace NadekoBot.Services.Database.Models
public bool State { get; set; } public bool State { get; set; }
public Permissionv2 Tov2() =>
new Permissionv2()
{
PrimaryTarget = PrimaryTarget,
PrimaryTargetId = PrimaryTargetId,
SecondaryTarget = SecondaryTarget,
SecondaryTargetName = SecondaryTargetName,
State = State,
};
//[NotMapped]
//private static Permission AllowAllPerm => new Permission()
//{
// PrimaryTarget = PrimaryPermissionType.Server,
// PrimaryTargetId = 0,
// SecondaryTarget = SecondaryPermissionType.AllModules,
// SecondaryTargetName = "*",
// State = true,
//};
//[NotMapped]
//private static Permission BlockNsfwPerm => new Permission()
//{
// PrimaryTarget = PrimaryPermissionType.Server,
// PrimaryTargetId = 0,
// SecondaryTarget = SecondaryPermissionType.Module,
// SecondaryTargetName = "nsfw",
// State = false,
//};
//public Permission Clone() => new Permission()
//{
// PrimaryTarget = PrimaryTarget,
// SecondaryTarget = SecondaryTarget,
// PrimaryTargetId = PrimaryTargetId,
// SecondaryTargetName = SecondaryTargetName,
// State = State,
//};
}
public interface IIndexed
{
int Index { get; set; }
}
[DebuggerDisplay("{PrimaryTarget}{SecondaryTarget} {SecondaryTargetName} {State} {PrimaryTargetId}")]
public class Permissionv2 : DbEntity, IIndexed
{
public int? GuildConfigId { get; set; }
public int Index { get; set; }
public PrimaryPermissionType PrimaryTarget { get; set; }
public ulong PrimaryTargetId { get; set; }
public SecondaryPermissionType SecondaryTarget { get; set; }
public string SecondaryTargetName { get; set; }
public bool State { get; set; }
[NotMapped] [NotMapped]
private static Permission AllowAllPerm => new Permission() public static Permissionv2 AllowAllPerm => new Permissionv2()
{ {
PrimaryTarget = PrimaryPermissionType.Server, PrimaryTarget = PrimaryPermissionType.Server,
PrimaryTargetId = 0, PrimaryTargetId = 0,
SecondaryTarget = SecondaryPermissionType.AllModules, SecondaryTarget = SecondaryPermissionType.AllModules,
SecondaryTargetName = "*", SecondaryTargetName = "*",
State = true, State = true,
Index = 0,
}; };
[NotMapped] [NotMapped]
private static Permission BlockNsfwPerm => new Permission() private static Permissionv2 BlockNsfwPerm => new Permissionv2()
{ {
PrimaryTarget = PrimaryPermissionType.Server, PrimaryTarget = PrimaryPermissionType.Server,
PrimaryTargetId = 0, PrimaryTargetId = 0,
SecondaryTarget = SecondaryPermissionType.Module, SecondaryTarget = SecondaryPermissionType.Module,
SecondaryTargetName = "nsfw", SecondaryTargetName = "nsfw",
State = false, State = false,
Index = 1
}; };
public static Permission GetDefaultRoot() public static List<Permissionv2> GetDefaultPermlist =>
new List<Permissionv2>
{ {
var root = AllowAllPerm; BlockNsfwPerm,
var blockNsfw = BlockNsfwPerm; AllowAllPerm
root.Previous = blockNsfw;
blockNsfw.Next = root;
return blockNsfw;
}
public Permission Clone() => new Permission()
{
PrimaryTarget = PrimaryTarget,
SecondaryTarget = SecondaryTarget,
PrimaryTargetId = PrimaryTargetId,
SecondaryTargetName = SecondaryTargetName,
State = State,
}; };
}
//public Permission Clone() => new Permission()
//{
// PrimaryTarget = PrimaryTarget,
// SecondaryTarget = SecondaryTarget,
// PrimaryTargetId = PrimaryTargetId,
// SecondaryTargetName = SecondaryTargetName,
// State = State,
//};
}
public enum PrimaryPermissionType public enum PrimaryPermissionType
{ {
User, User,

View File

@ -8,6 +8,6 @@ namespace NadekoBot.Services.Database.Repositories
Currency GetOrCreate(ulong userId); Currency GetOrCreate(ulong userId);
long GetUserCurrency(ulong userId); long GetUserCurrency(ulong userId);
bool TryUpdateState(ulong userId, long change); bool TryUpdateState(ulong userId, long change);
IEnumerable<Currency> GetTopRichest(int count); IEnumerable<Currency> GetTopRichest(int count, int skip);
} }
} }

View File

@ -10,11 +10,11 @@ namespace NadekoBot.Services.Database.Repositories
{ {
GuildConfig For(ulong guildId, Func<DbSet<GuildConfig>, IQueryable<GuildConfig>> includes = null); GuildConfig For(ulong guildId, Func<DbSet<GuildConfig>, IQueryable<GuildConfig>> includes = null);
GuildConfig LogSettingsFor(ulong guildId); GuildConfig LogSettingsFor(ulong guildId);
GuildConfig PermissionsFor(ulong guildId); IEnumerable<GuildConfig> OldPermissionsForAll();
IEnumerable<GuildConfig> PermissionsForAll();
IEnumerable<GuildConfig> GetAllGuildConfigs(); IEnumerable<GuildConfig> GetAllGuildConfigs();
GuildConfig SetNewRootPermission(ulong guildId, Permission p);
IEnumerable<FollowedStream> GetAllFollowedStreams(); IEnumerable<FollowedStream> GetAllFollowedStreams();
void SetCleverbotEnabled(ulong id, bool cleverbotEnabled); void SetCleverbotEnabled(ulong id, bool cleverbotEnabled);
IEnumerable<GuildConfig> Permissionsv2ForAll();
GuildConfig GcWithPermissionsv2For(ulong guildId);
} }
} }

View File

@ -10,5 +10,6 @@ namespace NadekoBot.Services.Database.Repositories
Task<Quote> GetRandomQuoteByKeywordAsync(ulong guildId, string keyword); Task<Quote> GetRandomQuoteByKeywordAsync(ulong guildId, string keyword);
Task<Quote> SearchQuoteKeywordTextAsync(ulong guildId, string keyword, string text); Task<Quote> SearchQuoteKeywordTextAsync(ulong guildId, string keyword, string text);
IEnumerable<Quote> GetGroup(ulong guildId, int skip, int take); IEnumerable<Quote> GetGroup(ulong guildId, int skip, int take);
void RemoveAllByKeyword(ulong guildId, string keyword);
} }
} }

View File

@ -27,8 +27,8 @@ namespace NadekoBot.Services.Database.Repositories.Impl
return cur; return cur;
} }
public IEnumerable<Currency> GetTopRichest(int count) => public IEnumerable<Currency> GetTopRichest(int count, int skip = 0) =>
_set.OrderByDescending(c => c.Amount).Take(count).ToList(); _set.OrderByDescending(c => c.Amount).Skip(skip).Take(count).ToList();
public long GetUserCurrency(ulong userId) => public long GetUserCurrency(ulong userId) =>
GetOrCreate(userId).Amount; GetOrCreate(userId).Amount;

View File

@ -2,7 +2,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using NadekoBot.Modules.Permissions;
using System; using System;
namespace NadekoBot.Services.Database.Repositories.Impl namespace NadekoBot.Services.Database.Repositories.Impl
@ -16,11 +15,10 @@ namespace NadekoBot.Services.Database.Repositories.Impl
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)
.Include(gc => gc.RootPermission)
.ThenInclude(gc => gc.Previous)
.Include(gc => gc.RootPermission)
.ThenInclude(gc => gc.Next)
.Include(gc => gc.MutedUsers) .Include(gc => gc.MutedUsers)
.Include(gc => gc.CommandAliases)
.Include(gc => gc.UnmuteTimers)
.Include(gc => gc.VcRoleInfos)
.Include(gc => gc.GenerateCurrencyChannelIds) .Include(gc => gc.GenerateCurrencyChannelIds)
.Include(gc => gc.FilterInvitesChannelIds) .Include(gc => gc.FilterInvitesChannelIds)
.Include(gc => gc.FilterWordsChannelIds) .Include(gc => gc.FilterWordsChannelIds)
@ -35,8 +33,9 @@ namespace NadekoBot.Services.Database.Repositories.Impl
/// <summary> /// <summary>
/// Gets and creates if it doesn't exist a config for a guild. /// Gets and creates if it doesn't exist a config for a guild.
/// </summary> /// </summary>
/// <param name="guildId"></param> /// <param name="guildId">For which guild</param>
/// <returns></returns> /// <param name="includes">Use to manipulate the set however you want</param>
/// <returns>Config for the guild</returns>
public GuildConfig For(ulong guildId, Func<DbSet<GuildConfig>, IQueryable<GuildConfig>> includes = null) public GuildConfig For(ulong guildId, Func<DbSet<GuildConfig>, IQueryable<GuildConfig>> includes = null)
{ {
GuildConfig config; GuildConfig config;
@ -65,7 +64,7 @@ namespace NadekoBot.Services.Database.Repositories.Impl
_set.Add((config = new GuildConfig _set.Add((config = new GuildConfig
{ {
GuildId = guildId, GuildId = guildId,
RootPermission = Permission.GetDefaultRoot(), Permissions = Permissionv2.GetDefaultPermlist
})); }));
_context.SaveChanges(); _context.SaveChanges();
} }
@ -74,41 +73,27 @@ namespace NadekoBot.Services.Database.Repositories.Impl
public GuildConfig LogSettingsFor(ulong guildId) public GuildConfig LogSettingsFor(ulong guildId)
{ {
return _set.Include(gc => gc.LogSetting) var config = _set.Include(gc => gc.LogSetting)
.ThenInclude(gc => gc.IgnoredChannels) .ThenInclude(gc => gc.IgnoredChannels)
.FirstOrDefault(); .FirstOrDefault();
}
public GuildConfig PermissionsFor(ulong guildId)
{
var query = _set.Include(gc => gc.RootPermission);
//todo this is possibly a disaster for performance
//What i could do instead is count the number of permissions in the permission table for this guild
// and make a for loop with those.
// or just select permissions for this guild and manually chain them
for (int i = 0; i < 60; i++)
{
query = query.ThenInclude(gc => gc.Next);
}
var config = query.FirstOrDefault(c => c.GuildId == guildId);
if (config == null) if (config == null)
{ {
_set.Add((config = new GuildConfig _set.Add((config = new GuildConfig
{ {
GuildId = guildId, GuildId = guildId,
RootPermission = Permission.GetDefaultRoot(), Permissions = Permissionv2.GetDefaultPermlist
})); }));
_context.SaveChanges(); _context.SaveChanges();
} }
return config; return config;
} }
public IEnumerable<GuildConfig> PermissionsForAll() public IEnumerable<GuildConfig> OldPermissionsForAll()
{ {
var query = _set.Include(gc => gc.RootPermission); var query = _set
.Where(gc => gc.RootPermission != null)
.Include(gc => gc.RootPermission);
//todo this is possibly a disaster for performance //todo this is possibly a disaster for performance
//What i could do instead is count the number of permissions in the permission table for this guild //What i could do instead is count the number of permissions in the permission table for this guild
@ -122,20 +107,44 @@ namespace NadekoBot.Services.Database.Repositories.Impl
return query.ToList(); return query.ToList();
} }
public IEnumerable<GuildConfig> Permissionsv2ForAll()
{
var query = _set
.Include(gc => gc.Permissions);
return query.ToList();
}
public GuildConfig GcWithPermissionsv2For(ulong guildId)
{
var config = _set
.Where(gc => gc.GuildId == guildId)
.Include(gc => gc.Permissions)
.FirstOrDefault();
if (config == null) // if there is no guildconfig, create new one
{
_set.Add((config = new GuildConfig
{
GuildId = guildId,
Permissions = Permissionv2.GetDefaultPermlist
}));
_context.SaveChanges();
}
else if (config.Permissions == null || !config.Permissions.Any()) // if no perms, add default ones
{
config.Permissions = Permissionv2.GetDefaultPermlist;
_context.SaveChanges();
}
return config;
}
public IEnumerable<FollowedStream> GetAllFollowedStreams() => public IEnumerable<FollowedStream> GetAllFollowedStreams() =>
_set.Include(gc => gc.FollowedStreams) _set.Include(gc => gc.FollowedStreams)
.SelectMany(gc => gc.FollowedStreams) .SelectMany(gc => gc.FollowedStreams)
.ToList(); .ToList();
public GuildConfig SetNewRootPermission(ulong guildId, Permission p)
{
var data = PermissionsFor(guildId);
data.RootPermission.Prepend(p);
data.RootPermission = p;
return data;
}
public void SetCleverbotEnabled(ulong id, bool cleverbotEnabled) public void SetCleverbotEnabled(ulong id, bool cleverbotEnabled)
{ {
var conf = _set.FirstOrDefault(gc => gc.GuildId == id); var conf = _set.FirstOrDefault(gc => gc.GuildId == id);

View File

@ -1,4 +1,6 @@
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using NadekoBot.Extensions;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -26,7 +28,11 @@ namespace NadekoBot.Services.Database.Repositories.Impl
public Task<Quote> SearchQuoteKeywordTextAsync(ulong guildId, string keyword, string text) public Task<Quote> SearchQuoteKeywordTextAsync(ulong guildId, string keyword, string text)
{ {
var rngk = new NadekoRandom(); var rngk = new NadekoRandom();
return _set.Where(q => q.Text.Contains(text) && q.GuildId == guildId && q.Keyword == keyword).OrderBy(q => rngk.Next()).FirstOrDefaultAsync(); return _set.Where(q => q.Text.ContainsNoCase(text, StringComparison.OrdinalIgnoreCase) && q.GuildId == guildId && q.Keyword == keyword).OrderBy(q => rngk.Next()).FirstOrDefaultAsync();
} }
public void RemoveAllByKeyword(ulong guildId, string keyword) =>
_set.RemoveRange(_set.Where(x => x.GuildId == guildId && x.Keyword.ToUpper() == keyword));
} }
} }

View File

@ -13,7 +13,7 @@ namespace NadekoBot.Services.Database.Repositories.Impl
public bool DeleteByGuildAndRoleId(ulong guildId, ulong roleId) public bool DeleteByGuildAndRoleId(ulong guildId, ulong roleId)
{ {
var role = _set.Where(s => s.GuildId == guildId && s.RoleId == roleId).FirstOrDefault(); var role = _set.FirstOrDefault(s => s.GuildId == guildId && s.RoleId == roleId);
if (role == null) if (role == null)
return false; return false;

View File

@ -7,13 +7,13 @@ namespace NadekoBot.Services
public interface IBotCredentials public interface IBotCredentials
{ {
ulong ClientId { get; } ulong ClientId { get; }
ulong BotId { get; }
string Token { get; } string Token { get; }
string GoogleApiKey { get; } string GoogleApiKey { get; }
ImmutableHashSet<ulong> OwnerIds { get; } ImmutableHashSet<ulong> OwnerIds { get; }
string MashapeKey { get; } string MashapeKey { get; }
string LoLApiKey { get; } string LoLApiKey { get; }
string PatreonAccessToken { get; }
DBConfig Db { get; } DBConfig Db { get; }

View File

@ -5,7 +5,6 @@ using Discord;
using System.Linq; using System.Linq;
using NLog; using NLog;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
namespace NadekoBot.Services.Impl namespace NadekoBot.Services.Impl
@ -15,7 +14,6 @@ namespace NadekoBot.Services.Impl
private Logger _log; private Logger _log;
public ulong ClientId { get; } public ulong ClientId { get; }
public ulong BotId { get; }
public string GoogleApiKey { get; } public string GoogleApiKey { get; }
@ -44,6 +42,7 @@ namespace NadekoBot.Services.Impl
public string CarbonKey { get; } public string CarbonKey { get; }
public string credsFileName { get; } = Path.Combine(Directory.GetCurrentDirectory(), "credentials.json"); public string credsFileName { get; } = Path.Combine(Directory.GetCurrentDirectory(), "credentials.json");
public string PatreonAccessToken { get; }
public BotCredentials() public BotCredentials()
{ {
@ -68,6 +67,7 @@ namespace NadekoBot.Services.Impl
GoogleApiKey = data[nameof(GoogleApiKey)]; GoogleApiKey = data[nameof(GoogleApiKey)];
MashapeKey = data[nameof(MashapeKey)]; MashapeKey = data[nameof(MashapeKey)];
OsuApiKey = data[nameof(OsuApiKey)]; OsuApiKey = data[nameof(OsuApiKey)];
PatreonAccessToken = data[nameof(PatreonAccessToken)];
int ts = 1; int ts = 1;
int.TryParse(data[nameof(TotalShards)], out ts); int.TryParse(data[nameof(TotalShards)], out ts);
@ -109,6 +109,7 @@ namespace NadekoBot.Services.Impl
public string CarbonKey { get; set; } = ""; public string CarbonKey { get; set; } = "";
public DBConfig Db { get; set; } = new DBConfig("sqlite", "Filename=./data/NadekoBot.db"); public DBConfig Db { get; set; } = new DBConfig("sqlite", "Filename=./data/NadekoBot.db");
public int TotalShards { get; set; } = 1; public int TotalShards { get; set; } = 1;
public string PatreonAccessToken { get; set; } = "";
} }
private class DbModel private class DbModel

View File

@ -42,6 +42,8 @@ namespace NadekoBot.Services
CultureInfo cultureInfo = null; CultureInfo cultureInfo = null;
try try
{ {
if (x.Value == null)
return null;
cultureInfo = new CultureInfo(x.Value); cultureInfo = new CultureInfo(x.Value);
} }
catch { } catch { }

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.2"; public const string BotVersion = "1.25";
public string Author => "Kwoth#2560"; public string Author => "Kwoth#2560";
public string Library => "Discord.Net"; public string Library => "Discord.Net";

View File

@ -1,6 +1,8 @@
using Discord.Commands; using Discord.Commands;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Modules.CustomReactions;
using NadekoBot.Services.Database.Models;
namespace NadekoBot.TypeReaders namespace NadekoBot.TypeReaders
{ {
@ -17,4 +19,46 @@ namespace NadekoBot.TypeReaders
return Task.FromResult(TypeReaderResult.FromSuccess(cmd)); return Task.FromResult(TypeReaderResult.FromSuccess(cmd));
} }
} }
public class CommandOrCrTypeReader : CommandTypeReader
{
public override async Task<TypeReaderResult> Read(ICommandContext context, string input)
{
input = input.ToUpperInvariant();
if (CustomReactions.GlobalReactions.Any(x => x.Trigger.ToUpperInvariant() == input))
{
return TypeReaderResult.FromSuccess(new CommandOrCrInfo(input));
}
var guild = context.Guild;
if (guild != null)
{
CustomReaction[] crs;
if (CustomReactions.GuildReactions.TryGetValue(guild.Id, out crs))
{
if (crs.Any(x => x.Trigger.ToUpperInvariant() == input))
{
return TypeReaderResult.FromSuccess(new CommandOrCrInfo(input));
}
}
}
var cmd = await base.Read(context, input);
if (cmd.IsSuccess)
{
return TypeReaderResult.FromSuccess(new CommandOrCrInfo(((CommandInfo)cmd.Values.First().Value).Aliases.First()));
}
return TypeReaderResult.FromError(CommandError.ParseFailed, "No such command or cr found.");
}
}
public class CommandOrCrInfo
{
public string Name { get; set; }
public CommandOrCrInfo(string input)
{
this.Name = input;
}
}
} }

View File

@ -21,6 +21,12 @@ namespace NadekoBot.Extensions
private const string arrow_left = "⬅"; private const string arrow_left = "⬅";
private const string arrow_right = "➡"; private const string arrow_right = "➡";
public static string ToBase64(this string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return Convert.ToBase64String(plainTextBytes);
}
public static Stream ToStream(this IEnumerable<byte> bytes, bool canWrite = false) public static Stream ToStream(this IEnumerable<byte> bytes, bool canWrite = false)
{ {
var ms = new MemoryStream(bytes as byte[] ?? bytes.ToArray(), canWrite); var ms = new MemoryStream(bytes as byte[] ?? bytes.ToArray(), canWrite);
@ -87,9 +93,9 @@ namespace NadekoBot.Extensions
private static EmbedBuilder AddPaginatedFooter(this EmbedBuilder embed, int curPage, int? lastPage) private static EmbedBuilder AddPaginatedFooter(this EmbedBuilder embed, int curPage, int? lastPage)
{ {
if (lastPage != null) if (lastPage != null)
return embed.WithFooter(efb => efb.WithText($"page {curPage} / {lastPage}")); return embed.WithFooter(efb => efb.WithText($"{curPage} / {lastPage}"));
else else
return embed.WithFooter(efb => efb.WithText($"page {curPage}")); return embed.WithFooter(efb => efb.WithText(curPage.ToString()));
} }
public static ReactionEventWrapper OnReaction(this IUserMessage msg, Action<SocketReaction> reactionAdded, Action<SocketReaction> reactionRemoved = null) public static ReactionEventWrapper OnReaction(this IUserMessage msg, Action<SocketReaction> reactionAdded, Action<SocketReaction> reactionRemoved = null)
@ -279,6 +285,15 @@ namespace NadekoBot.Extensions
} }
} }
/// <summary>
/// Easy use of fast, efficient case-insensitive Contains check with StringComparison Member Types
/// CurrentCulture, CurrentCultureIgnoreCase, InvariantCulture, InvariantCultureIgnoreCase, Ordinal, OrdinalIgnoreCase
/// </summary>
public static bool ContainsNoCase(this string str, string contains, StringComparison compare)
{
return str.IndexOf(contains, compare) >= 0;
}
public static string TrimTo(this string str, int maxLength, bool hideDots = false) public static string TrimTo(this string str, int maxLength, bool hideDots = false)
{ {
if (maxLength < 0) if (maxLength < 0)

View File

@ -14,5 +14,6 @@
"Type": "sqlite", "Type": "sqlite",
"ConnectionString": "Filename=./data/NadekoBot.db" "ConnectionString": "Filename=./data/NadekoBot.db"
}, },
"TotalShards": 1 "TotalShards": 1,
"PatreonAccessToken": ""
} }

View File

@ -23,12 +23,8 @@
"Google.Apis.Urlshortener.v1": "1.19.0.138", "Google.Apis.Urlshortener.v1": "1.19.0.138",
"Google.Apis.YouTube.v3": "1.20.0.701", "Google.Apis.YouTube.v3": "1.20.0.701",
"Google.Apis.Customsearch.v1": "1.20.0.466", "Google.Apis.Customsearch.v1": "1.20.0.466",
"ImageSharp": "1.0.0-alpha2-*", "ImageSharp": "1.0.0-alpha4-00031",
"ImageSharp.Processing": "1.0.0-alpha2-*", "ImageSharp.Drawing": "1.0.0-alpha4-00031",
"ImageSharp.Formats.Png": "1.0.0-alpha2-*",
"ImageSharp.Formats.Jpeg": "1.0.0-alpha2-*",
"ImageSharp.Drawing": "1.0.0-alpha2-*",
"ImageSharp.Drawing.Paths": "1.0.0-alpha2-*",
"Microsoft.EntityFrameworkCore": "1.1.0", "Microsoft.EntityFrameworkCore": "1.1.0",
"Microsoft.EntityFrameworkCore.Design": "1.1.0", "Microsoft.EntityFrameworkCore.Design": "1.1.0",
"Microsoft.EntityFrameworkCore.Sqlite": "1.1.0", "Microsoft.EntityFrameworkCore.Sqlite": "1.1.0",