diff --git a/Pipfile b/Pipfile index 096fb9b3..c0ed7ad5 100644 --- a/Pipfile +++ b/Pipfile @@ -1,15 +1,21 @@ [[source]] + url = "https://pypi.python.org/simple" verify_ssl = true name = "pypi" + [packages] + "72eb2aa" = {file = "https://github.com/Rapptz/discord.py/archive/rewrite.zip"} aiodns = "*" aiohttp = "<2.3.0,>=2.0.0" websockets = ">=4.0,<5.0" +titlecase = "*" + [dev-packages] + "flake8" = "*" "flake8-bugbear" = "*" "flake8-bandit" = "*" @@ -20,5 +26,7 @@ websockets = ">=4.0,<5.0" safety = "*" dodgy = "*" + [requires] + python_version = "3.6" diff --git a/Pipfile.lock b/Pipfile.lock index 4e5214bb..683fe3e6 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,20 @@ { "_meta": { "hash": { - "sha256": "d797e580ddcddc99bf058109ab0306ad584c2902752a3d4076ba713fdc580fb7" + "sha256": "2cca231e2bd4b5fdaa06fd33b68143231524f2855847ebf4cc497462e135fdf2" + }, + "host-environment-markers": { + "implementation_name": "cpython", + "implementation_version": "3.6.1", + "os_name": "nt", + "platform_machine": "AMD64", + "platform_python_implementation": "CPython", + "platform_release": "10", + "platform_system": "Windows", + "platform_version": "10.0.16299", + "python_full_version": "3.6.1", + "python_version": "3.6", + "sys_platform": "win32" }, "pipfile-spec": 6, "requires": { @@ -24,139 +37,143 @@ "sha256:99d0652f2c02f73bfa646bf44af82705260a523014576647d7959e664830b26b", "sha256:d8677adc679ce8d0ef706c14d9c3d2f27a0e0cc11d59730cdbaf218ad52dd9ea" ], - "index": "pypi", "version": "==1.1.1" }, "aiohttp": { "hashes": [ - "sha256:129d83dd067760cec3cfd4456b5c6d7ac29f2c639d856884568fd539bed5a51f", - "sha256:33c62afd115c456b0cf1e890fe6753055effe0f31a28321efd4f787378d6f4ab", - "sha256:666756e1d4cf161ed1486b82f65fdd386ac07dd20fb10f025abf4be54be12746", "sha256:9705ded5a0faa25c8f14c6afb7044002d66c9120ed7eadb4aa9ca4aad32bd00c", - "sha256:af5bfdd164256118a0a306b3f7046e63207d1f8cba73a67dcc0bd858dcfcd3bc", + "sha256:de8ef106e130b94ca143fdfc6f27cda1d8ba439462542377738af4d99d9f5dd2", + "sha256:f0e2ac69cb709367400008cebccd5d48161dd146096a009a632a132babe5714c", + "sha256:33c62afd115c456b0cf1e890fe6753055effe0f31a28321efd4f787378d6f4ab", + "sha256:dcc7e4dcec6b0012537b9f8a0726f8b111188894ab0f924b680d40b13d3298a0", "sha256:b80f44b99fa3c9b4530fcfa324a99b84843043c35b084e0b653566049974435d", + "sha256:eb6f1405b607fff7e44168e3ceb5d3c8a8c5a2d3effe0a27f843b16ec047a6d7", + "sha256:666756e1d4cf161ed1486b82f65fdd386ac07dd20fb10f025abf4be54be12746", + "sha256:d611ebd1ef48498210b65486306e065fde031040a1f3c455ca1b6baa7bf32ad3", "sha256:c67e105ec74b85c8cb666b6877569dee6f55b9548f982983b9bee80b3d47e6f3", + "sha256:129d83dd067760cec3cfd4456b5c6d7ac29f2c639d856884568fd539bed5a51f", "sha256:d15c6658de5b7783c2538407278fa062b079a46d5f814a133ae0f09bbb2cfbc4", - "sha256:d611ebd1ef48498210b65486306e065fde031040a1f3c455ca1b6baa7bf32ad3", - "sha256:dcc7e4dcec6b0012537b9f8a0726f8b111188894ab0f924b680d40b13d3298a0", - "sha256:de8ef106e130b94ca143fdfc6f27cda1d8ba439462542377738af4d99d9f5dd2", - "sha256:eb6f1405b607fff7e44168e3ceb5d3c8a8c5a2d3effe0a27f843b16ec047a6d7", - "sha256:f0e2ac69cb709367400008cebccd5d48161dd146096a009a632a132babe5714c" + "sha256:af5bfdd164256118a0a306b3f7046e63207d1f8cba73a67dcc0bd858dcfcd3bc" ], - "index": "pypi", "version": "==2.2.5" }, "async-timeout": { "hashes": [ - "sha256:00cff4d2dce744607335cba84e9929c3165632da2d27970dbc55802a0c7873d0", - "sha256:9093db5b8ddbe4b8f6885d1a6e0ad84ae3155464cbf6877c387605244c285f3c" + "sha256:9093db5b8ddbe4b8f6885d1a6e0ad84ae3155464cbf6877c387605244c285f3c", + "sha256:00cff4d2dce744607335cba84e9929c3165632da2d27970dbc55802a0c7873d0" ], "version": "==2.0.1" }, "chardet": { "hashes": [ - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691", + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae" ], "version": "==3.0.4" }, "idna": { "hashes": [ - "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f", - "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4" + "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4", + "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f" ], "version": "==2.6" }, "multidict": { "hashes": [ - "sha256:0462372fc74e4c061335118a4a5992b9a618d6c584b028ef03cf3e9b88a960e2", - "sha256:068e91060e3e211441b1a31f5e65de88fc346490e1fae583c35a75a5295c8ef7", "sha256:0fd4d255adcbab3341d64a2fff5acce23409e57bb94e626485dea3db70ddc35e", - "sha256:16c78b10e897a512aa34ab1969982e42246e53077ae903c1b334926e1ea832d1", + "sha256:93f1af99bbe75c854370460a60823d6726f9af2196818a64346000d02e074ed7", + "sha256:65546242d0c481c0daf0ef20c1be81c075fb763c5f4346f18f748b422fc40f32", + "sha256:0462372fc74e4c061335118a4a5992b9a618d6c584b028ef03cf3e9b88a960e2", + "sha256:63663541d395ffe4d51a3c021467d0a7b46c965b63fa1646cb46e2e2f1f36415", + "sha256:84a1cb5320f1494cd444ca3bd09ddba2e0af0cb210f9263bcf17357ab22671a1", "sha256:241c11614f64535e213ea143efa8b7e598793256601fc795e77075bdfa54f5d6", + "sha256:ea8a18ea02bf84981ec93faded773a866554666f13955c92139127892c4bb45c", + "sha256:b46ec31bb7729eaa678a3bb1c999460902df1e295fcc093b9aa5f2c7e68d5803", + "sha256:608f7eef60e6558418d7da6551dd3d07ccc1290ecc85755d781bd8100322ea5b", + "sha256:068e91060e3e211441b1a31f5e65de88fc346490e1fae583c35a75a5295c8ef7", "sha256:288e8f94fb6f586e7386c1f22c979ce3ec866ab23371fa8fef1dd526cd4dfde1", - "sha256:3508bea4974ee30fabcf7c8852fca7d9d54d496eaa068bee8311e0ac4df4ade3", "sha256:503ae54582601b0ff647731fee5efcdff5db1f4da0350febb31b628236a5f0b5", - "sha256:50de6f3786ba868ffb7d78d4bcacf0928321f9892366b2f4a0426bba644e3f25", - "sha256:608f7eef60e6558418d7da6551dd3d07ccc1290ecc85755d781bd8100322ea5b", - "sha256:63663541d395ffe4d51a3c021467d0a7b46c965b63fa1646cb46e2e2f1f36415", - "sha256:65546242d0c481c0daf0ef20c1be81c075fb763c5f4346f18f748b422fc40f32", "sha256:6d5f6f26f9025756035c473167b39c5a72e4e519a2286c9399d21f6682e4e5bc", - "sha256:84a1cb5320f1494cd444ca3bd09ddba2e0af0cb210f9263bcf17357ab22671a1", - "sha256:93f1af99bbe75c854370460a60823d6726f9af2196818a64346000d02e074ed7", - "sha256:b46ec31bb7729eaa678a3bb1c999460902df1e295fcc093b9aa5f2c7e68d5803", - "sha256:cd172509bfc9144395204dd2c0eb305ae5e89f8ad1714ffd7d793607c53c3244", - "sha256:d99819e9e15e1295a31a757360cab65bc96162870f90c29432564bd8e8999aca", - "sha256:e04b5bf8581718cf84c1c60bda40221d926ceb06f942ebabfc3baf467a1e34be", "sha256:e13265feabb1fa26f9cd49cbafd9b5de70ad768093ddb092af477c9823f44f0e", - "sha256:ea8a18ea02bf84981ec93faded773a866554666f13955c92139127892c4bb45c", + "sha256:50de6f3786ba868ffb7d78d4bcacf0928321f9892366b2f4a0426bba644e3f25", + "sha256:16c78b10e897a512aa34ab1969982e42246e53077ae903c1b334926e1ea832d1", + "sha256:e04b5bf8581718cf84c1c60bda40221d926ceb06f942ebabfc3baf467a1e34be", + "sha256:d99819e9e15e1295a31a757360cab65bc96162870f90c29432564bd8e8999aca", + "sha256:cd172509bfc9144395204dd2c0eb305ae5e89f8ad1714ffd7d793607c53c3244", + "sha256:3508bea4974ee30fabcf7c8852fca7d9d54d496eaa068bee8311e0ac4df4ade3", "sha256:fb4412490324705dcd2172baa8a3ea58ae23c5f982476805cad58ae929fe2a52" ], "version": "==4.1.0" }, "pycares": { "hashes": [ - "sha256:0e81c971236bb0767354f1456e67ab6ae305f248565ce77cd413a311f9572bf5", - "sha256:11c0ff3ccdb5a838cbd59a4e59df35d31355a80a61393bca786ca3b44569ba10", - "sha256:170d62bd300999227e64da4fa85459728cc96e62e44780bbc86a915fdae01f78", - "sha256:36f4c03df57c41a87eb3d642201684eb5a8bc194f4bafaa9f60ee6dc0aef8e40", - "sha256:371ce688776da984c4105c8ca760cc60944b9b49ccf8335c71dc7669335e6173", - "sha256:3a2234516f7db495083d8bba0ccdaabae587e62cfcd1b8154d5d0b09d3a48dfc", "sha256:3f288586592c697109b2b06e3988b7e17d9765887b5fc367010ee8500cbddc86", - "sha256:40134cee03c8bbfbc644d4c0bc81796e12dd012a5257fb146c5a5417812ee5f7", - "sha256:722f5d2c5f78d47b13b0112f6daff43ce4e08e8152319524d14f1f917cc5125e", - "sha256:7b18fab0ed534a898552df91bc804bd62bb3a2646c11e054baca14d23663e1d6", "sha256:8a39d03bd99ea191f86b990ef67ecce878d6bf6518c5cde9173fb34fb36beb5e", + "sha256:d8637bcc2f901aa61ec1d754abc862f9f145cb0346a0249360df4c159377018e", + "sha256:b95b339c11d824f0bb789d31b91c8534916fcbdce248cccce216fa2630bb8a90", "sha256:8ea263de8bf1a30b0d87150b4aa0e3203cf93bc1723ea3e7408a7d25e1299217", + "sha256:e72fa163f37ae3b09f143cc6690a36f012d13e905d142e1beed4ec0e593ff657", + "sha256:40134cee03c8bbfbc644d4c0bc81796e12dd012a5257fb146c5a5417812ee5f7", + "sha256:e2446577eeea79d2179c9469d9d4ce3ab8a07d7985465c3cb91e7d74abc329b6", + "sha256:11c0ff3ccdb5a838cbd59a4e59df35d31355a80a61393bca786ca3b44569ba10", + "sha256:7b18fab0ed534a898552df91bc804bd62bb3a2646c11e054baca14d23663e1d6", + "sha256:722f5d2c5f78d47b13b0112f6daff43ce4e08e8152319524d14f1f917cc5125e", + "sha256:bbfd9aba1e172cd2ab7b7142d49b28cf44d6451c4a66a870aff1dc3cb84849c7", + "sha256:f50be4dd53f009cfb4b98c3c6b240e18ff9b17e3f1c320bd594bb83eddabfcb2", "sha256:943e2dc67ff45ab4c81d628c959837d01561d7e185080ab7a276b8ca67573fb5", + "sha256:3a2234516f7db495083d8bba0ccdaabae587e62cfcd1b8154d5d0b09d3a48dfc", "sha256:9d56a54c93e64b30c0d31f394d9890f175edec029cd846221728f99263cdee82", - "sha256:b95b339c11d824f0bb789d31b91c8534916fcbdce248cccce216fa2630bb8a90", - "sha256:bbfd9aba1e172cd2ab7b7142d49b28cf44d6451c4a66a870aff1dc3cb84849c7", - "sha256:d8637bcc2f901aa61ec1d754abc862f9f145cb0346a0249360df4c159377018e", - "sha256:e2446577eeea79d2179c9469d9d4ce3ab8a07d7985465c3cb91e7d74abc329b6", - "sha256:e72fa163f37ae3b09f143cc6690a36f012d13e905d142e1beed4ec0e593ff657", + "sha256:371ce688776da984c4105c8ca760cc60944b9b49ccf8335c71dc7669335e6173", + "sha256:0e81c971236bb0767354f1456e67ab6ae305f248565ce77cd413a311f9572bf5", "sha256:f32b7c63094749fbc0c1106c9a785666ec8afd49ecfe7002a30bb7c42e62b47c", - "sha256:f50be4dd53f009cfb4b98c3c6b240e18ff9b17e3f1c320bd594bb83eddabfcb2" + "sha256:170d62bd300999227e64da4fa85459728cc96e62e44780bbc86a915fdae01f78", + "sha256:36f4c03df57c41a87eb3d642201684eb5a8bc194f4bafaa9f60ee6dc0aef8e40" ], "version": "==2.3.0" }, + "titlecase": { + "hashes": [ + "sha256:95d643a0c08097c02933aced707adfe1c275c335019e8e514dea782a465c5b84", + "sha256:84de7a97fb702c400e5ba11c6b30849944b39db12e20fbf4515a23c7538a0611" + ], + "version": "==0.12.0" + }, "websockets": { "hashes": [ + "sha256:f5192da704535a7cbf76d6e99c1ec4af7e8d1288252bf5a2385d414509ded0cf", "sha256:0c31bc832d529dc7583d324eb6c836a4f362032a1902723c112cf57883488d8c", - "sha256:1f3e5a52cab6daa3d432c7b0de0a14109be39d2bfaad033ee5de4a3d3e11dcdf", - "sha256:341824d8c9ad53fc43cca3fa9407f294125fa258592f7676640396501448e57e", - "sha256:367ff945bc0950ad9634591e2afe50bf2222bc4fad1088a386c4bb700888026e", - "sha256:3859ca16c229ddb0fa21c5090e4efcb037c08ce69b0c1dfed6122c3f98cd0c22", - "sha256:3d425ae081fb4ba1eef9ecf30472ffd79f8e868297ccc7a47993c96dbf2a819c", - "sha256:64896a6b3368c959b8096b655e46f03dfa65b96745249f374bd6a35705cc3489", - "sha256:6df87698022aef2596bffdfecc96d656db59c8d719708c8a471daa815ee61656", - "sha256:80188abdadd23edaaea05ce761dc9a2e1df31a74a0533967f0dcd9560c85add0", - "sha256:d1a0572b6edb22c9208e3e5381064e09d287d2a915f90233fef994ee7a14a935", - "sha256:da4d4fbe059b0453e726d6d993760065d69b823a27efc3040402a6fcfe6a1ed9", "sha256:da7610a017f5343fdf765f4e0eb6fd0dfd08264ca1565212b110836d9367fc9c", - "sha256:ebdd4f18fe7e3bea9bd3bf446b0f4117739478caa2c76e4f0fb72cc45b03cbd7", - "sha256:f5192da704535a7cbf76d6e99c1ec4af7e8d1288252bf5a2385d414509ded0cf", "sha256:fd81af8cf3e69f9a97f3a6c0623a0527de0f922c2df725f00cd7646d478af632", - "sha256:fecf51c13195c416c22422353b306dddb9c752e4b80b21e0fa1fccbe38246677" + "sha256:3d425ae081fb4ba1eef9ecf30472ffd79f8e868297ccc7a47993c96dbf2a819c", + "sha256:ebdd4f18fe7e3bea9bd3bf446b0f4117739478caa2c76e4f0fb72cc45b03cbd7", + "sha256:3859ca16c229ddb0fa21c5090e4efcb037c08ce69b0c1dfed6122c3f98cd0c22", + "sha256:d1a0572b6edb22c9208e3e5381064e09d287d2a915f90233fef994ee7a14a935", + "sha256:80188abdadd23edaaea05ce761dc9a2e1df31a74a0533967f0dcd9560c85add0", + "sha256:fecf51c13195c416c22422353b306dddb9c752e4b80b21e0fa1fccbe38246677", + "sha256:367ff945bc0950ad9634591e2afe50bf2222bc4fad1088a386c4bb700888026e", + "sha256:6df87698022aef2596bffdfecc96d656db59c8d719708c8a471daa815ee61656", + "sha256:341824d8c9ad53fc43cca3fa9407f294125fa258592f7676640396501448e57e", + "sha256:64896a6b3368c959b8096b655e46f03dfa65b96745249f374bd6a35705cc3489", + "sha256:1f3e5a52cab6daa3d432c7b0de0a14109be39d2bfaad033ee5de4a3d3e11dcdf", + "sha256:da4d4fbe059b0453e726d6d993760065d69b823a27efc3040402a6fcfe6a1ed9" ], - "index": "pypi", "version": "==4.0.1" }, "yarl": { "hashes": [ - "sha256:045dbba18c9142278113d5dc62622978a6f718ba662392d406141c59b540c514", + "sha256:d9ca55a5a297408f08e5401c23ad22bd9f580dab899212f0d5dc1830f0909404", "sha256:17e57a495efea42bcfca08b49e16c6d89e003acd54c99c903ea1cb3de0ba1248", - "sha256:213e8f54b4a942532d6ac32314c69a147d3b82fa1725ca05061b7c1a19a1d9b1", "sha256:3353fae45d93cc3e7e41bfcb1b633acc37db821d368e660b03068dbfcf68f8c8", "sha256:51a084ff8756811101f8b5031a14d1c2dd26c666976e1b18579c6b1c8761a102", - "sha256:5580f22ac1298261cd24e8e584180d83e2cca9a6167113466d2d16cb2aa1f7b1", - "sha256:64727a2593fdba5d6ef69e94eba793a196deeda7152c7bd3a64edda6b1f95f6e", - "sha256:6e75753065c310befab71c5077a59b7cb638d2146b1cfbb1c3b8f08b51362714", + "sha256:045dbba18c9142278113d5dc62622978a6f718ba662392d406141c59b540c514", + "sha256:213e8f54b4a942532d6ac32314c69a147d3b82fa1725ca05061b7c1a19a1d9b1", "sha256:7236eba4911a5556b497235828e7a4bc5d90957efa63b7c4b3e744d2d2cf1b94", - "sha256:a69dd7e262cdb265ac7d5e929d55f2f3d07baaadd158c8f19caebf8dde08dfe8", - "sha256:d9ca55a5a297408f08e5401c23ad22bd9f580dab899212f0d5dc1830f0909404", + "sha256:e9a6a319c4bbfb57618f207e86a7c519ab0f637be3d2366e4cdac271577834b8", + "sha256:6e75753065c310befab71c5077a59b7cb638d2146b1cfbb1c3b8f08b51362714", + "sha256:64727a2593fdba5d6ef69e94eba793a196deeda7152c7bd3a64edda6b1f95f6e", + "sha256:5580f22ac1298261cd24e8e584180d83e2cca9a6167113466d2d16cb2aa1f7b1", "sha256:e072edbd1c5628c0b8f97d00cf6c9fcd6a4ee2b5ded10d463fcb6eaa066cf40c", - "sha256:e9a6a319c4bbfb57618f207e86a7c519ab0f637be3d2366e4cdac271577834b8" + "sha256:a69dd7e262cdb265ac7d5e929d55f2f3d07baaadd158c8f19caebf8dde08dfe8" ], "version": "==1.1.1" } @@ -164,15 +181,15 @@ "develop": { "attrs": { "hashes": [ - "sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9", - "sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450" + "sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450", + "sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9" ], "version": "==17.4.0" }, "bandit": { "hashes": [ - "sha256:cb977045497f83ec3a02616973ab845c829cdab8144ce2e757fe031104a9abd4", - "sha256:de4cc19d6ba32d6f542c6a1ddadb4404571347d83ef1ed1e7afb7d0b38e0c25b" + "sha256:de4cc19d6ba32d6f542c6a1ddadb4404571347d83ef1ed1e7afb7d0b38e0c25b", + "sha256:cb977045497f83ec3a02616973ab845c829cdab8144ce2e757fe031104a9abd4" ], "version": "==1.4.0" }, @@ -185,8 +202,8 @@ }, "chardet": { "hashes": [ - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691", + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae" ], "version": "==3.0.4" }, @@ -201,30 +218,27 @@ "hashes": [ "sha256:65e13cf878d7aff129f1461c13cb5fd1bb6dfe66bb5327e09379c3877763280c" ], - "index": "pypi", "version": "==0.1.9" }, "dparse": { "hashes": [ - "sha256:7c9f9175d8fd83aed6d31a16c1a3ba4c38189120f1df416b46029d940b4ef582", - "sha256:e4b479dd4d6078ba5f087b28447a50eee0caed57f135b0f5a5e5d5024390f41d" + "sha256:e4b479dd4d6078ba5f087b28447a50eee0caed57f135b0f5a5e5d5024390f41d", + "sha256:7c9f9175d8fd83aed6d31a16c1a3ba4c38189120f1df416b46029d940b4ef582" ], "version": "==0.2.1" }, "flake8": { "hashes": [ - "sha256:7253265f7abd8b313e3892944044a365e3f4ac3fcdcfb4298f55ee9ddf188ba0", - "sha256:c7841163e2b576d435799169b78703ad6ac1bbb0f199994fc05f700b2a90ea37" + "sha256:c7841163e2b576d435799169b78703ad6ac1bbb0f199994fc05f700b2a90ea37", + "sha256:7253265f7abd8b313e3892944044a365e3f4ac3fcdcfb4298f55ee9ddf188ba0" ], - "index": "pypi", "version": "==3.5.0" }, "flake8-bandit": { "hashes": [ - "sha256:24572dc2181c967bec1e7767c1a1faa4921f3d5a4cf9f84a78e2a555ca6c442a", - "sha256:345f5e61cd5eaf354156d7b45173fd14f6e31d35391d884c3222597a363c61ca" + "sha256:345f5e61cd5eaf354156d7b45173fd14f6e31d35391d884c3222597a363c61ca", + "sha256:24572dc2181c967bec1e7767c1a1faa4921f3d5a4cf9f84a78e2a555ca6c442a" ], - "index": "pypi", "version": "==1.0.1" }, "flake8-bugbear": { @@ -232,7 +246,6 @@ "sha256:541746f0f3b2f1a8d7278e1d2d218df298996b60b02677708560db7c7e620e3b", "sha256:5f14a99d458e29cb92be9079c970030e0dd398b2decb179d76d39a5266ea1578" ], - "index": "pypi", "version": "==18.2.0" }, "flake8-import-order": { @@ -240,7 +253,6 @@ "sha256:40d2a39ed91e080f3285f4c16256b252d7c31070e7f11b7854415bb9f924ea81", "sha256:68d430781a9ef15c85a0121500cf8462f1a4bc7672acb2a32bfdbcab044ae0b7" ], - "index": "pypi", "version": "==0.17.1" }, "flake8-polyfill": { @@ -255,42 +267,39 @@ "sha256:68ea72a1a5b75e7018cae44d14f32473c798cf73d75cbaed86c6a9a907b770b2", "sha256:774d56103d9242ed968897455ef49b7d6de272000cfa83de5814273a868832f1" ], - "index": "pypi", "version": "==0.2.3" }, "flake8-tidy-imports": { "hashes": [ - "sha256:5fc28c82bba16abb4f1154dc59a90487f5491fbdb27e658cbee241e8fddc1b91", - "sha256:c05c9f7dadb5748a04b6fa1c47cb6ae5a8170f03cfb1dca8b37aec58c1ee6d15" + "sha256:c05c9f7dadb5748a04b6fa1c47cb6ae5a8170f03cfb1dca8b37aec58c1ee6d15", + "sha256:5fc28c82bba16abb4f1154dc59a90487f5491fbdb27e658cbee241e8fddc1b91" ], - "index": "pypi", "version": "==1.1.0" }, "flake8-todo": { "hashes": [ "sha256:6e4c5491ff838c06fe5a771b0e95ee15fc005ca57196011011280fc834a85915" ], - "index": "pypi", "version": "==0.7" }, "gitdb2": { "hashes": [ - "sha256:b60e29d4533e5e25bb50b7678bbc187c8f6bcff1344b4f293b2ba55c85795f09", - "sha256:cf9a4b68e8c4da8d42e48728c944ff7af2d8c9db303ac1ab32eac37aa4194b0e" + "sha256:cf9a4b68e8c4da8d42e48728c944ff7af2d8c9db303ac1ab32eac37aa4194b0e", + "sha256:b60e29d4533e5e25bb50b7678bbc187c8f6bcff1344b4f293b2ba55c85795f09" ], "version": "==2.0.3" }, "gitpython": { "hashes": [ - "sha256:ad61bc25deadb535b047684d06f3654c001d9415e1971e51c9c20f5b510076e9", - "sha256:b8367c432de995dc330b5b146c5bfdc0926b8496e100fda6692134e00c0dcdc5" + "sha256:05069e26177c650b3cb945dd543a7ef7ca449f8db5b73038b465105673c1ef61", + "sha256:c47cc31af6e88979c57a33962cbc30a7c25508d74a1b3a19ec5aa7ed64b03129" ], - "version": "==2.1.8" + "version": "==2.1.9" }, "idna": { "hashes": [ - "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f", - "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4" + "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4", + "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f" ], "version": "==2.6" }, @@ -310,15 +319,15 @@ }, "pbr": { "hashes": [ - "sha256:05f61c71aaefc02d8e37c0a3eeb9815ff526ea28b3b76324769e6158d7f95be1", - "sha256:60c25b7dfd054ef9bb0ae327af949dd4676aa09ac3a9471cdc871d8a9213f9ac" + "sha256:60c25b7dfd054ef9bb0ae327af949dd4676aa09ac3a9471cdc871d8a9213f9ac", + "sha256:05f61c71aaefc02d8e37c0a3eeb9815ff526ea28b3b76324769e6158d7f95be1" ], "version": "==3.1.1" }, "pycodestyle": { "hashes": [ - "sha256:682256a5b318149ca0d2a9185d365d8864a768a28db66a84a2ea946bcc426766", - "sha256:6c4245ade1edfad79c3446fadfc96b0de2759662dc29d07d80a6f27ad1ca6ba9" + "sha256:6c4245ade1edfad79c3446fadfc96b0de2759662dc29d07d80a6f27ad1ca6ba9", + "sha256:682256a5b318149ca0d2a9185d365d8864a768a28db66a84a2ea946bcc426766" ], "version": "==2.3.1" }, @@ -331,32 +340,32 @@ }, "pyparsing": { "hashes": [ + "sha256:fee43f17a9c4087e7ed1605bd6df994c6173c1e977d7ade7b651292fab2bd010", "sha256:0832bcf47acd283788593e7a0f542407bd9550a55a8a8435214a1960e04bcb04", - "sha256:281683241b25fe9b80ec9d66017485f6deff1af5cde372469134b56ca8447a07", - "sha256:8f1e18d3fd36c6795bb7e02a39fd05c611ffc2596c1e0d995d34d67630426c18", "sha256:9e8143a3e15c13713506886badd96ca4b579a87fbdf49e550dbfc057d6cb218e", + "sha256:281683241b25fe9b80ec9d66017485f6deff1af5cde372469134b56ca8447a07", "sha256:b8b3117ed9bdf45e14dcc89345ce638ec7e0e29b2b579fa1ecf32ce45ebac8a5", - "sha256:e4d45427c6e20a59bf4f88c639dcc03ce30d193112047f94012102f235853a58", - "sha256:fee43f17a9c4087e7ed1605bd6df994c6173c1e977d7ade7b651292fab2bd010" + "sha256:8f1e18d3fd36c6795bb7e02a39fd05c611ffc2596c1e0d995d34d67630426c18", + "sha256:e4d45427c6e20a59bf4f88c639dcc03ce30d193112047f94012102f235853a58" ], "version": "==2.2.0" }, "pyyaml": { "hashes": [ - "sha256:0c507b7f74b3d2dd4d1322ec8a94794927305ab4cebbe89cc47fe5e81541e6e8", - "sha256:16b20e970597e051997d90dc2cddc713a2876c47e3d92d59ee198700c5427736", "sha256:3262c96a1ca437e7e4763e2843746588a965426550f3797a79fca9c6199c431f", - "sha256:326420cbb492172dec84b0f65c80942de6cedb5233c413dd824483989c000608", - "sha256:4474f8ea030b5127225b8894d626bb66c01cda098d47a2b0d3429b6700af9fd8", + "sha256:16b20e970597e051997d90dc2cddc713a2876c47e3d92d59ee198700c5427736", + "sha256:e863072cdf4c72eebf179342c94e6989c67185842d9997960b3e69290b2fa269", + "sha256:bc6bced57f826ca7cb5125a10b23fd0f2fff3b7c4701d64c439a300ce665fff8", + "sha256:c01b880ec30b5a6e6aa67b09a2fe3fb30473008c85cd6a67359a1b15ed6d83a4", + "sha256:827dc04b8fa7d07c44de11fabbc888e627fa8293b695e0f99cb544fdfa1bf0d1", "sha256:592766c6303207a20efc445587778322d7f73b161bd994f227adaa341ba212ab", - "sha256:5ac82e411044fb129bae5cfbeb3ba626acb2af31a8d17d175004b70862a741a7", "sha256:5f84523c076ad14ff5e6c037fe1c89a7f73a3e04cf0377cb4d017014976433f3", - "sha256:827dc04b8fa7d07c44de11fabbc888e627fa8293b695e0f99cb544fdfa1bf0d1", + "sha256:0c507b7f74b3d2dd4d1322ec8a94794927305ab4cebbe89cc47fe5e81541e6e8", "sha256:b4c423ab23291d3945ac61346feeb9a0dc4184999ede5e7c43e1ffb975130ae6", - "sha256:bc6bced57f826ca7cb5125a10b23fd0f2fff3b7c4701d64c439a300ce665fff8", - "sha256:c01b880ec30b5a6e6aa67b09a2fe3fb30473008c85cd6a67359a1b15ed6d83a4", "sha256:ca233c64c6e40eaa6c66ef97058cdc80e8d0157a443655baa1b2966e812807ca", - "sha256:e863072cdf4c72eebf179342c94e6989c67185842d9997960b3e69290b2fa269" + "sha256:4474f8ea030b5127225b8894d626bb66c01cda098d47a2b0d3429b6700af9fd8", + "sha256:326420cbb492172dec84b0f65c80942de6cedb5233c413dd824483989c000608", + "sha256:5ac82e411044fb129bae5cfbeb3ba626acb2af31a8d17d175004b70862a741a7" ], "version": "==3.12" }, @@ -372,13 +381,12 @@ "sha256:9fb74211a0a0ab09541fe894293d66a558b6138a9fe8ebabc8cf56670e8a009c", "sha256:ff0c4b76ad791d33825e36c41671ea45330d438921e5395903c0e87e576a377a" ], - "index": "pypi", "version": "==1.7.0" }, "six": { "hashes": [ - "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", - "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" + "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb", + "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9" ], "version": "==1.11.0" }, diff --git a/README.md b/README.md index 76c385a4..7ab38d46 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,25 @@ This is the repository for all code relating to our first code jam, in March 201 **This code jam runs from the 23rd of March to the 25th of March, measured using the UTC timezone.** Make sure you open your pull request by then. Once the deadline is up, stop pushing commits - we will not accept any submissions made after this date. +## Credentials +In order to run this bot on your own, you will need a couple credentials, stored as environment variables. Since we are using `pipenv`, we are storing these in the `.env` file in the root directory. +Your .env should look like this: +``` +BOT_TOKEN=bottoken +ACCESS_TOKEN=accesstoken +YOUTUBE_DATA_KEY=youtubekey +``` +The `BOT_TOKEN` is the Discord token. Find how to obtain this [here](https://github.com/discord-python/code-jam-1/blob/master/doc/bot-setup.md). + +The `ACCESS_TOKEN` is a token to access our data API. Get in touch with @prithajnath to receive a token. + +The `YOUTUBE_DATA_KEY` is an API key from Google. Specifically, this uses the [YouTube Data API v3](https://console.developers.google.com/apis/credentials). Generate a key here, which will be associated with your Google account. + +## APIs used +* [Qwant](https://www.qwant.com/) (for snake pics) +* [Our custom Snake API](https://github.com/prithajnath/snake) (scraped a page with bs4 and saved it in a db) + + ## How To Participate First things first - set up your repository. Read [this guide on our site](https://pythondiscord.com/info/jams) for information on how to set yourself up for a code jam. diff --git a/bot/cogs/resources/facts.json b/bot/cogs/resources/facts.json new file mode 100644 index 00000000..6f7c27a8 --- /dev/null +++ b/bot/cogs/resources/facts.json @@ -0,0 +1,53 @@ +{ + "facts": { + "Snakes are carnivores (meat eaters).":"dangerous", + "Snakes don’t have eyelids.":"interesting", + "Snakes can’t bite food so have to swallow it whole.":"dangerous", + "Snakes have flexible jaws which allow them to eat prey bigger than their head!":"dangerous", + "Snakes are found on every continent of the world except Antarctica.":"interesting", + "Snakes have internal ears but not external ones.":"interesting", + "Snakes used in snake charming performances respond to movement, not sound.":"interesting", + "There are around 3000 different species of snake.":"interesting", + "Snakes have a unique anatomy which allows them to swallow and digest large prey.":"dangerous", + "Snakes are covered in scales.":"interesting", + "Snakeskin is smooth and dry.":"interesting", + "Snakes shed their skin a number of times a year in a process that usually lasts a few days.":"interesting", + "Snakes smell with their tongue.":"interesting", + "Pythons kill their prey by tightly wrapping around it and suffocating it in a process called constriction.":"dangerous", + "Some sea snakes can breathe partially through their skin, allowing for longer dives underwater.":"interesting", + "Some animals, such as the Mongoose, are immune to snake venom.":"interesting", + "While snakes do not have external ears or eardrums, their skin, muscles, and bones carry sound vibrations to their inner ears.":"interesting", + "Rattlesnake rattles are made of rings of keratin, which is the same material as human hair and fingernails. A rattler will add a new ring each time it sheds its skin.":"interesting", + "Some snakes have over 200 teeth. The teeth aren’t used for chewing but they point backward to prevent prey from escaping the snake’s throat.":"interesting", + "There are five recognized species of flying snakes. Growing up to 4 feet, some types can glide up to 330 feet through the air.":"interesting", + "Snakes do not lap up water like mammals do. Instead, they dunk their snouts underwater and use their throats to pump water into their stomachs.":"interesting", + "A snake’s fangs usually last about 6–10 weeks. When a fang wears out, a new one grows in its place.":"interesting", + "Snakes typically need to eat only 6–30 meals each year to be healthy.":"interesting", + "If the temperature reaches below 50° Fahrenheit, a snake’s body does not work properly.":"interesting", + "The Gaboon viper has the longest fangs of any snake, reaching about 2 inches (5 cm) long.":"dangerous", + "The longest snake ever recorded is the reticulated python. It can reach over 33 feet long, which is big enough to swallow a pig, a deer, or even a person.":"dangerous", + "Some venomous snakes have died after biting and poisoning themselves by mistake.":"self-harm", + "While a snake cannot hear the music of a snake charmer, the snake responds to the vibrations of the charmer’s tapping foot or to the movement of the flute.":"interesting", + "Most snakes are not harmful to humans and they help balance the ecosystem by keeping the population of rats, mice, and birds under control.":"interesting", + "Most snakes have an elongated right lung, many have a smaller left lung, and a few even have a third lung. They do not have a sense of taste, and most of their organs are organized linearly.":"interesting", + "Snakes kill over 40,000 people a year—though, with unreported incidents, the total may be over 100,000. About half of these deaths are in India.":"dangerous", + "Some members of the U.S. Army Special Forces are taught to kill and eat snakes during their survival training, which has earned them the nickname “Snake Eaters.”":"dangerous" + }, + "gifs":{ + "dangerous":[ + "https://media.giphy.com/media/2yP1jNgjNAkvu/giphy.gif", + "https://media.giphy.com/media/OGufyodtN4NUs/giphy.gif", + "https://media.giphy.com/media/tP2fZCu4K9Yac/giphy.gif", + "https://media.giphy.com/media/ldC6st7Bz3lZK/giphy.gif" + ], + "self-harm":[ + "https://media.giphy.com/media/A6r0BbR2ob1GE/giphy.gif", + "https://media.giphy.com/media/dFEd78w0sJNwA/giphy.gif" + ], + "interesting":[ + "https://media.giphy.com/media/10lKFp5Y03YITK/giphy.gif", + "https://media.giphy.com/media/ZPtGZIbpA1Z0Q/giphy.gif", + "https://media.giphy.com/media/hfV9dWY07x960/giphy.gif" + ] + } +} diff --git a/bot/cogs/resources/zen.json b/bot/cogs/resources/zen.json new file mode 100644 index 00000000..f573fe08 --- /dev/null +++ b/bot/cogs/resources/zen.json @@ -0,0 +1,33 @@ +{ + "zen" : [ + "Beautiful is better than ugly.", + "Explicit is better than implicit.", + "Simple is better than complex.", + "Complex is better than complicated.", + "Flat is better than nested.", + "Sparse is better than dense.", + "Readability counts.", + "Special cases aren't special enough to break the rules. Although practicality beats purity.", + "Errors should never pass silently. Unless explicitly silenced.", + "In the face of ambiguity, refuse the temptation to guess.", + "There should be one-- and preferably only one --obvious way to do it.", + "Although that way may not be obvious at first unless you're Dutch.", + "Now is better than never.", + "Although never is often better than *right* now.", + "If the implementation is hard to explain, it's a bad idea.", + "If the implementation is easy to explain, it may be a good idea.", + "Namespaces are one honking great idea -- let's do more of those!" + ], + + "gif":[ + "https://media.giphy.com/media/jCodV34MoczjW/giphy.gif", + "https://media.giphy.com/media/ZLF9Loju0q3MA/giphy.gif", + "https://media.giphy.com/media/v4NCChJtoH076/giphy.gif", + "https://media.giphy.com/media/3o6Ztfi66HECEU0Z4k/giphy.gif", + "https://media.giphy.com/media/HNSv7wrNUK5Ko/giphy.gif", + "https://media.giphy.com/media/3oFzmdjqH15YebLQ52/giphy.gif", + "https://media.giphy.com/media/2PIjvGv9DKtJ6/giphy.gif", + "https://media.giphy.com/media/26DN0U3SqKDG2fTFe/giphy.gif", + "https://media.giphy.com/media/3o6EhXODzc79cnZfRC/giphy.gif" + ] +} diff --git a/bot/cogs/snakes.py b/bot/cogs/snakes.py index c9ed8042..521c628c 100644 --- a/bot/cogs/snakes.py +++ b/bot/cogs/snakes.py @@ -1,9 +1,18 @@ # coding=utf-8 +import json import logging +import os +import random +import urllib from typing import Any, Dict +import aiohttp + +import discord from discord.ext.commands import AutoShardedBot, Context, command +from titlecase import titlecase + log = logging.getLogger(__name__) @@ -15,6 +24,42 @@ class Snakes: def __init__(self, bot: AutoShardedBot): self.bot = bot + async def get_snek_qwant_json(self, snake_name: str) -> str: + """ + Gets the json from Unsplash for a given snake query + :param snake_name: name of the snake + :return: the full JSON from the search API + """ + head = { + 'user-agent': ('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) ' + 'AppleWebKit/537.36 (KHTML, like Gecko) ' + 'Chrome/45.0.2454.101 Safari/537.36'), + } + url = f'https://api.qwant.com/api/search/images?count=5&offset=1&q={urllib.parse.quote(snake_name)}+snake' + async with aiohttp.ClientSession() as session: + async with session.get(url, headers=head) as response: + response = await response.json() + return response + + async def get_snek_image(self, name: str) -> str: + """ + Gets the URL of a snake image + :param name: name of snake + :return: image url + """ + json_response = await self.get_snek_qwant_json(name) + result_count = len(json_response["data"]["result"]["items"]) + if result_count == 1: + rand = 0 + else: + rand = random.randint(0, 2) # prevents returning the same image every time + try: + choice = str(json_response["data"]["result"]["items"][rand]["media"]) + except IndexError: + # if no(t enough) images are returned... + return 'https://dksignmt.com/wp-content/uploads/2015/01/404-Im%C3%A1gen-14.png' # 404 image + return choice + async def get_snek(self, name: str = None) -> Dict[str, Any]: """ Go online and fetch information about a snake @@ -28,11 +73,47 @@ async def get_snek(self, name: str = None) -> Dict[str, Any]: :param name: Optional, the name of the snake to get information for - omit for a random snake :return: A dict containing information on a snake """ + base_url = "https://protected-reef-75100.herokuapp.com/" + random_url = 'https://protected-reef-75100.herokuapp.com/random_snake' + search_url = base_url + 'search' + token = os.getenv('ACCESS_TOKEN') + headers = {'Authorization': f'Token {token}'} + snake_info = {} + if not name: + # get a random snake... + async with aiohttp.ClientSession() as session: + async with session.get(random_url, headers=headers) as response: + response = await response.read() + snake_info = json.loads(response.decode("utf-8")) + snake_info['matches_count'] = 1 + else: + params = {'snake': name} + async with aiohttp.ClientSession() as session: + async with session.get(search_url, headers=headers, params=params) as response: + # search snake endpoint something... + response = await response.read() + data = json.loads(response.decode("utf-8")) + try: + rand = random.randint(0, len(data) - 1) + except ValueError: + # handle the scenario with an empty range of (0,0) + rand = 0 + try: + snake_info = data[rand] + except IndexError: + # handles if there is no match in the database + snake_info['pass'] = False + return snake_info + snake_info['matches_count'] = len(data) - @command() + snake_info['image_url'] = await self.get_snek_image(snake_info['common_name']) + snake_info['pass'] = True # successful data retrieval + return snake_info + + @command(aliases=["g", "snake.get", "snake.g"]) async def get(self, ctx: Context, name: str = None): """ - Go online and fetch information about a snake + Gets information and an image about a snake This should make use of your `get_snek` method, using it to get information about a snake. This information should be sent back to Discord in an embed. @@ -40,9 +121,169 @@ async def get(self, ctx: Context, name: str = None): :param ctx: Context object passed from discord.py :param name: Optional, the name of the snake to get information for - omit for a random snake """ + embed = discord.Embed(color=0x3E885B) + if name and name.lower() == "python": + # handle Python special case + embed.add_field( + name="Python (programming language)", + value=( + "*Guido van Rossum*\n\n" + "This language is neither dangerous nor venomous and can be found in software globally" + ), + inline=False + ) + embed.set_image(url=await self.get_snek_image("python programming language")) + else: + snek_info = await self.get_snek(name) + if not snek_info['pass']: + embed = discord.Embed(color=0xDD3D5A) + embed.add_field( + name="We Couldn't Find That :snake:", + value=f':x: "{name}" didn\'t match anything in our database :frowning:', + inline=False + ) + await ctx.channel.send(embed=embed) + return # break out of rest of method + + if snek_info['is_venomous']: + # if the snake is venomous -- use the fancy check icon + venom_info = f":white_check_mark: venomous" + else: + # if the snake is not venomous -- use the fancy not allowed icon + venom_info = f":no_entry_sign: NOT venomous" + + if not snek_info['locations']: + # if no location field + location_info = '' + else: + location_info = f"\n\n:globe_with_meridians: Found in {snek_info['locations']}" + additional_info = '' # required to prevent referencing before assignment + if snek_info['matches_count'] and snek_info['matches_count'] > 1: + additional_info = f"\n\n" \ + f"This search matched {snek_info['matches_count']} snakes. " \ + f"Try creating a more specific query for information about a particular snake. " \ + f"(This is a random selection from the {snek_info['matches_count']}.)" + embed.add_field( + name=titlecase(snek_info['common_name']), + value=( + f":microscope: *{titlecase(snek_info['scientific_name'])}*\n\n" + f"{venom_info}" + f"{location_info}" + f"{additional_info}" + ), + inline=False + ) + embed.set_image(url=snek_info['image_url']) + await ctx.channel.send(embed=embed) # Any additional commands can be placed here. Be creative, but keep it to a reasonable amount! + @command(aliases=["t", "zen"]) + async def this(self, ctx: Context): + """ + Gets a random quote from the Zen of Python. Inspired by the Python this module + :param ctx: Context object passed from discord.py + """ + + em = discord.Embed(color=0x399600) + with open('bot/cogs/resources/zen.json', 'r', encoding="utf8") as f: + data = json.load(f) + zen_quote = random.choice(data['zen']) + a = zen_quote.split() + b = [ + "..." * random.randint(1, 3) + "..*hi" + "s" * random.randint(3, 7) + + "*" + "..." * random.randint(1, 3) for _ in range(len(a)) + ] + message = ''.join(list(map( + lambda x: x[0] + x[1], list(zip(a, b))) + )) + + em.add_field( + name="The Zen of Python says...", + value=message, + inline=False + ) + + em.set_image(url=random.choice(data['gif'])) + await ctx.channel.send( + content=ctx.message.author.mention, + embed=em + ) + + @command(aliases=["f"]) + async def fact(self, ctx: Context, cat: str = None): + """ + Gets a random fact about snakes + :param cat: the category for the given fact + :param ctx: Context object passed from discord.py + """ + message_suffix = { + "dangerous": ["Yikes!!", "Oh my!"], + "interesting": ["Pretty cool!", "Whoah!!", "Pretty sick!!"], + "self-harm": ["Ouch!!"] + } + _fact = self.get_snek_fact(cat) + em = discord.Embed(color=0x399600) + em.add_field( + name=titlecase(f"{_fact['cat']} snake fact"), + value=f"{_fact['message']} {random.choice(message_suffix[_fact['cat']])}", + inline=False + ) + em.set_image(url=_fact['gif']) + await ctx.channel.send( + content=ctx.message.author.mention, + embed=em + ) + + def get_snek_fact(self, cat: str) -> Dict[str, any]: + with open('bot/cogs/resources/facts.json', 'r', encoding="utf8") as f: + data = json.load(f) + if cat: + facts_with_cat = list(filter( + lambda x: data['facts'][x] == cat.lower(), + list(data['facts'].keys()) + )) + random_fact = random.choice(facts_with_cat) + else: + random_fact = random.choice(list(data['facts'].keys())) + gif_cat = data['facts'][random_fact] + gif_url = random.choice(data['gifs'][gif_cat]) + return {'message': random_fact, 'gif': gif_url, 'cat': gif_cat} + + async def get_video_json(self, search: str) -> str: + """ + Gets the json from the YouTube search API (YouTube Data API v3), with an optional search query + :param search: optional param for a user to search a specific type/name of snake videos + :return: the full JSON from the search API, as a string + """ + youtube_key = os.getenv('YOUTUBE_DATA_KEY') # generated: https://console.developers.google.com/apis/credentials + if search: + query = search + ' snake' + else: + query = 'snake' + url = f'https://www.googleapis.com/youtube/v3/search' \ + f'?part=snippet&q={urllib.parse.quote(query)}&type=video&key={youtube_key}' + async with aiohttp.ClientSession() as session: + async with session.get(url) as response: + response = await response.json() + return response['items'] + + @command(aliases=["v"]) + async def video(self, ctx: Context, name: str = None): + """ + Gets a YouTube video about snakes + :param name: Optional, a name of a snake. Used to search for videos with that name + :param ctx: Context object passed from discord.py + :return: + """ + data = await self.get_video_json(name) + num = random.randint(0, 5) # 5 videos are returned from the api + youtube_base_url = 'https://www.youtube.com/watch?v=' + await ctx.channel.send( + content=f"{ctx.message.author.mention} Here's a Snake Video!" + f"\n{youtube_base_url}{data[num]['id']['videoId']}" + ) + def setup(bot): bot.add_cog(Snakes(bot)) diff --git a/sources.md b/sources.md new file mode 100644 index 00000000..bdd82e05 --- /dev/null +++ b/sources.md @@ -0,0 +1,11 @@ +# Sources / Credits + +## Snake DB Information +Data about various snakes, stored in our database +* [Snake Type](http://www.snaketype.com) +* uh another one + +## Snake Fun Facts +Random facts about snakes +* [Science Kids](http://www.sciencekids.co.nz/sciencefacts/animals/snake.html) +* [Fact Retriever](https://www.factretriever.com/snake-facts)