Merge pull request #22 from Kwoth/1.9

ups
This commit is contained in:
samvaio 2017-10-11 13:15:40 +05:30 committed by GitHub
commit fb88e68bfd
39 changed files with 581 additions and 14195 deletions

View File

@ -13,21 +13,21 @@ Compression=lzma2
SolidCompression=yes SolidCompression=yes
OutputDir=userdocs:projekti/NadekoInstallerOutput OutputDir=userdocs:projekti/NadekoInstallerOutput
OutputBaseFilename=NadekoBot-setup-{#version} OutputBaseFilename=NadekoBot-setup-{#version}
AppReadmeFile=http://nadekobot.readthedocs.io/en/1.4/Commands%20List/ AppReadmeFile=http://nadekobot.readthedocs.io/en/latest/Commands%20List/
ArchitecturesInstallIn64BitMode=x64 ArchitecturesInstallIn64BitMode=x64
UsePreviousSetupType=no UsePreviousSetupType=no
DisableWelcomePage=no DisableWelcomePage=no
[Files] [Files]
;install ;install
Source: "src\NadekoBot\bin\Release\netcoreapp1.1\{#target}\publish\*"; DestDir: "{app}\{#sysfolder}"; Permissions: users-full; Flags: recursesubdirs onlyifdoesntexist ignoreversion createallsubdirs; Excludes: "*.pdb, *.db" Source: "src\NadekoBot\bin\Release\netcoreapp2.0\{#target}\publish\*"; DestDir: "{app}\{#sysfolder}"; Permissions: users-full; Flags: recursesubdirs onlyifdoesntexist ignoreversion createallsubdirs; Excludes: "*.pdb, *.db"
;rename credentials example to credentials, but don't overwrite if it exists ;rename credentials example to credentials, but don't overwrite if it exists
;Source: "src\NadekoBot\bin\Release\netcoreapp1.1\{#target}\publish\credentials_example.json"; DestName: "credentials.json"; DestDir: "{app}\{#sysfolder}"; Permissions: users-full; Flags: skipifsourcedoesntexist onlyifdoesntexist; ;Source: "src\NadekoBot\bin\Release\netcoreapp2.0\{#target}\publish\credentials_example.json"; DestName: "credentials.json"; DestDir: "{app}\{#sysfolder}"; Permissions: users-full; Flags: skipifsourcedoesntexist onlyifdoesntexist;
;reinstall - i want to copy all files, but i don't want to overwrite any data files because users will lose their customization if they don't have a backup, ;reinstall - i want to copy all files, but i don't want to overwrite any data files because users will lose their customization if they don't have a backup,
; and i don't want them to have to backup and then copy-merge into data folder themselves, or lose their currency images due to overwrite. ; and i don't want them to have to backup and then copy-merge into data folder themselves, or lose their currency images due to overwrite.
Source: "src\NadekoBot\bin\Release\netcoreapp1.1\{#target}\publish\*"; DestDir: "{app}\{#sysfolder}"; Permissions: users-full; Flags: recursesubdirs ignoreversion onlyifdestfileexists createallsubdirs; Excludes: "*.pdb, *.db, data\*, credentials.json"; Source: "src\NadekoBot\bin\Release\netcoreapp2.0\{#target}\publish\*"; DestDir: "{app}\{#sysfolder}"; Permissions: users-full; Flags: recursesubdirs ignoreversion onlyifdestfileexists createallsubdirs; Excludes: "*.pdb, *.db, data\*, credentials.json";
Source: "src\NadekoBot\bin\Release\netcoreapp1.1\{#target}\publish\data\*"; DestDir: "{app}\{#sysfolder}\data"; Permissions: users-full; Flags: recursesubdirs onlyifdoesntexist createallsubdirs; Source: "src\NadekoBot\bin\Release\netcoreapp2.0\{#target}\publish\data\*"; DestDir: "{app}\{#sysfolder}\data"; Permissions: users-full; Flags: recursesubdirs onlyifdoesntexist createallsubdirs;
;readme ;readme
;Source: "readme"; DestDir: "{app}"; Flags: isreadme ;Source: "readme"; DestDir: "{app}"; Flags: isreadme

View File

@ -37,7 +37,7 @@ Commands and aliases | Description | Usage
`.mentionrole` `.menro` | Mentions every person from the provided role or roles (separated by a ',') on this server. **Requires MentionEveryone server permission.** | `.menro RoleName` `.mentionrole` `.menro` | Mentions every person from the provided role or roles (separated by a ',') on this server. **Requires MentionEveryone server permission.** | `.menro RoleName`
`.donators` | List of the lovely people who donated to keep this project alive. | `.donators` `.donators` | List of the lovely people who donated to keep this project alive. | `.donators`
`.donadd` | Add a donator to the database. **Bot owner only** | `.donadd Donate Amount` `.donadd` | Add a donator to the database. **Bot owner only** | `.donadd Donate Amount`
`.autoassignrole` `.aar` | Automaticaly assigns a specified role to every user who joins the server. **Requires ManageRoles server permission.** | `.aar` to disable, `.aar Role Name` to enable `.autoassignrole` `.aar` | Automaticaly assigns a specified role to every user who joins the server. **Requires ManageRoles server permission.** | `.aar to disable` or `.aar Role Name to enable`
`.gvc` | Toggles game voice channel feature in the voice channel you're currently in. Users who join the game voice channel will get automatically redirected to the voice channel with the name of their current game, if it exists. Can't move users to channels that the bot has no connect permission for. One per server. **Requires Administrator server permission.** | `.gvc` `.gvc` | Toggles game voice channel feature in the voice channel you're currently in. Users who join the game voice channel will get automatically redirected to the voice channel with the name of their current game, if it exists. Can't move users to channels that the bot has no connect permission for. One per server. **Requires Administrator server permission.** | `.gvc`
`.languageset` `.langset` | Sets this server's response language. If bot's response strings have been translated to that language, bot will use that language in this server. Reset by using `default` as the locale name. Provide no arguments to see currently set language. | `.langset de-DE ` or `.langset default` `.languageset` `.langset` | Sets this server's response language. If bot's response strings have been translated to that language, bot will use that language in this server. Reset by using `default` as the locale name. Provide no arguments to see currently set language. | `.langset de-DE ` or `.langset default`
`.langsetdefault` `.langsetd` | Sets the bot's default response language. All servers which use a default locale will use this one. Setting to `default` will use the host's current culture. Provide no arguments to see currently set language. | `.langsetd en-US` or `.langsetd default` `.langsetdefault` `.langsetd` | Sets the bot's default response language. All servers which use a default locale will use this one. Setting to `default` will use the host's current culture. Provide no arguments to see currently set language. | `.langsetd en-US` or `.langsetd default`
@ -62,7 +62,7 @@ Commands and aliases | Description | Usage
`.defprefix` | Sets bot's default prefix for all bot commands. Provide no arguments to see the current default prefix. This will not change this server's current prefix. **Bot owner only** | `.defprefix +` `.defprefix` | Sets bot's default prefix for all bot commands. Provide no arguments to see the current default prefix. This will not change this server's current prefix. **Bot owner only** | `.defprefix +`
`.antiraid` | Sets an anti-raid protection on the server. First argument is number of people which will trigger the protection. Second one is a time interval in which that number of people needs to join in order to trigger the protection, and third argument is punishment for those people (Kick, Ban, Mute) **Requires Administrator server permission.** | `.antiraid 5 20 Kick` `.antiraid` | Sets an anti-raid protection on the server. First argument is number of people which will trigger the protection. Second one is a time interval in which that number of people needs to join in order to trigger the protection, and third argument is punishment for those people (Kick, Ban, Mute) **Requires Administrator server permission.** | `.antiraid 5 20 Kick`
`.antispam` | Stops people from repeating same message X times in a row. You can specify to either mute, kick or ban the offenders. Max message count is 10. **Requires Administrator server permission.** | `.antispam 3 Mute` or `.antispam 4 Kick` or `.antispam 6 Ban` `.antispam` | Stops people from repeating same message X times in a row. You can specify to either mute, kick or ban the offenders. Max message count is 10. **Requires Administrator server permission.** | `.antispam 3 Mute` or `.antispam 4 Kick` or `.antispam 6 Ban`
`.antispamignore` | Toggles whether antispam ignores current channel. Antispam must be enabled. | `.antispamignore` `.antispamignore` | Toggles whether antispam ignores current channel. Antispam must be enabled. **Requires Administrator server permission.** | `.antispamignore`
`.antilist` `.antilst` | Shows currently enabled protection features. | `.antilist` `.antilist` `.antilst` | Shows currently enabled protection features. | `.antilist`
`.prune` `.clear` | `.prune` removes all Nadeko's messages in the last 100 messages. `.prune X` removes last `X` number of messages from the channel (up to 100). `.prune @Someone` removes all Someone's messages in the last 100 messages. `.prune @Someone X` removes last `X` number of 'Someone's' messages in the channel. | `.prune` or `.prune 5` or `.prune @Someone` or `.prune @Someone X` `.prune` `.clear` | `.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`
`.slowmode` | Toggles slowmode. Disable by specifying no parameters. To enable, specify a number of messages each user can send, and an interval in seconds. For example 1 message every 5 seconds. **Requires ManageMessages server permission.** | `.slowmode 1 5` or `.slowmode` `.slowmode` | Toggles slowmode. Disable by specifying no parameters. To enable, specify a number of messages each user can send, and an interval in seconds. For example 1 message every 5 seconds. **Requires ManageMessages server permission.** | `.slowmode 1 5` or `.slowmode`
@ -95,7 +95,7 @@ Commands and aliases | Description | Usage
`.greet` | Toggles anouncements on the current channel when someone joins the server. **Requires ManageServer server permission.** | `.greet` `.greet` | Toggles anouncements on the current channel when someone joins the server. **Requires ManageServer server permission.** | `.greet`
`.greetmsg` | Sets a new join announcement message which will be shown in the server's channel. Type `%user%` if you want to mention the new member. Using it with no message will show the current greet message. You can use embed json from <http://nadekobot.me/embedbuilder/> instead of a regular text, if you want the message to be embedded. **Requires ManageServer server permission.** | `.greetmsg Welcome, %user%.` `.greetmsg` | Sets a new join announcement message which will be shown in the server's channel. Type `%user%` if you want to mention the new member. Using it with no message will show the current greet message. You can use embed json from <http://nadekobot.me/embedbuilder/> instead of a regular text, if you want the message to be embedded. **Requires ManageServer server permission.** | `.greetmsg Welcome, %user%.`
`.greetdm` | Toggles whether the greet messages will be sent in a DM (This is separate from greet - you can have both, any or neither enabled). **Requires ManageServer server permission.** | `.greetdm` `.greetdm` | Toggles whether the greet messages will be sent in a DM (This is separate from greet - you can have both, any or neither enabled). **Requires ManageServer server permission.** | `.greetdm`
`.greetdmmsg` | Sets a new join announcement message which will be sent to the user who joined. Type `%user%` if you want to mention the new member. Using it with no message will show the current DM greet message. You can use embed json from <http://nadekobot.me/embedbuilder/> instead of a regular text, if you want the message to be embedded. **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.me/embedbuilder/> instead of a regular text, if you want the message to be embedded. **Requires ManageServer server permission.** | `.greetdmmsg Welcome to the server, %user%`
`.bye` | Toggles anouncements on the current channel when someone leaves the server. **Requires ManageServer server permission.** | `.bye` `.bye` | Toggles anouncements on the current channel when someone leaves the server. **Requires ManageServer server permission.** | `.bye`
`.byemsg` | Sets a new leave announcement message. Type `%user%` if you want to show the name the user who left. Type `%id%` to show id. Using this command with no message will show the current bye message. You can use embed json from <http://nadekobot.me/embedbuilder/> instead of a regular text, if you want the message to be embedded. **Requires ManageServer server permission.** | `.byemsg %user% has left.` `.byemsg` | Sets a new leave announcement message. Type `%user%` if you want to show the name the user who left. Type `%id%` to show id. Using this command with no message will show the current bye message. You can use embed json from <http://nadekobot.me/embedbuilder/> instead of a regular text, if you want the message to be embedded. **Requires ManageServer server permission.** | `.byemsg %user% has left.`
`.byedel` | Sets the time it takes (in seconds) for bye messages to be auto-deleted. Set it to `0` to disable automatic deletion. **Requires ManageServer server permission.** | `.byedel 0` or `.byedel 30` `.byedel` | Sets the time it takes (in seconds) for bye messages to be auto-deleted. Set it to `0` to disable automatic deletion. **Requires ManageServer server permission.** | `.byedel 0` or `.byedel 30`
@ -146,10 +146,10 @@ Commands and aliases | Description | Usage
`.leaderboard` `.lb` | Displays the bot's currency leaderboard. | `.lb` `.leaderboard` `.lb` | Displays the bot's currency leaderboard. | `.lb`
`.race` | Starts a new animal race. | `.race` `.race` | Starts a new animal race. | `.race`
`.joinrace` `.jr` | Joins a new race. You can specify an amount of currency for betting (optional). You will get YourBet*(participants-1) back if you win. | `.jr` or `.jr 5` `.joinrace` `.jr` | Joins a new race. You can specify an amount of currency for betting (optional). You will get YourBet*(participants-1) back if you win. | `.jr` or `.jr 5`
`.startevent` | Starts one of the events seen on public nadeko. **Bot owner only** | `.startevent flowerreaction` `.startevent` | Starts one of the events seen on public nadeko. `reaction` and `sneakygamestatus` are the only 2 available now. **Bot owner only** | `.startevent reaction`
`.roll` | Rolls 0-100. If you supply a number `X` it rolls up to 30 normal dice. If you split 2 numbers with letter `d` (`xdy`) it will roll `X` dice from 1 to `y`. `Y` can be a letter 'F' if you want to roll fate dice instead of dnd. | `.roll` or `.roll 7` or `.roll 3d5` or `.roll 5dF` `.roll` | Rolls 0-100. If you supply a number `X` it rolls up to 30 normal dice. If you split 2 numbers with letter `d` (`xdy`) it will roll `X` dice from 1 to `y`. `Y` can be a letter 'F' if you want to roll fate dice instead of dnd. | `.roll` or `.roll 7` or `.roll 3d5` or `.roll 5dF`
`.rolluo` | Rolls `X` normal dice (up to 30) unordered. If you split 2 numbers with letter `d` (`xdy`) it will roll `X` dice from 1 to `y`. | `.rolluo` or `.rolluo 7` or `.rolluo 3d5` `.rolluo` | Rolls `X` normal dice (up to 30) unordered. If you split 2 numbers with letter `d` (`xdy`) it will roll `X` dice from 1 to `y`. | `.rolluo` or `.rolluo 7` or `.rolluo 3d5`
`.nroll` | Rolls in a given range. | `.nroll 5` (rolls 0-5) or `.nroll 5-15` `.nroll` | Rolls in a given range. | `.nroll 5` (rolls 0-5)` or `.nroll 5-15`
`.draw` | Draws a card from this server's deck. You can draw up to 10 cards by supplying a number of cards to draw. | `.draw` or `.draw 5` `.draw` | Draws a card from this server's deck. You can draw up to 10 cards by supplying a number of cards to draw. | `.draw` or `.draw 5`
`.drawnew` | Draws a card from the NEW deck of cards. You can draw up to 10 cards by supplying a number of cards to draw. | `.drawnew` or `.drawnew 5` `.drawnew` | Draws a card from the NEW deck of cards. You can draw up to 10 cards by supplying a number of cards to draw. | `.drawnew` or `.drawnew 5`
`.deckshuffle` `.dsh` | Reshuffles all cards back into the deck. | `.dsh` `.deckshuffle` `.dsh` | Reshuffles all cards back into the deck. | `.dsh`
@ -177,7 +177,7 @@ Commands and aliases | Description | Usage
Commands and aliases | Description | Usage Commands and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`.choose` | Chooses a thing from a list of things | `.choose Get up;Sleep;Sleep more` `.choose` | Chooses a thing from a list of things | `.choose Get up;Sleep;Sleep more`
`.8ball` | Ask the 8ball a yes/no question. | `.8ball should I do something` `.8ball` | Ask the 8ball a yes/no question. | `.8ball Is b1nzy a nice guy?`
`.rps` | Play a game of Rocket-Paperclip-Scissors with Nadeko. | `.rps scissors` `.rps` | Play a game of Rocket-Paperclip-Scissors with Nadeko. | `.rps scissors`
`.rategirl` | Use the universal hot-crazy wife zone matrix to determine the girl's worth. It is everything young men need to know about women. At any moment in time, any woman you have previously located on this chart can vanish from that location and appear anywhere else on the chart. | `.rategirl @SomeGurl` `.rategirl` | Use the universal hot-crazy wife zone matrix to determine the girl's worth. It is everything young men need to know about women. At any moment in time, any woman you have previously located on this chart can vanish from that location and appear anywhere else on the chart. | `.rategirl @SomeGurl`
`.linux` | Prints a customizable Linux interjection | `.linux Spyware Windows` `.linux` | Prints a customizable Linux interjection | `.linux Spyware Windows`
@ -200,7 +200,7 @@ Commands and aliases | Description | Usage
`.typeadd` | Adds a new article to the typing contest. **Bot owner only** | `.typeadd wordswords` `.typeadd` | Adds a new article to the typing contest. **Bot owner only** | `.typeadd wordswords`
`.typelist` | Lists added typing articles with their IDs. 15 per page. | `.typelist` or `.typelist 3` `.typelist` | Lists added typing articles with their IDs. 15 per page. | `.typelist` or `.typelist 3`
`.typedel` | Deletes a typing article given the ID. **Bot owner only** | `.typedel 3` `.typedel` | Deletes a typing article given the ID. **Bot owner only** | `.typedel 3`
`.tictactoe` `.ttt` | Starts a game of tic tac toe. Another user must run the command in the same channel in order to accept the challenge. Use numbers 1-9 to play. 15 seconds per move. | .ttt `.tictactoe` `.ttt` | Starts a game of tic tac toe. Another user must run the command in the same channel in order to accept the challenge. Use numbers 1-9 to play. 15 seconds per move. | `.ttt`
`.trivia` `.t` | Starts a game of trivia. You can add `nohint` to prevent hints. First player to get to 10 points wins by default. You can specify a different number. 30 seconds per question. | `.t` or `.t 5 nohint` `.trivia` `.t` | Starts a game of trivia. You can add `nohint` to prevent hints. First player to get to 10 points wins by default. You can specify a different number. 30 seconds per question. | `.t` or `.t 5 nohint`
`.tl` | Shows a current trivia leaderboard. | `.tl` `.tl` | Shows a current trivia leaderboard. | `.tl`
`.tq` | Quits current trivia after current question. | `.tq` `.tq` | Quits current trivia after current question. | `.tq`
@ -244,7 +244,7 @@ Commands and aliases | Description | Usage
`.soundcloudpl` `.scpl` | Queue a Soundcloud playlist using a link. | `.scpl soundcloudseturl` `.soundcloudpl` `.scpl` | Queue a Soundcloud playlist using a link. | `.scpl soundcloudseturl`
`.nowplaying` `.np` | Shows the song that the bot is currently playing. | `.np` `.nowplaying` `.np` | Shows the song that the bot is currently playing. | `.np`
`.shuffle` `.sh` `.plsh` | Shuffles the current playlist. | `.plsh` `.shuffle` `.sh` `.plsh` | Shuffles the current playlist. | `.plsh`
`.playlist` `.pl` | Queues up to 500 songs from a youtube playlist specified by a link, or keywords. | `.pl playlist link or name` `.playlist` `.pl` | Queues up to 500 songs from a youtube playlist specified by a link, or keywords. | `.pl <youtube_playlist_link>`
`.radio` `.ra` | Queues a radio stream from a link. It can be a direct mp3 radio stream, .m3u, .pls .asx or .xspf (Usage Video: <https://streamable.com/al54>) | `.ra radio link here` `.radio` `.ra` | Queues a radio stream from a link. It can be a direct mp3 radio stream, .m3u, .pls .asx or .xspf (Usage Video: <https://streamable.com/al54>) | `.ra radio link here`
`.local` `.lo` | Queues a local file by specifying a full path. **Bot owner only** | `.lo C:/music/mysong.mp3` `.local` `.lo` | Queues a local file by specifying a full path. **Bot owner only** | `.lo C:/music/mysong.mp3`
`.localplaylst` `.lopl` | Queues all songs from a directory. **Bot owner only** | `.lopl C:/music/classical` `.localplaylst` `.lopl` | Queues all songs from a directory. **Bot owner only** | `.lopl C:/music/classical`
@ -262,8 +262,10 @@ Commands and aliases | Description | Usage
### NSFW ### NSFW
Commands and aliases | Description | Usage Commands and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`.hentai` | Shows a hentai image from a random website (gelbooru or danbooru or konachan or atfbooru or yandere) with a given tag. Tag is optional but preferred. Only 1 tag allowed. | `.hentai yuri`
`.autohentai` | Posts a hentai every X seconds with a random tag from the provided tags. Use `|` to separate tags. 20 seconds minimum. Provide no arguments to disable. **Requires ManageMessages channel permission.** | `.autohentai 30 yuri|tail|long_hair` or `.autohentai` `.autohentai` | Posts a hentai every X seconds with a random tag from the provided tags. Use `|` to separate tags. 20 seconds minimum. Provide no arguments to disable. **Requires ManageMessages channel permission.** | `.autohentai 30 yuri|tail|long_hair` or `.autohentai`
`.autoboobs` | Posts a boobs every X seconds. 20 seconds minimum. Provide no arguments to disable. **Requires ManageMessages channel permission.** | `.autoboobs 30` or `.autoboobs`
`.autobutts` | Posts a butts every X seconds. 20 seconds minimum. Provide no arguments to disable. **Requires ManageMessages channel permission.** | `.autobutts 30` or `.autobutts`
`.hentai` | Shows a hentai image from a random website (gelbooru or danbooru or konachan or atfbooru or yandere) with a given tag. Tag is optional but preferred. Only 1 tag allowed. | `.hentai yuri`
`.hentaibomb` | Shows a total 5 images (from gelbooru, danbooru, konachan, yandere and atfbooru). Tag is optional but preferred. | `.hentaibomb yuri` `.hentaibomb` | Shows a total 5 images (from gelbooru, danbooru, konachan, yandere and atfbooru). Tag is optional but preferred. | `.hentaibomb yuri`
`.yandere` | Shows a random image from yandere with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `.yandere tag1+tag2` `.yandere` | Shows a random image from yandere with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `.yandere tag1+tag2`
`.konachan` | Shows a random hentai image from konachan with a given tag. Tag is optional but preferred. | `.konachan yuri` `.konachan` | Shows a random hentai image from konachan with a given tag. Tag is optional but preferred. | `.konachan yuri`
@ -322,9 +324,9 @@ Commands and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`.attack` | Attacks a target with the given move. Use `.movelist` to see a list of moves your type can use. | `.attack "vine whip" @someguy` `.attack` | Attacks a target with the given move. Use `.movelist` to see a list of moves your type can use. | `.attack "vine whip" @someguy`
`.movelist` `.ml` | Lists the moves you are able to use | `.ml` `.movelist` `.ml` | Lists the moves you are able to use | `.ml`
`.heal` | Heals someone. Revives those who fainted. Costs a NadekoFlower. | `.heal @someone` `.heal` | Heals someone. Revives those who fainted. Costs one Currency. | `.heal @someone`
`.type` | Get the poketype of the target. | `.type @someone` `.type` | Get the poketype of the target. | `.type @someone`
`.settype` | Set your poketype. Costs a NadekoFlower. Provide no arguments to see a list of available types. | `.settype fire` or `.settype` `.settype` | Set your poketype. Costs one Currency. 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)
@ -361,6 +363,9 @@ Commands and aliases | Description | Usage
`.mal` | Shows basic info from a 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` `.anime` `.ani` `.aq` | Queries anilist for an anime and shows the first result. | `.ani aquarion evol`
`.manga` `.mang` `.mq` | Queries anilist for a manga and shows the first result. | `.mq Shingeki no kyojin` `.manga` `.mang` `.mq` | Queries anilist for a manga and shows the first result. | `.mq Shingeki no kyojin`
`.feed` `.feedadd` | Subscribes to a feed. Bot will post an update up to once every 10 seconds. You can have up to 10 feeds on one server. All feeds must have unique URLs. **Requires ManageMessages server permission.** | `.feed https://www.rt.com/rss/`
`.feedremove` `.feedrm` `.feeddel` | Stops tracking a feed on the given index. Use `.feeds` command to see a list of feeds and their indexes. **Requires ManageMessages server permission.** | `.feedremove 3`
`.feeds` `.feedlist` | Shows the list of feeds you've subscribed to on this server. **Requires ManageMessages server permission.** | `.feeds`
`.yomama` `.ym` | Shows a random joke from <http://api.yomomma.info/> | `.ym` `.yomama` `.ym` | Shows a random joke from <http://api.yomomma.info/> | `.ym`
`.randjoke` `.rj` | Shows a random joke from <http://tambal.azurewebsites.net/joke/random> | `.rj` `.randjoke` `.rj` | Shows a random joke from <http://tambal.azurewebsites.net/joke/random> | `.rj`
`.chucknorris` `.cn` | Shows a random Chuck Norris joke from <http://api.icndb.com/jokes/random/> | `.cn` `.chucknorris` `.cn` | Shows a random Chuck Norris joke from <http://api.icndb.com/jokes/random/> | `.cn`
@ -371,7 +376,7 @@ Commands and aliases | Description | Usage
`.osu` | Shows osu stats for a player. | `.osu Name` or `.osu Name taiko` `.osu` | Shows osu stats for a player. | `.osu Name` or `.osu Name taiko`
`.osub` | Shows information about an osu beatmap. | `.osub https://osu.ppy.sh/s/127712` `.osub` | Shows information about an osu beatmap. | `.osub https://osu.ppy.sh/s/127712`
`.osu5` | Displays a user's top 5 plays. | `.osu5 Name` `.osu5` | Displays a user's top 5 plays. | `.osu5 Name`
`.overwatch` `.ow` | Show's basic stats on a player (competitive rank, playtime, level etc) Region codes are: `eu` `us` `cn` `kr` | `.ow us Battletag#1337` or `.overwatch eu Battletag#2016` `.overwatch` `.ow` | Show's basic stats on a player (competitive rank, playtime, level etc) Region codes are: `eu` `us` `cn` `kr` | `.ow us Battletag#1337` or `.overwatch eu Battletag#2016`
`.placelist` | Shows the list of available tags for the `.place` command. | `.placelist` `.placelist` | Shows the list of available tags for the `.place` command. | `.placelist`
`.place` | Shows a placeholder image of a given tag. Use `.placelist` to see all available tags. You can specify the width and height of the image as the last two optional arguments. | `.place Cage` or `.place steven 500 400` `.place` | Shows a placeholder image of a given tag. Use `.placelist` to see all available tags. You can specify the width and height of the image as the last two optional arguments. | `.place Cage` or `.place steven 500 400`
`.pokemon` `.poke` | Searches for a pokemon. | `.poke Sylveon` `.pokemon` `.poke` | Searches for a pokemon. | `.poke Sylveon`
@ -449,12 +454,13 @@ Commands and aliases | Description | Usage
`.experience` `.xp` | Shows your xp stats. Specify the user to show that user's stats instead. | `.xp` `.experience` `.xp` | Shows your xp stats. Specify the user to show that user's stats instead. | `.xp`
`.xprolerewards` `.xprrs` | Shows currently set role rewards. | `.xprrs` `.xprolerewards` `.xprrs` | Shows currently set role rewards. | `.xprrs`
`.xprolereward` `.xprr` | Sets a role reward on a specified level. Provide no role name in order to remove the role reward. **Requires ManageRoles server permission.** | `.xprr 3 Social` `.xprolereward` `.xprr` | Sets a role reward on a specified level. Provide no role name in order to remove the role reward. **Requires ManageRoles server permission.** | `.xprr 3 Social`
`.xpnotify` `.xpn` | Sets how the bot should notify you when you get a `server` or `global` level. You can set `dm` (for the bot to send a direct message), `channel` (to get notified in the channel you sent the last message in) or `none` to disable. | `.xpn global dm` `.xpn server channel` `.xpnotify` `.xpn` | Sets how the bot should notify you when you get a `server` or `global` level. You can set `dm` (for the bot to send a direct message), `channel` (to get notified in the channel you sent the last message in) or `none` to disable. | `.xpn global dm` or `.xpn server channel`
`.xpexclude` `.xpex` | Exclude a user or a role from the xp system, or whole current server. **Requires Administrator server permission.** | `.xpex Role Excluded-Role` `.xpex Server` `.xpexclude` `.xpex` | Exclude a channel, role or current server from the xp system. **Requires Administrator server permission.** | `.xpex Role Excluded-Role` or `.xpex Server`
`.xpexclusionlist` `.xpexl` | Shows the roles and channels excluded from the XP system on this server, as well as whether the whole server is excluded. | `.xpexl` `.xpexclusionlist` `.xpexl` | Shows the roles and channels excluded from the XP system on this server, as well as whether the whole server is excluded. | `.xpexl`
`.xpleaderboard` `.xplb` | Shows current server's xp leaderboard. | `.xplb` `.xpleaderboard` `.xplb` | Shows current server's xp leaderboard. | `.xplb`
`.xpgleaderboard` `.xpglb` | Shows the global xp leaderboard. | `.xpglb` `.xpgleaderboard` `.xpglb` | Shows the global xp leaderboard. | `.xpglb`
`.xpadd` | Adds xp to a user on the server. This does not affect their global ranking. You can use negative values. **Requires Administrator server permission.** | `.xpadd 100 @b1nzy` `.xpadd` | Adds xp to a user on the server. This does not affect their global ranking. You can use negative values. **Requires Administrator server permission.** | `.xpadd 100 @b1nzy`
`.clubadmin` | Assigns (or unassigns) staff role to the member of the club. Admins can ban, kick and accept applications. | `.clubadmin`
`.clubcreate` | Creates a club. You must be atleast level 5 and not be in the club already. | `.clubcreate b1nzy's friends` `.clubcreate` | Creates a club. You must be atleast level 5 and not be in the club already. | `.clubcreate b1nzy's friends`
`.clubicon` | Sets the club icon. | `.clubicon https://i.imgur.com/htfDMfU.png` `.clubicon` | Sets the club icon. | `.clubicon https://i.imgur.com/htfDMfU.png`
`.clubinfo` | Shows information about the club. | `.clubinfo b1nzy's friends#123` `.clubinfo` | Shows information about the club. | `.clubinfo b1nzy's friends#123`

View File

@ -19,9 +19,9 @@
###Question 5: I have an issue/bug/suggestion, where do I put it so it gets noticed? ###Question 5: I have an issue/bug/suggestion, where do I put it so it gets noticed?
----------- -----------
**Answer:** First, check [issues](https://github.com/Kwoth/NadekoBot/issues "GitHub NadekoBot Issues"), then check the `#suggestions` channel in the Nadeko [help server](https://discord.gg/nadekobot). **Answer:** First, check [issues](https://github.com/Kwoth/NadekoBot/issues "GitHub NadekoBot Issues"), then check the [suggestions](https://feathub.com/Kwoth/NadekoBot).
If your problem or suggestion is not there, feel free to request/notify us about it either in the Issues section of GitHub for issues or in the `#suggestions` channel on the Nadeko help server for suggestions. If your problem or suggestion is not there, feel free to request/notify us about it either in the Issues section of GitHub for issues or on feathub for suggestions.
###Question 6: How do I use this command? ###Question 6: How do I use this command?
-------- --------

View File

@ -5,7 +5,6 @@ If you do not see `credentials.json` you will need to rename `credentials_exampl
```json ```json
{ {
"ClientId": 179372110000358912, "ClientId": 179372110000358912,
"BotId": 179372110000358912,
"Token": "MTc5MzcyXXX2MDI1ODY3MjY0.ChKs4g.I8J_R9XX0t-QY-0PzXXXiN0-7vo", "Token": "MTc5MzcyXXX2MDI1ODY3MjY0.ChKs4g.I8J_R9XX0t-QY-0PzXXXiN0-7vo",
"OwnerIds": [ "OwnerIds": [
105635123466156544, 105635123466156544,
@ -23,7 +22,8 @@ If you do not see `credentials.json` you will need to rename `credentials_exampl
"TotalShards": 1, "TotalShards": 1,
"ShardRunCommand": "", "ShardRunCommand": "",
"ShardRunArguments": "", "ShardRunArguments": "",
"ShardRunPort": null "ShardRunPort": null,
"RestartCommand": null
} }
``` ```
----- -----
@ -71,16 +71,13 @@ It should look like:
```json ```json
"Token": "MTc5MzcyXXX2MDI1ODY3MjY0.ChKs4g.I8J_R9XX0t-QY-0PzXXXiN0-7vo", "Token": "MTc5MzcyXXX2MDI1ODY3MjY0.ChKs4g.I8J_R9XX0t-QY-0PzXXXiN0-7vo",
``` ```
##### Getting Client and Bot ID: ##### Getting Client ID:
- Copy the `Client ID` on the page and replace the `12312123` part of the **`"ClientId"`** line with it. - Copy the `Client ID` on the page and replace the `12312123` part of the **`"ClientId"`** line with it.
- **Important: Bot ID and Client ID** will be the same in **newer bot accounts** due to recent changes by Discord.
- If that's the case, **copy the same client ID** to **`"BotId"`**
``` ```
It should look like: It should look like:
``` ```
```json ```json
"ClientId": 179372110000358912, "ClientId": 179372110000358912,
"BotId": 179372110000358912,
``` ```
----- -----
##### Getting Owner ID*(s)*: ##### Getting Owner ID*(s)*:
@ -165,7 +162,27 @@ It should look like:
- **TotalShards** - **TotalShards**
- Required if the bot will be connected to more than 1500 servers. - Required if the bot will be connected to more than 1500 servers.
- Most likely unnecessary to change until your bot is added to more than 1500 servers. - Most likely unnecessary to change until your bot is added to more than 1500 servers.
----- - **RestartCommand**
- Required if you want to be able to use `.restart` command
- It requires command, and arguments to the command which to execute right before bot stops
- If you're using linux, it's easier, and more reliable to use auto restart option, and just use `.die`
For linux, or from the source, this is usually
```json
"RestartCommand": {
"Cmd": "dotnet",
"Args": "run -c Release"
}
```
For windows (regular installation, or from the updater), this is usually
```json
"RestartCommand": {
"Cmd": "NadekoBot.exe",
"Args": ""
}
```
## DB files ## DB files
@ -210,8 +227,6 @@ and that will save all the changes.
- **ShardRunPort** - **ShardRunPort**
- Bot uses a random UDP port in [5000, 6000) range for communication between shards - Bot uses a random UDP port in [5000, 6000) range for communication between shards
[Google Console]: https://console.developers.google.com [Google Console]: https://console.developers.google.com
[DiscordApp]: https://discordapp.com/developers/applications/me [DiscordApp]: https://discordapp.com/developers/applications/me
[Invite Guide]: http://discord.kongslien.net/guide.html [Invite Guide]: http://discord.kongslien.net/guide.html

