diff --git a/Pipfile.lock b/Pipfile.lock index 3d5bce5..a86bb16 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -16,17 +16,17 @@ "default": { "certifi": { "hashes": [ - "sha256:1f422849db327d534e3d0c5f02a263458c3955ec0aae4ff09b95f195c59f4edd", - "sha256:f05def092c44fbf25834a51509ef6e631dc19765ab8a57b4e7ab85531f0a9cf4" + "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c", + "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830" ], - "version": "==2020.11.8" + "version": "==2020.12.5" }, "h11": { "hashes": [ - "sha256:3c6c61d69c6f13d41f1b80ab0322f1872702a3ba26e12aa864c928f6a43fbaab", - "sha256:ab6c335e1b6ef34b205d5ca3e228c9299cc7218b049819ec84a388c2525e5d87" + "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6", + "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042" ], - "version": "==0.11.0" + "version": "==0.12.0" }, "h2": { "hashes": [ @@ -44,11 +44,10 @@ }, "httpcore": { "hashes": [ - "sha256:420700af11db658c782f7e8fda34f9dcd95e3ee93944dd97d78cb70247e0cd06", - "sha256:dd1d762d4f7c2702149d06be2597c35fb154c5eff9789a8c5823fbcf4d2978d6" + "sha256:37ae835fb370049b2030c3290e12ed298bf1473c41bb72ca4aa78681eba9b7c9", + "sha256:93e822cd16c32016b414b789aeff4e855d0ccbfc51df563ee34d4dbadbb3bcdc" ], - "markers": "python_version >= '3.6'", - "version": "==0.12.2" + "version": "==0.12.3" }, "httpx": { "extras": [ @@ -70,10 +69,10 @@ }, "idna": { "hashes": [ - "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", - "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" + "sha256:5205d03e7bcbb919cc9c19885f9920d622ca52448306f2377daede5cf3faac16", + "sha256:c5b02147e01ea9920e6b0a3f1f7bb833612d507592c837a6c49552768f4054e1" ], - "version": "==2.10" + "version": "==3.1" }, "rfc3986": { "extras": [ @@ -90,79 +89,127 @@ "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663", "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de" ], - "markers": "python_version >= '3.5'", "version": "==1.2.0" } }, "develop": { - "atomicwrites": { - "hashes": [ - "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197", - "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a" - ], - "markers": "sys_platform == 'win32'", - "version": "==1.4.0" - }, "attrs": { "hashes": [ "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6", "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==20.3.0" }, "bleach": { "hashes": [ - "sha256:52b5919b81842b1854196eaae5ca29679a2f2e378905c346d3ca8227c2c66080", - "sha256:9f8ccbeb6183c6e6cddea37592dfb0167485c1e3b13b3363bc325aa8bda3adbd" + "sha256:6123ddc1052673e52bab52cdc955bcb57a015264a1c57d37bea2f6b817af0125", + "sha256:98b3170739e5e83dd9dc19633f074727ad848cbedb6026708c8ac2d3b697a433" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==3.2.1" + "index": "pypi", + "version": "==3.3.0" }, "certifi": { "hashes": [ - "sha256:1f422849db327d534e3d0c5f02a263458c3955ec0aae4ff09b95f195c59f4edd", - "sha256:f05def092c44fbf25834a51509ef6e631dc19765ab8a57b4e7ab85531f0a9cf4" - ], - "version": "==2020.11.8" + "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c", + "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830" + ], + "version": "==2020.12.5" + }, + "cffi": { + "hashes": [ + "sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e", + "sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d", + "sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a", + "sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec", + "sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362", + "sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668", + "sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c", + "sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b", + "sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06", + "sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698", + "sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2", + "sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c", + "sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7", + "sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009", + "sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03", + "sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b", + "sha256:7ef7d4ced6b325e92eb4d3502946c78c5367bc416398d387b39591532536734e", + "sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909", + "sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53", + "sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35", + "sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26", + "sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b", + "sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01", + "sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb", + "sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293", + "sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd", + "sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d", + "sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3", + "sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d", + "sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e", + "sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca", + "sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d", + "sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775", + "sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375", + "sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b", + "sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b", + "sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f" + ], + "version": "==1.14.4" }, "chardet": { "hashes": [ - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa", + "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5" ], - "version": "==3.0.4" + "version": "==4.0.0" }, "colorama": { "hashes": [ "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b", "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2" ], - "markers": "sys_platform == 'win32'", "version": "==0.4.4" }, + "cryptography": { + "hashes": [ + "sha256:0003a52a123602e1acee177dc90dd201f9bb1e73f24a070db7d36c588e8f5c7d", + "sha256:0e85aaae861d0485eb5a79d33226dd6248d2a9f133b81532c8f5aae37de10ff7", + "sha256:594a1db4511bc4d960571536abe21b4e5c3003e8750ab8365fafce71c5d86901", + "sha256:69e836c9e5ff4373ce6d3ab311c1a2eed274793083858d3cd4c7d12ce20d5f9c", + "sha256:788a3c9942df5e4371c199d10383f44a105d67d401fb4304178020142f020244", + "sha256:7e177e4bea2de937a584b13645cab32f25e3d96fc0bc4a4cf99c27dc77682be6", + "sha256:83d9d2dfec70364a74f4e7c70ad04d3ca2e6a08b703606993407bf46b97868c5", + "sha256:84ef7a0c10c24a7773163f917f1cb6b4444597efd505a8aed0a22e8c4780f27e", + "sha256:9e21301f7a1e7c03dbea73e8602905a4ebba641547a462b26dd03451e5769e7c", + "sha256:9f6b0492d111b43de5f70052e24c1f0951cb9e6022188ebcb1cc3a3d301469b0", + "sha256:a69bd3c68b98298f490e84519b954335154917eaab52cf582fa2c5c7efc6e812", + "sha256:b4890d5fb9b7a23e3bf8abf5a8a7da8e228f1e97dc96b30b95685df840b6914a", + "sha256:c366df0401d1ec4e548bebe8f91d55ebcc0ec3137900d214dd7aac8427ef3030", + "sha256:dc42f645f8f3a489c3dd416730a514e7a91a59510ddaadc09d04224c098d3302" + ], + "version": "==3.3.1" + }, "docutils": { "hashes": [ "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==0.16" }, "h11": { "hashes": [ - "sha256:3c6c61d69c6f13d41f1b80ab0322f1872702a3ba26e12aa864c928f6a43fbaab", - "sha256:ab6c335e1b6ef34b205d5ca3e228c9299cc7218b049819ec84a388c2525e5d87" + "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6", + "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042" ], - "version": "==0.11.0" + "version": "==0.12.0" }, "httpcore": { "hashes": [ - "sha256:420700af11db658c782f7e8fda34f9dcd95e3ee93944dd97d78cb70247e0cd06", - "sha256:dd1d762d4f7c2702149d06be2597c35fb154c5eff9789a8c5823fbcf4d2978d6" + "sha256:37ae835fb370049b2030c3290e12ed298bf1473c41bb72ca4aa78681eba9b7c9", + "sha256:93e822cd16c32016b414b789aeff4e855d0ccbfc51df563ee34d4dbadbb3bcdc" ], - "markers": "python_version >= '3.6'", - "version": "==0.12.2" + "version": "==0.12.3" }, "httpx": { "extras": [ @@ -177,10 +224,10 @@ }, "idna": { "hashes": [ - "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", - "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" + "sha256:5205d03e7bcbb919cc9c19885f9920d622ca52448306f2377daede5cf3faac16", + "sha256:c5b02147e01ea9920e6b0a3f1f7bb833612d507592c837a6c49552768f4054e1" ], - "version": "==2.10" + "version": "==3.1" }, "iniconfig": { "hashes": [ @@ -189,68 +236,76 @@ ], "version": "==1.1.1" }, + "jeepney": { + "hashes": [ + "sha256:7d59b6622675ca9e993a6bd38de845051d315f8b0c72cca3aef733a20b648657", + "sha256:aec56c0eb1691a841795111e184e13cad504f7703b9a64f63020816afa79a8ae" + ], + "markers": "sys_platform == 'linux'", + "version": "==0.6.0" + }, "keyring": { "hashes": [ - "sha256:12de23258a95f3b13e5b167f7a641a878e91eab8ef16fafc077720a95e6115bb", - "sha256:207bd66f2a9881c835dad653da04e196c678bf104f8252141d2d3c4f31051579" + "sha256:9acb3e1452edbb7544822b12fd25459078769e560fa51f418b6d00afaa6178df", + "sha256:9f44660a5d4931bdc14c08a1d01ef30b18a7a8147380710d8c9f9531e1f6c3c0" ], - "markers": "python_version >= '3.6'", - "version": "==21.5.0" + "version": "==22.0.1" }, "packaging": { "hashes": [ - "sha256:05af3bb85d320377db281cf254ab050e1a7ebcbf5410685a9a407e18a1f81236", - "sha256:eb41423378682dadb7166144a4926e443093863024de508ca5c9737d6bc08376" + "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5", + "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==20.7" + "version": "==20.9" }, "pkginfo": { "hashes": [ - "sha256:a6a4ac943b496745cec21f14f021bbd869d5e9b4f6ec06918cffea5a2f4b9193", - "sha256:ce14d7296c673dc4c61c759a0b6c14bae34e34eb819c0017bb6ca5b7292c56e9" + "sha256:029a70cb45c6171c329dfc890cde0879f8c52d6f3922794796e06f577bb03db4", + "sha256:9fdbea6495622e022cc72c2e5e1b735218e4ffb2a2a69cde2694a6c1f16afb75" ], - "version": "==1.6.1" + "version": "==1.7.0" }, "pluggy": { "hashes": [ "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.13.1" }, "py": { "hashes": [ - "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2", - "sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342" + "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3", + "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.9.0" + "version": "==1.10.0" + }, + "pycparser": { + "hashes": [ + "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0", + "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705" + ], + "version": "==2.20" }, "pygments": { "hashes": [ - "sha256:381985fcc551eb9d37c52088a32914e00517e57f4a21609f48141ba08e193fa0", - "sha256:88a0bbcd659fcb9573703957c6b9cff9fab7295e6e76db54c9d00ae42df32773" + "sha256:bc9591213a8f0e0ca1a5e68a479b4887fdc3e75d0774e5c71c31920c427de435", + "sha256:df49d09b498e83c1a73128295860250b0b7edd4c723a32e9bc0d295c7c2ec337" ], - "markers": "python_version >= '3.5'", - "version": "==2.7.2" + "version": "==2.7.4" }, "pyparsing": { "hashes": [ "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.4.7" }, "pytest": { "hashes": [ - "sha256:4288fed0d9153d9646bfcdf0c0428197dba1ecb27a33bb6e031d002fa88653fe", - "sha256:c0a7e94a8cdbc5422a51ccdad8e6f1024795939cc89159a0ae7f0b316ad3823e" + "sha256:9d1edf9e7d0b84d72ea3dbcdfd22b35fb543a5e8f2a60092dd578936bf63d7f9", + "sha256:b574b57423e818210672e07ca1fa90aaf194a4f63f3ab909a2c67ebb22913839" ], - "markers": "python_version >= '3.5'", - "version": "==6.1.2" + "version": "==6.2.2" }, "pytest-httpx": { "hashes": [ @@ -268,14 +323,6 @@ "index": "pypi", "version": "==3.3.1" }, - "pywin32-ctypes": { - "hashes": [ - "sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942", - "sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98" - ], - "markers": "sys_platform == 'win32'", - "version": "==0.2.0" - }, "readme-renderer": { "hashes": [ "sha256:267854ac3b1530633c2394ead828afcd060fc273217c42ac36b6be9c42cd9a9d", @@ -285,11 +332,10 @@ }, "requests": { "hashes": [ - "sha256:7f1a0b932f4a60a1a65caa4263921bb7d9ee911957e0ae4a23a6dd08185ad5f8", - "sha256:e786fa28d8c9154e6a4de5d46a1d921b8749f8b74e28bde23768e5e16eece998" + "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804", + "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==2.25.0" + "version": "==2.25.1" }, "requests-toolbelt": { "hashes": [ @@ -308,12 +354,19 @@ ], "version": "==1.4.0" }, + "secretstorage": { + "hashes": [ + "sha256:30cfdef28829dad64d6ea1ed08f8eff6aa115a77068926bcc9f5225d5a3246aa", + "sha256:5c36f6537a523ec5f969ef9fad61c98eb9e017bc601d811e53aa25bece64892f" + ], + "markers": "sys_platform == 'linux'", + "version": "==3.3.0" + }, "six": { "hashes": [ "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.15.0" }, "sniffio": { @@ -321,7 +374,6 @@ "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663", "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de" ], - "markers": "python_version >= '3.5'", "version": "==1.2.0" }, "toml": { @@ -329,16 +381,14 @@ "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.10.2" }, "tqdm": { "hashes": [ - "sha256:5c0d04e06ccc0da1bd3fa5ae4550effcce42fcad947b4a6cafa77bdc9b09ff22", - "sha256:9e7b8ab0ecbdbf0595adadd5f0ebbb9e69010e0bd48bbb0c15e550bf2a5292df" + "sha256:4621f6823bab46a9cc33d48105753ccbea671b68bab2c50a9f0be23d4065cb5a", + "sha256:fe3d08dd00a526850568d542ff9de9bbc2a09a791da3c334f3213d8d0bbbca65" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==4.54.0" + "version": "==4.56.0" }, "twine": { "hashes": [ @@ -350,11 +400,10 @@ }, "urllib3": { "hashes": [ - "sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08", - "sha256:d8ff90d979214d7b4f8ce956e80f4028fc6860e4431f731ea4a8c08f23f99473" + "sha256:1b465e494e3e0d8939b50680403e3aedaa2bc434b7d5af64dfd3c958d7f5ae80", + "sha256:de3eedaad74a2683334e282005cd8d7f22f4d55fa690a2a1020a416cb0a47e73" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", - "version": "==1.26.2" + "version": "==1.26.3" }, "webencodings": { "hashes": [ diff --git a/pytchat/__init__.py b/pytchat/__init__.py index 66b8530..736668d 100644 --- a/pytchat/__init__.py +++ b/pytchat/__init__.py @@ -2,7 +2,7 @@ pytchat is a lightweight python library to browse youtube livechat without Selenium or BeautifulSoup. """ __copyright__ = 'Copyright (C) 2019, 2020 taizan-hokuto' -__version__ = '0.5.2' +__version__ = '0.5.3' __license__ = 'MIT' __author__ = 'taizan-hokuto' __author_email__ = '55448286+taizan-hokuto@users.noreply.github.com' diff --git a/pytchat/core/pytchat.py b/pytchat/core/pytchat.py index 67dc976..93605e9 100644 --- a/pytchat/core/pytchat.py +++ b/pytchat/core/pytchat.py @@ -95,7 +95,10 @@ def _setup(self): """Fetch first continuation parameter, create and start _listen loop. """ - self.continuation = liveparam.getparam(self._video_id, past_sec=3) + self.continuation = liveparam.getparam( + self._video_id, + channel_id=util.get_channelid(httpx.Client(http2=True), self._video_id), + past_sec=3) def _get_chat_component(self): ''' Fetch chat data and store them into buffer, diff --git a/pytchat/core_async/livechat.py b/pytchat/core_async/livechat.py index 322fd16..655f43c 100644 --- a/pytchat/core_async/livechat.py +++ b/pytchat/core_async/livechat.py @@ -152,7 +152,11 @@ async def _startlisten(self): create and start _listen loop. """ if not self.continuation: - self.continuation = liveparam.getparam(self._video_id, 3) + self.continuation = liveparam.getparam( + self._video_id, + channel_id=util.get_channelid(httpx.Client(http2=True), self._video_id), + past_sec=3) + await self._listen(self.continuation) async def _listen(self, continuation): @@ -210,8 +214,11 @@ async def _check_pause(self, continuation): ''' self._pauser.put_nowait(None) if not self._is_replay: - continuation = liveparam.getparam( - self._video_id, 3, self._topchat_only) + async with httpx.AsyncClient(http2=True) as client: + continuation = await liveparam.getparam(self._video_id, + channel_id=util.get_channelid_async(client, self.video_id), + past_sec=3) + return continuation async def _get_contents(self, continuation, client, headers): diff --git a/pytchat/core_multithread/livechat.py b/pytchat/core_multithread/livechat.py index 4125852..153dce1 100644 --- a/pytchat/core_multithread/livechat.py +++ b/pytchat/core_multithread/livechat.py @@ -148,7 +148,10 @@ def _startlisten(self): create and start _listen loop. """ if not self.continuation: - self.continuation = liveparam.getparam(self._video_id, 3) + self.continuation = liveparam.getparam( + self._video_id, + channel_id=util.get_channelid(httpx.Client(http2=True), self._video_id), + past_sec=3) self._listen(self.continuation) def _listen(self, continuation): @@ -207,7 +210,9 @@ def _check_pause(self, continuation): self._pauser.put_nowait(None) if not self._is_replay: continuation = liveparam.getparam( - self._video_id, 3, self._topchat_only) + self._video_id, channel_id=util.get_channelid(httpx.Client(http2=True), self._video_id), + past_sec=3, topchat_only=self._topchat_only) + return continuation def _get_contents(self, continuation, client, headers): diff --git a/pytchat/paramgen/liveparam.py b/pytchat/paramgen/liveparam.py index 6302832..52997ac 100644 --- a/pytchat/paramgen/liveparam.py +++ b/pytchat/paramgen/liveparam.py @@ -5,11 +5,16 @@ from urllib.parse import quote -def _header(video_id) -> str: - return b64enc(enc.rs(1, enc.rs(1, enc.rs(1, video_id))) + enc.nm(4, 1)) +def _header(video_id, channel_id) -> str: + S1_3 = enc.rs(1, video_id) + S1_5 = enc.rs(1, channel_id) + enc.rs(2, video_id) + S1 = enc.rs(3, S1_3) + enc.rs(5, S1_5) + S3 = enc.rs(48687757, enc.rs(1, video_id)) + header_replay = enc.rs(1, S1) + enc.rs(3, S3) + enc.nm(4, 1) + return b64enc(header_replay) -def _build(video_id, ts1, ts2, ts3, ts4, ts5, topchat_only) -> str: +def _build(video_id, channel_id, ts1, ts2, ts3, ts4, ts5, topchat_only) -> str: chattype = 4 if topchat_only else 1 b1 = enc.nm(1, 0) @@ -23,7 +28,7 @@ def _build(video_id, ts1, ts2, ts3, ts4, ts5, topchat_only) -> str: b11 = enc.nm(11, 3) b15 = enc.nm(15, 0) - header = enc.rs(3, _header(video_id)) + header = enc.rs(3, _header(video_id, channel_id)) timestamp1 = enc.nm(5, ts1) s6 = enc.nm(6, 0) s7 = enc.nm(7, 0) @@ -53,7 +58,7 @@ def _times(past_sec): return list(map(lambda x: int(x * 1000000), [_ts1, _ts2, _ts3, _ts4, _ts5])) -def getparam(video_id, past_sec=0, topchat_only=False) -> str: +def getparam(video_id, channel_id, past_sec=0, topchat_only=False) -> str: ''' Parameter --------- @@ -62,4 +67,4 @@ def getparam(video_id, past_sec=0, topchat_only=False) -> str: topchat_only : bool if True, fetch only 'top chat' ''' - return _build(video_id, *_times(past_sec), topchat_only) \ No newline at end of file + return _build(video_id, channel_id, *_times(past_sec), topchat_only) \ No newline at end of file diff --git a/tests/test_livechat.py b/tests/test_livechat.py deleted file mode 100644 index 925538d..0000000 --- a/tests/test_livechat.py +++ /dev/null @@ -1,48 +0,0 @@ -import asyncio -import json -from pytest_httpx import HTTPXMock -from concurrent.futures import CancelledError -from pytchat.core_multithread.livechat import LiveChat -from pytchat.core_async.livechat import LiveChatAsync -from pytchat.exceptions import ResponseContextError - - -def _open_file(path): - with open(path, mode='r', encoding='utf-8') as f: - return f.read() - - -def add_response_file(httpx_mock: HTTPXMock, jsonfile_path: str): - testdata = json.loads(_open_file(jsonfile_path)) - httpx_mock.add_response(json=testdata) - - -def test_async(httpx_mock: HTTPXMock): - add_response_file(httpx_mock, 'tests/testdata/paramgen_firstread.json') - - async def test_loop(): - try: - chat = LiveChatAsync(video_id='__test_id__') - _ = await chat.get() - assert chat.is_alive() - chat.terminate() - assert not chat.is_alive() - except ResponseContextError: - assert False - loop = asyncio.get_event_loop() - try: - loop.run_until_complete(test_loop()) - except CancelledError: - assert True - - -def test_multithread(httpx_mock: HTTPXMock): - add_response_file(httpx_mock, 'tests/testdata/paramgen_firstread.json') - try: - chat = LiveChat(video_id='__test_id__') - _ = chat.get() - assert chat.is_alive() - chat.terminate() - assert not chat.is_alive() - except ResponseContextError: - assert False diff --git a/tests/test_livechat_2.py b/tests/test_livechat_2.py deleted file mode 100644 index eba1236..0000000 --- a/tests/test_livechat_2.py +++ /dev/null @@ -1,71 +0,0 @@ -import asyncio -import json -from pytest_httpx import HTTPXMock -from concurrent.futures import CancelledError -from pytchat.core_multithread.livechat import LiveChat -from pytchat.core_async.livechat import LiveChatAsync -from pytchat.processors.dummy_processor import DummyProcessor - - -def _open_file(path): - with open(path, mode='r', encoding='utf-8') as f: - return f.read() - - -def add_response_file(httpx_mock: HTTPXMock, jsonfile_path: str): - testdata = json.loads(_open_file(jsonfile_path)) - httpx_mock.add_response(json=testdata) - - -def test_async_live_stream(httpx_mock: HTTPXMock): - add_response_file(httpx_mock, 'tests/testdata/test_stream.json') - - async def test_loop(): - chat = LiveChatAsync(video_id='__test_id__', processor=DummyProcessor()) - chats = await chat.get() - rawdata = chats[0]["chatdata"] - assert list(rawdata[0]["addChatItemAction"]["item"].keys())[ - 0] == "liveChatTextMessageRenderer" - assert list(rawdata[1]["addChatItemAction"]["item"].keys())[ - 0] == "liveChatTextMessageRenderer" - assert list(rawdata[2]["addChatItemAction"]["item"].keys())[ - 0] == "liveChatPlaceholderItemRenderer" - assert list(rawdata[3]["addLiveChatTickerItemAction"]["item"].keys())[ - 0] == "liveChatTickerPaidMessageItemRenderer" - assert list(rawdata[4]["addChatItemAction"]["item"].keys())[ - 0] == "liveChatPaidMessageRenderer" - assert list(rawdata[5]["addChatItemAction"]["item"].keys())[ - 0] == "liveChatPaidStickerRenderer" - assert list(rawdata[6]["addLiveChatTickerItemAction"]["item"].keys())[ - 0] == "liveChatTickerSponsorItemRenderer" - - loop = asyncio.get_event_loop() - try: - loop.run_until_complete(test_loop()) - except CancelledError: - assert True - - - - -def test_multithread_live_stream(httpx_mock: HTTPXMock): - add_response_file(httpx_mock, 'tests/testdata/test_stream.json') - chat = LiveChat(video_id='__test_id__', processor=DummyProcessor()) - chats = chat.get() - rawdata = chats[0]["chatdata"] - # assert fetching livachat data - assert list(rawdata[0]["addChatItemAction"]["item"].keys())[ - 0] == "liveChatTextMessageRenderer" - assert list(rawdata[1]["addChatItemAction"]["item"].keys())[ - 0] == "liveChatTextMessageRenderer" - assert list(rawdata[2]["addChatItemAction"]["item"].keys())[ - 0] == "liveChatPlaceholderItemRenderer" - assert list(rawdata[3]["addLiveChatTickerItemAction"]["item"].keys())[ - 0] == "liveChatTickerPaidMessageItemRenderer" - assert list(rawdata[4]["addChatItemAction"]["item"].keys())[ - 0] == "liveChatPaidMessageRenderer" - assert list(rawdata[5]["addChatItemAction"]["item"].keys())[ - 0] == "liveChatPaidStickerRenderer" - assert list(rawdata[6]["addLiveChatTickerItemAction"]["item"].keys())[ - 0] == "liveChatTickerSponsorItemRenderer" - chat.terminate() diff --git a/tests/test_liveparam.py b/tests/test_liveparam.py deleted file mode 100644 index 66d59be..0000000 --- a/tests/test_liveparam.py +++ /dev/null @@ -1,9 +0,0 @@ -import pytest -from pytchat.paramgen import liveparam - -def test_liveparam_0(mocker): - _ts1= 1546268400 - param = liveparam._build("01234567890", - *([_ts1*1000000 for i in range(5)]), topchat_only=False) - test_param="0ofMyAN1GhxDZzhLRFFvTE1ERXlNelExTmpjNE9UQWdBUT09KIC41tWqyt8CMAA4AEABShsIABAAGAAgADoAQABKAFCAuNbVqsrfAlgDeABQgLjW1arK3wJYgLjW1arK3wJoAYIBAggBiAEAmgECCACgAYC41tWqyt8C" - assert test_param == param \ No newline at end of file