mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2026-05-11 10:45:59 -04:00
Compare commits
740 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9752a9c719 | |||
| 7973babe4b | |||
| 78e4b578e2 | |||
| 8eb8848898 | |||
| aac1460240 | |||
| dde5582669 | |||
| aa854cf1f9 | |||
| 2bd05a5a04 | |||
| 3a8da1f82b | |||
| 811634a2b0 | |||
| 2512320b30 | |||
| db03faf042 | |||
| 701259158f | |||
| a5efdc6492 | |||
| 38b15ded87 | |||
| 351749dff6 | |||
| 2d9912cea7 | |||
| c4ab34a049 | |||
| 985e7b3c6d | |||
| 7546c50226 | |||
| 6435f6b882 | |||
| bbccb671b8 | |||
| 8abb24bc01 | |||
| 419008f644 | |||
| d17c2430d7 | |||
| ca533f8937 | |||
| 9d22d5b7b5 | |||
| 2846dce6ea | |||
| 9973b2e3b8 | |||
| d008a2559a | |||
| 7f3a0b8a88 | |||
| d0fca373ba | |||
| 451c4c9d54 | |||
| a59002275d | |||
| 99bbde7be9 | |||
| 92dbd14006 | |||
| 6e9243f6e9 | |||
| 8bba860f85 | |||
| d2d26835c3 | |||
| aff62a8006 | |||
| b5fd28ef7c | |||
| c510ebe5e5 | |||
| 5ba95090d9 | |||
| ad51fa830b | |||
| 1ba922eba2 | |||
| 9588a5740c | |||
| 7cd765d548 | |||
| 6022c0f7d7 | |||
| 0548744e94 | |||
| 8b2d115335 | |||
| 094735566d | |||
| f7b1f9f0dc | |||
| ce25011f0d | |||
| f85034eb27 | |||
| 849755ecd2 | |||
| 9217275908 | |||
| 9e13ca45e6 | |||
| 46c38a28eb | |||
| 76bbcf2f8c | |||
| ee7e8aa782 | |||
| fd0abc250d | |||
| 847f9fc8d1 | |||
| 046e98565e | |||
| 71eddc89ea | |||
| 9730a424ec | |||
| 7b260cdafc | |||
| 4369095a51 | |||
| 1c706e8c45 | |||
| 91029b73e5 | |||
| de4b42a11e | |||
| 03230b6386 | |||
| 4dbf2796c0 | |||
| 03892f5ef1 | |||
| fdf3f86ab0 | |||
| 7b15ad5989 | |||
| 443f2ca556 | |||
| fa692ccc0b | |||
| 0c3d8af8f4 | |||
| 3a20c11331 | |||
| aa8c9c350e | |||
| 139329233a | |||
| d79996aeea | |||
| fb839084fe | |||
| dea9dde637 | |||
| ebc657dcc6 | |||
| 80506856fb | |||
| 93a0e45c34 | |||
| 3cb2b95121 | |||
| a04869ab27 | |||
| c69b1185d3 | |||
| ad7466a026 | |||
| 54dad2a604 | |||
| d5899fae83 | |||
| 5d44bfabed | |||
| b6c8be5f43 | |||
| b2abfc5710 | |||
| a9b328ff3c | |||
| 0870403299 | |||
| f07b78bd0d | |||
| b2497386bb | |||
| f8558b98c1 | |||
| 84ac5f3952 | |||
| 404800c556 | |||
| 415385b747 | |||
| f7dbaca340 | |||
| 32b4c6ce86 | |||
| a3c36d4bde | |||
| fc4703ef80 | |||
| a301b2c758 | |||
| e27682abd3 | |||
| df922a0e3e | |||
| 51c83d958c | |||
| 17139ce439 | |||
| 61652a0306 | |||
| 113b97b9c9 | |||
| 2784730f7f | |||
| 1a9216b522 | |||
| 08fc732b7b | |||
| 54baf687ec | |||
| 8096cd803e | |||
| 27b0d606c8 | |||
| af220e497f | |||
| 892b2487f5 | |||
| 7971c02dc5 | |||
| c1d8272b49 | |||
| bce5dd26f3 | |||
| 04e97f3516 | |||
| 7eed033c9e | |||
| a2fe1a8757 | |||
| 9ee860c3f0 | |||
| 1dbe9537e9 | |||
| 775f4ce69a | |||
| e83beeef34 | |||
| e77cfff892 | |||
| 9495432b8f | |||
| d71c334a34 | |||
| aa8cc90ad0 | |||
| 589041556e | |||
| 85354f2722 | |||
| c0c5535005 | |||
| e126cf9f4e | |||
| c2d23b37a7 | |||
| 3a968d707f | |||
| b07c44c8b4 | |||
| 43b0a58649 | |||
| f258e93cf7 | |||
| 93138b04cb | |||
| 0cf54ec9c2 | |||
| ce031cf7bd | |||
| e6495bc7c0 | |||
| 1b196bf0fb | |||
| dbed24aaca | |||
| 48a7a21aca | |||
| f595afab18 | |||
| 0aca00b245 | |||
| 9af58d3abf | |||
| dd5ef3696f | |||
| 03d49bac53 | |||
| 6c082a10b1 | |||
| 77944e195a | |||
| 6ebfdef025 | |||
| bc39a6741c | |||
| bda7e08208 | |||
| aa69dd381f | |||
| 1fd8a8e0a6 | |||
| 1329fa1b09 | |||
| b550f38eed | |||
| ae7b912ac8 | |||
| af9478922e | |||
| 7acea29cdb | |||
| 6082eb21e3 | |||
| a91cda4995 | |||
| 7959654dc8 | |||
| dc9a85ca98 | |||
| 591ed50ac3 | |||
| 47350328e6 | |||
| 75ed749cb3 | |||
| f44ea8b749 | |||
| 76c0071f57 | |||
| 2a396b4438 | |||
| 51a54863c5 | |||
| 06f986b92e | |||
| 652ceba845 | |||
| 16d0f54d8f | |||
| 872cce784a | |||
| aec3ad382a | |||
| 9d4f9ef73c | |||
| cf7cafc261 | |||
| e3bff7e87c | |||
| 4b19421075 | |||
| cf371e8093 | |||
| 5eeadc6399 | |||
| f6823ea3d1 | |||
| f24290c423 | |||
| f8a36885fe | |||
| a555eff2cc | |||
| 05c389623c | |||
| bf00f5e9a2 | |||
| 7685c4d5d5 | |||
| e701ec9617 | |||
| 6c1ee096a1 | |||
| 2df282222f | |||
| 43c7bd48c7 | |||
| 86579068d9 | |||
| 8e6ab9aa35 | |||
| 77566a887a | |||
| 9d0eca1914 | |||
| 79a3164d9d | |||
| eb73e48192 | |||
| cd6af7f185 | |||
| 3d6020b9cf | |||
| 461f03aac0 | |||
| 35149f8837 | |||
| c0d01f32a6 | |||
| 83a0459b6a | |||
| 50f6dcef2f | |||
| 5c514fd663 | |||
| 1c2196f78f | |||
| 43cc3c40f3 | |||
| 7a6a4cf59d | |||
| 3bcf375204 | |||
| a175bdc1c7 | |||
| b557b437a3 | |||
| d1f0b59b5d | |||
| 3ece3a1f2b | |||
| 1f1a85de18 | |||
| e08c9dafa6 | |||
| ad27607ccc | |||
| c1bcca4432 | |||
| 9f2ed694ce | |||
| edadd8f2fd | |||
| afa08713e0 | |||
| d23620727e | |||
| b456c6ad3b | |||
| 0298b53803 | |||
| bfd6e4af3f | |||
| 31612aae4a | |||
| 219367e7c1 | |||
| 7b64f10fc7 | |||
| 1ad1744054 | |||
| 7b825f2cd7 | |||
| 3759fce090 | |||
| 470521f7c8 | |||
| a070dffb93 | |||
| 9e7bc94aab | |||
| 033d0113a5 | |||
| d0a53ed2df | |||
| 49b80e9fe3 | |||
| d5f5ddbec5 | |||
| 17c7dd658d | |||
| ca19ecaefc | |||
| c149f00f82 | |||
| b041d59fc7 | |||
| b983d5904b | |||
| 8b15053dd4 | |||
| e15815cd97 | |||
| 94a64d8fae | |||
| fd7088de1a | |||
| 7d4946560d | |||
| b7c9647e1a | |||
| 36b9f64aae | |||
| 60a72b2ba4 | |||
| f830f73ae6 | |||
| 95f51e1126 | |||
| 8916f55d52 | |||
| 4aaef9558a | |||
| 0b78664792 | |||
| db5d4d5158 | |||
| 0dfd8b6453 | |||
| 11a2fb1088 | |||
| 40feeff442 | |||
| a0a2976e0a | |||
| 741f3cbdcc | |||
| a6965c4b5a | |||
| 19b05e632c | |||
| 8610b47a68 | |||
| 2ab8890540 | |||
| 5de5a519c3 | |||
| 0d193d3e9e | |||
| 622382f425 | |||
| c1f09326cc | |||
| ddbbba4aaa | |||
| bcf7ea30c5 | |||
| 35e9fab701 | |||
| 864b6d313e | |||
| d47d12e961 | |||
| 9f0e752318 | |||
| 34bd5ead15 | |||
| 1fd5dffdc7 | |||
| 6d7a900bbb | |||
| fb4f921159 | |||
| 14cc701b25 | |||
| d8c4113d24 | |||
| 9eb6bb7738 | |||
| de96f8b9f9 | |||
| e34975001c | |||
| f3b282062b | |||
| 84732a24fa | |||
| dad775b494 | |||
| 05ad3fcd5c | |||
| 6ae02d2d02 | |||
| 757a3114dc | |||
| 94b9878c6c | |||
| 7775b16199 | |||
| f01d48f9ae | |||
| 179883094e | |||
| 971ccf9df4 | |||
| 07eb6bf88e | |||
| 5afd8174ca | |||
| f1fea38712 | |||
| f275c6e5e7 | |||
| 5ec25959df | |||
| 4f270f3aab | |||
| 4028dd3009 | |||
| 706b04610d | |||
| 014e3baea0 | |||
| 92ca7c935a | |||
| 5c9b1c9a3d | |||
| 5ebee60c97 | |||
| 3337a9cbab | |||
| 54975eb812 | |||
| 537531803a | |||
| f4b640126b | |||
| 1de3251127 | |||
| 7e98076e4a | |||
| c58c55b752 | |||
| 928be5717f | |||
| ccbaa926ce | |||
| d1208d7d19 | |||
| 099fe59a97 | |||
| 889acaec82 | |||
| c42e9d4c5c | |||
| 4378e5295d | |||
| 73a427f6aa | |||
| abfee70eb3 | |||
| 77cdbf8dd6 | |||
| 28bc68c916 | |||
| ecb64cc2ec | |||
| 23706a1ba9 | |||
| d3f406a34a | |||
| 55afc7eb33 | |||
| 7a70d12efd | |||
| 1ecaf6f8d5 | |||
| e01cdbb091 | |||
| b88b5a2601 | |||
| e7476edd68 | |||
| cbbeb412f9 | |||
| f544890f00 | |||
| 72560fa6d0 | |||
| 4637ff78c0 | |||
| 501aff41ea | |||
| 449b1bfe9e | |||
| 4a8358ecb4 | |||
| 8f74e4dd31 | |||
| 2b35d9f012 | |||
| 35001107e0 | |||
| a7d7b90ae8 | |||
| 119ba7ef8b | |||
| 28bbe9c646 | |||
| 8739c04024 | |||
| 57240d25b9 | |||
| 15ea5440a3 | |||
| 1e60d1c265 | |||
| b7cd097c43 | |||
| 6c934b02e6 | |||
| fcb9b40b43 | |||
| 7a6884e4b1 | |||
| e86698cfeb | |||
| 53650aefa6 | |||
| 1d80a0cad1 | |||
| f6d27a0f43 | |||
| f71aa9dd21 | |||
| 1cb5394e96 | |||
| 2b2dbd25f7 | |||
| dd4cd0eeb1 | |||
| ee7b0cf730 | |||
| 95ef5d6348 | |||
| 23192b9ef6 | |||
| 7cd98c8a63 | |||
| fca7686701 | |||
| be767478f4 | |||
| b3ad5d90ed | |||
| fb093b7411 | |||
| e4ea3110e3 | |||
| 79676c4f72 | |||
| d61827b92c | |||
| 1f1f46c70f | |||
| 9188e4a7ec | |||
| e5a780eb0c | |||
| d8c85a2b15 | |||
| 83080bc5a2 | |||
| 233bfc59ac | |||
| c606caf3a3 | |||
| efdf69552f | |||
| 38531bf95c | |||
| 6d714db928 | |||
| f8e7497695 | |||
| d6ef812704 | |||
| 4f81bc9621 | |||
| 59276ce2a5 | |||
| 96791bd72b | |||
| 8756b22f5a | |||
| 487d256f46 | |||
| fe0b6aaba4 | |||
| 017c8a6900 | |||
| afe4af0dc2 | |||
| fb8e4430ac | |||
| 7499f5dbfa | |||
| c7b58aa65b | |||
| 705d9b8238 | |||
| 1bc650b0f9 | |||
| 580aeea4e2 | |||
| 8495824843 | |||
| 18bb3611fa | |||
| 9f7bf8d1a2 | |||
| 82146eda3d | |||
| d75881e1a3 | |||
| 5be967e8c5 | |||
| d9fa875d84 | |||
| 04f93c98d2 | |||
| 402f6c19e7 | |||
| 84b0df0437 | |||
| 9f4a7f7623 | |||
| 10012c1e16 | |||
| d65f8856f4 | |||
| d79d8fbbea | |||
| 772590c41c | |||
| d9c71bddb8 | |||
| 29ce2401ca | |||
| 720ef38886 | |||
| 728ab6c8c1 | |||
| 935028addc | |||
| e70e22d557 | |||
| f3db4b5cb0 | |||
| d60fc06379 | |||
| a813260717 | |||
| 10d01df7dd | |||
| 8eb075fa86 | |||
| c2e7bfa641 | |||
| 2f23244937 | |||
| 9ecea9e1d5 | |||
| 61b34e835e | |||
| 4e2b83c052 | |||
| 45ee4755a6 | |||
| 59281afe90 | |||
| cf5a63a5d5 | |||
| 96869074c3 | |||
| c107d5fa7f | |||
| bed56e8891 | |||
| c4b641e62a | |||
| 153d710eb4 | |||
| 83471e0866 | |||
| 01b9843883 | |||
| 749af89e9f | |||
| 27b61a2770 | |||
| eb3b6346bb | |||
| 2e9a0de4a1 | |||
| f83e3cc3e7 | |||
| a8f4659552 | |||
| 25a5c3dec9 | |||
| c49cb4a213 | |||
| c4dbbc2d1e | |||
| fe3d6f57af | |||
| 052af2f9bf | |||
| 16da9f52ac | |||
| 22a342d36d | |||
| 4fcf32b5e9 | |||
| 5bdb455bc0 | |||
| 1cb74f0ea7 | |||
| c7e8c95640 | |||
| ccb322d08e | |||
| b27e0f2d21 | |||
| 6a715d87dd | |||
| 6138b78c07 | |||
| f84ef48819 | |||
| cda27944b6 | |||
| c9281f734b | |||
| f378ea0d2e | |||
| 40c37b5c06 | |||
| 57b7db6956 | |||
| b4f5c2c0a1 | |||
| f6903cf582 | |||
| 3816385228 | |||
| f65085946c | |||
| b10b746d9e | |||
| ed5945e182 | |||
| cf48a13fc7 | |||
| 29d9bbad32 | |||
| 004f42bf6e | |||
| 41e0d105f6 | |||
| fdd61963e6 | |||
| 10cbd4d3c4 | |||
| 64af7800dc | |||
| c428982c00 | |||
| 1363bc3f43 | |||
| 09ddfe4250 | |||
| e13de0950c | |||
| c1ac78eea4 | |||
| 21de95e0a6 | |||
| 0593bb9c53 | |||
| bd1ce26dc7 | |||
| 2612e7c23a | |||
| 93ca7abc1a | |||
| de4af14676 | |||
| c9a6c0ffcc | |||
| d414806fa2 | |||
| d54c129c57 | |||
| 7c848153f8 | |||
| 4e36c2f82d | |||
| b5c71bc59c | |||
| d20724d7b2 | |||
| 1cca5ee5cb | |||
| 95acf7402d | |||
| c8f3734569 | |||
| f9d846a704 | |||
| 3984cb8f48 | |||
| a0327a62dd | |||
| a388d07f30 | |||
| 7f0cca1baf | |||
| 249756e0d2 | |||
| d2e841f681 | |||
| b871241eac | |||
| 86b5932c8f | |||
| 39dbe2805b | |||
| 263e94454c | |||
| 01e8579215 | |||
| e00fa2df26 | |||
| 78615b5dc8 | |||
| 9f8a008442 | |||
| 6678b29396 | |||
| 11636b16d2 | |||
| 194981cd8b | |||
| 0c85e0fe22 | |||
| de3a057e6e | |||
| f36ed2f8c8 | |||
| 1d1f2c9f12 | |||
| 9feb7ad876 | |||
| 1b45397e67 | |||
| 55bbbe6268 | |||
| eeba454dbb | |||
| b80c327e35 | |||
| eb10508c5f | |||
| 73c08da037 | |||
| e18f94c17d | |||
| f1a20e1677 | |||
| 4ac606b468 | |||
| 980e8eeb3e | |||
| ffea55265d | |||
| fb0190f826 | |||
| 68800d28fc | |||
| 05c5c58eaf | |||
| 1c504f681e | |||
| 5bd7a23864 | |||
| 7aa829fa8c | |||
| de1b135dec | |||
| d83f14d1b6 | |||
| 0a705071c2 | |||
| 80d68684fb | |||
| c737785114 | |||
| 76ae62cb84 | |||
| 103f79eca5 | |||
| 0979231435 | |||
| f3da10ec98 | |||
| 0debc0a4d3 | |||
| bc8b9d32db | |||
| 73d68e926d | |||
| ba5b18dfe8 | |||
| be591d7c65 | |||
| b34a58e521 | |||
| 4f0043b805 | |||
| 0a0f2a9dcc | |||
| 50c9e7767d | |||
| a53f284c88 | |||
| ee0d1d269c | |||
| 6d1d699059 | |||
| 02d7193a92 | |||
| ef7216722f | |||
| 878d10a1e2 | |||
| d8bb18c07d | |||
| 18853d0c86 | |||
| 648a1a1893 | |||
| 52f264dae6 | |||
| 9dbf56f942 | |||
| 9b1018fa96 | |||
| 5ebde77747 | |||
| 66d8ded924 | |||
| 183572f312 | |||
| de09a8b7ca | |||
| 9a98d5aa8f | |||
| e6086bb7b3 | |||
| 064e9b6bd0 | |||
| 09ed5e67a6 | |||
| 2c96844209 | |||
| acbb5b1720 | |||
| 9bfa390d0c | |||
| 69c50591b2 | |||
| 02d3aec33e | |||
| e983e1cefb | |||
| b94bad38e7 | |||
| 8dcace4bfd | |||
| 1b6065bb46 | |||
| 89981f46b0 | |||
| 7322f0c676 | |||
| 5cef3e13e1 | |||
| b141729830 | |||
| b348a879c3 | |||
| d2742cbe6e | |||
| fb0be051aa | |||
| 14ba572acd | |||
| 46e37d5ff5 | |||
| 1ef62b5e32 | |||
| d6fce3c145 | |||
| 897adbf5ac | |||
| 0959aebd10 | |||
| 33f124263d | |||
| 73469f070c | |||
| 32372ea237 | |||
| ef6dbee516 | |||
| 2c6af90703 | |||
| dc4fb6d7c3 | |||
| 1a89eba9e6 | |||
| 1490b0dcbe | |||
| edabd07719 | |||
| ad0c75866f | |||
| f459a21bef | |||
| 8d8e1c61d8 | |||
| cee92e1cd2 | |||
| 2ab910e3e9 | |||
| 09b3642559 | |||
| 77e29ff43b | |||
| 9394b4880e | |||
| 923913f63d | |||
| fed115996c | |||
| 10647f14b2 | |||
| 6f0b3fb669 | |||
| afc30dd1c3 | |||
| d346216fa2 | |||
| 3febc94871 | |||
| fb125ef619 | |||
| fe61ef167e | |||
| 3b96e94992 | |||
| 5d48e6f3b1 | |||
| 6f103174aa | |||
| 815678584f | |||
| 13fef45e06 | |||
| 5cfa7b6ed1 | |||
| c80684a129 | |||
| 684004d614 | |||
| 4d7f065b10 | |||
| d1d8711f60 | |||
| f0821776a9 | |||
| 5c7361b95f | |||
| 980a1a452c | |||
| 4993c5a675 | |||
| 86b18c702c | |||
| 36b3fbd5bc | |||
| d9a63b45d4 | |||
| 4ddd576315 | |||
| fc36dae54f | |||
| 31395d9efc | |||
| ea4aaf61c1 | |||
| cf77eb2e47 | |||
| 5ae6fe2dda | |||
| 7c3b2673a5 | |||
| d69fd63da7 | |||
| 6b1fc786ee | |||
| 48e36d3ca1 | |||
| ff1864779a | |||
| 73643f84ae | |||
| 51fe1411cd | |||
| 409ac569b2 | |||
| 118df46630 | |||
| 3d76f3a787 | |||
| b7f1d9ed1a | |||
| cd32932b75 | |||
| 2700a005d4 | |||
| 115418d323 | |||
| 2a19f151fc | |||
| fa5a1f9c19 | |||
| da28630644 | |||
| 248d2baa2a | |||
| c6762234e6 | |||
| 0ba6d9a5af | |||
| 680a44c4b4 | |||
| f78c33445c | |||
| 85b0f34395 | |||
| f6cbe82848 | |||
| fd684bdb58 | |||
| 96a93e00aa | |||
| de912a3cfb | |||
| cf8e11238c | |||
| 7e05903c61 | |||
| 13cabfbad7 | |||
| 0651a6ddc3 | |||
| 9a1064c81d | |||
| d4da9edb3e | |||
| 4923ffe98a | |||
| 99bfb2fc7a | |||
| 5c2be25dfc | |||
| b1601b1bf0 | |||
| be5c7f4592 | |||
| 2fa5792f69 | |||
| 74910a490b | |||
| 19c69aaca6 | |||
| d8710f0c7d | |||
| 150de9ed6f | |||
| b483e24e33 | |||
| 2d02dcf682 | |||
| 8fa967cb91 | |||
| 80756ba490 | |||
| 03791b9fbc | |||
| feffb56847 | |||
| 53810b2262 | |||
| b12a41cd77 | |||
| 9b4581a781 | |||
| 7b91bc0633 | |||
| 94cfd23c00 | |||
| 422bbba7f6 | |||
| 68bc6e3325 | |||
| c5ab97ce0d | |||
| 35c88084ba | |||
| 0fc4939a07 | |||
| 82d9457647 | |||
| e469ee201b | |||
| 3988fbbc09 | |||
| a8745297dc | |||
| 311339240f | |||
| cf2925978b | |||
| 592751884e | |||
| 51ce2d82d6 | |||
| ba9d4b7f0f | |||
| 9fc4e54ece | |||
| bd341f1875 | |||
| b113a94c52 | |||
| 294adf270f | |||
| 1d3b541e8f | |||
| cc1d7b2b59 | |||
| 36b19de9da | |||
| 2063decbe7 | |||
| 6251c585e4 |
@@ -1,17 +0,0 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
|
||||
# Custom for Visual Studio
|
||||
*.cs diff=csharp
|
||||
|
||||
# Standard to msysgit
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
||||
@@ -0,0 +1,62 @@
|
||||
# Default
|
||||
* @Twentysix26
|
||||
|
||||
# Core
|
||||
redbot/core/bank.py @palmtree5
|
||||
redbot/core/checks.py @tekulvw
|
||||
redbot/core/cli.py @tekulvw
|
||||
redbot/core/config.py @tekulvw
|
||||
redbot/core/cog_manager.py @tekulvw
|
||||
redbot/core/core_commands.py @tekulvw
|
||||
redbot/core/context.py @Tobotimus
|
||||
redbot/core/data_manager.py @tekulvw
|
||||
redbot/core/dev_commands.py @tekulvw
|
||||
redbot/core/drivers/* @tekulvw
|
||||
redbot/core/events.py @tekulvw
|
||||
redbot/core/global_checks.py @tekulvw
|
||||
redbot/core/i18n.py @tekulvw
|
||||
redbot/core/json_io.py @tekulvw
|
||||
redbot/core/modlog.py @palmtree5
|
||||
redbot/core/rpc.py @tekulvw
|
||||
redbot/core/sentry_setup.py @Kowlin @tekulvw
|
||||
redbot/core/utils/chat_formatting.py @tekulvw
|
||||
redbot/core/utils/mod.py @palmtree5
|
||||
redbot/core/utils/data_converter.py @mikeshardmind
|
||||
redbot/core/utils/antispam.py @mikeshardmind
|
||||
redbot/core/utils/tunnel.py @mikeshardmind
|
||||
redbot/core/utils/caching.py @mikeshardmind
|
||||
redbot/core/utils/common_filters.py @mikeshardmind
|
||||
|
||||
# Cogs
|
||||
redbot/cogs/admin/* @tekulvw
|
||||
redbot/cogs/alias/* @tekulvw
|
||||
redbot/cogs/audio/* @aikaterna @atiwiex
|
||||
redbot/cogs/bank/* @tekulvw
|
||||
redbot/cogs/cleanup/* @palmtree5
|
||||
redbot/cogs/customcom/* @palmtree5
|
||||
redbot/cogs/downloader/* @tekulvw
|
||||
redbot/cogs/economy/* @palmtree5
|
||||
redbot/cogs/filter/* @palmtree5
|
||||
redbot/cogs/general/* @palmtree5
|
||||
redbot/cogs/image/* @palmtree5
|
||||
redbot/cogs/mod/* @palmtree5
|
||||
redbot/cogs/modlog/* @palmtree5
|
||||
redbot/cogs/streams/* @Twentysix26 @palmtree5
|
||||
redbot/cogs/trivia/* @Tobotimus
|
||||
redbot/cogs/dataconverter/* @mikeshardmind
|
||||
redbot/cogs/reports/* @mikeshardmind
|
||||
redbot/cogs/permissions/* @mikeshardmind
|
||||
redbot/cogs/warnings/* @palmtree5
|
||||
|
||||
# Docs
|
||||
docs/* @tekulvw @palmtree5
|
||||
|
||||
# Setup, instance setup, and running the bot
|
||||
setup.py @tekulvw
|
||||
redbot/__init__.py @tekulvw
|
||||
redbot/__main__.py @tekulvw
|
||||
redbot/setup.py @tekulvw
|
||||
|
||||
# Others
|
||||
.travis.yml @Kowlin
|
||||
crowdin.yml @Kowlin
|
||||
@@ -0,0 +1,147 @@
|
||||
# Contents
|
||||
* [1. Introduction](#1-introduction)
|
||||
* [1.1 Why do these guidelines exist?](#11-why-do-these-guidelines-exist)
|
||||
* [1.2 What kinds of contributions are we looking for?](#12-what-kinds-of-contributions-are-we-looking-for)
|
||||
* [2. Ground Rules](#2-ground-rules)
|
||||
* [3. Your First Contribution](#3-your-first-contribution)
|
||||
* [4. Getting Started](#4-getting-started)
|
||||
* [4.1 Setting up your development environment](#41-setting-up-your-development-environment)
|
||||
* [4.2 Testing](#42-testing)
|
||||
* [4.3 Style](#43-style)
|
||||
* [4.4 Make](#44-make)
|
||||
* [4.5 Keeping your dependencies up to date](#45-keeping-your-dependencies-up-to-date)
|
||||
* [4.6 To contribute changes](#46-to-contribute-changes)
|
||||
* [4.7 How To Report A Bug](#47-how-to-report-a-bug)
|
||||
* [4.8 How To Suggest A Feature Or Enhancement](#48-how-to-suggest-a-feature-or-enhancement)
|
||||
* [5. Code Review Process](#5-code-review-process)
|
||||
* [5.1 Issues](#51-issues)
|
||||
* [5.2 Pull Requests](#52-pull-requests)
|
||||
* [5.3 Differences between "new features" and "improvements"](#53-differences-between-new-features-and-improvements)
|
||||
* [6. Community](#6-community)
|
||||
|
||||
# 1. Introduction
|
||||
**Welcome!** First off, thank you for contributing to the further development of Red. We're always looking for new ways to improve our project and we appreciate any help you can give us.
|
||||
|
||||
### 1.1 Why do these guidelines exist?
|
||||
Red is an open source project. This means that each and every one of the developers and contributors who have helped make Red what it is today have done so by volunteering their time and effort. It takes a lot of time to coordinate and organize issues and new features and to review and test pull requests. By following these guidelines you will help the developers streamline the contribution process and save them time. In doing so we hope to get back to each and every issue and pull request in a timely manner.
|
||||
|
||||
### 1.2 What kinds of contributions are we looking for?
|
||||
We love receiving contributions from our community. Any assistance you can provide with regards to bug fixes, feature enhancements, and documentation is more than welcome.
|
||||
|
||||
# 2. Ground Rules
|
||||
We've made a point to use [ZenHub](https://www.zenhub.com/) (a plugin for GitHub) as our main source of collaboration and coordination. Your experience contributing to Red will be greatly improved if you go get that plugin.
|
||||
1. Ensure cross compatibility for Windows, Mac OS and Linux.
|
||||
2. Ensure all Python features used in contributions exist and work in Python 3.6 and above.
|
||||
3. Create new tests for code you add or bugs you fix. It helps us help you by making sure we don't accidentally break anything :grinning:
|
||||
4. Create any issues for new features you'd like to implement and explain why this feature is useful to everyone and not just you personally.
|
||||
5. Don't add new cogs unless specifically given approval in an issue discussing said cog idea.
|
||||
6. Be welcoming to newcomers and encourage diverse new contributors from all backgrounds. See [Python Community Code of Conduct](https://www.python.org/psf/codeofconduct/).
|
||||
|
||||
# 3. Your First Contribution
|
||||
Unsure of how to get started contributing to Red? Please take a look at the Issues section of this repo and sort by the following labels:
|
||||
|
||||
* beginner - issues that can normally be fixed in just a few lines of code and maybe a test or two.
|
||||
* help-wanted - issues that are currently unassigned to anyone and may be a bit more involved/complex than issues tagged with beginner.
|
||||
|
||||
**Working on your first Pull Request?** You can learn how from this *free* series [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github)
|
||||
|
||||
At this point you're ready to start making changes. Feel free to ask for help; everyone was a beginner at some point!
|
||||
|
||||
# 4. Getting Started
|
||||
|
||||
Red's repository is configured to follow a particular development workflow, using various reputable tools. We kindly ask that you stick to this workflow when contributing to Red, by following the guides below. This will help you to easily produce quality code, identify errors early, and streamline the code review process.
|
||||
|
||||
### 4.1 Setting up your development environment
|
||||
The following requirements must be installed prior to setting up:
|
||||
- Python 3.6.2 or greater (3.6.6 or greater on Windows)
|
||||
- git
|
||||
- pip
|
||||
- pipenv
|
||||
|
||||
If you're not on Windows, you can optionally install [pyenv](https://github.com/pyenv/pyenv), which will help you run tests for different python versions.
|
||||
|
||||
1. Fork and clone the repository to a directory on your local machine.
|
||||
2. Open a command line in that directory and execute the following commands:
|
||||
```bash
|
||||
pip install pipenv
|
||||
pipenv install --dev
|
||||
```
|
||||
Red, its dependencies, and all required development tools, are now installed to a virtual environment. Red is installed in editable mode, meaning that edits you make to the source code in the repository will be reflected when you run Red.
|
||||
3. Activate the new virtual environment with the command:
|
||||
```bash
|
||||
pipenv shell
|
||||
```
|
||||
From here onwards, we will assume you are executing commands from within this shell. Each time you open a new command line, you should execute this command first.
|
||||
|
||||
Note: If you haven't used `pipenv` before but are comfortable with virtualenvs, just run `pip install pipenv` in the virtualenv you're already using and invoke the command above from the cloned Red repo. It will do the correct thing.
|
||||
|
||||
### 4.2 Testing
|
||||
We've recently started using [tox](https://github.com/tox-dev/tox) to run all of our tests. It's extremely simple to use, and if you followed the previous section correctly, it is already installed to your virtual environment.
|
||||
|
||||
Currently, tox does the following, creating its own virtual environments for each stage:
|
||||
- Runs all of our unit tests with [pytest](https://github.com/pytest-dev/pytest) on python 3.6 and 3.7 (test environments `py36` and `py37`)
|
||||
- Ensures documentation builds without warnings, and all hyperlinks have a valid destination (test environment `docs`)
|
||||
- Ensures that the code meets our style guide with [black](https://github.com/ambv/black) (test environment `style`)
|
||||
|
||||
To run all of these tests, just run the command `tox` in the project directory.
|
||||
|
||||
To run a subset of these tests, use the command `tox -e <env>`, where `<env>` is the test environment you want tox to run. The test environments are noted in the dot points above.
|
||||
|
||||
Your PR will not be merged until all of these tests pass.
|
||||
|
||||
### 4.3 Style
|
||||
Our style checker of choice, [black](https://github.com/ambv/black), actually happens to be an auto-formatter. The checking functionality simply detects whether or not it would try to reformat something in your code, should you run the formatter on it. For this reason, we recommend using this tool as a formatter, regardless of any disagreements you might have with the style it enforces.
|
||||
|
||||
Use the command `black --help` to see how to use this tool. The full style guide is explained in detail on [black's GitHub repository](https://github.com/ambv/black). **There is one exception to this**, however, which is that we set the line length to 99, instead of black's default 88. When using `black` on the command line, simply use it like so: `black -l 99 -N <src>`.
|
||||
|
||||
### 4.4 Make
|
||||
You may have noticed we have a `Makefile` and a `make.bat` in the top-level directory. For now, you can do two things with them:
|
||||
1. `make reformat`: Reformat all python files in the project with Black
|
||||
2. `make stylecheck`: Check if any `.py` files in the project need reformatting
|
||||
|
||||
### 4.5 Keeping your dependencies up to date
|
||||
Whenever you pull from upstream (V3/develop on the main repository) and you notice the file `Pipfile.lock` has been changed, it usually means one of the package dependencies have been updated, added or removed. To make sure you're testing and formatting with the most up-to-date versions of our dependencies, run `pipenv install --dev` again.
|
||||
|
||||
### 4.6 To contribute changes
|
||||
|
||||
1. Create a new branch on your fork
|
||||
2. Make the changes
|
||||
3. If you like the changes and think the main Red project could use it:
|
||||
* Run tests with `tox` to ensure your code is up to scratch
|
||||
* Create a Pull Request on GitHub with your changes
|
||||
|
||||
### 4.7 How To Report A Bug
|
||||
Please see our **ISSUES.MD** for more information.
|
||||
|
||||
### 4.8 How To Suggest A Feature Or Enhancement
|
||||
The goal of Red is to be as useful to as many people as possible, this means that all features must be useful to anyone and any server that uses Red.
|
||||
|
||||
If you find yourself wanting a feature that Red does not already have, you're probably not alone. There's bound to be a great number of users out there needing the same thing and a lot of the features that Red has today have been added because of the needs of our users. Open an issue on our issues list and describe the feature you would like to see, how you would use it, how it should work, and why it would be useful to the Red community as a whole.
|
||||
|
||||
# 5. Code Review Process
|
||||
|
||||
We have a core team working tirelessly to implement new features and fix bugs for the Red community. This core team looks at and evaluates new issues and PRs on a daily basis.
|
||||
|
||||
The decisions we make are based on a simple majority of that team or by decree of the project owner.
|
||||
|
||||
### 5.1 Issues
|
||||
Any new issues will be looked at and evaluated for validity of a bug or for the usefulness of a suggested feature. If we have questions about your issue we will get back as soon as we can (usually in a day or two) and will try to make a decision within a week.
|
||||
|
||||
### 5.2 Pull Requests
|
||||
Pull requests are evaluated by their quality and how effectively they solve their corresponding issue. The process for reviewing pull requests is as follows:
|
||||
|
||||
1. A pull request is submitted
|
||||
2. Core team members will review and test the pull request (usually within a week)
|
||||
3. After a majority of the core team approves your pull request:
|
||||
* If your pull request is considered an improvement or enhancement the project owner will have 1 day to veto or approve your pull request.
|
||||
* If your pull request is considered a new feature the project owner will have 1 week to veto or approve your pull request.
|
||||
4. If any feedback is given we expect a response within 1 week or we may decide to close the PR.
|
||||
5. If your pull request is not vetoed and no core member requests changes then it will be approved and merged into the project.
|
||||
|
||||
### 5.3 Differences between "new features" and "improvements"
|
||||
The difference between a new feature and improvement can be quite fuzzy and the project owner reserves all rights to decide under which category your PR falls.
|
||||
|
||||
At a very basic level a PR is a new feature if it changes the intended way any part of the Red project currently works or if it modifies the user experience (UX) in any significant way. Otherwise, it is likely to be considered an improvement.
|
||||
|
||||
# 6. Community
|
||||
You can chat with the core team and other community members about issues or pull requests in the #coding channel of the Red support server located [here](https://discord.gg/red).
|
||||
@@ -0,0 +1,20 @@
|
||||
Please be sure to read through other issues as well to make sure what you are suggesting/reporting has not already
|
||||
been suggested/reported
|
||||
|
||||
### Type:
|
||||
|
||||
- [ ] Suggestion
|
||||
- [ ] Bug
|
||||
|
||||
### Brief description of the problem
|
||||
|
||||
### Expected behavior
|
||||
|
||||
### Actual behavior
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
4.
|
||||
@@ -0,0 +1,25 @@
|
||||
# Command bugs
|
||||
|
||||
<!--
|
||||
Did you find a bug with a command? Fill out the following:
|
||||
-->
|
||||
|
||||
#### Command name
|
||||
|
||||
<!-- Replace this line with the name of the command -->
|
||||
|
||||
#### What cog is this command from?
|
||||
|
||||
<!-- Replace this line with the name of the cog -->
|
||||
|
||||
#### What were you expecting to happen?
|
||||
|
||||
<!-- Replace this line with a description of what you were expecting to happen -->
|
||||
|
||||
#### What actually happened?
|
||||
|
||||
<!-- Replace this line with a description of what actually happened. Include any error messages -->
|
||||
|
||||
#### How can we reproduce this issue?
|
||||
|
||||
<!-- Replace with numbered steps to reproduce the issue -->
|
||||
@@ -0,0 +1,35 @@
|
||||
# Feature request
|
||||
|
||||
<!-- This template is for feature requests. Please fill out the following: -->
|
||||
|
||||
|
||||
#### Select the type of feature you are requesting:
|
||||
|
||||
<!-- To check a box, replace the space between the [] with a x -->
|
||||
|
||||
- [ ] Cog
|
||||
- [ ] Command
|
||||
- [ ] API functionality
|
||||
|
||||
#### Describe your requested feature
|
||||
|
||||
<!--
|
||||
Feel free to describe in as much detail as you wish.
|
||||
|
||||
If you are requesting a cog to be included in core:
|
||||
- Describe the functionality in as much detail as possible
|
||||
- Include the command structure, if possible
|
||||
- Please note that unless it's something that should be core functionality,
|
||||
we reserve the right to reject your suggestion and point you to our cog
|
||||
board to request it for a third-party cog
|
||||
|
||||
If you are requesting a command:
|
||||
- Include what cog it should be in and a name for the command
|
||||
- Describe the intended functionality for the command
|
||||
- Note any restrictions on who can use the command or where it can be used
|
||||
|
||||
If you are requesting API functionality:
|
||||
- Describe what it should do
|
||||
- Note whether it is to extend existing functionality or introduce new functionality
|
||||
|
||||
-->
|
||||
@@ -0,0 +1,21 @@
|
||||
# Other bugs
|
||||
|
||||
<!--
|
||||
Did you find a bug with something other than a command? Fill out the following:
|
||||
-->
|
||||
|
||||
#### What were you trying to do?
|
||||
|
||||
<!-- Replace this line with a description of what you were trying to do -->
|
||||
|
||||
#### What were you expecting to happen?
|
||||
|
||||
<!-- Replace this line with a description of what you were expecting to happen -->
|
||||
|
||||
#### What actually happened?
|
||||
|
||||
<!-- Replace this line with a description of what actually happened. Include any error messages -->
|
||||
|
||||
#### How can we reproduce this issue?
|
||||
|
||||
<!-- Replace with numbered steps to reproduce the issue -->
|
||||
@@ -0,0 +1,7 @@
|
||||
### Type
|
||||
|
||||
- [ ] Bugfix
|
||||
- [ ] Enhancement
|
||||
- [ ] New feature
|
||||
|
||||
### Description of the changes
|
||||
@@ -0,0 +1,14 @@
|
||||
# Bugfix request
|
||||
|
||||
<!--
|
||||
To be used for pull requests that fix a bug
|
||||
-->
|
||||
|
||||
#### Describe the bug being fixed
|
||||
|
||||
<!--
|
||||
If an issue exists for the bug, mention
|
||||
that this PR fixes that issue
|
||||
-->
|
||||
|
||||
#### Anything we need to know about this fix?
|
||||
@@ -0,0 +1,20 @@
|
||||
# Enhancement request
|
||||
|
||||
<!--
|
||||
To be used for PRs which enhance existing features
|
||||
-->
|
||||
|
||||
#### Describe the enhancement
|
||||
|
||||
<!--
|
||||
Describe what your changes do.
|
||||
If adding commands, describe any restrictions on their usage.
|
||||
- For example, who can use the command? Where can it be used?
|
||||
-->
|
||||
|
||||
#### Does this enhancement break existing functionality?
|
||||
|
||||
<!-- To check a box, replace the space between the [] with a x -->
|
||||
|
||||
- [ ] Yes
|
||||
- [ ] No
|
||||
@@ -0,0 +1,21 @@
|
||||
# New feature addition
|
||||
|
||||
<!--
|
||||
To be used for PRs which add a new feature
|
||||
Examples of this include new APIs, new core cogs, etc.
|
||||
-->
|
||||
|
||||
#### What type of feature is this?
|
||||
|
||||
<!-- To check a box, replace the space between the [] with a x -->
|
||||
|
||||
- [ ] New core cog
|
||||
- [ ] New API
|
||||
- [ ] Other
|
||||
|
||||
#### Describe the feature
|
||||
|
||||
<!--
|
||||
If you are adding a cog, describe its commands in detail (functionality, usage restrictions, etc).
|
||||
If the new feature introduces new requirements, please try to explain why they are necessary.
|
||||
-->
|
||||
@@ -0,0 +1,16 @@
|
||||
# New release
|
||||
|
||||
<!--
|
||||
To be used by collaborators for doing releases.
|
||||
Most contributors will not need to use this.
|
||||
-->
|
||||
|
||||
#### Version
|
||||
|
||||
|
||||
|
||||
#### Has a draft release been created for this?
|
||||
|
||||
- [ ] Yes
|
||||
- [ ] No
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Translations update
|
||||
|
||||
<!--
|
||||
Used for PRs updating translations from Crowdin
|
||||
-->
|
||||
+126
-40
@@ -1,50 +1,136 @@
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
*.json
|
||||
*.exe
|
||||
*.dll
|
||||
*.pot
|
||||
.data
|
||||
!/tests/cogs/dataconverter/data/**/*.json
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
### JetBrains template
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
# User-specific stuff:
|
||||
.idea/
|
||||
*.iws
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
## Plugin-specific files:
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# =========================
|
||||
# Operating System Files
|
||||
# =========================
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# OSX
|
||||
# =========================
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
### Python template
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
__pycache__
|
||||
json
|
||||
cache
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
.hypothesis/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# celery beat schedule file
|
||||
celerybeat-schedule
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
|
||||
# pytest
|
||||
.pytest_cache/
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
formats:
|
||||
- pdf
|
||||
|
||||
build:
|
||||
image: latest
|
||||
|
||||
requirements_file: dependency_links.txt
|
||||
|
||||
python:
|
||||
version: 3.6
|
||||
pip_install: true
|
||||
extra_requirements:
|
||||
- docs
|
||||
- mongo
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
dist: xenial
|
||||
language: python
|
||||
cache: pip
|
||||
notifications:
|
||||
email: false
|
||||
sudo: true
|
||||
|
||||
python:
|
||||
- 3.6.6
|
||||
- 3.7
|
||||
env:
|
||||
global:
|
||||
PIPENV_IGNORE_VIRTUALENVS=1
|
||||
matrix:
|
||||
TOXENV=py
|
||||
|
||||
install:
|
||||
- pip install --upgrade pip tox
|
||||
|
||||
script:
|
||||
- tox
|
||||
|
||||
jobs:
|
||||
include:
|
||||
|
||||
- python: 3.6.6
|
||||
env: TOXENV=docs
|
||||
- python: 3.6.6
|
||||
env: TOXENV=style
|
||||
|
||||
# These jobs only occur on tag creation if the prior ones succeed
|
||||
- stage: PyPi Deployment
|
||||
if: tag IS present
|
||||
python: 3.6.6
|
||||
env:
|
||||
- DEPLOYING=true
|
||||
deploy:
|
||||
- provider: pypi
|
||||
user: Red-DiscordBot
|
||||
password:
|
||||
secure: Ty9vYnd/wCuQkVC/OsS4E2jT9LVDVfzsFrQc4U2hMYcTJnYbl/3omyObdCWCOBC40vUDkVHAQU8ULHzoCA+2KX9Ds/7/P5zCumAA0uJRR9Smw7OlRzSMxJI+/lGq4CwXKzxDZKuo5rsxXEbW5qmYjtO8Mk6KuLkvieb1vyr2DcqWEFzg/7TZNDfD1oP8et8ITQ26lLP1dtQx/jlAiIBzgK9wziuwj1Divb9A///VsGz43N8maZ+jfsDjYqrfUVWTy3ar7JPUplletenYCR1PmQ5C46XfV0kitKd1aITJ48YPAKyYgKy8AIT+Uz1JArTnqdzLSFRNELS57qS00lzgllbteCyWQ8Uzy0Zpxb/5DDH8/mL1n0MyJrF8qjZd2hLNAXg3z/k9bGXeiMLGwoxRlGXkL2XpiVgI93UKKyVyooGNMgPTc/QdSc7krjAWcOtX/HgLR34jxeLPFEdzJNAFIimfDD8N+XTFcNBw6EvOYm/n5MXkckNoX/G+ThNobHZ7VKSASltZ9zBRAJ2dDh35G3CYmVEk33U77RKbL9le/Za9QVBcAO8i6rqVGYkdO7thHHKHc/1CB1jNnjsFSDt0bURtNfAqfwKCurQC8487zbEzT+2fog3Wygv7g3cklaRg4guY8UjZuFWStYGqbroTsOCd9ATNqeO5B13pNhllSzU=
|
||||
skip_cleanup: true
|
||||
on:
|
||||
repo: Cog-Creators/Red-DiscordBot
|
||||
python: 3.6.6
|
||||
tags: true
|
||||
- stage: Crowdin Deployment
|
||||
if: tag IS present
|
||||
python: 3.6.6
|
||||
env:
|
||||
- DEPLOYING=true
|
||||
before_deploy:
|
||||
- curl https://artifacts.crowdin.com/repo/GPG-KEY-crowdin | sudo apt-key add -
|
||||
- echo "deb https://artifacts.crowdin.com/repo/deb/ /" | sudo tee -a /etc/apt/sources.list
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -y crowdin
|
||||
- pip install redgettext==2.2
|
||||
deploy:
|
||||
- provider: script
|
||||
script: make gettext
|
||||
skip_cleanup: true
|
||||
on:
|
||||
repo: Cog-Creators/Red-DiscordBot
|
||||
python: 3.6.6
|
||||
tags: true
|
||||
@@ -631,8 +631,8 @@ to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
{one line to give the program's name and a brief idea of what it does.}
|
||||
Copyright (C) {year} {name of author}
|
||||
Red - A fully customizable Discord bot
|
||||
Copyright (C) 2015-2018 Twentysix
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
{project} Copyright (C) {year} {fullname}
|
||||
Red-DiscordBot Copyright (C) 2015-2018 Twentysix
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
@@ -671,4 +671,4 @@ into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
include README.md
|
||||
include LICENSE
|
||||
include dependency_links.txt
|
||||
@@ -0,0 +1,7 @@
|
||||
reformat:
|
||||
black -l 99 -N `git ls-files "*.py"`
|
||||
stylecheck:
|
||||
black --check -l 99 -N `git ls-files "*.py"`
|
||||
gettext:
|
||||
redgettext --command-docstrings --verbose --recursive redbot --exclude-files "redbot/pytest/**/*"
|
||||
crowdin upload
|
||||
@@ -0,0 +1,12 @@
|
||||
[[source]]
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
"discord.py" = { git = 'git://github.com/Rapptz/discord.py', ref = 'rewrite', editable = true }
|
||||
"e1839a8" = { path = ".", editable = true, extras = ['mongo', 'voice'] }
|
||||
|
||||
[dev-packages]
|
||||
tox = "*"
|
||||
"e1839a9" = { path = ".", editable = true, extras = ['docs', 'test', 'style'] }
|
||||
Generated
+781
@@ -0,0 +1,781 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "edd35f353e1fadc20094e40de6627db77fd61303da01794214c44d748e99838b"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"aiohttp": {
|
||||
"hashes": [
|
||||
"sha256:0419705a36b43c0ac6f15469f9c2a08cad5c939d78bd12a5c23ea167c8253b2b",
|
||||
"sha256:1812fc4bc6ac1bde007daa05d2d0f61199324e0cc893b11523e646595047ca08",
|
||||
"sha256:2214b5c0153f45256d5d52d1e0cafe53f9905ed035a142191727a5fb620c03dd",
|
||||
"sha256:275909137f0c92c61ba6bb1af856a522d5546f1de8ea01e4e726321c697754ac",
|
||||
"sha256:3983611922b561868428ea1e7269e757803713f55b53502423decc509fef1650",
|
||||
"sha256:51afec6ffa50a9da4cdef188971a802beb1ca8e8edb40fa429e5e529db3475fa",
|
||||
"sha256:589f2ec8a101a0f340453ee6945bdfea8e1cd84c8d88e5be08716c34c0799d95",
|
||||
"sha256:789820ddc65e1f5e71516adaca2e9022498fa5a837c79ba9c692a9f8f916c330",
|
||||
"sha256:7a968a0bdaaf9abacc260911775611c9a602214a23aeb846f2eb2eeaa350c4dc",
|
||||
"sha256:7aeefbed253f59ea39e70c5848de42ed85cb941165357fc7e87ab5d8f1f9592b",
|
||||
"sha256:7b2eb55c66512405103485bd7d285a839d53e7fdc261ab20e5bcc51d7aaff5de",
|
||||
"sha256:87bc95d3d333bb689c8d755b4a9d7095a2356108002149523dfc8e607d5d32a4",
|
||||
"sha256:9d80e40db208e29168d3723d1440ecbb06054d349c5ece6a2c5a611490830dd7",
|
||||
"sha256:a1b442195c2a77d33e4dbee67c9877ccbdd3a1f686f91eb479a9577ed8cc326b",
|
||||
"sha256:ab3d769413b322d6092f169f316f7b21cd261a7589f7e31db779d5731b0480d8",
|
||||
"sha256:b066d3dec5d0f5aee6e34e5765095dc3d6d78ef9839640141a2b20816a0642bd",
|
||||
"sha256:b24e7845ae8de3e388ef4bcfcf7f96b05f52c8e633b33cf8003a6b1d726fc7c2",
|
||||
"sha256:c59a953c3f8524a7c86eaeaef5bf702555be12f5668f6384149fe4bb75c52698",
|
||||
"sha256:cf2cc6c2c10d242790412bea7ccf73726a9a44b4c4b073d2699ef3b48971fd95",
|
||||
"sha256:e0c9c8d4150ae904f308ff27b35446990d2b1dfc944702a21925937e937394c6",
|
||||
"sha256:f1839db4c2b08a9c8f9788112644f8a8557e8e0ecc77b07091afabb941dc55d0",
|
||||
"sha256:f3df52362be39908f9c028a65490fae0475e4898b43a03d8aa29d1e765b45e07"
|
||||
],
|
||||
"version": "==3.4.4"
|
||||
},
|
||||
"aiohttp-json-rpc": {
|
||||
"hashes": [
|
||||
"sha256:00d72f40edfc7271578d545a8c47874c0e23cc5d3201ed8128481f6a4af47e32",
|
||||
"sha256:02d83b6998f8a0b7e59b46f0cb8a96b475bbf82600b1f9527df47135353f1ca8"
|
||||
],
|
||||
"version": "==0.11.2"
|
||||
},
|
||||
"appdirs": {
|
||||
"hashes": [
|
||||
"sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92",
|
||||
"sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"
|
||||
],
|
||||
"version": "==1.4.3"
|
||||
},
|
||||
"async-timeout": {
|
||||
"hashes": [
|
||||
"sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f",
|
||||
"sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"
|
||||
],
|
||||
"version": "==3.0.1"
|
||||
},
|
||||
"attrs": {
|
||||
"hashes": [
|
||||
"sha256:10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69",
|
||||
"sha256:ca4be454458f9dec299268d472aaa5a11f67a4ff70093396e1ceae9c76cf4bbb"
|
||||
],
|
||||
"version": "==18.2.0"
|
||||
},
|
||||
"chardet": {
|
||||
"hashes": [
|
||||
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
|
||||
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
|
||||
],
|
||||
"version": "==3.0.4"
|
||||
},
|
||||
"colorama": {
|
||||
"hashes": [
|
||||
"sha256:05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d",
|
||||
"sha256:f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48"
|
||||
],
|
||||
"version": "==0.4.1"
|
||||
},
|
||||
"discord-py": {
|
||||
"editable": true,
|
||||
"git": "git://github.com/Rapptz/discord.py",
|
||||
"ref": "7f4c57dd5ad20b7fa10aea485f674a4bc24b9547"
|
||||
},
|
||||
"discord.py": {
|
||||
"editable": true,
|
||||
"git": "git://github.com/Rapptz/discord.py",
|
||||
"ref": "rewrite"
|
||||
},
|
||||
"distro": {
|
||||
"hashes": [
|
||||
"sha256:224041cef9600e72d19ae41ba006e71c05c4dc802516da715d7fda55ba3d8742",
|
||||
"sha256:6ec8e539cf412830e5ccf521aecf879f2c7fcf60ce446e33cd16eef1ed8a0158"
|
||||
],
|
||||
"version": "==1.3.0"
|
||||
},
|
||||
"dnspython": {
|
||||
"hashes": [
|
||||
"sha256:36c5e8e38d4369a08b6780b7f27d790a292b2b08eea01607865bf0936c558e01",
|
||||
"sha256:f69c21288a962f4da86e56c4905b49d11aba7938d3d740e80d9e366ee4f1632d"
|
||||
],
|
||||
"version": "==1.16.0"
|
||||
},
|
||||
"e1839a8": {
|
||||
"editable": true,
|
||||
"extras": [
|
||||
"mongo",
|
||||
"voice"
|
||||
],
|
||||
"path": "."
|
||||
},
|
||||
"fuzzywuzzy": {
|
||||
"hashes": [
|
||||
"sha256:5ac7c0b3f4658d2743aa17da53a55598144edbc5bee3c6863840636e6926f254",
|
||||
"sha256:6f49de47db00e1c71d40ad16da42284ac357936fa9b66bea1df63fed07122d62"
|
||||
],
|
||||
"version": "==0.17.0"
|
||||
},
|
||||
"idna": {
|
||||
"hashes": [
|
||||
"sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
|
||||
"sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"
|
||||
],
|
||||
"version": "==2.8"
|
||||
},
|
||||
"idna-ssl": {
|
||||
"hashes": [
|
||||
"sha256:a933e3bb13da54383f9e8f35dc4f9cb9eb9b3b78c6b36f311254d6d0d92c6c7c"
|
||||
],
|
||||
"version": "==1.1.0"
|
||||
},
|
||||
"motor": {
|
||||
"hashes": [
|
||||
"sha256:462fbb824f4289481c158227a2579d6adaf1ec7c70cf7ebe60ed6ceb321e5869",
|
||||
"sha256:d035c09ab422bc50bf3efb134f7405694cae76268545bd21e14fb22e2638f84e"
|
||||
],
|
||||
"version": "==2.0.0"
|
||||
},
|
||||
"multidict": {
|
||||
"hashes": [
|
||||
"sha256:024b8129695a952ebd93373e45b5d341dbb87c17ce49637b34000093f243dd4f",
|
||||
"sha256:041e9442b11409be5e4fc8b6a97e4bcead758ab1e11768d1e69160bdde18acc3",
|
||||
"sha256:045b4dd0e5f6121e6f314d81759abd2c257db4634260abcfe0d3f7083c4908ef",
|
||||
"sha256:047c0a04e382ef8bd74b0de01407e8d8632d7d1b4db6f2561106af812a68741b",
|
||||
"sha256:068167c2d7bbeebd359665ac4fff756be5ffac9cda02375b5c5a7c4777038e73",
|
||||
"sha256:148ff60e0fffa2f5fad2eb25aae7bef23d8f3b8bdaf947a65cdbe84a978092bc",
|
||||
"sha256:1d1c77013a259971a72ddaa83b9f42c80a93ff12df6a4723be99d858fa30bee3",
|
||||
"sha256:1d48bc124a6b7a55006d97917f695effa9725d05abe8ee78fd60d6588b8344cd",
|
||||
"sha256:31dfa2fc323097f8ad7acd41aa38d7c614dd1960ac6681745b6da124093dc351",
|
||||
"sha256:34f82db7f80c49f38b032c5abb605c458bac997a6c3142e0d6c130be6fb2b941",
|
||||
"sha256:3d5dd8e5998fb4ace04789d1d008e2bb532de501218519d70bb672c4c5a2fc5d",
|
||||
"sha256:4a6ae52bd3ee41ee0f3acf4c60ceb3f44e0e3bc52ab7da1c2b2aa6703363a3d1",
|
||||
"sha256:4b02a3b2a2f01d0490dd39321c74273fed0568568ea0e7ea23e02bd1fb10a10b",
|
||||
"sha256:4b843f8e1dd6a3195679d9838eb4670222e8b8d01bc36c9894d6c3538316fa0a",
|
||||
"sha256:5de53a28f40ef3c4fd57aeab6b590c2c663de87a5af76136ced519923d3efbb3",
|
||||
"sha256:61b2b33ede821b94fa99ce0b09c9ece049c7067a33b279f343adfe35108a4ea7",
|
||||
"sha256:6a3a9b0f45fd75dc05d8e93dc21b18fc1670135ec9544d1ad4acbcf6b86781d0",
|
||||
"sha256:76ad8e4c69dadbb31bad17c16baee61c0d1a4a73bed2590b741b2e1a46d3edd0",
|
||||
"sha256:7ba19b777dc00194d1b473180d4ca89a054dd18de27d0ee2e42a103ec9b7d014",
|
||||
"sha256:7c1b7eab7a49aa96f3db1f716f0113a8a2e93c7375dd3d5d21c4941f1405c9c5",
|
||||
"sha256:7fc0eee3046041387cbace9314926aa48b681202f8897f8bff3809967a049036",
|
||||
"sha256:8ccd1c5fff1aa1427100ce188557fc31f1e0a383ad8ec42c559aabd4ff08802d",
|
||||
"sha256:8e08dd76de80539d613654915a2f5196dbccc67448df291e69a88712ea21e24a",
|
||||
"sha256:c18498c50c59263841862ea0501da9f2b3659c00db54abfbf823a80787fde8ce",
|
||||
"sha256:c49db89d602c24928e68c0d510f4fcf8989d77defd01c973d6cbe27e684833b1",
|
||||
"sha256:ce20044d0317649ddbb4e54dab3c1bcc7483c78c27d3f58ab3d0c7e6bc60d26a",
|
||||
"sha256:d1071414dd06ca2eafa90c85a079169bfeb0e5f57fd0b45d44c092546fcd6fd9",
|
||||
"sha256:d3be11ac43ab1a3e979dac80843b42226d5d3cccd3986f2e03152720a4297cd7",
|
||||
"sha256:db603a1c235d110c860d5f39988ebc8218ee028f07a7cbc056ba6424372ca31b"
|
||||
],
|
||||
"version": "==4.5.2"
|
||||
},
|
||||
"pymongo": {
|
||||
"hashes": [
|
||||
"sha256:025f94fc1e1364f00e50badc88c47f98af20012f23317234e51a11333ef986e6",
|
||||
"sha256:02aa7fb282606331aefbc0586e2cf540e9dbe5e343493295e7f390936ad2738e",
|
||||
"sha256:057210e831573e932702cf332012ed39da78edf0f02d24a3f0b213264a87a397",
|
||||
"sha256:0d946b79c56187fe139276d4c8ed612a27a616966c8b9779d6b79e2053587c8b",
|
||||
"sha256:104790893b928d310aae8a955e0bdbaa442fb0ac0a33d1bbb0741c791a407778",
|
||||
"sha256:15527ef218d95a8717486106553b0d54ff2641e795b65668754e17ab9ca6e381",
|
||||
"sha256:1826527a0b032f6e20e7ac7f72d7c26dd476a5e5aa82c04aa1c7088a59fded7d",
|
||||
"sha256:22e3aa4ce1c3eebc7f70f9ca7fd4ce1ea33e8bdb7b61996806cd312f08f84a3a",
|
||||
"sha256:244e1101e9a48615b9a16cbd194f73c115fdfefc96894803158608115f703b26",
|
||||
"sha256:24b8c04fdb633a84829d03909752c385faef249c06114cc8d8e1700b95aae5c8",
|
||||
"sha256:2c276696350785d3104412cbe3ac70ab1e3a10c408e7b20599ee41403a3ed630",
|
||||
"sha256:2d8474dc833b1182b651b184ace997a7bd83de0f51244de988d3c30e49f07de3",
|
||||
"sha256:3119b57fe1d964781e91a53e81532c85ed1701baaddec592e22f6b77a9fdf3df",
|
||||
"sha256:3bee8e7e0709b0fcdaa498a3e513bde9ffc7cd09dbceb11e425bd91c89dbd5b6",
|
||||
"sha256:436c071e01a464753d30dbfc8768dd93aecf2a8e378e5314d130b95e77b4d612",
|
||||
"sha256:46635e3f19ad04d5a7d7cf23d232388ddbfccf46d9a3b7436b6abadda4e84813",
|
||||
"sha256:4772e0b679717e7ac4608d996f57b6f380748a919b457cb05bb941467b888b22",
|
||||
"sha256:4e2cd80e16f481a62c3175b607373200e714ed29025f21559ebf7524f295689f",
|
||||
"sha256:52732960efa0e003ca1c092dc0a3c65276e897681287a788a01ca78dda3b41f0",
|
||||
"sha256:55a7de51ec7d1731b2431886d0349146645f2816e5b8eb982d7c49f89472c9f3",
|
||||
"sha256:5f8ed5934197a2d4b2087646e98de3e099a237099dcf498b9e38dd3465f74ef4",
|
||||
"sha256:64b064124fcbc8eb04a155117dc4d9a336e3cda3f069958fbc44fe70c3c3d1e9",
|
||||
"sha256:65958b8e4319f992e85dad59d8081888b97fcdbde5f0d14bc28f2848b92d3ef1",
|
||||
"sha256:7683428862e20c6a790c19e64f8ccf487f613fbc83d47e3d532df9c81668d451",
|
||||
"sha256:78566d5570c75a127c2491e343dc006798a384f06be588fe9b0cbe5595711559",
|
||||
"sha256:7d1cb00c093dbf1d0b16ccf123e79dee3b82608e4a2a88947695f0460eef13ff",
|
||||
"sha256:8c74e2a9b594f7962c62cef7680a4cb92a96b4e6e3c2f970790da67cc0213a7e",
|
||||
"sha256:8e60aa7699170f55f4b0f56ee6f8415229777ac7e4b4b1aa41fc61eec08c1f1d",
|
||||
"sha256:9447b561529576d89d3bf973e5241a88cf76e45bd101963f5236888713dea774",
|
||||
"sha256:970055bfeb0be373f2f5299a3db8432444bad3bc2f198753ee6c2a3a781e0959",
|
||||
"sha256:a6344b8542e584e140dc3c651d68bde51270e79490aa9320f9e708f9b2c39bd5",
|
||||
"sha256:ce309ca470d747b02ba6069d286a17b7df8e9c94d10d727d9cf3a64e51d85184",
|
||||
"sha256:cfbd86ed4c2b2ac71bbdbcea6669bf295def7152e3722ddd9dda94ac7981f33d",
|
||||
"sha256:d7929c513732dff093481f4a0954ed5ff16816365842136b17caa0b4992e49d3"
|
||||
],
|
||||
"version": "==3.7.2"
|
||||
},
|
||||
"python-levenshtein": {
|
||||
"hashes": [
|
||||
"sha256:033a11de5e3d19ea25c9302d11224e1a1898fe5abd23c61c7c360c25195e3eb1"
|
||||
],
|
||||
"version": "==0.12.0"
|
||||
},
|
||||
"pyyaml": {
|
||||
"hashes": [
|
||||
"sha256:3d7da3009c0f3e783b2c873687652d83b1bbfd5c88e9813fb7e5b03c0dd3108b",
|
||||
"sha256:3ef3092145e9b70e3ddd2c7ad59bdd0252a94dfe3949721633e41344de00a6bf",
|
||||
"sha256:40c71b8e076d0550b2e6380bada1f1cd1017b882f7e16f09a65be98e017f211a",
|
||||
"sha256:558dd60b890ba8fd982e05941927a3911dc409a63dcb8b634feaa0cda69330d3",
|
||||
"sha256:a7c28b45d9f99102fa092bb213aa12e0aaf9a6a1f5e395d36166639c1f96c3a1",
|
||||
"sha256:aa7dd4a6a427aed7df6fb7f08a580d68d9b118d90310374716ae90b710280af1",
|
||||
"sha256:bc558586e6045763782014934bfaf39d48b8ae85a2713117d16c39864085c613",
|
||||
"sha256:d46d7982b62e0729ad0175a9bc7e10a566fc07b224d2c79fafb5e032727eaa04",
|
||||
"sha256:d5eef459e30b09f5a098b9cea68bebfeb268697f78d647bd255a085371ac7f3f",
|
||||
"sha256:e01d3203230e1786cd91ccfdc8f8454c8069c91bee3962ad93b87a4b2860f537",
|
||||
"sha256:e170a9e6fcfd19021dd29845af83bb79236068bf5fd4df3327c1be18182b2531"
|
||||
],
|
||||
"version": "==3.13"
|
||||
},
|
||||
"raven": {
|
||||
"hashes": [
|
||||
"sha256:3fa6de6efa2493a7c827472e984ce9b020797d0da16f1db67197bcc23c8fae54",
|
||||
"sha256:44a13f87670836e153951af9a3c80405d36b43097db869a36e92809673692ce4"
|
||||
],
|
||||
"version": "==6.10.0"
|
||||
},
|
||||
"raven-aiohttp": {
|
||||
"hashes": [
|
||||
"sha256:1444a49c93a85b8bb57c6ee649e512368dce7a26ad64ac3a01d86aa5669d77f3",
|
||||
"sha256:6a34b6a9841ad0fd827eeb158edb5826c5c5bd7babe2cde2a3f23eb85313af04"
|
||||
],
|
||||
"version": "==0.7.0"
|
||||
},
|
||||
"red-lavalink": {
|
||||
"hashes": [
|
||||
"sha256:6a1a34471ccf4630eee537049568dd87e8e93614f1d1ce355dd74e5b10079782"
|
||||
],
|
||||
"version": "==0.1.2"
|
||||
},
|
||||
"schema": {
|
||||
"hashes": [
|
||||
"sha256:d994b0dc4966000037b26898df638e3e2a694cc73636cb2050e652614a350687",
|
||||
"sha256:fa1a53fe5f3b6929725a4e81688c250f46838e25d8c1885a10a590c8c01a7b74"
|
||||
],
|
||||
"version": "==0.6.8"
|
||||
},
|
||||
"websockets": {
|
||||
"hashes": [
|
||||
"sha256:0e2f7d6567838369af074f0ef4d0b802d19fa1fee135d864acc656ceefa33136",
|
||||
"sha256:2a16dac282b2fdae75178d0ed3d5b9bc3258dabfae50196cbb30578d84b6f6a6",
|
||||
"sha256:5a1fa6072405648cb5b3688e9ed3b94be683ce4a4e5723e6f5d34859dee495c1",
|
||||
"sha256:5c1f55a1274df9d6a37553fef8cff2958515438c58920897675c9bc70f5a0538",
|
||||
"sha256:669d1e46f165e0ad152ed8197f7edead22854a6c90419f544e0f234cc9dac6c4",
|
||||
"sha256:695e34c4dbea18d09ab2c258994a8bf6a09564e762655408241f6a14592d2908",
|
||||
"sha256:6b2e03d69afa8d20253455e67b64de1a82ff8612db105113cccec35d3f8429f0",
|
||||
"sha256:79ca7cdda7ad4e3663ea3c43bfa8637fc5d5604c7737f19a8964781abbd1148d",
|
||||
"sha256:7fd2dd9a856f72e6ed06f82facfce01d119b88457cd4b47b7ae501e8e11eba9c",
|
||||
"sha256:82c0354ac39379d836719a77ee360ef865377aa6fdead87909d50248d0f05f4d",
|
||||
"sha256:8f3b956d11c5b301206382726210dc1d3bee1a9ccf7aadf895aaf31f71c3716c",
|
||||
"sha256:91ec98640220ae05b34b79ee88abf27f97ef7c61cf525eec57ea8fcea9f7dddb",
|
||||
"sha256:952be9540d83dba815569d5cb5f31708801e0bbfc3a8c5aef1890b57ed7e58bf",
|
||||
"sha256:99ac266af38ba1b1fe13975aea01ac0e14bb5f3a3200d2c69f05385768b8568e",
|
||||
"sha256:9fa122e7adb24232247f8a89f2d9070bf64b7869daf93ac5e19546b409e47e96",
|
||||
"sha256:a0873eadc4b8ca93e2e848d490809e0123eea154aa44ecd0109c4d0171869584",
|
||||
"sha256:cb998bd4d93af46b8b49ecf5a72c0a98e5cc6d57fdca6527ba78ad89d6606484",
|
||||
"sha256:e02e57346f6a68523e3c43bbdf35dde5c440318d1f827208ae455f6a2ace446d",
|
||||
"sha256:e79a5a896bcee7fff24a788d72e5c69f13e61369d055f28113e71945a7eb1559",
|
||||
"sha256:ee55eb6bcf23ecc975e6b47c127c201b913598f38b6a300075f84eeef2d3baff",
|
||||
"sha256:f1414e6cbcea8d22843e7eafdfdfae3dd1aba41d1945f6ca66e4806c07c4f454"
|
||||
],
|
||||
"version": "==6.0"
|
||||
},
|
||||
"yarl": {
|
||||
"hashes": [
|
||||
"sha256:024ecdc12bc02b321bc66b41327f930d1c2c543fa9a561b39861da9388ba7aa9",
|
||||
"sha256:2f3010703295fbe1aec51023740871e64bb9664c789cba5a6bdf404e93f7568f",
|
||||
"sha256:3890ab952d508523ef4881457c4099056546593fa05e93da84c7250516e632eb",
|
||||
"sha256:3e2724eb9af5dc41648e5bb304fcf4891adc33258c6e14e2a7414ea32541e320",
|
||||
"sha256:5badb97dd0abf26623a9982cd448ff12cb39b8e4c94032ccdedf22ce01a64842",
|
||||
"sha256:73f447d11b530d860ca1e6b582f947688286ad16ca42256413083d13f260b7a0",
|
||||
"sha256:7ab825726f2940c16d92aaec7d204cfc34ac26c0040da727cf8ba87255a33829",
|
||||
"sha256:b25de84a8c20540531526dfbb0e2d2b648c13fd5dd126728c496d7c3fea33310",
|
||||
"sha256:c6e341f5a6562af74ba55205dbd56d248daf1b5748ec48a0200ba227bb9e33f4",
|
||||
"sha256:c9bb7c249c4432cd47e75af3864bc02d26c9594f49c82e2a28624417f0ae63b8",
|
||||
"sha256:e060906c0c585565c718d1c3841747b61c5439af2211e185f6739a9412dfbde1"
|
||||
],
|
||||
"version": "==1.3.0"
|
||||
}
|
||||
},
|
||||
"develop": {
|
||||
"aiohttp": {
|
||||
"hashes": [
|
||||
"sha256:0419705a36b43c0ac6f15469f9c2a08cad5c939d78bd12a5c23ea167c8253b2b",
|
||||
"sha256:1812fc4bc6ac1bde007daa05d2d0f61199324e0cc893b11523e646595047ca08",
|
||||
"sha256:2214b5c0153f45256d5d52d1e0cafe53f9905ed035a142191727a5fb620c03dd",
|
||||
"sha256:275909137f0c92c61ba6bb1af856a522d5546f1de8ea01e4e726321c697754ac",
|
||||
"sha256:3983611922b561868428ea1e7269e757803713f55b53502423decc509fef1650",
|
||||
"sha256:51afec6ffa50a9da4cdef188971a802beb1ca8e8edb40fa429e5e529db3475fa",
|
||||
"sha256:589f2ec8a101a0f340453ee6945bdfea8e1cd84c8d88e5be08716c34c0799d95",
|
||||
"sha256:789820ddc65e1f5e71516adaca2e9022498fa5a837c79ba9c692a9f8f916c330",
|
||||
"sha256:7a968a0bdaaf9abacc260911775611c9a602214a23aeb846f2eb2eeaa350c4dc",
|
||||
"sha256:7aeefbed253f59ea39e70c5848de42ed85cb941165357fc7e87ab5d8f1f9592b",
|
||||
"sha256:7b2eb55c66512405103485bd7d285a839d53e7fdc261ab20e5bcc51d7aaff5de",
|
||||
"sha256:87bc95d3d333bb689c8d755b4a9d7095a2356108002149523dfc8e607d5d32a4",
|
||||
"sha256:9d80e40db208e29168d3723d1440ecbb06054d349c5ece6a2c5a611490830dd7",
|
||||
"sha256:a1b442195c2a77d33e4dbee67c9877ccbdd3a1f686f91eb479a9577ed8cc326b",
|
||||
"sha256:ab3d769413b322d6092f169f316f7b21cd261a7589f7e31db779d5731b0480d8",
|
||||
"sha256:b066d3dec5d0f5aee6e34e5765095dc3d6d78ef9839640141a2b20816a0642bd",
|
||||
"sha256:b24e7845ae8de3e388ef4bcfcf7f96b05f52c8e633b33cf8003a6b1d726fc7c2",
|
||||
"sha256:c59a953c3f8524a7c86eaeaef5bf702555be12f5668f6384149fe4bb75c52698",
|
||||
"sha256:cf2cc6c2c10d242790412bea7ccf73726a9a44b4c4b073d2699ef3b48971fd95",
|
||||
"sha256:e0c9c8d4150ae904f308ff27b35446990d2b1dfc944702a21925937e937394c6",
|
||||
"sha256:f1839db4c2b08a9c8f9788112644f8a8557e8e0ecc77b07091afabb941dc55d0",
|
||||
"sha256:f3df52362be39908f9c028a65490fae0475e4898b43a03d8aa29d1e765b45e07"
|
||||
],
|
||||
"version": "==3.4.4"
|
||||
},
|
||||
"aiohttp-json-rpc": {
|
||||
"hashes": [
|
||||
"sha256:00d72f40edfc7271578d545a8c47874c0e23cc5d3201ed8128481f6a4af47e32",
|
||||
"sha256:02d83b6998f8a0b7e59b46f0cb8a96b475bbf82600b1f9527df47135353f1ca8"
|
||||
],
|
||||
"version": "==0.11.2"
|
||||
},
|
||||
"alabaster": {
|
||||
"hashes": [
|
||||
"sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359",
|
||||
"sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"
|
||||
],
|
||||
"version": "==0.7.12"
|
||||
},
|
||||
"appdirs": {
|
||||
"hashes": [
|
||||
"sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92",
|
||||
"sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"
|
||||
],
|
||||
"version": "==1.4.3"
|
||||
},
|
||||
"async-timeout": {
|
||||
"hashes": [
|
||||
"sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f",
|
||||
"sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"
|
||||
],
|
||||
"version": "==3.0.1"
|
||||
},
|
||||
"atomicwrites": {
|
||||
"hashes": [
|
||||
"sha256:0312ad34fcad8fac3704d441f7b317e50af620823353ec657a53e981f92920c0",
|
||||
"sha256:ec9ae8adaae229e4f8446952d204a3e4b5fdd2d099f9be3aaf556120135fb3ee"
|
||||
],
|
||||
"version": "==1.2.1"
|
||||
},
|
||||
"attrs": {
|
||||
"hashes": [
|
||||
"sha256:10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69",
|
||||
"sha256:ca4be454458f9dec299268d472aaa5a11f67a4ff70093396e1ceae9c76cf4bbb"
|
||||
],
|
||||
"version": "==18.2.0"
|
||||
},
|
||||
"babel": {
|
||||
"hashes": [
|
||||
"sha256:6778d85147d5d85345c14a26aada5e478ab04e39b078b0745ee6870c2b5cf669",
|
||||
"sha256:8cba50f48c529ca3fa18cf81fa9403be176d374ac4d60738b839122dfaaa3d23"
|
||||
],
|
||||
"version": "==2.6.0"
|
||||
},
|
||||
"black": {
|
||||
"hashes": [
|
||||
"sha256:817243426042db1d36617910df579a54f1afd659adb96fc5032fcf4b36209739",
|
||||
"sha256:e030a9a28f542debc08acceb273f228ac422798e5215ba2a791a6ddeaaca22a5"
|
||||
],
|
||||
"version": "==18.9b0"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7",
|
||||
"sha256:993f830721089fef441cdfeb4b2c8c9df86f0c63239f06bd025a76a7daddb033"
|
||||
],
|
||||
"version": "==2018.11.29"
|
||||
},
|
||||
"chardet": {
|
||||
"hashes": [
|
||||
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
|
||||
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
|
||||
],
|
||||
"version": "==3.0.4"
|
||||
},
|
||||
"click": {
|
||||
"hashes": [
|
||||
"sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13",
|
||||
"sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"
|
||||
],
|
||||
"version": "==7.0"
|
||||
},
|
||||
"colorama": {
|
||||
"hashes": [
|
||||
"sha256:05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d",
|
||||
"sha256:f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48"
|
||||
],
|
||||
"version": "==0.4.1"
|
||||
},
|
||||
"distro": {
|
||||
"hashes": [
|
||||
"sha256:224041cef9600e72d19ae41ba006e71c05c4dc802516da715d7fda55ba3d8742",
|
||||
"sha256:6ec8e539cf412830e5ccf521aecf879f2c7fcf60ce446e33cd16eef1ed8a0158"
|
||||
],
|
||||
"version": "==1.3.0"
|
||||
},
|
||||
"docutils": {
|
||||
"hashes": [
|
||||
"sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6",
|
||||
"sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274",
|
||||
"sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6"
|
||||
],
|
||||
"version": "==0.14"
|
||||
},
|
||||
"e1839a9": {
|
||||
"editable": true,
|
||||
"extras": [
|
||||
"docs",
|
||||
"test",
|
||||
"style"
|
||||
],
|
||||
"path": "."
|
||||
},
|
||||
"filelock": {
|
||||
"hashes": [
|
||||
"sha256:b8d5ca5ca1c815e1574aee746650ea7301de63d87935b3463d26368b76e31633",
|
||||
"sha256:d610c1bb404daf85976d7a82eb2ada120f04671007266b708606565dd03b5be6"
|
||||
],
|
||||
"version": "==3.0.10"
|
||||
},
|
||||
"fuzzywuzzy": {
|
||||
"hashes": [
|
||||
"sha256:5ac7c0b3f4658d2743aa17da53a55598144edbc5bee3c6863840636e6926f254",
|
||||
"sha256:6f49de47db00e1c71d40ad16da42284ac357936fa9b66bea1df63fed07122d62"
|
||||
],
|
||||
"version": "==0.17.0"
|
||||
},
|
||||
"idna": {
|
||||
"hashes": [
|
||||
"sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
|
||||
"sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"
|
||||
],
|
||||
"version": "==2.8"
|
||||
},
|
||||
"idna-ssl": {
|
||||
"hashes": [
|
||||
"sha256:a933e3bb13da54383f9e8f35dc4f9cb9eb9b3b78c6b36f311254d6d0d92c6c7c"
|
||||
],
|
||||
"version": "==1.1.0"
|
||||
},
|
||||
"imagesize": {
|
||||
"hashes": [
|
||||
"sha256:3f349de3eb99145973fefb7dbe38554414e5c30abd0c8e4b970a7c9d09f3a1d8",
|
||||
"sha256:f3832918bc3c66617f92e35f5d70729187676313caa60c187eb0f28b8fe5e3b5"
|
||||
],
|
||||
"version": "==1.1.0"
|
||||
},
|
||||
"jinja2": {
|
||||
"hashes": [
|
||||
"sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd",
|
||||
"sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"
|
||||
],
|
||||
"version": "==2.10"
|
||||
},
|
||||
"markupsafe": {
|
||||
"hashes": [
|
||||
"sha256:048ef924c1623740e70204aa7143ec592504045ae4429b59c30054cb31e3c432",
|
||||
"sha256:130f844e7f5bdd8e9f3f42e7102ef1d49b2e6fdf0d7526df3f87281a532d8c8b",
|
||||
"sha256:19f637c2ac5ae9da8bfd98cef74d64b7e1bb8a63038a3505cd182c3fac5eb4d9",
|
||||
"sha256:1b8a7a87ad1b92bd887568ce54b23565f3fd7018c4180136e1cf412b405a47af",
|
||||
"sha256:1c25694ca680b6919de53a4bb3bdd0602beafc63ff001fea2f2fc16ec3a11834",
|
||||
"sha256:1f19ef5d3908110e1e891deefb5586aae1b49a7440db952454b4e281b41620cd",
|
||||
"sha256:1fa6058938190ebe8290e5cae6c351e14e7bb44505c4a7624555ce57fbbeba0d",
|
||||
"sha256:31cbb1359e8c25f9f48e156e59e2eaad51cd5242c05ed18a8de6dbe85184e4b7",
|
||||
"sha256:3e835d8841ae7863f64e40e19477f7eb398674da6a47f09871673742531e6f4b",
|
||||
"sha256:4e97332c9ce444b0c2c38dd22ddc61c743eb208d916e4265a2a3b575bdccb1d3",
|
||||
"sha256:525396ee324ee2da82919f2ee9c9e73b012f23e7640131dd1b53a90206a0f09c",
|
||||
"sha256:52b07fbc32032c21ad4ab060fec137b76eb804c4b9a1c7c7dc562549306afad2",
|
||||
"sha256:52ccb45e77a1085ec5461cde794e1aa037df79f473cbc69b974e73940655c8d7",
|
||||
"sha256:5c3fbebd7de20ce93103cb3183b47671f2885307df4a17a0ad56a1dd51273d36",
|
||||
"sha256:5e5851969aea17660e55f6a3be00037a25b96a9b44d2083651812c99d53b14d1",
|
||||
"sha256:5edfa27b2d3eefa2210fb2f5d539fbed81722b49f083b2c6566455eb7422fd7e",
|
||||
"sha256:7d263e5770efddf465a9e31b78362d84d015cc894ca2c131901a4445eaa61ee1",
|
||||
"sha256:83381342bfc22b3c8c06f2dd93a505413888694302de25add756254beee8449c",
|
||||
"sha256:857eebb2c1dc60e4219ec8e98dfa19553dae33608237e107db9c6078b1167856",
|
||||
"sha256:98e439297f78fca3a6169fd330fbe88d78b3bb72f967ad9961bcac0d7fdd1550",
|
||||
"sha256:bf54103892a83c64db58125b3f2a43df6d2cb2d28889f14c78519394feb41492",
|
||||
"sha256:d9ac82be533394d341b41d78aca7ed0e0f4ba5a2231602e2f05aa87f25c51672",
|
||||
"sha256:e982fe07ede9fada6ff6705af70514a52beb1b2c3d25d4e873e82114cf3c5401",
|
||||
"sha256:edce2ea7f3dfc981c4ddc97add8a61381d9642dc3273737e756517cc03e84dd6",
|
||||
"sha256:efdc45ef1afc238db84cb4963aa689c0408912a0239b0721cb172b4016eb31d6",
|
||||
"sha256:f137c02498f8b935892d5c0172560d7ab54bc45039de8805075e19079c639a9c",
|
||||
"sha256:f82e347a72f955b7017a39708a3667f106e6ad4d10b25f237396a7115d8ed5fd",
|
||||
"sha256:fb7c206e01ad85ce57feeaaa0bf784b97fa3cad0d4a5737bc5295785f5c613a1"
|
||||
],
|
||||
"version": "==1.1.0"
|
||||
},
|
||||
"more-itertools": {
|
||||
"hashes": [
|
||||
"sha256:38a936c0a6d98a38bcc2d03fdaaedaba9f412879461dd2ceff8d37564d6522e4",
|
||||
"sha256:c0a5785b1109a6bd7fac76d6837fd1feca158e54e521ccd2ae8bfe393cc9d4fc",
|
||||
"sha256:fe7a7cae1ccb57d33952113ff4fa1bc5f879963600ed74918f1236e212ee50b9"
|
||||
],
|
||||
"version": "==5.0.0"
|
||||
},
|
||||
"multidict": {
|
||||
"hashes": [
|
||||
"sha256:024b8129695a952ebd93373e45b5d341dbb87c17ce49637b34000093f243dd4f",
|
||||
"sha256:041e9442b11409be5e4fc8b6a97e4bcead758ab1e11768d1e69160bdde18acc3",
|
||||
"sha256:045b4dd0e5f6121e6f314d81759abd2c257db4634260abcfe0d3f7083c4908ef",
|
||||
"sha256:047c0a04e382ef8bd74b0de01407e8d8632d7d1b4db6f2561106af812a68741b",
|
||||
"sha256:068167c2d7bbeebd359665ac4fff756be5ffac9cda02375b5c5a7c4777038e73",
|
||||
"sha256:148ff60e0fffa2f5fad2eb25aae7bef23d8f3b8bdaf947a65cdbe84a978092bc",
|
||||
"sha256:1d1c77013a259971a72ddaa83b9f42c80a93ff12df6a4723be99d858fa30bee3",
|
||||
"sha256:1d48bc124a6b7a55006d97917f695effa9725d05abe8ee78fd60d6588b8344cd",
|
||||
"sha256:31dfa2fc323097f8ad7acd41aa38d7c614dd1960ac6681745b6da124093dc351",
|
||||
"sha256:34f82db7f80c49f38b032c5abb605c458bac997a6c3142e0d6c130be6fb2b941",
|
||||
"sha256:3d5dd8e5998fb4ace04789d1d008e2bb532de501218519d70bb672c4c5a2fc5d",
|
||||
"sha256:4a6ae52bd3ee41ee0f3acf4c60ceb3f44e0e3bc52ab7da1c2b2aa6703363a3d1",
|
||||
"sha256:4b02a3b2a2f01d0490dd39321c74273fed0568568ea0e7ea23e02bd1fb10a10b",
|
||||
"sha256:4b843f8e1dd6a3195679d9838eb4670222e8b8d01bc36c9894d6c3538316fa0a",
|
||||
"sha256:5de53a28f40ef3c4fd57aeab6b590c2c663de87a5af76136ced519923d3efbb3",
|
||||
"sha256:61b2b33ede821b94fa99ce0b09c9ece049c7067a33b279f343adfe35108a4ea7",
|
||||
"sha256:6a3a9b0f45fd75dc05d8e93dc21b18fc1670135ec9544d1ad4acbcf6b86781d0",
|
||||
"sha256:76ad8e4c69dadbb31bad17c16baee61c0d1a4a73bed2590b741b2e1a46d3edd0",
|
||||
"sha256:7ba19b777dc00194d1b473180d4ca89a054dd18de27d0ee2e42a103ec9b7d014",
|
||||
"sha256:7c1b7eab7a49aa96f3db1f716f0113a8a2e93c7375dd3d5d21c4941f1405c9c5",
|
||||
"sha256:7fc0eee3046041387cbace9314926aa48b681202f8897f8bff3809967a049036",
|
||||
"sha256:8ccd1c5fff1aa1427100ce188557fc31f1e0a383ad8ec42c559aabd4ff08802d",
|
||||
"sha256:8e08dd76de80539d613654915a2f5196dbccc67448df291e69a88712ea21e24a",
|
||||
"sha256:c18498c50c59263841862ea0501da9f2b3659c00db54abfbf823a80787fde8ce",
|
||||
"sha256:c49db89d602c24928e68c0d510f4fcf8989d77defd01c973d6cbe27e684833b1",
|
||||
"sha256:ce20044d0317649ddbb4e54dab3c1bcc7483c78c27d3f58ab3d0c7e6bc60d26a",
|
||||
"sha256:d1071414dd06ca2eafa90c85a079169bfeb0e5f57fd0b45d44c092546fcd6fd9",
|
||||
"sha256:d3be11ac43ab1a3e979dac80843b42226d5d3cccd3986f2e03152720a4297cd7",
|
||||
"sha256:db603a1c235d110c860d5f39988ebc8218ee028f07a7cbc056ba6424372ca31b"
|
||||
],
|
||||
"version": "==4.5.2"
|
||||
},
|
||||
"packaging": {
|
||||
"hashes": [
|
||||
"sha256:0886227f54515e592aaa2e5a553332c73962917f2831f1b0f9b9f4380a4b9807",
|
||||
"sha256:f95a1e147590f204328170981833854229bb2912ac3d5f89e2a8ccd2834800c9"
|
||||
],
|
||||
"version": "==18.0"
|
||||
},
|
||||
"pluggy": {
|
||||
"hashes": [
|
||||
"sha256:8ddc32f03971bfdf900a81961a48ccf2fb677cf7715108f85295c67405798616",
|
||||
"sha256:980710797ff6a041e9a73a5787804f848996ecaa6f8a1b1e08224a5894f2074a"
|
||||
],
|
||||
"version": "==0.8.1"
|
||||
},
|
||||
"py": {
|
||||
"hashes": [
|
||||
"sha256:bf92637198836372b520efcba9e020c330123be8ce527e535d185ed4b6f45694",
|
||||
"sha256:e76826342cefe3c3d5f7e8ee4316b80d1dd8a300781612ddbc765c17ba25a6c6"
|
||||
],
|
||||
"version": "==1.7.0"
|
||||
},
|
||||
"pygments": {
|
||||
"hashes": [
|
||||
"sha256:5ffada19f6203563680669ee7f53b64dabbeb100eb51b61996085e99c03b284a",
|
||||
"sha256:e8218dd399a61674745138520d0d4cf2621d7e032439341bc3f647bff125818d"
|
||||
],
|
||||
"version": "==2.3.1"
|
||||
},
|
||||
"pyparsing": {
|
||||
"hashes": [
|
||||
"sha256:40856e74d4987de5d01761a22d1621ae1c7f8774585acae358aa5c5936c6c90b",
|
||||
"sha256:f353aab21fd474459d97b709e527b5571314ee5f067441dc9f88e33eecd96592"
|
||||
],
|
||||
"version": "==2.3.0"
|
||||
},
|
||||
"pytest": {
|
||||
"hashes": [
|
||||
"sha256:3e65a22eb0d4f1bdbc1eacccf4a3198bf8d4049dea5112d70a0c61b00e748d02",
|
||||
"sha256:5924060b374f62608a078494b909d341720a050b5224ff87e17e12377486a71d"
|
||||
],
|
||||
"version": "==4.1.0"
|
||||
},
|
||||
"pytest-asyncio": {
|
||||
"hashes": [
|
||||
"sha256:9fac5100fd716cbecf6ef89233e8590a4ad61d729d1732e0a96b84182df1daaf",
|
||||
"sha256:d734718e25cfc32d2bf78d346e99d33724deeba774cc4afdf491530c6184b63b"
|
||||
],
|
||||
"version": "==0.10.0"
|
||||
},
|
||||
"python-levenshtein": {
|
||||
"hashes": [
|
||||
"sha256:033a11de5e3d19ea25c9302d11224e1a1898fe5abd23c61c7c360c25195e3eb1"
|
||||
],
|
||||
"version": "==0.12.0"
|
||||
},
|
||||
"pytz": {
|
||||
"hashes": [
|
||||
"sha256:32b0891edff07e28efe91284ed9c31e123d84bea3fd98e1f72be2508f43ef8d9",
|
||||
"sha256:d5f05e487007e29e03409f9398d074e158d920d36eb82eaf66fb1136b0c5374c"
|
||||
],
|
||||
"version": "==2018.9"
|
||||
},
|
||||
"pyyaml": {
|
||||
"hashes": [
|
||||
"sha256:3d7da3009c0f3e783b2c873687652d83b1bbfd5c88e9813fb7e5b03c0dd3108b",
|
||||
"sha256:3ef3092145e9b70e3ddd2c7ad59bdd0252a94dfe3949721633e41344de00a6bf",
|
||||
"sha256:40c71b8e076d0550b2e6380bada1f1cd1017b882f7e16f09a65be98e017f211a",
|
||||
"sha256:558dd60b890ba8fd982e05941927a3911dc409a63dcb8b634feaa0cda69330d3",
|
||||
"sha256:a7c28b45d9f99102fa092bb213aa12e0aaf9a6a1f5e395d36166639c1f96c3a1",
|
||||
"sha256:aa7dd4a6a427aed7df6fb7f08a580d68d9b118d90310374716ae90b710280af1",
|
||||
"sha256:bc558586e6045763782014934bfaf39d48b8ae85a2713117d16c39864085c613",
|
||||
"sha256:d46d7982b62e0729ad0175a9bc7e10a566fc07b224d2c79fafb5e032727eaa04",
|
||||
"sha256:d5eef459e30b09f5a098b9cea68bebfeb268697f78d647bd255a085371ac7f3f",
|
||||
"sha256:e01d3203230e1786cd91ccfdc8f8454c8069c91bee3962ad93b87a4b2860f537",
|
||||
"sha256:e170a9e6fcfd19021dd29845af83bb79236068bf5fd4df3327c1be18182b2531"
|
||||
],
|
||||
"version": "==3.13"
|
||||
},
|
||||
"raven": {
|
||||
"hashes": [
|
||||
"sha256:3fa6de6efa2493a7c827472e984ce9b020797d0da16f1db67197bcc23c8fae54",
|
||||
"sha256:44a13f87670836e153951af9a3c80405d36b43097db869a36e92809673692ce4"
|
||||
],
|
||||
"version": "==6.10.0"
|
||||
},
|
||||
"raven-aiohttp": {
|
||||
"hashes": [
|
||||
"sha256:1444a49c93a85b8bb57c6ee649e512368dce7a26ad64ac3a01d86aa5669d77f3",
|
||||
"sha256:6a34b6a9841ad0fd827eeb158edb5826c5c5bd7babe2cde2a3f23eb85313af04"
|
||||
],
|
||||
"version": "==0.7.0"
|
||||
},
|
||||
"requests": {
|
||||
"hashes": [
|
||||
"sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e",
|
||||
"sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b"
|
||||
],
|
||||
"version": "==2.21.0"
|
||||
},
|
||||
"schema": {
|
||||
"hashes": [
|
||||
"sha256:d994b0dc4966000037b26898df638e3e2a694cc73636cb2050e652614a350687",
|
||||
"sha256:fa1a53fe5f3b6929725a4e81688c250f46838e25d8c1885a10a590c8c01a7b74"
|
||||
],
|
||||
"version": "==0.6.8"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
"sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
|
||||
"sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
|
||||
],
|
||||
"version": "==1.12.0"
|
||||
},
|
||||
"snowballstemmer": {
|
||||
"hashes": [
|
||||
"sha256:919f26a68b2c17a7634da993d91339e288964f93c274f1343e3bbbe2096e1128",
|
||||
"sha256:9f3bcd3c401c3e862ec0ebe6d2c069ebc012ce142cce209c098ccb5b09136e89"
|
||||
],
|
||||
"version": "==1.2.1"
|
||||
},
|
||||
"sphinx": {
|
||||
"hashes": [
|
||||
"sha256:429e3172466df289f0f742471d7e30ba3ee11f3b5aecd9a840480d03f14bcfe5",
|
||||
"sha256:c4cb17ba44acffae3d3209646b6baec1e215cad3065e852c68cc569d4df1b9f8"
|
||||
],
|
||||
"version": "==1.8.3"
|
||||
},
|
||||
"sphinx-rtd-theme": {
|
||||
"hashes": [
|
||||
"sha256:02f02a676d6baabb758a20c7a479d58648e0f64f13e07d1b388e9bb2afe86a09",
|
||||
"sha256:d0f6bc70f98961145c5b0e26a992829363a197321ba571b31b24ea91879e0c96"
|
||||
],
|
||||
"version": "==0.4.2"
|
||||
},
|
||||
"sphinxcontrib-asyncio": {
|
||||
"hashes": [
|
||||
"sha256:96627b1ec4eba08d09ad577ff9416c131910333ef37a2c82a2716e59646739f0"
|
||||
],
|
||||
"version": "==0.2.0"
|
||||
},
|
||||
"sphinxcontrib-websupport": {
|
||||
"hashes": [
|
||||
"sha256:68ca7ff70785cbe1e7bccc71a48b5b6d965d79ca50629606c7861a21b206d9dd",
|
||||
"sha256:9de47f375baf1ea07cdb3436ff39d7a9c76042c10a769c52353ec46e4e8fc3b9"
|
||||
],
|
||||
"version": "==1.1.0"
|
||||
},
|
||||
"toml": {
|
||||
"hashes": [
|
||||
"sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c",
|
||||
"sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"
|
||||
],
|
||||
"version": "==0.10.0"
|
||||
},
|
||||
"tox": {
|
||||
"hashes": [
|
||||
"sha256:2a8d8a63660563e41e64e3b5b677e81ce1ffa5e2a93c2c565d3768c287445800",
|
||||
"sha256:edfca7809925f49bdc110d0a2d9966bbf35a0c25637216d9586e7a5c5de17bfb"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.6.1"
|
||||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39",
|
||||
"sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22"
|
||||
],
|
||||
"version": "==1.24.1"
|
||||
},
|
||||
"virtualenv": {
|
||||
"hashes": [
|
||||
"sha256:34b9ae3742abed2f95d3970acf4d80533261d6061b51160b197f84e5b4c98b4c",
|
||||
"sha256:fa736831a7b18bd2bfeef746beb622a92509e9733d645952da136b0639cd40cd"
|
||||
],
|
||||
"version": "==16.2.0"
|
||||
},
|
||||
"websockets": {
|
||||
"hashes": [
|
||||
"sha256:0e2f7d6567838369af074f0ef4d0b802d19fa1fee135d864acc656ceefa33136",
|
||||
"sha256:2a16dac282b2fdae75178d0ed3d5b9bc3258dabfae50196cbb30578d84b6f6a6",
|
||||
"sha256:5a1fa6072405648cb5b3688e9ed3b94be683ce4a4e5723e6f5d34859dee495c1",
|
||||
"sha256:5c1f55a1274df9d6a37553fef8cff2958515438c58920897675c9bc70f5a0538",
|
||||
"sha256:669d1e46f165e0ad152ed8197f7edead22854a6c90419f544e0f234cc9dac6c4",
|
||||
"sha256:695e34c4dbea18d09ab2c258994a8bf6a09564e762655408241f6a14592d2908",
|
||||
"sha256:6b2e03d69afa8d20253455e67b64de1a82ff8612db105113cccec35d3f8429f0",
|
||||
"sha256:79ca7cdda7ad4e3663ea3c43bfa8637fc5d5604c7737f19a8964781abbd1148d",
|
||||
"sha256:7fd2dd9a856f72e6ed06f82facfce01d119b88457cd4b47b7ae501e8e11eba9c",
|
||||
"sha256:82c0354ac39379d836719a77ee360ef865377aa6fdead87909d50248d0f05f4d",
|
||||
"sha256:8f3b956d11c5b301206382726210dc1d3bee1a9ccf7aadf895aaf31f71c3716c",
|
||||
"sha256:91ec98640220ae05b34b79ee88abf27f97ef7c61cf525eec57ea8fcea9f7dddb",
|
||||
"sha256:952be9540d83dba815569d5cb5f31708801e0bbfc3a8c5aef1890b57ed7e58bf",
|
||||
"sha256:99ac266af38ba1b1fe13975aea01ac0e14bb5f3a3200d2c69f05385768b8568e",
|
||||
"sha256:9fa122e7adb24232247f8a89f2d9070bf64b7869daf93ac5e19546b409e47e96",
|
||||
"sha256:a0873eadc4b8ca93e2e848d490809e0123eea154aa44ecd0109c4d0171869584",
|
||||
"sha256:cb998bd4d93af46b8b49ecf5a72c0a98e5cc6d57fdca6527ba78ad89d6606484",
|
||||
"sha256:e02e57346f6a68523e3c43bbdf35dde5c440318d1f827208ae455f6a2ace446d",
|
||||
"sha256:e79a5a896bcee7fff24a788d72e5c69f13e61369d055f28113e71945a7eb1559",
|
||||
"sha256:ee55eb6bcf23ecc975e6b47c127c201b913598f38b6a300075f84eeef2d3baff",
|
||||
"sha256:f1414e6cbcea8d22843e7eafdfdfae3dd1aba41d1945f6ca66e4806c07c4f454"
|
||||
],
|
||||
"version": "==6.0"
|
||||
},
|
||||
"yarl": {
|
||||
"hashes": [
|
||||
"sha256:024ecdc12bc02b321bc66b41327f930d1c2c543fa9a561b39861da9388ba7aa9",
|
||||
"sha256:2f3010703295fbe1aec51023740871e64bb9664c789cba5a6bdf404e93f7568f",
|
||||
"sha256:3890ab952d508523ef4881457c4099056546593fa05e93da84c7250516e632eb",
|
||||
"sha256:3e2724eb9af5dc41648e5bb304fcf4891adc33258c6e14e2a7414ea32541e320",
|
||||
"sha256:5badb97dd0abf26623a9982cd448ff12cb39b8e4c94032ccdedf22ce01a64842",
|
||||
"sha256:73f447d11b530d860ca1e6b582f947688286ad16ca42256413083d13f260b7a0",
|
||||
"sha256:7ab825726f2940c16d92aaec7d204cfc34ac26c0040da727cf8ba87255a33829",
|
||||
"sha256:b25de84a8c20540531526dfbb0e2d2b648c13fd5dd126728c496d7c3fea33310",
|
||||
"sha256:c6e341f5a6562af74ba55205dbd56d248daf1b5748ec48a0200ba227bb9e33f4",
|
||||
"sha256:c9bb7c249c4432cd47e75af3864bc02d26c9594f49c82e2a28624417f0ae63b8",
|
||||
"sha256:e060906c0c585565c718d1c3841747b61c5439af2211e185f6739a9412dfbde1"
|
||||
],
|
||||
"version": "==1.3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,144 +1,135 @@
|
||||
# Red - A multifunction Discord bot
|
||||
#### *Fun bringer, admin helper and music bot*
|
||||
[<img align="right" title="Art by Supergiant Games" src="https://www.supergiantgames.com/static/images/transistor/cartoon_red.png">](https://www.supergiantgames.com/games/transistor/)
|
||||
<h1 align="center">
|
||||
<br>
|
||||
<a href="https://github.com/Cog-Creators/Red-DiscordBot/tree/V3/develop"><img src="https://imgur.com/pY1WUFX.png" alt="Red - Discord Bot"></a>
|
||||
<br>
|
||||
Red Discord Bot
|
||||
<br>
|
||||
</h1>
|
||||
|
||||
[<img src="https://img.shields.io/badge/Support-me!-orange.svg">](https://www.patreon.com/Twentysix26) [<img src="https://img.shields.io/badge/Official-Server-green.svg">](https://discord.gg/0k4npTwMvTpv9wrh) **< Announcements & Help!**
|
||||
##**[ [This version is obsolete and no longer being supported. Use the current one] ](https://github.com/Twentysix26/Red-DiscordBot/)**
|
||||
### Cool title, but what does it do exactly?
|
||||
A bit of everything. Seriously though:
|
||||
It has the [most common features](#general-commands) of many chatbots (!flip, !8, stopwatch, etc.), **custom commands** (inspired by Twitch's [Nightbot](https://www.nightbot.tv/)), memes.
|
||||
It features some games such as **Trivia**, rock paper scissors, [users can earn and play with credits](#economy-commands) in the slot machine.
|
||||
[The audio part is quite fleshed out](#audio-commands). Users can **stream youtube videos**, create **playlists** that everyone will be able to play and control (previous/next song, pause/resume, shuffle...).
|
||||
**MP3 and flac files can also be streamed** (see [FAQ](#faq) for details on local playlists)
|
||||
**Twitch's online notifications**: Red will notify the channels you want whenever you favorite Twitch streamers are online.
|
||||
As for the moderation tools, it includes a **powerful message filter with regular expression capabilities** and **mass messages cleanup**.
|
||||
[I'm planning to expand all this much more](#todo-list).
|
||||
See the [command list](#general-commands) for an even better idea of what this bot can do.
|
||||
<h4 align="center">Music, Moderation, Trivia, Stream Alerts and Fully Modular.</h4>
|
||||
|
||||
### I don't even know what I'm looking at. How do I install this?
|
||||
Do not panic. [Enter the wiki and follow the tutorials](https://github.com/Twentysix26/Red-DiscordBot/wiki)!
|
||||
If you have any issue, consult the [troubleshooting](https://github.com/Twentysix26/Red-DiscordBot/wiki/Troubleshooting) page, and if you're still stuck, [join the official server](https://discord.gg/0k4npTwMvTpv9wrh) so you can get some help.
|
||||
Once you're done, take a look at the command list and have fun.
|
||||
<p align="center">
|
||||
<a href="https://discord.gg/red">
|
||||
<img src="https://discordapp.com/api/guilds/133049272517001216/widget.png?style=shield" alt="Discord Server">
|
||||
</a>
|
||||
<a href="https://www.patreon.com/Red_Devs">
|
||||
<img src="https://img.shields.io/badge/Support-Red!-yellow.svg" alt="Support Red on Patreon!">
|
||||
</a>
|
||||
<a href="https://www.python.org/downloads/">
|
||||
<img src="https://img.shields.io/badge/Made%20With-Python%203-blue.svg?style=for-the-badge" alt="Made with Python 3">
|
||||
</a>
|
||||
<a href="https://crowdin.com/project/red-discordbot">
|
||||
<img src="https://d322cqt584bo4o.cloudfront.net/red-discordbot/localized.svg" alt="Localized with Crowdin">
|
||||
</a>
|
||||
<a href="https://github.com/Rapptz/discord.py/tree/rewrite">
|
||||
<img src="https://img.shields.io/badge/discord-py-blue.svg" alt="discord.py">
|
||||
</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.org/Cog-Creators/Red-DiscordBot">
|
||||
<img src="https://api.travis-ci.org/Cog-Creators/Red-DiscordBot.svg?branch=V3/develop" alt="Travis CI">
|
||||
</a>
|
||||
<a href="http://red-discordbot.readthedocs.io/en/v3-develop/?badge=v3-develop">
|
||||
<img src="https://readthedocs.org/projects/red-discordbot/badge/?version=v3-develop" alt="Red on readthedocs.org">
|
||||
</a>
|
||||
<a href="https://github.com/ambv/black">
|
||||
<img src="https://img.shields.io/badge/code%20style-black-000000.svg" alt="Code Style: Black">
|
||||
</a>
|
||||
<a href="http://makeapullrequest.com">
|
||||
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
### General commands
|
||||
<p align="center">
|
||||
<a href="#overview">Overview</a>
|
||||
•
|
||||
<a href="#installation">Installation</a>
|
||||
•
|
||||
<a href="http://red-discordbot.readthedocs.io/en/v3-develop/index.html">Documentation</a>
|
||||
•
|
||||
<a href="#plugins">Plugins</a>
|
||||
•
|
||||
<a href="#join-the-community">Community</a>
|
||||
•
|
||||
<a href="#license">License</a>
|
||||
</p>
|
||||
|
||||
| Command | Description |
|
||||
|-----------------------------------------------|--------------------------------------------|
|
||||
| !flip | Flip a coin |
|
||||
| !rps [rock/paper/scissors] | Play RPS |
|
||||
| !proverb | Random proverb |
|
||||
| !choose [option1 or option2 or option3 (...)] | Random choice. Supports multiple words |
|
||||
| !8 [question?] | Ask 8 ball a question |
|
||||
| !sw | Start/stop the stopwatch |
|
||||
| !trivia | Trivia help and lists |
|
||||
| !trivia [list] | Start a trivia session |
|
||||
| !trivia stop | Stop a trivia session |
|
||||
| !twitch [stream] | Check if stream is online |
|
||||
| !twitchalert [stream] | Red sends an alert in the channel when the stream is online (admin only)|
|
||||
| !stoptwitchalert [stream] | Stop stream alerts (admin only) |
|
||||
| !roll [number] | Random number between 0 and chosen number. |
|
||||
| !gif [text] | GIF search |
|
||||
| !imdb [movie/etc] | Retrieve information from IMDB |
|
||||
| !meme [id;text1;text2] | Create a meme |
|
||||
| !poll [question;answer1;answer2 (...)] | Start poll in the current channel |
|
||||
| !endpoll | Stop poll |
|
||||
| !addcom [command] [text] | Add a custom command |
|
||||
| !editcom [command] [text] | Edit a custom command |
|
||||
| !delcom [command] | Delete a custom command |
|
||||
| !customcommands | Custom commands' list |
|
||||
| !help | Command list |
|
||||
| !audio help | Audio command list and playlist explanation.|
|
||||
| !economy | Explanation of the economy module |
|
||||
| !admin help | Admin commands list |
|
||||
| !meme help | Explanation of !meme |
|
||||
# Overview
|
||||
|
||||
### Audio commands
|
||||
Red is a fully modular bot – meaning all features and commands can be enabled/disabled to your
|
||||
liking, making it completely customizable. This is also a *self-hosted bot* – meaning you will need
|
||||
to host and maintain your own instance. You can turn Red into an admin bot, music bot, trivia bot,
|
||||
new best friend or all of these together!
|
||||
|
||||
| Command | Description |
|
||||
|----------------------------|---------------------------------------------------------------------|
|
||||
| !youtube [link] | Play a youtube video in a voice channel |
|
||||
| !sing | Make Red sing |
|
||||
| !stop | Stop any voice channel activity |
|
||||
| !play [playlist_name] | Play chosen playlist |
|
||||
| !playlists | Playlist's list |
|
||||
| !next or !skip | Next song |
|
||||
| !prev | Previous song |
|
||||
| !pause | Pause song |
|
||||
| !resume | Resume song |
|
||||
| !replay or !repeat | Replay current song |
|
||||
| !title or !song | Current song's title + link |
|
||||
| !shuffle | Mix current playlist |
|
||||
| !volume [0-1] | Sets Red's output volume |
|
||||
| !addplaylist [name] [link] | Add a youtube playlist |
|
||||
| !delplaylist [name] | Delete a youtube playlist. Limited to author and admins |
|
||||
| !getplaylist | Get the current playlist through DM. This also works with favorites |
|
||||
| !addfavorite | Add song to your favorites |
|
||||
| !delfavorite | Remove song from your favorites |
|
||||
| !playfavorites | Play your favorites |
|
||||
| !local [playlist_name] | Play chosen local playlist |
|
||||
| !local or !locallist | Local playlists' list |
|
||||
| !downloadmode | Enables or disables download mode. (admin only) |
|
||||
[Installation](#installation) is easy, and you do **NOT** need to know anything about coding! Aside
|
||||
from installation and updating, every part of the bot can be controlled from within Discord.
|
||||
|
||||
### Admin commands
|
||||
**The default set of modules includes and is not limited to:**
|
||||
|
||||
| Command | Description |
|
||||
|-----------------------------------------------------------|---------------------------------------------------|
|
||||
| !addwords [word1 word2 (...)] [phrase/with/many/words] | Add words to message filter |
|
||||
| !removewords [word1 word2 (...)] [phrase/with/many/words] | Remove words from message filter |
|
||||
| !addregex [regex] | Add regular expression to message filter |
|
||||
| !removeregex [regex] | Remove regular expression from message filter |
|
||||
| !shutdown | Close the bot |
|
||||
| !join [invite] | Join another server |
|
||||
| !leaveserver | Leave server |
|
||||
| !shush | Ignore the current channel |
|
||||
| !talk | Stop ignoring the current channel |
|
||||
| !reload | Reload most files. Useful in case of manual edits |
|
||||
| !name [name] | Change the bot's name |
|
||||
| !cleanup [number] | Delete the last [number] messages |
|
||||
| !cleanup [name/mention] [number] | Delete the last [number] of messages by [name] |
|
||||
| !blacklist [name/mention] | Add user to blacklist. Red will ignore that user |
|
||||
| !forgive [name/mention] | Remove user from blacklist |
|
||||
| !setting [setting] [value] | Modify setting |
|
||||
- Moderation features (kick/ban/softban/hackban, mod-log, filter, chat cleanup)
|
||||
- Trivia (lists are included and can be easily added)
|
||||
- Music features (YouTube, SoundCloud, local files, playlists, queues)
|
||||
- Stream alerts (Twitch, Youtube, Mixer, Hitbox, Picarto)
|
||||
- Bank (slot machine, user credits)
|
||||
- Custom commands
|
||||
- Imgur/gif search
|
||||
- Admin automation (self-role assignment, cross-server announcements, mod-mail reports)
|
||||
- Customisable command permissions
|
||||
|
||||
**Additionally, other [plugins](#plugins) (cogs) can be easily found and added from our growing
|
||||
community of cog repositories.**
|
||||
|
||||
### Economy commands
|
||||
# Installation
|
||||
|
||||
| Command | Description |
|
||||
|-------------|--------------------------------------|
|
||||
| !register | Register a new account |
|
||||
| !balance | Check your balance |
|
||||
| !slot [bid] | Play the slot machine |
|
||||
| !slot help | Slot machine explanation and payouts |
|
||||
| !payday | Receive credits |
|
||||
**The following platforms are officially supported:**
|
||||
|
||||
### FAQ
|
||||
>I've done everything the README asked me to and it still doesn't work! Were you drunk when you coded this?
|
||||
- [Windows](https://red-discordbot.readthedocs.io/en/v3-develop/install_windows.html)
|
||||
- [MacOS](https://red-discordbot.readthedocs.io/en/v3-develop/install_linux_mac.html)
|
||||
- [Ubuntu](https://red-discordbot.readthedocs.io/en/v3-develop/install_linux_mac.html)
|
||||
- [Debian Stretch](https://red-discordbot.readthedocs.io/en/v3-develop/install_linux_mac.html)
|
||||
- [CentOS 7](https://red-discordbot.readthedocs.io/en/v3-develop/install_linux_mac.html)
|
||||
- [Arch Linux](https://red-discordbot.readthedocs.io/en/v3-develop/install_linux_mac.html)
|
||||
- [Raspbian Stretch](https://red-discordbot.readthedocs.io/en/v3-develop/install_linux_mac.html)
|
||||
|
||||
You're probably missing something.
|
||||
Feel free to join [my server](https://discord.gg/0k4npTwMvTpv9wrh) and head to #support to get some help! Oh, and my drinking habits are none of your business.
|
||||
Already using **Red** V2? Take a look at the [Data Converter](https://red-discordbot.readthedocs.io/en/v3-develop/cog_dataconverter.html)
|
||||
to import your data to V3.
|
||||
|
||||
>Does this bot work on multiple servers?
|
||||
If after reading the guide you are still experiencing issues, feel free to join the
|
||||
[Official Discord Server](https://discord.gg/red) and ask in the **#v3-support** channel for help.
|
||||
|
||||
Sure it does. Should you do it? Maybe. The permissions system is not that great at the moment but if you trust the people running the server it's ok. It's not advisable to send the bot in random servers at the moment.
|
||||
Custom commands only work in the server they were created in. Same for the message filter. This is by design. Also, remember that the bot can only be in one voice channel at once.
|
||||
# Plugins
|
||||
|
||||
>Will you implement [feature]?
|
||||
Red is fully modular, allowing you to load and unload plugins of your choice, and install 3rd party
|
||||
plugins directly from Discord! A few examples are:
|
||||
|
||||
Suggestions are always very welcome.
|
||||
- Cleverbot integration (talk to Red and she talks back)
|
||||
- Ban sync
|
||||
- Welcome messages
|
||||
- Casino
|
||||
- Reaction roles
|
||||
- Slow Mode
|
||||
- Anilist
|
||||
- And much, much more!
|
||||
|
||||
>How do local playlists work?
|
||||
Feel free to take a [peek](https://github.com/Cog-Creators/Red-DiscordBot/issues/1398) at a list of
|
||||
available 3rd party cogs!
|
||||
|
||||
Make as many folders as you want inside the localtracks folder. Names must be without spaces. Every folder counts as a different playlist. Every playlist can contain mp3 and flac files. Users can stream them by doing !local [playlist_name] and see the full list
|
||||
with !local or !locallist. They can also add tracks to their favorites.
|
||||
# Join the community!
|
||||
|
||||
>What's download mode?
|
||||
**Red** is in continuous development, and it’s supported by an active community which produces new
|
||||
content (cogs/plugins) for everyone to enjoy. New features are constantly added. If you can’t
|
||||
[find](https://github.com/Cog-Creators/Red-DiscordBot/issues/1398) the cog you’re looking for,
|
||||
consult our [guide](https://red-discordbot.readthedocs.io/en/v3-develop/guide_cog_creation.html) on
|
||||
building your own cogs!
|
||||
|
||||
Everytime you play the audio of a youtube video with download mode on the audio will be first downloaded and stored into the "cache" folder. It is recommended that you use this mode to avoid streaming problems. This is the default mode, you can switch between modes with !downloadmode.
|
||||
Join us on our [Official Discord Server](https://discord.gg/red)!
|
||||
|
||||
>Why is this bot called Red and the admin role "Transistor"? What's the meaning of !sing?
|
||||
# License
|
||||
|
||||
They're all references to [Transistor](https://www.supergiantgames.com/games/transistor/), a videogame by Supergiant Games.
|
||||
Released under the [GNU GPL v3](https://www.gnu.org/licenses/gpl-3.0.en.html) license.
|
||||
|
||||
### TODO List
|
||||
- [x] [Start rewriting Red](https://github.com/Twentysix26/Red-DiscordBot/tree/develop)
|
||||
- [ ] ~~Bundle some malware and slowly build up a botnet for world domination~~
|
||||
Red is named after the main character of "Transistor", a video game by
|
||||
[Super Giant Games](https://www.supergiantgames.com/games/transistor/).
|
||||
|
||||
Artwork created by [Sinlaire](https://sinlaire.deviantart.com/) on Deviant Art for the Red Discord
|
||||
Bot Project.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
api_key_env: CROWDIN_API_KEY
|
||||
project_identifier_env: CROWDIN_PROJECT_ID
|
||||
files:
|
||||
- source: /redbot/**/*.pot
|
||||
translation: /%original_path%/%locale%.po
|
||||
@@ -1,132 +0,0 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import glob
|
||||
|
||||
default_settings = ('{"TRIVIA_ADMIN_ONLY": false, "EDIT_CC_ADMIN_ONLY": false, "PASSWORD": "PASSWORDHERE", "FILTER": true, "CUSTOMCOMMANDS": true, ' +
|
||||
'"TRIVIA_MAX_SCORE": 10, "TRIVIA_DELAY": 15, "LOGGING": true, "EMAIL": "EMAILHERE", "ADMINROLE": "Transistor", "DOWNLOADMODE" : true, ' +
|
||||
'"VOLUME": 0.20, "TRIVIA_BOT_PLAYS" : false, "TRIVIA_TIMEOUT" : 120, "DEBUG_ID" : "IgnoreThis", "POLL_DURATION" : 60, "PREFIX" : "!"}')
|
||||
|
||||
default_apis = ('{"IMGFLIP_USERNAME": "USERNAMEHERE", "IMGFLIP_PASSWORD": "PASSWORDHERE", "MYAPIFILMS_TOKEN" : "TOKENHERE"}')
|
||||
|
||||
logger = logging.getLogger("__main__")
|
||||
|
||||
|
||||
def fileIO(filename, IO, data=None):
|
||||
if IO == "save" and data != None:
|
||||
with open(filename, encoding='utf-8', mode="w") as f:
|
||||
f.write(json.dumps(data))
|
||||
elif IO == "load" and data == None:
|
||||
with open(filename, encoding='utf-8', mode="r") as f:
|
||||
return json.loads(f.read())
|
||||
elif IO == "check" and data == None:
|
||||
try:
|
||||
with open(filename, encoding='utf-8', mode="r") as f:
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
else:
|
||||
logger.info("Invalid fileIO call")
|
||||
|
||||
def loadProverbs():
|
||||
with open("proverbs.txt", encoding='utf-8', mode="r") as f:
|
||||
data = f.readlines()
|
||||
return data
|
||||
|
||||
def loadAndCheckSettings():
|
||||
to_delete = []
|
||||
try:
|
||||
current_settings = fileIO("json/settings.json", "load")
|
||||
default = json.loads(default_settings)
|
||||
if current_settings.keys() != default.keys():
|
||||
logger.warning("Something wrong detected with settings.json. Starting check...")
|
||||
for field in default:
|
||||
if field not in current_settings:
|
||||
logger.info("Adding " + field + " field.")
|
||||
current_settings[field] = default[field]
|
||||
for field in current_settings:
|
||||
if field not in default:
|
||||
logger.info("Removing " + field + " field.")
|
||||
to_delete.append(field)
|
||||
for field in to_delete:
|
||||
del current_settings[field]
|
||||
logger.warning("Your settings.json was deprecated (missing or useless fields detected). I fixed it. " +
|
||||
"If the file was missing any field I've added it and put default values. You might want to check it.")
|
||||
fileIO("json/settings.json", "save", current_settings)
|
||||
return current_settings
|
||||
except IOError:
|
||||
fileIO("json/settings.json", "save", json.loads(default_settings))
|
||||
logger.error("Your settings.json is missing. I've created a new one. Edit it with your settings and restart me.")
|
||||
exit(1)
|
||||
except:
|
||||
logger.error("Your settings.json seems to be invalid. Check it. If you're unable to fix it delete it and I'll create a new one the next start.")
|
||||
exit(1)
|
||||
|
||||
def migration():
|
||||
if not os.path.exists("json/"):
|
||||
os.makedirs("json")
|
||||
logger.info("Creating json folder...")
|
||||
|
||||
if not os.path.exists("cache/"): #Stores youtube audio for DOWNLOADMODE
|
||||
os.makedirs("cache")
|
||||
|
||||
if not os.path.exists("trivia/"):
|
||||
os.makedirs("trivia")
|
||||
|
||||
files = glob.glob("*.json")
|
||||
if files != []:
|
||||
logger.info("Moving your json files into the json folder...")
|
||||
for f in files:
|
||||
logger.info("Moving {}...".format(f))
|
||||
os.rename(f, "json/" + f)
|
||||
|
||||
def createEmptyFiles():
|
||||
files = {"twitch.json": [], "commands.json": {}, "economy.json" : {}, "filter.json" : {}, "regex_filter.json" : {}, "shushlist.json" : [], "blacklist.json" : []}
|
||||
games = ["Multi Theft Auto", "her Turn()", "Tomb Raider II", "some music.", "NEO Scavenger", "Python", "World Domination", "with your heart."]
|
||||
files["games.json"] = games
|
||||
for f, data in files.items() :
|
||||
if not os.path.isfile("json/" + f):
|
||||
logger.info("Missing {}. Creating it...".format(f))
|
||||
fileIO("json/" + f, "save", data)
|
||||
if not os.path.isfile("json/settings.json"):
|
||||
logger.info("Missing settings.json. Creating it...\n")
|
||||
fileIO("json/settings.json", "save", json.loads(default_settings))
|
||||
print("You have to configure your settings. If you'd like to do it manually, close this window.\nOtherwise type your bot's account email. DO NOT use your own account for the bot, make a new one.\n\nEmail:")
|
||||
email = input(">")
|
||||
print("Now enter the password.")
|
||||
password = input(">")
|
||||
print("Admin role? Leave empty for default (Transistor)")
|
||||
admin_role = input(">")
|
||||
if admin_role == "":
|
||||
admin_role = "Transistor"
|
||||
print("Command prefix? Leave empty for default, '!'. Maximum 1 character.")
|
||||
prefix = input(">")
|
||||
if len(prefix) != 1 or prefix == " ":
|
||||
print("Invalid prefix. Setting prefix as '!'...")
|
||||
prefix = "!"
|
||||
new_settings = json.loads(default_settings)
|
||||
new_settings["EMAIL"] = email
|
||||
new_settings["PASSWORD"] = password
|
||||
new_settings["ADMINROLE"] = admin_role
|
||||
new_settings["PREFIX"] = prefix
|
||||
fileIO("json/settings.json", "save", new_settings )
|
||||
logger.info("Settings have been saved.")
|
||||
|
||||
if not os.path.isfile("json/apis.json"):
|
||||
logger.info("Missing apis.json. Creating it...\n")
|
||||
fileIO("json/apis.json", "save", json.loads(default_apis))
|
||||
print("\nIt's now time to configure optional services\nIf you're not interested, leave empty and keep pressing enter.\nMemes feature: create an account on https://imgflip.com/.\nimgflip username:")
|
||||
imgflip_username = input(">")
|
||||
print("Now enter the imgflip password.")
|
||||
imgflip_password = input(">")
|
||||
if imgflip_username == "": imgflip_username = "USERNAMEHERE"
|
||||
if imgflip_password == "": imgflip_password = "PASSWORDHERE"
|
||||
print("\n!imdb configuration. Get your token here http://www.myapifilms.com/token.do\nOr just press enter if you're not interested.")
|
||||
imdb_token = input(">")
|
||||
if imdb_token == "": imdb_token = "TOKENHERE"
|
||||
new_settings = json.loads(default_apis)
|
||||
new_settings["IMGFLIP_USERNAME"] = imgflip_username
|
||||
new_settings["IMGFLIP_PASSWORD"] = imgflip_password
|
||||
new_settings["MYAPIFILMS_TOKEN"] = imdb_token
|
||||
fileIO("json/apis.json", "save", new_settings )
|
||||
logger.info("API Settings have been saved.\n")
|
||||
@@ -0,0 +1 @@
|
||||
https://github.com/Rapptz/discord.py/tarball/7f4c57dd5ad20b7fa10aea485f674a4bc24b9547#egg=discord.py-1.0.0a0
|
||||
@@ -0,0 +1,23 @@
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = python -msphinx
|
||||
SPHINXPROJ = Red-DiscordBot
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
init:
|
||||
cd .. && pipenv lock -r --dev > docs/requirements.txt && echo 'git+https://github.com/Rapptz/discord.py@rewrite#egg=discord.py-1.0' >> docs/requirements.txt
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
@@ -0,0 +1,53 @@
|
||||
.. systemd service guide
|
||||
|
||||
==============================================
|
||||
Setting up auto-restart using systemd on Linux
|
||||
==============================================
|
||||
|
||||
-------------------------
|
||||
Creating the service file
|
||||
-------------------------
|
||||
|
||||
Create the new service file:
|
||||
|
||||
:code:`sudo -e /etc/systemd/system/red@.service`
|
||||
|
||||
Paste the following and replace all instances of :code:`username` with the username your bot is running under (hopefully not root):
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[Unit]
|
||||
Description=%I redbot
|
||||
After=multi-user.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/home/username/.local/bin/redbot %I --no-prompt
|
||||
User=username
|
||||
Group=username
|
||||
Type=idle
|
||||
Restart=always
|
||||
RestartSec=15
|
||||
RestartPreventExitStatus=0
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
Save and exit :code:`ctrl + O; enter; ctrl + x`
|
||||
|
||||
---------------------------------
|
||||
Starting and enabling the service
|
||||
---------------------------------
|
||||
|
||||
.. note:: This same file can be used to start as many instances of the bot as you wish, without creating more service files, just start and enable more services and add any bot instance name after the **@**
|
||||
|
||||
To start the bot, run the service and add the instance name after the **@**:
|
||||
|
||||
:code:`sudo systemctl start red@instancename`
|
||||
|
||||
To set the bot to start on boot, you must enable the service, again adding the instance name after the **@**:
|
||||
|
||||
:code:`sudo systemctl enable red@instancename`
|
||||
|
||||
To view Red’s log, you can acccess through journalctl:
|
||||
|
||||
:code:`sudo journalctl -u red@instancename`
|
||||
@@ -0,0 +1,109 @@
|
||||
.. CustomCommands Cog Reference
|
||||
|
||||
============================
|
||||
CustomCommands Cog Reference
|
||||
============================
|
||||
|
||||
------------
|
||||
How it works
|
||||
------------
|
||||
|
||||
CustomCommands allows you to create simple commands for your bot without requiring you to code your own cog for Red.
|
||||
|
||||
If the command you attempt to create shares a name with an already loaded command, you cannot overwrite it with this cog.
|
||||
|
||||
---------
|
||||
Cooldowns
|
||||
---------
|
||||
|
||||
You can set cooldowns for your custom commands. If a command is on cooldown, it will not be triggered.
|
||||
|
||||
You can set cooldowns per member or per channel, or set a cooldown guild-wide. You can also set multiple types of cooldown on a single custom command. All cooldowns must pass before the command will trigger.
|
||||
|
||||
------------------
|
||||
Context Parameters
|
||||
------------------
|
||||
|
||||
You can enhance your custom command's response by leaving spaces for the bot to substitute.
|
||||
|
||||
+-----------+----------------------------------------+
|
||||
| Argument | Substitute |
|
||||
+===========+========================================+
|
||||
| {message} | The message the bot is responding to. |
|
||||
+-----------+----------------------------------------+
|
||||
| {author} | The user who called the command. |
|
||||
+-----------+----------------------------------------+
|
||||
| {channel} | The channel the command was called in. |
|
||||
+-----------+----------------------------------------+
|
||||
| {server} | The server the command was called in. |
|
||||
+-----------+----------------------------------------+
|
||||
| {guild} | Same as with {server}. |
|
||||
+-----------+----------------------------------------+
|
||||
|
||||
You can further refine the response with dot notation. For example, {author.mention} will mention the user who called the command.
|
||||
|
||||
------------------
|
||||
Command Parameters
|
||||
------------------
|
||||
|
||||
You can further enhance your custom command's response by leaving spaces for the user to substitute.
|
||||
|
||||
To do this, simply put {#} in the response, replacing # with any number starting with 0. Each number will be replaced with what the user gave the command, in order.
|
||||
|
||||
You can refine the response with colon notation. For example, {0:Member} will accept members of the server, and {0:int} will accept a number. If no colon notation is provided, the argument will be returned unchanged.
|
||||
|
||||
+-----------------+--------------------------------+
|
||||
| Argument | Substitute |
|
||||
+=================+================================+
|
||||
| {#:Member} | A member of your server. |
|
||||
+-----------------+--------------------------------+
|
||||
| {#:TextChannel} | A text channel in your server. |
|
||||
+-----------------+--------------------------------+
|
||||
| {#:Role} | A role in your server. |
|
||||
+-----------------+--------------------------------+
|
||||
| {#:int} | A whole number. |
|
||||
+-----------------+--------------------------------+
|
||||
| {#:float} | A decimal number. |
|
||||
+-----------------+--------------------------------+
|
||||
| {#:bool} | True or False. |
|
||||
+-----------------+--------------------------------+
|
||||
|
||||
You can specify more than the above with colon notation, but those are the most common.
|
||||
|
||||
As with context parameters, you can use dot notation to further refine the response. For example, {0.mention:Member} will mention the Member specified.
|
||||
|
||||
----------------
|
||||
Example commands
|
||||
----------------
|
||||
|
||||
Showing your own avatar
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[p]customcom add simple avatar {author.avatar_url}
|
||||
[p]avatar
|
||||
https://cdn.discordapp.com/avatars/133801473317404673/be4c4a4fe47cb3e74c31a0504e7a295e.webp?size=1024
|
||||
|
||||
Repeating the user
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[p]customcom add simple say {0}
|
||||
[p]say Pete and Repeat
|
||||
Pete and Repeat
|
||||
|
||||
Greeting the specified member
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[p]customcom add simple greet Hello, {0.mention:Member}!
|
||||
[p]greet Twentysix
|
||||
Hello, @Twentysix!
|
||||
|
||||
Comparing two text channel's categories
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[p]customcom add simple comparecategory {0.category:TextChannel} | {1.category:TextChannel}
|
||||
[p]comparecategory #support #general
|
||||
Red | Community
|
||||
@@ -0,0 +1,62 @@
|
||||
.. Importing data from a V2 install
|
||||
|
||||
================================
|
||||
Importing data from a V2 install
|
||||
================================
|
||||
|
||||
----------------
|
||||
What you'll need
|
||||
----------------
|
||||
|
||||
1. A Running V3 bot
|
||||
2. The path where your V2 bot is installed
|
||||
|
||||
--------------
|
||||
Importing data
|
||||
--------------
|
||||
|
||||
.. important::
|
||||
|
||||
Unless otherwise specified, the V2 data will take priority over V3 data for the same entires
|
||||
|
||||
.. important::
|
||||
|
||||
For the purposes of this guide, your prefix will be denoted as
|
||||
[p]
|
||||
|
||||
You should swap whatever you made your prefix in for this.
|
||||
All of the below are commands to be entered in discord where the bot can
|
||||
see them.
|
||||
|
||||
The dataconverter cog is not loaded by default. To start, load it with
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[p]load dataconverter
|
||||
|
||||
Next, you'll need to give it the path where your V2 install is.
|
||||
|
||||
On linux and OSX, it may look something like:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
/home/username/Red-DiscordBot/
|
||||
|
||||
On Windows it will look something like:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
C:\Users\yourusername\Red-DiscordBot
|
||||
|
||||
Once you have that path, give it to the bot with the following command
|
||||
(make sure to swap your own path in)
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[p]convertdata /home/username/Red-DiscordBot/
|
||||
|
||||
|
||||
From here, if the path is correct, you will be prompted with an interactive menu asking you
|
||||
what data you would like to import
|
||||
|
||||
You can select an entry by number, or quit with any of 'quit', 'exit', 'q', '-1', or 'cancel'
|
||||
@@ -0,0 +1,9 @@
|
||||
.. Downloader Cog Reference
|
||||
|
||||
Downloader Cog Reference
|
||||
========================
|
||||
|
||||
.. automodule:: redbot.cogs.downloader
|
||||
|
||||
.. autoclass:: redbot.cogs.downloader.downloader.Downloader
|
||||
:members:
|
||||
@@ -0,0 +1,97 @@
|
||||
.. Permissions Cog Reference
|
||||
|
||||
=========================
|
||||
Permissions Cog Reference
|
||||
=========================
|
||||
|
||||
------------
|
||||
How it works
|
||||
------------
|
||||
|
||||
When loaded, the permissions cog will allow you to define extra custom rules for who can use a
|
||||
command.
|
||||
|
||||
If no applicable rules are found, the command will behave normally.
|
||||
|
||||
Rules can also be added to cogs, which will affect all commands from that cog. The cog name can be
|
||||
found from the help menu.
|
||||
|
||||
-------------
|
||||
Rule priority
|
||||
-------------
|
||||
|
||||
Rules set for subcommands will take precedence over rules set for the parent commands, which
|
||||
lastly take precedence over rules set for the cog. So for example, if a user is denied the Core
|
||||
cog, but allowed the ``[p]set token`` command, the user will not be able to use any command in the
|
||||
Core cog except for ``[p]set token``.
|
||||
|
||||
In terms of scope, global rules will be checked first, then server rules.
|
||||
|
||||
For each of those, the first rule pertaining to one of the following models will be used:
|
||||
|
||||
1. User
|
||||
2. Voice channel
|
||||
3. Text channel
|
||||
4. Channel category
|
||||
5. Roles, highest to lowest
|
||||
6. Server (can only be in global rules)
|
||||
7. Default rules
|
||||
|
||||
In private messages, only global rules about a user will be checked.
|
||||
|
||||
-------------------------
|
||||
Setting Rules From a File
|
||||
-------------------------
|
||||
|
||||
The permissions cog can also set, display or update rules with a YAML file with the
|
||||
``[p]permissions yaml`` command. Models must be represented by ID. Rules must be ``true`` for
|
||||
allow, or ``false`` for deny. Here is an example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
COG:
|
||||
Admin:
|
||||
78631113035100160: true
|
||||
96733288462286848: false
|
||||
Audio:
|
||||
133049272517001216: true
|
||||
default: false
|
||||
COMMAND:
|
||||
cleanup bot:
|
||||
78631113035100160: true
|
||||
default: false
|
||||
ping:
|
||||
96733288462286848: false
|
||||
default: true
|
||||
|
||||
----------------------
|
||||
Example configurations
|
||||
----------------------
|
||||
|
||||
Locking the ``[p]play`` command to approved server(s) as a bot owner:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[p]permissions setglobaldefault play deny
|
||||
[p]permissions addglobalrule allow play [server ID or name]
|
||||
|
||||
Locking the ``[p]play`` command to specific voice channel(s) as a serverowner or admin:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[p]permissions setserverdefault deny play
|
||||
[p]permissions setserverdefault deny "playlist start"
|
||||
[p]permissions addserverrule allow play [voice channel ID or name]
|
||||
[p]permissions addserverrule allow "playlist start" [voice channel ID or name]
|
||||
|
||||
Allowing extra roles to use ``[p]cleanup``:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[p]permissions addserverrule allow cleanup [role ID]
|
||||
|
||||
Preventing ``[p]cleanup`` from being used in channels where message history is important:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[p]permissions addserverrule deny cleanup [channel ID or mention]
|
||||
+213
@@ -0,0 +1,213 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Red - Discord Bot documentation build configuration file, created by
|
||||
# sphinx-quickstart on Thu Aug 10 23:18:25 2017.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
# containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.abspath(".."))
|
||||
|
||||
os.environ["BUILDING_DOCS"] = "1"
|
||||
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
"sphinx.ext.autodoc",
|
||||
"sphinx.ext.intersphinx",
|
||||
"sphinx.ext.viewcode",
|
||||
"sphinx.ext.napoleon",
|
||||
"sphinx.ext.doctest",
|
||||
"sphinxcontrib.asyncio",
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ["_templates"]
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = ".rst"
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = "index"
|
||||
|
||||
# General information about the project.
|
||||
project = "Red - Discord Bot"
|
||||
copyright = "2018, Cog Creators"
|
||||
author = "Cog Creators"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
from redbot.core import __version__
|
||||
|
||||
# The short X.Y version.
|
||||
version = __version__
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = __version__
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = None
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This patterns also effect to html_static_path and html_extra_path
|
||||
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = "sphinx"
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = False
|
||||
|
||||
# Role which is assigned when you make a simple reference within backticks
|
||||
default_role = "any"
|
||||
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
# html_theme_options = {}
|
||||
|
||||
html_context = {
|
||||
# Enable the "Edit in GitHub link within the header of each page.
|
||||
"display_github": True,
|
||||
"github_user": "Cog-Creators",
|
||||
"github_repo": "Red-DiscordBot",
|
||||
"github_version": "V3/develop/docs/",
|
||||
}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
# html_static_path = ['_static']
|
||||
|
||||
# Custom sidebar templates, must be a dictionary that maps document names
|
||||
# to template names.
|
||||
#
|
||||
# This is required for the alabaster theme
|
||||
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
|
||||
html_sidebars = {
|
||||
"**": [
|
||||
"about.html",
|
||||
"navigation.html",
|
||||
"relations.html", # needs 'show_related': True theme option to display
|
||||
"searchbox.html",
|
||||
"donate.html",
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
# -- Options for HTMLHelp output ------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = "Red-DiscordBotdoc"
|
||||
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, "Red-DiscordBot.tex", "Red - Discord Bot Documentation", "Cog Creators", "manual")
|
||||
]
|
||||
|
||||
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [(master_doc, "red-discordbot", "Red - Discord Bot Documentation", [author], 1)]
|
||||
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(
|
||||
master_doc,
|
||||
"Red-DiscordBot",
|
||||
"Red - Discord Bot Documentation",
|
||||
author,
|
||||
"Red-DiscordBot",
|
||||
"One line description of project.",
|
||||
"Miscellaneous",
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
# -- Options for linkcheck builder ----------------------------------------
|
||||
|
||||
# A list of regular expressions that match URIs that should not be
|
||||
# checked when doing a linkcheck build.
|
||||
linkcheck_ignore = [r"https://java.com*"]
|
||||
|
||||
|
||||
# -- Options for extensions -----------------------------------------------
|
||||
|
||||
# Intersphinx
|
||||
intersphinx_mapping = {
|
||||
"python": ("https://docs.python.org/3.6", None),
|
||||
"dpy": ("https://discordpy.readthedocs.io/en/rewrite/", None),
|
||||
"motor": ("https://motor.readthedocs.io/en/stable/", None),
|
||||
}
|
||||
|
||||
# Doctest
|
||||
# If this string is non-empty, all blocks with ``>>>`` in them will be
|
||||
# tested, not just the ones explicitly marked with ``.. doctest::``
|
||||
doctest_test_doctest_blocks = ""
|
||||
@@ -0,0 +1,42 @@
|
||||
.. V3 Bank
|
||||
|
||||
.. role:: python(code)
|
||||
:language: python
|
||||
|
||||
====
|
||||
Bank
|
||||
====
|
||||
|
||||
Bank has now been separated from Economy for V3. New to bank is support for
|
||||
having a global bank.
|
||||
|
||||
***********
|
||||
Basic Usage
|
||||
***********
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from redbot.core import bank
|
||||
|
||||
class MyCog:
|
||||
@commands.command()
|
||||
async def balance(self, ctx, user: discord.Member=None):
|
||||
if user is None:
|
||||
user = ctx.author
|
||||
bal = bank.get_balance(user)
|
||||
currency = bank.get_currency_name(ctx.guild)
|
||||
await ctx.send(
|
||||
"{}'s balance is {} {}".format(
|
||||
user.display_name, bal, currency
|
||||
)
|
||||
)
|
||||
|
||||
*************
|
||||
API Reference
|
||||
*************
|
||||
|
||||
Bank
|
||||
======
|
||||
|
||||
.. automodule:: redbot.core.bank
|
||||
:members:
|
||||
@@ -0,0 +1,23 @@
|
||||
.. bot module docs
|
||||
|
||||
===
|
||||
Bot
|
||||
===
|
||||
|
||||
.. automodule:: redbot.core.bot
|
||||
|
||||
RedBase
|
||||
^^^^^^^
|
||||
|
||||
.. autoclass:: RedBase
|
||||
:members:
|
||||
:exclude-members: get_context
|
||||
|
||||
.. automethod:: register_rpc_handler
|
||||
.. automethod:: unregister_rpc_handler
|
||||
|
||||
Red
|
||||
^^^
|
||||
|
||||
.. autoclass:: Red
|
||||
:members:
|
||||
@@ -0,0 +1,11 @@
|
||||
.. _checks:
|
||||
|
||||
========================
|
||||
Command Check Decorators
|
||||
========================
|
||||
|
||||
The following are all decorators for commands, which add restrictions to where and when they can be
|
||||
run.
|
||||
|
||||
.. automodule:: redbot.core.checks
|
||||
:members:
|
||||
@@ -0,0 +1,8 @@
|
||||
.. cog manager docs
|
||||
|
||||
===========
|
||||
Cog Manager
|
||||
===========
|
||||
|
||||
.. automodule:: redbot.core.cog_manager
|
||||
:members:
|
||||
@@ -0,0 +1,26 @@
|
||||
.. red commands module documentation
|
||||
|
||||
================
|
||||
Commands Package
|
||||
================
|
||||
|
||||
This package acts almost identically to :doc:`discord.ext.commands <dpy:ext/commands/api>`; i.e.
|
||||
all of the attributes from discord.py's are also in ours.
|
||||
Some of these attributes, however, have been slightly modified, while others have been added to
|
||||
extend functionlities used throughout the bot, as outlined below.
|
||||
|
||||
.. autofunction:: redbot.core.commands.command
|
||||
|
||||
.. autofunction:: redbot.core.commands.group
|
||||
|
||||
.. autoclass:: redbot.core.commands.Command
|
||||
:members:
|
||||
|
||||
.. autoclass:: redbot.core.commands.Group
|
||||
:members:
|
||||
|
||||
.. autoclass:: redbot.core.commands.Context
|
||||
:members:
|
||||
|
||||
.. automodule:: redbot.core.commands.requires
|
||||
:members: PrivilegeLevel, PermState, Requires
|
||||
@@ -0,0 +1,435 @@
|
||||
.. config shite
|
||||
|
||||
.. role:: python(code)
|
||||
:language: python
|
||||
|
||||
======
|
||||
Config
|
||||
======
|
||||
|
||||
Config was introduced in V3 as a way to make data storage easier and safer for all developers regardless of skill level.
|
||||
It will take some getting used to as the syntax is entirely different from what Red has used before, but we believe
|
||||
Config will be extremely beneficial to both cog developers and end users in the long run.
|
||||
|
||||
***********
|
||||
Basic Usage
|
||||
***********
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from redbot.core import Config
|
||||
|
||||
class MyCog:
|
||||
def __init__(self):
|
||||
self.config = Config.get_conf(self, identifier=1234567890)
|
||||
|
||||
self.config.register_global(
|
||||
foo=True
|
||||
)
|
||||
|
||||
@commands.command()
|
||||
async def return_some_data(self, ctx):
|
||||
await ctx.send(await self.config.foo())
|
||||
|
||||
********
|
||||
Tutorial
|
||||
********
|
||||
|
||||
.. py:currentmodule:: redbot.core.config
|
||||
|
||||
This tutorial will walk you through how to use Config.
|
||||
|
||||
First, you need to import Config:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from redbot.core import Config
|
||||
|
||||
Then, in the class's :code:`__init__` function, you need to get a config instance:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class MyCog:
|
||||
def __init__(self):
|
||||
self.config = Config.get_conf(self, identifier=1234567890)
|
||||
|
||||
The ``identifier`` in :py:meth:`Config.get_conf` is used to keep your cog's data separate
|
||||
from that of another cog, and thus should be unique to your cog. For example: if we
|
||||
have two cogs named :code:`MyCog` and their identifier is different, each will have
|
||||
its own data without overwriting the other's data. Note that it is also possible
|
||||
to force registration of a data key before allowing you to get and set data for
|
||||
that key by adding :code:`force_registration=True` after identifier (that defaults
|
||||
to :code:`False` though)
|
||||
|
||||
After we've gotten that, we need to register default values:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class MyCog:
|
||||
def __init__(self):
|
||||
self.config = Config.get_conf(self, identifier=1234567890)
|
||||
default_global = {
|
||||
"foobar": True,
|
||||
"foo": {
|
||||
"bar": True,
|
||||
"baz": False
|
||||
}
|
||||
}
|
||||
default_guild = {
|
||||
"blah": [],
|
||||
"baz": 1234567890
|
||||
}
|
||||
self.config.register_global(**default_global)
|
||||
self.config.register_guild(**default_guild)
|
||||
|
||||
As seen in the example above, we can set up our defaults in dicts and then use those in
|
||||
the appropriate :code:`register` function. As seen above, there's :py:meth:`Config.register_global`
|
||||
and :py:meth:`Config.register_guild`, but there's also :py:meth:`Config.register_member`,
|
||||
:py:meth:`Config.register_role`, :py:meth:`Config.register_user`, and :py:meth:`Config.register_channel`.
|
||||
Note that :code:`member` stores based on guild id AND the user's id.
|
||||
|
||||
Once we have our defaults registered and we have the object, we can now use those values
|
||||
in various ways:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@commands.command()
|
||||
@checks.admin_or_permissions(manage_guild=True)
|
||||
async def setbaz(self, ctx, new_value):
|
||||
await self.config.guild(ctx.guild).baz.set(new_value)
|
||||
await ctx.send("Value of baz has been changed!")
|
||||
|
||||
@commands.command()
|
||||
@checks.is_owner()
|
||||
async def setfoobar(self, ctx, new_value):
|
||||
await self.config.foobar.set(new_value)
|
||||
|
||||
@commands.command()
|
||||
async def checkbaz(self, ctx):
|
||||
baz_val = await self.config.guild(ctx.guild).baz()
|
||||
await ctx.send("The value of baz is {}".format("True" if baz_val else "False"))
|
||||
|
||||
Notice a few things in the above examples:
|
||||
|
||||
1. Global doesn't have anything in between :code:`self.config` and the variable.
|
||||
|
||||
2. Both the getters and setters need to be awaited because they're coroutines.
|
||||
|
||||
3. If you're getting the value, the syntax is::
|
||||
|
||||
self.config.<insert scope here, or nothing if global>.variable_name()
|
||||
|
||||
4. If setting, it's::
|
||||
|
||||
self.config.<insert scope here, or nothing if global>.variable_name.set(new_value)
|
||||
|
||||
It is also possible to use :code:`async with` syntax to get and set config
|
||||
values. When entering the statement, the config value is retreived, and on exit,
|
||||
it is saved. This puts a safeguard on any code within the :code:`async with`
|
||||
block such that if it breaks from the block in any way (whether it be from
|
||||
:code:`return`, :code:`break`, :code:`continue` or an exception), the value will
|
||||
still be saved.
|
||||
|
||||
.. important::
|
||||
|
||||
Only mutable config values can be used in the :code:`async with` statement
|
||||
(namely lists or dicts), and they must be modified *in place* for their
|
||||
changes to be saved.
|
||||
|
||||
Here is an example of the :code:`async with` syntax:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@commands.command()
|
||||
async def addblah(self, ctx, new_blah):
|
||||
guild_group = self.config.guild(ctx.guild)
|
||||
async with guild_group.blah() as blah:
|
||||
blah.append(new_blah)
|
||||
await ctx.send("The new blah value has been added!")
|
||||
|
||||
|
||||
.. important::
|
||||
|
||||
Please note that while you have nothing between ``config`` and the variable name for global
|
||||
data, you also have the following commands to get data specific to each category.
|
||||
|
||||
* :py:meth:`Config.guild` for guild data which takes an object of type :py:class:`discord.Guild`.
|
||||
* :py:meth:`Config.member` which takes :py:class:`discord.Member`.
|
||||
* :py:meth:`Config.user` which takes :py:class:`discord.User`.
|
||||
* :py:meth:`Config.role` which takes :py:class:`discord.Role`.
|
||||
* :py:meth:`Config.channel` which takes :py:class:`discord.TextChannel`.
|
||||
|
||||
If you need to wipe data from the config, you want to look at :py:meth:`Group.clear`, or :py:meth:`Config.clear_all`
|
||||
and similar methods, such as :py:meth:`Config.clear_all_guilds`.
|
||||
|
||||
Which one you should use depends on what you want to do.
|
||||
|
||||
If you're looking to clear data for a single guild/member/channel/role/user,
|
||||
you want to use :py:meth:`Group.clear` as that will clear the data only for the
|
||||
specified thing.
|
||||
|
||||
If using :py:meth:`Config.clear_all`, it will reset all data everywhere.
|
||||
|
||||
There are other methods provided to reset data from a particular scope. For
|
||||
example, :py:meth:`Config.clear_all_guilds` resets all guild data. For member
|
||||
data, you can clear on both a per-guild and guild-independent basis, see
|
||||
:py:meth:`Config.clear_all_members` for more info.
|
||||
|
||||
**************
|
||||
Advanced Usage
|
||||
**************
|
||||
|
||||
Config makes it extremely easy to organize data that can easily fit into one of the standard categories (global,
|
||||
guild, user etc.) but there may come a time when your data does not work with the existing categories. There are now
|
||||
features within Config to enable developers to work with data how they wish.
|
||||
|
||||
This usage guide will cover the following features:
|
||||
|
||||
- :py:meth:`Group.get_raw`
|
||||
- :py:meth:`Group.set_raw`
|
||||
- :py:meth:`Group.clear_raw`
|
||||
|
||||
For this example let's suppose that we're creating a cog that allows users to buy and own multiple pets using
|
||||
the built-in Economy credits::
|
||||
|
||||
from redbot.core import bank
|
||||
from redbot.core import Config
|
||||
from discord.ext import commands
|
||||
|
||||
|
||||
class Pets:
|
||||
def __init__(self):
|
||||
self.conf = Config.get_conf(self, 1234567890)
|
||||
|
||||
# Here we'll assign some default costs for the pets
|
||||
self.conf.register_global(
|
||||
dog=100,
|
||||
cat=100,
|
||||
bird=50
|
||||
)
|
||||
self.conf.register_user(
|
||||
pets={}
|
||||
)
|
||||
|
||||
And now that the cog is set up we'll need to create some commands that allow users to purchase these pets::
|
||||
|
||||
# continued
|
||||
@commands.command()
|
||||
async def get_pet(self, ctx, pet_type: str, pet_name: str):
|
||||
"""
|
||||
Purchase a pet.
|
||||
|
||||
Pet type must be one of: dog, cat, bird
|
||||
"""
|
||||
# Now we need to determine what the cost of the pet is and
|
||||
# if the user has enough credits to purchase it.
|
||||
|
||||
# We will need to use "get_raw"
|
||||
try:
|
||||
cost = await self.conf.get_raw(pet_type)
|
||||
except KeyError:
|
||||
# KeyError is thrown whenever the data you try to access does not
|
||||
# exist in the registered defaults or in the saved data.
|
||||
await ctx.send("Bad pet type, try again.")
|
||||
return
|
||||
|
||||
After we've determined the cost of the pet we need to check if the user has enough credits and then we'll need to
|
||||
assign a new pet to the user. This is very easily done using the V3 bank API and :py:meth:`Group.set_raw`::
|
||||
|
||||
# continued
|
||||
if await bank.can_spend(ctx.author, cost):
|
||||
await self.conf.user(ctx.author).pets.set_raw(
|
||||
pet_name, value={'cost': cost, 'hunger': 0}
|
||||
)
|
||||
|
||||
# this is equivalent to doing the following
|
||||
|
||||
pets = await self.conf.user(ctx.author).pets()
|
||||
pets[pet_name] = {'cost': cost, 'hunger': 0}
|
||||
await self.conf.user(ctx.author).pets.set(pets)
|
||||
|
||||
Since the pets can get hungry we're gonna need a command that let's pet owners check how hungry their pets are::
|
||||
|
||||
# continued
|
||||
@commands.command()
|
||||
async def hunger(self, ctx, pet_name: str):
|
||||
try:
|
||||
hunger = await self.conf.user(ctx.author).pets.get_raw(pet_name, 'hunger')
|
||||
except KeyError:
|
||||
# Remember, this is thrown if something in the provided identifiers
|
||||
# is not found in the saved data or the defaults.
|
||||
await ctx.send("You don't own that pet!")
|
||||
return
|
||||
|
||||
await ctx.send("Your pet has {}/100 hunger".format(hunger))
|
||||
|
||||
We're responsible pet owners here, so we've also got to have a way to feed our pets::
|
||||
|
||||
# continued
|
||||
@commands.command()
|
||||
async def feed(self, ctx, pet_name: str, food: int):
|
||||
# This is a bit more complicated because we need to check if the pet is
|
||||
# owned first.
|
||||
try:
|
||||
pet = await self.conf.user(ctx.author).pets.get_raw(pet_name)
|
||||
except KeyError:
|
||||
# If the given pet name doesn't exist in our data
|
||||
await ctx.send("You don't own that pet!")
|
||||
return
|
||||
|
||||
hunger = pet.get("hunger")
|
||||
|
||||
# Determine the new hunger and make sure it doesn't go negative
|
||||
new_hunger = max(hunger - food, 0)
|
||||
|
||||
await self.conf.user(ctx.author).pets.set_raw(
|
||||
pet_name, 'hunger', value=new_hunger
|
||||
)
|
||||
|
||||
# We could accomplish the same thing a slightly different way
|
||||
await self.conf.user(ctx.author).pets.get_attr(pet_name).hunger.set(new_hunger)
|
||||
|
||||
await ctx.send("Your pet is now at {}/100 hunger!".format(new_hunger)
|
||||
|
||||
Of course, if we're less than responsible pet owners, there are consequences::
|
||||
|
||||
#continued
|
||||
@commands.command()
|
||||
async def adopt(self, ctx, pet_name: str, *, member: discord.Member):
|
||||
try:
|
||||
pet = await self.conf.user(member).pets.get_raw(pet_name)
|
||||
except KeyError:
|
||||
await ctx.send("That person doesn't own that pet!")
|
||||
return
|
||||
|
||||
hunger = pet.get("hunger")
|
||||
if hunger < 80:
|
||||
await ctx.send("That pet is too well taken care of to be adopted.")
|
||||
return
|
||||
|
||||
await self.conf.user(member).pets.clear_raw(pet_name)
|
||||
|
||||
# this is equivalent to doing the following
|
||||
|
||||
pets = await self.conf.user(member).pets()
|
||||
del pets[pet_name]
|
||||
await self.conf.user(member).pets.set(pets)
|
||||
|
||||
await self.conf.user(ctx.author).pets.set_raw(pet_name, value=pet)
|
||||
await ctx.send(
|
||||
"Your request to adopt this pet has been granted due to "
|
||||
"how poorly it was taken care of."
|
||||
)
|
||||
|
||||
|
||||
*************
|
||||
V2 Data Usage
|
||||
*************
|
||||
There has been much conversation on how to bring V2 data into V3 and, officially, we recommend that cog developers
|
||||
make use of the public interface in Config (using the categories as described in these docs) rather than simply
|
||||
copying and pasting your V2 data into V3. Using Config as recommended will result in a much better experience for
|
||||
you in the long run and will simplify cog creation and maintenance.
|
||||
|
||||
However.
|
||||
|
||||
We realize that many of our cog creators have expressed disinterest in writing converters for V2 to V3 style data.
|
||||
As a result we have opened up config to take standard V2 data and allow cog developers to manipulate it in V3 in
|
||||
much the same way they would in V2. The following examples will demonstrate how to accomplish this.
|
||||
|
||||
.. warning::
|
||||
|
||||
By following this method to use V2 data in V3 you may be at risk of data corruption if your cog is used on a bot
|
||||
with multiple shards. USE AT YOUR OWN RISK.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from redbot.core import Config
|
||||
|
||||
|
||||
class ExampleCog:
|
||||
def __init__(self):
|
||||
self.conf = Config.get_conf(self, 1234567890)
|
||||
|
||||
self.data = {}
|
||||
|
||||
async def load_data(self):
|
||||
self.data = await self.conf.custom("V2", "V2").all()
|
||||
|
||||
async def save_data(self):
|
||||
await self.conf.custom("V2", "V2").set(self.data)
|
||||
|
||||
|
||||
async def setup(bot):
|
||||
cog = ExampleCog()
|
||||
await cog.load_data()
|
||||
bot.add_cog(cog)
|
||||
|
||||
*************
|
||||
API Reference
|
||||
*************
|
||||
|
||||
.. important::
|
||||
|
||||
Before we begin with the nitty gritty API Reference, you should know that there are tons of working code examples
|
||||
inside the bot itself! Simply take a peek inside of the :code:`tests/core/test_config.py` file for examples of using
|
||||
Config in all kinds of ways.
|
||||
|
||||
.. important::
|
||||
|
||||
When getting, setting or clearing values in Config, all keys are casted to `str` for you. This
|
||||
includes keys within a `dict` when one is being set, as well as keys in nested dictionaries
|
||||
within that `dict`. For example::
|
||||
|
||||
>>> conf = Config.get_conf(self, identifier=999)
|
||||
>>> conf.register_global(foo={})
|
||||
>>> await conf.foo.set_raw(123, value=True)
|
||||
>>> await conf.foo()
|
||||
{'123': True}
|
||||
>>> await conf.foo.set({123: True, 456: {789: False}}
|
||||
>>> await conf.foo()
|
||||
{'123': True, '456': {'789': False}}
|
||||
|
||||
.. automodule:: redbot.core.config
|
||||
|
||||
Config
|
||||
^^^^^^
|
||||
|
||||
.. autoclass:: Config
|
||||
:members:
|
||||
|
||||
Group
|
||||
^^^^^
|
||||
|
||||
.. autoclass:: Group
|
||||
:members:
|
||||
:special-members:
|
||||
|
||||
Value
|
||||
^^^^^
|
||||
|
||||
.. autoclass:: Value
|
||||
:members:
|
||||
:special-members: __call__
|
||||
|
||||
|
||||
****************
|
||||
Driver Reference
|
||||
****************
|
||||
|
||||
.. automodule:: redbot.core.drivers
|
||||
:members:
|
||||
|
||||
Base Driver
|
||||
^^^^^^^^^^^
|
||||
.. autoclass:: redbot.core.drivers.red_base.BaseDriver
|
||||
:members:
|
||||
|
||||
JSON Driver
|
||||
^^^^^^^^^^^
|
||||
.. autoclass:: redbot.core.drivers.red_json.JSON
|
||||
:members:
|
||||
|
||||
Mongo Driver
|
||||
^^^^^^^^^^^^
|
||||
.. autoclass:: redbot.core.drivers.red_mongo.Mongo
|
||||
:members:
|
||||
@@ -0,0 +1,11 @@
|
||||
.. data manager docs
|
||||
|
||||
============
|
||||
Data Manager
|
||||
============
|
||||
|
||||
Data manager is a module that handles all the information necessary to bootstrap
|
||||
the bot into a state where more abstract data management systems can take over.
|
||||
|
||||
.. automodule:: redbot.core.data_manager
|
||||
:members:
|
||||
@@ -0,0 +1,87 @@
|
||||
.. downloader framework reference
|
||||
|
||||
Downloader Framework
|
||||
====================
|
||||
|
||||
Info.json
|
||||
*********
|
||||
|
||||
The optional info.json file may exist inside every package folder in the repo,
|
||||
as well as in the root of the repo. The following sections describe the valid
|
||||
keys within an info file (and maybe how the Downloader cog uses them).
|
||||
|
||||
Keys common to both repo and cog info.json (case sensitive)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- ``author`` (list of strings) - list of names of authors of the cog or repo.
|
||||
|
||||
- ``description`` (string) - A long description of the cog or repo. For cogs, this
|
||||
is displayed when a user executes ``!cog info``.
|
||||
|
||||
- ``install_msg`` (string) - The message that gets displayed when a cog
|
||||
is installed or a repo is added
|
||||
|
||||
.. tip:: You can use the ``[p]`` key in your string to use the prefix
|
||||
used for installing.
|
||||
|
||||
- ``short`` (string) - A short description of the cog or repo. For cogs, this info
|
||||
is displayed when a user executes ``!cog list``
|
||||
|
||||
Keys specific to the cog info.json (case sensitive)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- ``bot_version`` (list of integer) - Min version number of Red in the format ``(MAJOR, MINOR, PATCH)``
|
||||
|
||||
- ``hidden`` (bool) - Determines if a cog is visible in the cog list for a repo.
|
||||
|
||||
- ``disabled`` (bool) - Determines if a cog is available for install.
|
||||
|
||||
- ``required_cogs`` (map of cogname to repo URL) - A map of required cogs that this cog depends on.
|
||||
Downloader will not deal with this functionality but it may be useful for other cogs.
|
||||
|
||||
- ``requirements`` (list of strings) - list of required libraries that are
|
||||
passed to pip on cog install. ``SHARED_LIBRARIES`` do NOT go in this
|
||||
list.
|
||||
|
||||
- ``tags`` (list of strings) - A list of strings that are related to the
|
||||
functionality of the cog. Used to aid in searching.
|
||||
|
||||
- ``type`` (string) - Optional, defaults to ``COG``. Must be either ``COG`` or
|
||||
``SHARED_LIBRARY``. If ``SHARED_LIBRARY`` then ``hidden`` will be ``True``.
|
||||
|
||||
API Reference
|
||||
*************
|
||||
|
||||
.. automodule:: redbot.cogs.downloader.json_mixins
|
||||
|
||||
.. autoclass RepoJSONMixin
|
||||
:members
|
||||
|
||||
.. automodule:: redbot.cogs.downloader.installable
|
||||
|
||||
Installable
|
||||
^^^^^^^^^^^
|
||||
|
||||
.. autoclass:: Installable
|
||||
:members:
|
||||
|
||||
.. automodule:: redbot.cogs.downloader.repo_manager
|
||||
|
||||
Repo
|
||||
^^^^
|
||||
|
||||
.. autoclass:: Repo
|
||||
:members:
|
||||
|
||||
Repo Manager
|
||||
^^^^^^^^^^^^
|
||||
|
||||
.. autoclass:: RepoManager
|
||||
:members:
|
||||
|
||||
Exceptions
|
||||
^^^^^^^^^^
|
||||
|
||||
.. automodule:: redbot.cogs.downloader.errors
|
||||
:members:
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
.. framework events list
|
||||
|
||||
=============
|
||||
Custom Events
|
||||
=============
|
||||
|
||||
RPC Server
|
||||
^^^^^^^^^^
|
||||
|
||||
.. py:method:: Red.on_shutdown()
|
||||
|
||||
Dispatched when the bot begins it's shutdown procedures.
|
||||
@@ -0,0 +1,58 @@
|
||||
.. i18n framework reference
|
||||
|
||||
.. role:: python(code)
|
||||
:language: python
|
||||
|
||||
==============================
|
||||
Internationalization Framework
|
||||
==============================
|
||||
|
||||
-----------
|
||||
Basic Usage
|
||||
-----------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from redbot.core import commands
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
|
||||
_ = Translator("ExampleCog", __file__)
|
||||
|
||||
@cog_i18n(_)
|
||||
class ExampleCog:
|
||||
"""description"""
|
||||
|
||||
@commands.command()
|
||||
async def mycom(self, ctx):
|
||||
"""command description"""
|
||||
await ctx.send(_("This is a test command"))
|
||||
|
||||
--------
|
||||
Tutorial
|
||||
--------
|
||||
|
||||
After making your cog, generate a :code:`messages.pot` file
|
||||
|
||||
The process of generating this will depend on the operating system
|
||||
you are using
|
||||
|
||||
In a command prompt in your cog's package (where yourcog.py is),
|
||||
create a directory called "locales".
|
||||
Then do one of the following:
|
||||
|
||||
Windows: :code:`python <your python install path>\Tools\i18n\pygettext.py -D -n -p locales`
|
||||
|
||||
Mac: ?
|
||||
|
||||
Linux: :code:`pygettext3 -D -n -p locales`
|
||||
|
||||
This will generate a messages.pot file with strings to be translated, including
|
||||
docstrings.
|
||||
|
||||
-------------
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
.. automodule:: redbot.core.i18n
|
||||
:members:
|
||||
:special-members: __call__
|
||||
@@ -0,0 +1,95 @@
|
||||
.. V3 Mod log
|
||||
|
||||
.. role:: python(code)
|
||||
:language: python
|
||||
|
||||
|
||||
=======
|
||||
Mod log
|
||||
=======
|
||||
|
||||
Mod log has now been separated from Mod for V3.
|
||||
|
||||
***********
|
||||
Basic Usage
|
||||
***********
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from redbot.core import modlog
|
||||
import discord
|
||||
|
||||
class MyCog:
|
||||
@commands.command()
|
||||
@checks.admin_or_permissions(ban_members=True)
|
||||
async def ban(self, ctx, user: discord.Member, reason: str=None):
|
||||
await ctx.guild.ban(user)
|
||||
case = modlog.create_case(
|
||||
ctx.guild, ctx.message.created_at, "ban", user,
|
||||
ctx.author, reason, until=None, channel=None
|
||||
)
|
||||
await ctx.send("Done. It was about time.")
|
||||
|
||||
|
||||
**********************
|
||||
Registering Case types
|
||||
**********************
|
||||
|
||||
To register a single case type:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from redbot.core import modlog
|
||||
import discord
|
||||
|
||||
class MyCog:
|
||||
def __init__(self, bot):
|
||||
ban_case = {
|
||||
"name": "ban",
|
||||
"default_setting": True,
|
||||
"image": ":hammer:",
|
||||
"case_str": "Ban",
|
||||
"audit_type": "ban"
|
||||
}
|
||||
modlog.register_casetype(**ban_case)
|
||||
|
||||
To register multiple case types:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from redbot.core import modlog
|
||||
import discord
|
||||
|
||||
class MyCog:
|
||||
def __init__(self, bot):
|
||||
new_types = [
|
||||
{
|
||||
"name": "ban",
|
||||
"default_setting": True,
|
||||
"image": ":hammer:",
|
||||
"case_str": "Ban",
|
||||
"audit_type": "ban"
|
||||
},
|
||||
{
|
||||
"name": "kick",
|
||||
"default_setting": True,
|
||||
"image": ":boot:",
|
||||
"case_str": "Kick",
|
||||
"audit_type": "kick"
|
||||
}
|
||||
]
|
||||
modlog.register_casetypes(new_types)
|
||||
|
||||
.. important::
|
||||
Image should be the emoji you want to represent your case type with.
|
||||
|
||||
|
||||
*************
|
||||
API Reference
|
||||
*************
|
||||
|
||||
Mod log
|
||||
=======
|
||||
|
||||
.. automodule:: redbot.core.modlog
|
||||
:members:
|
||||
@@ -0,0 +1,63 @@
|
||||
.. rpc docs
|
||||
|
||||
===
|
||||
RPC
|
||||
===
|
||||
|
||||
V3 comes default with an internal RPC server that may be used to remotely control the bot in various ways.
|
||||
Cogs must register functions to be exposed to RPC clients.
|
||||
Each of those functions must only take JSON serializable parameters and must return JSON serializable objects.
|
||||
|
||||
To enable the internal RPC server you must start the bot with the ``--rpc`` flag.
|
||||
|
||||
********
|
||||
Examples
|
||||
********
|
||||
|
||||
.. code-block:: Python
|
||||
|
||||
def setup(bot):
|
||||
c = Cog()
|
||||
bot.add_cog(c)
|
||||
bot.register_rpc_handler(c.rpc_method)
|
||||
|
||||
*******************************
|
||||
Interacting with the RPC Server
|
||||
*******************************
|
||||
|
||||
The RPC server opens a websocket bound to port ``6133`` on ``127.0.0.1``.
|
||||
This is not configurable for security reasons as broad access to this server gives anyone complete control over your bot.
|
||||
To access the server you must find a library that implements websocket based JSONRPC in the language of your choice.
|
||||
|
||||
There are a few built-in RPC methods to note:
|
||||
|
||||
* ``GET_METHODS`` - Returns a list of available RPC methods.
|
||||
* ``GET_METHOD_INFO`` - Will return the docstring for an available RPC method. Useful for finding information about the method's parameters and return values.
|
||||
* ``GET_TOPIC`` - Returns a list of available RPC message topics.
|
||||
* ``GET_SUBSCRIPTIONS`` - Returns a list of RPC subscriptions.
|
||||
* ``SUBSCRIBE`` - Subscribes to an available RPC message topic.
|
||||
* ``UNSUBSCRIBE`` - Unsubscribes from an RPC message topic.
|
||||
|
||||
All RPC methods accept a list of parameters.
|
||||
The built-in methods above expect their parameters to be in list format.
|
||||
|
||||
All cog-based methods expect their parameter list to take one argument, a JSON object, in the following format::
|
||||
|
||||
params = [
|
||||
{
|
||||
"args": [], # A list of positional arguments
|
||||
"kwargs": {}, # A dictionary of keyword arguments
|
||||
}
|
||||
]
|
||||
|
||||
# As an example, here's a call to "get_method_info"
|
||||
rpc_call("GET_METHOD_INFO", ["get_methods",])
|
||||
|
||||
# And here's a call to "core__load"
|
||||
rpc_call("CORE__LOAD", {"args": [["general", "economy", "downloader"],], "kwargs": {}})
|
||||
|
||||
*************
|
||||
API Reference
|
||||
*************
|
||||
|
||||
Please see the :class:`redbot.core.bot.RedBase` class for details on the RPC handler register and unregister methods.
|
||||
@@ -0,0 +1,59 @@
|
||||
.. red's core utils documentation
|
||||
|
||||
=================
|
||||
Utility Functions
|
||||
=================
|
||||
|
||||
General Utility
|
||||
===============
|
||||
|
||||
.. automodule:: redbot.core.utils
|
||||
:members: deduplicate_iterables, bounded_gather, bounded_gather_iter
|
||||
|
||||
Chat Formatting
|
||||
===============
|
||||
|
||||
.. automodule:: redbot.core.utils.chat_formatting
|
||||
:members:
|
||||
|
||||
Embed Helpers
|
||||
=============
|
||||
|
||||
.. automodule:: redbot.core.utils.embed
|
||||
:members:
|
||||
|
||||
Reaction Menus
|
||||
==============
|
||||
|
||||
.. automodule:: redbot.core.utils.menus
|
||||
:members:
|
||||
|
||||
Event Predicates
|
||||
================
|
||||
|
||||
.. automodule:: redbot.core.utils.predicates
|
||||
:members:
|
||||
|
||||
Mod Helpers
|
||||
===========
|
||||
|
||||
.. automodule:: redbot.core.utils.mod
|
||||
:members:
|
||||
|
||||
V2 Data Conversion
|
||||
==================
|
||||
|
||||
.. automodule:: redbot.core.utils.data_converter
|
||||
:members: DataConverter
|
||||
|
||||
Tunnel
|
||||
======
|
||||
|
||||
.. automodule:: redbot.core.utils.tunnel
|
||||
:members: Tunnel
|
||||
|
||||
Common Filters
|
||||
==============
|
||||
|
||||
.. automodule:: redbot.core.utils.common_filters
|
||||
:members:
|
||||
@@ -0,0 +1,94 @@
|
||||
.. Making cogs for V3
|
||||
|
||||
.. role:: python(code)
|
||||
:language: python
|
||||
|
||||
====================
|
||||
Creating cogs for V3
|
||||
====================
|
||||
|
||||
This guide serves as a tutorial on creating cogs for Red V3.
|
||||
It will cover the basics of setting up a package for your
|
||||
cog and the basics of setting up the file structure. We will
|
||||
also point you towards some further resources that may assist
|
||||
you in the process.
|
||||
|
||||
---------------
|
||||
Getting started
|
||||
---------------
|
||||
|
||||
To start off, be sure that you have installed Python 3.6.2 or higher (3.6.6 or higher on Windows).
|
||||
Open a terminal or command prompt and type :code:`pip install --process-dependency-links -U git+https://github.com/Cog-Creators/Red-DiscordBot@V3/develop#egg=redbot[test]`
|
||||
(note that if you get an error with this, try again but put :code:`python -m` in front of the command
|
||||
This will install the latest version of V3.
|
||||
|
||||
--------------------
|
||||
Setting up a package
|
||||
--------------------
|
||||
|
||||
To set up a package, we would just need to create a new folder.
|
||||
This should be named whatever you want the cog to be named (for
|
||||
the purposes of this example, we'll call this :code:`mycog`).
|
||||
In this folder, create three files: :code:`__init__.py`,
|
||||
:code:`mycog.py`, and :code:`info.json`. Open the folder in
|
||||
a text editor or IDE (examples include `Sublime Text 3 <https://www.sublimetext.com/>`_,
|
||||
`Visual Studio Code <https://code.visualstudio.com/>`_, `Atom <https://atom.io/>`_, and
|
||||
`PyCharm <http://www.jetbrains.com/pycharm/>`_).
|
||||
|
||||
--------------
|
||||
Creating a cog
|
||||
--------------
|
||||
|
||||
With your package opened in a text editor or IDE, open :code:`mycog.py`.
|
||||
In that file, place the following code:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from redbot.core import commands
|
||||
|
||||
class Mycog:
|
||||
"""My custom cog"""
|
||||
|
||||
@commands.command()
|
||||
async def mycom(self, ctx):
|
||||
"""This does stuff!"""
|
||||
# Your code will go here
|
||||
await ctx.send("I can do stuff!")
|
||||
|
||||
Open :code:`__init__.py`. In that file, place the following:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from .mycog import Mycog
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Mycog())
|
||||
|
||||
Make sure that both files are saved.
|
||||
|
||||
----------------
|
||||
Testing your cog
|
||||
----------------
|
||||
|
||||
To test your cog, you will need a running instance of V3.
|
||||
Assuming you installed V3 as outlined above, run :code:`redbot-setup`
|
||||
and provide the requested information. Once that's done, run Red
|
||||
by doing :code:`redbot <instance name> --dev` to start Red.
|
||||
Complete the inital setup by providing a valid token and setting a
|
||||
prefix. Once the bot has started up, use the link provided in the
|
||||
console to add it to a server (note that you must have the
|
||||
:code:`Manage Server` (or :code:`Administrator`) permission to add bots
|
||||
to a server). Once it's been added to a server, find the full path
|
||||
to the directory where your cog package is located. In Discord, do
|
||||
:code:`[p]addpath <path_to_folder_containing_package>`, then do
|
||||
:code:`[p]load mycog`. Once the cog is loaded, do :code:`[p]mycom`
|
||||
The bot should respond with :code:`I can do stuff!`. If it did, you
|
||||
have successfully created a cog!
|
||||
|
||||
--------------------
|
||||
Additional resources
|
||||
--------------------
|
||||
|
||||
Be sure to check out the :doc:`/guide_migration` for some resources
|
||||
on developing cogs for V3. This will also cover differences between V2 and V3 for
|
||||
those who developed cogs for V2.
|
||||
@@ -0,0 +1,154 @@
|
||||
.. Converting Data from a V2 cog
|
||||
|
||||
.. role:: python(code)
|
||||
:language: python
|
||||
|
||||
============================
|
||||
Importing Data From a V2 Cog
|
||||
============================
|
||||
|
||||
This guide serves as a tutorial on using the DataConverter class
|
||||
to import settings from a V2 cog.
|
||||
|
||||
------------------
|
||||
Things you'll need
|
||||
------------------
|
||||
|
||||
1. The path where each file holding related settings in v2 is
|
||||
2. A conversion function to take the data and transform it to conform to Config
|
||||
|
||||
-----------------------
|
||||
Getting your file paths
|
||||
-----------------------
|
||||
|
||||
You should probably not try to find the files manually.
|
||||
Asking the user for the base install path and using a relative path to where the
|
||||
data should be, then testing that the file exists there is safer. This is especially
|
||||
True if your cog has multiple settings files
|
||||
|
||||
Example
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from discord.ext import commands
|
||||
from pathlib import Path
|
||||
|
||||
@commands.command(name="filefinder")
|
||||
async def file_finding_command(self, ctx, filepath):
|
||||
"""
|
||||
this finds a file based on a user provided input and a known relative path
|
||||
"""
|
||||
|
||||
base_path = Path(filepath)
|
||||
fp = base_path / 'data' / 'mycog' / 'settings.json'
|
||||
if not fp.is_file():
|
||||
pass
|
||||
# fail, prompting user
|
||||
else:
|
||||
pass
|
||||
# do something with the file
|
||||
|
||||
---------------
|
||||
Converting data
|
||||
---------------
|
||||
|
||||
Once you've gotten your v2 settings file, you'll want to be able to import it
|
||||
There are a couple options available depending on how you would like to convert
|
||||
the data.
|
||||
|
||||
The first one takes a data path, and a conversion function and does the rest for you.
|
||||
This is great for simple data that just needs to quickly be imported without much
|
||||
modification.
|
||||
|
||||
|
||||
Here's an example of that in use:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pathlib import Path
|
||||
from discord.ext import commands
|
||||
|
||||
from redbot.core.utils.data_converter import DataConverter as dc
|
||||
from redbot.core.config import Config
|
||||
|
||||
...
|
||||
|
||||
|
||||
async def import_v2(self, file_path: Path):
|
||||
"""
|
||||
to be called from a command limited to owner
|
||||
|
||||
This should be a coroutine as the convert function will
|
||||
need to be awaited
|
||||
"""
|
||||
|
||||
# First we give the converter our cog's Config instance.
|
||||
converter = dc(self.config)
|
||||
|
||||
# next we design a way to get all of the data into Config's internal
|
||||
# format. This should be a generator, but you can also return a single
|
||||
# list with identical results outside of memory usage
|
||||
def conversion_spec(v2data):
|
||||
for guild_id in v2.data.keys():
|
||||
yield {(Config.GUILD, guild_id): {('blacklisted',): True}}
|
||||
# This is yielding a dictionary that is designed for config's set_raw.
|
||||
# The keys should be a tuple of Config scopes + the needed Identifiers. The
|
||||
# values should be another dictionary whose keys are tuples representing
|
||||
# config settings, the value should be the value to set for that.
|
||||
|
||||
# Then we pass the file and the conversion function
|
||||
await converter.convert(file_path, conversion_spec)
|
||||
# From here, our data should be imported
|
||||
|
||||
|
||||
You can also choose to convert all of your data and pass it as a single dict
|
||||
This can be useful if you want finer control over the dataconversion or want to
|
||||
preserve any data from v3 that may share the same entry and set it aside to prompt
|
||||
a user
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pathlib import Path
|
||||
from discord.ext import commands
|
||||
|
||||
from redbot.core.utils.data_converter import DataConverter as dc
|
||||
from redbot.core.config import Config
|
||||
|
||||
...
|
||||
|
||||
await dc(config_instance).dict_import(some_processed_dict)
|
||||
|
||||
|
||||
The format of the items of the dict is the same as in the above example
|
||||
|
||||
|
||||
-----------------------------------
|
||||
Config Scopes and their Identifiers
|
||||
-----------------------------------
|
||||
|
||||
This section is provided as a quick reference for the identifiers for default
|
||||
scopes available in Config. This does not cover usage of custom scopes, though the
|
||||
data converter is compatible with those as well.
|
||||
|
||||
Global::
|
||||
:code:`(Config.GLOBAL,)`
|
||||
Guild::
|
||||
:code:`(Config.GUILD, guild_id)`
|
||||
Channel::
|
||||
:code:`(Config.CHANNEL, channel_id)`
|
||||
User::
|
||||
:code:`(Config.USER, user_id)`
|
||||
Member::
|
||||
:code:`(Config.MEMBER, guild_id, user_id)`
|
||||
Role::
|
||||
:code:`(Config.ROLE, role_id)`
|
||||
|
||||
|
||||
-----------------------------
|
||||
More information and Examples
|
||||
-----------------------------
|
||||
|
||||
For a more in depth look at how all of these commands function
|
||||
You may want to take a look at how core data is being imported
|
||||
|
||||
:code:`redbot/cogs/dataconverter/core_specs.py`
|
||||
@@ -0,0 +1,56 @@
|
||||
.. V3 Migration Guide
|
||||
|
||||
.. role:: python(code)
|
||||
:language: python
|
||||
|
||||
====================
|
||||
Migrating Cogs to V3
|
||||
====================
|
||||
|
||||
First, be sure to read `discord.py's migration guide <http://discordpy.readthedocs.io/en/rewrite/migrating.html>`_
|
||||
as that covers all of the changes to discord.py that will affect the migration process
|
||||
|
||||
----------------
|
||||
Red as a package
|
||||
----------------
|
||||
|
||||
V3 makes Red a package that is installed with :code:`pip`. Please
|
||||
keep this in mind when writing cogs as this affects how imports
|
||||
should be done (for example, to import :code:`pagify` in V2, one
|
||||
would do :code:`from .utils.chat_formatting import pagify`; in
|
||||
V3, this becomes :code:`from redbot.core.utils.chat_formatting import pagify`)
|
||||
|
||||
----------------
|
||||
Cogs as packages
|
||||
----------------
|
||||
|
||||
V3 makes cogs into packages. See :doc:`/guide_cog_creation`
|
||||
for more on how to create packages for V3.
|
||||
|
||||
------
|
||||
Config
|
||||
------
|
||||
|
||||
Config is V3's replacement for :code:`dataIO`. Instead of fiddling with
|
||||
creating config directories and config files as was done in V2, V3's
|
||||
Config handles that whilst allowing for easy storage of settings on a
|
||||
per-server/member/user/role/channel or global basis. Be sure to check
|
||||
out :doc:`/framework_config` for the API docs for Config as well as a
|
||||
tutorial on using Config.
|
||||
|
||||
----
|
||||
Bank
|
||||
----
|
||||
|
||||
Bank in V3 has been split out from Economy. V3 introduces the ability
|
||||
to have a global bank as well as the ability to change the bank name
|
||||
and the name of the currency. Be sure to checkout :doc:`/framework_bank`
|
||||
for more on Bank
|
||||
|
||||
-------
|
||||
Mod Log
|
||||
-------
|
||||
|
||||
V3 introduces Mod Log as an API, thus allowing for cogs to add custom case
|
||||
types that will appear in a server's mod log channel. Be sure to checkout
|
||||
:doc:`/framework_modlog` for more on Mod Log`
|
||||
@@ -0,0 +1,55 @@
|
||||
.. Red - Discord Bot documentation master file, created by
|
||||
sphinx-quickstart on Thu Aug 10 23:18:25 2017.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to Red - Discord Bot's documentation!
|
||||
=============================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:caption: Installation Guides:
|
||||
|
||||
install_windows
|
||||
install_linux_mac
|
||||
venv_guide
|
||||
cog_dataconverter
|
||||
autostart_systemd
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Cog Reference:
|
||||
|
||||
cog_customcom
|
||||
cog_downloader
|
||||
cog_permissions
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Red Development Framework Reference:
|
||||
|
||||
guide_migration
|
||||
guide_cog_creation
|
||||
guide_data_conversion
|
||||
framework_bank
|
||||
framework_bot
|
||||
framework_checks
|
||||
framework_cogmanager
|
||||
framework_commands
|
||||
framework_config
|
||||
framework_datamanager
|
||||
framework_downloader
|
||||
framework_events
|
||||
framework_i18n
|
||||
framework_modlog
|
||||
framework_rpc
|
||||
framework_utils
|
||||
|
||||
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
@@ -0,0 +1,203 @@
|
||||
.. _linux-mac-install-guide:
|
||||
|
||||
==============================
|
||||
Installing Red on Linux or Mac
|
||||
==============================
|
||||
|
||||
.. warning::
|
||||
|
||||
For safety reasons, DO NOT install Red with a root user. If you are unsure how to create
|
||||
a new user, see the man page for the ``useradd`` command.
|
||||
|
||||
-------------------------------
|
||||
Installing the pre-requirements
|
||||
-------------------------------
|
||||
|
||||
Please install the pre-requirements using the commands listed for your operating system.
|
||||
|
||||
The pre-requirements are:
|
||||
- Python 3.6.2 or greater
|
||||
- pip 9.0 or greater
|
||||
- git
|
||||
- Java Runtime Environment 8 or later (for audio support)
|
||||
|
||||
~~~~~~~~~~
|
||||
Arch Linux
|
||||
~~~~~~~~~~
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
sudo pacman -Syu python-pip git base-devel jre8-openjdk
|
||||
|
||||
~~~~~~~~
|
||||
CentOS 7
|
||||
~~~~~~~~
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
yum -y groupinstall development
|
||||
yum -y install https://centos7.iuscommunity.org/ius-release.rpm
|
||||
yum -y install yum-utils wget which python36u python36u-pip python36u-devel openssl-devel libffi-devel git java-1.8.0-openjdk
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Debian and Raspbian Stretch
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. warning::
|
||||
|
||||
Audio will not work on Raspberry Pi's **below** 2B. This is a CPU problem and
|
||||
*cannot* be fixed.
|
||||
|
||||
We recommend installing pyenv as a method of installing non-native versions of python on
|
||||
Debian/Raspbian Stretch. This guide will tell you how. First, run the following commands:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
sudo apt install -y make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev git unzip default-jre
|
||||
curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash
|
||||
|
||||
After that last command, you may see a warning about 'pyenv' not being in the load path. Follow the
|
||||
instructions given to fix that, then close and reopen your shell.
|
||||
|
||||
Then run the following command:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
CONFIGURE_OPTS=--enable-optimizations pyenv install 3.7.0 -v
|
||||
|
||||
This may take a long time to complete.
|
||||
|
||||
After that is finished, run:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
pyenv global 3.7.0
|
||||
|
||||
Pyenv is now installed and your system should be configured to run Python 3.7.
|
||||
|
||||
~~~
|
||||
Mac
|
||||
~~~
|
||||
|
||||
Install Brew: in Finder or Spotlight, search for and open *Terminal*. In the terminal, paste the
|
||||
following, then press Enter:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
||||
|
||||
After the installation, install the required packages by pasting the commands and pressing enter,
|
||||
one-by-one:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
brew install python3 --with-brewed-openssl
|
||||
brew install git
|
||||
brew tap caskroom/versions
|
||||
brew cask install java8
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Ubuntu 18.04 Bionic Beaver
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
sudo apt install python3.6-dev python3-pip build-essential libssl-dev libffi-dev git unzip default-jre -y
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Ubuntu 16.04 Xenial Xerus
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
We recommend adding the ``deadsnakes`` apt repository to install Python 3.6.2 or greater:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
sudo apt install software-properties-common
|
||||
sudo add-apt-repository ppa:deadsnakes/ppa
|
||||
sudo apt update
|
||||
|
||||
Now, install python, pip, git and java with the following commands:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
sudo apt install python3.6-dev build-essential libssl-dev libffi-dev git unzip default-jre wget -y
|
||||
wget https://bootstrap.pypa.io/get-pip.py
|
||||
sudo python3.6 get-pip.py
|
||||
|
||||
------------------------------
|
||||
Creating a Virtual Environment
|
||||
------------------------------
|
||||
|
||||
We **strongly** recommend installing Red into a virtual environment. See the section
|
||||
`installing-in-virtual-environment`.
|
||||
|
||||
.. _installing-red-linux-mac:
|
||||
|
||||
--------------
|
||||
Installing Red
|
||||
--------------
|
||||
|
||||
Choose one of the following commands to install Red.
|
||||
|
||||
.. note::
|
||||
|
||||
If you're not inside an activated virtual environment, include the ``--user`` flag with all
|
||||
``pip3`` commands.
|
||||
|
||||
To install without audio support:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
pip3 install -U --process-dependency-links --no-cache-dir Red-DiscordBot
|
||||
|
||||
Or, to install with audio support:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
pip3 install -U --process-dependency-links --no-cache-dir Red-DiscordBot[voice]
|
||||
|
||||
Or, install with audio and MongoDB support:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
pip3 install -U --process-dependency-links --no-cache-dir Red-DiscordBot[voice,mongo]
|
||||
|
||||
.. note::
|
||||
|
||||
To install the development version, replace ``Red-DiscordBot`` in the above commands with the
|
||||
following link:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
git+https://github.com/Cog-Creators/Red-DiscordBot@V3/develop#egg=Red-DiscordBot
|
||||
|
||||
--------------------------
|
||||
Setting Up and Running Red
|
||||
--------------------------
|
||||
|
||||
After installation, set up your instance with the following command:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
redbot-setup
|
||||
|
||||
This will set the location where data will be stored, as well as your
|
||||
storage backend and the name of the instance (which will be used for
|
||||
running the bot).
|
||||
|
||||
Once done setting up the instance, run the following command to run Red:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
redbot <your instance name>
|
||||
|
||||
It will walk through the initial setup, asking for your token and a prefix.
|
||||
|
||||
You may also run Red via the launcher, which allows you to restart the bot
|
||||
from discord, and enable auto-restart. You may also update the bot from the
|
||||
launcher menu. Use the following command to run the launcher:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
redbot-launcher
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
.. _windows-install-guide:
|
||||
|
||||
=========================
|
||||
Installing Red on Windows
|
||||
=========================
|
||||
|
||||
---------------
|
||||
Needed Software
|
||||
---------------
|
||||
|
||||
* `Python <https://www.python.org/downloads/>`_ - Red needs Python 3.6.6 or greater on Windows
|
||||
|
||||
.. note:: Please make sure that the box to add Python to PATH is CHECKED, otherwise
|
||||
you may run into issues when trying to run Red
|
||||
|
||||
* `Git <https://git-scm.com/download/win>`_
|
||||
|
||||
.. attention:: Please choose the option to "Run Git from the Windows Command Prompt" in Git's setup
|
||||
|
||||
* `Java <https://java.com/en/download/manual.jsp>`_ - needed for Audio
|
||||
|
||||
.. attention:: Please choose the "Windows Online" installer
|
||||
|
||||
.. _installing-red-windows:
|
||||
|
||||
--------------
|
||||
Installing Red
|
||||
--------------
|
||||
|
||||
1. Open a command prompt (open Start, search for "command prompt", then click it)
|
||||
2. Create and activate a virtual environment (strongly recommended), see the section `using-venv`
|
||||
3. Run **one** of the following commands, depending on what extras you want installed
|
||||
|
||||
.. note::
|
||||
|
||||
If you're not inside an activated virtual environment, include the ``--user`` flag with all
|
||||
``pip`` commands.
|
||||
|
||||
* No audio:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
python -m pip install -U --process-dependency-links --no-cache-dir Red-DiscordBot
|
||||
|
||||
* With audio:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
python -m pip install -U --process-dependency-links --no-cache-dir Red-DiscordBot[voice]
|
||||
|
||||
* With audio and MongoDB support:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
python -m pip install -U --process-dependency-links --no-cache-dir Red-DiscordBot[voice,mongo]
|
||||
|
||||
.. note::
|
||||
|
||||
To install the development version, replace ``Red-DiscordBot`` in the above commands with the
|
||||
following link:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
git+https://github.com/Cog-Creators/Red-DiscordBot@V3/develop#egg=Red-DiscordBot
|
||||
|
||||
--------------------------
|
||||
Setting Up and Running Red
|
||||
--------------------------
|
||||
|
||||
After installation, set up your instance with the following command:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
redbot-setup
|
||||
|
||||
This will set the location where data will be stored, as well as your
|
||||
storage backend and the name of the instance (which will be used for
|
||||
running the bot).
|
||||
|
||||
Once done setting up the instance, run the following command to run Red:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
redbot <your instance name>
|
||||
|
||||
It will walk through the initial setup, asking for your token and a prefix.
|
||||
|
||||
You may also run Red via the launcher, which allows you to restart the bot
|
||||
from discord, and enable auto-restart. You may also update the bot from the
|
||||
launcher menu. Use the following command to run the launcher:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
redbot-launcher
|
||||
@@ -0,0 +1,36 @@
|
||||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=python -msphinx
|
||||
)
|
||||
set SOURCEDIR=.
|
||||
set BUILDDIR=_build
|
||||
set SPHINXPROJ=Red-DiscordBot
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The Sphinx module was not found. Make sure you have Sphinx installed,
|
||||
echo.then set the SPHINXBUILD environment variable to point to the full
|
||||
echo.path of the 'sphinx-build' executable. Alternatively you may add the
|
||||
echo.Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
|
||||
:end
|
||||
popd
|
||||
@@ -0,0 +1,132 @@
|
||||
.. _installing-in-virtual-environment:
|
||||
|
||||
=======================================
|
||||
Installing Red in a Virtual Environment
|
||||
=======================================
|
||||
Virtual environments allow you to isolate red's library dependencies, cog dependencies and python
|
||||
binaries from the rest of your system. It is strongly recommended you use this if you use python
|
||||
for more than just Red.
|
||||
|
||||
.. _using-venv:
|
||||
|
||||
--------------
|
||||
Using ``venv``
|
||||
--------------
|
||||
This is the quickest way to get your virtual environment up and running, as `venv` is shipped with
|
||||
python.
|
||||
|
||||
First, choose a directory where you would like to create your virtual environment. It's a good idea
|
||||
to keep it in a location which is easy to type out the path to. From now, we'll call it
|
||||
``path/to/venv/`` (or ``path\to\venv\`` on Windows).
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
``venv`` on Linux or Mac
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Create your virtual environment with the following command::
|
||||
|
||||
python3 -m venv path/to/venv/
|
||||
|
||||
And activate it with the following command::
|
||||
|
||||
source path/to/venv/bin/activate
|
||||
|
||||
.. important::
|
||||
|
||||
You must activate the virtual environment with the above command every time you open a new
|
||||
shell to run, install or update Red.
|
||||
|
||||
Continue reading `below <after-activating-virtual-environment>`.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
``venv`` on Windows
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
Create your virtual environment with the following command::
|
||||
|
||||
python -m venv path\to\venv\
|
||||
|
||||
And activate it with the following command::
|
||||
|
||||
path\to\venv\Scripts\activate.bat
|
||||
|
||||
.. important::
|
||||
|
||||
You must activate the virtual environment with the above command every time you open a new
|
||||
Command Prompt to run, install or update Red.
|
||||
|
||||
Continue reading `below <after-activating-virtual-environment>`.
|
||||
|
||||
.. _using-pyenv-virtualenv:
|
||||
|
||||
--------------------------
|
||||
Using ``pyenv virtualenv``
|
||||
--------------------------
|
||||
|
||||
.. note::
|
||||
|
||||
This is for non-Windows users only.
|
||||
|
||||
Using ``pyenv virtualenv`` saves you the headache of remembering where you installed your virtual
|
||||
environments. If you haven't already, install pyenv with `pyenv-installer`_.
|
||||
|
||||
First, ensure your pyenv interpreter is set to python 3.6.2 or greater with the following command::
|
||||
|
||||
pyenv version
|
||||
|
||||
Now, create a virtual environment with the following command::
|
||||
|
||||
pyenv virtualenv <name>
|
||||
|
||||
Replace ``<name>`` with whatever you like. If you forget what you named it, use the command ``pyenv
|
||||
versions``.
|
||||
|
||||
Now activate your virtualenv with the following command::
|
||||
|
||||
pyenv shell <name>
|
||||
|
||||
.. important::
|
||||
|
||||
You must activate the virtual environment with the above command every time you open a new
|
||||
shell to run, install or update Red.
|
||||
|
||||
Continue reading `below <after-activating-virtual-environment>`.
|
||||
|
||||
.. _pyenv-installer: https://github.com/pyenv/pyenv-installer/blob/master/README.rst
|
||||
|
||||
----
|
||||
|
||||
.. _after-activating-virtual-environment:
|
||||
|
||||
Once activated, your ``PATH`` environment variable will be modified to use the virtual
|
||||
environment's python executables, as well as other executables like ``pip``.
|
||||
|
||||
From here, install Red using the commands listed on your installation guide (`Windows
|
||||
<installing-red-windows>` or `Non-Windows <installing-red-linux-mac>`).
|
||||
|
||||
.. note::
|
||||
|
||||
The alternative to activating the virtual environment each time you open a new shell is to
|
||||
provide the full path to the executable. This will automatically use the virtual environment's
|
||||
python interpreter and installed libraries.
|
||||
|
||||
--------------------------------------------
|
||||
Virtual Environments with Multiple Instances
|
||||
--------------------------------------------
|
||||
If you are running multiple instances of Red on the same machine, you have the option of either
|
||||
using the same virtual environment for all of them, or creating separate ones.
|
||||
|
||||
.. note::
|
||||
|
||||
This only applies for multiple instances of V3. If you are running a V2 instance as well,
|
||||
You **must** use separate virtual environments.
|
||||
|
||||
The advantages of using a *single* virtual environment for all of your V3 instances are:
|
||||
|
||||
- When updating Red, you will only need to update it once for all instances (however you will still need to restart all instances for the changes to take effect)
|
||||
- It will save space on your hard drive
|
||||
|
||||
On the other hand, you may wish to update each of your instances individually.
|
||||
|
||||
.. important::
|
||||
|
||||
Windows users with multiple instances should create *separate* virtual environments, as
|
||||
updating multiple running instances at once is likely to cause errors.
|
||||
-249
@@ -1,249 +0,0 @@
|
||||
from random import randint, choice
|
||||
import time
|
||||
|
||||
import dataIO
|
||||
|
||||
client = None
|
||||
settings = []
|
||||
#words = dataIO.loadWords()
|
||||
#anagram_sessions_timestamps = {}
|
||||
anagram_sessions = []
|
||||
payday_register = {}
|
||||
PAYDAY_TIME = 300 # seconds between each payday
|
||||
PAYDAY_CREDITS = 120 # credits received
|
||||
|
||||
def initialize():
|
||||
global bank
|
||||
bank = dataIO.fileIO("json/economy.json", "load")
|
||||
|
||||
def loadHelp():
|
||||
global slot_help, economy_exp
|
||||
|
||||
if settings == []: return False #first run
|
||||
|
||||
slot_help = """ Slot machine payouts:
|
||||
:two: :two: :six: Bet * 5000
|
||||
:four_leaf_clover: :four_leaf_clover: :four_leaf_clover: +1000
|
||||
:cherries: :cherries: :cherries: +800
|
||||
:two: :six: Bet * 4
|
||||
:cherries: :cherries: Bet * 3
|
||||
|
||||
Three symbols: +500
|
||||
Two symbols: Bet * 2
|
||||
|
||||
You need an account to play. {0}register one.
|
||||
Bet range: 5 - 100
|
||||
""".format(settings["PREFIX"])
|
||||
|
||||
economy_exp = """ **Economy. Get rich and have fun with imaginary currency!**
|
||||
|
||||
{0}register - Register an account at the Twentysix bank
|
||||
{0}balance - Check your balance
|
||||
{0}slot help - Slot machine explanation
|
||||
{0}slot [bid] - Play the slot machine
|
||||
{0}payday - Type it every {1} seconds to receive some credits.
|
||||
""".format(settings["PREFIX"], str(PAYDAY_TIME))
|
||||
|
||||
async def checkCommands(message):
|
||||
p = settings["PREFIX"]
|
||||
cmd = message.content
|
||||
user = message.author
|
||||
if cmd == p + "balance":
|
||||
if accountCheck(user.id):
|
||||
await client.send_message(message.channel, "{} `Your balance is: {}`".format(user.mention, str(checkBalance(user.id))))
|
||||
else:
|
||||
await client.send_message(message.channel, "{} `You don't have an account at the Twentysix bank. Type !register to open one.`".format(user.mention, str(checkBalance(user.id))))
|
||||
elif cmd == p + "register":
|
||||
await registerAccount(user, message)
|
||||
elif cmd == p + "slot help":
|
||||
await client.send_message(message.author, slot_help)
|
||||
await client.send_message(message.channel, "{} `Check your DMs for the slot machine explanation.`".format(message.author.mention))
|
||||
elif cmd.startswith(p + "slot"):
|
||||
await slotMachineCheck(message)
|
||||
elif cmd == p + "economy":
|
||||
await client.send_message(message.author, economy_exp)
|
||||
await client.send_message(message.channel, "{} `Check your DMs for the economy explanation.`".format(message.author.mention))
|
||||
elif cmd == p + "challenge":
|
||||
#isChallengeOngoing(message)
|
||||
pass
|
||||
elif cmd == p + "payday":
|
||||
await payday(message)
|
||||
|
||||
async def registerAccount(user, message):
|
||||
if user.id not in bank:
|
||||
bank[user.id] = {"name" : user.name, "balance" : 100}
|
||||
dataIO.fileIO("json/economy.json", "save", bank)
|
||||
await client.send_message(message.channel, "{} `Account opened. Current balance: {}`".format(user.mention, str(checkBalance(user.id))))
|
||||
else:
|
||||
await client.send_message(message.channel, "{} `You already have an account at the Twentysix bank.`".format(user.mention))
|
||||
|
||||
def accountCheck(id):
|
||||
if id in bank:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def checkBalance(id):
|
||||
if accountCheck(id):
|
||||
return bank[id]["balance"]
|
||||
else:
|
||||
return False
|
||||
|
||||
def withdrawMoney(id, amount):
|
||||
if accountCheck(id):
|
||||
if bank[id]["balance"] >= int(amount):
|
||||
bank[id]["balance"] = bank[id]["balance"] - int(amount)
|
||||
dataIO.fileIO("json/economy.json", "save", bank)
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
def addMoney(id, amount):
|
||||
if accountCheck(id):
|
||||
bank[id]["balance"] = bank[id]["balance"] + int(amount)
|
||||
dataIO.fileIO("json/economy.json", "save", bank)
|
||||
else:
|
||||
return False
|
||||
|
||||
def enoughMoney(id, amount):
|
||||
if accountCheck(id):
|
||||
if bank[id]["balance"] >= int(amount):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
async def isChallengeOngoing(message): #Work in progress
|
||||
global anagram_sessions, anagram_sessions_timestamps
|
||||
id = message.channel.id
|
||||
for session in anagram_sessions:
|
||||
if time.perf_counter() - session.started >= 600:
|
||||
if session.done:
|
||||
anagram_sessions.remove(session)
|
||||
anagram_sessions.append(Anagram(message))
|
||||
return True
|
||||
else:
|
||||
await client.send_message(message.channel, "{} `A challenge is already ongoing.`".format(message.author.mention))
|
||||
return True
|
||||
else:
|
||||
await client.send_message(message.channel, "{} `You have to wait 10 minutes before each challenge.`".format(message.author.mention))
|
||||
return True
|
||||
anagram_sessions.append(Anagram(message))
|
||||
|
||||
async def payday(message):
|
||||
id = message.author.id
|
||||
if accountCheck(id):
|
||||
if id in payday_register:
|
||||
if abs(payday_register[id] - int(time.perf_counter())) >= PAYDAY_TIME:
|
||||
addMoney(id, PAYDAY_CREDITS)
|
||||
payday_register[id] = int(time.perf_counter())
|
||||
await client.send_message(message.channel, "{} `Here, take some credits. Enjoy! (+{} credits!)`".format(message.author.mention, str(PAYDAY_CREDITS)))
|
||||
else:
|
||||
await client.send_message(message.channel, "{} `Too soon. You have to wait {} seconds between each payday.`".format(message.author.mention, str(PAYDAY_TIME)))
|
||||
else:
|
||||
payday_register[id] = int(time.perf_counter())
|
||||
addMoney(id, PAYDAY_CREDITS)
|
||||
await client.send_message(message.channel, "{} `Here, take some credits. Enjoy! (+{} credits!)`".format(message.author.mention, str(PAYDAY_CREDITS)))
|
||||
else:
|
||||
await client.send_message(message.channel, "{} `You need an account to receive credits. (!economy)`".format(message.author.mention))
|
||||
|
||||
###############SLOT##############
|
||||
|
||||
async def slotMachineCheck(message):
|
||||
p = settings["PREFIX"]
|
||||
msg = message.content.split()
|
||||
if len(msg) == 2:
|
||||
if msg[1].isdigit():
|
||||
bid = int(msg[1])
|
||||
if enoughMoney(message.author.id, bid):
|
||||
if bid > 4 and bid < 101:
|
||||
await slotMachine(message, bid)
|
||||
else:
|
||||
await client.send_message(message.channel, "{} `Bid must be between 5 and 100.`".format(message.author.mention))
|
||||
else:
|
||||
await client.send_message(message.channel, "{0} `You need an account with enough funds to play the slot machine. ({1}economy)`".format(message.author.mention, settings["PREFIX"]))
|
||||
else:
|
||||
await client.send_message(message.channel, "{} `".format(message.author.mention) + p + "slot [bid]`")
|
||||
else:
|
||||
await client.send_message(message.channel, "{} `".format(message.author.mention) + p + "slot [bid]`")
|
||||
|
||||
async def slotMachine(message, bid):
|
||||
reel_pattern = [":cherries:", ":cookie:", ":two:", ":four_leaf_clover:", ":cyclone:", ":sunflower:", ":six:", ":mushroom:", ":heart:", ":snowflake:"]
|
||||
padding_before = [":mushroom:", ":heart:", ":snowflake:"] # padding prevents index errors
|
||||
padding_after = [":cherries:", ":cookie:", ":two:"]
|
||||
reel = padding_before + reel_pattern + padding_after
|
||||
reels = []
|
||||
for i in range(0, 3):
|
||||
n = randint(3,12)
|
||||
reels.append([reel[n - 1], reel[n], reel[n + 1]])
|
||||
line = [reels[0][1], reels[1][1], reels[2][1]]
|
||||
|
||||
display_reels = " " + reels[0][0] + " " + reels[1][0] + " " + reels[2][0] + "\n"
|
||||
display_reels += ">" + reels[0][1] + " " + reels[1][1] + " " + reels[2][1] + "\n"
|
||||
display_reels += " " + reels[0][2] + " " + reels[1][2] + " " + reels[2][2] + "\n"
|
||||
|
||||
if line[0] == ":two:" and line[1] == ":two:" and line[2] == ":six:":
|
||||
bid = bid * 5000
|
||||
await client.send_message(message.channel, "{}{} `226! Your bet is multiplied * 5000! {}!` ".format(display_reels, message.author.mention, str(bid)))
|
||||
elif line[0] == ":four_leaf_clover:" and line[1] == ":four_leaf_clover:" and line[2] == ":four_leaf_clover:":
|
||||
bid += 1000
|
||||
await client.send_message(message.channel, "{}{} `Three FLC! +1000!` ".format(display_reels, message.author.mention))
|
||||
elif line[0] == ":cherries:" and line[1] == ":cherries:" and line[2] == ":cherries:":
|
||||
bid += 800
|
||||
await client.send_message(message.channel, "{}{} `Three cherries! +800!` ".format(display_reels, message.author.mention))
|
||||
elif line[0] == line[1] == line[2]:
|
||||
bid += 500
|
||||
await client.send_message(message.channel, "{}{} `Three symbols! +500!` ".format(display_reels, message.author.mention))
|
||||
elif line[0] == ":two:" and line[1] == ":six:" or line[1] == ":two:" and line[2] == ":six:":
|
||||
bid = bid * 4
|
||||
await client.send_message(message.channel, "{}{} `26! Your bet is multiplied * 4! {}!` ".format(display_reels, message.author.mention, str(bid)))
|
||||
elif line[0] == ":cherries:" and line[1] == ":cherries:" or line[1] == ":cherries:" and line[2] == ":cherries:":
|
||||
bid = bid * 3
|
||||
await client.send_message(message.channel, "{}{} `Two cherries! Your bet is multiplied * 3! {}!` ".format(display_reels, message.author.mention, str(bid)))
|
||||
elif line[0] == line[1] or line[1] == line[2]:
|
||||
bid = bid * 2
|
||||
await client.send_message(message.channel, "{}{} `Two symbols! Your bet is multiplied * 2! {}!` ".format(display_reels, message.author.mention, str(bid)))
|
||||
# elif line[0] == ":cherries:" or line[1] == ":cherries:" or line[2] == ":cherries:":
|
||||
# await client.send_message(message.channel, "{}{} `Cherries! Your bet is safe!` ".format(display_reels, message.author.mention))
|
||||
else:
|
||||
await client.send_message(message.channel, "{}{} `Nothing! Lost bet.` ".format(display_reels, message.author.mention))
|
||||
withdrawMoney(message.author.id, bid)
|
||||
await client.send_message(message.channel, "`Credits left: {}`".format(str(checkBalance(message.author.id))))
|
||||
return True
|
||||
addMoney(message.author.id, bid)
|
||||
await client.send_message(message.channel, "`Current credits: {}`".format(str(checkBalance(message.author.id))))
|
||||
|
||||
#######################################
|
||||
|
||||
############### ANAGRAM ###############
|
||||
# Work in progress
|
||||
|
||||
class Anagram():
|
||||
def __init__(self, message):
|
||||
self.channel = message.channel
|
||||
self.word = choice(words).lower()
|
||||
self.anagram = list(self.word)
|
||||
shuffle(self.anagram)
|
||||
self.anagram = "".join(self.anagram)
|
||||
self.started = int(time.perf_counter())
|
||||
self.MAX_TIME = 60
|
||||
self.done = False
|
||||
|
||||
def checkWord(self, message):
|
||||
if time.perf_counter() - self.Atimestamp <= self.MAX_TIME:
|
||||
msg = message.content.lower()
|
||||
if msg.find(self.word) != -1:
|
||||
pass
|
||||
else:
|
||||
self.gameOver()
|
||||
|
||||
async def gameOver(self):
|
||||
self.done = True
|
||||
try:
|
||||
await client.send_message(self.channel, "`Anagram session over! No one guessed the word!`")
|
||||
except:
|
||||
pass
|
||||
|
||||
######################################
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
@@ -1,2 +0,0 @@
|
||||
Insert your local playlists folders here. Every folder counts as a different playlist and can contain
|
||||
.mp3 and .flac files. No spaces allowed in their filenames, use underscores instead.
|
||||
@@ -0,0 +1,30 @@
|
||||
@echo off
|
||||
|
||||
if "%1"=="" goto help
|
||||
|
||||
REM This allows us to expand variables at execution
|
||||
setlocal ENABLEDELAYEDEXPANSION
|
||||
|
||||
REM This will set PYFILES as a list of tracked .py files
|
||||
set PYFILES=
|
||||
for /F "tokens=* USEBACKQ" %%A in (`git ls-files "*.py"`) do (
|
||||
set PYFILES=!PYFILES! %%A
|
||||
)
|
||||
|
||||
goto %1
|
||||
|
||||
:reformat
|
||||
black -l 99 -N !PYFILES!
|
||||
exit /B %ERRORLEVEL%
|
||||
|
||||
:stylecheck
|
||||
black -l 99 -N --check !PYFILES!
|
||||
exit /B %ERRORLEVEL%
|
||||
|
||||
:help
|
||||
echo Usage:
|
||||
echo make ^<command^>
|
||||
echo.
|
||||
echo Commands:
|
||||
echo reformat Reformat all .py files being tracked by git.
|
||||
echo stylecheck Check which tracked .py files need reformatting.
|
||||
@@ -1 +0,0 @@
|
||||
{"playlist": ["https://www.youtube.com/watch?v=6sxnXO2RjVg", "https://www.youtube.com/watch?v=gj0Rz-uP4Mk", "https://www.youtube.com/watch?v=_izUd1S1BX0", "https://www.youtube.com/watch?v=K39qFmvbdww", "https://www.youtube.com/watch?v=ZFo8-JqzSCM", "https://www.youtube.com/watch?v=zD80CostTV0", "https://www.youtube.com/watch?v=mWADuNREJnY", "https://www.youtube.com/watch?v=xelUdXAvDVU", "https://www.youtube.com/watch?v=A2ptDgMOzc0", "https://www.youtube.com/watch?v=YwHrx0r0t2s", "https://www.youtube.com/watch?v=jqxNSvFMkag", "https://www.youtube.com/watch?v=gHgphqx1KT4", "https://www.youtube.com/watch?v=6sxnXO2RjVg", "https://www.youtube.com/watch?v=inb1z-qjxIU", "https://www.youtube.com/watch?v=fZZD8ckwLJA", "https://www.youtube.com/watch?v=xFn9V-VpkQ4", "https://www.youtube.com/watch?v=X7pjP_XkK4U", "https://www.youtube.com/watch?v=QPwPDDz-5Uo", "https://www.youtube.com/watch?v=6jmNe77vces", "https://www.youtube.com/watch?v=dga_ds1bJKg", "https://www.youtube.com/watch?v=oPmaVT-P5Ds", "https://www.youtube.com/watch?v=Ud_JZcC0tHI", "https://www.youtube.com/watch?v=35Cy7DUltYo", "https://www.youtube.com/watch?v=ZvmGLV_GE0M", "https://www.youtube.com/watch?v=7CXFXB4uknI", "https://www.youtube.com/watch?v=4pgbJaKemic", "https://www.youtube.com/watch?v=Jp6j5HJ-Cok", "https://www.youtube.com/watch?v=lzQ8GDBA8Is", "https://www.youtube.com/watch?v=Jt0mg8Z09SY", "https://www.youtube.com/watch?v=I6JZW7zMDfY", "https://www.youtube.com/watch?v=V2u-6XkB9O4", "https://www.youtube.com/watch?v=-ziSLGVQOSg", "https://www.youtube.com/watch?v=XFuAeGdUXQE", "https://www.youtube.com/watch?v=kHmoO_a4dDw", "https://www.youtube.com/watch?v=5XXe_5k_kno", "https://www.youtube.com/watch?v=Rk6YDzmqZ0I", "https://www.youtube.com/watch?v=5MgRt8zdr1I", "https://www.youtube.com/watch?v=50blPXs_F94", "https://www.youtube.com/watch?v=UrGLNtZ0rEg", "https://www.youtube.com/watch?v=atCwKBeq76w", "https://www.youtube.com/watch?v=QdfRZXsqDvc", "https://www.youtube.com/watch?v=lXgzQQ5XsHc", "https://www.youtube.com/watch?v=MAGoqMZRLB4", "https://www.youtube.com/watch?v=T1Ond-OwgU8", "https://www.youtube.com/watch?v=J-gkchrZIOU", "https://www.youtube.com/watch?v=3jrIK7YB0tE", "https://www.youtube.com/watch?v=RFxRTLmtsbE", "https://www.youtube.com/watch?v=0XSaKQlBZuE", "https://www.youtube.com/watch?v=cN-nfmrbvno", "https://www.youtube.com/watch?v=cUWyODR1_sA", "https://www.youtube.com/watch?v=uZ1a6hqxyJo", "https://www.youtube.com/watch?v=_sRkoZ-rbys", "https://www.youtube.com/watch?v=wdEibF6PXKY", "https://www.youtube.com/watch?v=KssCCe6KWcg", "https://www.youtube.com/watch?v=j3e_y9Bc7hs", "https://www.youtube.com/watch?v=QaP2vOdltP0", "https://www.youtube.com/watch?v=-n4kcvGS_Lk", "https://www.youtube.com/watch?v=e65ofKU6X6A", "https://www.youtube.com/watch?v=RDQsAvmPuT8", "https://www.youtube.com/watch?v=AFFaEgk-zeg", "https://www.youtube.com/watch?v=6aEx2xL37lw", "https://www.youtube.com/watch?v=H2GxBxeQGqA", "https://www.youtube.com/watch?v=Q_eE0NPArEY", "https://www.youtube.com/watch?v=WR8sxX0GoFo", "https://www.youtube.com/watch?v=Z_oIZzvSxeE", "https://www.youtube.com/watch?v=xL4oPjTACPo", "https://www.youtube.com/watch?v=aIz1cPfTRW4", "https://www.youtube.com/watch?v=DHG5-GxI_Es", "https://www.youtube.com/watch?v=VdqL8nbNbKg", "https://www.youtube.com/watch?v=mc7oGWgeA8s", "https://www.youtube.com/watch?v=clBEj47wjJM", "https://www.youtube.com/watch?v=Dsagy_qrjwc"], "author": "0"}
|
||||
@@ -1 +0,0 @@
|
||||
{"playlist": ["https://www.youtube.com/watch?v=fo-U2DVLt-I", "https://www.youtube.com/watch?v=2G5MPJ58yiM", "https://www.youtube.com/watch?v=-bQpAmqrUZ0", "https://www.youtube.com/watch?v=0I-zlOQFbJQ", "https://www.youtube.com/watch?v=4vcq3-CvUQo", "https://www.youtube.com/watch?v=0I-zlOQFbJQ", "https://www.youtube.com/watch?v=-bQpAmqrUZ0", "https://www.youtube.com/watch?v=2G5MPJ58yiM", "https://www.youtube.com/watch?v=fo-U2DVLt-I", "https://www.youtube.com/watch?v=gdOZ9TEeMT4", "https://www.youtube.com/watch?v=lxWeR2f_15Q", "https://www.youtube.com/watch?v=Kk9xQDYWtMo", "https://www.youtube.com/watch?v=SdKB8CT9eIM", "https://www.youtube.com/watch?v=HmyYe6P3zSk", "https://www.youtube.com/watch?v=CvCoE9Z_fy0", "https://www.youtube.com/watch?v=8vfbUXa7cF4", "https://www.youtube.com/watch?v=___m8qk9rKA", "https://www.youtube.com/watch?v=mu_37H-n_Nc", "https://www.youtube.com/watch?v=UCmiwCWqRYY", "https://www.youtube.com/watch?v=fyEJJkVDAAk"], "author": "0"}
|
||||
@@ -1 +0,0 @@
|
||||
{"playlist": ["https://www.youtube.com/watch?v=sRa1i1_K_-c", "https://www.youtube.com/watch?v=JHSyrs66vpk", "https://www.youtube.com/watch?v=Q-XPOwMztEA", "https://www.youtube.com/watch?v=VHufKcnlvzI", "https://www.youtube.com/watch?v=XINoGyLIkcE", "https://www.youtube.com/watch?v=wJkrgJI_7WY", "https://www.youtube.com/watch?v=CyJY5CFa1CE", "https://www.youtube.com/watch?v=DRKG19-hAlc", "https://www.youtube.com/watch?v=HJABO6w0EyA", "https://www.youtube.com/watch?v=r0noyvMPXpc", "https://www.youtube.com/watch?v=CYTEy3s-QRI", "https://www.youtube.com/watch?v=UJ6xBHmsGkk", "https://www.youtube.com/watch?v=RXfzu32HEOY", "https://www.youtube.com/watch?v=i7Yrtto5d_4", "https://www.youtube.com/watch?v=gIS593evoyU", "https://www.youtube.com/watch?v=9ztnSmWIDA0", "https://www.youtube.com/watch?v=nLP4ScjE1Wo", "https://www.youtube.com/watch?v=X5iiToqvBZ4"], "author": "0"}
|
||||
@@ -1 +0,0 @@
|
||||
{"playlist": ["https://www.youtube.com/watch?v=ezhFoRFTO1c&index=1&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=nznS-Tx2_ak&index=2&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=Op9IpbjV4yA&index=3&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=oHubvkHp5fc&index=4&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=9rN67kPp5tQ&index=5&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=3CCzW49z0hI&index=6&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=Z7GWyasxb5E&index=7&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=2Mahk4wS0XA&index=8&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=QaLF7Cqy-uA&index=9&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=H027APFs8vc&index=10&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=-jus1FrPILs&index=11&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=EAinJ8fVGGU&index=12&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=2H94C-MGM4M&index=13&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=raE7uP2L1Vo&index=14&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=nCyh83oprvU&index=15&list=PLA5F145C2D3E4A298"], "author": "0"}
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
{"playlist": ["https://www.youtube.com/watch?v=gziaF9VT2D4", "https://www.youtube.com/watch?v=7Okz5qov7Go", "https://www.youtube.com/watch?v=olmgSyTtiwI", "https://www.youtube.com/watch?v=tQFMDOQXW30", "https://www.youtube.com/watch?v=Q4lN5HRjWCQ", "https://www.youtube.com/watch?v=UMlnE9QWma0", "https://www.youtube.com/watch?v=ix6V-l-ro1o", "https://www.youtube.com/watch?v=PdjYXcQPbig", "https://www.youtube.com/watch?v=e9mcNVTpovE", "https://www.youtube.com/watch?v=v3bAw8G-qQ4", "https://www.youtube.com/watch?v=WczTbnB0_lE", "https://www.youtube.com/watch?v=e05sBkIz2h0", "https://www.youtube.com/watch?v=fklAh1ncxng", "https://www.youtube.com/watch?v=t6Xwj1lVZFc", "https://www.youtube.com/watch?v=0IfjbF8aY4o", "https://www.youtube.com/watch?v=sLZ7RCxMCO4"], "author": "0"}
|
||||
@@ -1 +0,0 @@
|
||||
{"playlist": ["https://www.youtube.com/watch?v=_XDlWepXuaM", "https://www.youtube.com/watch?v=lJUq8jzU0CA", "https://www.youtube.com/watch?v=OD4hSJybyCY", "https://www.youtube.com/watch?v=g2GVOqG5jWs", "https://www.youtube.com/watch?v=kgOkwV5xX8w", "https://www.youtube.com/watch?v=r6g2Iz3vzgY", "https://www.youtube.com/watch?v=pPArO-OI_3U", "https://www.youtube.com/watch?v=VcLk3fQ3Zwg", "https://www.youtube.com/watch?v=8gJv_NdTyZ0", "https://www.youtube.com/watch?v=z1GJMJbZybQ", "https://www.youtube.com/watch?v=1Qye2uNicbY", "https://www.youtube.com/watch?v=9lrWx7-PiUM", "https://www.youtube.com/watch?v=DVzUAqbAaaw", "https://www.youtube.com/watch?v=ojwkRSGXkn8", "https://www.youtube.com/watch?v=gX89Y7AgoXw", "https://www.youtube.com/watch?v=Nz30L9NYFf8", "https://www.youtube.com/watch?v=DMjBnLN2_ME", "https://www.youtube.com/watch?v=58MZ8ECtPTw", "https://www.youtube.com/watch?v=hvN3zMPn4fk", "https://www.youtube.com/watch?v=Op8T7MltzbU", "https://www.youtube.com/watch?v=Kp9hIeC828o", "https://www.youtube.com/watch?v=eP9nD0TsqEI", "https://www.youtube.com/watch?v=7jKA8bKfIic", "https://www.youtube.com/watch?v=6OkQiVWIp_E", "https://www.youtube.com/watch?v=PemXuiZ0iAc", "https://www.youtube.com/watch?v=hXTT8ZkwJ_o", "https://www.youtube.com/watch?v=8dO4mV7fuhU", "https://www.youtube.com/watch?v=5K7Q409AWKk", "https://www.youtube.com/watch?v=Lqre-N_28Yo", "https://www.youtube.com/watch?v=1DD_NCM_RJs"], "author": "0"}
|
||||
@@ -1 +0,0 @@
|
||||
{"author": "0", "playlist": ["https://www.youtube.com/watch?v=cvaIgq5j2Q8", "https://www.youtube.com/watch?v=Q69_lnD6GhE", "https://www.youtube.com/watch?v=TEsJW9KXuOc", "https://www.youtube.com/watch?v=McfkDbjfllo", "https://www.youtube.com/watch?v=lN3psvKJNvQ", "https://www.youtube.com/watch?v=bOpLs6qfYoI", "https://www.youtube.com/watch?v=cd8e2ECUHL4", "https://www.youtube.com/watch?v=7DVGCs6kWmc", "https://www.youtube.com/watch?v=pUyjKFclkCY", "https://www.youtube.com/watch?v=G75WApUdYJ4", "https://www.youtube.com/watch?v=oSMCZ0Y1nUE", "https://www.youtube.com/watch?v=K8qLdz9GT-0", "https://www.youtube.com/watch?v=QYKFwX1l4Rw", "https://www.youtube.com/watch?v=GmbpUKp6J6M", "https://www.youtube.com/watch?v=FLzIEKz8F20", "https://www.youtube.com/watch?v=NSZFKDOs-yc", "https://www.youtube.com/watch?v=mdML5WPEhEY", "https://www.youtube.com/watch?v=gRdgASty-1g", "https://www.youtube.com/watch?v=zcI8_rLWk3g", "https://www.youtube.com/watch?v=rRh_d2qjavQ", "https://www.youtube.com/watch?v=afJnOSqbP8k", "https://www.youtube.com/watch?v=6xYaoyr0D6E", "https://www.youtube.com/watch?v=oV2lyc5UKXc", "https://www.youtube.com/watch?v=fzB-oRQiI-s", "https://www.youtube.com/watch?v=jSEnYAPEOEQ", "https://www.youtube.com/watch?v=AGWGmkouZxs", "https://www.youtube.com/watch?v=SByfHj_cBQ4", "https://www.youtube.com/watch?v=UQFrKtIFqd8", "https://www.youtube.com/watch?v=HYm3xJabxHw", "https://www.youtube.com/watch?v=mz3h93cH3Zo", "https://www.youtube.com/watch?v=cXWTFV8Z-i0", "https://www.youtube.com/watch?v=oedmZoHjlHE", "https://www.youtube.com/watch?v=x9WpVoAC3tk", "https://www.youtube.com/watch?v=SOg73IfyoFw", "https://www.youtube.com/watch?v=RAO1kWJdYz8", "https://www.youtube.com/watch?v=xkIytYlDD_o", "https://www.youtube.com/watch?v=c0mX-5q3mrY", "https://www.youtube.com/watch?v=OQktBoamgXc", "https://www.youtube.com/watch?v=7RGTFmF-brI", "https://www.youtube.com/watch?v=h2XTsWgN0CU", "https://www.youtube.com/watch?v=2yhhK_2HZzQ", "https://www.youtube.com/watch?v=jx5oOXZOiWc", "https://www.youtube.com/watch?v=Xh8uiKbT9_E", "https://www.youtube.com/watch?v=ksme1nbbTAc", "https://www.youtube.com/watch?v=cSpnJjM1H24", "https://www.youtube.com/watch?v=6_svEzbs15w", "https://www.youtube.com/watch?v=gbOuRQNwtN4", "https://www.youtube.com/watch?v=EWQpFKhEEgI", "https://www.youtube.com/watch?v=GpOv05A1nf0", "https://www.youtube.com/watch?v=cyW2ajAVyfA", "https://www.youtube.com/watch?v=R7IJC6nMons", "https://www.youtube.com/watch?v=bYlUbG01-wA", "https://www.youtube.com/watch?v=vu5Q5Fox2ng", "https://www.youtube.com/watch?v=9buluPWlkAA", "https://www.youtube.com/watch?v=hDNcUGd88Qo", "https://www.youtube.com/watch?v=w77inmTq04E", "https://www.youtube.com/watch?v=VUoH08wbZ9E", "https://www.youtube.com/watch?v=YxqwOq2hA-k", "https://www.youtube.com/watch?v=G8Gb1cwLO3s", "https://www.youtube.com/watch?v=EjoDnuoSDkg", "https://www.youtube.com/watch?v=lfwVMlBRlDY", "https://www.youtube.com/watch?v=bYDxqf2zR2Y", "https://www.youtube.com/watch?v=qbKz5nov1KU", "https://www.youtube.com/watch?v=ZMKWC3Hi8p0", "https://www.youtube.com/watch?v=wyNc0WtHw6I", "https://www.youtube.com/watch?v=19hhHW9C4FA", "https://www.youtube.com/watch?v=pUKmdDaYhL8", "https://www.youtube.com/watch?v=pkyLAWX5V30", "https://www.youtube.com/watch?v=oY1iMtBExOo", "https://www.youtube.com/watch?v=4ugZ7NMiW50", "https://www.youtube.com/watch?v=EPElX0cjm-w", "https://www.youtube.com/watch?v=535ONQFgu2M", "https://www.youtube.com/watch?v=O6NvsM49N6w", "https://www.youtube.com/watch?v=McRA3CKvJZ4", "https://www.youtube.com/watch?v=2pKAcywkr0s", "https://www.youtube.com/watch?v=OFDB9SV6ug8", "https://www.youtube.com/watch?v=tyaPqW0bO5M", "https://www.youtube.com/watch?v=eprDsre1tQo", "https://www.youtube.com/watch?v=vQMSdPgAj6Q", "https://www.youtube.com/watch?v=Tvj2Q--JMhA", "https://www.youtube.com/watch?v=b8cOZ6iJ5PY", "https://www.youtube.com/watch?v=-1-DE0lDATQ", "https://www.youtube.com/watch?v=wL-2Cu6zSNk", "https://www.youtube.com/watch?v=vjd5ndxjt-8", "https://www.youtube.com/watch?v=YTpgmqlX_OA", "https://www.youtube.com/watch?v=eUEtFvjrqMg", "https://www.youtube.com/watch?v=1zn-5YVG3Sw", "https://www.youtube.com/watch?v=oMuvGDUgLfw", "https://www.youtube.com/watch?v=bbDY5bRcZrw", "https://www.youtube.com/watch?v=-jcsoAO83X0", "https://www.youtube.com/watch?v=fU_Vm5dVHgc", "https://www.youtube.com/watch?v=-yShvzoWrsA", "https://www.youtube.com/watch?v=uI4Aj-KbhcY", "https://www.youtube.com/watch?v=TU-5jJnK_7o", "https://www.youtube.com/watch?v=rnP8JZkmN68", "https://www.youtube.com/watch?v=yOMkGjp_m1Q", "https://www.youtube.com/watch?v=NOgZ-XNOHhU", "https://www.youtube.com/watch?v=A2qJNZklnuQ", "https://www.youtube.com/watch?v=F0GcEI-R9mM", "https://www.youtube.com/watch?v=cON1VmHX1jE"]}
|
||||
@@ -1 +0,0 @@
|
||||
{"playlist": ["https://www.youtube.com/watch?v=nU263Ud3LM4", "https://www.youtube.com/watch?v=m1KVDI7vbEM", "https://www.youtube.com/watch?v=D0j9AOEhzO8", "https://www.youtube.com/watch?v=pjGgfZ8JkyA", "https://www.youtube.com/watch?v=PK1yjBgxgho", "https://www.youtube.com/watch?v=eQdQ3ngu0n8", "https://www.youtube.com/watch?v=jFEOKz9-Xv8", "https://www.youtube.com/watch?v=rxqHQ9nOZcc", "https://www.youtube.com/watch?v=opXXFAl8lkY", "https://www.youtube.com/watch?v=mo_CY0HcIws", "https://www.youtube.com/watch?v=m1ud5-glY6M", "https://www.youtube.com/watch?v=fzcCjDb65QI", "https://www.youtube.com/watch?v=fbcjFvXGXYQ", "https://www.youtube.com/watch?v=TWrq8rY47Oo", "https://www.youtube.com/watch?v=9_H9rnqeDDU", "https://www.youtube.com/watch?v=jHxPVXfMjk4", "https://www.youtube.com/watch?v=gOg1sj1abyw", "https://www.youtube.com/watch?v=kFNHlJ6yvEA", "https://www.youtube.com/watch?v=JWsLm7mND1k", "https://www.youtube.com/watch?v=JbCtVIDMEAs", "https://www.youtube.com/watch?v=j2qWM1cnLrg", "https://www.youtube.com/watch?v=XLuSY7jTBxg", "https://www.youtube.com/watch?v=X7gHzu7SBlw", "https://www.youtube.com/watch?v=aP0m-PJozWo", "https://www.youtube.com/watch?v=4MNAktk9ei8", "https://www.youtube.com/watch?v=2XjouKSkSeM", "https://www.youtube.com/watch?v=0d1ZdB_f8h4", "https://www.youtube.com/watch?v=7Wmk58-o_r8", "https://www.youtube.com/watch?v=S1-VyHIx_SY", "https://www.youtube.com/watch?v=YZdy9-4KiEo", "https://www.youtube.com/watch?v=OuSzXP-Hj_A", "https://www.youtube.com/watch?v=epwA8VIbEFo", "https://www.youtube.com/watch?v=JuqZTPyzHfg", "https://www.youtube.com/watch?v=2YodHq4iZFc", "https://www.youtube.com/watch?v=_a3hoWJDXSs", "https://www.youtube.com/watch?v=-1KBQTGSDFA", "https://www.youtube.com/watch?v=4P4b_YTNC7c", "https://www.youtube.com/watch?v=AOZL3kkCUBQ", "https://www.youtube.com/watch?v=ul-brw07gJo", "https://www.youtube.com/watch?v=pEsQi6GRwhM", "https://www.youtube.com/watch?v=SWZvaWzdgek", "https://www.youtube.com/watch?v=HA9Ws-_iCEw", "https://www.youtube.com/watch?v=zUfJaqFV0hk", "https://www.youtube.com/watch?v=vdSA6waSFs8", "https://www.youtube.com/watch?v=g76W944CXzo", "https://www.youtube.com/watch?v=HwpJnvadoIQ", "https://www.youtube.com/watch?v=2Hw597sv7ZM", "https://www.youtube.com/watch?v=9ts_foHlT_w", "https://www.youtube.com/watch?v=B4u0FAJIvwg", "https://www.youtube.com/watch?v=3A_pI3UuMn8", "https://www.youtube.com/watch?v=AZl1LFtUQNA", "https://www.youtube.com/watch?v=ERy3UlFxFoc", "https://www.youtube.com/watch?v=txzD9iHBu-w", "https://www.youtube.com/watch?v=eaK564p5ksc", "https://www.youtube.com/watch?v=H9bDN_aZvNI", "https://www.youtube.com/watch?v=Gv9jl_vGb-w", "https://www.youtube.com/watch?v=xLD4J-qYf8k", "https://www.youtube.com/watch?v=h9SFxVFKZw0", "https://www.youtube.com/watch?v=txzD9iHBu-w", "https://www.youtube.com/watch?v=eaK564p5ksc", "https://www.youtube.com/watch?v=H9bDN_aZvNI", "https://www.youtube.com/watch?v=Gv9jl_vGb-w", "https://www.youtube.com/watch?v=xLD4J-qYf8k", "https://www.youtube.com/watch?v=h9SFxVFKZw0", "https://www.youtube.com/watch?v=exG220Mur04"], "author": "0"}
|
||||
@@ -1 +0,0 @@
|
||||
{"playlist": ["https://www.youtube.com/watch?v=pfAuWjCXwnw", "https://www.youtube.com/watch?v=ToLBU-zJ2S0", "https://www.youtube.com/watch?v=Z-7OySB0Yb4", "https://www.youtube.com/watch?v=91jSk2G6Dr0", "https://www.youtube.com/watch?v=pbTgi_gLppQ", "https://www.youtube.com/watch?v=8keRZa7hAqM", "https://www.youtube.com/watch?v=XfHdXHqWZyE", "https://www.youtube.com/watch?v=NkYxsnWj8Ds", "https://www.youtube.com/watch?v=XSGxYnnwcLg", "https://www.youtube.com/watch?v=ieTtWb7oHIo", "https://www.youtube.com/watch?v=y2F1BL_p5jk", "https://www.youtube.com/watch?v=Waf_AcAfPWA", "https://www.youtube.com/watch?v=dcx3mzLySew", "https://www.youtube.com/watch?v=-VruEefJAHI", "https://www.youtube.com/watch?v=EUxNv_9Zxns", "https://www.youtube.com/watch?v=C3yP_-lOhzA", "https://www.youtube.com/watch?v=cpjh4_ReUCw", "https://www.youtube.com/watch?v=urmoWFQw4aE", "https://www.youtube.com/watch?v=TAzxVL-xWww", "https://www.youtube.com/watch?v=zve5kLOjITU", "https://www.youtube.com/watch?v=2QceNDYmbAo", "https://www.youtube.com/watch?v=DV8zA27UdVU", "https://www.youtube.com/watch?v=uPQMYfXLpKo"], "author": "0"}
|
||||
@@ -1 +0,0 @@
|
||||
{"playlist": ["https://www.youtube.com/watch?v=lG5aSZBAuPs", "https://www.youtube.com/watch?v=uf9WLPZK2AU", "https://www.youtube.com/watch?v=PMd9eYXT0mM", "https://www.youtube.com/watch?v=J3JNlHQ-hj8", "https://www.youtube.com/watch?v=d8Q5kzUlim8", "https://www.youtube.com/watch?v=6sQCATXFzsI", "https://www.youtube.com/watch?v=KrxJQAYdfXo", "https://www.youtube.com/watch?v=V18pa_VDw3I", "https://www.youtube.com/watch?v=h4dzCbjtyW8", "https://www.youtube.com/watch?v=Z_8zEMF3EaY", "https://www.youtube.com/watch?v=ODkX3x1SDHo", "https://www.youtube.com/watch?v=yV2Z62mSoOA", "https://www.youtube.com/watch?v=LgE7gqts_Kg", "https://www.youtube.com/watch?v=EizM69vZebg", "https://www.youtube.com/watch?v=fhOjNhRZ1Gc", "https://www.youtube.com/watch?v=ITjX9IOJdLA"], "author": "0"}
|
||||
-551
@@ -1,551 +0,0 @@
|
||||
A bird in the hand is worth two in the bush
|
||||
A chain is only as strong as its weakest link
|
||||
A change is as good as a rest
|
||||
A drowning man will clutch at a straw.
|
||||
A fair day's work for a fair day's pay
|
||||
A fool and his money are soon parted
|
||||
A friend in need is a friend indeed
|
||||
A golden key can open any door
|
||||
A good beginning makes a good ending.
|
||||
A good man is hard to find
|
||||
A house divided against itself cannot stand
|
||||
A house is not a home
|
||||
A journey of a thousand miles begins with a single step
|
||||
A leopard cannot change its spots
|
||||
A little knowledge is a dangerous thing
|
||||
A little of what you fancy does you good
|
||||
A man who is his own lawyer has a fool for his client
|
||||
A man with a hammer sees every problem as a nail
|
||||
A miss is as good as a mile
|
||||
A new broom sweeps clean, but an old one knows where the dirt is.
|
||||
A nod is as good as a wink to a blind horse
|
||||
A penny saved is a penny earned
|
||||
A person is known by the company he keeps
|
||||
A picture is worth a thousand words
|
||||
A place for everything and everything in its place
|
||||
A poor workman always blames his tools
|
||||
A problem shared is a problem halved
|
||||
A prophet is not recognized in his own land
|
||||
A rising tide lifts all boats
|
||||
A rolling stone gathers no moss
|
||||
A soft answer turneth away wrath
|
||||
A stitch in time saves nine
|
||||
A swarm in May is worth a load of hay; a swarm in June is worth a silver spoon; but a swarm in July is not worth a fly.
|
||||
A thing of beauty is a joy forever
|
||||
A trouble shared is a trouble halved
|
||||
A volunteer is worth twenty pressed men
|
||||
A watched pot never boils
|
||||
A woman's place is in the home
|
||||
A man works from sun to sun but a woman's work is never done,
|
||||
A word to the wise is enough,
|
||||
Absence makes the heart grow fonder
|
||||
Absolute power corrupts absolutely.
|
||||
Accidents will happen (in the best-regulated families)
|
||||
Actions speak louder than words.
|
||||
Adversity makes strange bedfellows
|
||||
All good things come to he who waits
|
||||
All good things must come to an end,
|
||||
All is grist that comes to the mill
|
||||
All roads lead to Rome,
|
||||
All that glitters is not gold,
|
||||
All the world loves a lover
|
||||
All things come to those who wait
|
||||
All things must pass
|
||||
All work and no play makes Jack a dull boy,
|
||||
All you need is love
|
||||
All is fair in love and war
|
||||
All is for the best in the best of all possible worlds
|
||||
All is well that ends well
|
||||
An apple a day keeps the doctor away
|
||||
An army marches on its stomach.
|
||||
An Englishman's home is his castle
|
||||
Another day, another dollar.
|
||||
An ounce of prevention is worth a pound of cure
|
||||
Any port in a storm,
|
||||
Any publicity is good publicity
|
||||
April showers bring forth May flowers,
|
||||
As you make your bed, so you must lie upon it
|
||||
As you sow so shall you reap
|
||||
Ask a silly question and you will get a silly answer
|
||||
Ask my companion if I be a thief
|
||||
Ask no questions and hear no lies
|
||||
Attack is the best form of defense
|
||||
Bad news travels fast
|
||||
Barking dogs seldom bite,
|
||||
Beauty is in the eye of the beholder
|
||||
Beauty is only skin deep,
|
||||
Beggars should not be choosers,
|
||||
Behind every great man, there is a great woman
|
||||
Better late than never
|
||||
Better safe than sorry
|
||||
Better the Devil you know than the Devil you do not
|
||||
Better to have loved and lost than never to have loved at all
|
||||
Better to light one candle than to curse the darkness
|
||||
Better to remain silent and be thought a fool than to speak and remove all doubt
|
||||
Better wear out than rust out.
|
||||
Beware of Greeks bearing gifts
|
||||
Big fish eat little fish
|
||||
Birds of a feather flock together
|
||||
Blood is thicker than water
|
||||
Boys will be boys
|
||||
Brevity is the soul of wit
|
||||
Business before pleasure
|
||||
Caesar's wife must be above suspicion
|
||||
Careless talk costs lives
|
||||
Charity begins at home
|
||||
Cheats never prosper
|
||||
Children should be seen and not heard
|
||||
Christmas comes but once a year
|
||||
Cleanliness is next to godliness
|
||||
Clothes make the man
|
||||
Cold hands, warm heart
|
||||
Comparisons are odious
|
||||
Count your blessings
|
||||
Courage is the measure of a Man, Beauty is the measure of a Woman
|
||||
Cowards may die many times before their death
|
||||
Crime does not pay
|
||||
Cut your coat according to your cloth,
|
||||
Curiosity killed the cat
|
||||
Dead men tell no tales
|
||||
Devil take the hindmost
|
||||
Discretion is the better part of valour
|
||||
Do as I say, not as I do
|
||||
Do as you would be done by
|
||||
Do unto others as you would have them do unto you
|
||||
Do not bite the hand that feeds you
|
||||
Do not burn your bridges behind you
|
||||
Do not cast your pearls before swine
|
||||
Do not cry over spilt milk
|
||||
Do not change horses in midstream
|
||||
Do not count your chickens before they are hatched
|
||||
Do not cross the bridge till you come to it
|
||||
Do not cut off your nose to spite your face
|
||||
Do not keep a dog and bark yourself
|
||||
Do not let the bastards grind you down
|
||||
Do not look a gift horse in the mouth
|
||||
Do not make a mountain of a mole hill
|
||||
Do not meet troubles half-way
|
||||
Do not put all your eggs in one basket
|
||||
Do not put the cart before the horse
|
||||
Do not put new wine into old bottles
|
||||
Do not rock the boat
|
||||
Do not spoil the ship for a ha'pworth of tar
|
||||
Do not throw pearls to swine
|
||||
Do not teach your Grandmother to suck eggs
|
||||
Do not throw the baby out with the bathwater
|
||||
Do not try to walk before you can crawl
|
||||
Do not upset the apple-cart
|
||||
Do not wash your dirty linen in public
|
||||
Doubt is the beginning, not the end, of wisdom
|
||||
Early to bed and early to rise, makes a man healthy, wealthy and wise
|
||||
East is east, and west is west
|
||||
East, west, home is best,
|
||||
Easy come, easy go
|
||||
Eat breakfast as a king, lunch as a merchant and supper as a beggar
|
||||
Eat, drink and be merry, for tomorrow we die
|
||||
Empty vessels make the most noise
|
||||
Enough is as good as a feast
|
||||
Enough is enough
|
||||
Even a worm will turn
|
||||
Every cloud has a silver lining
|
||||
Every dog has his day
|
||||
Every Jack has his Jill
|
||||
Every little bit helps
|
||||
Every man for himself, and the Devil take the hindmost
|
||||
Every man has his price
|
||||
Every picture tells a story
|
||||
Every stick has two ends
|
||||
Everybody wants to go to heaven but nobody wants to die
|
||||
Everything comes to those who wait
|
||||
Every tide has its ebb
|
||||
Fact is stranger than fiction
|
||||
Failing to plan is planning to fail
|
||||
Faint heart never won fair lady
|
||||
Fair exchange is no robbery
|
||||
Faith will move mountains
|
||||
Familiarity breeds contempt
|
||||
Feed a cold and starve a fever
|
||||
Fight fire with fire
|
||||
Finders keepers, losers weepers
|
||||
First come, first served
|
||||
First impressions are the most lasting
|
||||
First things first
|
||||
Fish always stinks from the head downwards
|
||||
Fish and guests smell after three days
|
||||
Flattery will get you nowhere
|
||||
Fools rush in where angels fear to tread
|
||||
For want of a nail the shoe was lost; for want of a shoe the horse was lost; and for want of a horse the man was lost
|
||||
Forewarned is forearmed
|
||||
Fortune favours the brave
|
||||
Genius is an infinite capacity for taking pains
|
||||
Give a dog a bad name and hang him
|
||||
Give a man a fish and you feed him for a day. Teach a man to fish and you feed him for a lifetime
|
||||
Give a man rope enough and he will hang himself
|
||||
Give credit where credit is due
|
||||
Give him an inch and he will take a mile
|
||||
God helps those who help themselves
|
||||
Good fences make good neighbours
|
||||
Good talk saves the food
|
||||
Good things come to those who wait
|
||||
Great minds think alike
|
||||
Half a loaf is better than no bread
|
||||
Handsome is as handsome does
|
||||
Hard cases make bad law
|
||||
Hard work never did anyone any harm
|
||||
Haste makes waste
|
||||
He that goes a-borrowing, goes a-sorrowing
|
||||
He who can does, he who cannot, teaches
|
||||
He who fights and runs away may live to fight another day
|
||||
He who hesitates is lost
|
||||
He who laughs last laughs best
|
||||
He who lives by the sword shall die by the sword
|
||||
He who loves the world as his body may be entrusted with the empire.
|
||||
He who makes a beast out of himself gets rid of the pain of being a man
|
||||
He who pays the piper calls the tune
|
||||
He who knows does not speak. He who speaks does not know.
|
||||
He who sups with the Devil should have a long spoon
|
||||
Hell hath no fury like a woman scorned
|
||||
Hindsight is always twenty-twenty
|
||||
History repeats itself
|
||||
Home is where the heart is
|
||||
Honesty is the best policy
|
||||
Hope springs eternal
|
||||
Horses for courses
|
||||
Hunger never knows the taste, sleep never knows the comfort
|
||||
If anything can go wrong, it will
|
||||
If a job is worth doing, it is worth doing well
|
||||
If at first you do not succeed, try, try again
|
||||
If God had meant us to fly, he would have given us wings
|
||||
If ifs and ands were pots and pans, there would be no work for tinkers
|
||||
When life gives you lemons, make lemonade
|
||||
If the cap fits, wear it
|
||||
If the mountain will not come to Mohammed, then Mohammed must go to the mountain
|
||||
If we're not back by dawn, call the President.
|
||||
If wealth is lost, nothing is lost. If health is lost, something is lost. If character is lost, everything is lost.
|
||||
If wishes were horses, beggars would ride
|
||||
If you're growing in Age,then you're nearing to the Graveyard
|
||||
If you cannot be good, be careful
|
||||
If you cannot beat them, join them
|
||||
If you cannot stand the heat, get out of the kitchen
|
||||
If you give a mouse a cookie, he'll always ask for a glass of milk
|
||||
If you think that you know everything, then you're a Jack ass
|
||||
If you lie down with dogs, you will get up with fleas
|
||||
If you pay peanuts, you get monkeys
|
||||
If you steal from one author, it is plagiarism; if you steal from many, it is research.
|
||||
If you want a thing done well, do it yourself
|
||||
If you have never seen the bottom of the tree, you cannot know how tall it stands
|
||||
Imitation is the sincerest form of flattery
|
||||
In for a penny, in for a pound
|
||||
In the kingdom of the blind, the one eyed man is king
|
||||
In the midst of life, we are in death
|
||||
Into every life a little rain must fall
|
||||
It goes without saying
|
||||
It is all grist to the mill
|
||||
It is an ill wind that blows no one any good
|
||||
It is best to be on the safe side
|
||||
It is better to give than to receive
|
||||
It is better to have loved and lost than never to have loved at all
|
||||
It is better to cultivate a Land with two Bulls, rather working under Boss who never gives Wage when asked
|
||||
It is better to light a candle than curse the darkness
|
||||
It is better to travel hopefully than to arrive
|
||||
It is easy to be wise after the event
|
||||
It is never too late
|
||||
It is no use crying over spilt milk
|
||||
It is no use locking the stable door after the horse has bolted
|
||||
It is on
|
||||
It is the early bird that gets the worm
|
||||
It is the empty can that makes the most noise
|
||||
It is the squeaky wheel that gets the grease
|
||||
It never rains but it pours
|
||||
It takes a thief to catch a thief
|
||||
It needs a Hundred Lies to cover a Single Lie
|
||||
It takes all sorts to make a world
|
||||
It takes one to know one
|
||||
It takes two to tango
|
||||
I'm going to have to give you the pink slip
|
||||
Jack of all trades, master of none
|
||||
Jack of all trades, master of some
|
||||
Judge not, that ye be not judged.
|
||||
Keep your friends close and your enemies closer.
|
||||
Trust in God and keep your powder dry
|
||||
Kindness in words creates confidence. Kindness in thinking creates profoundness. Kindness in giving creates love.
|
||||
Knowledge is power, guard it well.
|
||||
Laugh before breakfast, cry before supper.
|
||||
Laugh and the world laughs with you, weep and you weep alone
|
||||
Laughter is the best medicine
|
||||
Least said, soonest mended
|
||||
Less is more
|
||||
Let bygones be bygones
|
||||
Let not the sun go down on your wrath
|
||||
Let sleeping dogs lie
|
||||
Let the buyer beware
|
||||
Let the dead bury the dead
|
||||
Let the punishment fit the crime
|
||||
Let well alone
|
||||
Let your hair down.
|
||||
Life begins at forty
|
||||
Life is not all beer and skittles
|
||||
Life is what you make it
|
||||
Lightning never strikes twice in the same place
|
||||
Like father, like son,
|
||||
Little pitchers have big ears
|
||||
Little strokes fell great oaks
|
||||
Little things please little minds
|
||||
Live and let live
|
||||
Live for today, for tomorrow never comes
|
||||
Loose lips, sink ships
|
||||
Look before you leap
|
||||
Love is blind
|
||||
Love of money is the root of all kinds of evil.
|
||||
Love makes the world go around
|
||||
Love will find a way
|
||||
Make hay while the sun shines
|
||||
Make love not war
|
||||
Man does not live by bread alone
|
||||
Manners maketh man
|
||||
Many a little makes a mickle
|
||||
Many a mickle makes a muckle
|
||||
Many a true word is spoken in jest
|
||||
Many hands make light work
|
||||
March comes in like a lion and goes out like a lamb
|
||||
Marriages are made in heaven
|
||||
Marry in haste, repent at leisure
|
||||
Memory is the treasure of the mind
|
||||
Men get spoiled by staying, Women get spoiled by wandering
|
||||
Might is right
|
||||
Might makes right
|
||||
Mighty oaks from little acorns grow
|
||||
Milking the bull
|
||||
Misery loves company
|
||||
Moderation in all things
|
||||
Monday's child is fair of face, Tuesday's child is full of grace, Wednesday's child is full of woe, Thursday's child has far to go, Friday's child is loving and giving, Saturday's child works hard for its living, and a child that is born on the Sabbath day is fair and wise and good and gay.
|
||||
Money does not grow on trees
|
||||
Money earned by deceit, goes by deceit
|
||||
Money is not everything
|
||||
Money makes the world go around
|
||||
Money talks
|
||||
Money makes many things, but also makes devil dance
|
||||
More haste, less speed
|
||||
Music has charms to soothe the savage beast
|
||||
Nature abhors a vacuum,
|
||||
Never reveal a man's wage, and woman's age
|
||||
Necessity is the mother of invention
|
||||
Needs must when the devil drives
|
||||
Never cast a clout until May be out
|
||||
Never give a sucker an even break
|
||||
Never judge a book by its cover
|
||||
Never let the sun go down on your anger
|
||||
Never look a gift horse in the mouth
|
||||
Never put off until tomorrow what you can do today
|
||||
Never speak ill of the dead
|
||||
Never say never
|
||||
Never tell tales out of school
|
||||
Nine tailors make a man,
|
||||
No guts, no glory
|
||||
No man can serve two masters
|
||||
No man is an island
|
||||
No names, no pack-drill
|
||||
No news is good news
|
||||
No one can make you feel inferior without your consent
|
||||
No pain, no gain
|
||||
No rest for the wicked
|
||||
Nothing is certain but death and taxes
|
||||
Nothing succeeds like success,
|
||||
Nothing ventured, nothing gained
|
||||
Once a witch always a witch
|
||||
Oil and water do not mix
|
||||
Old soldiers never die; they just fade away
|
||||
Once a thief, always a thief
|
||||
Once bitten, twice shy
|
||||
One good turn deserves another
|
||||
One half of the world does not know how the other half lives
|
||||
One hand washes the other
|
||||
One man's meat is another man's poison
|
||||
One might as well be hanged for a sheep as a lamb
|
||||
One law for the rich and another for the poor
|
||||
One swallow does not make a summer
|
||||
One who believes in Sword, dies by the Sword
|
||||
One year's seeding makes seven years weeding
|
||||
Only fools and horses work
|
||||
Opportunity never knocks twice at any man's door
|
||||
Out of sight, out of mind
|
||||
Over greedy man, over wrathful woman will never flourish
|
||||
Parsley seed goes nine times to the Devil
|
||||
Patience is a virtue
|
||||
Pearls of wisdom
|
||||
Penny wise and pound foolish
|
||||
People who live in glass houses should not throw stones
|
||||
Physician, heal thyself
|
||||
Possession is nine-tenths of the law
|
||||
Power corrupts; absolute power corrupts absolutely
|
||||
Practice makes perfect
|
||||
Practice what you preach
|
||||
Prevention is better than cure
|
||||
Pride goes before a fall
|
||||
Procrastination is the thief of time
|
||||
Put your best foot forward
|
||||
Put your money where your mouth is
|
||||
Red sky at night shepherds delight; red sky in the morning, shepherds warning
|
||||
Revenge is a dish best served cold
|
||||
Revenge is sweet
|
||||
Rome was not built in a day,
|
||||
Right or wrong, my country
|
||||
See a penny and pick it up, all the day you will have good luck; see a penny and let it lay, bad luck you will have all day
|
||||
See no evil, hear no evil, speak no evil
|
||||
Seeing is believing
|
||||
Seek and ye shall find
|
||||
Set a thief to catch a thief
|
||||
Shiny are the distant hills
|
||||
Shrouds have no pockets
|
||||
Silence is golden
|
||||
Slow and steady wins the race
|
||||
Slow but sure
|
||||
Softly, softly, catchee monkey
|
||||
Sometimes we are the student. Sometimes we are the master. And sometimes we are merely the lesson
|
||||
Spare the rod and spoil the child
|
||||
Speak as you find
|
||||
Speak softly and carry a big stick
|
||||
Speech is silver
|
||||
Sticks and stones may break my bones, but words will never hurt me
|
||||
Still waters run deep
|
||||
Strike while the iron is hot
|
||||
Stupid is as stupid does
|
||||
Success has many fathers, while failure is an orphan
|
||||
Take care of the pennies, and the pounds will take care of themselves
|
||||
Talk is cheap
|
||||
Talk of the Devil, and he is bound to appear
|
||||
Tell me who your friends are, and I'll tell you who you are
|
||||
Tell the truth and shame the Devil
|
||||
That which does not kill us makes us stronger
|
||||
The age of miracles is past
|
||||
The apple never falls far from the tree
|
||||
The best defence is a good offence
|
||||
The best-laid schemes of mice and men often go awry
|
||||
The best things in life are free
|
||||
The bigger they are, the harder they fall
|
||||
The boy is father to the man
|
||||
The bread never falls but on its buttered side
|
||||
The child is the father of the man
|
||||
The cobbler always wears the worst shoes
|
||||
The course of true love never did run smooth
|
||||
The customer is always right
|
||||
The darkest hour is just before the dawn
|
||||
The devil finds work for idle hands
|
||||
The Devil looks after his own
|
||||
The early bird catches the worm
|
||||
The end justifies the means
|
||||
The exception which proves the rule
|
||||
The female of the species is more deadly than the male
|
||||
The good die young
|
||||
The grass is always greener on the other side of the fence
|
||||
The hand that rocks the cradle rules the world
|
||||
The husband is always the last to know
|
||||
The innocent seldom find an uncomfortable pillow.
|
||||
The labourer is worthy of his hire
|
||||
The leopard does not change his spots
|
||||
The longest day must have an end
|
||||
The longest journey starts with a single step
|
||||
The moon is made of green cheese
|
||||
The more the merrier
|
||||
The more things change, the more they stay the same
|
||||
The only way to understand a woman is to love her
|
||||
The pen is mightier than the sword
|
||||
The proof of the pudding is in the eating
|
||||
The road to Hell is paved with good intentions
|
||||
The shoemaker's son always goes barefoot
|
||||
The squeaking wheel gets the grease
|
||||
The straw that broke the camel's back
|
||||
The way to a man's heart is through his stomach
|
||||
There ain't no such thing as a free lunch
|
||||
There are more ways of killing a cat than choking it with cream
|
||||
There are none so blind as those that will not see
|
||||
There are two sides to every question
|
||||
There but for the grace of God go I
|
||||
There is an exception to every rule
|
||||
There are always more fish in the sea
|
||||
There is honour among thieves
|
||||
There is many a good tune played on an old fiddle
|
||||
There is many a slip 'twixt cup and lip
|
||||
There is more than one way to skin a cat
|
||||
There is no accounting for tastes
|
||||
There is no fool like an old fool
|
||||
There is no place like home
|
||||
There is no smoke without fire
|
||||
There is no such thing as a free lunch
|
||||
There is no such thing as bad publicity
|
||||
There is no time like the present
|
||||
There is none so blind as those who will not see
|
||||
There's none so deaf as those who will not hear
|
||||
There is nowt so queer as folk
|
||||
There is one born every minute
|
||||
There is safety in numbers
|
||||
They that sow the wind shall reap the whirlwind
|
||||
Third time is a charm
|
||||
Those who do not learn from history are doomed to repeat it
|
||||
Those who live in glass houses should not throw stones
|
||||
Those who sleep with dogs will rise with fleas
|
||||
Time and tide wait for no man
|
||||
Time flies
|
||||
Time is a great healer
|
||||
Time is money
|
||||
Time will tell
|
||||
’Tis better to have loved and lost than never to have loved at all
|
||||
To be worn out is to be renewed.
|
||||
To each his own.
|
||||
To err is human, to forgive divine
|
||||
To the victor go the spoils
|
||||
To travel hopefully is a better thing than to arrive
|
||||
Tomorrow is another day
|
||||
Tomorrow never comes
|
||||
Too many cooks spoil the broth
|
||||
Truth is stranger than fiction
|
||||
Truth will out
|
||||
Two blacks do not make a white
|
||||
Two heads are better than one
|
||||
Two is company, but three is a crowd
|
||||
Two wrongs do not make a right
|
||||
Variety is the spice of life.
|
||||
Walk softly but carry a big stick.
|
||||
Walnuts and pears you plant for your heirs
|
||||
Waste not, want not
|
||||
What cannot be cured must be endured
|
||||
What goes around, comes around
|
||||
What goes up must come down
|
||||
What you lose on the swings you gain on the roundabouts
|
||||
What is sauce for the goose is sauce for the gander
|
||||
When in Rome, do as the Romans do.
|
||||
When it rains it pours.
|
||||
When the cat is away, the mice will play
|
||||
When the going gets tough, the tough get going
|
||||
When the oak is before the ash, then you will only get a splash; when the ash is before the oak, then you may expect a soak
|
||||
When three women gather, it becomes noisy.
|
||||
What the eye does not see, the heart does not grieve over
|
||||
Where there is a will there is a way
|
||||
Where there is muck there is brass
|
||||
Whether you think you can, or you think you can't, you're right.
|
||||
While there is life there is hope
|
||||
Whom the Gods love die young
|
||||
Why keep a dog and bark yourself?
|
||||
With a responsibility comes great power
|
||||
Woman is the root of both good and evil
|
||||
Wonders will never cease
|
||||
Work expands so as to fill the time available
|
||||
Worrying never did anyone any good
|
||||
You ain't seen nothing yet
|
||||
You are never too old to learn
|
||||
You are what you eat
|
||||
You can have too much of a good thing
|
||||
You can lead a horse to water, but you cannot make it drink
|
||||
You cannot have your cake and eat it too
|
||||
You cannot get blood out of a stone
|
||||
You cannot make a silk purse from a sow's ear
|
||||
You cannot make an omelette without breaking eggs
|
||||
You cannot make bricks without straw
|
||||
You cannot run with the hare and hunt with the hounds
|
||||
You cannot teach an old dog new tricks
|
||||
You cannot judge a book by its cover
|
||||
You cannot win them all
|
||||
You catch more flies with honey than with vinegar
|
||||
You pay your money and you take your choice
|
||||
Youth is wasted on the young
|
||||
You must have rocks in your head
|
||||
@@ -0,0 +1,34 @@
|
||||
import sys
|
||||
import warnings
|
||||
import discord
|
||||
import colorama
|
||||
|
||||
# Let's do all the dumb version checking in one place.
|
||||
if sys.platform == "win32":
|
||||
# Due to issues with ProactorEventLoop prior to 3.6.6 (bpo-26819)
|
||||
MIN_PYTHON_VERSION = (3, 6, 6)
|
||||
else:
|
||||
MIN_PYTHON_VERSION = (3, 6, 2)
|
||||
|
||||
if sys.version_info < MIN_PYTHON_VERSION:
|
||||
print(
|
||||
f"Python {'.'.join(map(str, MIN_PYTHON_VERSION))} is required to run Red, but you have "
|
||||
f"{sys.version}! Please update Python."
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
if discord.version_info.major < 1:
|
||||
print(
|
||||
"You are not running the rewritten version of discord.py.\n\n"
|
||||
"In order to use Red V3 you MUST be running d.py version "
|
||||
"1.0.0 or greater."
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
colorama.init()
|
||||
|
||||
# Filter fuzzywuzzy slow sequence matcher warning
|
||||
warnings.filterwarnings("ignore", module=r"fuzzywuzzy.*")
|
||||
# Prevent discord PyNaCl missing warning
|
||||
discord.voice_client.VoiceClient.warn_nacl = False
|
||||
@@ -0,0 +1,194 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Discord Version check
|
||||
|
||||
import sys
|
||||
import discord
|
||||
from redbot.core.bot import Red, ExitCodes
|
||||
from redbot.core.cog_manager import CogManagerUI
|
||||
from redbot.core.data_manager import create_temp_config, load_basic_configuration, config_file
|
||||
from redbot.core.json_io import JsonIO
|
||||
from redbot.core.global_checks import init_global_checks
|
||||
from redbot.core.events import init_events
|
||||
from redbot.core.cli import interactive_config, confirm, parse_cli_flags, ask_sentry
|
||||
from redbot.core.core_commands import Core
|
||||
from redbot.core.dev_commands import Dev
|
||||
from redbot.core import __version__
|
||||
import asyncio
|
||||
import logging.handlers
|
||||
import logging
|
||||
import os
|
||||
|
||||
# Let's not force this dependency, uvloop is much faster on cpython
|
||||
if sys.implementation.name == "cpython":
|
||||
try:
|
||||
import uvloop
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
|
||||
|
||||
if sys.platform == "win32":
|
||||
asyncio.set_event_loop(asyncio.ProactorEventLoop())
|
||||
|
||||
|
||||
#
|
||||
# Red - Discord Bot v3
|
||||
#
|
||||
# Made by Twentysix, improved by many
|
||||
#
|
||||
|
||||
|
||||
def init_loggers(cli_flags):
|
||||
# d.py stuff
|
||||
dpy_logger = logging.getLogger("discord")
|
||||
dpy_logger.setLevel(logging.WARNING)
|
||||
console = logging.StreamHandler()
|
||||
console.setLevel(logging.WARNING)
|
||||
dpy_logger.addHandler(console)
|
||||
|
||||
# Red stuff
|
||||
|
||||
logger = logging.getLogger("red")
|
||||
|
||||
red_format = logging.Formatter(
|
||||
"%(asctime)s %(levelname)s %(module)s %(funcName)s %(lineno)d: %(message)s",
|
||||
datefmt="[%d/%m/%Y %H:%M]",
|
||||
)
|
||||
|
||||
stdout_handler = logging.StreamHandler(sys.stdout)
|
||||
stdout_handler.setFormatter(red_format)
|
||||
|
||||
if cli_flags.debug:
|
||||
os.environ["PYTHONASYNCIODEBUG"] = "1"
|
||||
logger.setLevel(logging.DEBUG)
|
||||
else:
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
from redbot.core.data_manager import core_data_path
|
||||
|
||||
logfile_path = core_data_path() / "red.log"
|
||||
fhandler = logging.handlers.RotatingFileHandler(
|
||||
filename=str(logfile_path), encoding="utf-8", mode="a", maxBytes=10 ** 7, backupCount=5
|
||||
)
|
||||
fhandler.setFormatter(red_format)
|
||||
|
||||
logger.addHandler(fhandler)
|
||||
logger.addHandler(stdout_handler)
|
||||
|
||||
# Sentry stuff
|
||||
sentry_logger = logging.getLogger("red.sentry")
|
||||
sentry_logger.setLevel(logging.WARNING)
|
||||
|
||||
return logger, sentry_logger
|
||||
|
||||
|
||||
async def _get_prefix_and_token(red, indict):
|
||||
"""
|
||||
Again, please blame <@269933075037814786> for this.
|
||||
:param indict:
|
||||
:return:
|
||||
"""
|
||||
indict["token"] = await red.db.token()
|
||||
indict["prefix"] = await red.db.prefix()
|
||||
indict["enable_sentry"] = await red.db.enable_sentry()
|
||||
|
||||
|
||||
def list_instances():
|
||||
if not config_file.exists():
|
||||
print(
|
||||
"No instances have been configured! Configure one "
|
||||
"using `redbot-setup` before trying to run the bot!"
|
||||
)
|
||||
sys.exit(1)
|
||||
else:
|
||||
data = JsonIO(config_file)._load_json()
|
||||
text = "Configured Instances:\n\n"
|
||||
for instance_name in sorted(data.keys()):
|
||||
text += "{}\n".format(instance_name)
|
||||
print(text)
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def main():
|
||||
description = "Red - Version {}".format(__version__)
|
||||
cli_flags = parse_cli_flags(sys.argv[1:])
|
||||
if cli_flags.list_instances:
|
||||
list_instances()
|
||||
elif cli_flags.version:
|
||||
print(description)
|
||||
sys.exit(0)
|
||||
elif not cli_flags.instance_name and not cli_flags.no_instance:
|
||||
print("Error: No instance name was provided!")
|
||||
sys.exit(1)
|
||||
if cli_flags.no_instance:
|
||||
print(
|
||||
"\033[1m"
|
||||
"Warning: The data will be placed in a temporary folder and removed on next system reboot."
|
||||
"\033[0m"
|
||||
)
|
||||
cli_flags.instance_name = "temporary_red"
|
||||
create_temp_config()
|
||||
load_basic_configuration(cli_flags.instance_name)
|
||||
log, sentry_log = init_loggers(cli_flags)
|
||||
red = Red(cli_flags=cli_flags, description=description, pm_help=None)
|
||||
init_global_checks(red)
|
||||
init_events(red, cli_flags)
|
||||
red.add_cog(Core(red))
|
||||
red.add_cog(CogManagerUI())
|
||||
if cli_flags.dev:
|
||||
red.add_cog(Dev())
|
||||
loop = asyncio.get_event_loop()
|
||||
tmp_data = {}
|
||||
loop.run_until_complete(_get_prefix_and_token(red, tmp_data))
|
||||
token = os.environ.get("RED_TOKEN", tmp_data["token"])
|
||||
if cli_flags.token:
|
||||
token = cli_flags.token
|
||||
prefix = cli_flags.prefix or tmp_data["prefix"]
|
||||
if not (token and prefix):
|
||||
if cli_flags.no_prompt is False:
|
||||
new_token = interactive_config(red, token_set=bool(token), prefix_set=bool(prefix))
|
||||
if new_token:
|
||||
token = new_token
|
||||
else:
|
||||
log.critical("Token and prefix must be set in order to login.")
|
||||
sys.exit(1)
|
||||
loop.run_until_complete(_get_prefix_and_token(red, tmp_data))
|
||||
|
||||
if cli_flags.dry_run:
|
||||
loop.run_until_complete(red.http.close())
|
||||
sys.exit(0)
|
||||
if tmp_data["enable_sentry"]:
|
||||
red.enable_sentry()
|
||||
try:
|
||||
loop.run_until_complete(red.start(token, bot=True))
|
||||
except discord.LoginFailure:
|
||||
log.critical("This token doesn't seem to be valid.")
|
||||
db_token = loop.run_until_complete(red.db.token())
|
||||
if db_token and not cli_flags.no_prompt:
|
||||
print("\nDo you want to reset the token? (y/n)")
|
||||
if confirm("> "):
|
||||
loop.run_until_complete(red.db.token.set(""))
|
||||
print("Token has been reset.")
|
||||
except KeyboardInterrupt:
|
||||
log.info("Keyboard interrupt detected. Quitting...")
|
||||
loop.run_until_complete(red.logout())
|
||||
red._shutdown_mode = ExitCodes.SHUTDOWN
|
||||
except Exception as e:
|
||||
log.critical("Fatal exception", exc_info=e)
|
||||
sentry_log.critical("Fatal Exception", exc_info=e)
|
||||
loop.run_until_complete(red.logout())
|
||||
finally:
|
||||
pending = asyncio.Task.all_tasks(loop=red.loop)
|
||||
gathered = asyncio.gather(*pending, loop=red.loop, return_exceptions=True)
|
||||
gathered.cancel()
|
||||
try:
|
||||
red.rpc.server.close()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
sys.exit(red._shutdown_mode.value)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,5 @@
|
||||
from .admin import Admin
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Admin())
|
||||
@@ -0,0 +1,394 @@
|
||||
import logging
|
||||
from typing import Tuple
|
||||
|
||||
import discord
|
||||
|
||||
from redbot.core import Config, checks, commands
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
from redbot.core.utils.chat_formatting import box
|
||||
from .announcer import Announcer
|
||||
from .converters import MemberDefaultAuthor, SelfRole
|
||||
|
||||
log = logging.getLogger("red.admin")
|
||||
|
||||
T_ = Translator("Admin", __file__)
|
||||
|
||||
_ = lambda s: s
|
||||
GENERIC_FORBIDDEN = _(
|
||||
"I attempted to do something that Discord denied me permissions for."
|
||||
" Your command failed to successfully complete."
|
||||
)
|
||||
|
||||
HIERARCHY_ISSUE = _(
|
||||
"I tried to add {role.name} to {member.display_name} but that role"
|
||||
" is higher than my highest role in the Discord hierarchy so I was"
|
||||
" unable to successfully add it. Please give me a higher role and "
|
||||
"try again."
|
||||
)
|
||||
|
||||
USER_HIERARCHY_ISSUE = _(
|
||||
"I tried to add {role.name} to {member.display_name} but that role"
|
||||
" is higher than your highest role in the Discord hierarchy so I was"
|
||||
" unable to successfully add it. Please get a higher role and "
|
||||
"try again."
|
||||
)
|
||||
|
||||
RUNNING_ANNOUNCEMENT = _(
|
||||
"I am already announcing something. If you would like to make a"
|
||||
" different announcement please use `{prefix}announce cancel`"
|
||||
" first."
|
||||
)
|
||||
_ = T_
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class Admin(commands.Cog):
|
||||
"""A collection of server administration utilities."""
|
||||
|
||||
def __init__(self, config=Config):
|
||||
super().__init__()
|
||||
self.conf = config.get_conf(self, 8237492837454039, force_registration=True)
|
||||
|
||||
self.conf.register_global(serverlocked=False)
|
||||
|
||||
self.conf.register_guild(
|
||||
announce_ignore=False,
|
||||
announce_channel=None, # Integer ID
|
||||
selfroles=[], # List of integer ID's
|
||||
)
|
||||
|
||||
self.__current_announcer = None
|
||||
|
||||
def __unload(self):
|
||||
try:
|
||||
self.__current_announcer.cancel()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
async def complain(ctx: commands.Context, message: str, **kwargs):
|
||||
await ctx.send(message.format(**kwargs))
|
||||
|
||||
def is_announcing(self) -> bool:
|
||||
"""
|
||||
Is the bot currently announcing something?
|
||||
:return:
|
||||
"""
|
||||
if self.__current_announcer is None:
|
||||
return False
|
||||
|
||||
return self.__current_announcer.active or False
|
||||
|
||||
@staticmethod
|
||||
def pass_hierarchy_check(ctx: commands.Context, role: discord.Role) -> bool:
|
||||
"""
|
||||
Determines if the bot has a higher role than the given one.
|
||||
:param ctx:
|
||||
:param role: Role object.
|
||||
:return:
|
||||
"""
|
||||
return ctx.guild.me.top_role > role
|
||||
|
||||
@staticmethod
|
||||
def pass_user_hierarchy_check(ctx: commands.Context, role: discord.Role) -> bool:
|
||||
"""
|
||||
Determines if a user is allowed to add/remove/edit the given role.
|
||||
:param ctx:
|
||||
:param role:
|
||||
:return:
|
||||
"""
|
||||
return ctx.author.top_role > role
|
||||
|
||||
async def _addrole(self, ctx: commands.Context, member: discord.Member, role: discord.Role):
|
||||
try:
|
||||
await member.add_roles(role)
|
||||
except discord.Forbidden:
|
||||
if not self.pass_hierarchy_check(ctx, role):
|
||||
await self.complain(ctx, T_(HIERARCHY_ISSUE), role=role, member=member)
|
||||
else:
|
||||
await self.complain(ctx, T_(GENERIC_FORBIDDEN))
|
||||
else:
|
||||
await ctx.send(
|
||||
_("I successfully added {role.name} to {member.display_name}").format(
|
||||
role=role, member=member
|
||||
)
|
||||
)
|
||||
|
||||
async def _removerole(self, ctx: commands.Context, member: discord.Member, role: discord.Role):
|
||||
try:
|
||||
await member.remove_roles(role)
|
||||
except discord.Forbidden:
|
||||
if not self.pass_hierarchy_check(ctx, role):
|
||||
await self.complain(ctx, T_(HIERARCHY_ISSUE), role=role, member=member)
|
||||
else:
|
||||
await self.complain(ctx, T_(GENERIC_FORBIDDEN))
|
||||
else:
|
||||
await ctx.send(
|
||||
_("I successfully removed {role.name} from {member.display_name}").format(
|
||||
role=role, member=member
|
||||
)
|
||||
)
|
||||
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
@checks.admin_or_permissions(manage_roles=True)
|
||||
async def addrole(
|
||||
self, ctx: commands.Context, rolename: discord.Role, *, user: MemberDefaultAuthor = None
|
||||
):
|
||||
"""Add a role to a user.
|
||||
|
||||
If user is left blank it defaults to the author of the command.
|
||||
"""
|
||||
if user is None:
|
||||
user = ctx.author
|
||||
if self.pass_user_hierarchy_check(ctx, rolename):
|
||||
# noinspection PyTypeChecker
|
||||
await self._addrole(ctx, user, rolename)
|
||||
else:
|
||||
await self.complain(ctx, T_(USER_HIERARCHY_ISSUE), member=ctx.author, role=rolename)
|
||||
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
@checks.admin_or_permissions(manage_roles=True)
|
||||
async def removerole(
|
||||
self, ctx: commands.Context, rolename: discord.Role, *, user: MemberDefaultAuthor = None
|
||||
):
|
||||
"""Remove a role from a user.
|
||||
|
||||
If user is left blank it defaults to the author of the command.
|
||||
"""
|
||||
if user is None:
|
||||
user = ctx.author
|
||||
if self.pass_user_hierarchy_check(ctx, rolename):
|
||||
# noinspection PyTypeChecker
|
||||
await self._removerole(ctx, user, rolename)
|
||||
else:
|
||||
await self.complain(ctx, T_(USER_HIERARCHY_ISSUE))
|
||||
|
||||
@commands.group()
|
||||
@commands.guild_only()
|
||||
@checks.admin_or_permissions(manage_roles=True)
|
||||
async def editrole(self, ctx: commands.Context):
|
||||
"""Edit role settings."""
|
||||
pass
|
||||
|
||||
@editrole.command(name="colour", aliases=["color"])
|
||||
async def editrole_colour(
|
||||
self, ctx: commands.Context, role: discord.Role, value: discord.Colour
|
||||
):
|
||||
"""Edit a role's colour.
|
||||
|
||||
Use double quotes if the role contains spaces.
|
||||
Colour must be in hexadecimal format.
|
||||
[Online colour picker](http://www.w3schools.com/colors/colors_picker.asp)
|
||||
|
||||
Examples:
|
||||
`[p]editrole colour "The Transistor" #ff0000`
|
||||
`[p]editrole colour Test #ff9900`
|
||||
"""
|
||||
author = ctx.author
|
||||
reason = "{}({}) changed the colour of role '{}'".format(author.name, author.id, role.name)
|
||||
|
||||
if not self.pass_user_hierarchy_check(ctx, role):
|
||||
await self.complain(ctx, T_(USER_HIERARCHY_ISSUE))
|
||||
return
|
||||
|
||||
try:
|
||||
await role.edit(reason=reason, color=value)
|
||||
except discord.Forbidden:
|
||||
await self.complain(ctx, T_(GENERIC_FORBIDDEN))
|
||||
else:
|
||||
log.info(reason)
|
||||
await ctx.send(_("Done."))
|
||||
|
||||
@editrole.command(name="name")
|
||||
@checks.admin_or_permissions(administrator=True)
|
||||
async def edit_role_name(self, ctx: commands.Context, role: discord.Role, *, name: str):
|
||||
"""Edit a role's name.
|
||||
|
||||
Use double quotes if the role or the name contain spaces.
|
||||
|
||||
Examples:
|
||||
`[p]editrole name \"The Transistor\" Test`
|
||||
"""
|
||||
author = ctx.message.author
|
||||
old_name = role.name
|
||||
reason = "{}({}) changed the name of role '{}' to '{}'".format(
|
||||
author.name, author.id, old_name, name
|
||||
)
|
||||
|
||||
if not self.pass_user_hierarchy_check(ctx, role):
|
||||
await self.complain(ctx, T_(USER_HIERARCHY_ISSUE))
|
||||
return
|
||||
|
||||
try:
|
||||
await role.edit(reason=reason, name=name)
|
||||
except discord.Forbidden:
|
||||
await self.complain(ctx, T_(GENERIC_FORBIDDEN))
|
||||
else:
|
||||
log.info(reason)
|
||||
await ctx.send(_("Done."))
|
||||
|
||||
@commands.group(invoke_without_command=True)
|
||||
@checks.is_owner()
|
||||
async def announce(self, ctx: commands.Context, *, message: str):
|
||||
"""Announce a message to all servers the bot is in."""
|
||||
if not self.is_announcing():
|
||||
announcer = Announcer(ctx, message, config=self.conf)
|
||||
announcer.start()
|
||||
|
||||
self.__current_announcer = announcer
|
||||
|
||||
await ctx.send(_("The announcement has begun."))
|
||||
else:
|
||||
prefix = ctx.prefix
|
||||
await self.complain(ctx, T_(RUNNING_ANNOUNCEMENT), prefix=prefix)
|
||||
|
||||
@announce.command(name="cancel")
|
||||
@checks.is_owner()
|
||||
async def announce_cancel(self, ctx):
|
||||
"""Cancel a running announce."""
|
||||
try:
|
||||
self.__current_announcer.cancel()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
await ctx.send(_("The current announcement has been cancelled."))
|
||||
|
||||
@announce.command(name="channel")
|
||||
@commands.guild_only()
|
||||
@checks.guildowner_or_permissions(administrator=True)
|
||||
async def announce_channel(self, ctx, *, channel: discord.TextChannel = None):
|
||||
"""Change the channel to which the bot makes announcements."""
|
||||
if channel is None:
|
||||
channel = ctx.channel
|
||||
await self.conf.guild(ctx.guild).announce_channel.set(channel.id)
|
||||
|
||||
await ctx.send(
|
||||
_("The announcement channel has been set to {channel.mention}").format(channel=channel)
|
||||
)
|
||||
|
||||
@announce.command(name="ignore")
|
||||
@commands.guild_only()
|
||||
@checks.guildowner_or_permissions(administrator=True)
|
||||
async def announce_ignore(self, ctx):
|
||||
"""Toggle announcements being enabled this server."""
|
||||
ignored = await self.conf.guild(ctx.guild).announce_ignore()
|
||||
await self.conf.guild(ctx.guild).announce_ignore.set(not ignored)
|
||||
|
||||
if ignored: # Keeping original logic....
|
||||
await ctx.send(
|
||||
_("The server {guild.name} will receive announcements.").format(guild=ctx.guild)
|
||||
)
|
||||
else:
|
||||
await ctx.send(
|
||||
_("The server {guild.name} will not receive announcements.").format(
|
||||
guild=ctx.guild
|
||||
)
|
||||
)
|
||||
|
||||
async def _valid_selfroles(self, guild: discord.Guild) -> Tuple[discord.Role]:
|
||||
"""
|
||||
Returns a list of valid selfroles
|
||||
:param guild:
|
||||
:return:
|
||||
"""
|
||||
selfrole_ids = set(await self.conf.guild(guild).selfroles())
|
||||
guild_roles = guild.roles
|
||||
|
||||
valid_roles = tuple(r for r in guild_roles if r.id in selfrole_ids)
|
||||
valid_role_ids = set(r.id for r in valid_roles)
|
||||
|
||||
if selfrole_ids != valid_role_ids:
|
||||
await self.conf.guild(guild).selfroles.set(valid_role_ids)
|
||||
|
||||
# noinspection PyTypeChecker
|
||||
return valid_roles
|
||||
|
||||
@commands.guild_only()
|
||||
@commands.group(invoke_without_command=True)
|
||||
async def selfrole(self, ctx: commands.Context, *, selfrole: SelfRole):
|
||||
"""Add a role to yourself.
|
||||
|
||||
Server admins must have configured the role as user settable.
|
||||
|
||||
NOTE: The role is case sensitive!
|
||||
"""
|
||||
# noinspection PyTypeChecker
|
||||
await self._addrole(ctx, ctx.author, selfrole)
|
||||
|
||||
@selfrole.command(name="remove")
|
||||
async def selfrole_remove(self, ctx: commands.Context, *, selfrole: SelfRole):
|
||||
"""Remove a selfrole from yourself.
|
||||
|
||||
NOTE: The role is case sensitive!
|
||||
"""
|
||||
# noinspection PyTypeChecker
|
||||
await self._removerole(ctx, ctx.author, selfrole)
|
||||
|
||||
@selfrole.command(name="add")
|
||||
@checks.admin_or_permissions(manage_roles=True)
|
||||
async def selfrole_add(self, ctx: commands.Context, *, role: discord.Role):
|
||||
"""Add a role to the list of available selfroles.
|
||||
|
||||
NOTE: The role is case sensitive!
|
||||
"""
|
||||
async with self.conf.guild(ctx.guild).selfroles() as curr_selfroles:
|
||||
if role.id not in curr_selfroles:
|
||||
curr_selfroles.append(role.id)
|
||||
|
||||
await ctx.send(_("The selfroles list has been successfully modified."))
|
||||
|
||||
@selfrole.command(name="delete")
|
||||
@checks.admin_or_permissions(manage_roles=True)
|
||||
async def selfrole_delete(self, ctx: commands.Context, *, role: SelfRole):
|
||||
"""Remove a role from the list of available selfroles.
|
||||
|
||||
NOTE: The role is case sensitive!
|
||||
"""
|
||||
async with self.conf.guild(ctx.guild).selfroles() as curr_selfroles:
|
||||
curr_selfroles.remove(role.id)
|
||||
|
||||
await ctx.send(_("The selfroles list has been successfully modified."))
|
||||
|
||||
@selfrole.command(name="list")
|
||||
async def selfrole_list(self, ctx: commands.Context):
|
||||
"""
|
||||
Lists all available selfroles.
|
||||
"""
|
||||
selfroles = await self._valid_selfroles(ctx.guild)
|
||||
fmt_selfroles = "\n".join(["+ " + r.name for r in selfroles])
|
||||
|
||||
msg = _("Available Selfroles:\n{selfroles}").format(selfroles=fmt_selfroles)
|
||||
await ctx.send(box(msg, "diff"))
|
||||
|
||||
async def _serverlock_check(self, guild: discord.Guild) -> bool:
|
||||
"""
|
||||
Checks if serverlocked is enabled.
|
||||
:param guild:
|
||||
:return: True if locked and left server
|
||||
"""
|
||||
if await self.conf.serverlocked():
|
||||
await guild.leave()
|
||||
return True
|
||||
return False
|
||||
|
||||
@commands.command()
|
||||
@checks.is_owner()
|
||||
async def serverlock(self, ctx: commands.Context):
|
||||
"""Lock a bot to its current servers only."""
|
||||
serverlocked = await self.conf.serverlocked()
|
||||
await self.conf.serverlocked.set(not serverlocked)
|
||||
|
||||
if serverlocked:
|
||||
await ctx.send(_("The bot is no longer serverlocked."))
|
||||
else:
|
||||
await ctx.send(_("The bot is now serverlocked."))
|
||||
|
||||
# region Event Handlers
|
||||
async def on_guild_join(self, guild: discord.Guild):
|
||||
if await self._serverlock_check(guild):
|
||||
return
|
||||
|
||||
|
||||
# endregion
|
||||
@@ -0,0 +1,74 @@
|
||||
import asyncio
|
||||
|
||||
import discord
|
||||
from redbot.core import commands
|
||||
from redbot.core.i18n import Translator
|
||||
|
||||
_ = Translator("Announcer", __file__)
|
||||
|
||||
|
||||
class Announcer:
|
||||
def __init__(self, ctx: commands.Context, message: str, config=None):
|
||||
"""
|
||||
:param ctx:
|
||||
:param message:
|
||||
:param config: Used to determine channel overrides
|
||||
"""
|
||||
self.ctx = ctx
|
||||
self.message = message
|
||||
self.config = config
|
||||
|
||||
self.active = None
|
||||
|
||||
def start(self):
|
||||
"""
|
||||
Starts an announcement.
|
||||
:return:
|
||||
"""
|
||||
if self.active is None:
|
||||
self.active = True
|
||||
self.ctx.bot.loop.create_task(self.announcer())
|
||||
|
||||
def cancel(self):
|
||||
"""
|
||||
Cancels a running announcement.
|
||||
:return:
|
||||
"""
|
||||
self.active = False
|
||||
|
||||
async def _get_announce_channel(self, guild: discord.Guild) -> discord.TextChannel:
|
||||
channel_id = await self.config.guild(guild).announce_channel()
|
||||
channel = None
|
||||
|
||||
if channel_id is not None:
|
||||
channel = guild.get_channel(channel_id)
|
||||
|
||||
if channel is None:
|
||||
channel = guild.system_channel
|
||||
|
||||
if channel is None:
|
||||
channel = guild.text_channels[0]
|
||||
|
||||
return channel
|
||||
|
||||
async def announcer(self):
|
||||
guild_list = self.ctx.bot.guilds
|
||||
bot_owner = (await self.ctx.bot.application_info()).owner
|
||||
for g in guild_list:
|
||||
if not self.active:
|
||||
return
|
||||
|
||||
if await self.config.guild(g).announce_ignore():
|
||||
continue
|
||||
|
||||
channel = await self._get_announce_channel(g)
|
||||
|
||||
try:
|
||||
await channel.send(self.message)
|
||||
except discord.Forbidden:
|
||||
await bot_owner.send(
|
||||
_("I could not announce to server: {server.id}").format(server=g)
|
||||
)
|
||||
await asyncio.sleep(0.5)
|
||||
|
||||
self.active = False
|
||||
@@ -0,0 +1,35 @@
|
||||
import discord
|
||||
from redbot.core import commands
|
||||
from redbot.core.i18n import Translator
|
||||
|
||||
_ = Translator("AdminConverters", __file__)
|
||||
|
||||
|
||||
class MemberDefaultAuthor(commands.Converter):
|
||||
async def convert(self, ctx: commands.Context, arg: str) -> discord.Member:
|
||||
member_converter = commands.MemberConverter()
|
||||
try:
|
||||
member = await member_converter.convert(ctx, arg)
|
||||
except commands.BadArgument:
|
||||
if arg.strip() != "":
|
||||
raise
|
||||
else:
|
||||
member = ctx.author
|
||||
return member
|
||||
|
||||
|
||||
class SelfRole(commands.Converter):
|
||||
async def convert(self, ctx: commands.Context, arg: str) -> discord.Role:
|
||||
admin = ctx.command.instance
|
||||
if admin is None:
|
||||
raise commands.BadArgument(_("The Admin cog is not loaded."))
|
||||
|
||||
conf = admin.conf
|
||||
selfroles = await conf.guild(ctx.guild).selfroles()
|
||||
|
||||
role_converter = commands.RoleConverter()
|
||||
role = await role_converter.convert(ctx, arg)
|
||||
|
||||
if role.id not in selfroles:
|
||||
raise commands.BadArgument(_("The provided role is not a valid selfrole."))
|
||||
return role
|
||||
@@ -0,0 +1,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:41-0400\n"
|
||||
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
|
||||
"Language-Team: Arabic\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5);\n"
|
||||
"X-Generator: crowdin.com\n"
|
||||
"X-Crowdin-Project: red-discordbot\n"
|
||||
"X-Crowdin-Language: ar\n"
|
||||
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
|
||||
"Language: ar_SA\n"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\n"
|
||||
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
|
||||
"Language-Team: Bulgarian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: crowdin.com\n"
|
||||
"X-Crowdin-Project: red-discordbot\n"
|
||||
"X-Crowdin-Language: bg\n"
|
||||
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
|
||||
"Language: bg_BG\n"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\n"
|
||||
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
|
||||
"Language-Team: Danish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: crowdin.com\n"
|
||||
"X-Crowdin-Project: red-discordbot\n"
|
||||
"X-Crowdin-Language: da\n"
|
||||
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
|
||||
"Language: da_DK\n"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\n"
|
||||
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
|
||||
"Language-Team: German\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: crowdin.com\n"
|
||||
"X-Crowdin-Project: red-discordbot\n"
|
||||
"X-Crowdin-Language: de\n"
|
||||
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
|
||||
"Language: de_DE\n"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\n"
|
||||
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
|
||||
"Language-Team: Greek\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: crowdin.com\n"
|
||||
"X-Crowdin-Project: red-discordbot\n"
|
||||
"X-Crowdin-Language: el\n"
|
||||
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
|
||||
"Language: el_GR\n"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:43-0400\n"
|
||||
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
|
||||
"Language-Team: Pirate English\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: crowdin.com\n"
|
||||
"X-Crowdin-Project: red-discordbot\n"
|
||||
"X-Crowdin-Language: en-PT\n"
|
||||
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
|
||||
"Language: en_PT\n"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:41-0400\n"
|
||||
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
|
||||
"Language-Team: Spanish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: crowdin.com\n"
|
||||
"X-Crowdin-Project: red-discordbot\n"
|
||||
"X-Crowdin-Language: es-ES\n"
|
||||
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
|
||||
"Language: es_ES\n"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\n"
|
||||
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
|
||||
"Language-Team: Finnish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: crowdin.com\n"
|
||||
"X-Crowdin-Project: red-discordbot\n"
|
||||
"X-Crowdin-Language: fi\n"
|
||||
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
|
||||
"Language: fi_FI\n"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:41-0400\n"
|
||||
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
|
||||
"Language-Team: French\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Generator: crowdin.com\n"
|
||||
"X-Crowdin-Project: red-discordbot\n"
|
||||
"X-Crowdin-Language: fr\n"
|
||||
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
|
||||
"Language: fr_FR\n"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\n"
|
||||
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
|
||||
"Language-Team: Hungarian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: crowdin.com\n"
|
||||
"X-Crowdin-Project: red-discordbot\n"
|
||||
"X-Crowdin-Language: hu\n"
|
||||
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
|
||||
"Language: hu_HU\n"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:43-0400\n"
|
||||
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
|
||||
"Language-Team: Indonesian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: crowdin.com\n"
|
||||
"X-Crowdin-Project: red-discordbot\n"
|
||||
"X-Crowdin-Language: id\n"
|
||||
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
|
||||
"Language: id_ID\n"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\n"
|
||||
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
|
||||
"Language-Team: Italian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: crowdin.com\n"
|
||||
"X-Crowdin-Project: red-discordbot\n"
|
||||
"X-Crowdin-Language: it\n"
|
||||
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
|
||||
"Language: it_IT\n"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\n"
|
||||
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
|
||||
"Language-Team: Japanese\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: crowdin.com\n"
|
||||
"X-Crowdin-Project: red-discordbot\n"
|
||||
"X-Crowdin-Language: ja\n"
|
||||
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
|
||||
"Language: ja_JP\n"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\n"
|
||||
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
|
||||
"Language-Team: Korean\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: crowdin.com\n"
|
||||
"X-Crowdin-Project: red-discordbot\n"
|
||||
"X-Crowdin-Language: ko\n"
|
||||
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
|
||||
"Language: ko_KR\n"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:43-0400\n"
|
||||
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
|
||||
"Language-Team: LOLCAT\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: crowdin.com\n"
|
||||
"X-Crowdin-Project: red-discordbot\n"
|
||||
"X-Crowdin-Language: lol\n"
|
||||
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
|
||||
"Language: lol_US\n"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\n"
|
||||
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
|
||||
"Language-Team: Dutch\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: crowdin.com\n"
|
||||
"X-Crowdin-Project: red-discordbot\n"
|
||||
"X-Crowdin-Language: nl\n"
|
||||
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
|
||||
"Language: nl_NL\n"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\n"
|
||||
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
|
||||
"Language-Team: Norwegian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: crowdin.com\n"
|
||||
"X-Crowdin-Project: red-discordbot\n"
|
||||
"X-Crowdin-Language: no\n"
|
||||
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
|
||||
"Language: no_NO\n"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:43-0400\n"
|
||||
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
|
||||
"Language-Team: Polish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"Plural-Forms: nplurals=4; plural=((n == 1) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || n%10 == 1 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 12 && n%100 <= 14)) ? 2 : 3));\n"
|
||||
"X-Generator: crowdin.com\n"
|
||||
"X-Crowdin-Project: red-discordbot\n"
|
||||
"X-Crowdin-Language: pl\n"
|
||||
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
|
||||
"Language: pl_PL\n"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:43-0400\n"
|
||||
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
|
||||
"Language-Team: Portuguese, Brazilian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: crowdin.com\n"
|
||||
"X-Crowdin-Project: red-discordbot\n"
|
||||
"X-Crowdin-Language: pt-BR\n"
|
||||
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
|
||||
"Language: pt_BR\n"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:43-0400\n"
|
||||
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
|
||||
"Language-Team: Portuguese\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: crowdin.com\n"
|
||||
"X-Crowdin-Project: red-discordbot\n"
|
||||
"X-Crowdin-Language: pt-PT\n"
|
||||
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
|
||||
"Language: pt_PT\n"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user