View File

@ -1,9 +1,7 @@
Permissions Overview Permissions Overview
=================== ===================
Have you ever felt confused or even overwhelmed when trying to set Nadeko's permissions? In this guide we will be explaining how to use the Have you ever felt confused or even overwhelmed when trying to set Nadeko's permissions? In this guide we will be explaining how to use the
permission commands correctly and even cover a few common questions! Every command we discuss here can be found in the [Commands List](http://nadekobot.readthedocs.io/en/1.0/Commands%20List/#permissions). permission commands correctly and even cover a few common questions! Every command we discuss here can be found in the [Commands List](http://nadekobot.readthedocs.io/en/latest/Commands%20List/#permissions).
**To see the old guide for versions 0.9 and below, see [here](http://nadekobot.readthedocs.io/en/latest/Permissions%20System/)**
Why do we use the Permissions Commands? Why do we use the Permissions Commands?
------------------------------ ------------------------------
@ -15,17 +13,20 @@ With the permissions system it possible to restrict who can skip the current son
First Time Setup First Time Setup
------------------ ------------------
To change permissions you **must** meet the following requirement: To change permissions you **must** meet the following requirements:
**Have the role specified by `.permrole` (By default, this is Nadeko)** **Be the owner of the server.**
**If you are NOT the server owner, get the role specified by `.permrole` (By default, this is Nadeko).**
If you have an existing role called `Nadeko` but can't assign it to yourself, create a new role called `Nadeko` and assign that to yourself. If you have an existing role called `Nadeko` but can't assign it to yourself, create a new role called `Nadeko` and assign that to yourself.
![img0](https://i.imgur.com/5QKZqqy.gif)
If you would like to set a different role, such as `Admins`, to be the role required to edit permissions, do `.permrole Admins` (you must have the current permission role to be able to do this). If you would like to set a different role, such as `Admins`, to be the role required to edit permissions, do `.permrole Admins` (you must have the current permission role to be able to do this).
Basics & Hierarchy Basics & Hierarchy
----- -----
The [Commands List](http://nadekobot.readthedocs.io/en/1.0/Commands%20List/#permissions) is a great resource which lists **all** the available commands, however we'll go over a few commands here. The [Commands List](http://nadekobot.readthedocs.io/en/latest/Commands%20List/#permissions) is a great resource which lists **all** the available commands, however we'll go over a few commands here.
Firstly, let's explain how the permissions system works - It's simple once you figure out how each command works! Firstly, let's explain how the permissions system works - It's simple once you figure out how each command works!
The permissions system works as a chain, everytime a command is used, the permissions chain is checked. Starting from the top of the chain, the command is compared to a rule, if it isn't either allowed or disallowed by that rule it proceeds to check the next rule all the way till it reaches the bottom rule, which allows all commands. The permissions system works as a chain, everytime a command is used, the permissions chain is checked. Starting from the top of the chain, the command is compared to a rule, if it isn't either allowed or disallowed by that rule it proceeds to check the next rule all the way till it reaches the bottom rule, which allows all commands.
@ -35,7 +36,7 @@ To view this permissions chain, do `.listperms`, with the top of the chain being
If you want to remove a permission from the chain of permissions, do `.removeperm X` to remove rule number X and similarly, do `.moveperm X Y` to move rule number X to number Y (moving, not swapping!). If you want to remove a permission from the chain of permissions, do `.removeperm X` to remove rule number X and similarly, do `.moveperm X Y` to move rule number X to number Y (moving, not swapping!).
As an example, if you wanted to enable NSFW for a certain role, say "Lewd", you could do `.rolemdl NSFW enable Lewd`. As an example, if you wanted to enable NSFW for a certain role, say "Lewd", you could do `.rolemdl NSFW enable Lewd`.
This adds the rule to the top of the permissions chain so even if the default `.sm NSFW disabled` rule exists, the "Lewd" role will be able to use the NSFW module. This adds the rule to the top of the permissions chain so even if the default `.sm NSFW disable` rule exists, the "Lewd" role will be able to use the NSFW module.
If you want the bot to notify users why they can't use a command or module, use `.verbose true` and Nadeko will tell you what rule is preventing the command. If you want the bot to notify users why they can't use a command or module, use `.verbose true` and Nadeko will tell you what rule is preventing the command.

View File

@ -20,6 +20,6 @@ Some features have their own specific placeholders which are noted in that featu
- `%time%` - Bot time - `%time%` - Bot time
- `%server_time%` - Time on this server, set with `.timezone` command - `%server_time%` - Time on this server, set with `.timezone` command
**If you're using placeholders in embeds, don't use %user% and in titles, footers and field names. They will not show properly.** **If you're using placeholders in embeds, don't use %user% and %mention% in titles, footers and field names. They will not show properly.**
![img](http://i.imgur.com/lNNNfs1.png) ![img](http://i.imgur.com/lNNNfs1.png)

View File

@ -1,22 +1,22 @@
Prerequisites ### Prerequisites
- [.net core 1.1.X][.netcore] - [.net core sdk 2.0][.netcore]
- [ffmpeg][ffmpeg] (and added to path) either download or install using your distro's package manager - [ffmpeg][ffmpeg] (and added to path) either download or install using your distro's package manager
- [git][git] - [git][git]
- [redis][redis] for windows, or `apt-get install redis-server` for linux
*Clone the repo* ### Clone The Repo
`git clone -b 1.4 https://github.com/Kwoth/NadekoBot` `git clone -b 1.9 https://github.com/Kwoth/NadekoBot`
`cd NadekoBot/src/NadekoBot` `cd NadekoBot/src/NadekoBot`
Edit `credentials.json.` Read the JSON Exaplanations guide on the left if you don't know how to set it up Edit `credentials.json.` Read the JSON Exaplanations guide on the left if you don't know how to set it up
*run* ### Run
`dotnet restore`
`dotnet run -c Release` `dotnet run -c Release`
*when you decide to updatein the future (might not work if you've made custom edits to the source, make sure you know how git works)* *when you decide to update in the future (might not work if you've made custom edits to the source, make sure you know how git works)*
`git pull` `git pull`
`dotnet restore` `dotnet run -c Release`
`dotnet run -c Release`
[.netcore]: https://www.microsoft.com/net/download/core#/sdk [.netcore]: https://www.microsoft.com/net/download/core#/sdk
[ffmpeg]: http://ffmpeg.zeranoe.com/builds/ [ffmpeg]: http://ffmpeg.zeranoe.com/builds/
[git]: https://git-scm.com/downloads [git]: https://git-scm.com/downloads
[redis]: https://github.com/MicrosoftArchive/redis/releases/latest

View File

@ -32,7 +32,7 @@ After you've done that, you are ready to use your VPS.
Use the following command to get and run `linuxAIO.sh` Use the following command to get and run `linuxAIO.sh`
(Remember **Do Not** rename the file **linuxAIO.sh**) (Remember **Do Not** rename the file **linuxAIO.sh**)
`cd ~ && wget -N https://github.com/Kwoth/NadekoBot-BashScript/raw/1.4/linuxAIO.sh && bash linuxAIO.sh` `cd ~ && wget -N https://github.com/Kwoth/NadekoBot-BashScript/raw/1.9/linuxAIO.sh && bash linuxAIO.sh`
You should see these following options after using the above command: You should see these following options after using the above command:
@ -52,7 +52,7 @@ Welcome to NadekoBot Auto Prerequisites Installer.
Would you like to continue? Would you like to continue?
``` ```
That will install all the prerequisites your system need to run NadekoBot. That will install all the prerequisites your system need to run NadekoBot.
(Optional) **If** you want to install it manually, you can try finding it [here.](https://github.com/Kwoth/NadekoBot-BashScript/blob/1.4/nadekoautoinstaller.sh) (Optional) **If** you want to install it manually, you can try finding it [here.](https://github.com/Kwoth/NadekoBot-BashScript/blob/1.9/nadekoautoinstaller.sh)
Once *prerequisites* finish installing, Once *prerequisites* finish installing,
@ -107,7 +107,7 @@ The above command will create a new session named **nadeko** *(you can replace
**Next, we need to run `linuxAIO.sh` in order to get the latest running scripts with patches:** **Next, we need to run `linuxAIO.sh` in order to get the latest running scripts with patches:**
- `cd ~ && wget -N https://github.com/Kwoth/NadekoBot-BashScript/raw/1.4/linuxAIO.sh && bash linuxAIO.sh` - `cd ~ && wget -N https://github.com/Kwoth/NadekoBot-BashScript/raw/1.9/linuxAIO.sh && bash linuxAIO.sh`
**From the options,** **From the options,**
@ -156,7 +156,7 @@ Open **PuTTY** and login as you have before, type `reboot` and press Enter.
- `tmux kill-session -t nadeko` (don't forget to replace **nadeko** in the command with the name of your bot's session) - `tmux kill-session -t nadeko` (don't forget to replace **nadeko** in the command with the name of your bot's session)
- Make sure the bot is **not** running. - Make sure the bot is **not** running.
- `tmux new -s nadeko` (**nadeko** is the name of the session) - `tmux new -s nadeko` (**nadeko** is the name of the session)
- `cd ~ && wget -N https://github.com/Kwoth/NadekoBot-BashScript/raw/1.4/linuxAIO.sh && bash linuxAIO.sh` - `cd ~ && wget -N https://github.com/Kwoth/NadekoBot-BashScript/raw/1.9/linuxAIO.sh && bash linuxAIO.sh`
- Choose `1` to update the bot with **latest build** available. - Choose `1` to update the bot with **latest build** available.
- Next, choose either `2` or `3` to run the bot again with **normally** or **auto restart** respectively. - Next, choose either `2` or `3` to run the bot again with **normally** or **auto restart** respectively.
- Done. - Done.
@ -191,7 +191,7 @@ To set up Nadeko for music and Google API Keys, follow [Setting up your API keys
- Copy the `credentials.json` to desktop - Copy the `credentials.json` to desktop
- EDIT it as it is guided here: [Setting up credentials.json][setup credentials] - EDIT it as it is guided here: [Setting up credentials.json][setup credentials]
- Paste/put it back in the folder once done. `(Using WinSCP)` - Paste/put it back in the folder once done. `(Using WinSCP)`
- **If** you already have Nadeko 1.3.x setup and have `credentials.json` and `NadekoBot.db`, you can just copy and paste the `credentials.json` to `NadekoBot/src/NadekoBot` and `NadekoBot.db` to `NadekoBot/src/NadekoBot/bin/Release/netcoreapp1.1/data` using WinSCP. - **If** you already have Nadeko 1.3.x setup and have `credentials.json` and `NadekoBot.db`, you can just copy and paste the `credentials.json` to `NadekoBot/src/NadekoBot` and `NadekoBot.db` to `NadekoBot/src/NadekoBot/bin/Release/netcoreapp2.0/data` using WinSCP.
**Or** follow the [Upgrading Guide.][upgrading] **Or** follow the [Upgrading Guide.][upgrading]

View File

@ -60,7 +60,7 @@ A dialog box will open asking if you want to install `xcode-select`. Select inst
Use the following command to get and run `linuxAIO.sh`: Use the following command to get and run `linuxAIO.sh`:
(Remember **DO NOT** rename the file `linuxAIO.sh`) (Remember **DO NOT** rename the file `linuxAIO.sh`)
`cd ~ && wget -N https://github.com/Kwoth/NadekoBot-BashScript/raw/1.4/linuxAIO.sh && bash linuxAIO.sh` `cd ~ && wget -N https://github.com/Kwoth/NadekoBot-BashScript/raw/1.9/linuxAIO.sh && bash linuxAIO.sh`
Follow the on screen instructions: Follow the on screen instructions:
@ -76,7 +76,7 @@ Next, choose `6` to exit.
#### Setting up Credentials.json file #### Setting up Credentials.json file
- Open up the `NadekoBot` folder, which should be in your home directory, then `NadekoBot` folder then `src` folder and then the additonal `NadekoBot` folder. - Open up the `NadekoBot` folder, which should be in your home directory, then `NadekoBot` folder then `src` folder and then the additonal `NadekoBot` folder.
- Edit the way its guided here: [Setting up credentials.json](http://nadekobot.readthedocs.io/en/latest/JSON%20Explanations/#setting-up-credentialsjson-file) - Edit the way its guided here: [Setting up credentials.json](http://nadekobot.readthedocs.io/en/latest/JSON%20Explanations/#setting-up-credentialsjson-file)
- **If** you already have Nadeko 1.x setup and have `credentials.json` and `NadekoBot.db`, you can just copy and paste the `credentials.json` to `NadekoBot/src/NadekoBot` and `NadekoBot.db` to `NadekoBot/src/NadekoBot/bin/Release/netcoreapp1.1/data`. - **If** you already have Nadeko 1.x setup and have `credentials.json` and `NadekoBot.db`, you can just copy and paste the `credentials.json` to `NadekoBot/src/NadekoBot` and `NadekoBot.db` to `NadekoBot/src/NadekoBot/bin/Release/netcoreapp2.0/data`.
**Or** follow the [Upgrading Guide.](http://nadekobot.readthedocs.io/en/latest/guides/Upgrading%20Guide/) **Or** follow the [Upgrading Guide.](http://nadekobot.readthedocs.io/en/latest/guides/Upgrading%20Guide/)
#### Setting NadekoBot Music #### Setting NadekoBot Music
@ -99,7 +99,7 @@ The above command will create a new session named **nadeko** *(you can replace
**Next, we need to run `linuxAIO.sh` in order to get the latest running scripts with patches:** **Next, we need to run `linuxAIO.sh` in order to get the latest running scripts with patches:**
- `cd ~ && wget -N https://github.com/Kwoth/NadekoBot-BashScript/raw/1.4/linuxAIO.sh && bash linuxAIO.sh` - `cd ~ && wget -N https://github.com/Kwoth/NadekoBot-BashScript/raw/1.9/linuxAIO.sh && bash linuxAIO.sh`
**From the options,** **From the options,**
@ -131,7 +131,7 @@ If you used Screen press CTRL+A+D (this will detach the nadeko screen)
- `tmux kill-session -t nadeko` [(don't forget to replace **nadeko** in the command to what ever you named your bot's session)](http://nadekobot.readthedocs.io/en/latest/guides/OSX%20Guide/#some-more-info) - `tmux kill-session -t nadeko` [(don't forget to replace **nadeko** in the command to what ever you named your bot's session)](http://nadekobot.readthedocs.io/en/latest/guides/OSX%20Guide/#some-more-info)
- Make sure the bot is **not** running. - Make sure the bot is **not** running.
- `tmux new -s nadeko` (**nadeko** is the name of the session) - `tmux new -s nadeko` (**nadeko** is the name of the session)
- `cd ~ && wget -N https://github.com/Kwoth/NadekoBot-BashScript/raw/1.4/linuxAIO.sh && bash linuxAIO.sh` - `cd ~ && wget -N https://github.com/Kwoth/NadekoBot-BashScript/raw/1.9/linuxAIO.sh && bash linuxAIO.sh`
- Choose `1` to update the bot with **latest build** available. - Choose `1` to update the bot with **latest build** available.
- Next, choose either `2` or `3` to run the bot again with **normally** or **auto restart** respectively. - Next, choose either `2` or `3` to run the bot again with **normally** or **auto restart** respectively.
- Done. - Done.

View File

@ -1,3 +1,5 @@
# This section is for users who are upgrading from versions older than 1.4 to 1.4+
#### If you have NadekoBot 1.x on Windows #### If you have NadekoBot 1.x on Windows
- Go to `NadekoBot\src\NadekoBot` and backup your `credentials.json` file; then go to `NadekoBot\src\NadekoBot\bin\Release\netcoreapp1.0` and backup your `data` folder. - Go to `NadekoBot\src\NadekoBot` and backup your `credentials.json` file; then go to `NadekoBot\src\NadekoBot\bin\Release\netcoreapp1.0` and backup your `data` folder.
@ -10,21 +12,15 @@
#### If you are running Dockerised Nadeko #### If you are running Dockerised Nadeko
- Shutdown your existing container **docker stop nadeko**. - There is an updating section in the docker guide.
- Move you credentials and other files to another folder.
- Delete your container **docker rm nadeko**.
- Create a new container **docker create --name=nadeko -v /nadeko/:/root/nadeko uirel/nadeko:1.4**.
- Start the container **docker start nadeko** wait for it to complain about lacking credentials.
- Stop the container **docker stop nadeko** open the nadeko folder and replace the credentials, database and other files with your copies.
- Restart the container **docker start nadeko**.
#### If you have NadekoBot 1.x on Linux or macOS #### If you have NadekoBot 1.x on Linux or macOS
- Backup the `NadekoBot.db` from `NadekoBot/src/NadekoBot/bin/Release/netcoreapp1.0/data` - Backup the `NadekoBot.db` from `NadekoBot/src/NadekoBot/bin/Release/netcoreapp1.0/data`
- Backup the `credentials.json` from `NadekoBot/src/NadekoBot/` - Backup the `credentials.json` from `NadekoBot/src/NadekoBot/`
- **For MacOS Users Only:** download and install the latest version of [.NET Core SDK](https://www.microsoft.com/net/core#macos) - **For MacOS Users Only:** download and install the latest version of [.NET Core SDK](https://www.microsoft.com/net/core#macos)
- Next, use the command `cd ~ && wget -N https://github.com/Kwoth/NadekoBot-BashScript/raw/1.4/linuxAIO.sh && bash linuxAIO.sh` - Next, use the command `cd ~ && wget -N https://github.com/Kwoth/NadekoBot-BashScript/raw/1.9/linuxAIO.sh && bash linuxAIO.sh`
- **For Ubuntu, Debian and CentOS Users Only:** use the option `4. Auto-Install Prerequisites` to install the latest version of .NET Core SDK. - **For Ubuntu, Debian and CentOS Users Only:** use the option `4. Auto-Install Prerequisites` to install the latest version of .NET Core SDK.
- Use option `1. Download NadekoBot` to update your NadekoBot to 1.4.x. - Use option `1. Download NadekoBot` to update your NadekoBot to 1.9.x.
- Next, just [run your NadekoBot.](http://nadekobot.readthedocs.io/en/latest/guides/Linux%20Guide/#running-nadekobot) - Next, just [run your NadekoBot.](http://nadekobot.readthedocs.io/en/latest/guides/Linux%20Guide/#running-nadekobot)
- *NOTE: 1.4.x uses `NadekoBot.db` file from `NadekoBot/src/NadekoBot/bin/Release/netcoreapp1.1/data` folder.* - *NOTE: 1.9.x uses `NadekoBot.db` file from `NadekoBot/src/NadekoBot/bin/Release/netcoreapp2.0/data` folder.*

View File

@ -10,7 +10,7 @@ NadekoBot is an open source project, and it can be found on our [GitHub][GitHub]
Here you can read current [Issues][Issues]. Here you can read current [Issues][Issues].
If you want to contribute, be sure to PR on the **[1.4][1.4]** branch. If you want to contribute, be sure to PR on the current **[default][repo]** branch.
##Content ##Content
- [About](about.md) - [About](about.md)
@ -37,4 +37,4 @@ If you want to contribute, be sure to PR on the **[1.4][1.4]** branch.
[NadekoBot Server]: https://discord.gg/nadekobot [NadekoBot Server]: https://discord.gg/nadekobot
[GitHub]: https://github.com/Kwoth/NadekoBot [GitHub]: https://github.com/Kwoth/NadekoBot
[Issues]: https://github.com/Kwoth/NadekoBot/issues [Issues]: https://github.com/Kwoth/NadekoBot/issues
[1.4]: https://github.com/Kwoth/NadekoBot/tree/1.4 [repo]: https://github.com/Kwoth/NadekoBot

View File

@ -124,49 +124,49 @@ namespace NadekoBot.Modules.Administration
switch (type) switch (type)
{ {
case LogType.Other: case LogType.Other:
channelId = logSetting.LogOtherId = (logSetting.LogOtherId == null ? channel.Id : default(ulong?)); channelId = logSetting.LogOtherId = (logSetting.LogOtherId == null ? channel.Id : default);
break; break;
case LogType.MessageUpdated: case LogType.MessageUpdated:
channelId = logSetting.MessageUpdatedId = (logSetting.MessageUpdatedId == null ? channel.Id : default(ulong?)); channelId = logSetting.MessageUpdatedId = (logSetting.MessageUpdatedId == null ? channel.Id : default);
break; break;
case LogType.MessageDeleted: case LogType.MessageDeleted:
channelId = logSetting.MessageDeletedId = (logSetting.MessageDeletedId == null ? channel.Id : default(ulong?)); channelId = logSetting.MessageDeletedId = (logSetting.MessageDeletedId == null ? channel.Id : default);
break; break;
case LogType.UserJoined: case LogType.UserJoined:
channelId = logSetting.UserJoinedId = (logSetting.UserJoinedId == null ? channel.Id : default(ulong?)); channelId = logSetting.UserJoinedId = (logSetting.UserJoinedId == null ? channel.Id : default);
break; break;
case LogType.UserLeft: case LogType.UserLeft:
channelId = logSetting.UserLeftId = (logSetting.UserLeftId == null ? channel.Id : default(ulong?)); channelId = logSetting.UserLeftId = (logSetting.UserLeftId == null ? channel.Id : default);
break; break;
case LogType.UserBanned: case LogType.UserBanned:
channelId = logSetting.UserBannedId = (logSetting.UserBannedId == null ? channel.Id : default(ulong?)); channelId = logSetting.UserBannedId = (logSetting.UserBannedId == null ? channel.Id : default);
break; break;
case LogType.UserUnbanned: case LogType.UserUnbanned:
channelId = logSetting.UserUnbannedId = (logSetting.UserUnbannedId == null ? channel.Id : default(ulong?)); channelId = logSetting.UserUnbannedId = (logSetting.UserUnbannedId == null ? channel.Id : default);
break; break;
case LogType.UserUpdated: case LogType.UserUpdated:
channelId = logSetting.UserUpdatedId = (logSetting.UserUpdatedId == null ? channel.Id : default(ulong?)); channelId = logSetting.UserUpdatedId = (logSetting.UserUpdatedId == null ? channel.Id : default);
break; break;
case LogType.UserMuted: case LogType.UserMuted:
channelId = logSetting.UserMutedId = (logSetting.UserMutedId == null ? channel.Id : default(ulong?)); channelId = logSetting.UserMutedId = (logSetting.UserMutedId == null ? channel.Id : default);
break; break;
case LogType.ChannelCreated: case LogType.ChannelCreated:
channelId = logSetting.ChannelCreatedId = (logSetting.ChannelCreatedId == null ? channel.Id : default(ulong?)); channelId = logSetting.ChannelCreatedId = (logSetting.ChannelCreatedId == null ? channel.Id : default);
break; break;
case LogType.ChannelDestroyed: case LogType.ChannelDestroyed:
channelId = logSetting.ChannelDestroyedId = (logSetting.ChannelDestroyedId == null ? channel.Id : default(ulong?)); channelId = logSetting.ChannelDestroyedId = (logSetting.ChannelDestroyedId == null ? channel.Id : default);
break; break;
case LogType.ChannelUpdated: case LogType.ChannelUpdated:
channelId = logSetting.ChannelUpdatedId = (logSetting.ChannelUpdatedId == null ? channel.Id : default(ulong?)); channelId = logSetting.ChannelUpdatedId = (logSetting.ChannelUpdatedId == null ? channel.Id : default);
break; break;
case LogType.UserPresence: case LogType.UserPresence:
channelId = logSetting.LogUserPresenceId = (logSetting.LogUserPresenceId == null ? channel.Id : default(ulong?)); channelId = logSetting.LogUserPresenceId = (logSetting.LogUserPresenceId == null ? channel.Id : default);
break; break;
case LogType.VoicePresence: case LogType.VoicePresence:
channelId = logSetting.LogVoicePresenceId = (logSetting.LogVoicePresenceId == null ? channel.Id : default(ulong?)); channelId = logSetting.LogVoicePresenceId = (logSetting.LogVoicePresenceId == null ? channel.Id : default);
break; break;
case LogType.VoicePresenceTTS: case LogType.VoicePresenceTTS:
channelId = logSetting.LogVoicePresenceTTSId = (logSetting.LogVoicePresenceTTSId == null ? channel.Id : default(ulong?)); channelId = logSetting.LogVoicePresenceTTSId = (logSetting.LogVoicePresenceTTSId == null ? channel.Id : default);
break; break;
} }

View File

@ -194,6 +194,7 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.Administrator)]
public async Task AntispamIgnore() public async Task AntispamIgnore()
{ {
var channel = (ITextChannel)Context.Channel; var channel = (ITextChannel)Context.Channel;

View File

@ -31,9 +31,11 @@ namespace NadekoBot.Modules.Administration
private readonly MusicService _music; private readonly MusicService _music;
private readonly IBotConfigProvider _bc; private readonly IBotConfigProvider _bc;
private readonly NadekoBot _bot; private readonly NadekoBot _bot;
private readonly IBotCredentials _creds;
public SelfCommands(DbService db, NadekoBot bot, DiscordSocketClient client, public SelfCommands(DbService db, NadekoBot bot, DiscordSocketClient client,
MusicService music, IImagesService images, IBotConfigProvider bc) MusicService music, IImagesService images, IBotConfigProvider bc,
IBotCredentials creds)
{ {
_db = db; _db = db;
_client = client; _client = client;
@ -41,6 +43,7 @@ namespace NadekoBot.Modules.Administration
_music = music; _music = music;
_bc = bc; _bc = bc;
_bot = bot; _bot = bot;
_creds = creds;
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
@ -280,6 +283,22 @@ namespace NadekoBot.Modules.Administration
Environment.Exit(0); Environment.Exit(0);
} }
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task Restart()
{
var cmd = _creds.RestartCommand;
if (cmd == null || string.IsNullOrWhiteSpace(cmd.Cmd))
{
await ReplyErrorLocalized("restart_fail").ConfigureAwait(false);
return;
}
await ReplyConfirmLocalized("restarting").ConfigureAwait(false);
Process.Start(cmd.Cmd, cmd.Args);
Environment.Exit(0);
}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[OwnerOnly] [OwnerOnly]
public async Task SetName([Remainder] string newName) public async Task SetName([Remainder] string newName)

View File

@ -81,26 +81,28 @@ namespace NadekoBot.Modules.Administration.Services
//remove old //remove old
if (oldVc != null && guildVcRoles.TryGetValue(oldVc.Id, out IRole role)) if (oldVc != null && guildVcRoles.TryGetValue(oldVc.Id, out IRole role))
{ {
if (gusr.Roles.Contains(role)) try
{
await gusr.RemoveRoleAsync(role).ConfigureAwait(false);
}
catch
{ {
try try
{ {
await gusr.RemoveRoleAsync(role).ConfigureAwait(false);
await Task.Delay(500).ConfigureAwait(false); await Task.Delay(500).ConfigureAwait(false);
}
catch
{
await Task.Delay(200).ConfigureAwait(false);
await gusr.RemoveRoleAsync(role).ConfigureAwait(false); await gusr.RemoveRoleAsync(role).ConfigureAwait(false);
await Task.Delay(500).ConfigureAwait(false);
} }
catch { }
} }
} }
//add new //add new
if (newVc != null && guildVcRoles.TryGetValue(newVc.Id, out role)) if (newVc != null && guildVcRoles.TryGetValue(newVc.Id, out role))
{ {
if (!gusr.Roles.Contains(role)) if (!gusr.Roles.Contains(role))
{
await Task.Delay(500).ConfigureAwait(false);
await gusr.AddRoleAsync(role).ConfigureAwait(false); await gusr.AddRoleAsync(role).ConfigureAwait(false);
}
} }
} }

View File

@ -37,7 +37,10 @@ namespace NadekoBot.Modules.Administration
.AddField(efb => efb.WithName(GetText("reason")).WithValue(reason ?? "-"))) .AddField(efb => efb.WithName(GetText("reason")).WithValue(reason ?? "-")))
.ConfigureAwait(false); .ConfigureAwait(false);
} }
catch { } catch
{
}
var punishment = await _service.Warn(Context.Guild, user.Id, Context.User.ToString(), reason).ConfigureAwait(false); var punishment = await _service.Warn(Context.Guild, user.Id, Context.User.ToString(), reason).ConfigureAwait(false);
if (punishment == null) if (punishment == null)

View File

@ -80,6 +80,60 @@ namespace NadekoBot.Modules.CustomReactions
).ConfigureAwait(false); ).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases]
public async Task EditCustReact(int id, [Remainder] string message)
{
var channel = Context.Channel as ITextChannel;
if (string.IsNullOrWhiteSpace(message) || id < 0)
return;
if ((channel == null && !_creds.IsOwner(Context.User)) || (channel != null && !((IGuildUser)Context.User).GuildPermissions.Administrator))
{
await ReplyErrorLocalized("insuff_perms").ConfigureAwait(false);
return;
}
CustomReaction cr;
using (var uow = _db.UnitOfWork)
{
cr = uow.CustomReactions.Get(id);
if (cr != null)
{
cr.Response = message;
await uow.CompleteAsync().ConfigureAwait(false);
}
}
if (cr != null)
{
if (channel == null)
{
await _service.EditGcr(id, message).ConfigureAwait(false);
}
else
{
if (_service.GuildReactions.TryGetValue(Context.Guild.Id, out var crs))
{
var oldCr = crs.FirstOrDefault(x => x.Id == id);
if (oldCr != null)
oldCr.Response = message;
}
}
await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithTitle(GetText("edited_cust_react"))
.WithDescription($"#{cr.Id}")
.AddField(efb => efb.WithName(GetText("trigger")).WithValue(cr.Trigger))
.AddField(efb => efb.WithName(GetText("response")).WithValue(message.Length > 1024 ? GetText("redacted_too_long") : message))
).ConfigureAwait(false);
}
else
{
await ReplyErrorLocalized("edit_fail").ConfigureAwait(false);
}
}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[Priority(1)] [Priority(1)]
public async Task ListCustReact(int page = 1) public async Task ListCustReact(int page = 1)
@ -296,12 +350,8 @@ namespace NadekoBot.Modules.CustomReactions
} }
var setValue = reaction.ContainsAnywhere = !reaction.ContainsAnywhere; var setValue = reaction.ContainsAnywhere = !reaction.ContainsAnywhere;
using (var uow = _db.UnitOfWork) await _service.SetCrCaAsync(reaction.Id, setValue).ConfigureAwait(false);
{
uow.CustomReactions.Get(id).ContainsAnywhere = setValue;
uow.Complete();
}
if (setValue) if (setValue)
{ {
@ -348,11 +398,7 @@ namespace NadekoBot.Modules.CustomReactions
var setValue = reaction.DmResponse = !reaction.DmResponse; var setValue = reaction.DmResponse = !reaction.DmResponse;
using (var uow = _db.UnitOfWork) await _service.SetCrDmAsync(reaction.Id, setValue).ConfigureAwait(false);
{
uow.CustomReactions.Get(id).DmResponse = setValue;
uow.Complete();
}
if (setValue) if (setValue)
{ {
@ -398,12 +444,8 @@ namespace NadekoBot.Modules.CustomReactions
} }
var setValue = reaction.AutoDeleteTrigger = !reaction.AutoDeleteTrigger; var setValue = reaction.AutoDeleteTrigger = !reaction.AutoDeleteTrigger;
using (var uow = _db.UnitOfWork) await _service.SetCrAdAsync(reaction.Id, setValue).ConfigureAwait(false);
{
uow.CustomReactions.Get(id).AutoDeleteTrigger = setValue;
uow.Complete();
}
if (setValue) if (setValue)
{ {

View File

@ -59,6 +59,39 @@ namespace NadekoBot.Modules.CustomReactions.Services
var id = int.Parse(msg); var id = int.Parse(msg);
GlobalReactions = GlobalReactions.Where(cr => cr?.Id != id).ToArray(); GlobalReactions = GlobalReactions.Where(cr => cr?.Id != id).ToArray();
}, StackExchange.Redis.CommandFlags.FireAndForget); }, StackExchange.Redis.CommandFlags.FireAndForget);
sub.Subscribe(_client.CurrentUser.Id + "_gcr.edited", (ch, msg) =>
{
var obj = new { Id = 0, Message = "" };
obj = JsonConvert.DeserializeAnonymousType(msg, obj);
var gcr = GlobalReactions.FirstOrDefault(x => x.Id == obj.Id);
if (gcr != null)
gcr.Response = obj.Message;
}, StackExchange.Redis.CommandFlags.FireAndForget);
sub.Subscribe(_client.CurrentUser.Id + "_crad.toggle", (ch, msg) =>
{
var obj = new { Id = 0, Value = false };
obj = JsonConvert.DeserializeAnonymousType(msg, obj);
var gcr = GlobalReactions.FirstOrDefault(x => x.Id == obj.Id);
if (gcr != null)
gcr.AutoDeleteTrigger = obj.Value;
}, StackExchange.Redis.CommandFlags.FireAndForget);
sub.Subscribe(_client.CurrentUser.Id + "_crdm.toggle", (ch, msg) =>
{
var obj = new { Id = 0, Value = false };
obj = JsonConvert.DeserializeAnonymousType(msg, obj);
var gcr = GlobalReactions.FirstOrDefault(x => x.Id == obj.Id);
if(gcr != null)
gcr.DmResponse = obj.Value;
}, StackExchange.Redis.CommandFlags.FireAndForget);
sub.Subscribe(_client.CurrentUser.Id + "_crca.toggle", (ch, msg) =>
{
var obj = new { Id = 0, Value = false };
obj = JsonConvert.DeserializeAnonymousType(msg, obj);
var gcr = GlobalReactions.FirstOrDefault(x => x.Id == obj.Id);
if (gcr != null)
gcr.ContainsAnywhere = obj.Value;
}, StackExchange.Redis.CommandFlags.FireAndForget);
var items = uow.CustomReactions.GetAll(); var items = uow.CustomReactions.GetAll();
@ -66,6 +99,17 @@ namespace NadekoBot.Modules.CustomReactions.Services
GlobalReactions = items.Where(g => g.GuildId == null || g.GuildId == 0).ToArray(); GlobalReactions = items.Where(g => g.GuildId == null || g.GuildId == 0).ToArray();
} }
public Task EditGcr(int id, string message)
{
var sub = _cache.Redis.GetSubscriber();
return sub.PublishAsync(_client.CurrentUser.Id + "_gcr.edited", JsonConvert.SerializeObject(new
{
Id = id,
Message = message,
}));
}
public Task AddGcr(CustomReaction cr) public Task AddGcr(CustomReaction cr)
{ {
var sub = _cache.Redis.GetSubscriber(); var sub = _cache.Redis.GetSubscriber();
@ -123,7 +167,11 @@ namespace NadekoBot.Modules.CustomReactions.Services
return false; return false;
var hasTarget = cr.Response.ToLowerInvariant().Contains("%target%"); var hasTarget = cr.Response.ToLowerInvariant().Contains("%target%");
var trigger = cr.TriggerWithContext(umsg, _client).Trim().ToLowerInvariant(); var trigger = cr.TriggerWithContext(umsg, _client).Trim().ToLowerInvariant();
return ((hasTarget && content.StartsWith(trigger + " ")) || (_bc.BotConfig.CustomReactionsStartWith && content.StartsWith(trigger + " ")) || content == trigger); return ((cr.ContainsAnywhere &&
(content.GetWordPosition(trigger) != WordPosition.None))
|| (hasTarget && content.StartsWith(trigger + " "))
|| (_bc.BotConfig.CustomReactionsStartWith && content.StartsWith(trigger + " "))
|| content == trigger);
}).ToArray(); }).ToArray();
if (grs.Length == 0) if (grs.Length == 0)
return null; return null;
@ -171,5 +219,44 @@ namespace NadekoBot.Modules.CustomReactions.Services
} }
return false; return false;
} }
public Task SetCrDmAsync(int id, bool setValue)
{
using (var uow = _db.UnitOfWork)
{
uow.CustomReactions.Get(id).DmResponse = setValue;
uow.Complete();
}
var sub = _cache.Redis.GetSubscriber();
var data = new { Id = id, Value = setValue };
return sub.PublishAsync(_client.CurrentUser.Id + "_crdm.toggle", JsonConvert.SerializeObject(data));
}
public Task SetCrAdAsync(int id, bool setValue)
{
using (var uow = _db.UnitOfWork)
{
uow.CustomReactions.Get(id).AutoDeleteTrigger = setValue;
uow.Complete();
}
var sub = _cache.Redis.GetSubscriber();
var data = new { Id = id, Value = setValue };
return sub.PublishAsync(_client.CurrentUser.Id + "_crad.toggle", JsonConvert.SerializeObject(data));
}
public Task SetCrCaAsync(int id, bool setValue)
{
using (var uow = _db.UnitOfWork)
{
uow.CustomReactions.Get(id).ContainsAnywhere = setValue;
uow.Complete();
}
var sub = _cache.Redis.GetSubscriber();
var data = new { Id = id, Value = setValue };
return sub.PublishAsync(_client.CurrentUser.Id + "_crca.toggle", JsonConvert.SerializeObject(data));
}
} }
} }

