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
- [Help](#help)
@ -18,11 +18,11 @@ You can support the project on patreon: <https://patreon.com/nadekobot> or paypa
### Administration
Command and aliases | Description | Usage
----------------|--------------|-------
`.resetperms` | Resets 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`
`.resetperms` | Resets the bot's permissions module on this server to the default value. **Requires Administrator server permission.** | `.resetperms`
`.delmsgoncmd` | Toggles the automatic deletion of the user's successful command message to prevent chat flood. **Requires Administrator server permission.** | `.delmsgoncmd`
`.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`
`.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`
`.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`
@ -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`
`.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`
`.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`
`.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`
`.donators` | List of lovely people who donated to keep this project alive. | `.donators`
`.donadd` | Add a donator to the database. **Bot Owner only.** | `.donadd Donate Amount`
`.prune` `.clr` | `.prune` removes all Nadeko's messages in the last 100 messages. `.prune X` removes last `X` number of messages from the channel (up to 100). `.prune @Someone` removes all Someone's messages in the last 100 messages. `.prune @Someone X` removes last `X` number of 'Someone's' messages in the channel. | `.prune` or `.prune 5` or `.prune @Someone` or `.prune @Someone X`
`.mentionrole` `.menro` | Mentions every person from the provided role or roles (separated by a ',') on this server. Requires you to have the mention everyone permission. **Requires MentionEveryone server permission.** | `.menro RoleName`
`.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`
`.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`
`.fwtoall` | Toggles whether messages will be forwarded to all bot owners or only to the first one specified in the credentials.json **Bot Owner only.** | `.fwtoall`
`.logserver` | Enables or Disables ALL log events. If enabled, all log events will log to this channel. **Requires Administrator server permission.** **Bot Owner only.** | `.logserver enable` or `.logserver disable`
`.logignore` | Toggles whether the .logserver command ignores this channel. Useful if you have hidden admin channel and public log channel. **Requires Administrator server permission.** **Bot Owner only.** | `.logignore`
`.logevents` | Shows a list of all events you can subscribe to with `.log` **Requires Administrator server permission.** **Bot Owner only.** | `.logevents`
`.log` | Toggles logging event. Disables it if it'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`
`.migratedata` | Migrate data from old bot configuration **Bot Owner only.** | `.migratedata`
`.languageset` `.langset` | Sets this server's response language. If bot's response strings have been translated to that language, bot will use that language in this server. Reset by using `default` as the locale name. Provide no arguments to see currently set language. | `.langset de-DE ` or `.langset default`
`.langsetdefault` `.langsetd` | Sets the bot's default response language. All servers which use a default locale will use this one. Setting to `default` will use the host's current culture. Provide no arguments to see currently set language. | `.langsetd en-US` or `.langsetd default`
`.languageslist` `.langli` | List of languages for which translation (or part of it) exist atm. | `.langli`
`.logserver` | Enables or Disables ALL log events. If enabled, all log events will log to this channel. **Requires Administrator server permission.** **Bot Owner Only** | `.logserver enable` or `.logserver disable`
`.logignore` | Toggles whether the `.logserver` command ignores this channel. Useful if you have hidden admin channel and public log channel. **Requires Administrator server permission.** **Bot Owner Only** | `.logignore`
`.logevents` | Shows a list of all events you can subscribe to with `.log` **Requires Administrator server permission.** **Bot Owner Only** | `.logevents`
`.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`
`.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`
@ -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`
`.voicemute` | Prevents a mentioned user from speaking in voice channels. **Requires MuteMembers server permission.** | `.voicemute @Someone`
`.voiceunmute` | Gives a previously voice-muted user a permission to speak. **Requires MuteMembers server permission.** | `.voiceunmute @Someguy`
`.rotateplaying` `.ropl` | Toggles rotation of playing status of the dynamic strings you previously specified. **Bot Owner only.** | `.ropl`
`.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`
`.removeplaying` `.rmpl` `.repl` | Removes a playing string on a given number. **Bot Owner only.** | `.rmpl`
`.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`
`.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`
`.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`
`.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`
`.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`
`.rsar` | Removes a specified role from the list of self-assignable roles. **Requires ManageRoles server permission.** | `.rsar`
`.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`
`.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`
`.leave` | Makes Nadeko leave the server. Either name or id required. **Bot Owner only.** | `.leave 123123123331`
`.die` | Shuts the bot down. **Bot Owner only.** | `.die`
`.setname` `.newnm` | Gives the bot a new name. **Bot Owner only.** | `.newnm BotName`
`.setstatus` | Sets the bot's status. (Online/Idle/Dnd/Invisible) **Bot Owner only.** | `.setstatus Idle`
`.setavatar` `.setav` | Sets a new avatar image for the NadekoBot. Argument is a direct link to an image. **Bot Owner only.** | `.setav http://i.imgur.com/xTG3a1I.jpg`
`.setgame` | Sets the bots game. **Bot Owner only.** | `.setgame with snakes`
`.setstream` | Sets the bots stream. First argument is the twitch link, second argument is stream name. **Bot Owner only.** | `.setstream TWITCHLINK Hello`
`.send` | Sends a message to someone on a different server through the bot. Separate server and channel/user ids with `|` and prepend channel id with `c:` and 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' general channel 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 0 to disable automatic deletion. **Requires ManageServer server permission.** | `.greetdel 0` or `.greetdel 30`
`.fwmsgs` | Toggles forwarding of non-command messages sent to bot's DM to the bot owners **Bot Owner Only** | `.fwmsgs`
`.fwtoall` | Toggles whether messages will be forwarded to all bot owners or only to the first one specified in the credentials.json file **Bot Owner Only** | `.fwtoall`
`.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`
`.leave` | Makes Nadeko leave the server. Either server name or server ID is required. **Bot Owner Only** | `.leave 123123123331`
`.die` | Shuts the bot down. **Bot Owner Only** | `.die`
`.setname` `.newnm` | Gives the bot a new name. **Bot Owner Only** | `.newnm BotName`
`.setstatus` | Sets the bot's status. (Online/Idle/Dnd/Invisible) **Bot Owner Only** | `.setstatus Idle`
`.setavatar` `.setav` | Sets a new avatar image for the NadekoBot. Argument is a direct link to an image. **Bot Owner Only** | `.setav http://i.imgur.com/xTG3a1I.jpg`
`.setgame` | Sets the bots game. **Bot Owner Only** | `.setgame with snakes`
`.setstream` | Sets the bots stream. First argument is the twitch link, second argument is stream name. **Bot Owner Only** | `.setstream TWITCHLINK Hello`
`.send` | Sends a message to someone on a different server through the bot. Separate server and channel/user ids with `|` and prefix the channel id with `c:` and the user id with `u:`. **Bot Owner Only** | `.send serverid|c:channelid message` or `.send serverid|u:userid message`
`.announce` | Sends a message to all servers' default channel that bot is connected to. **Bot Owner Only** | `.announce Useless spam`
`.reloadimages` | Reloads images bot is using. Safe to use even when bot is being used heavily. **Bot Owner Only** | `.reloadimages`
`.greetdel` `.grdel` | Sets the time it takes (in seconds) for greet messages to be auto-deleted. Set it to 0 to disable automatic deletion. **Requires ManageServer server permission.** | `.greetdel 0` or `.greetdel 30`
`.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`
`.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`
`.byemsg` | Sets a new leave announcement message. Type %user% if you want to show the name the user who left. Type %id% to show id. Using this command with no message will show the current bye message. **Requires ManageServer server permission.** | `.byemsg %user% has left.`
`.byedel` | Sets the time it takes (in seconds) for bye messages to be auto-deleted. Set 0 to disable automatic deletion. **Requires ManageServer server permission.** | `.byedel 0` or `.byedel 30`
`.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`
`.byemsg` | Sets a new leave announcement message. Type `%user%` if you want to show the name the user who left. Type `%id%` to show id. Using this command with no message will show the current bye message. You can use embed json from <http://nadekobot.xyz/embedbuilder/> instead of a regular text, if you want the message to be embedded. **Requires ManageServer server permission.** | `.byemsg %user% has left.`
`.byedel` | Sets the time it takes (in seconds) for bye messages to be auto-deleted. Set it to `0` to disable automatic deletion. **Requires ManageServer server permission.** | `.byedel 0` or `.byedel 30`
`.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`
###### [Back to TOC](#table-of-contents)
###### [Back to ToC](#table-of-contents)
### ClashOfClans
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`
`,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]`
`,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`
@ -108,20 +112,20 @@ Command and aliases | Description | Usage
`,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]`
###### [Back to TOC](#table-of-contents)
###### [Back to ToC](#table-of-contents)
### CustomReactions
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`
`.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`
`.delcustreact` `.dcr` | Deletes a custom reaction on a specific index. If ran in DM, it is bot owner only and deletes a global custom reaction. If ran in a server, it requires Administration priviledges and removes server custom reaction. | `.dcr 5`
`.crstatsclear` | Resets the counters on `.crstats`. You can specify a trigger to clear stats only for that trigger. **Bot Owner only.** | `.crstatsclear` or `.crstatsclear rng`
`.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`
`.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
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`
`$cash` `$$$` | Check how much currency a person has. (Defaults to yourself) | `$$$` or `$$$ @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`
`$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`
`$leaderboard` `$lb` | Displays bot currency leaderboard. | `$lb`
`$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"`
`$betroll` `$br` | Bets a certain amount of currency and rolls a dice. Rolling over 66 yields x2 of your currency, over 90 - x4 and 100 x10. | `$br 5`
`$leaderboard` `$lb` | Displays the bot's currency leaderboard. | `$lb`
`$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`
`$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`
`$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`
`$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`
`$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`
`$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`
`$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`
`$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`
`$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`
`$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`
`$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`
`$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
Command and aliases | Description | Usage
----------------|--------------|-------
`>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`
`>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`
`>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`
@ -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`
`>typestart` | Starts a typing contest. | `>typestart`
`>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`
`>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`
`>typedel` | Deletes a typing article given the ID. **Bot Owner Only** | `>typedel 3`
`>tictactoe` `>ttt` | Starts a game of tic tac toe. Another user must run the command in the same channel in order to accept the challenge. Use numbers 1-9 to play. 15 seconds per move. | >ttt
`>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`
`>tq` | Quits current trivia after current question. | `>tq`
###### [Back to TOC](#table-of-contents)
###### [Back to ToC](#table-of-contents)
### Help
Command and aliases | Description | Usage
----------------|--------------|-------
`-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`
`-help` `-h` | Either shows a help for a single command, or DMs you help link if no arguments are specified. | `-h !!q` or `-h`
`-hgit` | Generates the commandlist.md file. **Bot Owner only.** | `-hgit`
`-commands` `-cmds` | List all of the bot's commands from a certain module. You can either specify the full name or only the first few letters of the module name. | `-commands Administration` or `-cmds Admin`
`-help` `-h` | Either shows a help for a single command, or DMs you help link if no arguments are specified. | `-h -cmds` or `-h`
`-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`
`-donate` | Instructions for helping the project financially. | `-donate`
###### [Back to TOC](#table-of-contents)
###### [Back to ToC](#table-of-contents)
### Music
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`
`!!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`
`!!fairplay` `!!fp` | Toggles fairplay. While enabled, music player will prioritize songs from users who didn't have their song recently played instead of the song's position in the queue. | `!!fp`
`!!queue` `!!q` `!!yq` | Queue a song using keywords or a link. Bot will join your voice channel.**You must be in a voice channel**. | `!!q Dream Of Venice`
`!!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`
`!!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`
`!!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`
`!!nowplaying` `!!np` | Shows the song currently playing. | `!!np`
`!!volume` `!!vol` | Sets the music volume 0-100% | `!!vol 50`
`!!nowplaying` `!!np` | Shows the song that the bot is currently playing. | `!!np`
`!!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`
`!!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`
`!!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`
`!!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`
`!!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`
`!!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`
`!!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`
`!!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`
`!!load` | Loads a saved playlist using it's ID. Use `!!pls` to list all saved playlists and !!save to save new ones. | `!!load 5`
`!!playlists` `!!pls` | Lists all playlists. Paginated. 20 per page. Default page is 0. | `!!pls 1`
`!!deleteplaylist` `!!delpls` | Deletes a saved playlist. Only if you made it or if you are the bot owner. | `!!delpls animu-5`
`!!save` | Saves a playlist under a certain name. Playlist name must be no longer than 20 characters and must not contain dashes. | `!!save classical1`
`!!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`
`!!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`
`!!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`
###### [Back to TOC](#table-of-contents)
###### [Back to ToC](#table-of-contents)
### NSFW
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`
`~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`
`~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`
`~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`
`~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`
`~boobs` | Real adult content. | `~boobs`
`~butts` `~ass` `~butt` | Real adult content. | `~butts` or `~ass`
###### [Back to TOC](#table-of-contents)
###### [Back to ToC](#table-of-contents)
### Permissions
Command and aliases | Description | Usage
----------------|--------------|-------
`;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`
`;removeperm` `;rp` | Removes a permission from a given position in Permissions list. | `;rp 1`
`;moveperm` `;mp` | Moves permission from one position to another in Permissions list. | `;mp 2 4`
`;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 the Permissions list. | `;mp 2 4`
`;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`
`;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`
`;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]`
`;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`
`;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`
`;cmdcooldown` `;cmdcd` | Sets a cooldown per user for a command. Set to 0 to remove the cooldown. | `;cmdcd "some cmd" 5`
`;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`
`;sbl` | Either [add]s or [rem]oves a server specified by a Name or an ID from a blacklist. **Bot Owner Only** | `;sbl add 12312321312` or `;sbl rem SomeTrashServer`
`;cmdcooldown` `;cmdcd` | Sets a cooldown per user for a command. Set it to 0 to remove the cooldown. | `;cmdcd "some cmd" 5`
`;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 deleting of invites posted in the server. Does not affect Bot Owner. | `;sfi`
`;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 deleting of messages containing forbidden words on the server. Does not affect Bot Owner. | `;sfw`
`;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`
`;srvrfilterinv` `;sfi` | Toggles automatic deletion of invites posted in the server. Does not affect the 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`
`;srvrfilterwords` `;sfw` | Toggles automatic deletion of messages containing filtered words on the server. Does not affect the 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`
`;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`
###### [Back to TOC](#table-of-contents)
###### [Back to ToC](#table-of-contents)
### Pokemon
Command and aliases | Description | Usage
----------------|--------------|-------
`>attack` | Attacks a target with the given move. Use `>movelist` to see a list of moves your type can use. | `>attack "vine whip" @someguy`
`>movelist` `>ml` | Lists the moves you are able to use | `>ml`
`>heal` | Heals someone. Revives those who fainted. Costs a NadekoFlower | `>heal @someone`
`>heal` | Heals someone. Revives those who fainted. Costs a NadekoFlower. | `>heal @someone`
`>type` | Get the poketype of the target. | `>type @someone`
`>settype` | Set your poketype. Costs a NadekoFlower. Provide no arguments to see a list of available types. | `>settype fire` or `>settype`
###### [Back to TOC](#table-of-contents)
###### [Back to ToC](#table-of-contents)
### Searches
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`
`~randomcat` `~meow` | Shows a random cat image. | `~meow`
`~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`
`~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`
`~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`
`~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`
`~define` `~def` | Finds a definition of a word. | `~def heresy`
`~#` | Searches Tagdef.com for a hashtag. | `~# ff`
`~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"`
`~revimg` | Returns a google reverse image search for an image from a link. | `~revimg Image link`
`~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`
`~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`
`~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"`
`~avatar` `~av` | Shows a mentioned person's avatar. | `~av "@SomeGuy"`
`~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`
`~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"`
`~mal` | Shows basic info from myanimelist profile. | `~mal straysocks`
`~mal` | Shows basic info from a MyAnimeList profile. | `~mal straysocks`
`~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`
`~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`
`~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`
`~magicitem` `~mi` | Shows a random magicitem 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`
`~osub` | Shows information about an osu beatmap. | `~osub https://osu.ppy.sh/s/127712`
`~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`
`~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`
`~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.
`~autotrans` `~at` | Starts automatic translation of all messages by users who set their `~atl` in this channel. You can set "del" argument to automatically delete all translated user messages. **Requires Administrator server permission.** **Bot Owner Only** | `~at` or `~at del`
`~autotranslang` `~atl` | Sets your source and target language to be used with `~at`. Specify no arguments to remove previously set value. | `~atl en>fr`
`~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`
###### [Back to TOC](#table-of-contents)
###### [Back to ToC](#table-of-contents)
### Utility
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`
`.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`
`.userid` `.uid` | Shows user ID. | `.uid` or `.uid "@SomeGuy"`
`.channelid` `.cid` | Shows current channel ID. | `.cid`
`.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`
`.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`
`.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`
`.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`
`.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`
`.activity` | Checks for spammers. **Bot Owner Only** | `.activity`
`.calculate` `.calc` | Evaluate a mathematical expression. | `.calc 1+1`
`.calcops` | Shows all available operations in .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`
`.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`
`.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`
`.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`
`.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`
`.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`
`.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`
`.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`
`.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`
`.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%!`
`.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%!`
`.convertlist` | List of the convertible dimensions and currencies. | `.convertlist`
`.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)
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 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
```
**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
@ -232,14 +264,14 @@ Ubuntu:
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 ffmpeg
```
**NOTE:** If you are running **UBUNTU 14.04**, you must run these first:
```
```sh
sudo add-apt-repository ppa:mc3man/trusty-media
sudo apt-get update
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:
```
```sh
sudo apt-get update
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
@ -330,14 +362,14 @@ If the [Nadeko installer](http://nadekobot.readthedocs.io/en/latest/guides/Linux
**OR**
```
```sh
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
```
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/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/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.
- `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`
[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
[Atom]: https://atom.io/
[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
[7zip]: http://www.7-zip.org/download.html
[DiscordApp]: https://discordapp.com/developers/applications/me

View File

@ -1,24 +1,25 @@
@ECHO off
TITLE Downloading Latest Build of NadekoBot...
::Setting convenient to read variables which don't delete the windows temp folder
SET root=%~dp0
CD /D %root%
SET rootdir=%cd%
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 build3=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.WebSocket\
SET build4=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Commands\
SET build5=%root%NadekoInstall_Temp\NadekoBot\src\NadekoBot\
SET installtemp=%root%NadekoInstall_Temp\
SET "root=%~dp0"
CD /D "%root%"
SET "rootdir=%cd%"
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 "build3=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.WebSocket\"
SET "build4=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Commands\"
SET "build5=%root%NadekoInstall_Temp\NadekoBot\src\NadekoBot\"
SET "installtemp=%root%NadekoInstall_Temp\"
::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
dotnet --version >nul 2>&1 || GOTO :dotnet
git --version >nul 2>&1 || GOTO :git
::Creates the install directory to work in and get the current directory because spaces ruins everything otherwise
:start
MKDIR NadekoInstall_Temp
CD /D %installtemp%
MKDIR "%root%NadekoInstall_Temp"
CD /D "%installtemp%"
::Downloads the latest version of Nadeko
ECHO Downloading Nadeko...
ECHO.
@ -28,28 +29,28 @@ TITLE Installing NadekoBot, please wait...
ECHO.
ECHO Installing Discord.Net(1/4)...
::Building Nadeko
CD /D %build1%
CD /D "%build1%"
dotnet restore >nul 2>&1
ECHO Installing Discord.Net(2/4)...
CD /D %build2%
CD /D "%build2%"
dotnet restore >nul 2>&1
ECHO Installing Discord.Net(3/4)...
CD /D %build3%
CD /D "%build3%"
dotnet restore >nul 2>&1
ECHO Installing Discord.Net(4/4)...
CD /D %build4%
CD /D "%build4%"
dotnet restore >nul 2>&1
ECHO.
ECHO Discord.Net installation completed successfully...
ECHO.
ECHO Installing NadekoBot...
CD /D %build5%
CD /D "%build5%"
dotnet restore >nul 2>&1
dotnet build --configuration Release >nul 2>&1
ECHO.
ECHO NadekoBot installation completed successfully...
::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
::Moves the NadekoBot folder to keep things tidy
ECHO.
@ -65,20 +66,23 @@ IF EXIST "%root%NadekoBot\" (GOTO :backupinstall)
ROBOCOPY "%root%NadekoBot" "%root%NadekoBot_Old" /MIR >nul 2>&1
IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror)
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
COPY "%root%NadekoBot_Old\src\NadekoBot\credentials.json" "%installtemp%NadekoBot\src\NadekoBot\credentials.json" >nul 2>&1
IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror)
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
IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror)
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
IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror)
ECHO.
ECHO Old data folder copied to new folder
ECHO Old data folder copied...
::Moves the setup Nadeko folder
RMDIR "%root%NadekoBot\" /S /Q >nul 2>&1
ROBOCOPY "%root%NadekoInstall_Temp" "%rootdir%" /E /MOVE >nul 2>&1
@ -103,7 +107,7 @@ IF EXIST "%root%NadekoBot\" (GOTO :backupinstall)
:giterror
ECHO.
ECHO Git clone failed, trying again
RMDIR %installtemp% /S /Q >nul 2>&1
RMDIR "%installtemp%" /S /Q >nul 2>&1
GOTO :start
:copyerror
::If at any point a copy error is encountered
@ -124,22 +128,39 @@ ECHO.
ECHO Your System Architecture is 32bit...
timeout /t 5
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"
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.
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"
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.
GOTO end
:end
::Normal execution of end of script
TITLE Installation complete!
TITLE NadekoBot Installation complete!
CD /D "%root%"
RMDIR /S /Q "%installtemp%" >nul 2>&1
ECHO.
ECHO Installation complete, press any key to close this window!
timeout /t 5
del Latest.bat
ECHO Installation complete!
ECHO.
PAUSE
del Latest.bat

View File

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

View File

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

View File

@ -1,24 +1,25 @@
@ECHO off
TITLE Downloading Stable Build of NadekoBot...
::Setting convenient to read variables which don't delete the windows temp folder
SET root=%~dp0
CD /D %root%
SET rootdir=%cd%
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 build3=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.WebSocket\
SET build4=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Commands\
SET build5=%root%NadekoInstall_Temp\NadekoBot\src\NadekoBot\
SET installtemp=%root%NadekoInstall_Temp\
SET "root=%~dp0"
CD /D "%root%"
SET "rootdir=%cd%"
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 "build3=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.WebSocket\"
SET "build4=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Commands\"
SET "build5=%root%NadekoInstall_Temp\NadekoBot\src\NadekoBot\"
SET "installtemp=%root%NadekoInstall_Temp\"
::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
dotnet --version >nul 2>&1 || GOTO :dotnet
git --version >nul 2>&1 || GOTO :git
::Creates the install directory to work in and get the current directory because spaces ruins everything otherwise
:start
MKDIR NadekoInstall_Temp
CD /D %installtemp%
MKDIR "%root%NadekoInstall_Temp"
CD /D "%installtemp%"
::Downloads the latest version of Nadeko
ECHO Downloading Nadeko...
ECHO.
@ -28,28 +29,28 @@ TITLE Installing NadekoBot, please wait...
ECHO.
ECHO Installing Discord.Net(1/4)...
::Building Nadeko
CD /D %build1%
CD /D "%build1%"
dotnet restore >nul 2>&1
ECHO Installing Discord.Net(2/4)...
CD /D %build2%
CD /D "%build2%"
dotnet restore >nul 2>&1
ECHO Installing Discord.Net(3/4)...
CD /D %build3%
CD /D "%build3%"
dotnet restore >nul 2>&1
ECHO Installing Discord.Net(4/4)...
CD /D %build4%
CD /D "%build4%"
dotnet restore >nul 2>&1
ECHO.
ECHO Discord.Net installation completed successfully...
ECHO.
ECHO Installing NadekoBot...
CD /D %build5%
CD /D "%build5%"
dotnet restore >nul 2>&1
dotnet build --configuration Release >nul 2>&1
ECHO.
ECHO NadekoBot installation completed successfully...
::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
::Moves the NadekoBot folder to keep things tidy
ECHO.
@ -65,20 +66,23 @@ IF EXIST "%root%NadekoBot\" (GOTO :backupinstall)
ROBOCOPY "%root%NadekoBot" "%root%NadekoBot_Old" /MIR >nul 2>&1
IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror)
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
COPY "%root%NadekoBot_Old\src\NadekoBot\credentials.json" "%installtemp%NadekoBot\src\NadekoBot\credentials.json" >nul 2>&1
IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror)
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
IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror)
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
IF %ERRORLEVEL% GEQ 8 (GOTO :copyerror)
ECHO.
ECHO Old data folder copied to new folder
ECHO Old data folder copied...
::Moves the setup Nadeko folder
RMDIR "%root%NadekoBot\" /S /Q >nul 2>&1
ROBOCOPY "%root%NadekoInstall_Temp" "%rootdir%" /E /MOVE >nul 2>&1
@ -103,7 +107,7 @@ IF EXIST "%root%NadekoBot\" (GOTO :backupinstall)
:giterror
ECHO.
ECHO Git clone failed, trying again
RMDIR %installtemp% /S /Q >nul 2>&1
RMDIR "%installtemp%" /S /Q >nul 2>&1
GOTO :start
:copyerror
::If at any point a copy error is encountered
@ -124,22 +128,39 @@ ECHO.
ECHO Your System Architecture is 32bit...
timeout /t 5
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"
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.
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"
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.
GOTO end
:end
::Normal execution of end of script
TITLE Installation complete!
TITLE NadekoBot Installation complete!
CD /D "%root%"
RMDIR /S /Q "%installtemp%" >nul 2>&1
ECHO.
ECHO Installation complete, press any key to close this window!
timeout /t 5
del Stable.bat
ECHO Installation complete!
ECHO.
PAUSE
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");
});
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 =>
{
b.Property<int>("Id")
@ -310,8 +330,12 @@ namespace NadekoBot.Migrations
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<bool>("AutoDeleteTrigger");
b.Property<DateTime?>("DateAdded");
b.Property<bool>("DmResponse");
b.Property<ulong?>("GuildId");
b.Property<bool>("IsRegex");
@ -764,6 +788,34 @@ namespace NadekoBot.Migrations
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 =>
{
b.Property<int>("Id")
@ -896,6 +948,26 @@ namespace NadekoBot.Migrations
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 =>
{
b.Property<int>("Id")
@ -915,6 +987,26 @@ namespace NadekoBot.Migrations
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 =>
{
b.Property<int>("Id")
@ -1006,6 +1098,13 @@ namespace NadekoBot.Migrations
.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 =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
@ -1112,6 +1211,13 @@ namespace NadekoBot.Migrations
.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 =>
{
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
@ -1134,6 +1240,20 @@ namespace NadekoBot.Migrations
.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 =>
{
b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "Affinity")

View File

@ -11,6 +11,7 @@ using Discord.WebSocket;
using NadekoBot.Services.Database.Models;
using static NadekoBot.Modules.Permissions.Permissions;
using System.Collections.Concurrent;
using Microsoft.EntityFrameworkCore;
using NLog;
namespace NadekoBot.Modules.Administration
@ -56,20 +57,12 @@ namespace NadekoBot.Modules.Administration
[RequireUserPermission(GuildPermission.Administrator)]
public async Task ResetPermissions()
{
var channel = (ITextChannel)Context.Channel;
using (var uow = DbHandler.UnitOfWork())
{
var config = uow.GuildConfigs.PermissionsFor(Context.Guild.Id);
config.RootPermission = Permission.GetDefaultRoot();
var toAdd = new PermissionCache()
{
RootPermission = config.RootPermission,
PermRole = config.PermissionRole,
Verbose = config.VerbosePermissions,
};
Cache.AddOrUpdate(channel.Guild.Id,
toAdd, (id, old) => toAdd);
var config = uow.GuildConfigs.GcWithPermissionsv2For(Context.Guild.Id);
config.Permissions = Permissionv2.GetDefaultPermlist;
await uow.CompleteAsync();
UpdateCache(config);
}
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>()
{
{"zh-TW", "Chinese (Traditional), China" },
{"zh-CN", "Chinese (Simplified), China"},
{"nl-NL", "Dutch, Netherlands"},
{"en-US", "English, United States"},
{"fr-FR", "French, France"},
{"ru-RU", "Russian, Russia"},
{"de-DE", "German, Germany"},
//{"nl-NL", "Dutch, Netherlands"},
//{"ja-JP", "Japanese, Japan"},
{"nb-NO", "Norwegian (bokmål), Norway"},
{"pl-PL", "Polish, Poland" },
{"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();
[NadekoCommand, Usage, Description, Aliases]
@ -97,11 +104,10 @@ namespace NadekoBot.Modules.Administration
}
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task LanguagesList()
{
await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithTitle(GetText("lang_list", ""))
.WithTitle(GetText("lang_list"))
.WithDescription(string.Join("\n",
supportedLocales.Select(x => $"{Format.Code(x.Key), -10} => {x.Value}"))));
}

View File

@ -2,13 +2,13 @@
using Discord.Commands;
using Microsoft.EntityFrameworkCore;
using NadekoBot.Attributes;
using NadekoBot.Extensions;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
using NLog;
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Administration
@ -20,6 +20,8 @@ namespace NadekoBot.Modules.Administration
{
private static ConcurrentDictionary<ulong, string> guildMuteRoles { 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> UserUnmuted = delegate { };
@ -43,6 +45,23 @@ namespace NadekoBot.Modules.Administration
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;
}
@ -67,10 +86,15 @@ namespace NadekoBot.Modules.Administration
public static async Task MuteUser(IGuildUser usr)
{
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())
{
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()
{
UserId = usr.Id
@ -78,7 +102,9 @@ namespace NadekoBot.Modules.Administration
ConcurrentHashSet<ulong> muted;
if (mutedUsers.TryGetValue(usr.Guild.Id, out muted))
muted.Add(usr.Id);
config.UnmuteTimers.RemoveWhere(x => x.UserId == usr.Id);
await uow.CompleteAsync().ConfigureAwait(false);
}
UserMuted(usr, MuteType.All);
@ -86,11 +112,13 @@ namespace NadekoBot.Modules.Administration
public static async Task UnmuteUser(IGuildUser usr)
{
await usr.ModifyAsync(x => x.Mute = false).ConfigureAwait(false);
await usr.RemoveRolesAsync(await GetMuteRole(usr.Guild)).ConfigureAwait(false);
StopUnmuteTimer(usr.GuildId, usr.Id);
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())
{
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()
{
UserId = usr.Id
@ -98,6 +126,9 @@ namespace NadekoBot.Modules.Administration
ConcurrentHashSet<ulong> muted;
if (mutedUsers.TryGetValue(usr.Guild.Id, out muted))
muted.TryRemove(usr.Id);
config.UnmuteTimers.RemoveWhere(x => x.UserId == usr.Id);
await uow.CompleteAsync().ConfigureAwait(false);
}
UserUnmuted(usr, MuteType.All);
@ -139,6 +170,79 @@ namespace NadekoBot.Modules.Administration
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]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageRoles)]
@ -170,6 +274,7 @@ namespace NadekoBot.Modules.Administration
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageRoles)]
[RequireUserPermission(GuildPermission.MuteMembers)]
[Priority(1)]
public async Task Mute(IGuildUser user)
{
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]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageRoles)]

View File

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

View File

@ -150,11 +150,11 @@ namespace NadekoBot.Modules.Administration
var guildUser = (IGuildUser)Context.User;
GuildConfig conf;
IEnumerable<SelfAssignedRole> roles;
SelfAssignedRole[] roles;
using (var uow = DbHandler.UnitOfWork())
{
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)
{
@ -167,14 +167,21 @@ namespace NadekoBot.Modules.Administration
return;
}
var roleIds = roles.Select(x => x.RoleId).ToArray();
if (conf.ExclusiveSelfAssignedRoles)
{
var sameRoleId = guildUser.RoleIds.FirstOrDefault(r => roles.Select(sar => sar.RoleId).Contains(r));
var sameRole = Context.Guild.GetRole(sameRoleId);
var sameRoleId = guildUser.RoleIds.FirstOrDefault(r => roleIds.Contains(r));
if (sameRoleId != default(ulong))
{
await ReplyErrorLocalized("self_assign_already_excl", Format.Bold(sameRole?.Name)).ConfigureAwait(false);
return;
var sameRole = Context.Guild.GetRole(sameRoleId);
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

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);
if (!botUser.GuildPermissions.ManageRoles || !botUser.GuildPermissions.ManageChannels)
{
await ReplyErrorLocalized("vt_no_perms").ConfigureAwait(false);
await ReplyErrorLocalized("vt_perms").ConfigureAwait(false);
return;
}

View File

@ -11,11 +11,27 @@ using NLog;
using System.Diagnostics;
using Discord.WebSocket;
using System;
using Newtonsoft.Json;
using NadekoBot.DataStructures;
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", ".")]
public class CustomReactions : NadekoTopLevelModule
{
@ -25,7 +41,7 @@ namespace NadekoBot.Modules.CustomReactions
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()
{
@ -43,11 +59,11 @@ namespace NadekoBot.Modules.CustomReactions
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;
if (channel == null)
return false;
return null;
var content = umsg.Content.Trim().ToLowerInvariant();
CustomReaction[] reactions;
@ -70,26 +86,9 @@ namespace NadekoBot.Modules.CustomReactions
var reaction = rs[new NadekoRandom().Next(0, rs.Length)];
if (reaction != null)
{
if (reaction.Response != "-")
{
CREmbed crembed;
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;
if (reaction.Response == "-")
return null;
return reaction;
}
}
}
@ -103,29 +102,10 @@ namespace NadekoBot.Modules.CustomReactions
return ((hasTarget && content.StartsWith(trigger + " ")) || content == trigger);
}).ToArray();
if (grs.Length == 0)
return false;
return null;
var greaction = grs[new NadekoRandom().Next(0, grs.Length)];
if (greaction != null)
{
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;
return greaction;
}
[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]
[OwnerOnly]
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 () =>
{
await Task.Delay(2000);
await Task.Delay(1500);
_runningUsers.Remove(Context.User.Id);
});
}

View File

@ -395,7 +395,7 @@ namespace NadekoBot.Modules.Gambling
target = Context.User;
WaifuInfo w;
IList<WaifuInfo> claims;
int divorces = 0;
int divorces;
using (var uow = DbHandler.UnitOfWork())
{
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("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($"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);
}
@ -494,7 +494,10 @@ namespace NadekoBot.Modules.Gambling
int count;
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;

View File

@ -244,19 +244,26 @@ namespace NadekoBot.Modules.Gambling
}
[NadekoCommand, Usage, Description, Aliases]
public async Task Leaderboard()
public async Task Leaderboard(int page = 1)
{
List<Currency> richest;
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()
.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++)
{
@ -267,7 +274,7 @@ namespace NadekoBot.Modules.Gambling
: usr.Username?.TrimTo(20, true);
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)
.WithIsInline(true));
}

View File

@ -5,12 +5,15 @@ using NadekoBot.Attributes;
using NadekoBot.Extensions;
using NadekoBot.Services;
using NLog;
using Services.CleverBotApi;
//using Services.CleverBotApi;
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Services.CleverBotApi;
namespace NadekoBot.Modules.Games
{
@ -27,13 +30,11 @@ namespace NadekoBot.Modules.Games
{
_log = LogManager.GetCurrentClassLogger();
var sw = Stopwatch.StartNew();
var bot = ChatterBotFactory.Create(ChatterBotType.CLEVERBOT);
CleverbotGuilds = new ConcurrentDictionary<ulong, Lazy<ChatterBotSession>>(
NadekoBot.AllGuildConfigs
.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();
_log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
@ -100,9 +101,7 @@ namespace NadekoBot.Modules.Games
return;
}
var cleverbot = ChatterBotFactory.Create(ChatterBotType.CLEVERBOT);
CleverbotGuilds.TryAdd(channel.Guild.Id, new Lazy<ChatterBotSession>(() => cleverbot.CreateSession(), true));
CleverbotGuilds.TryAdd(channel.Guild.Id, new Lazy<ChatterBotSession>(() => new ChatterBotSession(Context.Guild.Id), true));
using (var uow = DbHandler.UnitOfWork())
{
@ -113,5 +112,42 @@ namespace NadekoBot.Modules.Games
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 prefix = NadekoBot.ModulePrefixes[typeof(Games).Name];
var toSend = dropAmount == 1
? GetLocalText(channel, "curgen_sn", NadekoBot.BotConfig.CurrencySign, prefix)
: GetLocalText(channel, "curgen_pl", dropAmount, NadekoBot.BotConfig.CurrencySign, prefix);
? GetLocalText(channel, "curgen_sn", NadekoBot.BotConfig.CurrencySign)
+ GetLocalText(channel, "pick_sn", prefix)
: GetLocalText(channel, "curgen_pl", dropAmount, NadekoBot.BotConfig.CurrencySign)
+ GetLocalText(channel, "pick_pl", prefix);
var file = GetRandomCurrencyImage();
using (var fileStream = file.Value.ToStream())
{
@ -155,10 +157,15 @@ namespace NadekoBot.Modules.Games
//and then
var msgToSend = GetText("planted",
Format.Bold(Context.User.ToString()),
amount + NadekoBot.BotConfig.CurrencySign,
Format.Bold(Context.User.ToString()),
amount + NadekoBot.BotConfig.CurrencySign,
Prefix);
if (amount > 1)
msgToSend += " " + GetText("pick_pl", Prefix);
else
msgToSend += " " + GetText("pick_sn", Prefix);
IUserMessage msg;
using (var toSend = imgData.Value.ToStream())
{

View File

@ -1,4 +1,5 @@
using Discord;
using System;
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Attributes;
@ -8,6 +9,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ImageSharp.Processing;
namespace NadekoBot.Modules.Games
{
@ -39,7 +41,7 @@ namespace NadekoBot.Modules.Games
if (!ActivePolls.TryGetValue(Context.Guild.Id, out poll))
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)
@ -58,7 +60,7 @@ namespace NadekoBot.Modules.Games
await poll.StartPoll().ConfigureAwait(false);
}
else
await channel.SendErrorAsync("Poll is already running on this server.").ConfigureAwait(false);
await ReplyErrorLocalized("poll_already_running").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
@ -108,21 +110,24 @@ namespace NadekoBot.Modules.Games
var totalVotesCast = 0;
if (results.Length == 0)
{
sb.AppendLine("No votes cast.");
sb.AppendLine(GetText("no_votes_cast"));
}
else
{
for (int i = 0; i < results.Length; 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;
}
}
eb.WithDescription(sb.ToString())
.WithFooter(efb => efb.WithText(totalVotesCast + " total votes cast."));
.WithFooter(efb => efb.WithText(GetText("x_votes_cast", totalVotesCast)));
return eb;
}
@ -130,13 +135,13 @@ namespace NadekoBot.Modules.Games
public async Task StartPoll()
{
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;
msgToSend = answers.Aggregate(msgToSend, (current, answ) => current + $"`{num++}.` **{answ}**\n");
if (!IsPublic)
msgToSend += "\n**Private Message me with the corresponding number of the answer.**";
msgToSend += "\n" + Format.Bold(GetText("poll_vote_private"));
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);
}
@ -187,17 +192,23 @@ namespace NadekoBot.Modules.Games
{
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
{
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);
}
}
}
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);
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.";
}
else if (roll < 999)
@ -244,7 +244,7 @@ namespace NadekoBot.Modules.Games
hot = NextDouble(8, 10);
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?" +
" 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
{

View File

@ -347,10 +347,8 @@ namespace NadekoBot.Modules.Music
return;
}
var count = ids.Count();
var msg = await Context.Channel.SendMessageAsync(GetText("attempting_to_queue",
Format.Bold(count.ToString())))
.ConfigureAwait(false);
var msg = await Context.Channel.SendMessageAsync("🎵 " + GetText("attempting_to_queue",
Format.Bold(count.ToString()))).ConfigureAwait(false);
var cancelSource = new CancellationTokenSource();
@ -374,7 +372,7 @@ namespace NadekoBot.Modules.Music
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]
@ -722,7 +720,7 @@ namespace NadekoBot.Modules.Music
var embed = new EmbedBuilder()
.WithAuthor(eab => eab.WithName(GetText("playlists_page", num)).WithMusicIcon())
.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();
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);

View File

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

View File

@ -10,25 +10,12 @@ namespace NadekoBot.Modules.Permissions
{
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();
int throwaway;
return perms.CheckPermissions(message, command.Name, command.Module.Name, out throwaway);
}
var perms = permsEnumerable as List<Permissionv2> ?? permsEnumerable.ToList();
public static bool CheckPermissions(this IEnumerable<Permission> permsEnumerable, IUserMessage message, string commandName, string moduleName)
{
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++)
for (int i = perms.Count - 1; i >= 0; i--)
{
var perm = perms[i];
@ -38,11 +25,8 @@ namespace NadekoBot.Modules.Permissions
{
continue;
}
else
{
permIndex = i;
return result.Value;
}
permIndex = i;
return result.Value;
}
permIndex = -1; //defaut behaviour
return true;
@ -51,7 +35,7 @@ namespace NadekoBot.Modules.Permissions
//null = not applicable
//true = applicable, 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 &&
perm.SecondaryTargetName.ToLowerInvariant() == commandName.ToLowerInvariant()) ||
@ -86,7 +70,7 @@ namespace NadekoBot.Modules.Permissions
return null;
}
public static string GetCommand(this Permission perm, SocketGuild guild = null)
public static string GetCommand(this Permissionv2 perm, SocketGuild guild = null)
{
var com = "";
switch (perm.PrimaryTarget)
@ -143,98 +127,10 @@ namespace NadekoBot.Modules.Permissions
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)
{
do yield return perm;
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 NadekoBot.Services.Database.Models;
using System.Collections.Concurrent;
using NadekoBot.Extensions;
using System.Collections.Generic;
using Discord.WebSocket;
using System.Diagnostics;
using Microsoft.EntityFrameworkCore;
using NadekoBot.DataStructures;
using NadekoBot.TypeReaders;
using NLog;
namespace NadekoBot.Modules.Permissions
@ -17,53 +20,151 @@ namespace NadekoBot.Modules.Permissions
[NadekoModule("Permissions", ";")]
public partial class Permissions : NadekoTopLevelModule
{
public class PermissionCache
public class OldPermissionCache
{
public string PermRole { get; set; }
public bool Verbose { get; set; } = true;
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
public static ConcurrentDictionary<ulong, PermissionCache> Cache { get; }
public static ConcurrentDictionary<ulong, PermissionCache> Cache { get; } =
new ConcurrentDictionary<ulong, PermissionCache>();
static Permissions()
{
var log = LogManager.GetCurrentClassLogger();
var sw = Stopwatch.StartNew();
TryMigratePermissions();
using (var uow = DbHandler.UnitOfWork())
{
Cache = new ConcurrentDictionary<ulong, PermissionCache>(uow.GuildConfigs
.PermissionsForAll()
.ToDictionary(k => k.GuildId,
v => new PermissionCache()
{
RootPermission = v.RootPermission,
Verbose = v.VerbosePermissions,
PermRole = v.PermissionRole
}));
foreach (var x in uow.GuildConfigs.Permissionsv2ForAll())
{
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,
v => new OldPermissionCache()
{
RootPermission = v.RootPermission,
Verbose = v.VerbosePermissions,
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();
}
}
}
private static async Task AddPermissions(ulong guildId, params Permissionv2[] perms)
{
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]
[RequireContext(ContextType.Guild)]
public async Task Verbose(PermissionAction action)
{
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;
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);
UpdateCache(config);
}
if (action.Value)
{
@ -84,20 +185,15 @@ namespace NadekoBot.Modules.Permissions
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)
{
await ReplyConfirmLocalized("permrole", Format.Bold(config.PermissionRole)).ConfigureAwait(false);
return;
}
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);
UpdateCache(config);
}
await ReplyConfirmLocalized("permrole_changed", Format.Bold(role.Name)).ConfigureAwait(false);
@ -109,19 +205,32 @@ namespace NadekoBot.Modules.Permissions
{
if (page < 1 || page > 4)
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;
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)))}"));
perms = permCache.Permissions.Source.ToList();
}
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);
}
@ -131,43 +240,24 @@ namespace NadekoBot.Modules.Permissions
public async Task RemovePerm(int index)
{
index -= 1;
if (index < 0)
return;
try
{
Permission p;
Permissionv2 p;
using (var uow = DbHandler.UnitOfWork())
{
var config = uow.GuildConfigs.PermissionsFor(Context.Guild.Id);
var perms = config.RootPermission;
if (index == perms.Count() - 1)
{
return;
}
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; });
var config = uow.GuildConfigs.GcWithPermissionsv2For(Context.Guild.Id);
var permsCol = new PermissionsCollection<Permissionv2>(config.Permissions);
p = permsCol[index];
permsCol.RemoveAt(index);
uow._context.Remove(p);
await uow.CompleteAsync().ConfigureAwait(false);
UpdateCache(config);
}
using (var uow2 = DbHandler.UnitOfWork())
{
uow2._context.Remove<Permission>(p);
uow2._context.SaveChanges();
}
await ReplyConfirmLocalized("removed",
index+1,
Format.Code(p.GetCommand((SocketGuild)Context.Guild))).ConfigureAwait(false);
await ReplyConfirmLocalized("removed",
index + 1,
Format.Code(p.GetCommand((SocketGuild) Context.Guild))).ConfigureAwait(false);
}
catch (IndexOutOfRangeException)
{
@ -185,96 +275,36 @@ namespace NadekoBot.Modules.Permissions
{
try
{
Permission fromPerm = null;
Permission toPerm = null;
Permissionv2 fromPerm;
using (var uow = DbHandler.UnitOfWork())
{
var config = uow.GuildConfigs.PermissionsFor(Context.Guild.Id);
var perms = config.RootPermission;
var index = 0;
var fromFound = false;
var toFound = false;
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)
{
await ReplyErrorLocalized("not_found", ++from).ConfigureAwait(false);
return;
}
var config = uow.GuildConfigs.GcWithPermissionsv2For(Context.Guild.Id);
var permsCol = new PermissionsCollection<Permissionv2>(config.Permissions);
if (!toFound)
{
await ReplyErrorLocalized("not_found", ++to).ConfigureAwait(false);
return;
}
var fromFound = from < permsCol.Count;
var toFound = to < permsCol.Count;
if (!fromFound)
{
await ReplyErrorLocalized("not_found", ++from).ConfigureAwait(false);
return;
}
//Change chain for from indx
var next = fromPerm.Next;
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)
if (!toFound)
{
await ReplyErrorLocalized("not_found", ++to).ConfigureAwait(false);
return;
}
fromPerm = permsCol[from];
permsCol.RemoveAt(from);
permsCol.Insert(to, fromPerm);
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);
UpdateCache(config);
}
await ReplyConfirmLocalized("moved_permission",
Format.Code(fromPerm.GetCommand((SocketGuild) Context.Guild)),
++from,
Format.Code(fromPerm.GetCommand((SocketGuild) Context.Guild)),
++from,
++to)
.ConfigureAwait(false);
return;
@ -288,39 +318,27 @@ namespace NadekoBot.Modules.Permissions
[NadekoCommand, Usage, Description, Aliases]
[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,
PrimaryTargetId = 0,
SecondaryTarget = SecondaryPermissionType.Command,
SecondaryTargetName = command.Aliases.First().ToLowerInvariant(),
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);
}
PrimaryTarget = PrimaryPermissionType.Server,
PrimaryTargetId = 0,
SecondaryTarget = SecondaryPermissionType.Command,
SecondaryTargetName = command.Name.ToLowerInvariant(),
State = action.Value,
});
if (action.Value)
{
await ReplyConfirmLocalized("sx_enable",
Format.Code(command.Aliases.First()),
await ReplyConfirmLocalized("sx_enable",
Format.Code(command.Name),
GetText("of_command")).ConfigureAwait(false);
}
else
{
await ReplyConfirmLocalized("sx_disable",
Format.Code(command.Aliases.First()),
await ReplyConfirmLocalized("sx_disable",
Format.Code(command.Name),
GetText("of_command")).ConfigureAwait(false);
}
}
@ -329,25 +347,14 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)]
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,
PrimaryTargetId = 0,
SecondaryTarget = SecondaryPermissionType.Module,
SecondaryTargetName = module.Name.ToLowerInvariant(),
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);
}
PrimaryTarget = PrimaryPermissionType.Server,
PrimaryTargetId = 0,
SecondaryTarget = SecondaryPermissionType.Module,
SecondaryTargetName = module.Name.ToLowerInvariant(),
State = action.Value,
});
if (action.Value)
{
@ -365,39 +372,28 @@ namespace NadekoBot.Modules.Permissions
[NadekoCommand, Usage, Description, Aliases]
[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,
PrimaryTargetId = user.Id,
SecondaryTarget = SecondaryPermissionType.Command,
SecondaryTargetName = command.Aliases.First().ToLowerInvariant(),
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);
}
PrimaryTarget = PrimaryPermissionType.User,
PrimaryTargetId = user.Id,
SecondaryTarget = SecondaryPermissionType.Command,
SecondaryTargetName = command.Name.ToLowerInvariant(),
State = action.Value,
});
if (action.Value)
{
await ReplyConfirmLocalized("ux_enable",
Format.Code(command.Aliases.First()),
await ReplyConfirmLocalized("ux_enable",
Format.Code(command.Name),
GetText("of_command"),
Format.Code(user.ToString())).ConfigureAwait(false);
}
else
{
await ReplyConfirmLocalized("ux_disable",
Format.Code(command.Aliases.First()),
await ReplyConfirmLocalized("ux_disable",
Format.Code(command.Name),
GetText("of_command"),
Format.Code(user.ToString())).ConfigureAwait(false);
}
@ -407,25 +403,14 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)]
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,
PrimaryTargetId = user.Id,
SecondaryTarget = SecondaryPermissionType.Module,
SecondaryTargetName = module.Name.ToLowerInvariant(),
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);
}
PrimaryTarget = PrimaryPermissionType.User,
PrimaryTargetId = user.Id,
SecondaryTarget = SecondaryPermissionType.Module,
SecondaryTargetName = module.Name.ToLowerInvariant(),
State = action.Value,
});
if (action.Value)
{
@ -445,42 +430,31 @@ namespace NadekoBot.Modules.Permissions
[NadekoCommand, Usage, Description, Aliases]
[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)
return;
using (var uow = DbHandler.UnitOfWork())
await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{
PrimaryTarget = PrimaryPermissionType.Role,
PrimaryTargetId = role.Id,
SecondaryTarget = SecondaryPermissionType.Command,
SecondaryTargetName = command.Aliases.First().ToLowerInvariant(),
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);
}
PrimaryTarget = PrimaryPermissionType.Role,
PrimaryTargetId = role.Id,
SecondaryTarget = SecondaryPermissionType.Command,
SecondaryTargetName = command.Name.ToLowerInvariant(),
State = action.Value,
});
if (action.Value)
{
await ReplyConfirmLocalized("rx_enable",
Format.Code(command.Aliases.First()),
Format.Code(command.Name),
GetText("of_command"),
Format.Code(role.Name)).ConfigureAwait(false);
}
else
{
await ReplyConfirmLocalized("rx_disable",
Format.Code(command.Aliases.First()),
Format.Code(command.Name),
GetText("of_command"),
Format.Code(role.Name)).ConfigureAwait(false);
}
@ -493,25 +467,14 @@ namespace NadekoBot.Modules.Permissions
if (role == role.Guild.EveryoneRole)
return;
using (var uow = DbHandler.UnitOfWork())
await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{
PrimaryTarget = PrimaryPermissionType.Role,
PrimaryTargetId = role.Id,
SecondaryTarget = SecondaryPermissionType.Module,
SecondaryTargetName = module.Name.ToLowerInvariant(),
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);
}
PrimaryTarget = PrimaryPermissionType.Role,
PrimaryTargetId = role.Id,
SecondaryTarget = SecondaryPermissionType.Module,
SecondaryTargetName = module.Name.ToLowerInvariant(),
State = action.Value,
});
if (action.Value)
@ -532,39 +495,28 @@ namespace NadekoBot.Modules.Permissions
[NadekoCommand, Usage, Description, Aliases]
[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,
PrimaryTargetId = chnl.Id,
SecondaryTarget = SecondaryPermissionType.Command,
SecondaryTargetName = command.Aliases.First().ToLowerInvariant(),
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);
}
PrimaryTarget = PrimaryPermissionType.Channel,
PrimaryTargetId = chnl.Id,
SecondaryTarget = SecondaryPermissionType.Command,
SecondaryTargetName = command.Name.ToLowerInvariant(),
State = action.Value,
});
if (action.Value)
{
await ReplyConfirmLocalized("cx_enable",
Format.Code(command.Aliases.First()),
Format.Code(command.Name),
GetText("of_command"),
Format.Code(chnl.Name)).ConfigureAwait(false);
}
else
{
await ReplyConfirmLocalized("cx_disable",
Format.Code(command.Aliases.First()),
Format.Code(command.Name),
GetText("of_command"),
Format.Code(chnl.Name)).ConfigureAwait(false);
}
@ -574,25 +526,14 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)]
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,
PrimaryTargetId = chnl.Id,
SecondaryTarget = SecondaryPermissionType.Module,
SecondaryTargetName = module.Name.ToLowerInvariant(),
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);
}
PrimaryTarget = PrimaryPermissionType.Channel,
PrimaryTargetId = chnl.Id,
SecondaryTarget = SecondaryPermissionType.Module,
SecondaryTargetName = module.Name.ToLowerInvariant(),
State = action.Value,
});
if (action.Value)
{
@ -614,25 +555,14 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)]
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,
PrimaryTargetId = chnl.Id,
SecondaryTarget = SecondaryPermissionType.AllModules,
SecondaryTargetName = "*",
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);
}
PrimaryTarget = PrimaryPermissionType.Channel,
PrimaryTargetId = chnl.Id,
SecondaryTarget = SecondaryPermissionType.AllModules,
SecondaryTargetName = "*",
State = action.Value,
});
if (action.Value)
{
@ -653,25 +583,14 @@ namespace NadekoBot.Modules.Permissions
if (role == role.Guild.EveryoneRole)
return;
using (var uow = DbHandler.UnitOfWork())
await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{
PrimaryTarget = PrimaryPermissionType.Role,
PrimaryTargetId = role.Id,
SecondaryTarget = SecondaryPermissionType.AllModules,
SecondaryTargetName = "*",
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);
}
PrimaryTarget = PrimaryPermissionType.Role,
PrimaryTargetId = role.Id,
SecondaryTarget = SecondaryPermissionType.AllModules,
SecondaryTargetName = "*",
State = action.Value,
});
if (action.Value)
{
@ -689,25 +608,14 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)]
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,
PrimaryTargetId = user.Id,
SecondaryTarget = SecondaryPermissionType.AllModules,
SecondaryTargetName = "*",
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);
}
PrimaryTarget = PrimaryPermissionType.User,
PrimaryTargetId = user.Id,
SecondaryTarget = SecondaryPermissionType.AllModules,
SecondaryTargetName = "*",
State = action.Value,
});
if (action.Value)
{
@ -725,36 +633,27 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)]
public async Task AllSrvrMdls(PermissionAction action)
{
using (var uow = DbHandler.UnitOfWork())
var newPerm = new Permissionv2
{
var newPerm = new Permission
{
PrimaryTarget = PrimaryPermissionType.Server,
PrimaryTargetId = 0,
SecondaryTarget = SecondaryPermissionType.AllModules,
SecondaryTargetName = "*",
State = action.Value,
};
uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
PrimaryTarget = PrimaryPermissionType.Server,
PrimaryTargetId = 0,
SecondaryTarget = SecondaryPermissionType.AllModules,
SecondaryTargetName = "*",
State = action.Value,
};
var allowUser = new Permission
{
PrimaryTarget = PrimaryPermissionType.User,
PrimaryTargetId = Context.User.Id,
SecondaryTarget = SecondaryPermissionType.AllModules,
SecondaryTargetName = "*",
State = true,
};
var allowUser = new Permissionv2
{
PrimaryTarget = PrimaryPermissionType.User,
PrimaryTargetId = Context.User.Id,
SecondaryTarget = SecondaryPermissionType.AllModules,
SecondaryTargetName = "*",
State = true,
};
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, allowUser);
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 AddPermissions(Context.Guild.Id,
newPerm,
allowUser);
if (action.Value)
{
@ -766,4 +665,4 @@ namespace NadekoBot.Modules.Permissions
}
}
}
}
}

View File

@ -1,11 +1,11 @@
using Discord;
using System;
using Discord;
using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.Extensions;
using NadekoBot.Modules.Searches.Models;
using Newtonsoft.Json;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Searches
@ -20,7 +20,7 @@ namespace NadekoBot.Modules.Searches
{
if (string.IsNullOrWhiteSpace(query))
return;
var battletag = Regex.Replace(query, "#", "-", RegexOptions.IgnoreCase);
var battletag = query.Replace("#", "-");
await Context.Channel.TriggerTypingAsync().ConfigureAwait(false);
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("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_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_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))
.WithColor(NadekoBot.OkColor);
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
@ -73,15 +73,22 @@ namespace NadekoBot.Modules.Searches
{
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");
var model = JsonConvert.DeserializeObject<OverwatchApiModel.OverwatchPlayer>(url);
return model.data;
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);
return model.data;
}
}
}
catch
catch (Exception ex)
{
_log.Warn(ex);
return null;
}
}

View File

@ -26,12 +26,17 @@ namespace NadekoBot.Modules.Searches
{
var res = await http.GetStringAsync($"{_xkcdUrl}/info.0.json").ConfigureAwait(false);
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);
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;
}

View File

@ -22,6 +22,7 @@ using Configuration = AngleSharp.Configuration;
using NadekoBot.Attributes;
using Discord.Commands;
using ImageSharp.Processing.Processors;
using ImageSharp;
namespace NadekoBot.Modules.Searches
{
@ -41,17 +42,17 @@ namespace NadekoBot.Modules.Searches
var data = JsonConvert.DeserializeObject<WeatherData>(response);
var embed = new EmbedBuilder()
.AddField(fb => fb.WithName("🌍 " + GetText("location")).WithValue(data.name + ", " + data.sys.country).WithIsInline(true))
.AddField(fb => fb.WithName("📏 " + 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("😓 " + 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("🌡 " + 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("🌄 " + GetText("sunrise")).WithValue($"{data.sys.sunrise.ToUnixTimestamp():HH:mm}").WithIsInline(true))
.AddField(fb => fb.WithName("🌇 " + GetText("sunset")).WithValue($"{data.sys.sunset.ToUnixTimestamp():HH:mm}").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("📏 " + Format.Bold(GetText("latlong"))).WithValue($"{data.coord.lat}, {data.coord.lon}").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("😓 " + Format.Bold(GetText("humidity"))).WithValue($"{data.main.humidity}%").WithIsInline(true))
.AddField(fb => fb.WithName("💨 " + Format.Bold(GetText("wind_speed"))).WithValue(data.wind.speed + " m/s").WithIsInline(true))
.AddField(fb => fb.WithName("🌡 " + Format.Bold(GetText("temperature"))).WithValue(data.main.temp + "°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("🌄 " + Format.Bold(GetText("sunrise"))).WithValue($"{data.sys.sunrise.ToUnixTimestamp():HH:mm} UTC").WithIsInline(true))
.AddField(fb => fb.WithName("🌇 " + Format.Bold(GetText("sunset"))).WithValue($"{data.sys.sunset.ToUnixTimestamp():HH:mm} UTC").WithIsInline(true))
.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);
}
@ -217,7 +218,7 @@ namespace NadekoBot.Modules.Searches
if (string.IsNullOrWhiteSpace(ffs))
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);
}
@ -605,7 +606,7 @@ namespace NadekoBot.Modules.Searches
return;
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);
}

View File

@ -53,7 +53,7 @@ namespace NadekoBot.Modules.Utility
"GetHashCode",
"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();
}
public override string ToString()
{
return
$"{Channel.Mention} | {(int) Repeater.Interval.TotalHours}:{Repeater.Interval:mm} | {Repeater.Message.TrimTo(33)}";
}
public override string ToString() =>
$"{Channel?.Mention ?? $"<#{Repeater.ChannelId}>" } " +
$"| {(int) Repeater.Interval.TotalHours}:{Repeater.Interval:mm} " +
$"| {Repeater.Message.TrimTo(33)}";
}
static RepeatCommands()
@ -247,7 +246,7 @@ namespace NadekoBot.Modules.Utility
await Context.Channel.SendConfirmAsync(
"🔁 " + 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.Hours.ToString()),
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

@ -33,9 +33,9 @@ namespace NadekoBot.Modules.Utility
}
if (quotes.Any())
await Context.Channel.SendConfirmAsync(GetText("quotes_page", page + 1),
string.Join("\n", quotes.Select(q => $"{q.Keyword,-20} by {q.AuthorName}")))
.ConfigureAwait(false);
await Context.Channel.SendConfirmAsync(GetText("quotes_page", page + 1),
string.Join("\n", quotes.Select(q => $"`#{q.Id}` {Format.Bold(q.Keyword),-20} by {q.AuthorName}")))
.ConfigureAwait(false);
else
await ReplyErrorLocalized("quotes_page_none").ConfigureAwait(false);
}
@ -52,7 +52,8 @@ namespace NadekoBot.Modules.Utility
Quote quote;
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)
@ -61,7 +62,11 @@ namespace NadekoBot.Modules.Utility
CREmbed 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)
{
_log.Warn("Sending CREmbed failed");
@ -69,28 +74,31 @@ namespace NadekoBot.Modules.Utility
}
return;
}
await Context.Channel.SendMessageAsync("📣 " + quote.Text.SanitizeMentions());
await Context.Channel.SendMessageAsync($"`#{quote.Id}` 📣 " + quote.Text.SanitizeMentions());
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task SearchQuote(string keyword, [Remainder] string text)
{
if (string.IsNullOrWhiteSpace(keyword) || string.IsNullOrWhiteSpace(text))
return;
if (string.IsNullOrWhiteSpace(keyword) || string.IsNullOrWhiteSpace(text))
return;
keyword = keyword.ToUpperInvariant();
Quote keywordquote;
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)
return;
await Context.Channel.SendMessageAsync("💬 " + keyword + ": " + keywordquote.Text.SanitizeMentions());
await Context.Channel.SendMessageAsync("💬 " + keyword.ToLowerInvariant() + ": " +
keywordquote.Text.SanitizeMentions());
}
[NadekoCommand, Usage, Description, Aliases]
@ -119,36 +127,29 @@ namespace NadekoBot.Modules.Utility
[NadekoCommand, Usage, Description, Aliases]
[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;
string response;
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");
}
else
{
var q = qs[new NadekoRandom().Next(0, qs.Length)];
uow.Quotes.Remove(q);
await uow.CompleteAsync().ConfigureAwait(false);
sucess = true;
response = GetText("quote_deleted");
response = GetText("quote_deleted", id);
}
}
if(sucess)
if (sucess)
await Context.Channel.SendConfirmAsync(response);
else
await Context.Channel.SendErrorAsync(response);
@ -166,9 +167,7 @@ namespace NadekoBot.Modules.Utility
using (var uow = DbHandler.UnitOfWork())
{
var quotes = uow.Quotes.GetAllQuotesByKeyword(Context.Guild.Id, keyword);
//todo kwoth please don't be complete retard
uow.Quotes.RemoveRange(quotes.ToArray());//wtf?!
uow.Quotes.RemoveAllByKeyword(Context.Guild.Id, keyword.ToUpperInvariant());
await uow.CompleteAsync();
}
@ -177,4 +176,4 @@ namespace NadekoBot.Modules.Utility
}
}
}
}
}

