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
- [Help](#help)
- [Administration](#administration)
- [ClashOfClans](#clashofclans)
- [CustomReactions](#customreactions)
- [Gambling](#gambling)
- [Games](#games)
@ -13,6 +12,7 @@ You can support the project on patreon: <https://patreon.com/nadekobot> or paypa
- [Pokemon](#pokemon)
- [Searches](#searches)
- [Utility](#utility)
- [Xp](#xp)
### Administration
@ -90,7 +90,6 @@ Commands and aliases | Description | Usage
`.setgame` | Sets the bots game. **Bot owner only** | `.setgame with snakes`
`.setstream` | Sets the bots stream. First argument is the twitch link, second argument is stream name. **Bot owner only** | `.setstream TWITCHLINK Hello`
`.send` | Sends a message to someone on a different server through the bot. Separate server and channel/user ids with `|` and prefix the channel id with `c:` and the user id with `u:`. **Bot owner only** | `.send serverid|c:channelid message` or `.send serverid|u:userid message`
`.announce` | Sends a message to all servers' default channel that bot is connected to. **Bot owner only** | `.announce Useless spam`
`.reloadimages` | Reloads images bot is using. Safe to use even when bot is being used heavily. **Bot owner only** | `.reloadimages`
`.greetdel` `.grdel` | Sets the time it takes (in seconds) for greet messages to be auto-deleted. Set it to 0 to disable automatic deletion. **Requires ManageServer server permission.** | `.greetdel 0` or `.greetdel 30`
`.greet` | Toggles anouncements on the current channel when someone joins the server. **Requires ManageServer server permission.** | `.greet`
@ -119,21 +118,6 @@ Commands and aliases | Description | Usage
###### [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
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`
`.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`
`.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`
`.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`
@ -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`
`.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`
`.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)
### Games
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`
`.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`
`.rategirl` | Use the universal hot-crazy wife zone matrix to determine the girl's worth. It is everything young men need to know about women. At any moment in time, any woman you have previously located on this chart can vanish from that location and appear anywhere else on the chart. | `.rategirl @SomeGurl`
`.linux` | Prints a customizable Linux interjection | `.linux Spyware Windows`
`.leet` | Converts a text to leetspeak with 6 (1-6) severity levels | `.leet 3 Hello`
`.acrophobia` `.acro` | Starts an Acrophobia game. Second 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`
`.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`
`.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`
`.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`
`.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`
@ -211,7 +200,7 @@ Commands and aliases | Description | Usage
`.typeadd` | Adds a new article to the typing contest. **Bot owner only** | `.typeadd wordswords`
`.typelist` | Lists added typing articles with their IDs. 15 per page. | `.typelist` or `.typelist 3`
`.typedel` | Deletes a typing article given the ID. **Bot owner only** | `.typedel 3`
`.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`
`.tl` | Shows a current trivia leaderboard. | `.tl`
`.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`
`.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`
`.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`
`.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`
`.pause` `.p` | Pauses or Unpauses the song. | `.p`
`.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`
`.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`
`.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`
`.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`
`.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`
`.soundcloudpl` `.scpl` | Queue a Soundcloud playlist using a link. | `.scpl soundcloudseturl`
`.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`
`.boobs` | Real adult content. | `.boobs`
`.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)
@ -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`
`.pokemon` `.poke` | Searches for a pokemon. | `.poke Sylveon`
`.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`
`.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`
`.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`
`.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`
@ -400,7 +393,6 @@ Commands and aliases | Description | Usage
### Utility
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`
`.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`
@ -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`
`.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`
`.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`
`.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`
`.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`
`.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`
@ -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`
`.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`
`.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`
`.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`
###### [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!?
-----
**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?
----------
**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?
----------

View File

@ -16,6 +16,7 @@ If you do not see `credentials.json` you will need to rename `credentials_exampl
"GoogleApiKey": "AIzaSyDSci1sdlWQOWNVj1vlXxxxxxbk0oWMEzM",
"MashapeKey": "4UrKpcWXc2mshS8RKi00000y8Kf5p1Q8kI6jsn32bmd8oVWiY7",
"OsuApiKey": "4c8c8fdff8e1234581725db27fd140a7d93320d6",
"CleverbotApiKey": "",
"PatreonAccessToken": "",
"PatreonCampaignId": "334038",
"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:
`https://discordapp.com/oauth2/authorize?client_id=`**`12345678`**`&scope=bot&permissions=66186303` with your `Client ID`.
- 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`.
- 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.
- 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`
- **LOLAPIKey**
- **LoLApiKey**
- Required for all League of Legends commands.
- You can get this key [here](http://api.champion.gg/)
- **OsuAPIKey**
- You can get this key [here.](http://api.champion.gg/)
- **OsuApiKey**
- 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**
- For Patreon creators only.
- **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 **Write Changes**
![nadekodb](https://cdn.discordapp.com/attachments/251504306010849280/254067055240806400/nadekodb.gif)
and that will save all the changes.
## 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
![nadekodb](https://cdn.discordapp.com/attachments/251504306010849280/254067055240806400/nadekodb.gif)
[Google Console]: https://console.developers.google.com
[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
===================
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?
------------------------------
@ -15,11 +15,14 @@ With the permissions system it possible to restrict who can skip the current son
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.
![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).
@ -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!).
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.
@ -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
2. `.sc !!nowplaying enable`
2. `.sc .nowplaying enable`
* Enables the "nowplaying" command for everyone
3. `.sc !!listqueue enable`
3. `.sc .listqueue enable`
* 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
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/)
@ -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.
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

View File

@ -6,17 +6,17 @@ Prerequisites
*Clone the repo*
`git clone -b 1.4 https://github.com/Kwoth/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*
`dotnet restore`
`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`
`dotnet restore`
`dotnet run -c Release`
[.netcore]: https://www.microsoft.com/net/download/core#/sdk
[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 libsodium
brew install tmux
brew install python
brew install youtube-dl
```
#### Installing .NET Core SDK

View File

@ -10,21 +10,21 @@
#### 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.
- Delete your container **docker rm nadeko**.
- Create a new container **docker create --name=nadeko -v /nadeko/:/root/nadeko uirel/nadeko:1.4**.
- Start the container **docker start nadeko** wait for it to complain about lacking credentials.
- Stop the container **docker stop nadeko** open the nadeko folder and replace the credentials, database and other files with your copies.
- Restart the container **docker start nadeko**.
- Delete your container `docker rm nadeko`.
- Create a new container `docker create --name=nadeko -v /nadeko/:/root/nadeko uirel/nadeko:1.4`.
- Start the container 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.
- Restart the container `docker start nadeko`.
#### 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 `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)
- Backup the `NadekoBot.db` from `NadekoBot/src/NadekoBot/bin/Release/netcoreapp1.0/data`.
- 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).
- 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.
- 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)
- *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
- 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.*
- 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/).*

View File

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

View File

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

View File

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

View File

@ -1,8 +1,8 @@
using Discord.Commands;
using NadekoBot.Services;
using System.Runtime.CompilerServices;
using System.Runtime.CompilerServices;
using Discord.Commands;
using NadekoBot.Services.Impl;
namespace NadekoBot.Attributes
namespace NadekoBot.Common.Attributes
{
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)]
sealed class NadekoModuleAttribute : GroupAttribute

View File

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

View File

@ -1,8 +1,8 @@
using Discord.Commands;
using NadekoBot.Services;
using System.Runtime.CompilerServices;
using System.Runtime.CompilerServices;
using Discord.Commands;
using NadekoBot.Services.Impl;
namespace NadekoBot.Attributes
namespace NadekoBot.Common.Attributes
{
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 NLog;
namespace NadekoBot.DataStructures
namespace NadekoBot.Common
{
public class CREmbed
{
@ -31,19 +33,31 @@ namespace NadekoBot.DataStructures
public EmbedBuilder ToEmbed()
{
var embed = new EmbedBuilder()
.WithTitle(Title)
.WithDescription(Description)
.WithColor(new Discord.Color(Color));
var embed = new EmbedBuilder();
if (!string.IsNullOrWhiteSpace(Title))
embed.WithTitle(Title);
if (!string.IsNullOrWhiteSpace(Description))
embed.WithDescription(Description);
embed.WithColor(new Discord.Color(Color));
if (Footer != null)
embed.WithFooter(efb => efb.WithIconUrl(Footer.IconUrl).WithText(Footer.Text));
embed.WithThumbnailUrl(Thumbnail)
.WithImageUrl(Image);
embed.WithFooter(efb =>
{
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)
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;
@ -58,7 +72,13 @@ namespace NadekoBot.DataStructures
try
{
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)
return false;

View File

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

View File

@ -2,9 +2,8 @@
using System.Collections;
using System.Collections.Generic;
namespace NadekoBot.DataStructures
namespace NadekoBot.Common.Collections
{
public static class DisposableReadOnlyListExtensions
{
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.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; }
private readonly object _locker = new object();

View File

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

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
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,16 +1,15 @@
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Extensions;
using NadekoBot.Services;
using NadekoBot.Services.Administration;
using NadekoBot.Services.Music;
using System;
using System;
using System.Collections.Concurrent;
using System.Linq;
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
{

View File

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

View File

@ -1,22 +1,19 @@
using Discord.Commands;
using Discord.WebSocket;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System;
using System.Threading.Tasks;
using Discord.Commands;
using Discord.WebSocket;
namespace NadekoBot.DataStructures
namespace NadekoBot.Common
{
public class Shard0Precondition : PreconditionAttribute
{
public override Task<PreconditionResult> CheckPermissions(ICommandContext context, CommandInfo command, IServiceProvider services)
{
var c = (DiscordSocketClient)context.Client;
if (c.ShardId == 0)
return Task.FromResult(PreconditionResult.FromSuccess());
else
if (c.ShardId != 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.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System;
using Discord;
namespace NadekoBot.DataStructures.ShardCom
namespace NadekoBot.Common.ShardCom
{
public class ShardComMessage
{

View File

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

View File

@ -1,11 +1,11 @@
using Newtonsoft.Json;
using System;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace NadekoBot.DataStructures.ShardCom
namespace NadekoBot.Common.ShardCom
{
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 NadekoBot.Services;
using NadekoBot.Services.CustomReactions;
using System;
using System;
using System.Linq;
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
{
private readonly CommandService _cmds;
private readonly CommandHandler _cmdHandler;
public CommandTypeReader(CommandService cmds, CommandHandler cmdHandler)
{
_cmds = cmds;
_cmdHandler = cmdHandler;
}
public override Task<TypeReaderResult> Read(ICommandContext context, string input, IServiceProvider _)
public override Task<TypeReaderResult> Read(ICommandContext context, string input, IServiceProvider services)
{
var _cmds = ((INServiceProvider)services).GetService<CommandService>();
var _cmdHandler = ((INServiceProvider)services).GetService<CommandHandler>();
input = input.ToUpperInvariant();
var prefix = _cmdHandler.GetPrefix(context.Guild);
if (!input.StartsWith(prefix.ToUpperInvariant()))
@ -38,17 +31,12 @@ namespace NadekoBot.TypeReaders
public class CommandOrCrTypeReader : CommandTypeReader
{
private readonly CustomReactionsService _crs;
public CommandOrCrTypeReader(CustomReactionsService crs, CommandService cmds, CommandHandler cmdHandler) : base(cmds, cmdHandler)
{
_crs = crs;
}
public override async Task<TypeReaderResult> Read(ICommandContext context, string input, IServiceProvider _)
public override async Task<TypeReaderResult> Read(ICommandContext context, string input, IServiceProvider services)
{
input = input.ToUpperInvariant();
var _crs = ((INServiceProvider)services).GetService<CustomReactionsService>();
if (_crs.GlobalReactions.Any(x => x.Trigger.ToUpperInvariant() == 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)
{
return TypeReaderResult.FromSuccess(new CommandOrCrInfo(((CommandInfo)cmd.Values.First().Value).Name));

View File

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

View File

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

View File

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

View File

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

View File

@ -1,9 +1,9 @@
using Discord.Commands;
using System;
using System.Threading.Tasks;
using NadekoBot.Modules.Permissions;
using System;
using Discord.Commands;
using NadekoBot.Common.TypeReaders.Models;
namespace NadekoBot.TypeReaders
namespace NadekoBot.Common.TypeReaders
{
/// <summary>
/// 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 System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{

View File

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

View File

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

View File

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.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>("MuteTime");
b.HasKey("Id");
b.HasIndex("GuildConfigId")
@ -181,6 +183,14 @@ namespace NadekoBot.Migrations
b.Property<int>("TriviaCurrencyReward");
b.Property<int>("XpMinutesTimeout")
.ValueGeneratedOnAdd()
.HasDefaultValue(5);
b.Property<int>("XpPerMessage")
.ValueGeneratedOnAdd()
.HasDefaultValue(3);
b.HasKey("Id");
b.ToTable("BotConfig");
@ -236,6 +246,63 @@ namespace NadekoBot.Migrations
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 =>
{
b.Property<int>("Id")
@ -361,6 +428,8 @@ namespace NadekoBot.Migrations
b.Property<bool>("AutoDeleteTrigger");
b.Property<bool>("ContainsAnywhere");
b.Property<DateTime?>("DateAdded");
b.Property<bool>("DmResponse");
@ -387,10 +456,20 @@ namespace NadekoBot.Migrations
b.Property<string>("AvatarId");
b.Property<int?>("ClubId");
b.Property<DateTime?>("DateAdded");
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<string>("Username");
@ -399,6 +478,8 @@ namespace NadekoBot.Migrations
b.HasAlternateKey("UserId");
b.HasIndex("ClubId");
b.ToTable("DiscordUser");
});
@ -441,6 +522,26 @@ namespace NadekoBot.Migrations
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 =>
{
b.Property<int>("Id")
@ -800,6 +901,24 @@ namespace NadekoBot.Migrations
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 =>
{
b.Property<int>("Id")
@ -1126,6 +1245,71 @@ namespace NadekoBot.Migrations
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 =>
{
b.Property<int>("Id")
@ -1165,6 +1349,35 @@ namespace NadekoBot.Migrations
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 =>
{
b.Property<int>("Id")
@ -1212,6 +1425,28 @@ namespace NadekoBot.Migrations
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 =>
{
b.Property<int>("Id")
@ -1284,6 +1519,51 @@ namespace NadekoBot.Migrations
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 =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig")
@ -1333,6 +1613,40 @@ namespace NadekoBot.Migrations
.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 =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
@ -1354,6 +1668,13 @@ namespace NadekoBot.Migrations
.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 =>
{
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
@ -1361,6 +1682,13 @@ namespace NadekoBot.Migrations
.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 =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
@ -1439,6 +1767,13 @@ namespace NadekoBot.Migrations
.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 =>
{
b.HasOne("NadekoBot.Services.Database.Models.Permission", "Next")
@ -1510,6 +1845,28 @@ namespace NadekoBot.Migrations
.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 =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
@ -1540,6 +1897,13 @@ namespace NadekoBot.Migrations
.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 =>
{
b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "New")
@ -1562,6 +1926,21 @@ namespace NadekoBot.Migrations
.WithMany("WarnPunishments")
.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.Linq;
using System.Threading.Tasks;
using NadekoBot.Common.Attributes;
using NadekoBot.Services;
using NadekoBot.Attributes;
using NadekoBot.Modules.Administration.Services;
using NadekoBot.Services.Database.Models;
using NadekoBot.Services.Administration;
namespace NadekoBot.Modules.Administration
{
public partial class Administration : NadekoTopLevelModule
public partial class Administration : NadekoTopLevelModule<AdministrationService>
{
private IGuild _nadekoSupportServer;
private readonly DbService _db;
private readonly AdministrationService _admin;
public Administration(DbService db, AdministrationService admin)
public Administration(DbService db)
{
_db = db;
_admin = admin;
}
[NadekoCommand, Usage, Description, Aliases]
@ -40,12 +38,12 @@ namespace NadekoBot.Modules.Administration
}
if (enabled)
{
_admin.DeleteMessagesOnCommand.Add(Context.Guild.Id);
_service.DeleteMessagesOnCommand.Add(Context.Guild.Id);
await ReplyConfirmLocalized("delmsg_on").ConfigureAwait(false);
}
else
{
_admin.DeleteMessagesOnCommand.TryRemove(Context.Guild.Id);
_service.DeleteMessagesOnCommand.TryRemove(Context.Guild.Id);
await ReplyConfirmLocalized("delmsg_off").ConfigureAwait(false);
}
}
@ -58,7 +56,7 @@ namespace NadekoBot.Modules.Administration
{
var guser = (IGuildUser)Context.User;
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;
try
{

View File

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

View File

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

View File

@ -1,6 +1,6 @@
using System;
namespace NadekoBot.Modules.Administration.Commands.Migration
namespace NadekoBot.Modules.Administration.Common.Migration
{
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 System.Collections.Concurrent;
namespace NadekoBot.Services.Administration
namespace NadekoBot.Modules.Administration.Common
{
public enum ProtectionType
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,27 +4,28 @@ using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
using Newtonsoft.Json;
using NadekoBot.Modules.Administration.Commands.Migration;
using System.Collections.Concurrent;
using NadekoBot.Extensions;
using NadekoBot.Services.Database;
using Microsoft.Data.Sqlite;
using NadekoBot.Common.Attributes;
using NadekoBot.Common.Collections;
using NadekoBot.Modules.Administration.Common.Migration;
namespace NadekoBot.Modules.Administration
{
public partial class Administration
{
[Group]
public class Migration : NadekoSubmodule
public class MigrationCommands : NadekoSubmodule
{
private const int CURRENT_VERSION = 1;
private readonly DbService _db;
public Migration(DbService db)
public MigrationCommands(DbService db)
{
_db = db;
}
@ -211,10 +212,10 @@ namespace NadekoBot.Modules.Administration
type = FollowedStream.FollowedStreamType.Twitch;
break;
case StreamNotificationConfig0_9.StreamType.Beam:
type = FollowedStream.FollowedStreamType.Beam;
type = FollowedStream.FollowedStreamType.Mixer;
break;
case StreamNotificationConfig0_9.StreamType.Hitbox:
type = FollowedStream.FollowedStreamType.Hitbox;
type = FollowedStream.FollowedStreamType.Smashcast;
break;
default:
break;
@ -351,54 +352,6 @@ namespace NadekoBot.Modules.Administration
oldConfig.RotatingStatuses.ForEach(i => messages.Add(new PlayingStatus { Status = i }));
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
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 }));

View File

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

View File

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

View File

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

View File

@ -1,42 +1,50 @@
using Discord;
using Discord.Commands;
using Microsoft.EntityFrameworkCore;
using NadekoBot.Attributes;
using NadekoBot.Extensions;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
using System;
using System.Linq;
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
{
public partial class Administration
{
[Group]
public class ProtectionCommands : NadekoSubmodule
public class ProtectionCommands : NadekoSubmodule<ProtectionService>
{
private readonly ProtectionService _service;
private readonly MuteService _mute;
private readonly DbService _db;
public ProtectionCommands(ProtectionService service, MuteService mute, DbService db)
public ProtectionCommands(MuteService mute, DbService db)
{
_service = service;
_mute = mute;
_db = db;
}
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))
ignoredString = "none";
string add = "";
if (settings.Action == PunishmentAction.Mute
&& settings.MuteTime > 0)
{
add = " (" + settings.MuteTime + "s)";
}
return GetText("spam_stats",
Format.Bold(stats.AntiSpamSettings.MessageThreshold.ToString()),
Format.Bold(stats.AntiSpamSettings.Action.ToString()),
Format.Bold(settings.MessageThreshold.ToString()),
Format.Bold(settings.Action.ToString() + add),
ignoredString);
}
@ -62,8 +70,7 @@ namespace NadekoBot.Modules.Administration
return;
}
AntiRaidStats throwaway;
if (_service.AntiRaidGuilds.TryRemove(Context.Guild.Id, out throwaway))
if (_service.AntiRaidGuilds.TryRemove(Context.Guild.Id, out _))
{
using (var uow = _db.UnitOfWork)
{
@ -114,15 +121,12 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[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)
return;
AntiSpamStats throwaway;
if (_service.AntiSpamGuilds.TryRemove(Context.Guild.Id, out throwaway))
if (_service.AntiSpamGuilds.TryRemove(Context.Guild.Id, out var removed))
{
throwaway.UserStats.ForEach(x => x.Value.Dispose());
removed.UserStats.ForEach(x => x.Value.Dispose());
using (var uow = _db.UnitOfWork)
{
var gc = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.AntiSpamSetting)
@ -135,6 +139,21 @@ namespace NadekoBot.Modules.Administration
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
{
await _mute.GetMuteRole(Context.Guild).ConfigureAwait(false);
@ -152,10 +171,15 @@ namespace NadekoBot.Modules.Administration
{
Action = action,
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)
{

View File

@ -1,28 +1,19 @@
using Discord;
using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.Extensions;
using NadekoBot.Services.Administration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NadekoBot.Common.Attributes;
using NadekoBot.Modules.Administration.Services;
namespace NadekoBot.Modules.Administration
{
public partial class Administration
{
[Group]
public class PruneCommands : ModuleBase
public class PruneCommands : NadekoSubmodule<PruneService>
{
private readonly TimeSpan twoWeeks = TimeSpan.FromDays(14);
private readonly PruneService _prune;
public PruneCommands(PruneService prune)
{
_prune = prune;
}
//delets her own messages, no perm required
[NadekoCommand, Usage, Description, Aliases]
@ -31,7 +22,7 @@ namespace NadekoBot.Modules.Administration
{
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);
}
// prune x
@ -39,7 +30,7 @@ namespace NadekoBot.Modules.Administration
[RequireContext(ContextType.Guild)]
[RequireUserPermission(ChannelPermission.ManageMessages)]
[RequireBotPermission(GuildPermission.ManageMessages)]
[Priority(0)]
[Priority(1)]
public async Task Prune(int count)
{
count++;
@ -47,7 +38,7 @@ namespace NadekoBot.Modules.Administration
return;
if (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]
@ -55,7 +46,7 @@ namespace NadekoBot.Modules.Administration
[RequireContext(ContextType.Guild)]
[RequireUserPermission(ChannelPermission.ManageMessages)]
[RequireBotPermission(GuildPermission.ManageMessages)]
[Priority(1)]
[Priority(0)]
public async Task Prune(IGuildUser user, int count = 100)
{
if (user.Id == Context.User.Id)
@ -66,7 +57,7 @@ namespace NadekoBot.Modules.Administration
if (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.Commands;
using Microsoft.EntityFrameworkCore;
using NadekoBot.Attributes;
using NadekoBot.Extensions;
using NadekoBot.Services;
using NadekoBot.Services.Administration;
using NadekoBot.Services.Database.Models;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using NadekoBot.Common.Attributes;
using NadekoBot.Modules.Administration.Common;
using NadekoBot.Modules.Administration.Services;
namespace NadekoBot.Modules.Administration
{
public partial class Administration
{
[Group]
public class SlowModeCommands : NadekoSubmodule
public class SlowModeCommands : NadekoSubmodule<SlowmodeService>
{
private readonly SlowmodeService _service;
private readonly DbService _db;
public SlowModeCommands(SlowmodeService service, DbService db)
public SlowModeCommands(DbService db)
{
_service = service;
_db = db;
}
@ -31,9 +30,9 @@ namespace NadekoBot.Modules.Administration
[RequireUserPermission(GuildPermission.ManageMessages)]
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);
}
}
@ -67,7 +66,7 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageMessages)]
[Priority(1)]
[Priority(0)]
public async Task SlowmodeWhitelist(IGuildUser user)
{
var siu = new SlowmodeIgnoredUser
@ -99,7 +98,7 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageMessages)]
[Priority(0)]
[Priority(1)]
public async Task SlowmodeWhitelist(IRole role)
{
var sir = new SlowmodeIgnoredRole

View File

@ -1,16 +1,16 @@
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Attributes;
using NadekoBot.Extensions;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NadekoBot.Common.Attributes;
using NadekoBot.Common.Collections;
namespace NadekoBot.Modules.Administration
{
@ -195,18 +195,23 @@ namespace NadekoBot.Modules.Administration
var roleIds = roles.Select(x => x.RoleId).ToArray();
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)
{
await guildUser.RemoveRoleAsync(sameRole).ConfigureAwait(false);
await Task.Delay(500).ConfigureAwait(false);
try
{
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

View File

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

View File

@ -1,24 +1,22 @@
using Discord;
using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.Extensions;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
using System.Threading.Tasks;
using NadekoBot.Common.Attributes;
namespace NadekoBot.Modules.Administration
{
public partial class Administration
{
[Group]
public class ServerGreetCommands : NadekoSubmodule
public class ServerGreetCommands : NadekoSubmodule<GreetSettingsService>
{
private readonly GreetSettingsService _greetService;
private readonly DbService _db;
public ServerGreetCommands(GreetSettingsService greetService, DbService db)
public ServerGreetCommands(DbService db)
{
_greetService = greetService;
_db = db;
}
@ -30,7 +28,7 @@ namespace NadekoBot.Modules.Administration
if (timer < 0 || timer > 600)
return;
await _greetService.SetGreetDel(Context.Guild.Id, timer).ConfigureAwait(false);
await _service.SetGreetDel(Context.Guild.Id, timer).ConfigureAwait(false);
if (timer > 0)
await ReplyConfirmLocalized("greetdel_on", timer).ConfigureAwait(false);
@ -43,7 +41,7 @@ namespace NadekoBot.Modules.Administration
[RequireUserPermission(GuildPermission.ManageGuild)]
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)
await ReplyConfirmLocalized("greet_on").ConfigureAwait(false);
@ -67,7 +65,7 @@ namespace NadekoBot.Modules.Administration
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);
if (!sendGreetEnabled)
@ -79,7 +77,7 @@ namespace NadekoBot.Modules.Administration
[RequireUserPermission(GuildPermission.ManageGuild)]
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)
await ReplyConfirmLocalized("greetdm_on").ConfigureAwait(false);
@ -103,7 +101,7 @@ namespace NadekoBot.Modules.Administration
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);
if (!sendGreetEnabled)
@ -115,7 +113,7 @@ namespace NadekoBot.Modules.Administration
[RequireUserPermission(GuildPermission.ManageGuild)]
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)
await ReplyConfirmLocalized("bye_on").ConfigureAwait(false);
@ -139,7 +137,7 @@ namespace NadekoBot.Modules.Administration
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);
if (!sendByeEnabled)
@ -151,7 +149,7 @@ namespace NadekoBot.Modules.Administration
[RequireUserPermission(GuildPermission.ManageGuild)]
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)
await ReplyConfirmLocalized("byedel_on", timer).ConfigureAwait(false);

View File

@ -1,17 +1,18 @@
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Services.Database.Models;
using NLog;
using System;
using System.Collections.Concurrent;
using System;
using System.Collections.Generic;
using System.Linq;
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;
private readonly Logger _log;

View File

@ -1,15 +1,16 @@
using Discord.WebSocket;
using NadekoBot.Services.Database.Models;
using NLog;
using System;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
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 DiscordSocketClient _client;

View File

@ -1,16 +1,17 @@
using Discord.WebSocket;
using NadekoBot.Extensions;
using NadekoBot.Services.Database.Models;
using NLog;
using System;
using System.Collections.Concurrent;
using System;
using System.Collections.Generic;
using System.Linq;
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>();
@ -42,7 +43,7 @@ namespace NadekoBot.Services.Administration
if (gUser == null)
return;
var game = gUser.Game?.Name.TrimTo(50).ToLowerInvariant();
var game = gUser.Game?.Name?.TrimTo(50).ToLowerInvariant();
if (oldState.VoiceChannel == newState.VoiceChannel ||
newState.VoiceChannel == null)

View File

@ -1,17 +1,17 @@
using NadekoBot.Extensions;
using NadekoBot.Services.Database.Models;
using System;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Collections.Concurrent;
using NadekoBot.Services;
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>();
private ConcurrentDictionary<ulong, TimeZoneInfo> _timezones;
private readonly DbService _db;

View File

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

View File

@ -1,17 +1,19 @@
using Discord;
using Discord.WebSocket;
using Microsoft.EntityFrameworkCore;
using NadekoBot.Extensions;
using NadekoBot.Services.Database.Models;
using NLog;
using System;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
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
{
@ -20,7 +22,7 @@ namespace NadekoBot.Services.Administration
All
}
public class MuteService
public class MuteService : INService
{
public ConcurrentDictionary<ulong, string> GuildMuteRoles { 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> 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 DiscordSocketClient _client;

View File

@ -1,15 +1,16 @@
using Discord.WebSocket;
using NadekoBot.DataStructures.Replacements;
using NadekoBot.Services.Database.Models;
using NadekoBot.Services.Music;
using NLog;
using System;
using System;
using System.Linq;
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 DiscordSocketClient _client;
@ -17,35 +18,35 @@ namespace NadekoBot.Services.Administration
private readonly Logger _log;
private readonly Replacer _rep;
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
{
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;
BotConfig = bc;
_bcp = bcp;
_music = music;
_db = db;
_log = LogManager.GetCurrentClassLogger();
_rep = new ReplacementBuilder()
.WithClient(client)
.WithStats(client)
//.WithMusic(music)
.WithMusic(music)
.Build();
_t = new Timer(async (objState) =>
{
try
{
using (var uow = _db.UnitOfWork)
{
BotConfig = uow.BotConfig.GetOrCreate();
}
var state = (TimerState)objState;
bcp.Reload();
var state = (TimerState)objState;
if (!BotConfig.RotatingStatuses)
return;
if (state.Index >= BotConfig.RotatingStatusMessages.Count)

View File

@ -1,16 +1,18 @@
using Discord;
using Discord.WebSocket;
using NadekoBot.Services.Database.Models;
using NLog;
using System;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
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 =
new ConcurrentDictionary<ulong, AntiRaidStats>();
@ -76,7 +78,7 @@ namespace NadekoBot.Services.Administration
if (spamSettings.UserStats.TryRemove(msg.Author.Id, out stats))
{
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);
}
}
@ -109,7 +111,7 @@ namespace NadekoBot.Services.Administration
var users = settings.RaidUsers.ToArray();
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);
@ -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");
foreach (var gu in gus)
@ -137,7 +139,10 @@ namespace NadekoBot.Services.Administration
case PunishmentAction.Mute:
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"); }
break;

View File

@ -1,15 +1,15 @@
using Discord;
using NadekoBot.Extensions;
using System;
using System.Collections.Concurrent;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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
private ConcurrentHashSet<ulong> _pruningGuilds = new ConcurrentHashSet<ulong>();

View File

@ -1,18 +1,20 @@
using Discord.WebSocket;
using NadekoBot.DataStructures.ModuleBehaviors;
using NadekoBot.Extensions;
using NadekoBot.Services.Database.Models;
using NLog;
using System;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using Discord;
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, HashSet<ulong>> IgnoredRoles = new ConcurrentDictionary<ulong, HashSet<ulong>>();

View File

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