View File

@ -41,12 +41,51 @@ namespace NadekoBot.Modules.Gambling
var ar = new AnimalRace(_cs, _bc.BotConfig.RaceAnimals.Shuffle().ToArray()); var ar = new AnimalRace(_cs, _bc.BotConfig.RaceAnimals.Shuffle().ToArray());
if (!AnimalRaces.TryAdd(Context.Guild.Id, ar)) if (!AnimalRaces.TryAdd(Context.Guild.Id, ar))
return Context.Channel.SendErrorAsync(GetText("animal_race"), GetText("animal_race_already_started")); return Context.Channel.SendErrorAsync(GetText("animal_race"), GetText("animal_race_already_started"));
ar.Initialize(); ar.Initialize();
var count = 0;
Task _client_MessageReceived(SocketMessage arg)
{
var _ = Task.Run(() => {
try
{
if (arg.Channel.Id == Context.Channel.Id)
{
if (ar.CurrentPhase == AnimalRace.Phase.Running && ++count % 9 == 0)
{
raceMessage = null;
}
}
}
catch { }
});
return Task.CompletedTask;
}
Task Ar_OnEnded(AnimalRace race)
{
_client.MessageReceived -= _client_MessageReceived;
AnimalRaces.TryRemove(Context.Guild.Id, out _);
var winner = race.FinishedUsers[0];
if (race.FinishedUsers[0].Bet > 0)
{
return Context.Channel.SendConfirmAsync(GetText("animal_race"),
GetText("animal_race_won_money", Format.Bold(winner.Username),
winner.Animal.Icon, (race.FinishedUsers[0].Bet * (race.Users.Length - 1)) + _bc.BotConfig.CurrencySign));
}
else
{
return Context.Channel.SendConfirmAsync(GetText("animal_race"),
GetText("animal_race_won", Format.Bold(winner.Username), winner.Animal.Icon));
}
}
ar.OnStartingFailed += Ar_OnStartingFailed; ar.OnStartingFailed += Ar_OnStartingFailed;
ar.OnStateUpdate += Ar_OnStateUpdate; ar.OnStateUpdate += Ar_OnStateUpdate;
ar.OnEnded += Ar_OnEnded; ar.OnEnded += Ar_OnEnded;
ar.OnStarted += Ar_OnStarted; ar.OnStarted += Ar_OnStarted;
_client.MessageReceived += _client_MessageReceived;
return Context.Channel.SendConfirmAsync(GetText("animal_race"), GetText("animal_race_starting"), return Context.Channel.SendConfirmAsync(GetText("animal_race"), GetText("animal_race_starting"),
footer: GetText("animal_race_join_instr", Prefix)); footer: GetText("animal_race_join_instr", Prefix));
@ -60,23 +99,6 @@ namespace NadekoBot.Modules.Gambling
return Context.Channel.SendConfirmAsync(GetText("animal_race"), GetText("animal_race_starting_with_x", race.Users.Length)); return Context.Channel.SendConfirmAsync(GetText("animal_race"), GetText("animal_race_starting_with_x", race.Users.Length));
} }
private Task Ar_OnEnded(AnimalRace race)
{
AnimalRaces.TryRemove(Context.Guild.Id, out _);
var winner = race.FinishedUsers[0];
if (race.FinishedUsers[0].Bet > 0)
{
return Context.Channel.SendConfirmAsync(GetText("animal_race"),
GetText("animal_race_won_money", Format.Bold(winner.Username),
winner.Animal.Icon, (race.FinishedUsers[0].Bet * (race.Users.Length - 1)) + _bc.BotConfig.CurrencySign));
}
else
{
return Context.Channel.SendConfirmAsync(GetText("animal_race"),
GetText("animal_race_won", Format.Bold(winner.Username), winner.Animal.Icon));
}
}
private async Task Ar_OnStateUpdate(AnimalRace race) private async Task Ar_OnStateUpdate(AnimalRace race)
{ {
var text = $@"|🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🔚| var text = $@"|🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🔚|
@ -88,11 +110,13 @@ namespace NadekoBot.Modules.Gambling
}))} }))}
|🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🔚|"; |🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🔚|";
if (raceMessage == null) var msg = raceMessage;
if (msg == null)
raceMessage = await Context.Channel.SendConfirmAsync(text) raceMessage = await Context.Channel.SendConfirmAsync(text)
.ConfigureAwait(false); .ConfigureAwait(false);
else else
await raceMessage.ModifyAsync(x => x.Embed = new EmbedBuilder() await msg.ModifyAsync(x => x.Embed = new EmbedBuilder()
.WithTitle(GetText("animal_race")) .WithTitle(GetText("animal_race"))
.WithDescription(text) .WithDescription(text)
.WithOkColor() .WithOkColor()

View File

@ -192,7 +192,7 @@ namespace NadekoBot.Modules.Gambling
if (users.Count > 0) if (users.Count > 0)
{ {
await _cs.AddToManyAsync("", _amount, users.ToArray()).ConfigureAwait(false); await _cs.AddToManyAsync("Reaction Event", _amount, users.ToArray()).ConfigureAwait(false);
} }
users.Clear(); users.Clear();

View File

@ -56,9 +56,9 @@ namespace NadekoBot.Modules.Games.Common.Hangman
public Task EndedTask => _endingCompletionSource.Task; public Task EndedTask => _endingCompletionSource.Task;
public Hangman(TermType type) public Hangman(string type)
{ {
this.TermType = type.ToString().Replace('_', ' ').ToTitleCase(); this.TermType = type.Trim().ToLowerInvariant().ToTitleCase();
this.Term = TermPool.GetTerm(type); this.Term = TermPool.GetTerm(type);
} }

View File

@ -3,7 +3,6 @@ using NadekoBot.Modules.Games.Common.Hangman.Exceptions;
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -25,21 +24,17 @@ namespace NadekoBot.Modules.Games.Common.Hangman
} }
} }
private static readonly ImmutableArray<TermType> _termTypes = Enum.GetValues(typeof(TermType)) public static HangmanObject GetTerm(string type)
.Cast<TermType>()
.ToImmutableArray();
public static HangmanObject GetTerm(TermType type)
{ {
var rng = new NadekoRandom(); var rng = new NadekoRandom();
if (type == TermType.Random) if (type == "random")
{ {
var keys = Data.Keys.ToArray(); var keys = Data.Keys.ToArray();
type = _termTypes[rng.Next(0, _termTypes.Length - 1)]; // - 1 because last one is 'all' type = Data.Keys.ToArray()[rng.Next(0, Data.Keys.Count())];
} }
if (!Data.TryGetValue(type.ToString(), out var termTypes) || termTypes.Length == 0) if (!Data.TryGetValue(type, out var termTypes) || termTypes.Length == 0)
throw new TermNotFoundException(); throw new TermNotFoundException();
var obj = termTypes[rng.Next(0, termTypes.Length)]; var obj = termTypes[rng.Next(0, termTypes.Length)];

View File

@ -29,12 +29,12 @@ namespace NadekoBot.Modules.Games
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Hangmanlist() public async Task Hangmanlist()
{ {
await Context.Channel.SendConfirmAsync(Format.Code(GetText("hangman_types", Prefix)) + "\n" + string.Join(", ", TermPool.Data.Keys)); await Context.Channel.SendConfirmAsync(Format.Code(GetText("hangman_types", Prefix)) + "\n" + string.Join("\n", TermPool.Data.Keys));
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Hangman([Remainder]TermType type = TermType.Random) public async Task Hangman([Remainder]string type = "random")
{ {
var hm = new Hangman(type); var hm = new Hangman(type);

View File

@ -155,7 +155,7 @@ namespace NadekoBot.Modules.Help
"http://nadekobot.readthedocs.io/en/latest/Commands%20List/", "http://nadekobot.readthedocs.io/en/latest/Commands%20List/",
"http://nadekobot.readthedocs.io/en/latest/").ConfigureAwait(false); "http://nadekobot.readthedocs.io/en/latest/").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task Donate() public async Task Donate()
{ {

View File

@ -2,17 +2,39 @@
namespace NadekoBot.Modules.Searches.Common namespace NadekoBot.Modules.Searches.Common
{ {
public class HitboxResponse public interface IStreamResponse
{ {
public bool Success { get; set; } = true; int Viewers { get; }
[JsonProperty("media_is_live")] string Title { get; }
public string MediaIsLive { get; set; } bool Live { get; }
public bool IsLive => MediaIsLive == "1"; string Game { get; }
[JsonProperty("media_views")] int FollowerCount { get; }
public string Views { get; set; } string Url { get; }
string Icon { get; }
} }
public class TwitchResponse public class SmashcastResponse : IStreamResponse
{
public bool Success { get; set; } = true;
public int Followers { get; set; }
[JsonProperty("user_logo")]
public string UserLogo { get; set; }
[JsonProperty("is_live")]
public string IsLive { get; set; }
public int Viewers => 0;
public string Title => "";
public bool Live => IsLive == "1";
public string Game => "";
public int FollowerCount => Followers;
public string Icon => !string.IsNullOrWhiteSpace(UserLogo)
? "https://edge.sf.hitbox.tv" + UserLogo
: "";
public string Url { get; set; }
}
public class TwitchResponse : IStreamResponse
{ {
public string Error { get; set; } = null; public string Error { get; set; } = null;
public bool IsLive => Stream != null; public bool IsLive => Stream != null;
@ -21,15 +43,53 @@ namespace NadekoBot.Modules.Searches.Common
public class StreamInfo public class StreamInfo
{ {
public int Viewers { get; set; } public int Viewers { get; set; }
public string Game { get; set; }
public ChannelInfo Channel { get; set; }
public class ChannelInfo
{
public string Status { get; set; }
public string Logo { get; set; }
public int Followers { get; set; }
}
} }
public int Viewers => Stream?.Viewers ?? 0;
public string Title => Stream?.Channel?.Status;
public bool Live => IsLive;
public string Game => Stream?.Game;
public int FollowerCount => Stream?.Channel?.Followers ?? 0;
public string Url { get; set; }
public string Icon => Stream?.Channel?.Logo;
} }
public class BeamResponse public class MixerResponse : IStreamResponse
{ {
public class MixerType
{
public string Parent { get; set; }
public string Name { get; set; }
}
public class MixerThumbnail
{
public string Url { get; set; }
}
public string Url { get; set; }
public string Error { get; set; } = null; public string Error { get; set; } = null;
[JsonProperty("online")] [JsonProperty("online")]
public bool IsLive { get; set; } public bool IsLive { get; set; }
public int ViewersCurrent { get; set; } public int ViewersCurrent { get; set; }
public string Name { get; set; }
public int NumFollowers { get; set; }
public MixerType Type { get; set; }
public MixerThumbnail Thumbnail { get; set; }
public int Viewers => ViewersCurrent;
public string Title => Name;
public bool Live => IsLive;
public string Game => Type?.Name ?? "";
public int FollowerCount => NumFollowers;
public string Icon => Thumbnail?.Url;
} }
} }

View File

@ -6,7 +6,6 @@ using NadekoBot.Common.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Modules.Searches.Services; using NadekoBot.Modules.Searches.Services;
using System; using System;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml; using System.Xml;
@ -42,7 +41,12 @@ namespace NadekoBot.Modules.Searches
{ {
await reader.Read(); await reader.Read();
} }
catch { success = false; } catch (Exception ex)
{
Console.WriteLine(ex);
success = false;
}
} }
if (success) if (success)

View File

@ -20,6 +20,8 @@ using NadekoBot.Common;
using NadekoBot.Common.Attributes; using NadekoBot.Common.Attributes;
using NadekoBot.Modules.Searches.Common; using NadekoBot.Modules.Searches.Common;
using NadekoBot.Modules.Searches.Services; using NadekoBot.Modules.Searches.Services;
using NadekoBot.Common.Replacements;
using Discord.WebSocket;
namespace NadekoBot.Modules.Searches namespace NadekoBot.Modules.Searches
{ {
@ -34,6 +36,40 @@ namespace NadekoBot.Modules.Searches
_google = google; _google = google;
} }
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageMessages)]
public async Task Say([Remainder]string message)
{
if (string.IsNullOrWhiteSpace(message))
return;
var rep = new ReplacementBuilder()
.WithDefault(Context.User, Context.Channel, Context.Guild, (DiscordSocketClient)Context.Client)
.Build();
if (CREmbed.TryParse(message, out var embedData))
{
rep.Replace(embedData);
try
{
await Context.Channel.EmbedAsync(embedData.ToEmbed(), embedData.PlainText?.SanitizeMentions() ?? "").ConfigureAwait(false);
}
catch (Exception ex)
{
_log.Warn(ex);
}
}
else
{
var msg = rep.Replace(message);
if (!string.IsNullOrWhiteSpace(msg))
{
await Context.Channel.SendConfirmAsync(msg).ConfigureAwait(false);
}
}
}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task Weather([Remainder] string query) public async Task Weather([Remainder] string query)
{ {

View File

@ -229,11 +229,4 @@ namespace NadekoBot.Modules.Searches.Services
public ulong UserId { get; set; } public ulong UserId { get; set; }
public ulong ChannelId { get; set; } public ulong ChannelId { get; set; }
} }
public class StreamStatus
{
public bool IsLive { get; set; }
public string ApiLink { get; set; }
public string Views { get; set; }
}
} }