View File

@ -64,7 +64,10 @@ namespace NadekoBot.Modules.Utility
IMessageChannel ch;
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
{
@ -100,25 +103,20 @@ namespace NadekoBot.Modules.Utility
[Priority(1)]
public async Task Remind(MeOrHere meorhere, string timeStr, [Remainder] string message)
{
IMessageChannel target;
if (meorhere == MeOrHere.Me)
{
target = await ((IGuildUser)Context.User).CreateDMChannelAsync().ConfigureAwait(false);
}
else
{
target = Context.Channel;
}
await Remind(target, timeStr, message).ConfigureAwait(false);
ulong target;
target = meorhere == MeOrHere.Me ? Context.User.Id : Context.Channel.Id;
await RemindInternal(target, meorhere == MeOrHere.Me, timeStr, message).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageMessages)]
[Priority(0)]
public async Task Remind(IMessageChannel ch, string timeStr, [Remainder] string message)
{
var channel = (ITextChannel)Context.Channel;
public Task Remind(ITextChannel channel, string timeStr, [Remainder] string message) =>
RemindInternal(channel.Id, false, timeStr, message);
public async Task RemindInternal(ulong targetId, bool isPrivate, string timeStr, [Remainder] string message)
{
var m = _regex.Match(timeStr);
if (m.Length == 0)
@ -148,7 +146,7 @@ namespace NadekoBot.Modules.Utility
(groupName == "hours" && value > 23) ||
(groupName == "minutes" && value > 59))
{
await channel.SendErrorAsync($"Invalid {groupName} value.").ConfigureAwait(false);
await Context.Channel.SendErrorAsync($"Invalid {groupName} value.").ConfigureAwait(false);
return;
}
namesAndValues[groupName] = value;
@ -163,12 +161,12 @@ namespace NadekoBot.Modules.Utility
var rem = new Reminder
{
ChannelId = ch.Id,
IsPrivate = ch is IDMChannel,
ChannelId = targetId,
IsPrivate = isPrivate,
When = time,
Message = message,
UserId = Context.User.Id,
ServerId = channel.Guild.Id
ServerId = Context.Guild.Id
};
using (var uow = DbHandler.UnitOfWork())
@ -179,9 +177,9 @@ namespace NadekoBot.Modules.Utility
try
{
await channel.SendConfirmAsync(
await Context.Channel.SendConfirmAsync(
"⏰ " + 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(output),
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", ".")]
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]
//[RequireContext(ContextType.Guild)]
@ -114,7 +114,7 @@ namespace NadekoBot.Modules.Utility
Timer t;
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);
await ReplyConfirmLocalized("rrc_stop", Format.Bold(role.Name)).ConfigureAwait(false);
@ -157,7 +157,7 @@ namespace NadekoBot.Modules.Utility
catch { }
}, null, 0, timeout * 1000);
rotatingRoleColors.AddOrUpdate(role.Id, t, (key, old) =>
_rotatingRoleColors.AddOrUpdate(role.Id, t, (key, old) =>
{
old.Change(Timeout.Infinite, Timeout.Infinite);
return t;
@ -217,33 +217,18 @@ namespace NadekoBot.Modules.Utility
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task InRole(params IRole[] roles)
public async Task InRole([Remainder] IRole role)
{
if (roles.Length == 0)
return;
var send = " " + Format.Bold(GetText("inrole_list"));
var rng = new NadekoRandom();
var usrs = (await Context.Guild.GetUsersAsync()).ToArray();
foreach (var role in roles.Where(r => r.Id != Context.Guild.Id))
{
send += $"```css\n[{role.Name}]\n";
send += string.Join(", ", usrs.Where(u => u.RoleIds.Contains(role.Id)).Select(u => u.ToString()));
send += "\n```";
}
var usr = (IGuildUser)Context.User;
while (send.Length > 2000)
{
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);
var roleUsers = usrs.Where(u => u.RoleIds.Contains(role.Id)).Select(u => u.ToString())
.ToArray();
var embed = new EmbedBuilder().WithOkColor()
.WithTitle(" " + Format.Bold(GetText("inrole_list", Format.Bold(role.Name))) + $" - {roleUsers.Length}")
.WithDescription(string.Join(", ", roleUsers
.OrderBy(x => rng.Next())
.Take(50)));
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
}
[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 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 JsonConvert.SerializeObject(grouping, Formatting.Indented).ToStream().ConfigureAwait(false), title, title).ConfigureAwait(false);
}

View File

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

View File

@ -96,7 +96,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string acro_desc {
get {
@ -150,7 +150,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string addcustreact_desc {
get {
@ -177,7 +177,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string addplaying_desc {
get {
@ -231,7 +231,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string adsarm_desc {
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>
/// Looks up a localized string similar to allchnlmdls acm.
/// </summary>
@ -420,7 +474,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string announce_desc {
get {
@ -501,7 +555,7 @@ namespace NadekoBot.Resources {
}
/// <summary>
/// Looks up a localized string similar to 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..
/// Looks up a localized string similar to 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..
/// </summary>
public static string antispam_desc {
get {
@ -690,7 +744,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string autoplay_desc {
get {
@ -1014,7 +1068,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string byedel_desc {
get {
@ -1041,7 +1095,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string byemsg_desc {
get {
@ -1068,7 +1122,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string calcops_desc {
get {
@ -1419,7 +1473,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string chnlfilterinv_desc {
get {
@ -1446,7 +1500,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string chnlfilterwords_desc {
get {
@ -1527,7 +1581,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string chucknorris_desc {
get {
@ -1743,7 +1797,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string cmdcooldown_desc {
get {
@ -1770,7 +1824,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string cmdcosts_desc {
get {
@ -1851,7 +1905,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string commands_desc {
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>
/// Looks up a localized string similar to createinvite crinv.
/// </summary>
@ -2310,7 +2418,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string delcustreact_desc {
get {
@ -2337,7 +2445,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string deleteplaylist_desc {
get {
@ -2364,7 +2472,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string deletequote_desc {
get {
@ -2373,7 +2481,7 @@ namespace NadekoBot.Resources {
}
/// <summary>
/// Looks up a localized string similar to `{0}delq abc`.
/// Looks up a localized string similar to `{0}delq 123456`.
/// </summary>
public static string deletequote_usage {
get {
@ -2391,7 +2499,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string delmsgoncmd_desc {
get {
@ -2607,7 +2715,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string donators_desc {
get {
@ -2715,7 +2823,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string fairplay_desc {
get {
@ -2823,7 +2931,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string forwardtoall_desc {
get {
@ -2931,7 +3039,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string google_desc {
get {
@ -3012,7 +3120,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string greetdel_desc {
get {
@ -3066,7 +3174,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string greetdmmsg_desc {
get {
@ -3093,7 +3201,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string greetmsg_desc {
get {
@ -3156,7 +3264,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string h_usage {
get {
@ -3174,7 +3282,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string half_desc {
get {
@ -3282,7 +3390,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string heal_desc {
get {
@ -3498,7 +3606,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string image_desc {
get {
@ -3552,7 +3660,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string inrole_desc {
get {
@ -3561,7 +3669,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string inrole_usage {
get {
@ -3687,7 +3795,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string languageset_desc {
get {
@ -3768,7 +3876,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string lcsc_desc {
get {
@ -3795,7 +3903,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string leaderboard_desc {
get {
@ -3822,7 +3930,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string leave_desc {
get {
@ -4128,7 +4236,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string listwar_usage {
get {
@ -4173,7 +4281,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string load_desc {
get {
@ -4254,7 +4362,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string log_desc {
get {
@ -4308,7 +4416,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string logignore_desc {
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>
/// Looks up a localized string similar to magicitem mi.
/// </summary>
@ -4470,7 +4632,7 @@ namespace NadekoBot.Resources {
}
/// <summary>
/// Looks up a localized string similar to Shows a random magicitem from &lt;https://1d4chan.org/wiki/List_of_/tg/%27s_magic_items&gt;.
/// Looks up a localized string similar to Shows a random magic item from &lt;https://1d4chan.org/wiki/List_of_/tg/%27s_magic_items&gt;.
/// </summary>
public static string magicitem_desc {
get {
@ -4524,7 +4686,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string mal_desc {
get {
@ -4578,7 +4740,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string max_desc {
get {
@ -4713,7 +4875,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string mentionrole_desc {
get {
@ -4848,7 +5010,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string moveperm_desc {
get {
@ -4902,7 +5064,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string mute_desc {
get {
@ -4911,7 +5073,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string mute_usage {
get {
@ -4956,7 +5118,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string nowplaying_desc {
get {
@ -5145,7 +5307,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string permrole_desc {
get {
@ -5307,7 +5469,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string playlists_desc {
get {
@ -5469,7 +5631,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string prune_desc {
get {
@ -5523,7 +5685,7 @@ namespace NadekoBot.Resources {
}
/// <summary>
/// Looks up a localized string similar to Queue a song using keywords or a link. Bot will join your voice channel.**You must be in a voice channel**..
/// Looks up a localized string similar to Queue a song using keywords or a link. Bot will join your voice channel. **You must be in a voice channel**..
/// </summary>
public static string queue_desc {
get {
@ -5793,7 +5955,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string remind_desc {
get {
@ -5820,7 +5982,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string remindtemplate_desc {
get {
@ -5901,7 +6063,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string removeperm_desc {
get {
@ -6009,7 +6171,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string renamerole_desc {
get {
@ -6036,7 +6198,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string repeat_desc {
get {
@ -6198,7 +6360,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string resetpermissions_desc {
get {
@ -6252,7 +6414,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string revav_desc {
get {
@ -6279,7 +6441,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string revimg_desc {
get {
@ -6387,7 +6549,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string roles_desc {
get {
@ -6414,7 +6576,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string roll_desc {
get {
@ -6441,7 +6603,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string rolluo_desc {
get {
@ -6522,7 +6684,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string rps_desc {
get {
@ -6630,7 +6792,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string save_desc {
get {
@ -6738,7 +6900,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string send_desc {
get {
@ -6765,7 +6927,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string serverblacklist_desc {
get {
@ -7548,7 +7710,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string soundcloudpl_desc {
get {
@ -7575,7 +7737,7 @@ namespace NadekoBot.Resources {
}
/// <summary>
/// Looks up a localized string similar to Queue a soundcloud song using keywords. Bot will join your voice channel.**You must be in a voice channel**..
/// Looks up a localized string similar to Queue a soundcloud song using keywords. Bot will join your voice channel. **You must be in a voice channel**..
/// </summary>
public static string soundcloudqueue_desc {
get {
@ -7629,7 +7791,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string srvrfilterinv_desc {
get {
@ -7656,7 +7818,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string srvrfilterwords_desc {
get {
@ -8088,7 +8250,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string trivia_desc {
get {
@ -8439,7 +8601,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string userblacklist_desc {
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>
/// Looks up a localized string similar to verbose v.
/// </summary>
@ -8682,7 +8898,7 @@ namespace NadekoBot.Resources {
}
/// <summary>
/// Looks up a localized string similar to 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..
/// Looks up a localized string similar to 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..
/// </summary>
public static string voiceplustext_desc {
get {
@ -8763,7 +8979,7 @@ namespace NadekoBot.Resources {
}
/// <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>
public static string volume_desc {
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>
</data>
<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 name="hgit_cmd" xml:space="preserve">
<value>hgit</value>
@ -157,7 +157,7 @@
<value>commands cmds</value>
</data>
<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 name="commands_usage" xml:space="preserve">
<value>`{0}commands Administration` or `{0}cmds Admin`</value>
@ -166,7 +166,7 @@
<value>greetdel grdel</value>
</data>
<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 name="greetdel_usage" xml:space="preserve">
<value>`{0}greetdel 0` or `{0}greetdel 30`</value>
@ -184,7 +184,7 @@
<value>greetmsg</value>
</data>
<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 name="greetmsg_usage" xml:space="preserve">
<value>`{0}greetmsg Welcome, %user%.`</value>
@ -202,7 +202,7 @@
<value>byemsg</value>
</data>
<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 name="byemsg_usage" xml:space="preserve">
<value>`{0}byemsg %user% has left.`</value>
@ -211,7 +211,7 @@
<value>byedel</value>
</data>
<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 name="byedel_usage" xml:space="preserve">
<value>`{0}byedel 0` or `{0}byedel 30`</value>
@ -238,7 +238,7 @@
<value>logignore</value>
</data>
<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 name="logignore_usage" xml:space="preserve">
<value>`{0}logignore`</value>
@ -274,7 +274,7 @@
<value>repeat</value>
</data>
<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 name="repeat_usage" xml:space="preserve">
<value>`{0}repeat 5 Hello there`</value>
@ -292,7 +292,7 @@
<value>addplaying adpl</value>
</data>
<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 name="addplaying_usage" xml:space="preserve">
<value>`{0}adpl`</value>
@ -337,7 +337,7 @@
<value>voice+text v+t</value>
</data>
<data name="voiceplustext_desc" xml:space="preserve">
<value>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.</value>
<value>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.</value>
</data>
<data name="voiceplustext_usage" xml:space="preserve">
<value>`{0}v+t`</value>
@ -364,7 +364,7 @@
<value>lcsc</value>
</data>
<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 name="lcsc_usage" xml:space="preserve">
<value>`{0}lcsc`</value>
@ -427,7 +427,7 @@
<value>addcustreact acr</value>
</data>
<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 name="addcustreact_usage" xml:space="preserve">
<value>`{0}acr "hello" Hi there %user%`</value>
@ -463,7 +463,7 @@
<value>delcustreact dcr</value>
</data>
<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 name="delcustreact_usage" xml:space="preserve">
<value>`{0}dcr 5`</value>
@ -481,7 +481,7 @@
<value>leave</value>
</data>
<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 name="leave_usage" xml:space="preserve">
<value>`{0}leave 123123123331`</value>
@ -490,7 +490,7 @@
<value>delmsgoncmd</value>
</data>
<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 name="delmsgoncmd_usage" xml:space="preserve">
<value>`{0}delmsgoncmd`</value>
@ -526,7 +526,7 @@
<value>renamerole renr</value>
</data>
<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 name="renamerole_usage" xml:space="preserve">
<value>`{0}renr "First role" SecondRole`</value>
@ -589,10 +589,10 @@
<value>mute</value>
</data>
<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 name="mute_usage" xml:space="preserve">
<value>`{0}mute @Someone`</value>
<value>`{0}mute @Someone` or `{0}mute 30 @Someone`</value>
</data>
<data name="voiceunmute_cmd" xml:space="preserve">
<value>voiceunmute</value>
@ -679,7 +679,7 @@
<value>prune clr</value>
</data>
<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 name="prune_usage" xml:space="preserve">
<value>`{0}prune` or `{0}prune 5` or `{0}prune @Someone` or `{0}prune @Someone X`</value>
@ -724,7 +724,7 @@
<value>send</value>
</data>
<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 name="send_usage" xml:space="preserve">
<value>`{0}send serverid|c:channelid message` or `{0}send serverid|u:userid message`</value>
@ -733,7 +733,7 @@
<value>mentionrole menro</value>
</data>
<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 name="mentionrole_usage" xml:space="preserve">
<value>`{0}menro RoleName`</value>
@ -751,7 +751,7 @@
<value>donators</value>
</data>
<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 name="donators_usage" xml:space="preserve">
<value>`{0}donators`</value>
@ -769,7 +769,7 @@
<value>announce</value>
</data>
<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 name="announce_usage" xml:space="preserve">
<value>`{0}announce Useless spam`</value>
@ -787,7 +787,7 @@
<value>remind</value>
</data>
<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 name="remind_usage" xml:space="preserve">
<value>`{0}remind me 1d5h Do something` or `{0}remind #general 1m Start now!`</value>
@ -796,7 +796,7 @@
<value>remindtemplate</value>
</data>
<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 name="remindtemplate_usage" xml:space="preserve">
<value>`{0}remindtemplate %user%, do %message%!`</value>
@ -841,10 +841,10 @@
<value>inrole</value>
</data>
<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 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 name="checkmyperms_cmd" xml:space="preserve">
<value>checkmyperms</value>
@ -895,7 +895,7 @@
<value>roles</value>
</data>
<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 name="roles_usage" xml:space="preserve">
<value>`{0}roles 2` or `{0}roles @Someone`</value>
@ -913,7 +913,7 @@
<value>chnlfilterinv cfi</value>
</data>
<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 name="chnlfilterinv_usage" xml:space="preserve">
<value>`{0}cfi`</value>
@ -922,7 +922,7 @@
<value>srvrfilterinv sfi</value>
</data>
<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 name="srvrfilterinv_usage" xml:space="preserve">
<value>`{0}sfi`</value>
@ -931,7 +931,7 @@
<value>chnlfilterwords cfw</value>
</data>
<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 name="chnlfilterwords_usage" xml:space="preserve">
<value>`{0}cfw`</value>
@ -958,7 +958,7 @@
<value>srvrfilterwords sfw</value>
</data>
<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 name="srvrfilterwords_usage" xml:space="preserve">
<value>`{0}sfw`</value>
@ -967,7 +967,7 @@
<value>permrole pr</value>
</data>
<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 name="permrole_usage" xml:space="preserve">
<value>`{0}pr role`</value>
@ -1084,7 +1084,7 @@
<value>ubl</value>
</data>
<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 name="userblacklist_usage" xml:space="preserve">
<value>`{0}ubl add @SomeUser` or `{0}ubl rem 12312312313`</value>
@ -1102,7 +1102,7 @@
<value>sbl</value>
</data>
<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 name="serverblacklist_usage" xml:space="preserve">
<value>`{0}sbl add 12312321312` or `{0}sbl rem SomeTrashServer`</value>
@ -1111,7 +1111,7 @@
<value>cmdcooldown cmdcd</value>
</data>
<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 name="cmdcooldown_usage" xml:space="preserve">
<value>`{0}cmdcd "some cmd" 5`</value>
@ -1156,10 +1156,10 @@
<value>deletequote delq</value>
</data>
<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 name="deletequote_usage" xml:space="preserve">
<value>`{0}delq abc`</value>
<value>`{0}delq 123456`</value>
</data>
<data name="draw_cmd" xml:space="preserve">
<value>draw</value>
@ -1201,7 +1201,7 @@
<value>roll</value>
</data>
<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 name="roll_usage" xml:space="preserve">
<value>`{0}roll` or `{0}roll 7` or `{0}roll 3d5` or `{0}roll 5dF`</value>
@ -1210,7 +1210,7 @@
<value>rolluo</value>
</data>
<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 name="rolluo_usage" xml:space="preserve">
<value>`{0}rolluo` or `{0}rolluo 7` or `{0}rolluo 3d5`</value>
@ -1291,7 +1291,7 @@
<value>leaderboard lb</value>
</data>
<data name="leaderboard_desc" xml:space="preserve">
<value>Displays bot currency leaderboard.</value>
<value>Displays the bot's currency leaderboard.</value>
</data>
<data name="leaderboard_usage" xml:space="preserve">
<value>`{0}lb`</value>
@ -1300,7 +1300,7 @@
<value>trivia t</value>
</data>
<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 name="trivia_usage" xml:space="preserve">
<value>`{0}t` or `{0}t 5 nohint`</value>
@ -1426,7 +1426,7 @@
<value>rps</value>
</data>
<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 name="rps_usage" xml:space="preserve">
<value>`{0}rps scissors`</value>
@ -1480,7 +1480,7 @@
<value>queue q yq</value>
</data>
<data name="queue_desc" xml:space="preserve">
<value>Queue a song using keywords or a link. Bot will join your voice channel.**You must be in a voice channel**.</value>
<value>Queue a song using keywords or a link. Bot will join your voice channel. **You must be in a voice channel**.</value>
</data>
<data name="queue_usage" xml:space="preserve">
<value>`{0}q Dream Of Venice`</value>
@ -1489,7 +1489,7 @@
<value>soundcloudqueue sq</value>
</data>
<data name="soundcloudqueue_desc" xml:space="preserve">
<value>Queue a soundcloud song using keywords. Bot will join your voice channel.**You must be in a voice channel**.</value>
<value>Queue a soundcloud song using keywords. Bot will join your voice channel. **You must be in a voice channel**.</value>
</data>
<data name="soundcloudqueue_usage" xml:space="preserve">
<value>`{0}sq Dream Of Venice`</value>
@ -1507,7 +1507,7 @@
<value>nowplaying np</value>
</data>
<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 name="nowplaying_usage" xml:space="preserve">
<value>`{0}np`</value>
@ -1516,7 +1516,7 @@
<value>volume vol</value>
</data>
<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 name="volume_usage" xml:space="preserve">
<value>`{0}vol 50`</value>
@ -1534,7 +1534,7 @@
<value>max</value>
</data>
<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 name="max_usage" xml:space="preserve">
<value>`{0}max`</value>
@ -1543,7 +1543,7 @@
<value>half</value>
</data>
<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 name="half_usage" xml:space="preserve">
<value>`{0}half`</value>
@ -1561,7 +1561,7 @@
<value>soundcloudpl scpl</value>
</data>
<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 name="soundcloudpl_usage" xml:space="preserve">
<value>`{0}scpl soundcloudseturl`</value>
@ -1660,7 +1660,7 @@
<value>save</value>
</data>
<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 name="save_usage" xml:space="preserve">
<value>`{0}save classical1`</value>
@ -1669,7 +1669,7 @@
<value>load</value>
</data>
<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 name="load_usage" xml:space="preserve">
<value>`{0}load 5`</value>
@ -1678,7 +1678,7 @@
<value>playlists pls</value>
</data>
<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 name="playlists_usage" xml:space="preserve">
<value>`{0}pls 1`</value>
@ -1687,7 +1687,7 @@
<value>deleteplaylist delpls</value>
</data>
<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 name="deleteplaylist_usage" xml:space="preserve">
<value>`{0}delpls animu-5`</value>
@ -1705,7 +1705,7 @@
<value>autoplay ap</value>
</data>
<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 name="autoplay_usage" xml:space="preserve">
<value>`{0}ap`</value>
@ -1939,7 +1939,7 @@
<value>image img</value>
</data>
<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 name="image_usage" xml:space="preserve">
<value>`{0}img cute kitten`</value>
@ -1966,7 +1966,7 @@
<value>google g</value>
</data>
<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 name="google_usage" xml:space="preserve">
<value>`{0}google query`</value>
@ -2029,7 +2029,7 @@
<value>chucknorris cn</value>
</data>
<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 name="chucknorris_usage" xml:space="preserve">
<value>`{0}cn`</value>
@ -2038,7 +2038,7 @@
<value>magicitem mi</value>
</data>
<data name="magicitem_desc" xml:space="preserve">
<value>Shows a random magicitem from &lt;https://1d4chan.org/wiki/List_of_/tg/%27s_magic_items&gt;</value>
<value>Shows a random magic item from &lt;https://1d4chan.org/wiki/List_of_/tg/%27s_magic_items&gt;</value>
</data>
<data name="magicitem_usage" xml:space="preserve">
<value>`{0}mi`</value>
@ -2047,7 +2047,7 @@
<value>revav</value>
</data>
<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 name="revav_usage" xml:space="preserve">
<value>`{0}revav "@SomeGuy"`</value>
@ -2056,7 +2056,7 @@
<value>revimg</value>
</data>
<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 name="revimg_usage" xml:space="preserve">
<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>
</data>
<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 name="claim_cmd" xml:space="preserve">
<value>claim call c</value>
@ -2296,7 +2296,7 @@
<value>readme guide</value>
</data>
<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 name="calcops_usage" xml:space="preserve">
<value>`{0}calcops`</value>
@ -2320,7 +2320,7 @@
<value>`{0}greetdmmsg Welcome to the server, %user%`.</value>
</data>
<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 name="cash_desc" xml:space="preserve">
<value>Check how much currency a person has. (Defaults to yourself)</value>
@ -2350,7 +2350,7 @@
<value>allusrmdls aum</value>
</data>
<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 name="moveperm_usage" xml:space="preserve">
<value>`{0}mp 2 4`</value>
@ -2359,7 +2359,7 @@
<value>moveperm mp</value>
</data>
<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 name="removeperm_usage" xml:space="preserve">
<value>`{0}rp 1`</value>
@ -2416,7 +2416,7 @@
<value>fwtoall</value>
</data>
<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 name="forwardtoall_usage" xml:space="preserve">
<value>`{0}fwtoall`</value>
@ -2425,7 +2425,7 @@
<value>resetperms</value>
</data>
<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 name="resetpermissions_usage" xml:space="preserve">
<value>`{0}resetperms`</value>
@ -2443,7 +2443,7 @@
<value>antispam</value>
</data>
<data name="antispam_desc" xml:space="preserve">
<value>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.</value>
<value>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.</value>
</data>
<data name="antispam_usage" xml:space="preserve">
<value>`{0}antispam 3 Mute` or `{0}antispam 4 Kick` or `{0}antispam 6 Ban`</value>
@ -2488,7 +2488,7 @@
<value>adsarm</value>
</data>
<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 name="adsarm_usage" xml:space="preserve">
<value>`{0}adsarm`</value>
@ -2713,7 +2713,7 @@
<value>heal</value>
</data>
<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 name="heal_usage" xml:space="preserve">
<value>`{0}heal @someone`</value>
@ -2794,7 +2794,7 @@
<value>acrophobia acro</value>
</data>
<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 name="acro_usage" xml:space="preserve">
<value>`{0}acro` or `{0}acro 30`</value>
@ -2812,7 +2812,7 @@
<value>log</value>
</data>
<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 name="log_usage" xml:space="preserve">
<value>`{0}log userpresence` or `{0}log userbanned`</value>
@ -2821,7 +2821,7 @@
<value>fairplay fp</value>
</data>
<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 name="fairplay_usage" xml:space="preserve">
<value>`{0}fp`</value>
@ -2938,7 +2938,7 @@
<value>cmdcosts</value>
</data>
<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 name="cmdcosts_usage" xml:space="preserve">
<value>`{0}cmdcosts` or `{0}cmdcosts 2`</value>
@ -3037,7 +3037,7 @@
<value>mal</value>
</data>
<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 name="mal_usage" xml:space="preserve">
<value>`{0}mal straysocks`</value>
@ -3127,7 +3127,7 @@
<value>languageset langset</value>
</data>
<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 name="languageset_usage" xml:space="preserve">
<value>`{0}langset de-DE ` or `{0}langset default`</value>
@ -3150,4 +3150,76 @@
<data name="rategirl_usage" xml:space="preserve">
<value>`{0}rategirl @SomeGurl`</value>
</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>

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

View File

@ -139,7 +139,7 @@
<value>@{0} You already claimed base #{1}. You can't claim a new one.</value>
</data>
<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 name="clashofclans_enemy" xml:space="preserve">
<value>Enemy</value>
@ -151,10 +151,10 @@
<value>Invalid base number.</value>
</data>
<data name="clashofclans_invalid_size" xml:space="preserve">
<value>Not a Valid war size.</value>
<value>Not a valid war size.</value>
</data>
<data name="clashofclans_list_active_wars" xml:space="preserve">
<value>List Of Active Wars</value>
<value>List of active wars</value>
</data>
<data name="clashofclans_not_claimed" xml:space="preserve">
<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>
</data>
<data name="clashofclans_no_active_wars" xml:space="preserve">
<value>No active wars.</value>
<value>No active war.</value>
</data>
<data name="clashofclans_size" xml:space="preserve">
<value>Size</value>
@ -205,7 +205,7 @@
<value>New Custom Reaction</value>
</data>
<data name="customreactions_no_found" xml:space="preserve">
<value>No custom reactions found.</value>
<value>No custom reaction found.</value>
</data>
<data name="customreactions_no_found_id" xml:space="preserve">
<value>No custom reaction found with that id.</value>
@ -467,11 +467,10 @@ Reason: {1}</value>
Reason: {1}</value>
</data>
<data name="administration_kicked_user" xml:space="preserve">
<value>User Kicked</value>
<value>User kicked</value>
</data>
<data name="administration_lang_list" xml:space="preserve">
<value>List Of Languages
{0}</value>
<value>List of languages</value>
</data>
<data name="administration_lang_set" xml:space="preserve">
<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>
</data>
<data name="administration_msg_del" xml:space="preserve">
<value>Message Deleted in #{0}</value>
<value>Message deleted in #{0}</value>
</data>
<data name="administration_msg_update" xml:space="preserve">
<value>Message Updated in #{0}</value>
<value>Message updated in #{0}</value>
</data>
<data name="administration_muted_pl" xml:space="preserve">
<value>Muted</value>
@ -551,16 +550,16 @@ Reason: {1}</value>
<value>I need **Administration** permission to do that.</value>
</data>
<data name="administration_new_msg" xml:space="preserve">
<value>New Message</value>
<value>New message</value>
</data>
<data name="administration_new_nick" xml:space="preserve">
<value>New Nickname</value>
<value>New nickname</value>
</data>
<data name="administration_new_topic" xml:space="preserve">
<value>New Topic</value>
<value>New topic</value>
</data>
<data name="administration_nick_change" xml:space="preserve">
<value>Nickname Changed</value>
<value>Nickname changed</value>
</data>
<data name="administration_no_server" xml:space="preserve">
<value>Can't find that server</value>
@ -569,13 +568,13 @@ Reason: {1}</value>
<value>No shard with that ID found.</value>
</data>
<data name="administration_old_msg" xml:space="preserve">
<value>Old Message</value>
<value>Old message</value>
</data>
<data name="administration_old_nick" xml:space="preserve">
<value>Old Nickname</value>
<value>Old nickname</value>
</data>
<data name="administration_old_topic" xml:space="preserve">
<value>Old Topic</value>
<value>Old topic</value>
</data>
<data name="administration_perms" xml:space="preserve">
<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>
</data>
<data name="administration_prot_active" xml:space="preserve">
<value>Active Protections</value>
<value>Active protections</value>
</data>
<data name="administration_prot_disable" xml:space="preserve">
<value>{0} has been **disabled** on this server.</value>
@ -596,7 +595,7 @@ Reason: {1}</value>
<value>Error. I need ManageRoles permission</value>
</data>
<data name="administration_prot_none" xml:space="preserve">
<value>No protections enabled.</value>
<value>No protection enabled.</value>
</data>
<data name="administration_raid_cnt" xml:space="preserve">
<value>User threshold must be between {0} and {1}.</value>
@ -755,10 +754,10 @@ Reason: {1}</value>
__IgnoredChannels__: {2}</value>
</data>
<data name="administration_text_chan_created" xml:space="preserve">
<value>Text Channel Created</value>
<value>Text channel created.</value>
</data>
<data name="administration_text_chan_destroyed" xml:space="preserve">
<value>Text Channel Destroyed </value>
<value>Text channel destroyed.</value>
</data>
<data name="administration_undeafen" xml:space="preserve">
<value>Undeafen successful.</value>
@ -771,13 +770,13 @@ Reason: {1}</value>
<value>Username</value>
</data>
<data name="administration_username_changed" xml:space="preserve">
<value>Username Changed</value>
<value>Username changed</value>
</data>
<data name="administration_users" xml:space="preserve">
<value>Users</value>
</data>
<data name="administration_user_banned" xml:space="preserve">
<value>User Banned</value>
<value>User banned</value>
</data>
<data name="administration_user_chat_mute" xml:space="preserve">
<value>{0} has been **muted** from chatting.</value>
@ -786,19 +785,19 @@ Reason: {1}</value>
<value>{0} has been **unmuted** from chatting.</value>
</data>
<data name="administration_user_joined" xml:space="preserve">
<value>User Joined</value>
<value>User joined</value>
</data>
<data name="administration_user_left" xml:space="preserve">
<value>User Left</value>
<value>User left</value>
</data>
<data name="administration_user_muted" xml:space="preserve">
<value>{0} has been **muted** from text and voice chat.</value>
</data>
<data name="administration_user_role_add" xml:space="preserve">
<value>User's Role Added</value>
<value>User's role added</value>
</data>
<data name="administration_user_role_rem" xml:space="preserve">
<value>User's Role Removed</value>
<value>User's role removed</value>
</data>
<data name="administration_user_status_change" xml:space="preserve">
<value>{0} is now {1}</value>
@ -822,10 +821,10 @@ Reason: {1}</value>
<value>{0} has been **voice unmuted**.</value>
</data>
<data name="administration_voice_chan_created" xml:space="preserve">
<value>Voice Channel Created</value>
<value>Voice channel created</value>
</data>
<data name="administration_voice_chan_destroyed" xml:space="preserve">
<value>Voice Channel Destroyed</value>
<value>Voice channel destroyed</value>
</data>
<data name="administration_vt_disabled" xml:space="preserve">
<value>Disabled voice + text feature.</value>
@ -856,7 +855,7 @@ Reason: {1}</value>
Reason: {1}</value>
</data>
<data name="administration_user_unbanned" xml:space="preserve">
<value>User Unbanned</value>
<value>User unbanned</value>
</data>
<data name="administration_migration_done" xml:space="preserve">
<value>Migration done!</value>
@ -865,10 +864,10 @@ Reason: {1}</value>
<value>Error while migrating, check bot's console for more information.</value>
</data>
<data name="administration_presence_updates" xml:space="preserve">
<value>Presence Updates</value>
<value>Presence updates</value>
</data>
<data name="administration_sb_user" xml:space="preserve">
<value>User Soft-Banned</value>
<value>User soft-banned</value>
</data>
<data name="gambling_awarded" xml:space="preserve">
<value>has awarded {0} to {1}</value>
@ -910,7 +909,7 @@ Reason: {1}</value>
<comment>X has Y flowers</comment>
</data>
<data name="gambling_heads" xml:space="preserve">
<value>Heads</value>
<value>Head</value>
</data>
<data name="gambling_leaderboard" xml:space="preserve">
<value>Leaderboard</value>
@ -931,7 +930,7 @@ Reason: {1}</value>
<value>No more cards in the deck.</value>
</data>
<data name="gambling_raffled_user" xml:space="preserve">
<value>Raffled User</value>
<value>Raffled user</value>
</data>
<data name="gambling_roll" xml:space="preserve">
<value>You rolled {0}.</value>
@ -965,7 +964,7 @@ Lasts {1} seconds. Don't tell anyone. Shhh.</value>
<value>SneakyGameStatus event started</value>
</data>
<data name="gambling_tails" xml:space="preserve">
<value>Tails</value>
<value>Tail</value>
</data>
<data name="gambling_take" xml:space="preserve">
<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>
</data>
<data name="help_bot_owner_only" xml:space="preserve">
<value>Bot Owner Only</value>
<value>Bot owner only</value>
</data>
<data name="help_channel_permission" xml:space="preserve">
<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>
</data>
<data name="help_cmd_and_alias" xml:space="preserve">
<value>Command and aliases</value>
<value>Commands and aliases</value>
</data>
<data name="help_commandlist_regen" xml:space="preserve">
<value>Commandlist Regenerated.</value>
<value>Commandlist regenerated.</value>
</data>
<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>
@ -1009,14 +1008,14 @@ Don't forget to leave your discord name or id in the message.
**Thank you** ♥️</value>
</data>
<data name="help_guide" xml:space="preserve">
<value>**List of Commands**: &lt;{0}&gt;
**Hosting Guides and docs can be found here**: &lt;{1}&gt;</value>
<value>**List of commands**: &lt;{0}&gt;
**Hosting guides and docs can be found here**: &lt;{1}&gt;</value>
</data>
<data name="help_list_of_commands" xml:space="preserve">
<value>List Of Commands</value>
<value>List of commands</value>
</data>
<data name="help_list_of_modules" xml:space="preserve">
<value>List Of Modules</value>
<value>List of modules</value>
</data>
<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>
@ -1028,7 +1027,7 @@ Don't forget to leave your discord name or id in the message.
<value>Requires {0} server permission.</value>
</data>
<data name="help_table_of_contents" xml:space="preserve">
<value>Table Of Contents</value>
<value>Table of contents</value>
</data>
<data name="help_usage" xml:space="preserve">
<value>Usage</value>
@ -1041,7 +1040,7 @@ Don't forget to leave your discord name or id in the message.
<value>Tag</value>
</data>
<data name="gambling_animal_race" xml:space="preserve">
<value>Animal Race</value>
<value>Animal race</value>
</data>
<data name="gambling_animal_race_failed" xml:space="preserve">
<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>
</data>
<data name="gambling_changes_of_heart" xml:space="preserve">
<value>Changes Of Heart</value>
<value>Changes of heart</value>
</data>
<data name="gambling_claimed_by" xml:space="preserve">
<value>Claimed By</value>
<value>Claimed by</value>
</data>
<data name="gambling_divorces" xml:space="preserve">
<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>
</data>
<data name="games_submissions_closed" xml:space="preserve">
<value>Submissions Closed</value>
<value>Submissions closed</value>
</data>
<data name="gambling_animal_race_already_started" xml:space="preserve">
<value>Animal Race is already running.</value>
</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">
<value>Total: {0} Average: {1}</value>
</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>
</data>
<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>
</data>
<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 name="games_failed_loading_question" xml:space="preserve">
<value>Failed loading a question.</value>
</data>
<data name="games_game_started" xml:space="preserve">
<value>Game Started</value>
<value>Game started</value>
</data>
<data name="games_hangman_game_started" xml:space="preserve">
<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>
</data>
<data name="games_ttt_has_won" xml:space="preserve">
<value>{0} has Won!</value>
<value>{0} has won!</value>
</data>
<data name="games_ttt_matched_three" xml:space="preserve">
<value>Matched Three</value>
<value>Matched three</value>
</data>
<data name="games_ttt_no_moves" xml:space="preserve">
<value>No moves left!</value>
</data>
<data name="games_ttt_time_expired" xml:space="preserve">
<value>Time Expired!</value>
<value>Time expired!</value>
</data>
<data name="games_ttt_users_move" xml:space="preserve">
<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>
</data>
<data name="music_finished_song" xml:space="preserve">
<value>Finished Song</value>
<value>Finished song</value>
</data>
<data name="music_fp_disabled" xml:space="preserve">
<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>
</data>
<data name="music_now_playing" xml:space="preserve">
<value>Now Playing</value>
<value>Now playing</value>
</data>
<data name="music_no_player" xml:space="preserve">
<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>
</data>
<data name="music_player_queue" xml:space="preserve">
<value>Player Queue - Page {0}/{1}</value>
<value>Player queue - Page {0}/{1}</value>
</data>
<data name="music_playing_song" xml:space="preserve">
<value>Playing Song</value>
<value>Playing song</value>
</data>
<data name="music_playlists" xml:space="preserve">
<value>`#{0}` - **{1}** by *{2}* ({3} songs)</value>
</data>
<data name="music_playlists_page" xml:space="preserve">
<value>Page {0} of Saved Playlists</value>
<value>Page {0} of saved playlists</value>
</data>
<data name="music_playlist_deleted" xml:space="preserve">
<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>
</data>
<data name="music_playlist_saved" xml:space="preserve">
<value>Playlist Saved</value>
<value>Playlist saved</value>
</data>
<data name="music_play_limit" xml:space="preserve">
<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>
</data>
<data name="music_queued_song" xml:space="preserve">
<value>Queued Song</value>
<value>Queued song</value>
</data>
<data name="music_queue_cleared" xml:space="preserve">
<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>
</data>
<data name="music_repeating_cur_song" xml:space="preserve">
<value>Repeating Current Song</value>
<value>Repeating current song</value>
</data>
<data name="music_repeating_playlist" xml:space="preserve">
<value>Repeating Playlist</value>
<value>Repeating playlist</value>
</data>
<data name="music_repeating_track" xml:space="preserve">
<value>Repeating Track</value>
<value>Repeating track</value>
</data>
<data name="music_repeating_track_stopped" xml:space="preserve">
<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>
</data>
<data name="music_songs_shuffled" xml:space="preserve">
<value>Songs shuffled.</value>
<value>Songs shuffled</value>
</data>
<data name="music_song_moved" xml:space="preserve">
<value>Song Moved</value>
<value>Song moved</value>
</data>
<data name="music_time_format" xml:space="preserve">
<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>
</data>
<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 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 name="permissions_allowed" xml:space="preserve">
<value>Allowed</value>
</data>
<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 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 name="permissions_asm_disable" xml:space="preserve">
<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>
</data>
<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 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 name="permissions_blacklisted" xml:space="preserve">
<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>
</data>
<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 name="permissions_cmdcd_none" xml:space="preserve">
<value>No command cooldowns set.</value>
</data>
<data name="permissions_command_costs" xml:space="preserve">
<value>Command Costs</value>
<value>Command costs</value>
</data>
<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 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 name="permissions_denied" xml:space="preserve">
<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>
</data>
<data name="permissions_filter_word_list" xml:space="preserve">
<value>List Of Filtered Words</value>
<value>List of filtered words</value>
</data>
<data name="permissions_filter_word_remove" xml:space="preserve">
<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 name="permissions_of_command" xml:space="preserve">
<value>command</value>
<comment>Gen (of command)</comment>
<comment>Gen. (of command)</comment>
</data>
<data name="permissions_of_module" xml:space="preserve">
<value>module</value>
@ -1682,13 +1684,13 @@ Don't forget to leave your discord name or id in the message.
<value>Comic #</value>
</data>
<data name="searches_compet_loses" xml:space="preserve">
<value>Competitive Loses</value>
<value>Competitive losses</value>
</data>
<data name="searches_compet_played" xml:space="preserve">
<value>Competitive Played</value>
<value>Competitive played</value>
</data>
<data name="searches_compet_rank" xml:space="preserve">
<value>Competitive Rank</value>
<value>Competitive rank</value>
</data>
<data name="searches_compet_wins" xml:space="preserve">
<value>Competitive Wins</value>
@ -1742,7 +1744,7 @@ Don't forget to leave your discord name or id in the message.
<value>Humidity</value>
</data>
<data name="searches_image_search_for" xml:space="preserve">
<value>Image Search For:</value>
<value>Image search for:</value>
</data>
<data name="searches_imdb_fail" xml:space="preserve">
<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>
</data>
<data name="searches_on_hold" xml:space="preserve">
<value>On-Hold</value>
<value>On-hold</value>
</data>
<data name="searches_original_url" xml:space="preserve">
<value>Original Url</value>
<value>Original url</value>
</data>
<data name="searches_osu_api_key" xml:space="preserve">
<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>
</data>
<data name="searches_profile_link" xml:space="preserve">
<value>Profile Link:</value>
<value>Profile link:</value>
</data>
<data name="searches_quality" xml:space="preserve">
<value>Quality:</value>
</data>
<data name="searches_quick_playtime" xml:space="preserve">
<value>Quick Playtime</value>
<value>Quick playtime</value>
</data>
<data name="searches_quick_wins" xml:space="preserve">
<value>Quick Wins</value>
<value>Quick wins</value>
</data>
<data name="searches_rating" xml:space="preserve">
<value>Rating</value>
@ -1833,13 +1835,13 @@ Don't forget to leave your discord name or id in the message.
<value>Score:</value>
</data>
<data name="searches_search_for" xml:space="preserve">
<value>Search For:</value>
<value>Search for:</value>
</data>
<data name="searches_shorten_fail" xml:space="preserve">
<value>Failed to shorten that url.</value>
</data>
<data name="searches_short_url" xml:space="preserve">
<value>Short Url</value>
<value>Short url</value>
</data>
<data name="searches_something_went_wrong" xml:space="preserve">
<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>
</data>
<data name="searches_store_url" xml:space="preserve">
<value>Store Url</value>
<value>Store url</value>
</data>
<data name="searches_streamer_offline" xml:space="preserve">
<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>
</data>
<data name="searches_wind_speed" xml:space="preserve">
<value>Wind Speed</value>
<value>Wind speed</value>
</data>
<data name="searches_x_most_banned_champs" xml:space="preserve">
<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>
</data>
<data name="utility_activity_page" xml:space="preserve">
<value>Activity Page #{0}</value>
<value>Activity page #{0}</value>
</data>
<data name="utility_activity_users_total" xml:space="preserve">
<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>
</data>
<data name="utility_channel_topic" xml:space="preserve">
<value>Channel Topic</value>
<value>Channel topic</value>
</data>
<data name="utility_commands_ran" xml:space="preserve">
<value>Commands Ran</value>
<value>Commands ran</value>
</data>
<data name="utility_convert" xml:space="preserve">
<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>
</data>
<data name="utility_created_at" xml:space="preserve">
<value>Created At</value>
<value>Created at</value>
</data>
<data name="utility_csc_join" xml:space="preserve">
<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>
</data>
<data name="utility_custom_emojis" xml:space="preserve">
<value>Custom Emojis</value>
<value>Custom emojis</value>
</data>
<data name="utility_error" xml:space="preserve">
<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>
</data>
<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 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 name="utility_invalid_value" xml:space="preserve">
<value>Invalid {0} value.</value>
@ -2013,18 +2015,18 @@ Don't forget to leave your discord name or id in the message.
<value>Joined Discord</value>
</data>
<data name="utility_joined_server" xml:space="preserve">
<value>Joined Server</value>
<value>Joined server</value>
</data>
<data name="utility_listservers" xml:space="preserve">
<value>ID: {0}
Members: {1}
OwnerID: {2}</value>
Owner ID: {2}</value>
</data>
<data name="utility_listservers_none" xml:space="preserve">
<value>No servers found on that page.</value>
</data>
<data name="utility_list_of_repeaters" xml:space="preserve">
<value>List of Repeaters</value>
<value>List of repeater</value>
</data>
<data name="utility_members" xml:space="preserve">
<value>Members</value>
@ -2036,7 +2038,7 @@ OwnerID: {2}</value>
<value>Messages</value>
</data>
<data name="utility_message_repeater" xml:space="preserve">
<value>Message Repeater</value>
<value>Message repeater</value>
</data>
<data name="utility_name" xml:space="preserve">
<value>Name</value>
@ -2089,13 +2091,13 @@ OwnerID: {2}</value>
<value>Quote Added</value>
</data>
<data name="utility_quote_deleted" xml:space="preserve">
<value>Deleted a random quote.</value>
<value>Quote #{0} deleted.</value>
</data>
<data name="utility_region" xml:space="preserve">
<value>Region</value>
</data>
<data name="utility_registered_on" xml:space="preserve">
<value>Registered On</value>
<value>Registered on</value>
</data>
<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>
@ -2110,7 +2112,7 @@ OwnerID: {2}</value>
<value>Repeating {0} every {1} day(s), {2} hour(s) and {3} minute(s).</value>
</data>
<data name="utility_repeaters_list" xml:space="preserve">
<value>List Of Repeaters</value>
<value>List of repeaters</value>
</data>
<data name="utility_repeaters_none" xml:space="preserve">
<value>No repeaters running on this server.</value>
@ -2146,13 +2148,13 @@ OwnerID: {2}</value>
<value>{0} of this server is {1}</value>
</data>
<data name="utility_server_info" xml:space="preserve">
<value>Server Info</value>
<value>Server info</value>
</data>
<data name="utility_shard" xml:space="preserve">
<value>Shard</value>
</data>
<data name="utility_shard_stats" xml:space="preserve">
<value>Shard Stats</value>
<value>Shard stats</value>
</data>
<data name="utility_shard_stats_txt" xml:space="preserve">
<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>
</data>
<data name="utility_text_channels" xml:space="preserve">
<value>Text Channels</value>
<value>Text channels</value>
</data>
<data name="utility_togtub_room_link" xml:space="preserve">
<value>Here is your room link:</value>
@ -2183,6 +2185,97 @@ OwnerID: {2}</value>
<value>Users</value>
</data>
<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>
</root>

View File

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

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 System.Collections.Concurrent;
using System.Threading;
using Microsoft.EntityFrameworkCore;
using NadekoBot.DataStructures;
namespace NadekoBot.Services
@ -28,11 +29,7 @@ namespace NadekoBot.Services
}
public class CommandHandler
{
#if GLOBAL_NADEKO
public const int GlobalCommandsCooldown = 1500;
#else
public const int GlobalCommandsCooldown = 750;
#endif
private readonly DiscordShardedClient _client;
private readonly CommandService _commandService;
@ -273,13 +270,76 @@ namespace NadekoBot.Services
// maybe this message is a custom reaction
// todo log custom reaction executions. return struct with info
var crExecuted = await Task.Run(() => CustomReactions.TryExecuteCustomReaction(usrMsg)).ConfigureAwait(false);
if (crExecuted) //if it was, don't execute the command
var cr = await Task.Run(() => CustomReactions.TryGetCustomReaction(usrMsg)).ConfigureAwait(false);
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;
}
}
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;
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
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;
bool resetCommand = cmd.Name == "resetperms";
var resetCommand = cmd.Name == "resetperms";
var module = cmd.Module.GetTopLevelModule();
PermissionCache pc;
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())
{
var config = uow.GuildConfigs.PermissionsFor(context.Guild.Id);
return new PermissionCache()
{
Verbose = config.VerbosePermissions,
RootPermission = config.RootPermission,
PermRole = config.PermissionRole.Trim().ToLowerInvariant(),
};
var config = uow.GuildConfigs.GcWithPermissionsv2For(context.Guild.Id);
Permissions.UpdateCache(config);
}
});
Permissions.Cache.TryGetValue(context.Guild.Id, out pc);
if(pc == null)
throw new Exception("Cache is null.");
}
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));
}

View File

@ -10,8 +10,13 @@ namespace NadekoBot.Services.Database.Models
public Regex Regex { get; set; }
public string Response { get; set; }
public string Trigger { get; set; }
public bool IsRegex { 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

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using static NadekoBot.Modules.Administration.Administration;
namespace NadekoBot.Services.Database.Models
@ -41,7 +42,8 @@ namespace NadekoBot.Services.Database.Models
public HashSet<GCChannelId> GenerateCurrencyChannelIds { get; set; } = new HashSet<GCChannelId>();
//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 string PermissionRole { get; set; } = "Nadeko";
@ -67,9 +69,59 @@ namespace NadekoBot.Services.Database.Models
public string Locale { 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 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 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;
namespace NadekoBot.Services.Database.Models
@ -17,46 +18,101 @@ namespace NadekoBot.Services.Database.Models
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]
private static Permission AllowAllPerm => new Permission()
public static Permissionv2 AllowAllPerm => new Permissionv2()
{
PrimaryTarget = PrimaryPermissionType.Server,
PrimaryTargetId = 0,
SecondaryTarget = SecondaryPermissionType.AllModules,
SecondaryTargetName = "*",
State = true,
Index = 0,
};
[NotMapped]
private static Permission BlockNsfwPerm => new Permission()
private static Permissionv2 BlockNsfwPerm => new Permissionv2()
{
PrimaryTarget = PrimaryPermissionType.Server,
PrimaryTargetId = 0,
SecondaryTarget = SecondaryPermissionType.Module,
SecondaryTargetName = "nsfw",
State = false,
Index = 1
};
public static Permission GetDefaultRoot()
{
var root = AllowAllPerm;
var blockNsfw = BlockNsfwPerm;
public static List<Permissionv2> GetDefaultPermlist =>
new List<Permissionv2>
{
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
{
User,

View File

@ -8,6 +8,6 @@ namespace NadekoBot.Services.Database.Repositories
Currency GetOrCreate(ulong userId);
long GetUserCurrency(ulong userId);
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 LogSettingsFor(ulong guildId);
GuildConfig PermissionsFor(ulong guildId);
IEnumerable<GuildConfig> PermissionsForAll();
IEnumerable<GuildConfig> OldPermissionsForAll();
IEnumerable<GuildConfig> GetAllGuildConfigs();
GuildConfig SetNewRootPermission(ulong guildId, Permission p);
IEnumerable<FollowedStream> GetAllFollowedStreams();
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> SearchQuoteKeywordTextAsync(ulong guildId, string keyword, string text);
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;
}
public IEnumerable<Currency> GetTopRichest(int count) =>
_set.OrderByDescending(c => c.Amount).Take(count).ToList();
public IEnumerable<Currency> GetTopRichest(int count, int skip = 0) =>
_set.OrderByDescending(c => c.Amount).Skip(skip).Take(count).ToList();
public long GetUserCurrency(ulong userId) =>
GetOrCreate(userId).Amount;

View File

@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using NadekoBot.Modules.Permissions;
using System;
namespace NadekoBot.Services.Database.Repositories.Impl
@ -16,11 +15,10 @@ namespace NadekoBot.Services.Database.Repositories.Impl
public IEnumerable<GuildConfig> GetAllGuildConfigs() =>
_set.Include(gc => gc.LogSetting)
.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.CommandAliases)
.Include(gc => gc.UnmuteTimers)
.Include(gc => gc.VcRoleInfos)
.Include(gc => gc.GenerateCurrencyChannelIds)
.Include(gc => gc.FilterInvitesChannelIds)
.Include(gc => gc.FilterWordsChannelIds)
@ -35,8 +33,9 @@ namespace NadekoBot.Services.Database.Repositories.Impl
/// <summary>
/// Gets and creates if it doesn't exist a config for a guild.
/// </summary>
/// <param name="guildId"></param>
/// <returns></returns>
/// <param name="guildId">For which guild</param>
/// <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)
{
GuildConfig config;
@ -44,15 +43,15 @@ namespace NadekoBot.Services.Database.Repositories.Impl
if (includes == null)
{
config = _set
.Include(gc => gc.FollowedStreams)
.Include(gc => gc.LogSetting)
.ThenInclude(ls => ls.IgnoredChannels)
.Include(gc => gc.FilterInvitesChannelIds)
.Include(gc => gc.FilterWordsChannelIds)
.Include(gc => gc.FilteredWords)
.Include(gc => gc.GenerateCurrencyChannelIds)
.Include(gc => gc.CommandCooldowns)
.FirstOrDefault(c => c.GuildId == guildId);
.Include(gc => gc.FollowedStreams)
.Include(gc => gc.LogSetting)
.ThenInclude(ls => ls.IgnoredChannels)
.Include(gc => gc.FilterInvitesChannelIds)
.Include(gc => gc.FilterWordsChannelIds)
.Include(gc => gc.FilteredWords)
.Include(gc => gc.GenerateCurrencyChannelIds)
.Include(gc => gc.CommandCooldowns)
.FirstOrDefault(c => c.GuildId == guildId);
}
else
{
@ -65,7 +64,7 @@ namespace NadekoBot.Services.Database.Repositories.Impl
_set.Add((config = new GuildConfig
{
GuildId = guildId,
RootPermission = Permission.GetDefaultRoot(),
Permissions = Permissionv2.GetDefaultPermlist
}));
_context.SaveChanges();
}
@ -74,41 +73,27 @@ namespace NadekoBot.Services.Database.Repositories.Impl
public GuildConfig LogSettingsFor(ulong guildId)
{
return _set.Include(gc => gc.LogSetting)
var config = _set.Include(gc => gc.LogSetting)
.ThenInclude(gc => gc.IgnoredChannels)
.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)
{
_set.Add((config = new GuildConfig
{
GuildId = guildId,
RootPermission = Permission.GetDefaultRoot(),
Permissions = Permissionv2.GetDefaultPermlist
}));
_context.SaveChanges();
}
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
//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();
}
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() =>
_set.Include(gc => gc.FollowedStreams)
.SelectMany(gc => gc.FollowedStreams)
.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)
{
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.Linq;
using System.Threading.Tasks;
@ -26,7 +28,11 @@ namespace NadekoBot.Services.Database.Repositories.Impl
public Task<Quote> SearchQuoteKeywordTextAsync(ulong guildId, string keyword, string text)
{
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)
{
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)
return false;

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,8 @@
using Discord.Commands;
using System.Linq;
using System.Threading.Tasks;
using NadekoBot.Modules.CustomReactions;
using NadekoBot.Services.Database.Models;
namespace NadekoBot.TypeReaders
{
@ -17,4 +19,46 @@ namespace NadekoBot.TypeReaders
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_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)
{
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)
{
if (lastPage != null)
return embed.WithFooter(efb => efb.WithText($"page {curPage} / {lastPage}"));
return embed.WithFooter(efb => efb.WithText($"{curPage} / {lastPage}"));
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)
@ -278,6 +284,15 @@ namespace NadekoBot.Extensions
return list;
}
}
/// <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)
{
@ -436,4 +451,4 @@ namespace NadekoBot.Extensions
: usr.AvatarUrl;
}
}
}
}

View File

@ -14,5 +14,6 @@
"Type": "sqlite",
"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.YouTube.v3": "1.20.0.701",
"Google.Apis.Customsearch.v1": "1.20.0.466",
"ImageSharp": "1.0.0-alpha2-*",
"ImageSharp.Processing": "1.0.0-alpha2-*",
"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-*",
"ImageSharp": "1.0.0-alpha4-00031",
"ImageSharp.Drawing": "1.0.0-alpha4-00031",
"Microsoft.EntityFrameworkCore": "1.1.0",
"Microsoft.EntityFrameworkCore.Design": "1.1.0",
"Microsoft.EntityFrameworkCore.Sqlite": "1.1.0",