From 2452b4ef8fdd590c39ac52e2fb83a24b8bc4e9ff Mon Sep 17 00:00:00 2001 From: mhdzumair Date: Mon, 4 Mar 2024 01:18:13 +0530 Subject: [PATCH] Added qBittorrent - WebDav support --- Pipfile | 2 + Pipfile.lock | 241 ++++++++++++-- db/schemas.py | 30 +- resources/exceptions/qbittorrent_error.mp4 | Bin 0 -> 109148 bytes resources/exceptions/webdav_error.mp4 | Bin 0 -> 103398 bytes resources/html/configure.html | 69 ++++ resources/js/config_script.js | 26 ++ streaming_providers/qbittorrent/__init__.py | 0 streaming_providers/qbittorrent/utils.py | 332 ++++++++++++++++++++ streaming_providers/routes.py | 5 + utils/parser.py | 6 + 11 files changed, 689 insertions(+), 22 deletions(-) create mode 100644 resources/exceptions/qbittorrent_error.mp4 create mode 100644 resources/exceptions/webdav_error.mp4 create mode 100644 streaming_providers/qbittorrent/__init__.py create mode 100644 streaming_providers/qbittorrent/utils.py diff --git a/Pipfile b/Pipfile index 9a95eed..4deaf3b 100644 --- a/Pipfile +++ b/Pipfile @@ -36,6 +36,8 @@ redis = {extras = ["hiredis"], version = "*"} dramatiq = {extras = ["redis", "watch"], version = "*"} gunicorn = "*" scrapy = "*" +aioqbt = {git = "git+https://github.com/mhdzumair/aioqbt.git"} +aiowebdav = "*" [dev-packages] pysocks = "*" diff --git a/Pipfile.lock b/Pipfile.lock index a48506c..96cd019 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "30880a6cb492bb705c7671889e64ef1113f718c771ed9c6545b3431e37e1f396" + "sha256": "c4f0cccc167e5c86cc664635228cca7445feea11d2c58ebefd1d1a3cbbadb7b9" }, "pipfile-spec": 6, "requires": { @@ -16,6 +16,118 @@ ] }, "default": { + "aiofiles": { + "hashes": [ + "sha256:19297512c647d4b27a2cf7c34caa7e405c0d60b5560618a29a9fe027b18b0107", + "sha256:84ec2218d8419404abcb9f0c02df3f34c6e0a68ed41072acfb1cef5cbc29051a" + ], + "markers": "python_version >= '3.7'", + "version": "==23.2.1" + }, + "aiohttp": { + "hashes": [ + "sha256:017a21b0df49039c8f46ca0971b3a7fdc1f56741ab1240cb90ca408049766168", + "sha256:039df344b45ae0b34ac885ab5b53940b174530d4dd8a14ed8b0e2155b9dddccb", + "sha256:055ce4f74b82551678291473f66dc9fb9048a50d8324278751926ff0ae7715e5", + "sha256:06a9b2c8837d9a94fae16c6223acc14b4dfdff216ab9b7202e07a9a09541168f", + "sha256:07b837ef0d2f252f96009e9b8435ec1fef68ef8b1461933253d318748ec1acdc", + "sha256:0ed621426d961df79aa3b963ac7af0d40392956ffa9be022024cd16297b30c8c", + "sha256:0fa43c32d1643f518491d9d3a730f85f5bbaedcbd7fbcae27435bb8b7a061b29", + "sha256:1f5a71d25cd8106eab05f8704cd9167b6e5187bcdf8f090a66c6d88b634802b4", + "sha256:1f5cd333fcf7590a18334c90f8c9147c837a6ec8a178e88d90a9b96ea03194cc", + "sha256:27468897f628c627230dba07ec65dc8d0db566923c48f29e084ce382119802bc", + "sha256:298abd678033b8571995650ccee753d9458dfa0377be4dba91e4491da3f2be63", + "sha256:2c895a656dd7e061b2fd6bb77d971cc38f2afc277229ce7dd3552de8313a483e", + "sha256:361a1026c9dd4aba0109e4040e2aecf9884f5cfe1b1b1bd3d09419c205e2e53d", + "sha256:363afe77cfcbe3a36353d8ea133e904b108feea505aa4792dad6585a8192c55a", + "sha256:38a19bc3b686ad55804ae931012f78f7a534cce165d089a2059f658f6c91fa60", + "sha256:38f307b41e0bea3294a9a2a87833191e4bcf89bb0365e83a8be3a58b31fb7f38", + "sha256:3e59c23c52765951b69ec45ddbbc9403a8761ee6f57253250c6e1536cacc758b", + "sha256:4b4af9f25b49a7be47c0972139e59ec0e8285c371049df1a63b6ca81fdd216a2", + "sha256:504b6981675ace64c28bf4a05a508af5cde526e36492c98916127f5a02354d53", + "sha256:50fca156d718f8ced687a373f9e140c1bb765ca16e3d6f4fe116e3df7c05b2c5", + "sha256:522a11c934ea660ff8953eda090dcd2154d367dec1ae3c540aff9f8a5c109ab4", + "sha256:52df73f14ed99cee84865b95a3d9e044f226320a87af208f068ecc33e0c35b96", + "sha256:595f105710293e76b9dc09f52e0dd896bd064a79346234b521f6b968ffdd8e58", + "sha256:59c26c95975f26e662ca78fdf543d4eeaef70e533a672b4113dd888bd2423caa", + "sha256:5bce0dc147ca85caa5d33debc4f4d65e8e8b5c97c7f9f660f215fa74fc49a321", + "sha256:5eafe2c065df5401ba06821b9a054d9cb2848867f3c59801b5d07a0be3a380ae", + "sha256:5ed3e046ea7b14938112ccd53d91c1539af3e6679b222f9469981e3dac7ba1ce", + "sha256:5fe9ce6c09668063b8447f85d43b8d1c4e5d3d7e92c63173e6180b2ac5d46dd8", + "sha256:648056db9a9fa565d3fa851880f99f45e3f9a771dd3ff3bb0c048ea83fb28194", + "sha256:69361bfdca5468c0488d7017b9b1e5ce769d40b46a9f4a2eed26b78619e9396c", + "sha256:6b0e029353361f1746bac2e4cc19b32f972ec03f0f943b390c4ab3371840aabf", + "sha256:6b88f9386ff1ad91ace19d2a1c0225896e28815ee09fc6a8932fded8cda97c3d", + "sha256:770d015888c2a598b377bd2f663adfd947d78c0124cfe7b959e1ef39f5b13869", + "sha256:7943c414d3a8d9235f5f15c22ace69787c140c80b718dcd57caaade95f7cd93b", + "sha256:7cf5c9458e1e90e3c390c2639f1017a0379a99a94fdfad3a1fd966a2874bba52", + "sha256:7f46acd6a194287b7e41e87957bfe2ad1ad88318d447caf5b090012f2c5bb528", + "sha256:82e6aa28dd46374f72093eda8bcd142f7771ee1eb9d1e223ff0fa7177a96b4a5", + "sha256:835a55b7ca49468aaaac0b217092dfdff370e6c215c9224c52f30daaa735c1c1", + "sha256:84871a243359bb42c12728f04d181a389718710129b36b6aad0fc4655a7647d4", + "sha256:8aacb477dc26797ee089721536a292a664846489c49d3ef9725f992449eda5a8", + "sha256:8e2c45c208c62e955e8256949eb225bd8b66a4c9b6865729a786f2aa79b72e9d", + "sha256:90842933e5d1ff760fae6caca4b2b3edba53ba8f4b71e95dacf2818a2aca06f7", + "sha256:938a9653e1e0c592053f815f7028e41a3062e902095e5a7dc84617c87267ebd5", + "sha256:939677b61f9d72a4fa2a042a5eee2a99a24001a67c13da113b2e30396567db54", + "sha256:9d3c9b50f19704552f23b4eaea1fc082fdd82c63429a6506446cbd8737823da3", + "sha256:a6fe5571784af92b6bc2fda8d1925cccdf24642d49546d3144948a6a1ed58ca5", + "sha256:a78ed8a53a1221393d9637c01870248a6f4ea5b214a59a92a36f18151739452c", + "sha256:ab40e6251c3873d86ea9b30a1ac6d7478c09277b32e14745d0d3c6e76e3c7e29", + "sha256:abf151955990d23f84205286938796c55ff11bbfb4ccfada8c9c83ae6b3c89a3", + "sha256:acef0899fea7492145d2bbaaaec7b345c87753168589cc7faf0afec9afe9b747", + "sha256:b40670ec7e2156d8e57f70aec34a7216407848dfe6c693ef131ddf6e76feb672", + "sha256:b791a3143681a520c0a17e26ae7465f1b6f99461a28019d1a2f425236e6eedb5", + "sha256:b955ed993491f1a5da7f92e98d5dad3c1e14dc175f74517c4e610b1f2456fb11", + "sha256:ba39e9c8627edc56544c8628cc180d88605df3892beeb2b94c9bc857774848ca", + "sha256:bca77a198bb6e69795ef2f09a5f4c12758487f83f33d63acde5f0d4919815768", + "sha256:c3452ea726c76e92f3b9fae4b34a151981a9ec0a4847a627c43d71a15ac32aa6", + "sha256:c46956ed82961e31557b6857a5ca153c67e5476972e5f7190015018760938da2", + "sha256:c7c8b816c2b5af5c8a436df44ca08258fc1a13b449393a91484225fcb7545533", + "sha256:cd73265a9e5ea618014802ab01babf1940cecb90c9762d8b9e7d2cc1e1969ec6", + "sha256:dad46e6f620574b3b4801c68255492e0159d1712271cc99d8bdf35f2043ec266", + "sha256:dc9b311743a78043b26ffaeeb9715dc360335e5517832f5a8e339f8a43581e4d", + "sha256:df822ee7feaaeffb99c1a9e5e608800bd8eda6e5f18f5cfb0dc7eeb2eaa6bbec", + "sha256:e083c285857b78ee21a96ba1eb1b5339733c3563f72980728ca2b08b53826ca5", + "sha256:e5e46b578c0e9db71d04c4b506a2121c0cb371dd89af17a0586ff6769d4c58c1", + "sha256:e99abf0bba688259a496f966211c49a514e65afa9b3073a1fcee08856e04425b", + "sha256:ee43080e75fc92bf36219926c8e6de497f9b247301bbf88c5c7593d931426679", + "sha256:f033d80bc6283092613882dfe40419c6a6a1527e04fc69350e87a9df02bbc283", + "sha256:f1088fa100bf46e7b398ffd9904f4808a0612e1d966b4aa43baa535d1b6341eb", + "sha256:f56455b0c2c7cc3b0c584815264461d07b177f903a04481dfc33e08a89f0c26b", + "sha256:f59dfe57bb1ec82ac0698ebfcdb7bcd0e99c255bd637ff613760d5f33e7c81b3", + "sha256:f7217af2e14da0856e082e96ff637f14ae45c10a5714b63c77f26d8884cf1051", + "sha256:f734e38fd8666f53da904c52a23ce517f1b07722118d750405af7e4123933511", + "sha256:f95511dd5d0e05fd9728bac4096319f80615aaef4acbecb35a990afebe953b0e", + "sha256:fdd215b7b7fd4a53994f238d0f46b7ba4ac4c0adb12452beee724ddd0743ae5d", + "sha256:feeb18a801aacb098220e2c3eea59a512362eb408d4afd0c242044c33ad6d542", + "sha256:ff30218887e62209942f91ac1be902cc80cddb86bf00fbc6783b7a43b2bea26f" + ], + "markers": "python_version >= '3.8'", + "version": "==3.9.3" + }, + "aioqbt": { + "git": "git+https://github.com/mhdzumair/aioqbt.git", + "markers": "python_version >= '3.7'", + "ref": "4be694b899a13df86d420b88ab777ab559bef8e9" + }, + "aiosignal": { + "hashes": [ + "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc", + "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.1" + }, + "aiowebdav": { + "hashes": [ + "sha256:1b7be6122ab69f06f1639bfea9fd3beb43a7d375b5e1ced560b832e04c000026", + "sha256:8345f8a55a5eea4e029de0b5c7ba38fbeaaee3e0fdc1e0ca29e60d997643cc2f" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==0.1.0rc5" + }, "annotated-types": { "hashes": [ "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43", @@ -41,6 +153,14 @@ "markers": "python_version >= '3.6'", "version": "==3.10.4" }, + "async-timeout": { + "hashes": [ + "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f", + "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028" + ], + "markers": "python_version >= '3.7'", + "version": "==4.0.3" + }, "attrs": { "hashes": [ "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30", @@ -396,6 +516,89 @@ ], "version": "==0.2.1" }, + "frozenlist": { + "hashes": [ + "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7", + "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98", + "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad", + "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5", + "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae", + "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e", + "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a", + "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701", + "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d", + "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6", + "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6", + "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106", + "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75", + "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868", + "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a", + "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0", + "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1", + "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826", + "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec", + "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6", + "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950", + "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19", + "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0", + "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8", + "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a", + "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09", + "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86", + "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c", + "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5", + "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b", + "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b", + "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d", + "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0", + "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea", + "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776", + "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a", + "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897", + "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7", + "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09", + "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9", + "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe", + "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd", + "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742", + "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09", + "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0", + "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932", + "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1", + "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a", + "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49", + "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d", + "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7", + "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480", + "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89", + "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e", + "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b", + "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82", + "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb", + "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068", + "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8", + "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b", + "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb", + "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2", + "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11", + "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b", + "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc", + "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0", + "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497", + "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17", + "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0", + "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2", + "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439", + "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5", + "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac", + "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825", + "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887", + "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced", + "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74" + ], + "markers": "python_version >= '3.8'", + "version": "==1.4.1" + }, "gevent": { "hashes": [ "sha256:17ebb6f981389c17321b95bc59ff6a65edeb98f3205884babaec9cb514aaa0d3", @@ -1217,12 +1420,12 @@ }, "pydantic": { "hashes": [ - "sha256:37a5432e54b12fecaa1049c5195f3d860a10e01bdfd24f1840ef14bd0d3aeab3", - "sha256:a09be1c3d28f3abe37f8a78af58284b236a92ce520105ddc91a6d29ea1176ba7" + "sha256:72c6034df47f46ccdf81869fddb81aade68056003900a8724a4f160700016a2a", + "sha256:e07805c4c7f5c6826e33a1d4c9d47950d7eaf34868e2690f8594d2e30241f11f" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==2.6.2" + "version": "==2.6.3" }, "pydantic-core": { "hashes": [ @@ -1442,12 +1645,12 @@ }, "python-dateutil": { "hashes": [ - "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", - "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" + "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", + "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" ], "index": "pypi", "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.8.2" + "version": "==2.9.0.post0" }, "python-dotenv": { "hashes": [ @@ -1629,11 +1832,11 @@ "hiredis" ], "hashes": [ - "sha256:0dab495cd5753069d3bc650a0dde8a8f9edde16fc5691b689a566eda58100d0f", - "sha256:ed4802971884ae19d640775ba3b03aa2e7bd5e8fb8dfaed2decce4d0fc48391f" + "sha256:3f82cc80d350e93042c8e6e7a5d0596e4dd68715babffba79492733e1f367037", + "sha256:4caa8e1fcb6f3c0ef28dba99535101d80934b7d4cd541bbb47f4a3826ee472d1" ], "markers": "python_version >= '3.7'", - "version": "==5.0.1" + "version": "==5.0.2" }, "requests": { "hashes": [ @@ -1703,11 +1906,11 @@ }, "sniffio": { "hashes": [ - "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101", - "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384" + "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", + "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc" ], "markers": "python_version >= '3.7'", - "version": "==1.3.0" + "version": "==1.3.1" }, "soupsieve": { "hashes": [ @@ -1815,19 +2018,19 @@ }, "twisted": { "hashes": [ - "sha256:4ae8bce12999a35f7fe6443e7f1893e6fe09588c8d2bed9c35cdce8ff2d5b444", - "sha256:987847a0790a2c597197613686e2784fd54167df3a55d0fb17c8412305d76ce5" + "sha256:039f2e6a49ab5108abd94de187fa92377abe5985c7a72d68d0ad266ba19eae63", + "sha256:6b38b6ece7296b5e122c9eb17da2eeab3d98a198f50ca9efd00fb03e5b4fd4ae" ], "markers": "python_full_version >= '3.8.0'", - "version": "==23.10.0" + "version": "==24.3.0" }, "typing-extensions": { "hashes": [ - "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783", - "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd" + "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475", + "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb" ], "markers": "python_version >= '3.8'", - "version": "==4.9.0" + "version": "==4.10.0" }, "tzlocal": { "hashes": [ diff --git a/db/schemas.py b/db/schemas.py index 4bcbaff..c44bea9 100644 --- a/db/schemas.py +++ b/db/schemas.py @@ -62,6 +62,18 @@ class Streams(BaseModel): streams: Optional[list[Stream]] = [] +class QBittorrentConfig(BaseModel): + qbittorrent_url: str + qbittorrent_username: str + qbittorrent_password: str + seeding_time_limit: int = 1440 # 24 hours + seeding_ratio_limit: float = 1.0 + play_video_after: int = Field(default=100, le=100, ge=0) + webdav_url: str + webdav_username: str + webdav_password: str + + class StreamingProvider(BaseModel): service: Literal[ "realdebrid", @@ -72,17 +84,29 @@ class StreamingProvider(BaseModel): "pikpak", "torbox", "premiumize", + "qbittorrent", ] token: str | None = None username: str | None = None password: str | None = None enable_watchlist_catalogs: bool = True + qbittorrent_config: QBittorrentConfig | None = None @model_validator(mode="after") def validate_token_or_username_password(self) -> "StreamingProvider": - # validating the token or username and password - if not self.token and not self.username and not self.password: - raise ValueError("Either token or username and password must be present") + # validating the token or (username and password) or qbittorrent_config + if self.service is None: + return self + if self.service == "pikpak": + if not self.username or not self.password: + raise ValueError("Username and password are required") + elif self.service == "qbittorrent": + if not self.qbittorrent_config: + raise ValueError("qbittorrent_config is required") + else: + if not self.token or not (self.username and self.password): + raise ValueError("Token or username and password are required") + return self class Config: diff --git a/resources/exceptions/qbittorrent_error.mp4 b/resources/exceptions/qbittorrent_error.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..89a0e8cf5e25ed9e2df0efa7d9200c4cf839578f GIT binary patch literal 109148 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

q92N2aD$byG{`#7WlSF7`|H(9JA}C2t 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 (Premium) + @@ -100,6 +101,74 @@ + +

diff --git a/resources/js/config_script.js b/resources/js/config_script.js index 8aa2bf6..d761074 100644 --- a/resources/js/config_script.js +++ b/resources/js/config_script.js @@ -177,9 +177,15 @@ function updateProviderFields(isChangeEvent = false) { if (servicesRequiringCredentials.includes(provider)) { setElementDisplay('credentials', 'block'); setElementDisplay('token_input', 'none'); + setElementDisplay('qbittorrent_config', 'none'); + } else if (provider === 'qbittorrent') { + setElementDisplay('qbittorrent_config', 'block'); + setElementDisplay('credentials', 'none'); + setElementDisplay('token_input', 'none'); } else { setElementDisplay('credentials', 'none'); setElementDisplay('token_input', 'block'); + setElementDisplay('qbittorrent_config', 'none'); } setElementDisplay('watchlist_section', 'block'); watchlistLabel.textContent = `Enable ${provider.charAt(0).toUpperCase() + provider.slice(1)} Watchlist`; @@ -187,6 +193,7 @@ function updateProviderFields(isChangeEvent = false) { setElementDisplay('credentials', 'none'); setElementDisplay('token_input', 'none'); setElementDisplay('watchlist_section', 'none'); + setElementDisplay('qbittorrent_config', 'none'); } // Reset the fields only if this is triggered by an onchange event @@ -260,6 +267,23 @@ function getUserData() { validateInput('password', document.getElementById('password').value); streamingProviderData.username = document.getElementById('username').value; streamingProviderData.password = document.getElementById('password').value; + } else if (provider === 'qbittorrent') { + streamingProviderData.qbittorrent_config = { + qbittorrent_url: document.getElementById('qbittorrent_url').value, + qbittorrent_username: document.getElementById('qbittorrent_username').value, + qbittorrent_password: document.getElementById('qbittorrent_password').value, + seeding_time_limit: parseInt(document.getElementById('seeding_time_limit').value, 10), + seeding_ratio_limit: parseFloat(document.getElementById('seeding_ratio_limit').value), + play_video_after: parseInt(document.getElementById('play_video_after_download').value, 10), + webdav_url: document.getElementById('webdav_url').value, + webdav_username: document.getElementById('webdav_username').value, + webdav_password: document.getElementById('webdav_password').value, + }; + // Validate qBittorrent-specific inputs + validateInput('qbittorrent_url', streamingProviderData.qbittorrent_config.qbittorrent_url); + validateInput('seeding_time_limit', !isNaN(streamingProviderData.qbittorrent_config.seeding_time_limit)); + validateInput('seeding_ratio_limit', !isNaN(streamingProviderData.qbittorrent_config.seeding_ratio_limit)); + validateInput('play_video_after_download', !isNaN(streamingProviderData.qbittorrent_config.play_video_after)); } else { validateInput('provider_token', document.getElementById('provider_token').value); streamingProviderData.token = document.getElementById('provider_token').value; @@ -413,6 +437,8 @@ document.addEventListener('DOMContentLoaded', function () { setupPasswordToggle('password', 'togglePassword', 'togglePasswordIcon'); setupPasswordToggle('api_password', 'toggleApiPassword', 'toggleApiPasswordIcon'); + setupPasswordToggle('qbittorrent_password', 'toggleQbittorrentPassword', 'toggleQbittorrentPasswordIcon'); + setupPasswordToggle('webdav_password', 'toggleWebdavPassword', 'toggleWebdavPasswordIcon'); if (navigator.share) { document.getElementById('shareBtn').style.display = 'block'; diff --git a/streaming_providers/qbittorrent/__init__.py b/streaming_providers/qbittorrent/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/streaming_providers/qbittorrent/utils.py b/streaming_providers/qbittorrent/utils.py new file mode 100644 index 0000000..cefb63f --- /dev/null +++ b/streaming_providers/qbittorrent/utils.py @@ -0,0 +1,332 @@ +import asyncio +from datetime import timedelta +from os import path +from urllib.parse import urljoin, urlparse, quote + +from aiohttp import ClientConnectorError +from aioqbt.api import AddFormBuilder, TorrentInfo +from aioqbt.client import create_client, APIClient +from aioqbt.exc import LoginError, AddTorrentError +from aiowebdav.client import Client as WebDavClient +from aiowebdav.exceptions import RemoteResourceNotFound, NoConnection +from thefuzz import fuzz + +from db.models import TorrentStreams +from db.schemas import UserData +from streaming_providers.exceptions import ProviderException + + +async def check_torrent_status( + qbittorrent: APIClient, info_hash: str +) -> TorrentInfo | None: + """Checks the status of a torrent with a given info_hash or torrent_name.""" + available_torrents = await qbittorrent.torrents.info(hashes=[info_hash]) + return available_torrents[0] if available_torrents else None + + +async def add_magnet( + qbittorrent: APIClient, magnet_link: str, info_hash: str, user_data: UserData +): + """Adds a magnet link to the qbittorrent server.""" + try: + await qbittorrent.torrents.add( + AddFormBuilder.with_client(qbittorrent) + .include_url(magnet_link) + .savepath(info_hash) + .seeding_time_limit( + timedelta( + minutes=user_data.streaming_provider.qbittorrent_config.seeding_time_limit + ) + ) + .ratio_limit( + user_data.streaming_provider.qbittorrent_config.seeding_ratio_limit + ) + .build() + ) + except AddTorrentError: + raise ProviderException( + "Failed to add the torrent to qBittorrent", "add_torrent_failed.mp4" + ) + + +async def wait_for_torrent_to_complete( + qbittorrent: APIClient, + info_hash: str, + play_video_after: int, + max_retries: int, + retry_interval: int, +): + """Waits for a torrent with the given info_hash to complete downloading.""" + retries = 0 + while retries < max_retries: + torrent = await check_torrent_status(qbittorrent, info_hash) + if torrent and torrent.progress * 100 >= play_video_after: + return + await asyncio.sleep(retry_interval) + retries += 1 + + raise ProviderException("Torrent not downloaded yet.", "torrent_not_downloaded.mp4") + + +async def get_files_from_folder( + webdav: WebDavClient, base_url_path: str, root_path: str +) -> list[dict]: + """Helper function to recursively get files from a folder including subfolders.""" + try: + contents = await webdav.list(root_path, get_info=True) + except RemoteResourceNotFound: + return [] + + files = [] + for item in contents: + # skip the root folder + if item["path"].endswith(root_path.removesuffix("/") + "/"): + continue + + if item["isdir"]: + files.extend( + await get_files_from_folder( + webdav, base_url_path, item["path"].removeprefix(base_url_path) + ) + ) + else: + item.update( + { + "name": path.basename(item["path"]), + "size": int(item["size"]), + } + ) + files.append(item) + + return files + + +async def find_file_in_folder_tree( + webdav: WebDavClient, user_data: UserData, info_hash: str, filename: str +) -> dict | None: + base_url_path = urlparse( + user_data.streaming_provider.qbittorrent_config.webdav_url + ).path + + files = await get_files_from_folder(webdav, base_url_path, info_hash) + if not files: + return None + + exact_match = next((file for file in files if file["name"] == filename), None) + if exact_match: + return exact_match + + # Fuzzy matching as a fallback + for file in files: + file["fuzzy_ratio"] = fuzz.ratio(filename, file["name"]) + selected_file = max(files, key=lambda x: x["fuzzy_ratio"]) + + # If the fuzzy ratio is less than 50, then select the largest file + if selected_file["fuzzy_ratio"] < 50: + selected_file = max(files, key=lambda x: x["size"]) + + if "video" not in selected_file["content_type"]: + raise ProviderException( + "No matching file available for this torrent", "no_matching_file.mp4" + ) + + return selected_file + + +async def initialize_qbittorrent(user_data: UserData): + try: + qbittorrent = await create_client( + user_data.streaming_provider.qbittorrent_config.qbittorrent_url + + "/api/v2/", + username=user_data.streaming_provider.qbittorrent_config.qbittorrent_username, + password=user_data.streaming_provider.qbittorrent_config.qbittorrent_password, + ) + except LoginError: + raise ProviderException( + "Invalid qBittorrent credentials", "invalid_credentials.mp4" + ) + except ClientConnectorError: + raise ProviderException( + "Failed to connect to qBittorrent", "qbittorrent_error.mp4" + ) + return qbittorrent + + +async def initialize_webdav(user_data: UserData): + webdav_options = { + "webdav_hostname": user_data.streaming_provider.qbittorrent_config.webdav_url, + "webdav_login": user_data.streaming_provider.qbittorrent_config.webdav_username, + "webdav_password": user_data.streaming_provider.qbittorrent_config.webdav_password, + } + + webdav = WebDavClient(webdav_options) + + try: + if not await webdav.check(): + raise ProviderException( + "Invalid WebDAV credentials", "invalid_credentials.mp4" + ) + except NoConnection: + raise ProviderException( + "Failed to connect to the WebDAV server", "webdav_error.mp4" + ) + return webdav + + +async def handle_torrent_status( + qbittorrent: APIClient, + info_hash: str, + play_video_after: int, + max_retries: int, + retry_interval: int, +): + torrent = await check_torrent_status(qbittorrent, info_hash) + if not torrent: + return + + if torrent.progress * 100 >= play_video_after: + return torrent + + await wait_for_torrent_to_complete( + qbittorrent, info_hash, play_video_after, max_retries, retry_interval + ) + return torrent + + +async def retrieve_or_download_file( + qbittorrent: APIClient, + webdav: WebDavClient, + user_data: UserData, + play_video_after: int, + filename: str, + magnet_link: str, + info_hash: str, + max_retries: int, + retry_interval: int, +): + selected_file = await find_file_in_folder_tree( + webdav, user_data, info_hash, filename + ) + if not selected_file: + await add_magnet(qbittorrent, magnet_link, info_hash, user_data) + await wait_for_torrent_to_complete( + qbittorrent, info_hash, play_video_after, max_retries, retry_interval + ) + selected_file = await find_file_in_folder_tree( + webdav, user_data, info_hash, filename + ) + if selected_file is None: + raise ProviderException( + "No matching file available for this torrent", "no_matching_file.mp4" + ) + return selected_file + + +def generate_webdav_url(user_data: UserData, selected_file: dict) -> str: + webdav_url = user_data.streaming_provider.qbittorrent_config.webdav_url + webdav_username = user_data.streaming_provider.qbittorrent_config.webdav_username + webdav_password = user_data.streaming_provider.qbittorrent_config.webdav_password + + # Check if credentials are provided + if webdav_username and webdav_password: + # URL encode the username and password + webdav_username = quote(webdav_username, safe="") + webdav_password = quote(webdav_password, safe="") + parsed_url = urlparse(webdav_url) + netloc = f"{webdav_username}:{webdav_password}@{parsed_url.netloc}" + base_url = parsed_url._replace(netloc=netloc).geturl() + else: + base_url = webdav_url + + return urljoin( + base_url, + quote(selected_file["path"]), # Ensure the path is URL encoded + ) + + +async def get_direct_link_from_qbittorrent( + info_hash: str, + magnet_link: str, + user_data: UserData, + stream: TorrentStreams, + filename: str, + max_retries=5, + retry_interval=5, +) -> str: + """Get the direct link from the qBittorrent server.""" + qbittorrent = webdav = None + play_video_after = user_data.streaming_provider.qbittorrent_config.play_video_after + try: + qbittorrent = await initialize_qbittorrent(user_data) + webdav = await initialize_webdav(user_data) + await handle_torrent_status( + qbittorrent, + info_hash, + play_video_after, + max_retries, + retry_interval, + ) + + selected_file = await retrieve_or_download_file( + qbittorrent, + webdav, + user_data, + play_video_after, + filename or stream.torrent_name, + magnet_link, + info_hash, + max_retries, + retry_interval, + ) + + return generate_webdav_url(user_data, selected_file) + finally: + if qbittorrent: + await qbittorrent.close() + if webdav: + await webdav.close() + + +async def update_qbittorrent_cache_status( + streams: list[TorrentStreams], user_data: UserData +): + """Updates the cache status of streams based on qBittorrent's instant availability.""" + qbittorrent = None + try: + qbittorrent = await initialize_qbittorrent(user_data) + torrents_info = await qbittorrent.torrents.info( + hashes=[stream.id for stream in streams] + ) + torrents_dict = {torrent.hash: torrent.progress for torrent in torrents_info} + except ProviderException: + return + finally: + if qbittorrent: + await qbittorrent.close() + + for stream in streams: + stream.cached = torrents_dict.get(stream.id, 0) == 1 + + +async def fetch_info_hashes_from_webdav( + user_data: UserData, +) -> list[str]: + """Fetches the info_hashes from directories in the WebDAV server that are named after the torrent's info hashes.""" + webdav = None + try: + webdav = await initialize_webdav(user_data) + directories = await webdav.list() + + # Filter out directory names that match the length of an info hash (40 chars) plus the trailing slash + info_hashes = [ + dirname.removesuffix("/") + for dirname in directories + if len(dirname) == 41 and dirname.endswith("/") + ] + + return info_hashes + except ProviderException: + return [] + finally: + if webdav: + await webdav.close() diff --git a/streaming_providers/routes.py b/streaming_providers/routes.py index 4240a07..43ca694 100644 --- a/streaming_providers/routes.py +++ b/streaming_providers/routes.py @@ -23,6 +23,7 @@ from streaming_providers.realdebrid.utils import get_direct_link_from_realdebrid from streaming_providers.seedr.api import router as seedr_router from streaming_providers.seedr.utils import get_direct_link_from_seedr from streaming_providers.torbox.utils import get_direct_link_from_torbox +from streaming_providers.qbittorrent.utils import get_direct_link_from_qbittorrent from utils import crypto, torrent, wrappers, const router = APIRouter() @@ -85,6 +86,10 @@ async def streaming_provider_endpoint( video_url = get_direct_link_from_premiumize( info_hash, magnet_link, user_data, stream.torrent_name, filename, 1, 0 ) + elif user_data.streaming_provider.service == "qbittorrent": + video_url = await get_direct_link_from_qbittorrent( + info_hash, magnet_link, user_data, stream, filename, 1, 0 + ) else: video_url = get_direct_link_from_debridlink( info_hash, magnet_link, user_data, filename, stream.file_index, 1, 0 diff --git a/utils/parser.py b/utils/parser.py index 497c3fd..7c2f5fc 100644 --- a/utils/parser.py +++ b/utils/parser.py @@ -28,6 +28,10 @@ from streaming_providers.premiumize.utils import ( update_pm_cache_status, fetch_downloaded_info_hashes_from_premiumize, ) +from streaming_providers.qbittorrent.utils import ( + update_qbittorrent_cache_status, + fetch_info_hashes_from_webdav, +) from streaming_providers.realdebrid.utils import ( update_rd_cache_status, fetch_downloaded_info_hashes_from_rd, @@ -57,6 +61,7 @@ CACHE_UPDATE_FUNCTIONS = { "seedr": update_seedr_cache_status, "torbox": update_torbox_cache_status, "premiumize": update_pm_cache_status, + "qbittorrent": update_qbittorrent_cache_status, } # Define provider-specific downloaded info hashes fetch functions @@ -69,6 +74,7 @@ FETCH_DOWNLOADED_INFO_HASHES_FUNCTIONS = { "seedr": fetch_downloaded_info_hashes_from_seedr, "torbox": fetch_downloaded_info_hashes_from_torbox, "premiumize": fetch_downloaded_info_hashes_from_premiumize, + "qbittorrent": fetch_info_hashes_from_webdav, }