View File

@ -21,20 +21,21 @@ namespace NadekoBot.Modules.Searches.Services
{ {
private readonly Timer _streamCheckTimer; private readonly Timer _streamCheckTimer;
private bool firstStreamNotifPass { get; set; } = true; private bool firstStreamNotifPass { get; set; } = true;
private readonly ConcurrentDictionary<string, StreamStatus> _cachedStatuses = new ConcurrentDictionary<string, StreamStatus>(); private readonly ConcurrentDictionary<string, IStreamResponse> _cachedStatuses = new ConcurrentDictionary<string, IStreamResponse>();
private readonly DbService _db; private readonly DbService _db;
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
private readonly NadekoStrings _strings; private readonly NadekoStrings _strings;
private readonly HttpClient _http;
public StreamNotificationService(DbService db, DiscordSocketClient client, NadekoStrings strings) public StreamNotificationService(DbService db, DiscordSocketClient client, NadekoStrings strings)
{ {
_db = db; _db = db;
_client = client; _client = client;
_strings = strings; _strings = strings;
_http = new HttpClient();
_streamCheckTimer = new Timer(async (state) => _streamCheckTimer = new Timer(async (state) =>
{ {
var oldCachedStatuses = new ConcurrentDictionary<string, StreamStatus>(_cachedStatuses); var oldCachedStatuses = new ConcurrentDictionary<string, IStreamResponse>(_cachedStatuses);
_cachedStatuses.Clear(); _cachedStatuses.Clear();
IEnumerable<FollowedStream> streams; IEnumerable<FollowedStream> streams;
using (var uow = _db.UnitOfWork) using (var uow = _db.UnitOfWork)
@ -52,9 +53,9 @@ namespace NadekoBot.Modules.Searches.Services
return; return;
} }
StreamStatus oldStatus; IStreamResponse oldResponse;
if (oldCachedStatuses.TryGetValue(newStatus.ApiLink, out oldStatus) && if (oldCachedStatuses.TryGetValue(newStatus.Url, out oldResponse) &&
oldStatus.IsLive != newStatus.IsLive) oldResponse.Live != newStatus.Live)
{ {
var server = _client.GetGuild(fs.GuildId); var server = _client.GetGuild(fs.GuildId);
var channel = server?.GetTextChannel(fs.ChannelId); var channel = server?.GetTextChannel(fs.ChannelId);
@ -80,92 +81,85 @@ namespace NadekoBot.Modules.Searches.Services
}, null, TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(60)); }, null, TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(60));
} }
public async Task<StreamStatus> GetStreamStatus(FollowedStream stream, bool checkCache = true) public async Task<IStreamResponse> GetStreamStatus(FollowedStream stream, bool checkCache = true)
{ {
string response; string response;
StreamStatus result; IStreamResponse result;
switch (stream.Type) switch (stream.Type)
{ {
case FollowedStream.FollowedStreamType.Smashcast: case FollowedStream.FollowedStreamType.Smashcast:
var hitboxUrl = $"https://api.hitbox.tv/media/status/{stream.Username.ToLowerInvariant()}"; var smashcastUrl = $"https://api.smashcast.tv/user/{stream.Username.ToLowerInvariant()}";
if (checkCache && _cachedStatuses.TryGetValue(hitboxUrl, out result)) if (checkCache && _cachedStatuses.TryGetValue(smashcastUrl, out result))
return result; return result;
using (var http = new HttpClient()) response = await _http.GetStringAsync(smashcastUrl).ConfigureAwait(false);
{
response = await http.GetStringAsync(hitboxUrl).ConfigureAwait(false); var scData = JsonConvert.DeserializeObject<SmashcastResponse>(response);
} if (!scData.Success)
var hbData = JsonConvert.DeserializeObject<HitboxResponse>(response);
if (!hbData.Success)
throw new StreamNotFoundException($"{stream.Username} [{stream.Type}]"); throw new StreamNotFoundException($"{stream.Username} [{stream.Type}]");
result = new StreamStatus() scData.Url = smashcastUrl;
{ _cachedStatuses.AddOrUpdate(smashcastUrl, scData, (key, old) => scData);
IsLive = hbData.IsLive, return scData;
ApiLink = hitboxUrl,
Views = hbData.Views
};
_cachedStatuses.AddOrUpdate(hitboxUrl, result, (key, old) => result);
return result;
case FollowedStream.FollowedStreamType.Twitch: case FollowedStream.FollowedStreamType.Twitch:
var twitchUrl = $"https://api.twitch.tv/kraken/streams/{Uri.EscapeUriString(stream.Username.ToLowerInvariant())}?client_id=67w6z9i09xv2uoojdm9l0wsyph4hxo6"; var twitchUrl = $"https://api.twitch.tv/kraken/streams/{Uri.EscapeUriString(stream.Username.ToLowerInvariant())}?client_id=67w6z9i09xv2uoojdm9l0wsyph4hxo6";
if (checkCache && _cachedStatuses.TryGetValue(twitchUrl, out result)) if (checkCache && _cachedStatuses.TryGetValue(twitchUrl, out result))
return result; return result;
using (var http = new HttpClient()) response = await _http.GetStringAsync(twitchUrl).ConfigureAwait(false);
{
response = await http.GetStringAsync(twitchUrl).ConfigureAwait(false);
}
var twData = JsonConvert.DeserializeObject<TwitchResponse>(response); var twData = JsonConvert.DeserializeObject<TwitchResponse>(response);
if (twData.Error != null) if (twData.Error != null)
{ {
throw new StreamNotFoundException($"{stream.Username} [{stream.Type}]"); throw new StreamNotFoundException($"{stream.Username} [{stream.Type}]");
} }
result = new StreamStatus() twData.Url = twitchUrl;
{ _cachedStatuses.AddOrUpdate(twitchUrl, twData, (key, old) => twData);
IsLive = twData.IsLive, return twData;
ApiLink = twitchUrl,
Views = twData.Stream?.Viewers.ToString() ?? "0"
};
_cachedStatuses.AddOrUpdate(twitchUrl, result, (key, old) => result);
return result;
case FollowedStream.FollowedStreamType.Mixer: case FollowedStream.FollowedStreamType.Mixer:
var beamUrl = $"https://mixer.com/api/v1/channels/{stream.Username.ToLowerInvariant()}"; var beamUrl = $"https://mixer.com/api/v1/channels/{stream.Username.ToLowerInvariant()}";
if (checkCache && _cachedStatuses.TryGetValue(beamUrl, out result)) if (checkCache && _cachedStatuses.TryGetValue(beamUrl, out result))
return result; return result;
using (var http = new HttpClient()) response = await _http.GetStringAsync(beamUrl).ConfigureAwait(false);
{
response = await http.GetStringAsync(beamUrl).ConfigureAwait(false);
}
var bmData = JsonConvert.DeserializeObject<BeamResponse>(response);
var bmData = JsonConvert.DeserializeObject<MixerResponse>(response);
if (bmData.Error != null) if (bmData.Error != null)
throw new StreamNotFoundException($"{stream.Username} [{stream.Type}]"); throw new StreamNotFoundException($"{stream.Username} [{stream.Type}]");
result = new StreamStatus() bmData.Url = beamUrl;
{ _cachedStatuses.AddOrUpdate(beamUrl, bmData, (key, old) => bmData);
IsLive = bmData.IsLive, return bmData;
ApiLink = beamUrl,
Views = bmData.ViewersCurrent.ToString()
};
_cachedStatuses.AddOrUpdate(beamUrl, result, (key, old) => result);
return result;
default: default:
break; break;
} }
return null; return null;
} }
public EmbedBuilder GetEmbed(FollowedStream fs, StreamStatus status, ulong guildId) public EmbedBuilder GetEmbed(FollowedStream fs, IStreamResponse status, ulong guildId)
{ {
var embed = new EmbedBuilder().WithTitle(fs.Username) var embed = new EmbedBuilder()
.WithUrl(GetLink(fs)) .WithTitle(fs.Username)
.AddField(efb => efb.WithName(GetText(fs, "status")) .WithUrl(GetLink(fs))
.WithValue(status.IsLive ? "Online" : "Offline") .WithDescription(GetLink(fs))
.WithIsInline(true)) .AddField(efb => efb.WithName(GetText(fs, "status"))
.AddField(efb => efb.WithName(GetText(fs, "viewers")) .WithValue(status.Live ? "Online" : "Offline")
.WithValue(status.IsLive ? status.Views : "-") .WithIsInline(true))
.WithIsInline(true)) .AddField(efb => efb.WithName(GetText(fs, "viewers"))
.AddField(efb => efb.WithName(GetText(fs, "platform")) .WithValue(status.Live ? status.Viewers.ToString() : "-")
.WithValue(fs.Type.ToString()) .WithIsInline(true))
.WithIsInline(true)) .WithColor(status.Live ? NadekoBot.OkColor : NadekoBot.ErrorColor);
.WithColor(status.IsLive ? NadekoBot.OkColor : NadekoBot.ErrorColor);
if (!string.IsNullOrWhiteSpace(status.Title))
embed.WithAuthor(status.Title);
if (!string.IsNullOrWhiteSpace(status.Game))
embed.AddField(GetText(fs, "streaming"),
status.Game,
true);
embed.AddField(GetText(fs, "followers"),
status.FollowerCount.ToString(),
true);
if (!string.IsNullOrWhiteSpace(status.Icon))
embed.WithThumbnailUrl(status.Icon);
return embed; return embed;
} }
@ -179,7 +173,7 @@ namespace NadekoBot.Modules.Searches.Services
public string GetLink(FollowedStream fs) public string GetLink(FollowedStream fs)
{ {
if (fs.Type == FollowedStream.FollowedStreamType.Smashcast) if (fs.Type == FollowedStream.FollowedStreamType.Smashcast)
return $"https://www.hitbox.tv/{fs.Username}/"; return $"https://www.smashcast.tv/{fs.Username}/";
if (fs.Type == FollowedStream.FollowedStreamType.Twitch) if (fs.Type == FollowedStream.FollowedStreamType.Twitch)
return $"https://www.twitch.tv/{fs.Username}/"; return $"https://www.twitch.tv/{fs.Username}/";
if (fs.Type == FollowedStream.FollowedStreamType.Mixer) if (fs.Type == FollowedStream.FollowedStreamType.Mixer)
@ -187,4 +181,4 @@ namespace NadekoBot.Modules.Searches.Services
return "??"; return "??";
} }
} }
} }

