Compare commits

..

234 Commits

Author SHA1 Message Date
ce783c3f75
Merge pull request #4 from mattburchett/revert-3-1.9
Revert "1.9 2017/11/30"
2017-11-30 19:16:55 -06:00
0589728f58
Revert "1.9 2017/11/30" 2017-11-30 19:16:48 -06:00
be9352bc03
Merge pull request #3 from mattburchett/1.9
1.9 2017/11/30
2017-11-30 19:15:58 -06:00
af26fcfa5f Merge pull request #2 from mattburchett/weather2
Weather2
2017-09-21 10:00:47 -07:00
Matt
7a73869a9f Changing commas to slashes 2017-09-21 10:23:10 -05:00
Matt
b1987be30c Fixing again. 2017-09-21 10:17:02 -05:00
Matt
cdd5928028 Adding a line break, maybe 2017-09-21 09:55:15 -05:00
c3a93b17dc Merge pull request #1 from mattburchett/weather2
Weather2
2017-09-20 19:27:57 -07:00
unknown
55c4691933 Fixing 2017-09-20 21:27:14 -05:00
unknown
cf2532af9a Typo 2017-09-20 21:27:03 -05:00
unknown
89a6adb389 Fixing typo. 2017-09-20 21:19:43 -05:00
unknown
b66ba51e0d Fixing? 2017-09-20 21:09:39 -05:00
unknown
f20ccd01f4 Fixing? 2017-09-20 21:06:44 -05:00
unknown
8842a86b30 Adding Weather Changes to include Fehrenheit as well as Celsius? 2017-09-20 20:32:25 -05:00
Master Kwoth
038f17c3a4 Commands which have no command strings should no longer throw an exception 2017-09-17 08:33:16 +02:00
Master Kwoth
bdc6974451 Commands strings are now in data/command_strings.json. Database path no longer has ./ prefix and filename -> Data Source. Fixed permissions migration due to new EF behaviour. Although commands will now error if they don't have their entry in the command strings - needs fixing. 2017-09-17 07:28:48 +02:00
Master Kwoth
0234df0844 Merge pull request #1602 from shivaco/patch-2
Re-phrase, etc.
2017-09-16 21:10:09 +02:00
shivaco
68a92426c2 Re-phrased, added gif for using .permrole, etc. 2017-09-16 21:28:45 +06:00
shivaco
f5eaa4f335 Totally not noob at Markdowning 2017-09-16 21:23:56 +06:00
Master Kwoth
7923c32323 Merge pull request #1601 from shivaco/patch-2
Markdown edits and re-phrase
2017-09-16 10:36:03 +02:00
shivaco
cf5756e0a8 Some edits in Markdown and a bit of re-phrase 2017-09-16 14:12:53 +06:00
Master Kwoth
9f2d9d6710 version upped 2017-09-16 04:35:02 +02:00
Master Kwoth
6bea4b9f02 Upgraded to .net core 2.0 2017-09-16 02:10:22 +02:00
Master Kwoth
a127e43dc0 Version upped 2017-09-15 22:22:03 +02:00
Master Kwoth
9cff3b59c1 clubapps and clubbans now have ok color line 2017-09-15 22:19:31 +02:00
Master Kwoth
4841418cff Added .clubadmin, .autoboobs and .autobutts, cleaned up SongBuffer. 2017-09-15 22:17:31 +02:00
Master Kwoth
51f9ae9e3b Merge pull request #1593 from shivaco/patch-3
Fixed the mistype + added hyperlink
2017-09-15 19:38:19 +02:00
Master Kwoth
eef5ad0c36 Merge pull request #1598 from numbermaniac/1.4
FAQ.md: Grammar/spelling and sentence structure
2017-09-15 19:27:38 +02:00
numbermaniac
c3755055a1 FAQ.md: Grammar/spelling and sentence structure 2017-09-15 19:42:26 +10:00
Master Kwoth
16fd835d4b Caching anime and manga seraches. Club disband error message fixed. 2017-09-15 02:42:51 +02:00
Master Kwoth
25258a0c61 Possible fix for redis on linux. Setgame/SetStream and rotating statuses will now properly work across shards. 2017-09-14 19:37:41 +02:00
Master Kwoth
37412e4e73 Fixed shop role name. Fixed .xpglb (it will now show usernames and discriminators) 2017-09-13 21:15:49 +02:00
shivaco
494d8405b8 Fixed the mistype + added hyperlink 2017-09-13 23:19:07 +06:00
Master Kwoth
0a52676042 possible fix for null migration error 2017-09-13 08:12:07 +02:00
Master Kwoth
48adfc19af Fixed slow .xp and .xpglb 2017-09-13 05:10:26 +02:00
Master Kwoth
067297478e Removed leftover logs 2017-09-13 03:18:33 +02:00
Master Kwoth
a2c4695557 Global custom reactions now use redis pub/sub 2017-09-13 03:12:40 +02:00
Master Kwoth
438f68cde7 global nadeko won't cache nsfw images 2017-09-12 23:49:37 +02:00
Master Kwoth
46f9de01d6 Using redis to cache avatar images, reduced xp image size. 2017-09-12 22:27:51 +02:00
Master Kwoth
90b698f18e Fixed .clubapply help string 2017-09-12 08:14:58 +02:00
Master Kwoth
d51c28b73c .xpglb should be faster now. 2017-09-12 05:00:14 +02:00
Master Kwoth
f08fd3bdb1 1.8.4 2017-09-11 23:39:44 +02:00
Master Kwoth
ea0ca1471f Xp system fixes 2017-09-11 23:39:28 +02:00
Master Kwoth
4c591a69b1 Fixes to .xprr, leveling system 2017-09-11 22:43:32 +02:00
Master Kwoth
d658fe7414 Updated discord.net 2017-09-11 20:25:06 +02:00
Master Kwoth
81a7c6f398 Added .nsfwcc command to prevent memory leaks if nsfw is spammed a lot. 2017-09-11 19:30:02 +02:00
Master Kwoth
cdf15d6c01 Fixed club leaderboard 2017-09-11 19:20:18 +02:00
Master Kwoth
1a85825049 Fixed trivia, closes #1578 2017-09-11 19:12:49 +02:00
Master Kwoth
62c016c7cf 1.8.2 2017-09-11 01:49:51 +02:00
Master Kwoth
6c3025ecf1 Potential xp null error fix 2017-09-11 01:42:39 +02:00
Master Kwoth
927e98514a Fixed exclusion list after restarts, closes #1571 2017-09-11 00:21:14 +02:00
Master Kwoth
3de9a40ffd Fixed catfact thanks to twindragon, closes #1547 2017-09-11 00:01:31 +02:00
Master Kwoth
1af4679d9e When you guess a letter in hangman, updated message will now correctly show previous guesses. closes #1541 2017-09-10 23:48:34 +02:00
Master Kwoth
4adf85a9eb Possible fix for #1523, im not testing that though :D 2017-09-10 23:44:24 +02:00
Master Kwoth
531633b018 Possible trivia weirdness fix, #1522 2017-09-10 23:15:58 +02:00
Master Kwoth
76249c5b29 Made numbers 3 and 7 smaller in slot image because they were overflowing 2017-09-10 23:08:46 +02:00
Master Kwoth
771e0df064 closes #1500, #1433 2017-09-10 23:01:26 +02:00
Master Kwoth
2ab4274c22 Don't lose ignored channels if updating .antiraid #1402 2017-09-10 22:44:23 +02:00
Master Kwoth
6f12ad1478 Docs updates, closes #1570 2017-09-10 22:32:29 +02:00
Master Kwoth
b9f22df756 Fixed .xpex command help, .xpex channel will now default to current channel 2017-09-10 19:14:29 +02:00
Master Kwoth
6b896d8091 Merge branch '1.4' of https://github.com/Kwoth/NadekoBot into 1.4 2017-09-10 17:58:41 +02:00
Master Kwoth
268f9b0448 fixed .xpglb help string. Version upped to 1.8.1 2017-09-10 17:58:32 +02:00
Master Kwoth
5403105062 Merge pull request #1566 from shivaco/patch-2
Some mistypes
2017-09-10 17:25:44 +02:00
Master Kwoth
192667aa35 Merge branch '1.4' of https://github.com/Kwoth/NadekoBot into 1.4 2017-09-10 17:04:42 +02:00
Master Kwoth
af334a0b5c fixed club creation bug 2017-09-10 17:04:32 +02:00
shivaco
14490024ea FIx of some mistypes 2017-09-10 16:20:55 +06:00
Master Kwoth
88833bd5fc Merge pull request #1565 from numbermaniac/1.4
fix spelling of "client" in JSON Explanations.md
2017-09-10 06:30:55 +02:00
numbermaniac
9531fb7717 fix spelling of "client" in JSON Explanations 2017-09-10 14:16:11 +10:00
Master Kwoth
cd2a86c624 Updated commandlist 2017-09-10 04:00:56 +02:00
Master Kwoth
35176465b1 Merge branch '1.4' of https://github.com/Kwoth/NadekoBot into 1.4 2017-09-10 03:54:17 +02:00
Master Kwoth
306ff3a918 Merge branch 'xp-system' into 1.4 2017-09-10 03:53:56 +02:00
Master Kwoth
96d792f63b Xp and clubs finished. Need a lot of testing. Version upped to 1.8-beta 2017-09-10 03:52:34 +02:00
Master Kwoth
f61123ef92 Merge pull request #1545 from Deivedux/1.4
Fixed command prefixes in Permissions System doc
2017-08-30 20:15:17 +02:00
Deivedux
2aca71cd8a Update Permissions System.md 2017-08-30 20:56:44 +03:00
Master Kwoth
20fb253eb3 Removed .rrc because it's prohibited 2017-08-25 22:48:39 +02:00
Master Kwoth
5362821843 Version upped 2017-08-22 05:50:03 +02:00
Master Kwoth
19d710cdd4 Merge branch '1.4' of https://github.com/Kwoth/NadekoBot into 1.4 2017-08-22 05:49:04 +02:00
Master Kwoth
088d95340f Started work on the xp system 2017-08-22 05:48:45 +02:00
Master Kwoth
e5609a0708 .prefix bugfix, #1524 2017-08-22 05:47:57 +02:00
Master Kwoth
a612e50ea3 Merge pull request #1521 from alistairmackenzie/1.4
Fix typo in rategirl command.
2017-08-21 03:22:04 +02:00
Alistair Mackenzie
658597db9f Fix typo in rategirl command. Solves #1517 2017-08-21 02:08:57 +01:00
Master Kwoth
919c81d385 Fixed .wheel example 2017-08-16 22:05:06 +02:00
Master Kwoth
f255ed26dd .sad enable/disable string was swapped 2017-08-16 11:51:41 +02:00
Master Kwoth
03a86b0be9 Antispam can now take an extra parameter at the end which is the time of the mute. It will be ignored if punishment type isn't mute 2017-08-16 01:12:18 +02:00
Master Kwoth
fe3770270e Added .songautodelete/.sad command. 2017-08-15 23:54:54 +02:00
Master Kwoth
e50e71014e Upped version 2017-08-15 22:59:48 +02:00
Master Kwoth
d74a23d215 You can now gift items to waifus with '.gift' command 2017-08-14 07:25:32 +02:00
Master Kwoth
7a1895bf31 possible fix for flowerreaction event on public nadeko 2017-08-14 05:19:37 +02:00
Master Kwoth
70906ed5cb Added betflip and betroll multiplier to .bce, closes #1498 2017-08-13 04:24:20 +02:00
Master Kwoth
a98be21181 small error fix 2017-08-11 22:53:31 +02:00
Master Kwoth
1552d2c892 Fixed extra space in %target%, closes #1483 2017-08-11 14:02:48 +02:00
Master Kwoth
6c5ea68032 .antispam should now update when you use it with new parameters. Use no parameters to disable it if it exists, or run it with default values if it doesn't 2017-08-06 18:01:10 +02:00
Master Kwoth
0bf6459e6a if .tesar is enabled, .iam will remove all other self assignable roles except only one. #1402 2017-08-06 17:43:15 +02:00
Master Kwoth
f02ac7cd78 renamed hitbox to smashcast 2017-08-06 17:34:52 +02:00
Master Kwoth
e2d7ed343c Beam renamed to mixer. Version upped. 2017-08-06 16:07:48 +02:00
Master Kwoth
57dd324f3e You can no longer give your max role to other users with .sr 2017-08-06 15:59:29 +02:00
Master Kwoth
464118f792 having .crca enabled with %target% will replace target with everything that comes after the trigger wherever it is in the triggering message 2017-08-06 14:31:28 +02:00
Master Kwoth
10fdd36e87 fixed sfi and sfw not ignoring server admin when message is edited. #1444 2017-08-06 12:02:13 +02:00
Master Kwoth
1358878773 Fixed index for .qn 2017-08-06 11:49:27 +02:00
Master Kwoth
540209706d Added .qn and fixed .hangman bugs 2017-08-05 12:38:53 +02:00
Master Kwoth
79d3fca7e4 Fixed incorrect usage for .ttt 2017-08-05 10:51:46 +02:00
Master Kwoth
d12d70df1b Fixed connect4 weird wins 2017-08-05 10:46:38 +02:00
Master Kwoth
ce602b5b35 Version upped 2017-08-05 10:13:05 +02:00
Master Kwoth
38125509e5 fixed .weather min/max temperature 2017-08-05 10:12:20 +02:00
Master Kwoth
958eca2935 Nunchi fix, shop fix 2017-08-05 09:52:32 +02:00
Master Kwoth
dea9a935a4 Small nunchi fix, global nadeko improvement 2017-08-04 19:43:25 +02:00
Master Kwoth
47125ed687 connect4 bugfixes 2017-08-04 18:12:26 +02:00
Master Kwoth
ec7f69f1c0 connect4 game added. 2017-08-04 14:36:07 +02:00
Master Kwoth
94e4c89564 Updated commandlist 2017-08-03 20:19:43 +02:00
Master Kwoth
d9a446d874 Nunchi is much more fair and forgiving now. There are 5 seconds delays between rounds, and only one player can fail per round (multiple users can still get booted if they're inactive) 2017-08-03 20:19:09 +02:00
Master Kwoth
f3984c824e Nunchi game added. A bit confusing now. Will be polished further tomorrow. 2017-08-03 00:29:38 +02:00
Master Kwoth
e0be610ec0 .wheel command added (wheel of fortune gambling) 2017-08-02 22:07:19 +02:00
Master Kwoth
82aac891dd animal racing rewritten to be isolated. Please hunt bugs. 2017-08-01 00:11:36 +02:00
Master Kwoth
3097ef88a7 Fixed hangman error 2017-07-31 08:50:04 +02:00
Master Kwoth
f06ee47516 cleanup 2017-07-28 12:38:08 +02:00
Master Kwoth
d5978a0d66 .hangman completely rewritten. Should work almost the same, with some minor improvements (such as showing the category, and you can now guess the whole word at once) 2017-07-28 12:28:08 +02:00
Master Kwoth
53661b3337 Removed old stuff 2017-07-27 18:44:45 +02:00
Master Kwoth
2fe812c4ac Merge branch '1.4' of https://github.com/Kwoth/NadekoBot into 1.4 2017-07-27 18:43:37 +02:00
Master Kwoth
fece28b66b Acrophobia completely rewritten. Works the same as before, only much more maintainable. It won't repost itself after 10 messages anymore though. 2017-07-27 18:43:15 +02:00
Master Kwoth
bf7585cd83 slight cleanup 2017-07-26 18:19:39 +02:00
Master Kwoth
f1e59d561d Update ResponseStrings.ru-RU.json (POEditor.com) 2017-07-26 18:09:29 +02:00
Master Kwoth
97b84ef469 Update ResponseStrings.ro-RO.json (POEditor.com) 2017-07-26 18:09:26 +02:00
Master Kwoth
a0496454bd Update ResponseStrings.pt-BR.json (POEditor.com) 2017-07-26 18:09:24 +02:00
Master Kwoth
ffd570511a Update ResponseStrings.pl-PL.json (POEditor.com) 2017-07-26 18:09:21 +02:00
Master Kwoth
ed623dd967 Update ResponseStrings.nb-NO.json (POEditor.com) 2017-07-26 18:09:19 +02:00
Master Kwoth
e10aee9c69 Update ResponseStrings.ko-KR.json (POEditor.com) 2017-07-26 18:09:16 +02:00
Master Kwoth
6294dc8679 Update ResponseStrings.ja-JP.json (POEditor.com) 2017-07-26 18:09:13 +02:00
Master Kwoth
89b810df54 Update ResponseStrings.it-IT.json (POEditor.com) 2017-07-26 18:09:11 +02:00
Master Kwoth
2d1b5dda96 Update ResponseStrings.id-ID.json (POEditor.com) 2017-07-26 18:09:08 +02:00
Master Kwoth
2a137004a5 Update ResponseStrings.he-IL.json (POEditor.com) 2017-07-26 18:09:05 +02:00
Master Kwoth
92bf9b88b4 Update ResponseStrings.de-DE.json (POEditor.com) 2017-07-26 18:09:03 +02:00
Master Kwoth
44b3223c1b Update ResponseStrings.fr-FR.json (POEditor.com) 2017-07-26 18:09:00 +02:00
Master Kwoth
81f0032262 Update ResponseStrings.nl-NL.json (POEditor.com) 2017-07-26 18:08:57 +02:00
Master Kwoth
d86c8ed41b Update ResponseStrings.da-DK.json (POEditor.com) 2017-07-26 18:08:55 +02:00
Master Kwoth
afda3e2046 Update ResponseStrings.cs-CZ.json (POEditor.com) 2017-07-26 18:08:52 +02:00
Master Kwoth
8e7935f893 Update ResponseStrings.zh-TW.json (POEditor.com) 2017-07-26 18:08:49 +02:00
Master Kwoth
5295704447 Update ResponseStrings.zh-CN.json (POEditor.com) 2017-07-26 18:08:47 +02:00
Master Kwoth
c738cb569e Update ResponseStrings.ar.json (POEditor.com) 2017-07-26 18:08:44 +02:00
Master Kwoth
263a95a6ad cleanup 2017-07-25 18:31:30 +02:00
Master Kwoth
e9cf57d46f .crdm was deleted by accident, it's back now 2017-07-23 09:52:45 +02:00
Master Kwoth
f773b0c6b6 .crca added. If you enable it on a custom reation, you can use the trigger word anywhere in the sentence in order to trigger that custom reaction. 2017-07-22 18:12:08 +02:00
Master Kwoth
1aa86937c8 small changes 2017-07-22 07:57:17 +02:00
Master Kwoth
f1b348406d Bugfixes 2017-07-21 07:10:17 +02:00
Master Kwoth
b9bb72f06d Streamrole is smarter, but possibly more expensive. It will rescan users when settings are changed. And when the bot is started. 2017-07-21 06:56:21 +02:00
Master Kwoth
d074444c26 commandlist updated 2017-07-21 03:05:13 +02:00
Master Kwoth
0d216ad78a .nsfwtbl added. You can now blacklist tags which are used in nsfw commands. 2017-07-21 03:04:44 +02:00
Master Kwoth
0131b7713e Make sure to assign new bot creds variable 2017-07-20 23:48:25 +02:00
Master Kwoth
613655eb95 You can now add CleverBotApiKey from cleverbot.com/api in order to use official cleverbot, instead of stupid program-o 2017-07-20 22:58:19 +02:00
Master Kwoth
cedaf73785 Sped up .streamrole initialization 5x, but it might error out if there are too many users streaming when the command is ran. 2017-07-20 20:03:11 +02:00
Master Kwoth
9163510eee .bce command added, you can now edit BotConfig without editing the database and restarting the bot. Cleanup 2017-07-20 05:10:39 +02:00
Master Kwoth
fe88611183 Fixed .shop pagination 2017-07-19 11:02:14 +02:00
Master Kwoth
4130317f40 .srkw, .srwl and .srbl commands added. 2017-07-19 10:38:14 +02:00
Master Kwoth
3f7f6cecbe Merge branch '1.4' of https://github.com/Kwoth/NadekoBot into 1.4 2017-07-19 09:31:10 +02:00
Master Kwoth
50236d71d5 Fixed multi-shard bots 2017-07-19 09:31:00 +02:00
Master Kwoth
8612dc852e Merge pull request #1423 from Deivedux/1.4
Updated windows guides
2017-07-18 21:07:39 +02:00
Deivedux
8dd24443c0 Update Windows Guide.md
Added missing installation part for music features.
2017-07-18 21:30:27 +03:00
Deivedux
86743250cf Update Upgrading Guide.md
Windows part of the upgrading guide is now more straightforward.
2017-07-18 21:29:08 +03:00
Master Kwoth
661d026973 Updated imagesharp 2017-07-18 18:26:55 +02:00
Master Kwoth
55b1c3945b Updated commandlist. Goodbye clash of clans 👋 closes #1420 2017-07-18 04:25:30 +02:00
Master Kwoth
c054543d98 Huge refactor is over 2017-07-17 21:42:36 +02:00
Master Kwoth
618968d2e4 More refactoring 2017-07-17 04:37:51 +02:00
Master Kwoth
4e11a6c8bc More refactoring 2017-07-15 18:34:34 +02:00
Master Kwoth
b3243eb0e9 More cleanup 2017-07-15 15:08:34 +02:00
Master Kwoth
028606b080 More cleanup 2017-07-15 05:54:36 +02:00
Master Kwoth
ac5e4e7540 Version upped 2017-07-15 05:33:23 +02:00
Master Kwoth
30bafa8a89 More cleanup 2017-07-15 05:23:46 +02:00
Master Kwoth
4eca5be1d4 Huge cleanup,
rewrite of the NadekoBot.cs, way services are loaded has changed. Updated discord.net.
2017-07-15 05:04:16 +02:00
Master Kwoth
f239c46e20 Words should get filtered in edited messages too. 2017-07-14 18:39:21 +02:00
Master Kwoth
1c72d2864a Merge pull request #1397 from samdivaio/1.5-music-changes
Stop no longer resets current song index 0, formatting changes. Use `.srm all` to get pre-update `.stop` behavior (clears the queue and stops the player)
2017-07-14 17:52:44 +02:00
Master Kwoth
45ee3042bb Merge branch '1.4' of https://github.com/Kwoth/NadekoBot into 1.4 2017-07-14 17:49:55 +02:00
Master Kwoth
17719dd8e2 finished .streamrole 2017-07-14 17:09:06 +02:00
samvaio
11b533c3b7 Done as per Kwoth. 2017-07-14 09:45:31 +05:30
Master Kwoth
b8573f11b5 Added .streamrole, needs testing. 2017-07-14 05:00:30 +02:00
samvaio
f26a7de704 Revert "Stop works as it used to before. Auto rpl disabled."
This reverts commit fd410bc856.
2017-07-14 00:54:23 +05:30
Master Kwoth
6124c3dce8 Merge pull request #1403 from hakufu/1.4
Add deny perm for addReactions on mute
2017-07-13 20:36:55 +02:00
hakufu
390a637c08 Add deny perm for addReactions on mute
Added the permission for the channel override when muting to also include the denial of "addReactions."
2017-07-13 14:08:51 -04:00
samvaio
202c5e98a5 Makeover to highlight the information.
Look is similar to early version of Nadeko.
2017-07-13 17:45:46 +05:30
samvaio
fd410bc856 Stop works as it used to before. Auto rpl disabled.
Bot no longer repeats playlist on default.

Bot now clears the queued songs list (playlist)
- if `.stop` command is used.
- if the last song of the queue is playing and `.next` command is used.
- if the the last song of the queue finished playing.
2017-07-13 17:36:49 +05:30
samvaio
c328ec68d3 Documents updated
macOS prerequisite info added
2017-07-13 17:34:28 +05:30
samvaio
4dbdce7f5d Merge pull request #15 from Kwoth/1.4
ups
2017-07-13 17:14:29 +05:30
Master Kwoth
67f0cfb717 Version upped 2017-07-13 04:09:38 +02:00
Master Kwoth
ed40bc99b2 .movesong works more intuitively now, and current song's index is now updated after songs are moved 2017-07-13 04:09:21 +02:00
Master Kwoth
b85cc023f2 format 2017-07-12 15:38:34 +02:00
Master Kwoth
467b482ff9 Added some stuff to stats sending 2017-07-12 04:13:50 +02:00
Master Kwoth
c0012e296e Some stats stuff for science 2017-07-12 03:39:44 +02:00
Master Kwoth
8a75c28d73 Small doc fixes 2017-07-12 02:02:17 +02:00
Master Kwoth
4b9977e5d6 Upped version 2017-07-11 20:22:24 +02:00
Master Kwoth
c1cf85b338 Fixed error when logging something related to a user who has no avatar, closes #1381 2017-07-11 20:22:06 +02:00
Master Kwoth
5e230fad22 using .n when rpl is disabled will stop the queue 2017-07-11 20:11:36 +02:00
Master Kwoth
0e4728d9c9 Fixed .play when queue is stopped. .play X will now also unstop the player 2017-07-11 19:52:10 +02:00
Master Kwoth
8f90410e2d Small refactor 2017-07-11 03:16:56 +02:00
Master Kwoth
ec94459722 Fixed soundcloud song length, closes #1380 2017-07-11 01:23:37 +02:00
Master Kwoth
ab3ad4f2fb Upped version 2017-07-10 21:56:53 +02:00
Master Kwoth
dc0176365b Fixed .convert, closes #1377 2017-07-10 21:35:45 +02:00
Master Kwoth
34b56c6353 Fixed .srm, closes #1373 2017-07-10 21:31:47 +02:00
Master Kwoth
9a744172a9 Fixed a bug where spamming .n would crash the music player, closes #1372 2017-07-10 21:21:45 +02:00
Master Kwoth
70f0f6af44 Fixed some links queueing random songs. closes #1368 2017-07-10 21:08:11 +02:00
Master Kwoth
3119a47007 Upped version 2017-07-10 19:40:55 +02:00
Master Kwoth
5db254e8f3 Fixed .lolban, closes #1340 2017-07-10 19:40:34 +02:00
Master Kwoth
f396fc78db Fixed shard number bold in unresponsive shard 2017-07-09 19:26:17 +02:00
Master Kwoth
9d778de7f2 fixed .ropl with %queued% and %playing% 2017-07-09 12:43:14 +02:00
Master Kwoth
3966629263 Upped version 2017-07-09 01:40:54 +02:00
Master Kwoth
f1a4a88730 Fixed song time on songs shorter than 1 minute 2017-07-09 01:39:47 +02:00
Master Kwoth
fad0b908c8 fixed .autoplay 2017-07-09 01:37:17 +02:00
Master Kwoth
9eab7d949f Possibly fix youtube-dl certificate error 2017-07-09 00:56:12 +02:00
Master Kwoth
f58e7ed7ac Fixed .warnlogall, updated commandlist 2017-07-08 15:27:48 +02:00
Master Kwoth
27f925fa63 Fixed userpresence and game changes readded to userpresence 2017-07-08 14:54:19 +02:00
Master Kwoth
aa01314b3a Embed field names and values will be trimmed to their acceptable length to prevent errors. closes #1355 2017-07-08 14:20:06 +02:00
Master Kwoth
72e7b04319 Fixed 100% cpu usage on single threaded systems. Totally my bad. 2017-07-08 13:42:16 +02:00
Master Kwoth
568cdfbd3c Fixed .save 2017-07-08 13:27:53 +02:00
Master Kwoth
4132565948 Fixed footer icon urls 2017-07-08 00:05:11 +02:00
Master Kwoth
96ae60378b 1.54b 2017-07-07 23:23:10 +02:00
Master Kwoth
4de7e38277 fixed trivia, and some other things 2017-07-07 23:22:34 +02:00
Master Kwoth
ab99801a37 version upped 2017-07-07 16:07:57 +02:00
Master Kwoth
994457f9af Merge branch '1.4' of https://github.com/Kwoth/NadekoBot into 1.4 2017-07-07 15:52:38 +02:00
Master Kwoth
9e9f21d525 Update ResponseStrings.ro-RO.json (POEditor.com) 2017-07-07 15:48:42 +02:00
Master Kwoth
f3f934e05f Update ResponseStrings.pt-BR.json (POEditor.com) 2017-07-07 15:48:40 +02:00
Master Kwoth
bf860f9aa8 Update ResponseStrings.pl-PL.json (POEditor.com) 2017-07-07 15:48:37 +02:00
Master Kwoth
a49002a808 Update ResponseStrings.nb-NO.json (POEditor.com) 2017-07-07 15:48:35 +02:00
Master Kwoth
88e42e672b Update ResponseStrings.ko-KR.json (POEditor.com) 2017-07-07 15:48:32 +02:00
Master Kwoth
fcbf3a0918 Update ResponseStrings.ja-JP.json (POEditor.com) 2017-07-07 15:48:29 +02:00
Master Kwoth
cb04e987c3 Update ResponseStrings.it-IT.json (POEditor.com) 2017-07-07 15:48:27 +02:00
Master Kwoth
7f4970a5da Update ResponseStrings.id-ID.json (POEditor.com) 2017-07-07 15:48:24 +02:00
Master Kwoth
19246b9bf2 Update ResponseStrings.he-IL.json (POEditor.com) 2017-07-07 15:48:20 +02:00
Master Kwoth
b73e0d18e5 Update ResponseStrings.de-DE.json (POEditor.com) 2017-07-07 15:48:17 +02:00
Master Kwoth
d0c580f39a Update ResponseStrings.fr-FR.json (POEditor.com) 2017-07-07 15:48:14 +02:00
Master Kwoth
93b48ff3b0 Update ResponseStrings.nl-NL.json (POEditor.com) 2017-07-07 15:48:12 +02:00
Master Kwoth
b04e7cbd55 Update ResponseStrings.da-DK.json (POEditor.com) 2017-07-07 15:48:09 +02:00
Master Kwoth
fe175ecd43 Update ResponseStrings.cs-CZ.json (POEditor.com) 2017-07-07 15:48:06 +02:00
Master Kwoth
c7936335bf Update ResponseStrings.zh-TW.json (POEditor.com) 2017-07-07 15:48:04 +02:00
Master Kwoth
264e38c7a0 Update ResponseStrings.zh-CN.json (POEditor.com) 2017-07-07 15:48:01 +02:00
Master Kwoth
d782ceb9fa Update ResponseStrings.ar.json (POEditor.com) 2017-07-07 15:47:58 +02:00
Master Kwoth
e15045292f Fixed embeds 2017-07-07 15:45:21 +02:00
Master Kwoth
74ad7b32bd done testing 2017-07-07 13:40:17 +02:00
380 changed files with 26334 additions and 6375 deletions

View File

@ -3,7 +3,6 @@ You can support the project on patreon: <https://patreon.com/nadekobot> or paypa
##Table of contents ##Table of contents
- [Help](#help) - [Help](#help)
- [Administration](#administration) - [Administration](#administration)
- [ClashOfClans](#clashofclans)
- [CustomReactions](#customreactions) - [CustomReactions](#customreactions)
- [Gambling](#gambling) - [Gambling](#gambling)
- [Games](#games) - [Games](#games)
@ -13,6 +12,7 @@ You can support the project on patreon: <https://patreon.com/nadekobot> or paypa
- [Pokemon](#pokemon) - [Pokemon](#pokemon)
- [Searches](#searches) - [Searches](#searches)
- [Utility](#utility) - [Utility](#utility)
- [Xp](#xp)
### Administration ### Administration
@ -90,7 +90,6 @@ Commands and aliases | Description | Usage
`.setgame` | Sets the bots game. **Bot owner only** | `.setgame with snakes` `.setgame` | Sets the bots game. **Bot owner only** | `.setgame with snakes`
`.setstream` | Sets the bots stream. First argument is the twitch link, second argument is stream name. **Bot owner only** | `.setstream TWITCHLINK Hello` `.setstream` | Sets the bots stream. First argument is the twitch link, second argument is stream name. **Bot owner only** | `.setstream TWITCHLINK Hello`
`.send` | Sends a message to someone on a different server through the bot. Separate server and channel/user ids with `|` and prefix the channel id with `c:` and the user id with `u:`. **Bot owner only** | `.send serverid|c:channelid message` or `.send serverid|u:userid message` `.send` | Sends a message to someone on a different server through the bot. Separate server and channel/user ids with `|` and prefix the channel id with `c:` and the user id with `u:`. **Bot owner only** | `.send serverid|c:channelid message` or `.send serverid|u:userid message`
`.announce` | Sends a message to all servers' default channel that bot is connected to. **Bot owner only** | `.announce Useless spam`
`.reloadimages` | Reloads images bot is using. Safe to use even when bot is being used heavily. **Bot owner only** | `.reloadimages` `.reloadimages` | Reloads images bot is using. Safe to use even when bot is being used heavily. **Bot owner only** | `.reloadimages`
`.greetdel` `.grdel` | Sets the time it takes (in seconds) for greet messages to be auto-deleted. Set it to 0 to disable automatic deletion. **Requires ManageServer server permission.** | `.greetdel 0` or `.greetdel 30` `.greetdel` `.grdel` | Sets the time it takes (in seconds) for greet messages to be auto-deleted. Set it to 0 to disable automatic deletion. **Requires ManageServer server permission.** | `.greetdel 0` or `.greetdel 30`
`.greet` | Toggles anouncements on the current channel when someone joins the server. **Requires ManageServer server permission.** | `.greet` `.greet` | Toggles anouncements on the current channel when someone joins the server. **Requires ManageServer server permission.** | `.greet`
@ -119,21 +118,6 @@ Commands and aliases | Description | Usage
###### [Back to ToC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
### ClashOfClans
Commands and aliases | Description | Usage
----------------|--------------|-------
`.createwar` `.cw` | Creates a new war by specifying a size (>10 and multiple of 5) and enemy clan name. **Requires ManageMessages server permission.** | `.cw 15 The Enemy Clan`
`.startwar` `.sw` | Starts a war with a given number. | `.sw 15`
`.listwar` `.lw` | Shows the active war claims by a number. Shows all wars in a short way if no number is specified. | `.lw [war_number]` or `.lw`
`.basecall` | Claims a certain base from a certain war. You can supply a name in the third optional argument to claim in someone else's place. | `.basecall [war_number] [base_number] [optional_other_name]`
`.callfinish1` `.cf1` | Finish your claim with 1 star if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. | `.cf1 1` or `.cf1 1 5`
`.callfinish2` `.cf2` | Finish your claim with 2 stars if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. | `.cf2 1` or `.cf2 1 5`
`.callfinish` `.cf` | Finish your claim with 3 stars if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. | `.cf 1` or `.cf 1 5`
`.endwar` `.ew` | Ends the war with a given index. | `.ew [war_number]`
`.uncall` | Removes your claim from a certain war. Optional second argument denotes a person in whose place to unclaim | `.uc [war_number] [optional_other_name]`
###### [Back to ToC](#table-of-contents)
### CustomReactions ### CustomReactions
Commands and aliases | Description | Usage Commands and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
@ -142,6 +126,7 @@ Commands and aliases | Description | Usage
`.listcustreactg` `.lcrg` | Lists global or server custom reactions (20 commands per page) grouped by trigger, and show a number of responses for each. Running the command in DM will list global custom reactions, while running it in server will list that server's custom reactions. | `.lcrg 1` `.listcustreactg` `.lcrg` | Lists global or server custom reactions (20 commands per page) grouped by trigger, and show a number of responses for each. Running the command in DM will list global custom reactions, while running it in server will list that server's custom reactions. | `.lcrg 1`
`.showcustreact` `.scr` | Shows a custom reaction's response on a given ID. | `.scr 1` `.showcustreact` `.scr` | Shows a custom reaction's response on a given ID. | `.scr 1`
`.delcustreact` `.dcr` | Deletes a custom reaction on a specific index. If ran in DM, it is bot owner only and deletes a global custom reaction. If ran in a server, it requires Administration privileges and removes server custom reaction. | `.dcr 5` `.delcustreact` `.dcr` | Deletes a custom reaction on a specific index. If ran in DM, it is bot owner only and deletes a global custom reaction. If ran in a server, it requires Administration privileges and removes server custom reaction. | `.dcr 5`
`.crca` | Toggles whether the custom reaction will trigger if the triggering message contains the keyword (instead of only starting with it). | `.crca 44`
`.crdm` | Toggles whether the response message of the custom reaction will be sent as a direct message. | `.crdm 44` `.crdm` | Toggles whether the response message of the custom reaction will be sent as a direct message. | `.crdm 44`
`.crad` | Toggles whether the message triggering the custom reaction will be automatically deleted. | `.crad 59` `.crad` | Toggles whether the message triggering the custom reaction will be automatically deleted. | `.crad 59`
`.crstatsclear` | Resets the counters on `.crstats`. You can specify a trigger to clear stats only for that trigger. **Bot owner only** | `.crstatsclear` or `.crstatsclear rng` `.crstatsclear` | Resets the counters on `.crstats`. You can specify a trigger to clear stats only for that trigger. **Bot owner only** | `.crstatsclear` or `.crstatsclear rng`
@ -183,23 +168,27 @@ Commands and aliases | Description | Usage
`.affinity` | Sets your affinity towards someone you want to be claimed by. Setting affinity will reduce their `.claim` on you by 20%. You can leave second argument empty to clear your affinity. 30 minutes cooldown. | `.affinity @MyHusband` or `.affinity` `.affinity` | Sets your affinity towards someone you want to be claimed by. Setting affinity will reduce their `.claim` on you by 20%. You can leave second argument empty to clear your affinity. 30 minutes cooldown. | `.affinity @MyHusband` or `.affinity`
`.waifus` `.waifulb` | Shows top 9 waifus. You can specify another page to show other waifus. | `.waifus` or `.waifulb 3` `.waifus` `.waifulb` | Shows top 9 waifus. You can specify another page to show other waifus. | `.waifus` or `.waifulb 3`
`.waifuinfo` `.waifustats` | Shows waifu stats for a target person. Defaults to you if no user is provided. | `.waifuinfo @MyCrush` or `.waifuinfo` `.waifuinfo` `.waifustats` | Shows waifu stats for a target person. Defaults to you if no user is provided. | `.waifuinfo @MyCrush` or `.waifuinfo`
`.waifugift` `.gift` `.gifts` | Gift an item to someone. This will increase their waifu value by 50% of the gifted item's value if they don't have affinity set towards you, or 100% if they do. Provide no arguments to see a list of items that you can gift. | `.gifts` or `.gift Rose @Himesama`
`.wheeloffortune` `.wheel` | Bets a certain amount of currency on the wheel of fortune. Wheel can stop on one of many different multipliers. Won amount is rounded down to the nearest whole number. | `.wheel 10`
###### [Back to ToC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
### Games ### Games
Commands and aliases | Description | Usage Commands and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`.leet` | Converts a text to leetspeak with 6 (1-6) severity levels | `.leet 3 Hello`
`.choose` | Chooses a thing from a list of things | `.choose Get up;Sleep;Sleep more` `.choose` | Chooses a thing from a list of things | `.choose Get up;Sleep;Sleep more`
`.8ball` | Ask the 8ball a yes/no question. | `.8ball should I do something` `.8ball` | Ask the 8ball a yes/no question. | `.8ball should I do something`
`.rps` | Play a game of Rocket-Paperclip-Scissors with Nadeko. | `.rps scissors` `.rps` | Play a game of Rocket-Paperclip-Scissors with Nadeko. | `.rps scissors`
`.rategirl` | Use the universal hot-crazy wife zone matrix to determine the girl's worth. It is everything young men need to know about women. At any moment in time, any woman you have previously located on this chart can vanish from that location and appear anywhere else on the chart. | `.rategirl @SomeGurl` `.rategirl` | Use the universal hot-crazy wife zone matrix to determine the girl's worth. It is everything young men need to know about women. At any moment in time, any woman you have previously located on this chart can vanish from that location and appear anywhere else on the chart. | `.rategirl @SomeGurl`
`.linux` | Prints a customizable Linux interjection | `.linux Spyware Windows` `.linux` | Prints a customizable Linux interjection | `.linux Spyware Windows`
`.leet` | Converts a text to leetspeak with 6 (1-6) severity levels | `.leet 3 Hello`
`.acrophobia` `.acro` | Starts an Acrophobia game. Second argument is optional round length in seconds. (default is 60) | `.acro` or `.acro 30` `.acrophobia` `.acro` | Starts an Acrophobia game. Second argument is optional round length in seconds. (default is 60) | `.acro` or `.acro 30`
`.cleverbot` | Toggles cleverbot session. When enabled, the bot will reply to messages starting with bot mention in the server. Custom reactions starting with %mention% won't work if cleverbot is enabled. **Requires ManageMessages server permission.** | `.cleverbot` `.cleverbot` | Toggles cleverbot session. When enabled, the bot will reply to messages starting with bot mention in the server. Custom reactions starting with %mention% won't work if cleverbot is enabled. **Requires ManageMessages server permission.** | `.cleverbot`
`.connect4` `.con4` | Creates or joins an existing connect4 game. 2 players are required for the game. Objective of the game is to get 4 of your pieces next to each other in a vertical, horizontal or diagonal line. | `.connect4`
`.hangmanlist` | Shows a list of hangman term types. | `.hangmanlist` `.hangmanlist` | Shows a list of hangman term types. | `.hangmanlist`
`.hangman` | Starts a game of hangman in the channel. Use `.hangmanlist` to see a list of available term types. Defaults to 'all'. | `.hangman` or `.hangman movies` `.hangman` | Starts a game of hangman in the channel. Use `.hangmanlist` to see a list of available term types. Defaults to 'all'. | `.hangman` or `.hangman movies`
`.hangmanstop` | Stops the active hangman game on this channel if it exists. | `.hangmanstop` `.hangmanstop` | Stops the active hangman game on this channel if it exists. | `.hangmanstop`
`.nunchi` | Creates or joins an existing nunchi game. Users have to count up by 1 from the starting number shown by the bot. If someone makes a mistake (types an incorrent number, or repeats the same number) they are out of the game and a new round starts without them. Minimum 3 users required. | `.nunchi`
`.pick` | Picks the currency planted in this channel. 60 seconds cooldown. | `.pick` `.pick` | Picks the currency planted in this channel. 60 seconds cooldown. | `.pick`
`.plant` | Spend an amount of currency to plant it in this channel. Default is 1. (If bot is restarted or crashes, the currency will be lost) | `.plant` or `.plant 5` `.plant` | Spend an amount of currency to plant it in this channel. Default is 1. (If bot is restarted or crashes, the currency will be lost) | `.plant` or `.plant 5`
`.gencurrency` `.gc` | Toggles currency generation on this channel. Every posted message will have chance to spawn currency. Chance is specified by the Bot Owner. (default is 2%) **Requires ManageMessages server permission.** | `.gc` `.gencurrency` `.gc` | Toggles currency generation on this channel. Every posted message will have chance to spawn currency. Chance is specified by the Bot Owner. (default is 2%) **Requires ManageMessages server permission.** | `.gc`
@ -211,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`
@ -235,20 +224,22 @@ Commands and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`.play` `.start` | If no arguments are specified, acts as `.next 1` command. If you specify a song number, it will jump to that song. If you specify a search query, acts as a `.q` command | `.play` or `.play 5` or `.play Dream Of Venice` `.play` `.start` | If no arguments are specified, acts as `.next 1` command. If you specify a song number, it will jump to that song. If you specify a search query, acts as a `.q` command | `.play` or `.play 5` or `.play Dream Of Venice`
`.queue` `.q` `.yq` | Queue a song using keywords or a link. Bot will join your voice channel. **You must be in a voice channel**. | `.q Dream Of Venice` `.queue` `.q` `.yq` | Queue a song using keywords or a link. Bot will join your voice channel. **You must be in a voice channel**. | `.q Dream Of Venice`
`.queuenext` `.qn` | Works the same as `.queue` command, except it enqueues the new song after the current one. **You must be in a voice channel**. | `.qn Dream Of Venice`
`.queuesearch` `.qs` `.yqs` | Search for top 5 youtube song result using keywords, and type the index of the song to play that song. Bot will join your voice channel. **You must be in a voice channel**. | `.qs Dream Of Venice` `.queuesearch` `.qs` `.yqs` | Search for top 5 youtube song result using keywords, and type the index of the song to play that song. Bot will join your voice channel. **You must be in a voice channel**. | `.qs Dream Of Venice`
`.listqueue` `.lq` | Lists 15 currently queued songs per page. Default page is 1. | `.lq` or `.lq 2` `.listqueue` `.lq` | Lists 10 currently queued songs per page. Default page is 1. | `.lq` or `.lq 2`
`.next` `.n` | Goes to the next song in the queue. You have to be in the same voice channel as the bot. You can skip multiple songs, but in that case songs will not be requeued if .rcs or .rpl is enabled. | `.n` or `.n 5` `.next` `.n` | Goes to the next song in the queue. You have to be in the same voice channel as the bot. You can skip multiple songs, but in that case songs will not be requeued if .rcs or .rpl is enabled. | `.n` or `.n 5`
`.stop` `.s` | Stops the music and clears the playlist. Stays in the channel. | `.s` `.stop` `.s` | Stops the music and preserves the current song index. Stays in the channel. | `.s`
`.destroy` `.d` | Completely stops the music and unbinds the bot from the channel. (may cause weird behaviour) | `.d` `.destroy` `.d` | Completely stops the music and unbinds the bot from the channel. (may cause weird behaviour) | `.d`
`.pause` `.p` | Pauses or Unpauses the song. | `.p` `.pause` `.p` | Pauses or Unpauses the song. | `.p`
`.volume` `.vol` | Sets the music playback volume (0-100%) | `.vol 50` `.volume` `.vol` | Sets the music playback volume (0-100%) | `.vol 50`
`.defvol` `.dv` | Sets the default music volume when music playback is started (0-100). Persists through restarts. | `.dv 80` `.defvol` `.dv` | Sets the default music volume when music playback is started (0-100). Persists through restarts. | `.dv 80`
`.songremove` `.srm` | Remove a song by its # in the queue, or 'all' to remove all songs from the queue. | `.srm 5` `.songremove` `.srm` | Remove a song by its # in the queue, or 'all' to remove all songs from the queue and reset the song index. | `.srm 5`
`.playlists` `.pls` | Lists all playlists. Paginated, 20 per page. Default page is 0. | `.pls 1` `.playlists` `.pls` | Lists all playlists. Paginated, 20 per page. Default page is 0. | `.pls 1`
`.deleteplaylist` `.delpls` | Deletes a saved playlist. Works only if you made it or if you are the bot owner. | `.delpls animu-5` `.deleteplaylist` `.delpls` | Deletes a saved playlist. Works only if you made it or if you are the bot owner. | `.delpls animu-5`
`.save` | Saves a playlist under a certain name. Playlist name must be no longer than 20 characters and must not contain dashes. | `.save classical1` `.save` | Saves a playlist under a certain name. Playlist name must be no longer than 20 characters and must not contain dashes. | `.save classical1`
`.load` | Loads a saved playlist using its ID. Use `.pls` to list all saved playlists and `.save` to save new ones. | `.load 5` `.load` | Loads a saved playlist using its ID. Use `.pls` to list all saved playlists and `.save` to save new ones. | `.load 5`
`.fairplay` `.fp` | Toggles fairplay. While enabled, the bot will prioritize songs from users who didn't have their song recently played instead of the song's position in the queue. | `.fp` `.fairplay` `.fp` | Toggles fairplay. While enabled, the bot will prioritize songs from users who didn't have their song recently played instead of the song's position in the queue. | `.fp`
`.songautodelete` `.sad` | Toggles whether the song should be automatically removed from the music queue when it finishes playing. | `.sad`
`.soundcloudqueue` `.sq` | Queue a soundcloud song using keywords. Bot will join your voice channel. **You must be in a voice channel**. | `.sq Dream Of Venice` `.soundcloudqueue` `.sq` | Queue a soundcloud song using keywords. Bot will join your voice channel. **You must be in a voice channel**. | `.sq Dream Of Venice`
`.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`
@ -282,6 +273,8 @@ Commands and aliases | Description | Usage
`.gelbooru` | Shows a random hentai image from gelbooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `.gelbooru yuri+kissing` `.gelbooru` | Shows a random hentai image from gelbooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `.gelbooru yuri+kissing`
`.boobs` | Real adult content. | `.boobs` `.boobs` | Real adult content. | `.boobs`
`.butts` `.ass` `.butt` | Real adult content. | `.butts` or `.ass` `.butts` `.ass` `.butt` | Real adult content. | `.butts` or `.ass`
`.nsfwtagbl` `.nsfwtbl` | Toggles whether the tag is blacklisted or not in nsfw searches. Provide no parameters to see the list of blacklisted tags. | `.nsfwtbl poop`
`.nsfwcc` | Clears nsfw cache. **Bot owner only** | `.nsfwcc`
###### [Back to ToC](#table-of-contents) ###### [Back to ToC](#table-of-contents)
@ -383,11 +376,11 @@ Commands and aliases | Description | Usage
`.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`
`.pokemonability` `.pokeab` | Searches for a pokemon ability. | `.pokeab overgrow` `.pokemonability` `.pokeab` | Searches for a pokemon ability. | `.pokeab overgrow`
`.hitbox` `.hb` | Notifies this channel when a certain user starts streaming. **Requires ManageMessages server permission.** | `.hitbox SomeStreamer` `.smashcast` `.hb` | Notifies this channel when a certain user starts streaming. **Requires ManageMessages server permission.** | `.smashcast SomeStreamer`
`.twitch` `.tw` | Notifies this channel when a certain user starts streaming. **Requires ManageMessages server permission.** | `.twitch SomeStreamer` `.twitch` `.tw` | Notifies this channel when a certain user starts streaming. **Requires ManageMessages server permission.** | `.twitch SomeStreamer`
`.beam` `.bm` | Notifies this channel when a certain user starts streaming. **Requires ManageMessages server permission.** | `.beam SomeStreamer` `.mixer` `.bm` | Notifies this channel when a certain user starts streaming. **Requires ManageMessages server permission.** | `.mixer SomeStreamer`
`.liststreams` `.ls` | Lists all streams you are following on this server. | `.ls` `.liststreams` `.ls` | Lists all streams you are following on this server. | `.ls`
`.removestream` `.rms` | Removes notifications of a certain streamer from a certain platform on this channel. **Requires ManageMessages server permission.** | `.rms Twitch SomeGuy` or `.rms Beam SomeOtherGuy` `.removestream` `.rms` | Removes notifications of a certain streamer from a certain platform on this channel. **Requires ManageMessages server permission.** | `.rms Twitch SomeGuy` or `.rms mixer SomeOtherGuy`
`.checkstream` `.cs` | Checks if a user is online on a certain streaming platform. | `.cs twitch MyFavStreamer` `.checkstream` `.cs` | Checks if a user is online on a certain streaming platform. | `.cs twitch MyFavStreamer`
`.translate` `.trans` | Translates from>to text. From the given language to the destination language. | `.trans en>fr Hello` `.translate` `.trans` | Translates from>to text. From the given language to the destination language. | `.trans en>fr Hello`
`.autotrans` `.at` | Starts automatic translation of all messages by users who set their `.atl` in this channel. You can set "del" argument to automatically delete all translated user messages. **Requires Administrator server permission.** **Bot owner only** | `.at` or `.at del` `.autotrans` `.at` | Starts automatic translation of all messages by users who set their `.atl` in this channel. You can set "del" argument to automatically delete all translated user messages. **Requires Administrator server permission.** **Bot owner only** | `.at` or `.at del`
@ -400,7 +393,6 @@ Commands and aliases | Description | Usage
### Utility ### Utility
Commands and aliases | Description | Usage Commands and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`.rotaterolecolor` `.rrc` | Rotates a roles color on an interval with a list of supplied colors. First argument is interval in seconds (Minimum 60). Second argument is a role, followed by a space-separated list of colors in hex. Provide a rolename with a 0 interval to disable. **Requires ManageRoles server permission.** **Bot owner only** | `.rrc 60 MyLsdRole #ff0000 #00ff00 #0000ff` or `.rrc 0 MyLsdRole`
`.togethertube` `.totube` | Creates a new room on <https://togethertube.com> and shows the link in the chat. | `.totube` `.togethertube` `.totube` | Creates a new room on <https://togethertube.com> and shows the link in the chat. | `.totube`
`.whosplaying` `.whpl` | Shows a list of users who are playing the specified game. | `.whpl Overwatch` `.whosplaying` `.whpl` | Shows a list of users who are playing the specified game. | `.whpl Overwatch`
`.inrole` | Lists every person from the specified role on this server. You can use role ID, role name. | `.inrole Some Role` `.inrole` | Lists every person from the specified role on this server. You can use role ID, role name. | `.inrole Some Role`
@ -417,11 +409,12 @@ Commands and aliases | Description | Usage
`.listservers` | Lists servers the bot is on with some basic info. 15 per page. **Bot owner only** | `.listservers 3` `.listservers` | Lists servers the bot is on with some basic info. 15 per page. **Bot owner only** | `.listservers 3`
`.savechat` | Saves a number of messages to a text file and sends it to you. **Bot owner only** | `.savechat 150` `.savechat` | Saves a number of messages to a text file and sends it to you. **Bot owner only** | `.savechat 150`
`.ping` | Ping the bot to see if there are latency issues. | `.ping` `.ping` | Ping the bot to see if there are latency issues. | `.ping`
`.botconfigedit` `.bce` | Sets one of available bot config settings to a specified value. Use the command without any parameters to get a list of available settings. **Bot owner only** | `.bce CurrencyName b1nzy` or `.bce`
`.calculate` `.calc` | Evaluate a mathematical expression. | `.calc 1+1` `.calculate` `.calc` | Evaluate a mathematical expression. | `.calc 1+1`
`.calcops` | Shows all available operations in the `.calc` command | `.calcops` `.calcops` | Shows all available operations in the `.calc` command | `.calcops`
`.alias` `.cmdmap` | Create a custom alias for a certain Nadeko command. Provide no alias to remove the existing one. **Requires Administrator server permission.** | `.alias allin $bf 100 h` or `.alias "linux thingy" >loonix Spyware Windows` `.alias` `.cmdmap` | Create a custom alias for a certain Nadeko command. Provide no alias to remove the existing one. **Requires Administrator server permission.** | `.alias allin $bf 100 h` or `.alias "linux thingy" >loonix Spyware Windows`
`.aliaslist` `.cmdmaplist` `.aliases` | Shows the list of currently set aliases. Paginated. | `.aliaslist` or `.aliaslist 3` `.aliaslist` `.cmdmaplist` `.aliases` | Shows the list of currently set aliases. Paginated. | `.aliaslist` or `.aliaslist 3`
`.serverinfo` `.sinfo` | Shows info about the server the bot is on. If no channel is supplied, it defaults to current one. | `.sinfo Some Server` `.serverinfo` `.sinfo` | Shows info about the server the bot is on. If no server is supplied, it defaults to current one. | `.sinfo Some Server`
`.channelinfo` `.cinfo` | Shows info about the channel. If no channel is supplied, it defaults to current one. | `.cinfo #some-channel` `.channelinfo` `.cinfo` | Shows info about the channel. If no channel is supplied, it defaults to current one. | `.cinfo #some-channel`
`.userinfo` `.uinfo` | Shows info about the user. If no user is supplied, it defaults a user running the command. | `.uinfo @SomeUser` `.userinfo` `.uinfo` | Shows info about the user. If no user is supplied, it defaults a user running the command. | `.uinfo @SomeUser`
`.activity` | Checks for spammers. **Bot owner only** | `.activity` `.activity` | Checks for spammers. **Bot owner only** | `.activity`
@ -440,6 +433,39 @@ Commands and aliases | Description | Usage
`.repeatremove` `.reprm` | Removes a repeating message on a specified index. Use `.repeatlist` to see indexes. **Requires ManageMessages server permission.** | `.reprm 2` `.repeatremove` `.reprm` | Removes a repeating message on a specified index. Use `.repeatlist` to see indexes. **Requires ManageMessages server permission.** | `.reprm 2`
`.repeat` | Repeat a message every `X` minutes in the current channel. You can instead specify time of day for the message to be repeated at daily (make sure you've set your server's timezone). You can have up to 5 repeating messages on the server in total. **Requires ManageMessages server permission.** | `.repeat 5 Hello there` or `.repeat 17:30 tea time` `.repeat` | Repeat a message every `X` minutes in the current channel. You can instead specify time of day for the message to be repeated at daily (make sure you've set your server's timezone). You can have up to 5 repeating messages on the server in total. **Requires ManageMessages server permission.** | `.repeat 5 Hello there` or `.repeat 17:30 tea time`
`.repeatlist` `.replst` | Shows currently repeating messages and their indexes. **Requires ManageMessages server permission.** | `.repeatlist` `.repeatlist` `.replst` | Shows currently repeating messages and their indexes. **Requires ManageMessages server permission.** | `.repeatlist`
`.streamrole` | Sets a role which is monitored for streamers (FromRole), and a role to add if a user from 'FromRole' is streaming (AddRole). When a user from 'FromRole' starts streaming, they will receive an 'AddRole'. Provide no arguments to disable **Requires ManageRoles server permission.** | `.streamrole "Eligible Streamers" "Featured Streams"`
`.streamrolekw` `.srkw` | Sets keyword which is required in the stream's title in order for the streamrole to apply. Provide no keyword in order to reset. **Requires ManageRoles server permission.** | `.srkw` or `.srkw PUBG`
`.streamrolebl` `.srbl` | Adds or removes a blacklisted user. Blacklisted users will never receive the stream role. **Requires ManageRoles server permission.** | `.srbl add @b1nzy#1234` or `.srbl rem @b1nzy#1234`
`.streamrolewl` `.srwl` | Adds or removes a whitelisted user. Whitelisted users will receive the stream role even if they don't have the specified keyword in their stream title. **Requires ManageRoles server permission.** | `.srwl add @b1nzy#1234` or `.srwl rem @b1nzy#1234`
`.convertlist` | List of the convertible dimensions and currencies. | `.convertlist` `.convertlist` | List of the convertible dimensions and currencies. | `.convertlist`
`.convert` | Convert quantities. Use `.convertlist` to see supported dimensions and currencies. | `.convert m km 1000` `.convert` | Convert quantities. Use `.convertlist` to see supported dimensions and currencies. | `.convert m km 1000`
`.verboseerror` `.ve` | Toggles whether the bot should print command errors when a command is incorrectly used. **Requires ManageMessages server permission.** | `.ve` `.verboseerror` `.ve` | Toggles whether the bot should print command errors when a command is incorrectly used. **Requires ManageMessages server permission.** | `.ve`
###### [Back to ToC](#table-of-contents)
### Xp
Commands and aliases | Description | Usage
----------------|--------------|-------
`.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`
`.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`
`.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`
`.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`
`.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`
`.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`
`.clubinfo` | Shows information about the club. | `.clubinfo b1nzy's friends#123`
`.clubbans` | Shows the list of users who have banned from your club. Paginated. You must be club owner to use this command. | `.clubbans 2`
`.clubapps` | Shows the list of users who have applied to your club. Paginated. You must be club owner to use this command. | `.clubapps 2`
`.clubapply` | Apply to join a club. You must meet that club's minimum level requirement, and not be on its ban list. | `.clubapply b1nzy's friends#123`
`.clubaccept` | Accept a user who applied to your club. | `.clubaccept b1nzy#1337`
`.clubleave` | Leaves the club you're currently in. | `.clubleave`
`.clubkick` | Kicks the user from the club. You must be the club owner. They will be able to apply again. | `.clubkick b1nzy#1337`
`.clubban` | Bans the user from the club. You must be the club owner. They will not be able to apply again. | `.clubban b1nzy#1337`
`.clubunban` | Unbans the previously banned user from the club. You must be the club owner. | `.clubunban b1nzy#1337`
`.clublevelreq` | Sets the club required level to apply to join the club. You must be club owner. You can't set this number below 5. | `.clublevelreq 7`
`.clubdisband` | Disbands the club you're the owner of. This action is irreversible. | `.clubdisband`
`.clublb` | Shows club rankings on the specified page. | `.clublb 2`

View File

@ -56,13 +56,13 @@ Follow this Detailed [Guide](http://discord.kongslien.net/guide.html).
###Question 12: I'm building NadekoBot from source, but I get hundreds of (namespace) errors without changing anything!? ###Question 12: I'm building NadekoBot from source, but I get hundreds of (namespace) errors without changing anything!?
----- -----
**Answer:** Using Visual Studio, you can solve these errors by going to `Tools` -> `NuGet Package Manager` -> `Manage NuGet Packages for Solution`. Go to the Installed tab, select the Packages that were missing (usually `Newtonsoft.json` and `RestSharp`) and install them for all projects **Answer:** Using Visual Studio, you can solve these errors by going to `Tools` -> `NuGet Package Manager` -> `Manage NuGet Packages for Solution`. Go to the Installed tab, select the Packages that were missing (usually `Newtonsoft.json` and `RestSharp`) and install them for all projects.
###Question 13: My bot has all permissions but it's still saying, "Failed to add roles. Bot has insufficient permissions". How do I fix this? ###Question 13: My bot has all permissions but it's still saying, "Failed to add roles. Bot has insufficient permissions". How do I fix this?
---------- ----------
**Answer:** Discord has added few new features and the roles now follows the role hierarchy which means you need to place your bot's role above every-other role your server has to fix the role hierarchy issue. [Here's](https://support.discordapp.com/hc/en-us/articles/214836687-Role-Management-101) a link to Discords role management 101. **Answer:** Discord has added a few new features and the roles now follow the role hierarchy, which means you need to place your bot's role above every other role on your server to fix the issue. [Here's](https://support.discordapp.com/hc/en-us/articles/214836687-Role-Management-101) a link to Discord's role management 101.
**Please Note:** *The bot can only set/add all roles below its own highest role. It can not assign it's "highest role" to anyone else.* **Please Note:** *The bot can only set/add all roles below its own highest role. It cannot assign its "highest role" to anyone else.*
###Question 14: I've broken permissions and am stuck, can I reset permissions? ###Question 14: I've broken permissions and am stuck, can I reset permissions?
---------- ----------

View File

@ -16,6 +16,7 @@ If you do not see `credentials.json` you will need to rename `credentials_exampl
"GoogleApiKey": "AIzaSyDSci1sdlWQOWNVj1vlXxxxxxbk0oWMEzM", "GoogleApiKey": "AIzaSyDSci1sdlWQOWNVj1vlXxxxxxbk0oWMEzM",
"MashapeKey": "4UrKpcWXc2mshS8RKi00000y8Kf5p1Q8kI6jsn32bmd8oVWiY7", "MashapeKey": "4UrKpcWXc2mshS8RKi00000y8Kf5p1Q8kI6jsn32bmd8oVWiY7",
"OsuApiKey": "4c8c8fdff8e1234581725db27fd140a7d93320d6", "OsuApiKey": "4c8c8fdff8e1234581725db27fd140a7d93320d6",
"CleverbotApiKey": "",
"PatreonAccessToken": "", "PatreonAccessToken": "",
"PatreonCampaignId": "334038", "PatreonCampaignId": "334038",
"Db": null, "Db": null,
@ -47,7 +48,7 @@ If you do not see `credentials.json` you will need to rename `credentials_exampl
- Replace the **`12345678`** in this link: - Replace the **`12345678`** in this link:
`https://discordapp.com/oauth2/authorize?client_id=`**`12345678`**`&scope=bot&permissions=66186303` with your `Client ID`. `https://discordapp.com/oauth2/authorize?client_id=`**`12345678`**`&scope=bot&permissions=66186303` with your `Client ID`.
- The link should now look like this: - The link should now look like this:
`https://discordapp.com/oauth2/authorize?client_id=`**`YOUR_CLENT_ID_HERE`**`&scope=bot&permissions=66186303` `https://discordapp.com/oauth2/authorize?client_id=`**`YOUR_CLIENT_ID_HERE`**`&scope=bot&permissions=66186303`
- Go to the newly created link and pick the server we created, and click `Authorize`. - Go to the newly created link and pick the server we created, and click `Authorize`.
- The bot should have been added to your server. - The bot should have been added to your server.
@ -148,12 +149,15 @@ It should look like:
- Required for Urban Disctionary, Hashtag search, and Hearthstone cards. - Required for Urban Disctionary, Hashtag search, and Hearthstone cards.
- You need to create an account on their [api marketplace](https://market.mashape.com/), after that go to `market.mashape.com/YOURNAMEHERE/applications/default-application` and press **Get the keys** in the top right corner. - You need to create an account on their [api marketplace](https://market.mashape.com/), after that go to `market.mashape.com/YOURNAMEHERE/applications/default-application` and press **Get the keys** in the top right corner.
- Copy the key and paste it into `credentials.json` - Copy the key and paste it into `credentials.json`
- **LOLAPIKey** - **LoLApiKey**
- Required for all League of Legends commands. - Required for all League of Legends commands.
- You can get this key [here](http://api.champion.gg/) - You can get this key [here.](http://api.champion.gg/)
- **OsuAPIKey** - **OsuApiKey**
- Required for Osu commands - Required for Osu commands
- You can get this key [here.](https://osu.ppy.sh/p/api) - You can get this key [here.](https://osu.ppy.sh/p/api)
- **CleverbotApiKey**
- Required if you want to use official cleverobot, instead of program-o
- you can get this key [here.](http://www.cleverbot.com/api/)
- **PatreonAccessToken** - **PatreonAccessToken**
- For Patreon creators only. - For Patreon creators only.
- **PatreonCampaignId** - **PatreonCampaignId**
@ -185,6 +189,8 @@ in order to open the database file you will need [DB Browser for SQLite](http://
- click on **Apply** - click on **Apply**
- click on **Write Changes** - click on **Write Changes**
![nadekodb](https://cdn.discordapp.com/attachments/251504306010849280/254067055240806400/nadekodb.gif)
and that will save all the changes. and that will save all the changes.
## Sharding your bot ## Sharding your bot
@ -205,8 +211,7 @@ and that will save all the changes.
- 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
![nadekodb](https://cdn.discordapp.com/attachments/251504306010849280/254067055240806400/nadekodb.gif)
[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,9 @@
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/)** **To see the guide, [click here](http://nadekobot.readthedocs.io/en/latest/Permissions%20System/)**
Why do we use the Permissions Commands? Why do we use the Permissions Commands?
------------------------------ ------------------------------
@ -15,11 +15,14 @@ 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).
@ -35,7 +38,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.
@ -49,11 +52,11 @@ To allow users to only see the current song and have a DJ role for queuing follo
* Disables music commands for everybody * Disables music commands for everybody
2. `.sc !!nowplaying enable` 2. `.sc .nowplaying enable`
* Enables the "nowplaying" command for everyone * Enables the "nowplaying" command for everyone
3. `.sc !!listqueue enable` 3. `.sc .listqueue enable`
* Enables the "listqueue" command for everyone * Enables the "listqueue" command for everyone

View File

@ -10,7 +10,7 @@ For this guide we will be using the folder /nadeko as our config root folder.
```bash ```bash
docker create --name=nadeko -v /nadeko/conf/:/root/nadeko -v /nadeko/data:/opt/NadekoBot/src/NadekoBot/bin/Release/netcoreapp1.1/data uirel/nadeko:1.4 docker create --name=nadeko -v /nadeko/conf/:/root/nadeko -v /nadeko/data:/opt/NadekoBot/src/NadekoBot/bin/Release/netcoreapp1.1/data uirel/nadeko:1.4
``` ```
-If you are coming from a previous version of nadeko (the old docker) make sure your crednetials.json has been copied into this directory and is the only thing in this folder. -If you are coming from a previous version of nadeko (the old docker) make sure your credentials.json has been copied into this directory and is the only thing in this folder.
-If you are making a fresh install, create your credentials.json from the following guide and place it in the /nadeko folder [Nadeko JSON Guide](http://nadekobot.readthedocs.io/en/latest/JSON%20Explanations/) -If you are making a fresh install, create your credentials.json from the following guide and place it in the /nadeko folder [Nadeko JSON Guide](http://nadekobot.readthedocs.io/en/latest/JSON%20Explanations/)
@ -21,7 +21,7 @@ Next start the docker up with
The docker will start and the log file will start scrolling past. Depending on hardware the bot start can take up to 5 minutes on a small DigitalOcean droplet. The docker will start and the log file will start scrolling past. Depending on hardware the bot start can take up to 5 minutes on a small DigitalOcean droplet.
Once the log ends with "NadekoBot | Starting NadekoBot v1.0-rc2" the bot is ready and can be invited to your server. Ctrl+C at this point to stop viewing the logs. Once the log ends with "NadekoBot | Starting NadekoBot v1.0-rc2" the bot is ready and can be invited to your server. Ctrl+C at this point to stop viewing the logs.
After a few moments you should be able to invite Nadeko to your server. If you cannot check the log file for errors After a few moments you should be able to invite Nadeko to your server. If you cannot check the log file for errors.
## Monitoring ## Monitoring

View File

@ -6,17 +6,17 @@ Prerequisites
*Clone the repo* *Clone the repo*
`git clone -b 1.4 https://github.com/Kwoth/NadekoBot` `git clone -b 1.4 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 Explanations](http://nadekobot.readthedocs.io/en/latest/JSON%20Explanations/) guide if you don't know how to set it up.
*run* *run*
`dotnet restore` `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 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

View File

@ -24,6 +24,8 @@ brew install opusfile
brew install libffi brew install libffi
brew install libsodium brew install libsodium
brew install tmux brew install tmux
brew install python
brew install youtube-dl
``` ```
#### Installing .NET Core SDK #### Installing .NET Core SDK

View File

@ -10,21 +10,21 @@
#### If you are running Dockerised Nadeko #### If you are running Dockerised Nadeko
- Shutdown your existing container **docker stop nadeko**. - Shutdown your existing container `docker stop nadeko`.
- Move you credentials and other files to another folder. - Move you credentials and other files to another folder.
- Delete your container **docker rm nadeko**. - Delete your container `docker rm nadeko`.
- Create a new container **docker create --name=nadeko -v /nadeko/:/root/nadeko uirel/nadeko:1.4**. - 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. - Start the container with `docker start nadeko`, and 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. - 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**. - 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.4/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.4+ version.
- 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.4+ version uses `NadekoBot.db` file from `NadekoBot/src/NadekoBot/bin/Release/netcoreapp1.1/data` folder.*

View File

@ -7,7 +7,7 @@
#### Guide #### Guide
- Download and run the [NadekoBot Updater.][Updater] - Download and run the [NadekoBot Updater.][Updater]
- Press **`Install ffmpeg`** button if you want music features. - Press **`Install ffmpeg`** and **`Install youtube-dl`** if you want music features.
***NOTE:** RESTART YOUR PC IF YOU DO.* ***NOTE:** RESTART YOUR PC IF YOU DO.*
- Press **`Update`** and go through the installation wizard. - Press **`Update`** and go through the installation wizard.
***NOTE:** If you're upgrading from 1.3, DO NOT select your old nadekobot folder. Install it in a separate directory and read the [upgrading guide](http://nadekobot.readthedocs.io/en/latest/guides/Upgrading%20Guide/).* ***NOTE:** If you're upgrading from 1.3, DO NOT select your old nadekobot folder. Install it in a separate directory and read the [upgrading guide](http://nadekobot.readthedocs.io/en/latest/guides/Upgrading%20Guide/).*

View File

@ -2,7 +2,7 @@
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace NadekoBot.DataStructures namespace NadekoBot.Common
{ {
public class AsyncLazy<T> : Lazy<Task<T>> public class AsyncLazy<T> : Lazy<Task<T>>
{ {

View File

@ -1,9 +1,9 @@
using Discord.Commands; using System.Linq;
using NadekoBot.Services;
using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using Discord.Commands;
using NadekoBot.Services.Impl;
namespace NadekoBot.Attributes namespace NadekoBot.Common.Attributes
{ {
public class Aliases : AliasAttribute public class Aliases : AliasAttribute
{ {

View File

@ -1,8 +1,8 @@
using Discord.Commands; using System.Runtime.CompilerServices;
using NadekoBot.Services; using Discord.Commands;
using System.Runtime.CompilerServices; using NadekoBot.Services.Impl;
namespace NadekoBot.Attributes namespace NadekoBot.Common.Attributes
{ {
public class Description : SummaryAttribute public class Description : SummaryAttribute
{ {

View File

@ -1,8 +1,8 @@
using Discord.Commands; using System.Runtime.CompilerServices;
using NadekoBot.Services; using Discord.Commands;
using System.Runtime.CompilerServices; using NadekoBot.Services.Impl;
namespace NadekoBot.Attributes namespace NadekoBot.Common.Attributes
{ {
public class NadekoCommand : CommandAttribute public class NadekoCommand : CommandAttribute
{ {

View File

@ -1,7 +1,7 @@
using Discord.Commands; using System;
using System; using Discord.Commands;
namespace NadekoBot.Attributes namespace NadekoBot.Common.Attributes
{ {
[AttributeUsage(AttributeTargets.Class)] [AttributeUsage(AttributeTargets.Class)]
sealed class NadekoModuleAttribute : GroupAttribute sealed class NadekoModuleAttribute : GroupAttribute

View File

@ -1,9 +1,9 @@
using System.Threading.Tasks; using System;
using System.Threading.Tasks;
using Discord.Commands; using Discord.Commands;
using System;
using NadekoBot.Services; using NadekoBot.Services;
namespace NadekoBot.Attributes namespace NadekoBot.Common.Attributes
{ {
public class OwnerOnlyAttribute : PreconditionAttribute public class OwnerOnlyAttribute : PreconditionAttribute
{ {

View File

@ -1,8 +1,8 @@
using Discord.Commands; using System.Runtime.CompilerServices;
using NadekoBot.Services; using Discord.Commands;
using System.Runtime.CompilerServices; using NadekoBot.Services.Impl;
namespace NadekoBot.Attributes namespace NadekoBot.Common.Attributes
{ {
public class Usage : RemarksAttribute public class Usage : RemarksAttribute
{ {

View File

@ -0,0 +1,26 @@
namespace NadekoBot.Common
{
public enum BotConfigEditType
{
BetflipMultiplier,
Betroll100Multiplier,
Betroll67Multiplier,
Betroll91Multiplier,
CurrencyGenerationChance,
CurrencyGenerationCooldown,
CurrencyName,
CurrencyPluralName,
CurrencySign,
DmHelpString,
HelpString,
CurrencyDropAmount,
CurrencyDropAmountMax,
MinimumBetAmount,
TriviaCurrencyReward,
XpPerMessage,
XpMinutesTimeout,
//ErrorColor, //after i fix the nadekobot.cs static variables
//OkColor
}
}

View File

@ -1,8 +1,10 @@
using Discord; using System;
using Discord;
using NadekoBot.Extensions;
using Newtonsoft.Json; using Newtonsoft.Json;
using NLog; using NLog;
namespace NadekoBot.DataStructures namespace NadekoBot.Common
{ {
public class CREmbed public class CREmbed
{ {
@ -31,19 +33,31 @@ namespace NadekoBot.DataStructures
public EmbedBuilder ToEmbed() public EmbedBuilder ToEmbed()
{ {
var embed = new EmbedBuilder() var embed = new EmbedBuilder();
.WithTitle(Title)
.WithDescription(Description) if (!string.IsNullOrWhiteSpace(Title))
.WithColor(new Discord.Color(Color)); embed.WithTitle(Title);
if (!string.IsNullOrWhiteSpace(Description))
embed.WithDescription(Description);
embed.WithColor(new Discord.Color(Color));
if (Footer != null) if (Footer != null)
embed.WithFooter(efb => efb.WithIconUrl(Footer.IconUrl).WithText(Footer.Text)); embed.WithFooter(efb =>
embed.WithThumbnailUrl(Thumbnail) {
.WithImageUrl(Image); efb.WithText(Footer.Text);
if (Uri.IsWellFormedUriString(Footer.IconUrl, UriKind.Absolute))
efb.WithIconUrl(Footer.IconUrl);
});
if (Thumbnail != null && Uri.IsWellFormedUriString(Thumbnail, UriKind.Absolute))
embed.WithThumbnailUrl(Thumbnail);
if(Image != null && Uri.IsWellFormedUriString(Image, UriKind.Absolute))
embed.WithImageUrl(Image);
if (Fields != null) if (Fields != null)
foreach (var f in Fields) foreach (var f in Fields)
{ {
embed.AddField(efb => efb.WithName(f.Name).WithValue(f.Value).WithIsInline(f.Inline)); if(!string.IsNullOrWhiteSpace(f.Name) && !string.IsNullOrWhiteSpace(f.Value))
embed.AddField(efb => efb.WithName(f.Name).WithValue(f.Value).WithIsInline(f.Inline));
} }
return embed; return embed;
@ -58,7 +72,13 @@ namespace NadekoBot.DataStructures
try try
{ {
var crembed = JsonConvert.DeserializeObject<CREmbed>(input); var crembed = JsonConvert.DeserializeObject<CREmbed>(input);
if(crembed.Fields != null && crembed.Fields.Length > 0)
foreach (var f in crembed.Fields)
{
f.Name = f.Name.TrimTo(256);
f.Value = f.Value.TrimTo(1024);
}
if (!crembed.IsValid) if (!crembed.IsValid)
return false; return false;

View File

@ -1,13 +1,14 @@
// License MIT // License MIT
// Source: https://github.com/i3arnon/ConcurrentHashSet // Source: https://github.com/i3arnon/ConcurrentHashSet
using ConcurrentCollections; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
namespace System.Collections.Concurrent namespace NadekoBot.Common.Collections
{ {
/// <summary> /// <summary>
/// Represents a thread-safe hash-based unique collection. /// Represents a thread-safe hash-based unique collection.

View File

@ -2,9 +2,8 @@
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
namespace NadekoBot.DataStructures namespace NadekoBot.Common.Collections
{ {
public static class DisposableReadOnlyListExtensions public static class DisposableReadOnlyListExtensions
{ {
public static IDisposableReadOnlyList<T> AsDisposable<T>(this IReadOnlyList<T> arr) where T : IDisposable public static IDisposableReadOnlyList<T> AsDisposable<T>(this IReadOnlyList<T> arr) where T : IDisposable

View File

@ -1,11 +1,11 @@
using NadekoBot.Services.Database.Models; using System.Collections;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using NadekoBot.Services.Database.Models;
namespace NadekoBot.DataStructures namespace NadekoBot.Common.Collections
{ {
public class IndexedCollection<T> : IList<T> where T : IIndexed public class IndexedCollection<T> : IList<T> where T : class, IIndexed
{ {
public List<T> Source { get; } public List<T> Source { get; }
private readonly object _locker = new object(); private readonly object _locker = new object();

View File

@ -1,29 +1,19 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
namespace NadekoBot.DataStructures namespace NadekoBot.Common.Collections
{ {
public class PoopyRingBuffer : IDisposable public class PoopyRingBuffer : IDisposable
{ {
// readpos == writepos means empty // readpos == writepos means empty
// writepos == readpos - 1 means full // writepos == readpos - 1 means full
private byte[] buffer; private byte[] _buffer;
public int Capacity { get; } public int Capacity { get; }
private int _readPos = 0; private int ReadPos { get; set; } = 0;
private int ReadPos private int WritePos { get; set; } = 0;
{
get => _readPos;
set => _readPos = value;
}
private int _writePos = 0;
private int WritePos
{
get => _writePos;
set => _writePos = value;
}
public int Length => ReadPos <= WritePos public int Length => ReadPos <= WritePos
? WritePos - ReadPos ? WritePos - ReadPos
: Capacity - (ReadPos - WritePos); : Capacity - (ReadPos - WritePos);
@ -38,7 +28,7 @@ namespace NadekoBot.DataStructures
public PoopyRingBuffer(int capacity = 81920 * 100) public PoopyRingBuffer(int capacity = 81920 * 100)
{ {
this.Capacity = capacity + 1; this.Capacity = capacity + 1;
this.buffer = new byte[this.Capacity]; this._buffer = new byte[this.Capacity];
} }
public int Read(byte[] b, int offset, int toRead) public int Read(byte[] b, int offset, int toRead)
@ -51,7 +41,7 @@ namespace NadekoBot.DataStructures
if (WritePos > ReadPos) if (WritePos > ReadPos)
{ {
Array.Copy(buffer, ReadPos, b, offset, toRead); Array.Copy(_buffer, ReadPos, b, offset, toRead);
ReadPos += toRead; ReadPos += toRead;
} }
else else
@ -60,12 +50,12 @@ namespace NadekoBot.DataStructures
var firstRead = toRead > toEnd ? var firstRead = toRead > toEnd ?
toEnd : toEnd :
toRead; toRead;
Array.Copy(buffer, ReadPos, b, offset, firstRead); Array.Copy(_buffer, ReadPos, b, offset, firstRead);
ReadPos += firstRead; ReadPos += firstRead;
var secondRead = toRead - firstRead; var secondRead = toRead - firstRead;
if (secondRead > 0) if (secondRead > 0)
{ {
Array.Copy(buffer, 0, b, offset + firstRead, secondRead); Array.Copy(_buffer, 0, b, offset + firstRead, secondRead);
ReadPos = secondRead; ReadPos = secondRead;
} }
} }
@ -82,7 +72,7 @@ namespace NadekoBot.DataStructures
if (WritePos < ReadPos) if (WritePos < ReadPos)
{ {
Array.Copy(b, offset, buffer, WritePos, toWrite); Array.Copy(b, offset, _buffer, WritePos, toWrite);
WritePos += toWrite; WritePos += toWrite;
} }
else else
@ -91,11 +81,11 @@ namespace NadekoBot.DataStructures
var firstWrite = toWrite > toEnd ? var firstWrite = toWrite > toEnd ?
toEnd : toEnd :
toWrite; toWrite;
Array.Copy(b, offset, buffer, WritePos, firstWrite); Array.Copy(b, offset, _buffer, WritePos, firstWrite);
var secondWrite = toWrite - firstWrite; var secondWrite = toWrite - firstWrite;
if (secondWrite > 0) if (secondWrite > 0)
{ {
Array.Copy(b, offset + firstWrite, buffer, 0, secondWrite); Array.Copy(b, offset + firstWrite, _buffer, 0, secondWrite);
WritePos = secondWrite; WritePos = secondWrite;
} }
else else
@ -110,7 +100,7 @@ namespace NadekoBot.DataStructures
public void Dispose() public void Dispose()
{ {
buffer = null; _buffer = null;
} }
} }
} }

View File

@ -1,7 +1,7 @@
using Discord; using System.Threading.Tasks;
using System.Threading.Tasks; using Discord;
namespace NadekoBot.DataStructures.ModuleBehaviors namespace NadekoBot.Common.ModuleBehaviors
{ {
/// <summary> /// <summary>
/// Implemented by modules which block execution before anything is executed /// Implemented by modules which block execution before anything is executed

View File

@ -1,8 +1,8 @@
using Discord; using System.Threading.Tasks;
using Discord;
using Discord.WebSocket; using Discord.WebSocket;
using System.Threading.Tasks;
namespace NadekoBot.DataStructures.ModuleBehaviors namespace NadekoBot.Common.ModuleBehaviors
{ {
/// <summary> /// <summary>
/// Implemented by modules which can execute something and prevent further commands from being executed. /// Implemented by modules which can execute something and prevent further commands from being executed.

View File

@ -1,4 +1,4 @@
namespace NadekoBot.DataStructures.ModuleBehaviors namespace NadekoBot.Common.ModuleBehaviors
{ {
public interface IEarlyExecutor public interface IEarlyExecutor
{ {

View File

@ -1,7 +1,7 @@
using Discord; using System.Threading.Tasks;
using System.Threading.Tasks; using Discord;
namespace NadekoBot.DataStructures.ModuleBehaviors namespace NadekoBot.Common.ModuleBehaviors
{ {
public interface IInputTransformer public interface IInputTransformer
{ {

View File

@ -1,8 +1,8 @@
using Discord; using System.Threading.Tasks;
using Discord;
using Discord.WebSocket; using Discord.WebSocket;
using System.Threading.Tasks;
namespace NadekoBot.DataStructures.ModuleBehaviors namespace NadekoBot.Common.ModuleBehaviors
{ {
public interface ILateBlocker public interface ILateBlocker
{ {

View File

@ -1,4 +1,4 @@
namespace NadekoBot.DataStructures.ModuleBehaviors namespace NadekoBot.Common.ModuleBehaviors
{ {
public interface ILateBlockingExecutor public interface ILateBlockingExecutor
{ {

View File

@ -1,8 +1,8 @@
using Discord; using System.Threading.Tasks;
using Discord;
using Discord.WebSocket; using Discord.WebSocket;
using System.Threading.Tasks;
namespace NadekoBot.DataStructures.ModuleBehaviors namespace NadekoBot.Common.ModuleBehaviors
{ {
/// <summary> /// <summary>
/// Last thing to be executed, won't stop further executions /// Last thing to be executed, won't stop further executions

View File

@ -1,26 +1,21 @@
using System; using System;
using System.Security.Cryptography; using System.Security.Cryptography;
namespace NadekoBot.Services namespace NadekoBot.Common
{ {
public class NadekoRandom : Random public class NadekoRandom : Random
{ {
RandomNumberGenerator rng; readonly RandomNumberGenerator _rng;
public NadekoRandom() : base() public NadekoRandom() : base()
{ {
rng = RandomNumberGenerator.Create(); _rng = RandomNumberGenerator.Create();
}
private NadekoRandom(int Seed) : base(Seed)
{
rng = RandomNumberGenerator.Create();
} }
public override int Next() public override int Next()
{ {
var bytes = new byte[sizeof(int)]; var bytes = new byte[sizeof(int)];
rng.GetBytes(bytes); _rng.GetBytes(bytes);
return Math.Abs(BitConverter.ToInt32(bytes, 0)); return Math.Abs(BitConverter.ToInt32(bytes, 0));
} }
@ -29,7 +24,7 @@ namespace NadekoBot.Services
if (maxValue <= 0) if (maxValue <= 0)
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
var bytes = new byte[sizeof(int)]; var bytes = new byte[sizeof(int)];
rng.GetBytes(bytes); _rng.GetBytes(bytes);
return Math.Abs(BitConverter.ToInt32(bytes, 0)) % maxValue; return Math.Abs(BitConverter.ToInt32(bytes, 0)) % maxValue;
} }
@ -40,27 +35,27 @@ namespace NadekoBot.Services
if (minValue == maxValue) if (minValue == maxValue)
return minValue; return minValue;
var bytes = new byte[sizeof(int)]; var bytes = new byte[sizeof(int)];
rng.GetBytes(bytes); _rng.GetBytes(bytes);
var sign = Math.Sign(BitConverter.ToInt32(bytes, 0)); var sign = Math.Sign(BitConverter.ToInt32(bytes, 0));
return (sign * BitConverter.ToInt32(bytes, 0)) % (maxValue - minValue) + minValue; return (sign * BitConverter.ToInt32(bytes, 0)) % (maxValue - minValue) + minValue;
} }
public override void NextBytes(byte[] buffer) public override void NextBytes(byte[] buffer)
{ {
rng.GetBytes(buffer); _rng.GetBytes(buffer);
} }
protected override double Sample() protected override double Sample()
{ {
var bytes = new byte[sizeof(double)]; var bytes = new byte[sizeof(double)];
rng.GetBytes(bytes); _rng.GetBytes(bytes);
return Math.Abs(BitConverter.ToDouble(bytes, 0) / double.MaxValue + 1); return Math.Abs(BitConverter.ToDouble(bytes, 0) / double.MaxValue + 1);
} }
public override double NextDouble() public override double NextDouble()
{ {
var bytes = new byte[sizeof(double)]; var bytes = new byte[sizeof(double)];
rng.GetBytes(bytes); _rng.GetBytes(bytes);
return BitConverter.ToDouble(bytes, 0); return BitConverter.ToDouble(bytes, 0);
} }
} }

View File

@ -1,8 +1,8 @@
using Discord.Commands; using System;
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.Commands;
namespace NadekoBot.DataStructures namespace NadekoBot.Common
{ {
public class NoPublicBot : PreconditionAttribute public class NoPublicBot : PreconditionAttribute
{ {

View File

@ -1,6 +1,6 @@
using System; using System;
namespace ConcurrentCollections namespace NadekoBot.Common
{ {
public static class PlatformHelper public static class PlatformHelper
{ {

View File

@ -1,16 +1,15 @@
using Discord; using System;
using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Extensions;
using NadekoBot.Services;
using NadekoBot.Services.Administration;
using NadekoBot.Services.Music;
using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Extensions;
using NadekoBot.Modules.Administration.Services;
using NadekoBot.Modules.Music.Services;
namespace NadekoBot.DataStructures.Replacements namespace NadekoBot.Common.Replacements
{ {
public class ReplacementBuilder public class ReplacementBuilder
{ {

View File

@ -2,7 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
namespace NadekoBot.DataStructures.Replacements namespace NadekoBot.Common.Replacements
{ {
public class Replacer public class Replacer
{ {

View File

@ -1,22 +1,19 @@
using Discord.Commands; using System;
using Discord.WebSocket;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.Commands;
using Discord.WebSocket;
namespace NadekoBot.DataStructures namespace NadekoBot.Common
{ {
public class Shard0Precondition : PreconditionAttribute public class Shard0Precondition : PreconditionAttribute
{ {
public override Task<PreconditionResult> CheckPermissions(ICommandContext context, CommandInfo command, IServiceProvider services) public override Task<PreconditionResult> CheckPermissions(ICommandContext context, CommandInfo command, IServiceProvider services)
{ {
var c = (DiscordSocketClient)context.Client; var c = (DiscordSocketClient)context.Client;
if (c.ShardId == 0) if (c.ShardId != 0)
return Task.FromResult(PreconditionResult.FromSuccess());
else
return Task.FromResult(PreconditionResult.FromError("Must be ran from shard #0")); return Task.FromResult(PreconditionResult.FromError("Must be ran from shard #0"));
return Task.FromResult(PreconditionResult.FromSuccess());
} }
} }
} }

View File

@ -1,11 +1,7 @@
using Discord; using System;
using System; using Discord;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.DataStructures.ShardCom namespace NadekoBot.Common.ShardCom
{ {
public class ShardComMessage public class ShardComMessage
{ {

View File

@ -1,11 +1,10 @@
using Newtonsoft.Json; using System.Net;
using System;
using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json;
namespace NadekoBot.DataStructures.ShardCom namespace NadekoBot.Common.ShardCom
{ {
public class ShardComClient public class ShardComClient
{ {

View File

@ -1,11 +1,11 @@
using Newtonsoft.Json; using System;
using System;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json;
namespace NadekoBot.DataStructures.ShardCom namespace NadekoBot.Common.ShardCom
{ {
public class ShardComServer : IDisposable public class ShardComServer : IDisposable
{ {

View File

@ -0,0 +1,9 @@
namespace NadekoBot.Common.TypeReaders
{
public enum AddRemove
{
Add = 0,
Rem = 1,
Rm = 1,
}
}

View File

@ -1,25 +1,18 @@
using Discord.Commands; using System;
using NadekoBot.Services;
using NadekoBot.Services.CustomReactions;
using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.Commands;
using NadekoBot.Modules.CustomReactions.Services;
using NadekoBot.Services;
namespace NadekoBot.TypeReaders namespace NadekoBot.Common.TypeReaders
{ {
public class CommandTypeReader : TypeReader public class CommandTypeReader : TypeReader
{ {
private readonly CommandService _cmds; public override Task<TypeReaderResult> Read(ICommandContext context, string input, IServiceProvider services)
private readonly CommandHandler _cmdHandler;
public CommandTypeReader(CommandService cmds, CommandHandler cmdHandler)
{
_cmds = cmds;
_cmdHandler = cmdHandler;
}
public override Task<TypeReaderResult> Read(ICommandContext context, string input, IServiceProvider _)
{ {
var _cmds = ((INServiceProvider)services).GetService<CommandService>();
var _cmdHandler = ((INServiceProvider)services).GetService<CommandHandler>();
input = input.ToUpperInvariant(); input = input.ToUpperInvariant();
var prefix = _cmdHandler.GetPrefix(context.Guild); var prefix = _cmdHandler.GetPrefix(context.Guild);
if (!input.StartsWith(prefix.ToUpperInvariant())) if (!input.StartsWith(prefix.ToUpperInvariant()))
@ -38,17 +31,12 @@ namespace NadekoBot.TypeReaders
public class CommandOrCrTypeReader : CommandTypeReader public class CommandOrCrTypeReader : CommandTypeReader
{ {
private readonly CustomReactionsService _crs; public override async Task<TypeReaderResult> Read(ICommandContext context, string input, IServiceProvider services)
public CommandOrCrTypeReader(CustomReactionsService crs, CommandService cmds, CommandHandler cmdHandler) : base(cmds, cmdHandler)
{
_crs = crs;
}
public override async Task<TypeReaderResult> Read(ICommandContext context, string input, IServiceProvider _)
{ {
input = input.ToUpperInvariant(); input = input.ToUpperInvariant();
var _crs = ((INServiceProvider)services).GetService<CustomReactionsService>();
if (_crs.GlobalReactions.Any(x => x.Trigger.ToUpperInvariant() == input)) if (_crs.GlobalReactions.Any(x => x.Trigger.ToUpperInvariant() == input))
{ {
return TypeReaderResult.FromSuccess(new CommandOrCrInfo(input)); return TypeReaderResult.FromSuccess(new CommandOrCrInfo(input));
@ -65,7 +53,7 @@ namespace NadekoBot.TypeReaders
} }
} }
var cmd = await base.Read(context, input, _); var cmd = await base.Read(context, input, services);
if (cmd.IsSuccess) if (cmd.IsSuccess)
{ {
return TypeReaderResult.FromSuccess(new CommandOrCrInfo(((CommandInfo)cmd.Values.First().Value).Name)); return TypeReaderResult.FromSuccess(new CommandOrCrInfo(((CommandInfo)cmd.Values.First().Value).Name));

View File

@ -1,21 +1,15 @@
using Discord.Commands; using System;
using NadekoBot.Services.Administration;
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.Commands;
using NadekoBot.Modules.Administration.Services;
namespace NadekoBot.TypeReaders namespace NadekoBot.Common.TypeReaders
{ {
public class GuildDateTimeTypeReader : TypeReader public class GuildDateTimeTypeReader : TypeReader
{ {
private readonly GuildTimezoneService _gts; public override Task<TypeReaderResult> Read(ICommandContext context, string input, IServiceProvider services)
public GuildDateTimeTypeReader(GuildTimezoneService gts)
{
_gts = gts;
}
public override Task<TypeReaderResult> Read(ICommandContext context, string input, IServiceProvider _)
{ {
var _gts = (GuildTimezoneService)services.GetService(typeof(GuildTimezoneService));
if (!DateTime.TryParse(input, out var dt)) if (!DateTime.TryParse(input, out var dt))
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Input string is in an incorrect format.")); return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Input string is in an incorrect format."));

View File

@ -1,10 +1,10 @@
using Discord.Commands; using System;
using Discord.WebSocket;
using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.Commands;
using Discord.WebSocket;
namespace NadekoBot.TypeReaders namespace NadekoBot.Common.TypeReaders
{ {
public class GuildTypeReader : TypeReader public class GuildTypeReader : TypeReader
{ {

View File

@ -1,4 +1,4 @@
namespace NadekoBot.Modules.Permissions namespace NadekoBot.Common.TypeReaders.Models
{ {
public class PermissionAction public class PermissionAction
{ {

View File

@ -1,10 +1,10 @@
using Discord.Commands; using System;
using NadekoBot.Extensions;
using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.Commands;
using NadekoBot.Extensions;
namespace NadekoBot.TypeReaders namespace NadekoBot.Common.TypeReaders
{ {
public class ModuleTypeReader : TypeReader public class ModuleTypeReader : TypeReader
{ {

View File

@ -1,9 +1,9 @@
using Discord.Commands; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Modules.Permissions; using Discord.Commands;
using System; using NadekoBot.Common.TypeReaders.Models;
namespace NadekoBot.TypeReaders namespace NadekoBot.Common.TypeReaders
{ {
/// <summary> /// <summary>
/// Used instead of bool for more flexible keywords for true/false only in the permission module /// Used instead of bool for more flexible keywords for true/false only in the permission module

View File

@ -1,23 +0,0 @@
using Discord.Commands;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.DataStructures
{
//public class SyncPrecondition : PreconditionAttribute
//{
// public override Task<PreconditionResult> CheckPermissions(ICommandContext context,
// CommandInfo command,
// IServiceProvider services)
// {
// }
//}
//public enum SyncType
//{
// Guild
//}
}

View File

@ -1,6 +1,4 @@
using System; using Microsoft.EntityFrameworkCore.Migrations;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations namespace NadekoBot.Migrations
{ {

View File

@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations namespace NadekoBot.Migrations

View File

@ -1,6 +1,4 @@
using System; using Microsoft.EntityFrameworkCore.Migrations;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations namespace NadekoBot.Migrations
{ {

View File

@ -1,6 +1,4 @@
using System; using Microsoft.EntityFrameworkCore.Migrations;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations namespace NadekoBot.Migrations
{ {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,45 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class streamrole : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "StreamRoleSettings",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
AddRoleId = table.Column<ulong>(nullable: false),
DateAdded = table.Column<DateTime>(nullable: true),
FromRoleId = table.Column<ulong>(nullable: false),
GuildConfigId = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_StreamRoleSettings", x => x.Id);
table.ForeignKey(
name: "FK_StreamRoleSettings_GuildConfigs_GuildConfigId",
column: x => x.GuildConfigId,
principalTable: "GuildConfigs",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_StreamRoleSettings_GuildConfigId",
table: "StreamRoleSettings",
column: "GuildConfigId",
unique: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "StreamRoleSettings");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,93 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class streamrolekwblwl : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "Enabled",
table: "StreamRoleSettings",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<string>(
name: "Keyword",
table: "StreamRoleSettings",
nullable: true);
migrationBuilder.CreateTable(
name: "StreamRoleBlacklistedUser",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
DateAdded = table.Column<DateTime>(nullable: true),
StreamRoleSettingsId = table.Column<int>(nullable: true),
UserId = table.Column<ulong>(nullable: false),
Username = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_StreamRoleBlacklistedUser", x => x.Id);
table.ForeignKey(
name: "FK_StreamRoleBlacklistedUser_StreamRoleSettings_StreamRoleSettingsId",
column: x => x.StreamRoleSettingsId,
principalTable: "StreamRoleSettings",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "StreamRoleWhitelistedUser",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
DateAdded = table.Column<DateTime>(nullable: true),
StreamRoleSettingsId = table.Column<int>(nullable: true),
UserId = table.Column<ulong>(nullable: false),
Username = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_StreamRoleWhitelistedUser", x => x.Id);
table.ForeignKey(
name: "FK_StreamRoleWhitelistedUser_StreamRoleSettings_StreamRoleSettingsId",
column: x => x.StreamRoleSettingsId,
principalTable: "StreamRoleSettings",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_StreamRoleBlacklistedUser_StreamRoleSettingsId",
table: "StreamRoleBlacklistedUser",
column: "StreamRoleSettingsId");
migrationBuilder.CreateIndex(
name: "IX_StreamRoleWhitelistedUser_StreamRoleSettingsId",
table: "StreamRoleWhitelistedUser",
column: "StreamRoleSettingsId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "StreamRoleBlacklistedUser");
migrationBuilder.DropTable(
name: "StreamRoleWhitelistedUser");
migrationBuilder.DropColumn(
name: "Enabled",
table: "StreamRoleSettings");
migrationBuilder.DropColumn(
name: "Keyword",
table: "StreamRoleSettings");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class nsfwblacklist : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "NsfwBlacklitedTag",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
DateAdded = table.Column<DateTime>(nullable: true),
GuildConfigId = table.Column<int>(nullable: true),
Tag = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_NsfwBlacklitedTag", x => x.Id);
table.ForeignKey(
name: "FK_NsfwBlacklitedTag_GuildConfigs_GuildConfigId",
column: x => x.GuildConfigId,
principalTable: "GuildConfigs",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_NsfwBlacklitedTag_GuildConfigId",
table: "NsfwBlacklitedTag",
column: "GuildConfigId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "NsfwBlacklitedTag");
}
}
}

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class waifuitems : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "WaifuItem",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
DateAdded = table.Column<DateTime>(nullable: true),
Item = table.Column<int>(nullable: false),
ItemEmoji = table.Column<string>(nullable: true),
Price = table.Column<int>(nullable: false),
WaifuInfoId = table.Column<int>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_WaifuItem", x => x.Id);
table.ForeignKey(
name: "FK_WaifuItem_WaifuInfo_WaifuInfoId",
column: x => x.WaifuInfoId,
principalTable: "WaifuInfo",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_WaifuItem_WaifuInfoId",
table: "WaifuItem",
column: "WaifuInfoId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "WaifuItem");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class mutetimeantispam : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "MuteTime",
table: "AntiSpamSetting",
nullable: false,
defaultValue: 0);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "MuteTime",
table: "AntiSpamSetting");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,296 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class xpandclubs : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "XpMinutesTimeout",
table: "BotConfig",
nullable: false,
defaultValue: 5)
.Annotation("Sqlite:Autoincrement", true);
migrationBuilder.AddColumn<int>(
name: "XpPerMessage",
table: "BotConfig",
nullable: false,
defaultValue: 3)
.Annotation("Sqlite:Autoincrement", true);
migrationBuilder.CreateTable(
name: "Clubs",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
DateAdded = table.Column<DateTime>(nullable: true),
Discrim = table.Column<int>(nullable: false),
ImageUrl = table.Column<string>(nullable: true),
MinimumLevelReq = table.Column<int>(nullable: false),
Name = table.Column<string>(maxLength: 20, nullable: false),
OwnerId = table.Column<int>(nullable: false),
Xp = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Clubs", x => x.Id);
table.UniqueConstraint("AK_Clubs_Name_Discrim", x => new { x.Name, x.Discrim });
table.ForeignKey(
name: "FK_Clubs_DiscordUser_OwnerId",
column: x => x.OwnerId,
principalTable: "DiscordUser",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.Sql(MigrationQueries.UserClub);
migrationBuilder.AddColumn<DateTime>(
name: "LastLevelUp",
table: "DiscordUser",
nullable: false,
defaultValue: DateTime.UtcNow);
migrationBuilder.AddColumn<int>(
name: "NotifyOnLevelUp",
table: "DiscordUser",
nullable: false,
defaultValue: 0);
migrationBuilder.CreateTable(
name: "UserXpStats",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
AwardedXp = table.Column<int>(nullable: false),
DateAdded = table.Column<DateTime>(nullable: true),
GuildId = table.Column<ulong>(nullable: false),
LastLevelUp = table.Column<DateTime>(nullable: false, defaultValue: new DateTime(2017, 9, 9, 1, 7, 29, 858, DateTimeKind.Local)),
NotifyOnLevelUp = table.Column<int>(nullable: false),
UserId = table.Column<ulong>(nullable: false),
Xp = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_UserXpStats", x => x.Id);
});
migrationBuilder.CreateTable(
name: "XpSettings",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
DateAdded = table.Column<DateTime>(nullable: true),
GuildConfigId = table.Column<int>(nullable: false),
NotifyMessage = table.Column<string>(nullable: true),
ServerExcluded = table.Column<bool>(nullable: false),
XpRoleRewardExclusive = table.Column<bool>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_XpSettings", x => x.Id);
table.ForeignKey(
name: "FK_XpSettings_GuildConfigs_GuildConfigId",
column: x => x.GuildConfigId,
principalTable: "GuildConfigs",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ClubApplicants",
columns: table => new
{
ClubId = table.Column<int>(nullable: false),
UserId = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ClubApplicants", x => new { x.ClubId, x.UserId });
table.ForeignKey(
name: "FK_ClubApplicants_Clubs_ClubId",
column: x => x.ClubId,
principalTable: "Clubs",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_ClubApplicants_DiscordUser_UserId",
column: x => x.UserId,
principalTable: "DiscordUser",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ClubBans",
columns: table => new
{
ClubId = table.Column<int>(nullable: false),
UserId = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ClubBans", x => new { x.ClubId, x.UserId });
table.ForeignKey(
name: "FK_ClubBans_Clubs_ClubId",
column: x => x.ClubId,
principalTable: "Clubs",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_ClubBans_DiscordUser_UserId",
column: x => x.UserId,
principalTable: "DiscordUser",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ExcludedItem",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
DateAdded = table.Column<DateTime>(nullable: true),
ItemId = table.Column<ulong>(nullable: false),
ItemType = table.Column<int>(nullable: false),
XpSettingsId = table.Column<int>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_ExcludedItem", x => x.Id);
table.ForeignKey(
name: "FK_ExcludedItem_XpSettings_XpSettingsId",
column: x => x.XpSettingsId,
principalTable: "XpSettings",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "XpRoleReward",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
DateAdded = table.Column<DateTime>(nullable: true),
Level = table.Column<int>(nullable: false),
RoleId = table.Column<ulong>(nullable: false),
XpSettingsId = table.Column<int>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_XpRoleReward", x => x.Id);
table.UniqueConstraint("AK_XpRoleReward_Level", x => x.Level);
table.ForeignKey(
name: "FK_XpRoleReward_XpSettings_XpSettingsId",
column: x => x.XpSettingsId,
principalTable: "XpSettings",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_DiscordUser_ClubId",
table: "DiscordUser",
column: "ClubId");
migrationBuilder.CreateIndex(
name: "IX_ClubApplicants_UserId",
table: "ClubApplicants",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_ClubBans_UserId",
table: "ClubBans",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_Clubs_OwnerId",
table: "Clubs",
column: "OwnerId",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_ExcludedItem_XpSettingsId",
table: "ExcludedItem",
column: "XpSettingsId");
migrationBuilder.CreateIndex(
name: "IX_UserXpStats_UserId_GuildId",
table: "UserXpStats",
columns: new[] { "UserId", "GuildId" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_XpRoleReward_XpSettingsId",
table: "XpRoleReward",
column: "XpSettingsId");
migrationBuilder.CreateIndex(
name: "IX_XpSettings_GuildConfigId",
table: "XpSettings",
column: "GuildConfigId",
unique: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_DiscordUser_Clubs_ClubId",
table: "DiscordUser");
migrationBuilder.DropTable(
name: "ClubApplicants");
migrationBuilder.DropTable(
name: "ClubBans");
migrationBuilder.DropTable(
name: "ExcludedItem");
migrationBuilder.DropTable(
name: "UserXpStats");
migrationBuilder.DropTable(
name: "XpRoleReward");
migrationBuilder.DropTable(
name: "Clubs");
migrationBuilder.DropTable(
name: "XpSettings");
migrationBuilder.DropIndex(
name: "IX_DiscordUser_ClubId",
table: "DiscordUser");
migrationBuilder.DropColumn(
name: "ClubId",
table: "DiscordUser");
migrationBuilder.DropColumn(
name: "LastLevelUp",
table: "DiscordUser");
migrationBuilder.DropColumn(
name: "NotifyOnLevelUp",
table: "DiscordUser");
migrationBuilder.DropColumn(
name: "XpMinutesTimeout",
table: "BotConfig");
migrationBuilder.DropColumn(
name: "XpPerMessage",
table: "BotConfig");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class lastXpGain : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "LastXpGain",
table: "DiscordUser",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
migrationBuilder.Sql("DELETE FROM XpRoleReward WHERE XpSettingsId is null");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "LastXpGain",
table: "DiscordUser");
}
}
}

View File

@ -0,0 +1,38 @@
namespace NadekoBot.Migrations
{
internal class MigrationQueries
{
public static string UserClub { get; } = @"
CREATE TABLE DiscordUser_tmp(
Id INTEGER PRIMARY KEY,
AvatarId TEXT,
Discriminator TEXT,
UserId INTEGER UNIQUE NOT NULL,
DateAdded TEXT,
Username TEXT
);
INSERT INTO DiscordUser_tmp
SELECT Id, AvatarId, Discriminator, UserId, DateAdded, Username
FROM DiscordUser;
DROP TABLE DiscordUser;
CREATE TABLE DiscordUser(
Id INTEGER PRIMARY KEY,
AvatarId TEXT,
Discriminator TEXT,
UserId INTEGER UNIQUE NOT NULL,
DateAdded TEXT,
Username TEXT,
ClubId INTEGER,
CONSTRAINT FK_DiscordUser_Clubs_ClubId FOREIGN KEY(ClubId) REFERENCES Clubs(Id) ON DELETE RESTRICT
);
INSERT INTO DiscordUser
SELECT Id, AvatarId, Discriminator, UserId, DateAdded, Username, NULL
FROM DiscordUser_tmp;
DROP TABLE DiscordUser_tmp;";
}
}

View File

@ -70,6 +70,8 @@ namespace NadekoBot.Migrations
b.Property<int>("MessageThreshold"); b.Property<int>("MessageThreshold");
b.Property<int>("MuteTime");
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("GuildConfigId") b.HasIndex("GuildConfigId")
@ -181,6 +183,14 @@ namespace NadekoBot.Migrations
b.Property<int>("TriviaCurrencyReward"); b.Property<int>("TriviaCurrencyReward");
b.Property<int>("XpMinutesTimeout")
.ValueGeneratedOnAdd()
.HasDefaultValue(5);
b.Property<int>("XpPerMessage")
.ValueGeneratedOnAdd()
.HasDefaultValue(3);
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("BotConfig"); b.ToTable("BotConfig");
@ -236,6 +246,63 @@ namespace NadekoBot.Migrations
b.ToTable("ClashOfClans"); b.ToTable("ClashOfClans");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubApplicants", b =>
{
b.Property<int>("ClubId");
b.Property<int>("UserId");
b.HasKey("ClubId", "UserId");
b.HasIndex("UserId");
b.ToTable("ClubApplicants");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubBans", b =>
{
b.Property<int>("ClubId");
b.Property<int>("UserId");
b.HasKey("ClubId", "UserId");
b.HasIndex("UserId");
b.ToTable("ClubBans");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubInfo", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime?>("DateAdded");
b.Property<int>("Discrim");
b.Property<string>("ImageUrl");
b.Property<int>("MinimumLevelReq");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(20);
b.Property<int>("OwnerId");
b.Property<int>("Xp");
b.HasKey("Id");
b.HasAlternateKey("Name", "Discrim");
b.HasIndex("OwnerId")
.IsUnique();
b.ToTable("Clubs");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -361,6 +428,8 @@ namespace NadekoBot.Migrations
b.Property<bool>("AutoDeleteTrigger"); b.Property<bool>("AutoDeleteTrigger");
b.Property<bool>("ContainsAnywhere");
b.Property<DateTime?>("DateAdded"); b.Property<DateTime?>("DateAdded");
b.Property<bool>("DmResponse"); b.Property<bool>("DmResponse");
@ -387,10 +456,20 @@ namespace NadekoBot.Migrations
b.Property<string>("AvatarId"); b.Property<string>("AvatarId");
b.Property<int?>("ClubId");
b.Property<DateTime?>("DateAdded"); b.Property<DateTime?>("DateAdded");
b.Property<string>("Discriminator"); b.Property<string>("Discriminator");
b.Property<DateTime>("LastLevelUp")
.ValueGeneratedOnAdd()
.HasDefaultValue(new DateTime(2017, 9, 11, 22, 0, 31, 236, DateTimeKind.Local));
b.Property<DateTime>("LastXpGain");
b.Property<int>("NotifyOnLevelUp");
b.Property<ulong>("UserId"); b.Property<ulong>("UserId");
b.Property<string>("Username"); b.Property<string>("Username");
@ -399,6 +478,8 @@ namespace NadekoBot.Migrations
b.HasAlternateKey("UserId"); b.HasAlternateKey("UserId");
b.HasIndex("ClubId");
b.ToTable("DiscordUser"); b.ToTable("DiscordUser");
}); });
@ -441,6 +522,26 @@ namespace NadekoBot.Migrations
b.ToTable("EightBallResponses"); b.ToTable("EightBallResponses");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime?>("DateAdded");
b.Property<ulong>("ItemId");
b.Property<int>("ItemType");
b.Property<int?>("XpSettingsId");
b.HasKey("Id");
b.HasIndex("XpSettingsId");
b.ToTable("ExcludedItem");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -800,6 +901,24 @@ namespace NadekoBot.Migrations
b.ToTable("MutedUserId"); b.ToTable("MutedUserId");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.NsfwBlacklitedTag", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime?>("DateAdded");
b.Property<int?>("GuildConfigId");
b.Property<string>("Tag");
b.HasKey("Id");
b.HasIndex("GuildConfigId");
b.ToTable("NsfwBlacklitedTag");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -1126,6 +1245,71 @@ namespace NadekoBot.Migrations
b.ToTable("StartupCommand"); b.ToTable("StartupCommand");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime?>("DateAdded");
b.Property<int?>("StreamRoleSettingsId");
b.Property<ulong>("UserId");
b.Property<string>("Username");
b.HasKey("Id");
b.HasIndex("StreamRoleSettingsId");
b.ToTable("StreamRoleBlacklistedUser");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<ulong>("AddRoleId");
b.Property<DateTime?>("DateAdded");
b.Property<bool>("Enabled");
b.Property<ulong>("FromRoleId");
b.Property<int>("GuildConfigId");
b.Property<string>("Keyword");
b.HasKey("Id");
b.HasIndex("GuildConfigId")
.IsUnique();
b.ToTable("StreamRoleSettings");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime?>("DateAdded");
b.Property<int?>("StreamRoleSettingsId");
b.Property<ulong>("UserId");
b.Property<string>("Username");
b.HasKey("Id");
b.HasIndex("StreamRoleSettingsId");
b.ToTable("StreamRoleWhitelistedUser");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -1165,6 +1349,35 @@ namespace NadekoBot.Migrations
b.ToTable("PokeGame"); b.ToTable("PokeGame");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.UserXpStats", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("AwardedXp");
b.Property<DateTime?>("DateAdded");
b.Property<ulong>("GuildId");
b.Property<DateTime>("LastLevelUp")
.ValueGeneratedOnAdd()
.HasDefaultValue(new DateTime(2017, 9, 11, 22, 0, 31, 238, DateTimeKind.Local));
b.Property<int>("NotifyOnLevelUp");
b.Property<ulong>("UserId");
b.Property<int>("Xp");
b.HasKey("Id");
b.HasIndex("UserId", "GuildId")
.IsUnique();
b.ToTable("UserXpStats");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -1212,6 +1425,28 @@ namespace NadekoBot.Migrations
b.ToTable("WaifuInfo"); b.ToTable("WaifuInfo");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime?>("DateAdded");
b.Property<int>("Item");
b.Property<string>("ItemEmoji");
b.Property<int>("Price");
b.Property<int?>("WaifuInfoId");
b.HasKey("Id");
b.HasIndex("WaifuInfoId");
b.ToTable("WaifuItem");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -1284,6 +1519,51 @@ namespace NadekoBot.Migrations
b.ToTable("WarningPunishment"); b.ToTable("WarningPunishment");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime?>("DateAdded");
b.Property<int>("Level");
b.Property<ulong>("RoleId");
b.Property<int?>("XpSettingsId");
b.HasKey("Id");
b.HasAlternateKey("Level");
b.HasIndex("XpSettingsId");
b.ToTable("XpRoleReward");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime?>("DateAdded");
b.Property<int>("GuildConfigId");
b.Property<string>("NotifyMessage");
b.Property<bool>("ServerExcluded");
b.Property<bool>("XpRoleRewardExclusive");
b.HasKey("Id");
b.HasIndex("GuildConfigId")
.IsUnique();
b.ToTable("XpSettings");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b =>
{ {
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig")
@ -1333,6 +1613,40 @@ namespace NadekoBot.Migrations
.OnDelete(DeleteBehavior.Cascade); .OnDelete(DeleteBehavior.Cascade);
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubApplicants", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.ClubInfo", "Club")
.WithMany("Applicants")
.HasForeignKey("ClubId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubBans", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.ClubInfo", "Club")
.WithMany("Bans")
.HasForeignKey("ClubId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubInfo", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "Owner")
.WithOne()
.HasForeignKey("NadekoBot.Services.Database.Models.ClubInfo", "OwnerId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b =>
{ {
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
@ -1354,6 +1668,13 @@ namespace NadekoBot.Migrations
.HasForeignKey("BotConfigId"); .HasForeignKey("BotConfigId");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.DiscordUser", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.ClubInfo", "Club")
.WithMany("Users")
.HasForeignKey("ClubId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b =>
{ {
b.HasOne("NadekoBot.Services.Database.Models.BotConfig") b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
@ -1361,6 +1682,13 @@ namespace NadekoBot.Migrations
.HasForeignKey("BotConfigId"); .HasForeignKey("BotConfigId");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.XpSettings")
.WithMany("ExclusionList")
.HasForeignKey("XpSettingsId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b =>
{ {
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
@ -1439,6 +1767,13 @@ namespace NadekoBot.Migrations
.HasForeignKey("GuildConfigId"); .HasForeignKey("GuildConfigId");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.NsfwBlacklitedTag", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
.WithMany("NsfwBlacklistedTags")
.HasForeignKey("GuildConfigId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b =>
{ {
b.HasOne("NadekoBot.Services.Database.Models.Permission", "Next") b.HasOne("NadekoBot.Services.Database.Models.Permission", "Next")
@ -1510,6 +1845,28 @@ namespace NadekoBot.Migrations
.HasForeignKey("BotConfigId"); .HasForeignKey("BotConfigId");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings")
.WithMany("Blacklist")
.HasForeignKey("StreamRoleSettingsId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig")
.WithOne("StreamRole")
.HasForeignKey("NadekoBot.Services.Database.Models.StreamRoleSettings", "GuildConfigId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings")
.WithMany("Whitelist")
.HasForeignKey("StreamRoleSettingsId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b =>
{ {
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
@ -1540,6 +1897,13 @@ namespace NadekoBot.Migrations
.OnDelete(DeleteBehavior.Cascade); .OnDelete(DeleteBehavior.Cascade);
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.WaifuInfo")
.WithMany("Items")
.HasForeignKey("WaifuInfoId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b =>
{ {
b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "New") b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "New")
@ -1562,6 +1926,21 @@ namespace NadekoBot.Migrations
.WithMany("WarnPunishments") .WithMany("WarnPunishments")
.HasForeignKey("GuildConfigId"); .HasForeignKey("GuildConfigId");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.XpSettings")
.WithMany("RoleRewards")
.HasForeignKey("XpSettingsId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig")
.WithOne("XpSettings")
.HasForeignKey("NadekoBot.Services.Database.Models.XpSettings", "GuildConfigId")
.OnDelete(DeleteBehavior.Cascade);
});
} }
} }
} }

View File

@ -5,23 +5,21 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Common.Attributes;
using NadekoBot.Services; using NadekoBot.Services;
using NadekoBot.Attributes; using NadekoBot.Modules.Administration.Services;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using NadekoBot.Services.Administration;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
{ {
public partial class Administration : NadekoTopLevelModule public partial class Administration : NadekoTopLevelModule<AdministrationService>
{ {
private IGuild _nadekoSupportServer; private IGuild _nadekoSupportServer;
private readonly DbService _db; private readonly DbService _db;
private readonly AdministrationService _admin;
public Administration(DbService db, AdministrationService admin) public Administration(DbService db)
{ {
_db = db; _db = db;
_admin = admin;
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
@ -40,12 +38,12 @@ namespace NadekoBot.Modules.Administration
} }
if (enabled) if (enabled)
{ {
_admin.DeleteMessagesOnCommand.Add(Context.Guild.Id); _service.DeleteMessagesOnCommand.Add(Context.Guild.Id);
await ReplyConfirmLocalized("delmsg_on").ConfigureAwait(false); await ReplyConfirmLocalized("delmsg_on").ConfigureAwait(false);
} }
else else
{ {
_admin.DeleteMessagesOnCommand.TryRemove(Context.Guild.Id); _service.DeleteMessagesOnCommand.TryRemove(Context.Guild.Id);
await ReplyConfirmLocalized("delmsg_off").ConfigureAwait(false); await ReplyConfirmLocalized("delmsg_off").ConfigureAwait(false);
} }
} }
@ -58,7 +56,7 @@ namespace NadekoBot.Modules.Administration
{ {
var guser = (IGuildUser)Context.User; var guser = (IGuildUser)Context.User;
var maxRole = guser.GetRoles().Max(x => x.Position); var maxRole = guser.GetRoles().Max(x => x.Position);
if ((Context.User.Id != Context.Guild.OwnerId) && (maxRole < role.Position || maxRole <= usr.GetRoles().Max(x => x.Position))) if ((Context.User.Id != Context.Guild.OwnerId) && (maxRole <= role.Position || maxRole <= usr.GetRoles().Max(x => x.Position)))
return; return;
try try
{ {

View File

@ -1,26 +1,24 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
using NadekoBot.Services.Administration;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Common.Attributes;
using NadekoBot.Modules.Administration.Services;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
{ {
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class AutoAssignRoleCommands : NadekoSubmodule public class AutoAssignRoleCommands : NadekoSubmodule<AutoAssignRoleService>
{ {
private readonly DbService _db; private readonly DbService _db;
private readonly AutoAssignRoleService _service;
public AutoAssignRoleCommands(AutoAssignRoleService service, DbService db) public AutoAssignRoleCommands(DbService db)
{ {
_db = db; _db = db;
_service = service;
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
@ -39,7 +37,7 @@ namespace NadekoBot.Modules.Administration
if (role == null) if (role == null)
{ {
conf.AutoAssignRoleId = 0; conf.AutoAssignRoleId = 0;
_service.AutoAssignedRoles.TryRemove(Context.Guild.Id, out ulong throwaway); _service.AutoAssignedRoles.TryRemove(Context.Guild.Id, out _);
} }
else else
{ {

View File

@ -2,7 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace NadekoBot.Modules.Administration.Commands.Migration namespace NadekoBot.Modules.Administration.Common.Migration
{ {
public class CommandPrefixes0_9 public class CommandPrefixes0_9
{ {

View File

@ -1,6 +1,6 @@
using System; using System;
namespace NadekoBot.Modules.Administration.Commands.Migration namespace NadekoBot.Modules.Administration.Common.Migration
{ {
public class MigrationException : Exception public class MigrationException : Exception
{ {

View File

@ -1,8 +1,9 @@
using Discord; using System.Collections.Concurrent;
using Discord;
using NadekoBot.Common.Collections;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System.Collections.Concurrent;
namespace NadekoBot.Services.Administration namespace NadekoBot.Modules.Administration.Common
{ {
public enum ProtectionType public enum ProtectionType
{ {

View File

@ -1,12 +1,13 @@
using Discord.WebSocket; using System;
using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.WebSocket;
using NadekoBot.Modules.Administration.Services;
namespace NadekoBot.Services.Administration namespace NadekoBot.Modules.Administration.Common
{ {
public class Ratelimiter public class Ratelimiter
{ {

View File

@ -1,10 +1,10 @@
using Discord; using System;
using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Discord;
namespace NadekoBot.Services.Administration namespace NadekoBot.Modules.Administration.Common
{ {
public class UserSpamStats : IDisposable public class UserSpamStats : IDisposable
{ {

View File

@ -1,24 +1,22 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.Services; using NadekoBot.Services;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Services.Administration; using NadekoBot.Common.Attributes;
using NadekoBot.Modules.Administration.Services;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
{ {
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class GameChannelCommands : NadekoSubmodule public class GameChannelCommands : NadekoSubmodule<GameVoiceChannelService>
{ {
private readonly DbService _db; private readonly DbService _db;
private readonly GameVoiceChannelService _service;
public GameChannelCommands(GameVoiceChannelService service, DbService db) public GameChannelCommands(DbService db)
{ {
_db = db; _db = db;
_service = service;
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]

View File

@ -1,6 +1,5 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -8,6 +7,7 @@ using System.Collections.Immutable;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Common.Attributes;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
{ {

View File

@ -1,16 +1,16 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.DataStructures;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Modules.Permissions;
using NadekoBot.Services; using NadekoBot.Services;
using NadekoBot.Services.Administration;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System; using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using static NadekoBot.Services.Administration.LogCommandService; using NadekoBot.Common;
using NadekoBot.Common.Attributes;
using NadekoBot.Common.TypeReaders.Models;
using NadekoBot.Modules.Administration.Services;
using static NadekoBot.Modules.Administration.Services.LogCommandService;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
{ {
@ -18,14 +18,12 @@ namespace NadekoBot.Modules.Administration
{ {
[Group] [Group]
[NoPublicBot] [NoPublicBot]
public class LogCommands : NadekoSubmodule public class LogCommands : NadekoSubmodule<LogCommandService>
{ {
private readonly LogCommandService _lc;
private readonly DbService _db; private readonly DbService _db;
public LogCommands(LogCommandService lc, DbService db) public LogCommands(DbService db)
{ {
_lc = lc;
_db = db; _db = db;
} }
@ -46,7 +44,7 @@ namespace NadekoBot.Modules.Administration
using (var uow = _db.UnitOfWork) using (var uow = _db.UnitOfWork)
{ {
logSetting = uow.GuildConfigs.LogSettingsFor(channel.Guild.Id).LogSetting; logSetting = uow.GuildConfigs.LogSettingsFor(channel.Guild.Id).LogSetting;
_lc.GuildLogSettings.AddOrUpdate(channel.Guild.Id, (id) => logSetting, (id, old) => logSetting); _service.GuildLogSettings.AddOrUpdate(channel.Guild.Id, (id) => logSetting, (id, old) => logSetting);
logSetting.LogOtherId = logSetting.LogOtherId =
logSetting.MessageUpdatedId = logSetting.MessageUpdatedId =
logSetting.MessageDeletedId = logSetting.MessageDeletedId =
@ -82,7 +80,7 @@ namespace NadekoBot.Modules.Administration
using (var uow = _db.UnitOfWork) using (var uow = _db.UnitOfWork)
{ {
var config = uow.GuildConfigs.LogSettingsFor(channel.Guild.Id); var config = uow.GuildConfigs.LogSettingsFor(channel.Guild.Id);
LogSetting logSetting = _lc.GuildLogSettings.GetOrAdd(channel.Guild.Id, (id) => config.LogSetting); LogSetting logSetting = _service.GuildLogSettings.GetOrAdd(channel.Guild.Id, (id) => config.LogSetting);
removed = logSetting.IgnoredChannels.RemoveWhere(ilc => ilc.ChannelId == channel.Id); removed = logSetting.IgnoredChannels.RemoveWhere(ilc => ilc.ChannelId == channel.Id);
config.LogSetting.IgnoredChannels.RemoveWhere(ilc => ilc.ChannelId == channel.Id); config.LogSetting.IgnoredChannels.RemoveWhere(ilc => ilc.ChannelId == channel.Id);
if (removed == 0) if (removed == 0)
@ -106,8 +104,8 @@ namespace NadekoBot.Modules.Administration
[OwnerOnly] [OwnerOnly]
public async Task LogEvents() public async Task LogEvents()
{ {
await Context.Channel.SendConfirmAsync(GetText("log_events") + "\n" + await Context.Channel.SendConfirmAsync(Format.Bold(GetText("log_events")) + "\n" +
string.Join(", ", Enum.GetNames(typeof(LogType)).Cast<string>())) $"```fix\n{string.Join(", ", Enum.GetNames(typeof(LogType)).Cast<string>())}```")
.ConfigureAwait(false); .ConfigureAwait(false);
} }
@ -122,7 +120,7 @@ namespace NadekoBot.Modules.Administration
using (var uow = _db.UnitOfWork) using (var uow = _db.UnitOfWork)
{ {
var logSetting = uow.GuildConfigs.LogSettingsFor(channel.Guild.Id).LogSetting; var logSetting = uow.GuildConfigs.LogSettingsFor(channel.Guild.Id).LogSetting;
_lc.GuildLogSettings.AddOrUpdate(channel.Guild.Id, (id) => logSetting, (id, old) => logSetting); _service.GuildLogSettings.AddOrUpdate(channel.Guild.Id, (id) => logSetting, (id, old) => logSetting);
switch (type) switch (type)
{ {
case LogType.Other: case LogType.Other:

View File

@ -4,27 +4,28 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.Commands; using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.Services; using NadekoBot.Services;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using Newtonsoft.Json; using Newtonsoft.Json;
using NadekoBot.Modules.Administration.Commands.Migration;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services.Database; using NadekoBot.Services.Database;
using Microsoft.Data.Sqlite; using Microsoft.Data.Sqlite;
using NadekoBot.Common.Attributes;
using NadekoBot.Common.Collections;
using NadekoBot.Modules.Administration.Common.Migration;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
{ {
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class Migration : NadekoSubmodule public class MigrationCommands : NadekoSubmodule
{ {
private const int CURRENT_VERSION = 1; private const int CURRENT_VERSION = 1;
private readonly DbService _db; private readonly DbService _db;
public Migration(DbService db) public MigrationCommands(DbService db)
{ {
_db = db; _db = db;
} }
@ -211,10 +212,10 @@ namespace NadekoBot.Modules.Administration
type = FollowedStream.FollowedStreamType.Twitch; type = FollowedStream.FollowedStreamType.Twitch;
break; break;
case StreamNotificationConfig0_9.StreamType.Beam: case StreamNotificationConfig0_9.StreamType.Beam:
type = FollowedStream.FollowedStreamType.Beam; type = FollowedStream.FollowedStreamType.Mixer;
break; break;
case StreamNotificationConfig0_9.StreamType.Hitbox: case StreamNotificationConfig0_9.StreamType.Hitbox:
type = FollowedStream.FollowedStreamType.Hitbox; type = FollowedStream.FollowedStreamType.Smashcast;
break; break;
default: default:
break; break;
@ -351,54 +352,6 @@ namespace NadekoBot.Modules.Administration
oldConfig.RotatingStatuses.ForEach(i => messages.Add(new PlayingStatus { Status = i })); oldConfig.RotatingStatuses.ForEach(i => messages.Add(new PlayingStatus { Status = i }));
botConfig.RotatingStatusMessages = messages; botConfig.RotatingStatusMessages = messages;
//Prefix
botConfig.ModulePrefixes.Clear();
botConfig.ModulePrefixes.AddRange(new HashSet<ModulePrefix>
{
new ModulePrefix()
{
ModuleName = "Administration",
Prefix = oldConfig.CommandPrefixes.Administration
},
new ModulePrefix()
{
ModuleName = "Searches",
Prefix = oldConfig.CommandPrefixes.Searches
},
new ModulePrefix() {ModuleName = "NSFW", Prefix = oldConfig.CommandPrefixes.NSFW},
new ModulePrefix()
{
ModuleName = "Conversations",
Prefix = oldConfig.CommandPrefixes.Conversations
},
new ModulePrefix()
{
ModuleName = "ClashOfClans",
Prefix = oldConfig.CommandPrefixes.ClashOfClans
},
new ModulePrefix() {ModuleName = "Help", Prefix = oldConfig.CommandPrefixes.Help},
new ModulePrefix() {ModuleName = "Music", Prefix = oldConfig.CommandPrefixes.Music},
new ModulePrefix() {ModuleName = "Trello", Prefix = oldConfig.CommandPrefixes.Trello},
new ModulePrefix() {ModuleName = "Games", Prefix = oldConfig.CommandPrefixes.Games},
new ModulePrefix()
{
ModuleName = "Gambling",
Prefix = oldConfig.CommandPrefixes.Gambling
},
new ModulePrefix()
{
ModuleName = "Permissions",
Prefix = oldConfig.CommandPrefixes.Permissions
},
new ModulePrefix()
{
ModuleName = "Programming",
Prefix = oldConfig.CommandPrefixes.Programming
},
new ModulePrefix() {ModuleName = "Pokemon", Prefix = oldConfig.CommandPrefixes.Pokemon},
new ModulePrefix() {ModuleName = "Utility", Prefix = oldConfig.CommandPrefixes.Utility}
});
//Blacklist //Blacklist
var blacklist = new HashSet<BlacklistItem>(oldConfig.ServerBlacklist.Select(server => new BlacklistItem() { ItemId = server, Type = BlacklistType.Server })); var blacklist = new HashSet<BlacklistItem>(oldConfig.ServerBlacklist.Select(server => new BlacklistItem() { ItemId = server, Type = BlacklistType.Server }));
blacklist.AddRange(oldConfig.ChannelBlacklist.Select(channel => new BlacklistItem() { ItemId = channel, Type = BlacklistType.Channel })); blacklist.AddRange(oldConfig.ChannelBlacklist.Select(channel => new BlacklistItem() { ItemId = channel, Type = BlacklistType.Channel }));

View File

@ -1,31 +1,29 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.Services; using NadekoBot.Services;
using NadekoBot.Services.Administration;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Common.Attributes;
using NadekoBot.Modules.Administration.Services;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
{ {
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class MuteCommands : NadekoSubmodule public class MuteCommands : NadekoSubmodule<MuteService>
{ {
private readonly MuteService _service;
private readonly DbService _db; private readonly DbService _db;
public MuteCommands(MuteService service, DbService db) public MuteCommands(DbService db)
{ {
_service = service;
_db = db; _db = db;
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
[Priority(1)] [Priority(0)]
public async Task SetMuteRole([Remainder] string name) public async Task SetMuteRole([Remainder] string name)
{ {
name = name.Trim(); name = name.Trim();
@ -45,7 +43,7 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
[Priority(0)] [Priority(1)]
public Task SetMuteRole([Remainder] IRole role) public Task SetMuteRole([Remainder] IRole role)
=> SetMuteRole(role.Name); => SetMuteRole(role.Name);
@ -53,7 +51,7 @@ namespace NadekoBot.Modules.Administration
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
[RequireUserPermission(GuildPermission.MuteMembers)] [RequireUserPermission(GuildPermission.MuteMembers)]
[Priority(1)] [Priority(0)]
public async Task Mute(IGuildUser user) public async Task Mute(IGuildUser user)
{ {
try try
@ -71,7 +69,7 @@ namespace NadekoBot.Modules.Administration
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
[RequireUserPermission(GuildPermission.MuteMembers)] [RequireUserPermission(GuildPermission.MuteMembers)]
[Priority(0)] [Priority(1)]
public async Task Mute(int minutes, IGuildUser user) public async Task Mute(int minutes, IGuildUser user)
{ {
if (minutes < 1 || minutes > 1440) if (minutes < 1 || minutes > 1440)

View File

@ -1,26 +1,24 @@
using Discord.Commands; using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.Services; using NadekoBot.Services;
using NadekoBot.Services.Administration;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Common.Attributes;
using NadekoBot.Modules.Administration.Services;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
{ {
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class PlayingRotateCommands : NadekoSubmodule public class PlayingRotateCommands : NadekoSubmodule<PlayingRotateService>
{ {
private static readonly object _locker = new object(); private static readonly object _locker = new object();
private readonly DbService _db; private readonly DbService _db;
private readonly PlayingRotateService _service;
public PlayingRotateCommands(PlayingRotateService service, DbService db) public PlayingRotateCommands(DbService db)
{ {
_db = db; _db = db;
_service = service;
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]

View File

@ -1,7 +1,7 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using NadekoBot.Attributes;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Common.Attributes;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
{ {
@ -11,7 +11,7 @@ namespace NadekoBot.Modules.Administration
public class PrefixCommands : NadekoSubmodule public class PrefixCommands : NadekoSubmodule
{ {
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[Priority(0)] [Priority(1)]
public new async Task Prefix() public new async Task Prefix()
{ {
await ReplyConfirmLocalized("prefix_current", Format.Code(_cmdHandler.GetPrefix(Context.Guild))).ConfigureAwait(false); await ReplyConfirmLocalized("prefix_current", Format.Code(_cmdHandler.GetPrefix(Context.Guild))).ConfigureAwait(false);
@ -21,7 +21,7 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.Administrator)] [RequireUserPermission(GuildPermission.Administrator)]
[Priority(1)] [Priority(0)]
public new async Task Prefix([Remainder]string prefix) public new async Task Prefix([Remainder]string prefix)
{ {
if (string.IsNullOrWhiteSpace(prefix)) if (string.IsNullOrWhiteSpace(prefix))

View File

@ -1,42 +1,50 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System; using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Services.Administration; using NadekoBot.Common.Attributes;
using NadekoBot.Modules.Administration.Common;
using NadekoBot.Modules.Administration.Services;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
{ {
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class ProtectionCommands : NadekoSubmodule public class ProtectionCommands : NadekoSubmodule<ProtectionService>
{ {
private readonly ProtectionService _service;
private readonly MuteService _mute; private readonly MuteService _mute;
private readonly DbService _db; private readonly DbService _db;
public ProtectionCommands(ProtectionService service, MuteService mute, DbService db) public ProtectionCommands(MuteService mute, DbService db)
{ {
_service = service;
_mute = mute; _mute = mute;
_db = db; _db = db;
} }
private string GetAntiSpamString(AntiSpamStats stats) private string GetAntiSpamString(AntiSpamStats stats)
{ {
var ignoredString = string.Join(", ", stats.AntiSpamSettings.IgnoredChannels.Select(c => $"<#{c.ChannelId}>")); var settings = stats.AntiSpamSettings;
var ignoredString = string.Join(", ", settings.IgnoredChannels.Select(c => $"<#{c.ChannelId}>"));
if (string.IsNullOrWhiteSpace(ignoredString)) if (string.IsNullOrWhiteSpace(ignoredString))
ignoredString = "none"; ignoredString = "none";
string add = "";
if (settings.Action == PunishmentAction.Mute
&& settings.MuteTime > 0)
{
add = " (" + settings.MuteTime + "s)";
}
return GetText("spam_stats", return GetText("spam_stats",
Format.Bold(stats.AntiSpamSettings.MessageThreshold.ToString()), Format.Bold(settings.MessageThreshold.ToString()),
Format.Bold(stats.AntiSpamSettings.Action.ToString()), Format.Bold(settings.Action.ToString() + add),
ignoredString); ignoredString);
} }
@ -62,8 +70,7 @@ namespace NadekoBot.Modules.Administration
return; return;
} }
AntiRaidStats throwaway; if (_service.AntiRaidGuilds.TryRemove(Context.Guild.Id, out _))
if (_service.AntiRaidGuilds.TryRemove(Context.Guild.Id, out throwaway))
{ {
using (var uow = _db.UnitOfWork) using (var uow = _db.UnitOfWork)
{ {
@ -114,15 +121,12 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.Administrator)] [RequireUserPermission(GuildPermission.Administrator)]
public async Task AntiSpam(int messageCount = 3, PunishmentAction action = PunishmentAction.Mute) [Priority(1)]
public async Task AntiSpam()
{ {
if (messageCount < 2 || messageCount > 10) if (_service.AntiSpamGuilds.TryRemove(Context.Guild.Id, out var removed))
return;
AntiSpamStats throwaway;
if (_service.AntiSpamGuilds.TryRemove(Context.Guild.Id, out throwaway))
{ {
throwaway.UserStats.ForEach(x => x.Value.Dispose()); removed.UserStats.ForEach(x => x.Value.Dispose());
using (var uow = _db.UnitOfWork) using (var uow = _db.UnitOfWork)
{ {
var gc = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.AntiSpamSetting) var gc = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.AntiSpamSetting)
@ -135,6 +139,21 @@ namespace NadekoBot.Modules.Administration
return; return;
} }
await AntiSpam(3).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.Administrator)]
[Priority(0)]
public async Task AntiSpam(int messageCount, PunishmentAction action = PunishmentAction.Mute, int time = 0)
{
if (messageCount < 2 || messageCount > 10)
return;
if (time < 0 || time > 60 * 12)
return;
try try
{ {
await _mute.GetMuteRole(Context.Guild).ConfigureAwait(false); await _mute.GetMuteRole(Context.Guild).ConfigureAwait(false);
@ -152,10 +171,15 @@ namespace NadekoBot.Modules.Administration
{ {
Action = action, Action = action,
MessageThreshold = messageCount, MessageThreshold = messageCount,
MuteTime = time,
} }
}; };
_service.AntiSpamGuilds.AddOrUpdate(Context.Guild.Id, stats, (key, old) => stats); stats = _service.AntiSpamGuilds.AddOrUpdate(Context.Guild.Id, stats, (key, old) =>
{
stats.AntiSpamSettings.IgnoredChannels = old.AntiSpamSettings.IgnoredChannels;
return stats;
});
using (var uow = _db.UnitOfWork) using (var uow = _db.UnitOfWork)
{ {

View File

@ -1,28 +1,19 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services.Administration;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Common.Attributes;
using NadekoBot.Modules.Administration.Services;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
{ {
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class PruneCommands : ModuleBase public class PruneCommands : NadekoSubmodule<PruneService>
{ {
private readonly TimeSpan twoWeeks = TimeSpan.FromDays(14); private readonly TimeSpan twoWeeks = TimeSpan.FromDays(14);
private readonly PruneService _prune;
public PruneCommands(PruneService prune)
{
_prune = prune;
}
//delets her own messages, no perm required //delets her own messages, no perm required
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
@ -31,7 +22,7 @@ namespace NadekoBot.Modules.Administration
{ {
var user = await Context.Guild.GetCurrentUserAsync().ConfigureAwait(false); var user = await Context.Guild.GetCurrentUserAsync().ConfigureAwait(false);
await _prune.PruneWhere((ITextChannel)Context.Channel, 100, (x) => x.Author.Id == user.Id).ConfigureAwait(false); await _service.PruneWhere((ITextChannel)Context.Channel, 100, (x) => x.Author.Id == user.Id).ConfigureAwait(false);
Context.Message.DeleteAfter(3); Context.Message.DeleteAfter(3);
} }
// prune x // prune x
@ -39,7 +30,7 @@ namespace NadekoBot.Modules.Administration
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequireUserPermission(ChannelPermission.ManageMessages)] [RequireUserPermission(ChannelPermission.ManageMessages)]
[RequireBotPermission(GuildPermission.ManageMessages)] [RequireBotPermission(GuildPermission.ManageMessages)]
[Priority(0)] [Priority(1)]
public async Task Prune(int count) public async Task Prune(int count)
{ {
count++; count++;
@ -47,7 +38,7 @@ namespace NadekoBot.Modules.Administration
return; return;
if (count > 1000) if (count > 1000)
count = 1000; count = 1000;
await _prune.PruneWhere((ITextChannel)Context.Channel, count, x => true).ConfigureAwait(false); await _service.PruneWhere((ITextChannel)Context.Channel, count, x => true).ConfigureAwait(false);
} }
//prune @user [x] //prune @user [x]
@ -55,7 +46,7 @@ namespace NadekoBot.Modules.Administration
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequireUserPermission(ChannelPermission.ManageMessages)] [RequireUserPermission(ChannelPermission.ManageMessages)]
[RequireBotPermission(GuildPermission.ManageMessages)] [RequireBotPermission(GuildPermission.ManageMessages)]
[Priority(1)] [Priority(0)]
public async Task Prune(IGuildUser user, int count = 100) public async Task Prune(IGuildUser user, int count = 100)
{ {
if (user.Id == Context.User.Id) if (user.Id == Context.User.Id)
@ -66,7 +57,7 @@ namespace NadekoBot.Modules.Administration
if (count > 1000) if (count > 1000)
count = 1000; count = 1000;
await _prune.PruneWhere((ITextChannel)Context.Channel, count, m => m.Author.Id == user.Id && DateTime.UtcNow - m.CreatedAt < twoWeeks); await _service.PruneWhere((ITextChannel)Context.Channel, count, m => m.Author.Id == user.Id && DateTime.UtcNow - m.CreatedAt < twoWeeks);
} }
} }
} }

View File

@ -1,28 +1,27 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
using NadekoBot.Services.Administration;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Common.Attributes;
using NadekoBot.Modules.Administration.Common;
using NadekoBot.Modules.Administration.Services;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
{ {
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class SlowModeCommands : NadekoSubmodule public class SlowModeCommands : NadekoSubmodule<SlowmodeService>
{ {
private readonly SlowmodeService _service;
private readonly DbService _db; private readonly DbService _db;
public SlowModeCommands(SlowmodeService service, DbService db) public SlowModeCommands(DbService db)
{ {
_service = service;
_db = db; _db = db;
} }
@ -31,9 +30,9 @@ namespace NadekoBot.Modules.Administration
[RequireUserPermission(GuildPermission.ManageMessages)] [RequireUserPermission(GuildPermission.ManageMessages)]
public async Task Slowmode() public async Task Slowmode()
{ {
if (_service.RatelimitingChannels.TryRemove(Context.Channel.Id, out Ratelimiter throwaway)) if (_service.RatelimitingChannels.TryRemove(Context.Channel.Id, out Ratelimiter removed))
{ {
throwaway.CancelSource.Cancel(); removed.CancelSource.Cancel();
await ReplyConfirmLocalized("slowmode_disabled").ConfigureAwait(false); await ReplyConfirmLocalized("slowmode_disabled").ConfigureAwait(false);
} }
} }
@ -67,7 +66,7 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageMessages)] [RequireUserPermission(GuildPermission.ManageMessages)]
[Priority(1)] [Priority(0)]
public async Task SlowmodeWhitelist(IGuildUser user) public async Task SlowmodeWhitelist(IGuildUser user)
{ {
var siu = new SlowmodeIgnoredUser var siu = new SlowmodeIgnoredUser
@ -99,7 +98,7 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageMessages)] [RequireUserPermission(GuildPermission.ManageMessages)]
[Priority(0)] [Priority(1)]
public async Task SlowmodeWhitelist(IRole role) public async Task SlowmodeWhitelist(IRole role)
{ {
var sir = new SlowmodeIgnoredRole var sir = new SlowmodeIgnoredRole

View File

@ -1,16 +1,16 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Common.Attributes;
using NadekoBot.Common.Collections;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
{ {
@ -195,18 +195,23 @@ namespace NadekoBot.Modules.Administration
var roleIds = roles.Select(x => x.RoleId).ToArray(); var roleIds = roles.Select(x => x.RoleId).ToArray();
if (conf.ExclusiveSelfAssignedRoles) if (conf.ExclusiveSelfAssignedRoles)
{ {
var sameRoleId = guildUser.RoleIds.FirstOrDefault(r => roleIds.Contains(r)); var sameRoles = guildUser.RoleIds.Where(r => roleIds.Contains(r));
if (sameRoleId != default(ulong)) foreach (var roleId in sameRoles)
{ {
var sameRole = Context.Guild.GetRole(sameRoleId); var sameRole = Context.Guild.GetRole(roleId);
if (sameRole != null) if (sameRole != null)
{ {
await guildUser.RemoveRoleAsync(sameRole).ConfigureAwait(false); try
await Task.Delay(500).ConfigureAwait(false); {
await guildUser.RemoveRoleAsync(sameRole).ConfigureAwait(false);
await Task.Delay(300).ConfigureAwait(false);
}
catch (Exception ex)
{
_log.Warn(ex);
}
} }
//await ReplyErrorLocalized("self_assign_already_excl", Format.Bold(sameRole?.Name)).ConfigureAwait(false);
//return;
} }
} }
try try

View File

@ -1,6 +1,5 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -12,34 +11,34 @@ using Discord.WebSocket;
using NadekoBot.Services; using NadekoBot.Services;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using NadekoBot.Services.Administration;
using System.Diagnostics; using System.Diagnostics;
using NadekoBot.DataStructures; using NadekoBot.Common.Attributes;
using NadekoBot.Services.Music; using NadekoBot.Modules.Administration.Services;
using NadekoBot.Modules.Music.Services;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
{ {
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class SelfCommands : NadekoSubmodule public class SelfCommands : NadekoSubmodule<SelfService>
{ {
private readonly DbService _db; private readonly DbService _db;
private static readonly object _locker = new object(); private static readonly object _locker = new object();
private readonly SelfService _service;
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
private readonly IImagesService _images; private readonly IImagesService _images;
private readonly MusicService _music; private readonly MusicService _music;
private readonly IBotConfigProvider _bc;
public SelfCommands(DbService db, SelfService service, DiscordSocketClient client, public SelfCommands(DbService db, DiscordSocketClient client,
MusicService music, IImagesService images) MusicService music, IImagesService images, IBotConfigProvider bc)
{ {
_db = db; _db = db;
_service = service;
_client = client; _client = client;
_images = images; _images = images;
_music = music; _music = music;
_bc = bc;
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
@ -100,13 +99,13 @@ namespace NadekoBot.Modules.Administration
} }
else else
{ {
await Context.Channel.SendConfirmAsync("", string.Join("\n--\n", scmds.Select(x => await Context.Channel.SendConfirmAsync("", string.Join("\n", scmds.Select(x =>
{ {
string str = Format.Code(GetText("server")) + ": " + (x.GuildId == null ? "-" : x.GuildName + "/" + x.GuildId); string str = $"```css\n[{GetText("server") + "]: " + (x.GuildId == null ? "-" : x.GuildName + " #" + x.GuildId)}";
str += $@" str += $@"
{Format.Code(GetText("channel"))}: {x.ChannelName}/{x.ChannelId} [{GetText("channel")}]: {x.ChannelName} #{x.ChannelId}
{Format.Code(GetText("command_text"))}: {x.CommandText}"; [{GetText("command_text")}]: {x.CommandText}```";
return str; return str;
})), footer: GetText("page", page + 1)) })), footer: GetText("page", page + 1))
.ConfigureAwait(false); .ConfigureAwait(false);
@ -182,9 +181,11 @@ namespace NadekoBot.Modules.Administration
using (var uow = _db.UnitOfWork) using (var uow = _db.UnitOfWork)
{ {
var config = uow.BotConfig.GetOrCreate(); var config = uow.BotConfig.GetOrCreate();
_service.ForwardDMs = config.ForwardMessages = !config.ForwardMessages; config.ForwardMessages = !config.ForwardMessages;
uow.Complete(); uow.Complete();
} }
_bc.Reload();
if (_service.ForwardDMs) if (_service.ForwardDMs)
await ReplyConfirmLocalized("fwdm_start").ConfigureAwait(false); await ReplyConfirmLocalized("fwdm_start").ConfigureAwait(false);
else else
@ -199,9 +200,11 @@ namespace NadekoBot.Modules.Administration
{ {
var config = uow.BotConfig.GetOrCreate(); var config = uow.BotConfig.GetOrCreate();
lock (_locker) lock (_locker)
_service.ForwardDMsToAllOwners = config.ForwardToAllOwners = !config.ForwardToAllOwners; config.ForwardToAllOwners = !config.ForwardToAllOwners;
uow.Complete(); uow.Complete();
} }
_bc.Reload();
if (_service.ForwardDMsToAllOwners) if (_service.ForwardDMsToAllOwners)
await ReplyConfirmLocalized("fwall_start").ConfigureAwait(false); await ReplyConfirmLocalized("fwall_start").ConfigureAwait(false);
else else
@ -289,7 +292,7 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireUserPermission(GuildPermission.ManageNicknames)] [RequireUserPermission(GuildPermission.ManageNicknames)]
[Priority(1)] [Priority(0)]
public async Task SetNick([Remainder] string newNick = null) public async Task SetNick([Remainder] string newNick = null)
{ {
if (string.IsNullOrWhiteSpace(newNick)) if (string.IsNullOrWhiteSpace(newNick))
@ -303,7 +306,7 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireBotPermission(GuildPermission.ManageNicknames)] [RequireBotPermission(GuildPermission.ManageNicknames)]
[RequireUserPermission(GuildPermission.ManageNicknames)] [RequireUserPermission(GuildPermission.ManageNicknames)]
[Priority(0)] [Priority(1)]
public async Task SetNick(IGuildUser gu, [Remainder] string newNick = null) public async Task SetNick(IGuildUser gu, [Remainder] string newNick = null)
{ {
await gu.ModifyAsync(u => u.Nickname = newNick).ConfigureAwait(false); await gu.ModifyAsync(u => u.Nickname = newNick).ConfigureAwait(false);
@ -406,19 +409,6 @@ namespace NadekoBot.Modules.Administration
await ReplyConfirmLocalized("message_sent").ConfigureAwait(false); await ReplyConfirmLocalized("message_sent").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task Announce([Remainder] string message)
{
var channels = _client.Guilds.Select(g => g.DefaultChannel).ToArray();
if (channels == null)
return;
await Task.WhenAll(channels.Where(c => c != null).Select(c => c.SendConfirmAsync(GetText("message_from_bo", Context.User.ToString()), message)))
.ConfigureAwait(false);
await ReplyConfirmLocalized("message_sent").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[OwnerOnly] [OwnerOnly]
public async Task ReloadImages() public async Task ReloadImages()

View File

@ -1,24 +1,22 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Common.Attributes;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
{ {
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class ServerGreetCommands : NadekoSubmodule public class ServerGreetCommands : NadekoSubmodule<GreetSettingsService>
{ {
private readonly GreetSettingsService _greetService;
private readonly DbService _db; private readonly DbService _db;
public ServerGreetCommands(GreetSettingsService greetService, DbService db) public ServerGreetCommands(DbService db)
{ {
_greetService = greetService;
_db = db; _db = db;
} }
@ -30,7 +28,7 @@ namespace NadekoBot.Modules.Administration
if (timer < 0 || timer > 600) if (timer < 0 || timer > 600)
return; return;
await _greetService.SetGreetDel(Context.Guild.Id, timer).ConfigureAwait(false); await _service.SetGreetDel(Context.Guild.Id, timer).ConfigureAwait(false);
if (timer > 0) if (timer > 0)
await ReplyConfirmLocalized("greetdel_on", timer).ConfigureAwait(false); await ReplyConfirmLocalized("greetdel_on", timer).ConfigureAwait(false);
@ -43,7 +41,7 @@ namespace NadekoBot.Modules.Administration
[RequireUserPermission(GuildPermission.ManageGuild)] [RequireUserPermission(GuildPermission.ManageGuild)]
public async Task Greet() public async Task Greet()
{ {
var enabled = await _greetService.SetGreet(Context.Guild.Id, Context.Channel.Id).ConfigureAwait(false); var enabled = await _service.SetGreet(Context.Guild.Id, Context.Channel.Id).ConfigureAwait(false);
if (enabled) if (enabled)
await ReplyConfirmLocalized("greet_on").ConfigureAwait(false); await ReplyConfirmLocalized("greet_on").ConfigureAwait(false);
@ -67,7 +65,7 @@ namespace NadekoBot.Modules.Administration
return; return;
} }
var sendGreetEnabled = _greetService.SetGreetMessage(Context.Guild.Id, ref text); var sendGreetEnabled = _service.SetGreetMessage(Context.Guild.Id, ref text);
await ReplyConfirmLocalized("greetmsg_new").ConfigureAwait(false); await ReplyConfirmLocalized("greetmsg_new").ConfigureAwait(false);
if (!sendGreetEnabled) if (!sendGreetEnabled)
@ -79,7 +77,7 @@ namespace NadekoBot.Modules.Administration
[RequireUserPermission(GuildPermission.ManageGuild)] [RequireUserPermission(GuildPermission.ManageGuild)]
public async Task GreetDm() public async Task GreetDm()
{ {
var enabled = await _greetService.SetGreetDm(Context.Guild.Id).ConfigureAwait(false); var enabled = await _service.SetGreetDm(Context.Guild.Id).ConfigureAwait(false);
if (enabled) if (enabled)
await ReplyConfirmLocalized("greetdm_on").ConfigureAwait(false); await ReplyConfirmLocalized("greetdm_on").ConfigureAwait(false);
@ -103,7 +101,7 @@ namespace NadekoBot.Modules.Administration
return; return;
} }
var sendGreetEnabled = _greetService.SetGreetDmMessage(Context.Guild.Id, ref text); var sendGreetEnabled = _service.SetGreetDmMessage(Context.Guild.Id, ref text);
await ReplyConfirmLocalized("greetdmmsg_new").ConfigureAwait(false); await ReplyConfirmLocalized("greetdmmsg_new").ConfigureAwait(false);
if (!sendGreetEnabled) if (!sendGreetEnabled)
@ -115,7 +113,7 @@ namespace NadekoBot.Modules.Administration
[RequireUserPermission(GuildPermission.ManageGuild)] [RequireUserPermission(GuildPermission.ManageGuild)]
public async Task Bye() public async Task Bye()
{ {
var enabled = await _greetService.SetBye(Context.Guild.Id, Context.Channel.Id).ConfigureAwait(false); var enabled = await _service.SetBye(Context.Guild.Id, Context.Channel.Id).ConfigureAwait(false);
if (enabled) if (enabled)
await ReplyConfirmLocalized("bye_on").ConfigureAwait(false); await ReplyConfirmLocalized("bye_on").ConfigureAwait(false);
@ -139,7 +137,7 @@ namespace NadekoBot.Modules.Administration
return; return;
} }
var sendByeEnabled = _greetService.SetByeMessage(Context.Guild.Id, ref text); var sendByeEnabled = _service.SetByeMessage(Context.Guild.Id, ref text);
await ReplyConfirmLocalized("byemsg_new").ConfigureAwait(false); await ReplyConfirmLocalized("byemsg_new").ConfigureAwait(false);
if (!sendByeEnabled) if (!sendByeEnabled)
@ -151,7 +149,7 @@ namespace NadekoBot.Modules.Administration
[RequireUserPermission(GuildPermission.ManageGuild)] [RequireUserPermission(GuildPermission.ManageGuild)]
public async Task ByeDel(int timer = 30) public async Task ByeDel(int timer = 30)
{ {
await _greetService.SetByeDel(Context.Guild.Id, timer).ConfigureAwait(false); await _service.SetByeDel(Context.Guild.Id, timer).ConfigureAwait(false);
if (timer > 0) if (timer > 0)
await ReplyConfirmLocalized("byedel_on", timer).ConfigureAwait(false); await ReplyConfirmLocalized("byedel_on", timer).ConfigureAwait(false);

View File

@ -1,17 +1,18 @@
using Discord; using System;
using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Services.Database.Models;
using NLog;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Common.Collections;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
using NLog;
namespace NadekoBot.Services.Administration namespace NadekoBot.Modules.Administration.Services
{ {
public class AdministrationService public class AdministrationService : INService
{ {
public readonly ConcurrentHashSet<ulong> DeleteMessagesOnCommand; public readonly ConcurrentHashSet<ulong> DeleteMessagesOnCommand;
private readonly Logger _log; private readonly Logger _log;

View File

@ -1,15 +1,16 @@
using Discord.WebSocket; using System;
using NadekoBot.Services.Database.Models;
using NLog;
using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.WebSocket;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
using NLog;
namespace NadekoBot.Services.Administration namespace NadekoBot.Modules.Administration.Services
{ {
public class AutoAssignRoleService public class AutoAssignRoleService : INService
{ {
private readonly Logger _log; private readonly Logger _log;
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;

View File

@ -1,16 +1,17 @@
using Discord.WebSocket; using System;
using NadekoBot.Extensions;
using NadekoBot.Services.Database.Models;
using NLog;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.WebSocket;
using NadekoBot.Common.Collections;
using NadekoBot.Extensions;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
using NLog;
namespace NadekoBot.Services.Administration namespace NadekoBot.Modules.Administration.Services
{ {
public class GameVoiceChannelService public class GameVoiceChannelService : INService
{ {
public readonly ConcurrentHashSet<ulong> GameVoiceChannels = new ConcurrentHashSet<ulong>(); public readonly ConcurrentHashSet<ulong> GameVoiceChannels = new ConcurrentHashSet<ulong>();
@ -42,7 +43,7 @@ namespace NadekoBot.Services.Administration
if (gUser == null) if (gUser == null)
return; return;
var game = gUser.Game?.Name.TrimTo(50).ToLowerInvariant(); var game = gUser.Game?.Name?.TrimTo(50).ToLowerInvariant();
if (oldState.VoiceChannel == newState.VoiceChannel || if (oldState.VoiceChannel == newState.VoiceChannel ||
newState.VoiceChannel == null) newState.VoiceChannel == null)

View File

@ -1,17 +1,17 @@
using NadekoBot.Extensions; using System;
using NadekoBot.Services.Database.Models; using System.Collections.Concurrent;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Collections.Concurrent;
using NadekoBot.Services;
using Discord.WebSocket; using Discord.WebSocket;
using NadekoBot.Extensions;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
namespace NadekoBot.Services.Administration namespace NadekoBot.Modules.Administration.Services
{ {
public class GuildTimezoneService public class GuildTimezoneService : INService
{ {
//hack >.> // todo 70 this is a hack >.<
public static ConcurrentDictionary<ulong, GuildTimezoneService> AllServices { get; } = new ConcurrentDictionary<ulong, GuildTimezoneService>(); public static ConcurrentDictionary<ulong, GuildTimezoneService> AllServices { get; } = new ConcurrentDictionary<ulong, GuildTimezoneService>();
private ConcurrentDictionary<ulong, TimeZoneInfo> _timezones; private ConcurrentDictionary<ulong, TimeZoneInfo> _timezones;
private readonly DbService _db; private readonly DbService _db;

View File

@ -1,19 +1,23 @@
using Discord; using System;
using Discord.WebSocket;
using NadekoBot.Extensions;
using NadekoBot.Services.Database.Models;
using NLog;
using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord;
using Discord.WebSocket;
using NadekoBot.Extensions;
using NadekoBot.Modules.Administration.Common;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
using NadekoBot.Services.Impl;
using NLog;
using NadekoBot.Common;
namespace NadekoBot.Services.Administration namespace NadekoBot.Modules.Administration.Services
{ {
public class LogCommandService [NoPublicBot]
public class LogCommandService : INService
{ {
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
@ -66,14 +70,15 @@ namespace NadekoBot.Services.Administration
{ {
var keys = PresenceUpdates.Keys.ToList(); var keys = PresenceUpdates.Keys.ToList();
await Task.WhenAll(keys.Select(async key => await Task.WhenAll(keys.Select(key =>
{ {
if (PresenceUpdates.TryRemove(key, out List<string> messages)) if (PresenceUpdates.TryRemove(key, out var msgs))
try { await key.SendConfirmAsync(GetText(key.Guild, "presence_updates"), string.Join(Environment.NewLine, messages)); } {
catch var title = GetText(key.Guild, "presence_updates");
{ var desc = string.Join(Environment.NewLine, msgs);
// ignored return key.SendConfirmAsync(title, desc.TrimTo(2048));
} }
return Task.CompletedTask;
})); }));
} }
catch (Exception ex) catch (Exception ex)
@ -146,10 +151,13 @@ namespace NadekoBot.Services.Administration
{ {
embed.WithTitle("👥" + GetText(g, "avatar_changed")) embed.WithTitle("👥" + GetText(g, "avatar_changed"))
.WithDescription($"{before.Username}#{before.Discriminator} | {before.Id}") .WithDescription($"{before.Username}#{before.Discriminator} | {before.Id}")
.WithThumbnailUrl(before.GetAvatarUrl())
.WithImageUrl(after.GetAvatarUrl())
.WithFooter(fb => fb.WithText(CurrentTime(g))) .WithFooter(fb => fb.WithText(CurrentTime(g)))
.WithOkColor(); .WithOkColor();
if (Uri.IsWellFormedUriString(before.GetAvatarUrl(), UriKind.Absolute))
embed.WithThumbnailUrl(before.GetAvatarUrl());
if (Uri.IsWellFormedUriString(after.GetAvatarUrl(), UriKind.Absolute))
embed.WithImageUrl(after.GetAvatarUrl());
} }
else else
{ {
@ -369,40 +377,59 @@ namespace NadekoBot.Services.Administration
{ {
try try
{ {
if (!GuildLogSettings.TryGetValue(before.Guild.Id, out LogSetting logSetting) if (!GuildLogSettings.TryGetValue(before.Guild.Id, out LogSetting logSetting))
|| (logSetting.UserUpdatedId == null))
return; return;
ITextChannel logChannel; ITextChannel logChannel;
if ((logChannel = await TryGetLogChannel(before.Guild, logSetting, LogType.UserUpdated)) == null) if (logSetting.UserUpdatedId != null && (logChannel = await TryGetLogChannel(before.Guild, logSetting, LogType.UserUpdated)) != null)
return;
var embed = new EmbedBuilder().WithOkColor().WithFooter(efb => efb.WithText(CurrentTime(before.Guild)))
.WithTitle($"{before.Username}#{before.Discriminator} | {before.Id}");
if (before.Nickname != after.Nickname)
{ {
embed.WithAuthor(eab => eab.WithName("👥 " + GetText(logChannel.Guild, "nick_change"))) var embed = new EmbedBuilder().WithOkColor().WithFooter(efb => efb.WithText(CurrentTime(before.Guild)))
.WithTitle($"{before.Username}#{before.Discriminator} | {before.Id}");
if (before.Nickname != after.Nickname)
{
embed.WithAuthor(eab => eab.WithName("👥 " + GetText(logChannel.Guild, "nick_change")))
.AddField(efb => efb.WithName(GetText(logChannel.Guild, "old_nick")).WithValue($"{before.Nickname}#{before.Discriminator}"))
.AddField(efb => efb.WithName(GetText(logChannel.Guild, "new_nick")).WithValue($"{after.Nickname}#{after.Discriminator}"));
.AddField(efb => efb.WithName(GetText(logChannel.Guild, "old_nick")).WithValue($"{before.Nickname}#{before.Discriminator}")) await logChannel.EmbedAsync(embed).ConfigureAwait(false);
.AddField(efb => efb.WithName(GetText(logChannel.Guild, "new_nick")).WithValue($"{after.Nickname}#{after.Discriminator}")); }
else if (!before.Roles.SequenceEqual(after.Roles))
{
if (before.Roles.Count < after.Roles.Count)
{
var diffRoles = after.Roles.Where(r => !before.Roles.Contains(r)).Select(r => r.Name);
embed.WithAuthor(eab => eab.WithName("⚔ " + GetText(logChannel.Guild, "user_role_add")))
.WithDescription(string.Join(", ", diffRoles).SanitizeMentions());
}
else if (before.Roles.Count > after.Roles.Count)
{
var diffRoles = before.Roles.Where(r => !after.Roles.Contains(r)).Select(r => r.Name);
embed.WithAuthor(eab => eab.WithName("⚔ " + GetText(logChannel.Guild, "user_role_rem")))
.WithDescription(string.Join(", ", diffRoles).SanitizeMentions());
}
await logChannel.EmbedAsync(embed).ConfigureAwait(false);
}
} }
else if (!before.Roles.SequenceEqual(after.Roles))
logChannel = null;
if (logSetting.LogUserPresenceId != null && (logChannel = await TryGetLogChannel(before.Guild, logSetting, LogType.UserPresence)) != null)
{ {
if (before.Roles.Count < after.Roles.Count) if (before.Status != after.Status)
{ {
var diffRoles = after.Roles.Where(r => !before.Roles.Contains(r)).Select(r => r.Name); var str = "🎭" + Format.Code(PrettyCurrentTime(after.Guild)) +
embed.WithAuthor(eab => eab.WithName("⚔ " + GetText(logChannel.Guild, "user_role_add"))) GetText(logChannel.Guild, "user_status_change",
.WithDescription(string.Join(", ", diffRoles).SanitizeMentions()); "👤" + Format.Bold(after.Username),
Format.Bold(after.Status.ToString()));
PresenceUpdates.AddOrUpdate(logChannel,
new List<string>() { str }, (id, list) => { list.Add(str); return list; });
} }
else if (before.Roles.Count > after.Roles.Count) else if (before.Game?.Name != after.Game?.Name)
{ {
var diffRoles = before.Roles.Where(r => !after.Roles.Contains(r)).Select(r => r.Name); var str = $"👾`{PrettyCurrentTime(after.Guild)}`👤__**{after.Username}**__ is now playing **{after.Game?.Name ?? "-"}**.";
embed.WithAuthor(eab => eab.WithName("⚔ " + GetText(logChannel.Guild, "user_role_rem"))) PresenceUpdates.AddOrUpdate(logChannel,
.WithDescription(string.Join(", ", diffRoles).SanitizeMentions()); new List<string>() { str }, (id, list) => { list.Add(str); return list; });
} }
} }
else
return;
await logChannel.EmbedAsync(embed).ConfigureAwait(false);
} }
catch catch
{ {
@ -580,7 +607,7 @@ namespace NadekoBot.Services.Administration
"👤" + Format.Bold(usr.Username + "#" + usr.Discriminator), "👤" + Format.Bold(usr.Username + "#" + usr.Discriminator),
Format.Bold(beforeVch.Name ?? "")); Format.Bold(beforeVch.Name ?? ""));
} }
if (str != null) if (!string.IsNullOrWhiteSpace(str))
PresenceUpdates.AddOrUpdate(logChannel, new List<string>() { str }, (id, list) => { list.Add(str); return list; }); PresenceUpdates.AddOrUpdate(logChannel, new List<string>() { str }, (id, list) => { list.Add(str); return list; });
} }
catch catch
@ -647,14 +674,17 @@ namespace NadekoBot.Services.Administration
ITextChannel logChannel; ITextChannel logChannel;
if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.UserLeft)) == null) if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.UserLeft)) == null)
return; return;
var embed = new EmbedBuilder()
await logChannel.EmbedAsync(new EmbedBuilder()
.WithOkColor() .WithOkColor()
.WithTitle("❌ " + GetText(logChannel.Guild, "user_left")) .WithTitle("❌ " + GetText(logChannel.Guild, "user_left"))
.WithThumbnailUrl(usr.GetAvatarUrl())
.WithDescription(usr.ToString()) .WithDescription(usr.ToString())
.AddField(efb => efb.WithName("Id").WithValue(usr.Id.ToString())) .AddField(efb => efb.WithName("Id").WithValue(usr.Id.ToString()))
.WithFooter(efb => efb.WithText(CurrentTime(usr.Guild)))).ConfigureAwait(false); .WithFooter(efb => efb.WithText(CurrentTime(usr.Guild)));
if (Uri.IsWellFormedUriString(usr.GetAvatarUrl(), UriKind.Absolute))
embed.WithThumbnailUrl(usr.GetAvatarUrl());
await logChannel.EmbedAsync(embed).ConfigureAwait(false);
} }
catch catch
{ {
@ -678,13 +708,17 @@ namespace NadekoBot.Services.Administration
if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.UserJoined)) == null) if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.UserJoined)) == null)
return; return;
await logChannel.EmbedAsync(new EmbedBuilder() var embed = new EmbedBuilder()
.WithOkColor() .WithOkColor()
.WithTitle("✅ " + GetText(logChannel.Guild, "user_joined")) .WithTitle("✅ " + GetText(logChannel.Guild, "user_joined"))
.WithThumbnailUrl(usr.GetAvatarUrl())
.WithDescription($"{usr}") .WithDescription($"{usr}")
.AddField(efb => efb.WithName("Id").WithValue(usr.Id.ToString())) .AddField(efb => efb.WithName("Id").WithValue(usr.Id.ToString()))
.WithFooter(efb => efb.WithText(CurrentTime(usr.Guild)))).ConfigureAwait(false); .WithFooter(efb => efb.WithText(CurrentTime(usr.Guild)));
if (Uri.IsWellFormedUriString(usr.GetAvatarUrl(), UriKind.Absolute))
embed.WithThumbnailUrl(usr.GetAvatarUrl());
await logChannel.EmbedAsync(embed).ConfigureAwait(false);
} }
catch (Exception ex) { _log.Warn(ex); } catch (Exception ex) { _log.Warn(ex); }
}); });
@ -704,14 +738,17 @@ namespace NadekoBot.Services.Administration
ITextChannel logChannel; ITextChannel logChannel;
if ((logChannel = await TryGetLogChannel(guild, logSetting, LogType.UserUnbanned)) == null) if ((logChannel = await TryGetLogChannel(guild, logSetting, LogType.UserUnbanned)) == null)
return; return;
var embed = new EmbedBuilder()
await logChannel.EmbedAsync(new EmbedBuilder()
.WithOkColor() .WithOkColor()
.WithTitle("♻️ " + GetText(logChannel.Guild, "user_unbanned")) .WithTitle("♻️ " + GetText(logChannel.Guild, "user_unbanned"))
.WithThumbnailUrl(usr.GetAvatarUrl())
.WithDescription(usr.ToString()) .WithDescription(usr.ToString())
.AddField(efb => efb.WithName("Id").WithValue(usr.Id.ToString())) .AddField(efb => efb.WithName("Id").WithValue(usr.Id.ToString()))
.WithFooter(efb => efb.WithText(CurrentTime(guild)))).ConfigureAwait(false); .WithFooter(efb => efb.WithText(CurrentTime(guild)));
if (Uri.IsWellFormedUriString(usr.GetAvatarUrl(), UriKind.Absolute))
embed.WithThumbnailUrl(usr.GetAvatarUrl());
await logChannel.EmbedAsync(embed).ConfigureAwait(false);
} }
catch (Exception ex) { _log.Warn(ex); } catch (Exception ex) { _log.Warn(ex); }
}); });
@ -731,13 +768,19 @@ namespace NadekoBot.Services.Administration
ITextChannel logChannel; ITextChannel logChannel;
if ((logChannel = await TryGetLogChannel(guild, logSetting, LogType.UserBanned)) == null) if ((logChannel = await TryGetLogChannel(guild, logSetting, LogType.UserBanned)) == null)
return; return;
await logChannel.EmbedAsync(new EmbedBuilder() var embed = new EmbedBuilder()
.WithOkColor() .WithOkColor()
.WithTitle("🚫 " + GetText(logChannel.Guild, "user_banned")) .WithTitle("🚫 " + GetText(logChannel.Guild, "user_banned"))
.WithThumbnailUrl(usr.GetAvatarUrl())
.WithDescription(usr.ToString()) .WithDescription(usr.ToString())
.AddField(efb => efb.WithName("Id").WithValue(usr.Id.ToString())) .AddField(efb => efb.WithName("Id").WithValue(usr.Id.ToString()))
.WithFooter(efb => efb.WithText(CurrentTime(guild)))).ConfigureAwait(false); .WithFooter(efb => efb.WithText(CurrentTime(guild)));
var avatarUrl = usr.GetAvatarUrl();
if (Uri.IsWellFormedUriString(avatarUrl, UriKind.Absolute))
embed.WithThumbnailUrl(usr.GetAvatarUrl());
await logChannel.EmbedAsync(embed).ConfigureAwait(false);
} }
catch (Exception ex) { _log.Warn(ex); } catch (Exception ex) { _log.Warn(ex); }
}); });

View File

@ -1,17 +1,19 @@
using Discord; using System;
using Discord.WebSocket;
using Microsoft.EntityFrameworkCore;
using NadekoBot.Extensions;
using NadekoBot.Services.Database.Models;
using NLog;
using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord;
using Discord.WebSocket;
using Microsoft.EntityFrameworkCore;
using NadekoBot.Common.Collections;
using NadekoBot.Extensions;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
using NLog;
namespace NadekoBot.Services.Administration namespace NadekoBot.Modules.Administration.Services
{ {
public enum MuteType public enum MuteType
{ {
@ -20,7 +22,7 @@ namespace NadekoBot.Services.Administration
All All
} }
public class MuteService public class MuteService : INService
{ {
public ConcurrentDictionary<ulong, string> GuildMuteRoles { get; } public ConcurrentDictionary<ulong, string> GuildMuteRoles { get; }
public ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>> MutedUsers { get; } public ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>> MutedUsers { get; }
@ -30,7 +32,7 @@ namespace NadekoBot.Services.Administration
public event Action<IGuildUser, MuteType> UserMuted = delegate { }; public event Action<IGuildUser, MuteType> UserMuted = delegate { };
public event Action<IGuildUser, MuteType> UserUnmuted = delegate { }; public event Action<IGuildUser, MuteType> UserUnmuted = delegate { };
private static readonly OverwritePermissions denyOverwrite = new OverwritePermissions(sendMessages: PermValue.Deny, attachFiles: PermValue.Deny); private static readonly OverwritePermissions denyOverwrite = new OverwritePermissions(addReactions: PermValue.Deny, sendMessages: PermValue.Deny, attachFiles: PermValue.Deny);
private readonly Logger _log = LogManager.GetCurrentClassLogger(); private readonly Logger _log = LogManager.GetCurrentClassLogger();
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;

View File

@ -1,15 +1,16 @@
using Discord.WebSocket; using System;
using NadekoBot.DataStructures.Replacements;
using NadekoBot.Services.Database.Models;
using NadekoBot.Services.Music;
using NLog;
using System;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Discord.WebSocket;
using NadekoBot.Common.Replacements;
using NadekoBot.Modules.Music.Services;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
using NLog;
namespace NadekoBot.Services.Administration namespace NadekoBot.Modules.Administration.Services
{ {
public class PlayingRotateService public class PlayingRotateService : INService
{ {
private readonly Timer _t; private readonly Timer _t;
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
@ -17,35 +18,35 @@ namespace NadekoBot.Services.Administration
private readonly Logger _log; private readonly Logger _log;
private readonly Replacer _rep; private readonly Replacer _rep;
private readonly DbService _db; private readonly DbService _db;
public BotConfig BotConfig { get; private set; } //todo load whole botconifg, not just for this service when you have the time private readonly IBotConfigProvider _bcp;
public BotConfig BotConfig => _bcp.BotConfig;
private class TimerState private class TimerState
{ {
public int Index { get; set; } public int Index { get; set; }
} }
public PlayingRotateService(DiscordSocketClient client, BotConfig bc, MusicService music, DbService db) public PlayingRotateService(DiscordSocketClient client, IBotConfigProvider bcp, MusicService music, DbService db)
{ {
_client = client; _client = client;
BotConfig = bc; _bcp = bcp;
_music = music; _music = music;
_db = db; _db = db;
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
_rep = new ReplacementBuilder() _rep = new ReplacementBuilder()
.WithClient(client) .WithClient(client)
.WithStats(client) .WithStats(client)
//.WithMusic(music) .WithMusic(music)
.Build(); .Build();
_t = new Timer(async (objState) => _t = new Timer(async (objState) =>
{ {
try try
{ {
using (var uow = _db.UnitOfWork) bcp.Reload();
{
BotConfig = uow.BotConfig.GetOrCreate(); var state = (TimerState)objState;
}
var state = (TimerState)objState;
if (!BotConfig.RotatingStatuses) if (!BotConfig.RotatingStatuses)
return; return;
if (state.Index >= BotConfig.RotatingStatusMessages.Count) if (state.Index >= BotConfig.RotatingStatusMessages.Count)

View File

@ -1,16 +1,18 @@
using Discord; using System;
using Discord.WebSocket;
using NadekoBot.Services.Database.Models;
using NLog;
using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord;
using Discord.WebSocket;
using NadekoBot.Modules.Administration.Common;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
using NLog;
namespace NadekoBot.Services.Administration namespace NadekoBot.Modules.Administration.Services
{ {
public class ProtectionService public class ProtectionService : INService
{ {
public readonly ConcurrentDictionary<ulong, AntiRaidStats> AntiRaidGuilds = public readonly ConcurrentDictionary<ulong, AntiRaidStats> AntiRaidGuilds =
new ConcurrentDictionary<ulong, AntiRaidStats>(); new ConcurrentDictionary<ulong, AntiRaidStats>();
@ -76,7 +78,7 @@ namespace NadekoBot.Services.Administration
if (spamSettings.UserStats.TryRemove(msg.Author.Id, out stats)) if (spamSettings.UserStats.TryRemove(msg.Author.Id, out stats))
{ {
stats.Dispose(); stats.Dispose();
await PunishUsers(spamSettings.AntiSpamSettings.Action, ProtectionType.Spamming, (IGuildUser)msg.Author) await PunishUsers(spamSettings.AntiSpamSettings.Action, ProtectionType.Spamming, spamSettings.AntiSpamSettings.MuteTime, (IGuildUser)msg.Author)
.ConfigureAwait(false); .ConfigureAwait(false);
} }
} }
@ -109,7 +111,7 @@ namespace NadekoBot.Services.Administration
var users = settings.RaidUsers.ToArray(); var users = settings.RaidUsers.ToArray();
settings.RaidUsers.Clear(); settings.RaidUsers.Clear();
await PunishUsers(settings.AntiRaidSettings.Action, ProtectionType.Raiding, users).ConfigureAwait(false); await PunishUsers(settings.AntiRaidSettings.Action, ProtectionType.Raiding, 0, users).ConfigureAwait(false);
} }
await Task.Delay(1000 * settings.AntiRaidSettings.Seconds).ConfigureAwait(false); await Task.Delay(1000 * settings.AntiRaidSettings.Seconds).ConfigureAwait(false);
@ -127,7 +129,7 @@ namespace NadekoBot.Services.Administration
} }
private async Task PunishUsers(PunishmentAction action, ProtectionType pt, params IGuildUser[] gus) private async Task PunishUsers(PunishmentAction action, ProtectionType pt, int muteTime, params IGuildUser[] gus)
{ {
_log.Info($"[{pt}] - Punishing [{gus.Length}] users with [{action}] in {gus[0].Guild.Name} guild"); _log.Info($"[{pt}] - Punishing [{gus.Length}] users with [{action}] in {gus[0].Guild.Name} guild");
foreach (var gu in gus) foreach (var gu in gus)
@ -137,7 +139,10 @@ namespace NadekoBot.Services.Administration
case PunishmentAction.Mute: case PunishmentAction.Mute:
try try
{ {
await _mute.MuteUser(gu).ConfigureAwait(false); if (muteTime <= 0)
await _mute.MuteUser(gu).ConfigureAwait(false);
else
await _mute.TimedMute(gu, TimeSpan.FromSeconds(muteTime)).ConfigureAwait(false);
} }
catch (Exception ex) { _log.Warn(ex, "I can't apply punishement"); } catch (Exception ex) { _log.Warn(ex, "I can't apply punishement"); }
break; break;

View File

@ -1,15 +1,15 @@
using Discord; using System;
using NadekoBot.Extensions;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord;
using NadekoBot.Common.Collections;
using NadekoBot.Extensions;
using NadekoBot.Services;
namespace NadekoBot.Services.Administration namespace NadekoBot.Modules.Administration.Services
{ {
public class PruneService public class PruneService : INService
{ {
//channelids where prunes are currently occuring //channelids where prunes are currently occuring
private ConcurrentHashSet<ulong> _pruningGuilds = new ConcurrentHashSet<ulong>(); private ConcurrentHashSet<ulong> _pruningGuilds = new ConcurrentHashSet<ulong>();

View File

@ -1,18 +1,20 @@
using Discord.WebSocket; using System;
using NadekoBot.DataStructures.ModuleBehaviors;
using NadekoBot.Extensions;
using NadekoBot.Services.Database.Models;
using NLog;
using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Discord;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord;
using Discord.WebSocket;
using NadekoBot.Common.ModuleBehaviors;
using NadekoBot.Extensions;
using NadekoBot.Modules.Administration.Common;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
using NLog;
namespace NadekoBot.Services.Administration namespace NadekoBot.Modules.Administration.Services
{ {
public class SlowmodeService : IEarlyBlocker public class SlowmodeService : IEarlyBlocker, INService
{ {
public ConcurrentDictionary<ulong, Ratelimiter> RatelimitingChannels = new ConcurrentDictionary<ulong, Ratelimiter>(); public ConcurrentDictionary<ulong, Ratelimiter> RatelimitingChannels = new ConcurrentDictionary<ulong, Ratelimiter>();
public ConcurrentDictionary<ulong, HashSet<ulong>> IgnoredRoles = new ConcurrentDictionary<ulong, HashSet<ulong>>(); public ConcurrentDictionary<ulong, HashSet<ulong>> IgnoredRoles = new ConcurrentDictionary<ulong, HashSet<ulong>>();

View File

@ -1,21 +1,22 @@
using Discord; using System.Collections.Generic;
using NadekoBot.DataStructures;
using NadekoBot.DataStructures.ModuleBehaviors;
using NadekoBot.Extensions;
using NadekoBot.Services.Database.Models;
using NLog;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord;
using Discord.WebSocket; using Discord.WebSocket;
using System.Collections.Generic; using NadekoBot.Common;
using NadekoBot.Common.ModuleBehaviors;
using NadekoBot.Extensions;
using NadekoBot.Services;
using NadekoBot.Services.Impl;
using NLog;
namespace NadekoBot.Services.Administration namespace NadekoBot.Modules.Administration.Services
{ {
public class SelfService : ILateExecutor public class SelfService : ILateExecutor, INService
{ {
public volatile bool ForwardDMs; public bool ForwardDMs => _bc.BotConfig.ForwardMessages;
public volatile bool ForwardDMsToAllOwners; public bool ForwardDMsToAllOwners => _bc.BotConfig.ForwardToAllOwners;
private readonly NadekoBot _bot; private readonly NadekoBot _bot;
private readonly CommandHandler _cmdHandler; private readonly CommandHandler _cmdHandler;
@ -26,9 +27,10 @@ namespace NadekoBot.Services.Administration
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
private readonly IBotCredentials _creds; private readonly IBotCredentials _creds;
private ImmutableArray<AsyncLazy<IDMChannel>> ownerChannels = new ImmutableArray<AsyncLazy<IDMChannel>>(); private ImmutableArray<AsyncLazy<IDMChannel>> ownerChannels = new ImmutableArray<AsyncLazy<IDMChannel>>();
private readonly IBotConfigProvider _bc;
public SelfService(DiscordSocketClient client, NadekoBot bot, CommandHandler cmdHandler, DbService db, public SelfService(DiscordSocketClient client, NadekoBot bot, CommandHandler cmdHandler, DbService db,
BotConfig bc, ILocalization localization, NadekoStrings strings, IBotCredentials creds) IBotConfigProvider bc, ILocalization localization, NadekoStrings strings, IBotCredentials creds)
{ {
_bot = bot; _bot = bot;
_cmdHandler = cmdHandler; _cmdHandler = cmdHandler;
@ -38,16 +40,13 @@ namespace NadekoBot.Services.Administration
_strings = strings; _strings = strings;
_client = client; _client = client;
_creds = creds; _creds = creds;
_bc = bc;
ForwardDMs = bc.ForwardMessages;
ForwardDMsToAllOwners = bc.ForwardToAllOwners;
var _ = Task.Run(async () => var _ = Task.Run(async () =>
{ {
while (!bot.Ready) await bot.Ready.Task.ConfigureAwait(false);
await Task.Delay(1000);
foreach (var cmd in bc.StartupCommands) foreach (var cmd in bc.BotConfig.StartupCommands)
{ {
await cmdHandler.ExecuteExternal(cmd.GuildId, cmd.ChannelId, cmd.CommandText); await cmdHandler.ExecuteExternal(cmd.GuildId, cmd.ChannelId, cmd.CommandText);
await Task.Delay(400).ConfigureAwait(false); await Task.Delay(400).ConfigureAwait(false);
@ -56,8 +55,7 @@ namespace NadekoBot.Services.Administration
var ___ = Task.Run(async () => var ___ = Task.Run(async () =>
{ {
while (!bot.Ready) await bot.Ready.Task.ConfigureAwait(false);
await Task.Delay(1000);
await Task.Delay(5000); await Task.Delay(5000);

View File

@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Discord;
using Microsoft.EntityFrameworkCore;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
namespace NadekoBot.Modules.Administration.Services
{
public class UserPunishService : INService
{
private readonly MuteService _mute;
private readonly DbService _db;
public UserPunishService(MuteService mute, DbService db)
{
_mute = mute;
_db = db;
}
public async Task<PunishmentAction?> Warn(IGuild guild, ulong userId, string modName, string reason)
{
if (string.IsNullOrWhiteSpace(reason))
reason = "-";
var guildId = guild.Id;
var warn = new Warning()
{
UserId = userId,
GuildId = guildId,
Forgiven = false,
Reason = reason,
Moderator = modName,
};
int warnings = 1;
List<WarningPunishment> ps;
using (var uow = _db.UnitOfWork)
{
ps = uow.GuildConfigs.For(guildId, set => set.Include(x => x.WarnPunishments))
.WarnPunishments;
warnings += uow.Warnings
.For(guildId, userId)
.Where(w => !w.Forgiven && w.UserId == userId)
.Count();
uow.Warnings.Add(warn);
uow.Complete();
}
var p = ps.FirstOrDefault(x => x.Count == warnings);
if (p != null)
{
var user = await guild.GetUserAsync(userId);
if (user == null)
return null;
switch (p.Punishment)
{
case PunishmentAction.Mute:
if (p.Time == 0)
await _mute.MuteUser(user).ConfigureAwait(false);
else
await _mute.TimedMute(user, TimeSpan.FromMinutes(p.Time)).ConfigureAwait(false);
break;
case PunishmentAction.Kick:
await user.KickAsync().ConfigureAwait(false);
break;
case PunishmentAction.Ban:
await guild.AddBanAsync(user).ConfigureAwait(false);
break;
case PunishmentAction.Softban:
await guild.AddBanAsync(user, 7).ConfigureAwait(false);
try
{
await guild.RemoveBanAsync(user).ConfigureAwait(false);
}
catch
{
await guild.RemoveBanAsync(user).ConfigureAwait(false);
}
break;
default:
break;
}
return p.Punishment;
}
return null;
}
}
}

Some files were not shown because too many files have changed in this diff Show More