View File

@ -9,6 +9,7 @@ using Microsoft.EntityFrameworkCore;
using NadekoBot.Common.Attributes; using NadekoBot.Common.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Modules.Searches.Services; using NadekoBot.Modules.Searches.Services;
using NadekoBot.Modules.Searches.Common;
namespace NadekoBot.Modules.Searches namespace NadekoBot.Modules.Searches
{ {
@ -124,11 +125,11 @@ namespace NadekoBot.Modules.Searches
Username = stream, Username = stream,
Type = platform, Type = platform,
})); }));
if (streamStatus.IsLive) if (streamStatus.Live)
{ {
await ReplyConfirmLocalized("streamer_online", await ReplyConfirmLocalized("streamer_online",
username, username,
streamStatus.Views) streamStatus.Viewers)
.ConfigureAwait(false); .ConfigureAwait(false);
} }
else else
@ -154,7 +155,7 @@ namespace NadekoBot.Modules.Searches
Type = type, Type = type,
}; };
StreamStatus status; IStreamResponse status;
try try
{ {
status = await _service.GetStreamStatus(fs).ConfigureAwait(false); status = await _service.GetStreamStatus(fs).ConfigureAwait(false);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -40,7 +40,13 @@ namespace NadekoBot.Services.Database.Repositories.Impl
public int GetUserGuildRanking(ulong userId, ulong guildId) public int GetUserGuildRanking(ulong userId, ulong guildId)
{ {
if (!_set.Where(x => x.GuildId == guildId && x.UserId == userId).Any()) if (!_set.Where(x => x.GuildId == guildId && x.UserId == userId).Any())
return _set.Count(); {
var cnt = _set.Count(x => x.GuildId == guildId);
if (cnt == 0)
return 1;
else
return cnt;
}
return _set return _set
.Where(x => x.GuildId == guildId) .Where(x => x.GuildId == guildId)

View File

@ -24,14 +24,27 @@ namespace NadekoBot.Services
string ShardRunArguments { get; } string ShardRunArguments { get; }
string PatreonCampaignId { get; } string PatreonCampaignId { get; }
string CleverbotApiKey { get; } string CleverbotApiKey { get; }
RestartConfig RestartCommand { get; }
}
public class RestartConfig
{
public RestartConfig(string cmd, string args)
{
this.Cmd = cmd;
this.Args = args;
}
public string Cmd { get; }
public string Args { get; }
} }
public class DBConfig public class DBConfig
{ {
public DBConfig(string type, string connString) public DBConfig(string type, string connectionString)
{ {
this.Type = type; this.Type = type;
this.ConnectionString = connString; this.ConnectionString = connectionString;
} }
public string Type { get; } public string Type { get; }
public string ConnectionString { get; } public string ConnectionString { get; }

View File

@ -27,7 +27,7 @@ namespace NadekoBot.Services.Impl
public string LoLApiKey { get; } public string LoLApiKey { get; }
public string OsuApiKey { get; } public string OsuApiKey { get; }
public string CleverbotApiKey { get; } public string CleverbotApiKey { get; }
public RestartConfig RestartCommand { get; }
public DBConfig Db { get; } public DBConfig Db { get; }
public int TotalShards { get; } public int TotalShards { get; }
public string CarbonKey { get; } public string CarbonKey { get; }
@ -72,6 +72,13 @@ namespace NadekoBot.Services.Impl
ShardRunCommand = data[nameof(ShardRunCommand)]; ShardRunCommand = data[nameof(ShardRunCommand)];
ShardRunArguments = data[nameof(ShardRunArguments)]; ShardRunArguments = data[nameof(ShardRunArguments)];
CleverbotApiKey = data[nameof(CleverbotApiKey)]; CleverbotApiKey = data[nameof(CleverbotApiKey)];
var restartSection = data.GetSection(nameof(RestartCommand));
var cmd = restartSection["cmd"];
var args = restartSection["args"];
if (!string.IsNullOrWhiteSpace(cmd))
RestartCommand = new RestartConfig(cmd, args);
if (string.IsNullOrWhiteSpace(ShardRunCommand)) if (string.IsNullOrWhiteSpace(ShardRunCommand))
ShardRunCommand = "dotnet"; ShardRunCommand = "dotnet";
if (string.IsNullOrWhiteSpace(ShardRunArguments)) if (string.IsNullOrWhiteSpace(ShardRunArguments))
@ -124,6 +131,7 @@ namespace NadekoBot.Services.Impl
public int TotalShards { get; set; } = 1; public int TotalShards { get; set; } = 1;
public string PatreonAccessToken { get; set; } = ""; public string PatreonAccessToken { get; set; } = "";
public string PatreonCampaignId { get; set; } = "334038"; public string PatreonCampaignId { get; set; } = "334038";
public string RestartCommand { get; set; } = null;
public string ShardRunCommand { get; set; } = ""; public string ShardRunCommand { get; set; } = "";
public string ShardRunArguments { get; set; } = ""; public string ShardRunArguments { get; set; } = "";

View File

@ -20,7 +20,7 @@ namespace NadekoBot.Services.Impl
private readonly IBotCredentials _creds; private readonly IBotCredentials _creds;
private readonly DateTime _started; private readonly DateTime _started;
public const string BotVersion = "1.9.1"; public const string BotVersion = "1.10.2";
public string Author => "Kwoth#2560"; public string Author => "Kwoth#2560";
public string Library => "Discord.Net"; public string Library => "Discord.Net";

View File

@ -4,7 +4,8 @@
"customreactions_insuff_perms": "Insufficient permissions. Requires Bot ownership for global custom reactions, and Administrator for server custom reactions.", "customreactions_insuff_perms": "Insufficient permissions. Requires Bot ownership for global custom reactions, and Administrator for server custom reactions.",
"customreactions_list_all": "List of all custom reactions", "customreactions_list_all": "List of all custom reactions",
"customreactions_name": "Custom Reactions", "customreactions_name": "Custom Reactions",
"customreactions_new_cust_react": "New Custom Reaction", "customreactions_new_cust_react": "\"New Custom Reaction",
"customreactions_edited_cust_react": "Custom Reaction Edited",
"customreactions_no_found": "No custom reaction found.", "customreactions_no_found": "No custom reaction found.",
"customreactions_no_found_id": "No custom reaction found with that id.", "customreactions_no_found_id": "No custom reaction found with that id.",
"customreactions_response": "Response", "customreactions_response": "Response",
@ -878,5 +879,10 @@
"searches_feed_not_valid": "Invalid link, or you're already following that feed on this server, or you've reached maximum number of feeds allowed.", "searches_feed_not_valid": "Invalid link, or you're already following that feed on this server, or you've reached maximum number of feeds allowed.",
"searches_feed_out_of_range": "Index out of range.", "searches_feed_out_of_range": "Index out of range.",
"searches_feed_removed": "Feed removed.", "searches_feed_removed": "Feed removed.",
"searches_feed_no_feed": "You haven't subscribed to any feeds on this server." "searches_feed_no_feed": "You haven't subscribed to any feeds on this server.",
"administration_restart_fail": "You must setup RestartCommand in your credentials.json",
"administration_restarting": "Restarting.",
"customreactions_edit_fail": "Custom reaction with that ID does not exist.",
"searches_streaming": "Streaming",
"searches_followers": "Followers"
} }

View File

@ -18,6 +18,7 @@
"TotalShards": 1, "TotalShards": 1,
"PatreonAccessToken": "", "PatreonAccessToken": "",
"PatreonCampaignId": "334038", "PatreonCampaignId": "334038",
"RestartCommand": null,
"ShardRunCommand": "", "ShardRunCommand": "",
"ShardRunArguments": "", "ShardRunArguments": "",
"ShardRunPort": null "ShardRunPort": null

View File

@ -284,7 +284,8 @@
"Cmd": "autoassignrole aar", "Cmd": "autoassignrole aar",
"Desc": "Automaticaly assigns a specified role to every user who joins the server.", "Desc": "Automaticaly assigns a specified role to every user who joins the server.",
"Usage": [ "Usage": [
"{0}aar` to disable, `{0}aar Role Name` to enabl" "{0}aar to disable",
"{0}aar Role Name to enable"
] ]
}, },
"leave": { "leave": {
@ -900,9 +901,9 @@
}, },
"nroll": { "nroll": {
"Cmd": "nroll", "Cmd": "nroll",
"Desc": "Rolls in a given range.", "Desc": "Rolls in a given range. If you specify just one number instead of the range, it will role from 0 to that number.",
"Usage": [ "Usage": [
"{0}nroll 5` (rolls 0-5", "{0}nroll 5",
"{0}nroll 5-15" "{0}nroll 5-15"
] ]
}, },
@ -1199,8 +1200,7 @@
"Cmd": "playlist pl", "Cmd": "playlist pl",
"Desc": "Queues up to 500 songs from a youtube playlist specified by a link, or keywords.", "Desc": "Queues up to 500 songs from a youtube playlist specified by a link, or keywords.",
"Usage": [ "Usage": [
"{0}pl playlist lin", "{0}pl <youtube_playlist_link>"
"ame"
] ]
}, },
"soundcloudpl": { "soundcloudpl": {
@ -1738,7 +1738,7 @@
"Cmd": "greetdmmsg", "Cmd": "greetdmmsg",
"Desc": "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.me/embedbuilder/> instead of a regular text, if you want the message to be embedded.", "Desc": "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.me/embedbuilder/> instead of a regular text, if you want the message to be embedded.",
"Usage": [ "Usage": [
"{0}greetdmmsg Welcome to the server, %user%`" "{0}greetdmmsg Welcome to the server, %user%"
] ]
}, },
"cash": { "cash": {
@ -2126,7 +2126,7 @@
"Desc": "Show's basic stats on a player (competitive rank, playtime, level etc) Region codes are: `eu` `us` `cn` `kr`", "Desc": "Show's basic stats on a player (competitive rank, playtime, level etc) Region codes are: `eu` `us` `cn` `kr`",
"Usage": [ "Usage": [
"{0}ow us Battletag#1337", "{0}ow us Battletag#1337",
"`{0}overwatch eu Battletag#2016" "{0}overwatch eu Battletag#2016"
] ]
}, },
"acro": { "acro": {
@ -2390,7 +2390,7 @@
"Cmd": "tictactoe ttt", "Cmd": "tictactoe ttt",
"Desc": "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.", "Desc": "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.",
"Usage": [ "Usage": [
"0}tt" "{0}ttt"
] ]
}, },
"timezones": { "timezones": {
@ -2786,14 +2786,16 @@
"Cmd": "xpexclude xpex", "Cmd": "xpexclude xpex",
"Desc": "Exclude a channel, role or current server from the xp system.", "Desc": "Exclude a channel, role or current server from the xp system.",
"Usage": [ "Usage": [
"{0}xpex Role Excluded-Role` `{0}xpex Server" "{0}xpex Role Excluded-Role",
"{0}xpex Server"
] ]
}, },
"xpnotify": { "xpnotify": {
"Cmd": "xpnotify xpn", "Cmd": "xpnotify xpn",
"Desc": "Sets how the bot should notify you when you get a `server` or `global` level. You can set `dm` (for the bot to send a direct message), `channel` (to get notified in the channel you sent the last message in) or `none` to disable.", "Desc": "Sets how the bot should notify you when you get a `server` or `global` level. You can set `dm` (for the bot to send a direct message), `channel` (to get notified in the channel you sent the last message in) or `none` to disable.",
"Usage": [ "Usage": [
"{0}xpn global dm` `{0}xpn server channel" "{0}xpn global dm",
"{0}xpn server channel"
] ]
}, },
"xprolerewards": { "xprolerewards": {
@ -2833,7 +2835,7 @@
}, },
"clubcreate": { "clubcreate": {
"Cmd": "clubcreate", "Cmd": "clubcreate",
"Desc": "Creates a club. You must be atleast level 5 and not be in the club already.", "Desc": "Creates a club. You must be at least level 5 and not be in the club already.",
"Usage": [ "Usage": [
"{0}clubcreate b1nzy's friends" "{0}clubcreate b1nzy's friends"
] ]
@ -2963,7 +2965,7 @@
"Cmd": "8ball", "Cmd": "8ball",
"Desc": "Ask the 8ball a yes/no question.", "Desc": "Ask the 8ball a yes/no question.",
"Usage": [ "Usage": [
"{0}8ball" "{0}8ball Is b1nzy a nice guy?"
] ]
}, },
"feed": { "feed": {
@ -2986,5 +2988,19 @@
"usage": [ "usage": [
"{0}feeds" "{0}feeds"
] ]
},
"editcustreact": {
"cmd": "editcustreact ecr",
"desc": "Edits the custom reaction's response given it's ID.",
"usage": [
"{0}ecr 123 I'm a magical girl"
]
},
"say": {
"cmd": "say",
"desc": "Bot will send the message you typed in this channel. Supports embeds.",
"usage": [
"{0}say hi"
]
} }
} }