Add support for private, semi-private, and webseed torrent types for prowlarr & jackett & Manual imports; store torrent file content

- Updated streaming providers to allow adding torrents by file for webseed and private torrents.
- Implemented functionality to store the content of torrent files.
This commit is contained in:
mhdzumair
2024-12-22 18:21:58 +05:30
parent 5b2936282c
commit 70e8d1946b
29 changed files with 646 additions and 372 deletions
Generated
+293 -293
View File
@@ -41,94 +41,94 @@
},
"aiohttp": {
"hashes": [
"sha256:012f176945af138abc10c4a48743327a92b4ca9adc7a0e078077cdb5dbab7be0",
"sha256:02c13415b5732fb6ee7ff64583a5e6ed1c57aa68f17d2bda79c04888dfdc2769",
"sha256:03b6002e20938fc6ee0918c81d9e776bebccc84690e2b03ed132331cca065ee5",
"sha256:04814571cb72d65a6899db6099e377ed00710bf2e3eafd2985166f2918beaf59",
"sha256:0580f2e12de2138f34debcd5d88894786453a76e98febaf3e8fe5db62d01c9bf",
"sha256:06a8e2ee1cbac16fe61e51e0b0c269400e781b13bcfc33f5425912391a542985",
"sha256:076bc454a7e6fd646bc82ea7f98296be0b1219b5e3ef8a488afbdd8e81fbac50",
"sha256:0c9527819b29cd2b9f52033e7fb9ff08073df49b4799c89cb5754624ecd98299",
"sha256:0dc49f42422163efb7e6f1df2636fe3db72713f6cd94688e339dbe33fe06d61d",
"sha256:14cdb5a9570be5a04eec2ace174a48ae85833c2aadc86de68f55541f66ce42ab",
"sha256:15fccaf62a4889527539ecb86834084ecf6e9ea70588efde86e8bc775e0e7542",
"sha256:24213ba85a419103e641e55c27dc7ff03536c4873470c2478cce3311ba1eee7b",
"sha256:31d5093d3acd02b31c649d3a69bb072d539d4c7659b87caa4f6d2bcf57c2fa2b",
"sha256:3691ed7726fef54e928fe26344d930c0c8575bc968c3e239c2e1a04bd8cf7838",
"sha256:386fbe79863eb564e9f3615b959e28b222259da0c48fd1be5929ac838bc65683",
"sha256:3bbbfff4c679c64e6e23cb213f57cc2c9165c9a65d63717108a644eb5a7398df",
"sha256:3de34936eb1a647aa919655ff8d38b618e9f6b7f250cc19a57a4bf7fd2062b6d",
"sha256:40d1c7a7f750b5648642586ba7206999650208dbe5afbcc5284bcec6579c9b91",
"sha256:44224d815853962f48fe124748227773acd9686eba6dc102578defd6fc99e8d9",
"sha256:47ad15a65fb41c570cd0ad9a9ff8012489e68176e7207ec7b82a0940dddfd8be",
"sha256:482cafb7dc886bebeb6c9ba7925e03591a62ab34298ee70d3dd47ba966370d2c",
"sha256:49c7dbbc1a559ae14fc48387a115b7d4bbc84b4a2c3b9299c31696953c2a5219",
"sha256:4b2c7ac59c5698a7a8207ba72d9e9c15b0fc484a560be0788b31312c2c5504e4",
"sha256:4cca22a61b7fe45da8fc73c3443150c3608750bbe27641fc7558ec5117b27fdf",
"sha256:4cfce37f31f20800a6a6620ce2cdd6737b82e42e06e6e9bd1b36f546feb3c44f",
"sha256:502a1464ccbc800b4b1995b302efaf426e8763fadf185e933c2931df7db9a199",
"sha256:53bf2097e05c2accc166c142a2090e4c6fd86581bde3fd9b2d3f9e93dda66ac1",
"sha256:593c114a2221444f30749cc5e5f4012488f56bd14de2af44fe23e1e9894a9c60",
"sha256:5d6958671b296febe7f5f859bea581a21c1d05430d1bbdcf2b393599b1cdce77",
"sha256:5ef359ebc6949e3a34c65ce20230fae70920714367c63afd80ea0c2702902ccf",
"sha256:613e5169f8ae77b1933e42e418a95931fb4867b2991fc311430b15901ed67079",
"sha256:61b9bae80ed1f338c42f57c16918853dc51775fb5cb61da70d590de14d8b5fb4",
"sha256:6362cc6c23c08d18ddbf0e8c4d5159b5df74fea1a5278ff4f2c79aed3f4e9f46",
"sha256:65a96e3e03300b41f261bbfd40dfdbf1c301e87eab7cd61c054b1f2e7c89b9e8",
"sha256:65e55ca7debae8faaffee0ebb4b47a51b4075f01e9b641c31e554fd376595c6c",
"sha256:68386d78743e6570f054fe7949d6cb37ef2b672b4d3405ce91fafa996f7d9b4d",
"sha256:68ff6f48b51bd78ea92b31079817aff539f6c8fc80b6b8d6ca347d7c02384e33",
"sha256:6ab29b8a0beb6f8eaf1e5049252cfe74adbaafd39ba91e10f18caeb0e99ffb34",
"sha256:77ae58586930ee6b2b6f696c82cf8e78c8016ec4795c53e36718365f6959dc82",
"sha256:77c4aa15a89847b9891abf97f3d4048f3c2d667e00f8a623c89ad2dccee6771b",
"sha256:78153314f26d5abef3239b4a9af20c229c6f3ecb97d4c1c01b22c4f87669820c",
"sha256:7852bbcb4d0d2f0c4d583f40c3bc750ee033265d80598d0f9cb6f372baa6b836",
"sha256:7e97d622cb083e86f18317282084bc9fbf261801b0192c34fe4b1febd9f7ae69",
"sha256:7f3dc0e330575f5b134918976a645e79adf333c0a1439dcf6899a80776c9ab39",
"sha256:80886dac673ceaef499de2f393fc80bb4481a129e6cb29e624a12e3296cc088f",
"sha256:811f23b3351ca532af598405db1093f018edf81368e689d1b508c57dcc6b6a32",
"sha256:86a5dfcc39309470bd7b68c591d84056d195428d5d2e0b5ccadfbaf25b026ebc",
"sha256:8b3cf2dc0f0690a33f2d2b2cb15db87a65f1c609f53c37e226f84edb08d10f52",
"sha256:8cc5203b817b748adccb07f36390feb730b1bc5f56683445bfe924fc270b8816",
"sha256:909af95a72cedbefe5596f0bdf3055740f96c1a4baa0dd11fd74ca4de0b4e3f1",
"sha256:974d3a2cce5fcfa32f06b13ccc8f20c6ad9c51802bb7f829eae8a1845c4019ec",
"sha256:98283b94cc0e11c73acaf1c9698dea80c830ca476492c0fe2622bd931f34b487",
"sha256:98f5635f7b74bcd4f6f72fcd85bea2154b323a9f05226a80bc7398d0c90763b0",
"sha256:99b7920e7165be5a9e9a3a7f1b680f06f68ff0d0328ff4079e5163990d046767",
"sha256:9bca390cb247dbfaec3c664326e034ef23882c3f3bfa5fbf0b56cad0320aaca5",
"sha256:9e2e576caec5c6a6b93f41626c9c02fc87cd91538b81a3670b2e04452a63def6",
"sha256:9ef405356ba989fb57f84cac66f7b0260772836191ccefbb987f414bcd2979d9",
"sha256:a55d2ad345684e7c3dd2c20d2f9572e9e1d5446d57200ff630e6ede7612e307f",
"sha256:ab7485222db0959a87fbe8125e233b5a6f01f4400785b36e8a7878170d8c3138",
"sha256:b1fc6b45010a8d0ff9e88f9f2418c6fd408c99c211257334aff41597ebece42e",
"sha256:b78f053a7ecfc35f0451d961dacdc671f4bcbc2f58241a7c820e9d82559844cf",
"sha256:b99acd4730ad1b196bfb03ee0803e4adac371ae8efa7e1cbc820200fc5ded109",
"sha256:be2b516f56ea883a3e14dda17059716593526e10fb6303189aaf5503937db408",
"sha256:beb39a6d60a709ae3fb3516a1581777e7e8b76933bb88c8f4420d875bb0267c6",
"sha256:bf3d1a519a324af764a46da4115bdbd566b3c73fb793ffb97f9111dbc684fc4d",
"sha256:c49a76c1038c2dd116fa443eba26bbb8e6c37e924e2513574856de3b6516be99",
"sha256:c5532f0441fc09c119e1dca18fbc0687e64fbeb45aa4d6a87211ceaee50a74c4",
"sha256:c6b9e6d7e41656d78e37ce754813fa44b455c3d0d0dced2a047def7dc5570b74",
"sha256:c87bf31b7fdab94ae3adbe4a48e711bfc5f89d21cf4c197e75561def39e223bc",
"sha256:cbad88a61fa743c5d283ad501b01c153820734118b65aee2bd7dbb735475ce0d",
"sha256:cf14627232dfa8730453752e9cdc210966490992234d77ff90bc8dc0dce361d5",
"sha256:db1d0b28fcb7f1d35600150c3e4b490775251dea70f894bf15c678fdd84eda6a",
"sha256:ddf5f7d877615f6a1e75971bfa5ac88609af3b74796ff3e06879e8422729fd01",
"sha256:e44a9a3c053b90c6f09b1bb4edd880959f5328cf63052503f892c41ea786d99f",
"sha256:efb15a17a12497685304b2d976cb4939e55137df7b09fa53f1b6a023f01fcb4e",
"sha256:fbbaea811a2bba171197b08eea288b9402faa2bab2ba0858eecdd0a4105753a3"
"sha256:0882c2820fd0132240edbb4a51eb8ceb6eef8181db9ad5291ab3332e0d71df5f",
"sha256:0a6d3fbf2232e3a08c41eca81ae4f1dff3d8f1a30bae415ebe0af2d2458b8a33",
"sha256:0b7fb429ab1aafa1f48578eb315ca45bd46e9c37de11fe45c7f5f4138091e2f1",
"sha256:0eb98d90b6690827dcc84c246811feeb4e1eea683c0eac6caed7549be9c84665",
"sha256:0fd82b8e9c383af11d2b26f27a478640b6b83d669440c0a71481f7c865a51da9",
"sha256:10b4ff0ad793d98605958089fabfa350e8e62bd5d40aa65cdc69d6785859f94e",
"sha256:1642eceeaa5ab6c9b6dfeaaa626ae314d808188ab23ae196a34c9d97efb68350",
"sha256:1dac54e8ce2ed83b1f6b1a54005c87dfed139cf3f777fdc8afc76e7841101226",
"sha256:1e69966ea6ef0c14ee53ef7a3d68b564cc408121ea56c0caa2dc918c1b2f553d",
"sha256:1f21bb8d0235fc10c09ce1d11ffbd40fc50d3f08a89e4cf3a0c503dc2562247a",
"sha256:2170816e34e10f2fd120f603e951630f8a112e1be3b60963a1f159f5699059a6",
"sha256:21fef42317cf02e05d3b09c028712e1d73a9606f02467fd803f7c1f39cc59add",
"sha256:249cc6912405917344192b9f9ea5cd5b139d49e0d2f5c7f70bdfaf6b4dbf3a2e",
"sha256:3499c7ffbfd9c6a3d8d6a2b01c26639da7e43d47c7b4f788016226b1e711caa8",
"sha256:3af41686ccec6a0f2bdc66686dc0f403c41ac2089f80e2214a0f82d001052c03",
"sha256:3e23419d832d969f659c208557de4a123e30a10d26e1e14b73431d3c13444c2e",
"sha256:3ea1b59dc06396b0b424740a10a0a63974c725b1c64736ff788a3689d36c02d2",
"sha256:44167fc6a763d534a6908bdb2592269b4bf30a03239bcb1654781adf5e49caf1",
"sha256:479b8c6ebd12aedfe64563b85920525d05d394b85f166b7873c8bde6da612f9c",
"sha256:4af57160800b7a815f3fe0eba9b46bf28aafc195555f1824555fa2cfab6c1538",
"sha256:4b4fa1cb5f270fb3eab079536b764ad740bb749ce69a94d4ec30ceee1b5940d5",
"sha256:4eed954b161e6b9b65f6be446ed448ed3921763cc432053ceb606f89d793927e",
"sha256:541d823548ab69d13d23730a06f97460f4238ad2e5ed966aaf850d7c369782d9",
"sha256:568c1236b2fde93b7720f95a890741854c1200fba4a3471ff48b2934d2d93fd3",
"sha256:5854be2f3e5a729800bac57a8d76af464e160f19676ab6aea74bde18ad19d438",
"sha256:620598717fce1b3bd14dd09947ea53e1ad510317c85dda2c9c65b622edc96b12",
"sha256:6526e5fb4e14f4bbf30411216780c9967c20c5a55f2f51d3abd6de68320cc2f3",
"sha256:6fba278063559acc730abf49845d0e9a9e1ba74f85f0ee6efd5803f08b285853",
"sha256:70d1f9dde0e5dd9e292a6d4d00058737052b01f3532f69c0c65818dac26dc287",
"sha256:731468f555656767cda219ab42e033355fe48c85fbe3ba83a349631541715ba2",
"sha256:81b8fe282183e4a3c7a1b72f5ade1094ed1c6345a8f153506d114af5bf8accd9",
"sha256:84a585799c58b795573c7fa9b84c455adf3e1d72f19a2bf498b54a95ae0d194c",
"sha256:85992ee30a31835fc482468637b3e5bd085fa8fe9392ba0bdcbdc1ef5e9e3c55",
"sha256:8811f3f098a78ffa16e0ea36dffd577eb031aea797cbdba81be039a4169e242c",
"sha256:88a12ad8ccf325a8a5ed80e6d7c3bdc247d66175afedbe104ee2aaca72960d8e",
"sha256:8be8508d110d93061197fd2d6a74f7401f73b6d12f8822bbcd6d74f2b55d71b1",
"sha256:8e2bf8029dbf0810c7bfbc3e594b51c4cc9101fbffb583a3923aea184724203c",
"sha256:929f3ed33743a49ab127c58c3e0a827de0664bfcda566108989a14068f820194",
"sha256:92cde43018a2e17d48bb09c79e4d4cb0e236de5063ce897a5e40ac7cb4878773",
"sha256:92fc484e34b733704ad77210c7957679c5c3877bd1e6b6d74b185e9320cc716e",
"sha256:943a8b052e54dfd6439fd7989f67fc6a7f2138d0a2cf0a7de5f18aa4fe7eb3b1",
"sha256:9d73ee3725b7a737ad86c2eac5c57a4a97793d9f442599bea5ec67ac9f4bdc3d",
"sha256:9f5b3c1ed63c8fa937a920b6c1bec78b74ee09593b3f5b979ab2ae5ef60d7600",
"sha256:9fd46ce0845cfe28f108888b3ab17abff84ff695e01e73657eec3f96d72eef34",
"sha256:a344d5dc18074e3872777b62f5f7d584ae4344cd6006c17ba12103759d407af3",
"sha256:a60804bff28662cbcf340a4d61598891f12eea3a66af48ecfdc975ceec21e3c8",
"sha256:a8f5f7515f3552d899c61202d99dcb17d6e3b0de777900405611cd747cecd1b8",
"sha256:a9b7371665d4f00deb8f32208c7c5e652059b0fda41cf6dbcac6114a041f1cc2",
"sha256:aa54f8ef31d23c506910c21163f22b124facb573bff73930735cf9fe38bf7dff",
"sha256:aba807f9569455cba566882c8938f1a549f205ee43c27b126e5450dc9f83cc62",
"sha256:ae545f31489548c87b0cced5755cfe5a5308d00407000e72c4fa30b19c3220ac",
"sha256:af01e42ad87ae24932138f154105e88da13ce7d202a6de93fafdafb2883a00ef",
"sha256:b540bd67cfb54e6f0865ceccd9979687210d7ed1a1cc8c01f8e67e2f1e883d28",
"sha256:b6212a60e5c482ef90f2d788835387070a88d52cf6241d3916733c9176d39eab",
"sha256:b63de12e44935d5aca7ed7ed98a255a11e5cb47f83a9fded7a5e41c40277d104",
"sha256:ba74ec819177af1ef7f59063c6d35a214a8fde6f987f7661f4f0eecc468a8f76",
"sha256:bb49c7f1e6ebf3821a42d81d494f538107610c3a705987f53068546b0e90303e",
"sha256:bd176afcf8f5d2aed50c3647d4925d0db0579d96f75a31e77cbaf67d8a87742d",
"sha256:bd7227b87a355ce1f4bf83bfae4399b1f5bb42e0259cb9405824bd03d2f4336a",
"sha256:bf8d9bfee991d8acc72d060d53860f356e07a50f0e0d09a8dfedea1c554dd0d5",
"sha256:bfde76a8f430cf5c5584553adf9926534352251d379dcb266ad2b93c54a29745",
"sha256:c341c7d868750e31961d6d8e60ff040fb9d3d3a46d77fd85e1ab8e76c3e9a5c4",
"sha256:c7a06301c2fb096bdb0bd25fe2011531c1453b9f2c163c8031600ec73af1cc99",
"sha256:cb23d8bb86282b342481cad4370ea0853a39e4a32a0042bb52ca6bdde132df43",
"sha256:d119fafe7b634dbfa25a8c597718e69a930e4847f0b88e172744be24515140da",
"sha256:d40f9da8cabbf295d3a9dae1295c69975b86d941bc20f0a087f0477fa0a66231",
"sha256:d6c9af134da4bc9b3bd3e6a70072509f295d10ee60c697826225b60b9959acdd",
"sha256:dd7659baae9ccf94ae5fe8bfaa2c7bc2e94d24611528395ce88d009107e00c6d",
"sha256:de8d38f1c2810fa2a4f1d995a2e9c70bb8737b18da04ac2afbf3971f65781d87",
"sha256:e595c591a48bbc295ebf47cb91aebf9bd32f3ff76749ecf282ea7f9f6bb73886",
"sha256:ec2aa89305006fba9ffb98970db6c8221541be7bee4c1d027421d6f6df7d1ce2",
"sha256:ec82bf1fda6cecce7f7b915f9196601a1bd1a3079796b76d16ae4cce6d0ef89b",
"sha256:ed9ee95614a71e87f1a70bc81603f6c6760128b140bc4030abe6abaa988f1c3d",
"sha256:f047569d655f81cb70ea5be942ee5d4421b6219c3f05d131f64088c73bb0917f",
"sha256:ffa336210cf9cd8ed117011085817d00abe4c08f99968deef0013ea283547204",
"sha256:ffb3dc385f6bb1568aa974fe65da84723210e5d9707e360e9ecb51f59406cd2e"
],
"markers": "python_version >= '3.9'",
"version": "==3.11.10"
"version": "==3.11.11"
},
"aiohttp-socks": {
"hashes": [
"sha256:5b320d1bb156fc56d0b31f9de8d5b9b0affbcf1f2df9b8172334dc10e63e4e2f",
"sha256:8e30dff7cd21806979bfa76ef5697ca03b05665521bc00e6e0d7fd029c917886"
"sha256:146d9b0a921b712112a2da3d63633141eb63710b949102ccecc1ab1bb2e2548f",
"sha256:d68f30f86e89b3d601bfa87211dc9b616cd360f835a0c80544361b37e8c73610"
],
"index": "pypi",
"markers": "python_full_version >= '3.8.0'",
"version": "==0.9.1"
"version": "==0.9.2"
},
"aioqbt": {
"git": "git+https://github.com/mhdzumair/aioqbt.git",
@@ -137,12 +137,12 @@
},
"aioseedrcc": {
"hashes": [
"sha256:1c6616196d1a00a0e2477fae356d297c295e3546b571314678eb1cdbca33528f",
"sha256:cbb11c531f75d040137bd172143d6599190e7252da14c6290b6299febfec0e80"
"sha256:00ca6256e2092fe259d2a81b151dd55e348e83150c7ce8d8c8c6d97a8ba5319e",
"sha256:4810e24f9371b32a743987d6a45e0ec477f5eb6cebd64b22fe75d29095dbfff3"
],
"index": "pypi",
"markers": "python_version >= '3.10'",
"version": "==0.3.1"
"version": "==0.3.2"
},
"aiosignal": {
"hashes": [
@@ -196,11 +196,11 @@
},
"attrs": {
"hashes": [
"sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346",
"sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"
"sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff",
"sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308"
],
"markers": "python_version >= '3.7'",
"version": "==24.2.0"
"markers": "python_version >= '3.8'",
"version": "==24.3.0"
},
"automat": {
"hashes": [
@@ -434,11 +434,11 @@
},
"click": {
"hashes": [
"sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28",
"sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"
"sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2",
"sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"
],
"markers": "python_version >= '3.7'",
"version": "==8.1.7"
"version": "==8.1.8"
},
"click-loglevel": {
"hashes": [
@@ -1046,12 +1046,12 @@
},
"jinja2": {
"hashes": [
"sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369",
"sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"
"sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb",
"sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==3.1.4"
"version": "==3.1.5"
},
"jmespath": {
"hashes": [
@@ -1792,118 +1792,118 @@
},
"pydantic": {
"hashes": [
"sha256:be04d85bbc7b65651c5f8e6b9976ed9c6f41782a55524cef079a34a0bb82144d",
"sha256:cb5ac360ce894ceacd69c403187900a02c4b20b693a9dd1d643e1effab9eadf9"
"sha256:597e135ea68be3a37552fb524bc7d0d66dcf93d395acd93a00682f1efcb8ee3d",
"sha256:82f12e9723da6de4fe2ba888b5971157b3be7ad914267dea8f05f82b28254f06"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==2.10.3"
"version": "==2.10.4"
},
"pydantic-core": {
"hashes": [
"sha256:00e6424f4b26fe82d44577b4c842d7df97c20be6439e8e685d0d715feceb9fb9",
"sha256:029d9757eb621cc6e1848fa0b0310310de7301057f623985698ed7ebb014391b",
"sha256:02a3d637bd387c41d46b002f0e49c52642281edacd2740e5a42f7017feea3f2c",
"sha256:0325336f348dbee6550d129b1627cb8f5351a9dc91aad141ffb96d4937bd9529",
"sha256:062f60e512fc7fff8b8a9d680ff0ddaaef0193dba9fa83e679c0c5f5fbd018bc",
"sha256:0b3dfe500de26c52abe0477dde16192ac39c98f05bf2d80e76102d394bd13854",
"sha256:0e4216e64d203e39c62df627aa882f02a2438d18a5f21d7f721621f7a5d3611d",
"sha256:121ceb0e822f79163dd4699e4c54f5ad38b157084d97b34de8b232bcaad70278",
"sha256:159cac0a3d096f79ab6a44d77a961917219707e2a130739c64d4dd46281f5c2a",
"sha256:15aae984e46de8d376df515f00450d1522077254ef6b7ce189b38ecee7c9677c",
"sha256:15cc53a3179ba0fcefe1e3ae50beb2784dede4003ad2dfd24f81bba4b23a454f",
"sha256:161c27ccce13b6b0c8689418da3885d3220ed2eae2ea5e9b2f7f3d48f1d52c27",
"sha256:19910754e4cc9c63bc1c7f6d73aa1cfee82f42007e407c0f413695c2f7ed777f",
"sha256:1ba5e3963344ff25fc8c40da90f44b0afca8cfd89d12964feb79ac1411a260ac",
"sha256:1c00666a3bd2f84920a4e94434f5974d7bbc57e461318d6bb34ce9cdbbc1f6b2",
"sha256:1c39b07d90be6b48968ddc8c19e7585052088fd7ec8d568bb31ff64c70ae3c97",
"sha256:206b5cf6f0c513baffaeae7bd817717140770c74528f3e4c3e1cec7871ddd61a",
"sha256:258c57abf1188926c774a4c94dd29237e77eda19462e5bb901d88adcab6af919",
"sha256:2cdf7d86886bc6982354862204ae3b2f7f96f21a3eb0ba5ca0ac42c7b38598b9",
"sha256:2d4567c850905d5eaaed2f7a404e61012a51caf288292e016360aa2b96ff38d4",
"sha256:35c14ac45fcfdf7167ca76cc80b2001205a8d5d16d80524e13508371fb8cdd9c",
"sha256:38de0a70160dd97540335b7ad3a74571b24f1dc3ed33f815f0880682e6880131",
"sha256:3af385b0cee8df3746c3f406f38bcbfdc9041b5c2d5ce3e5fc6637256e60bbc5",
"sha256:3b748c44bb9f53031c8cbc99a8a061bc181c1000c60a30f55393b6e9c45cc5bd",
"sha256:3bbd5d8cc692616d5ef6fbbbd50dbec142c7e6ad9beb66b78a96e9c16729b089",
"sha256:3ccaa88b24eebc0f849ce0a4d09e8a408ec5a94afff395eb69baf868f5183107",
"sha256:3fa80ac2bd5856580e242dbc202db873c60a01b20309c8319b5c5986fbe53ce6",
"sha256:4228b5b646caa73f119b1ae756216b59cc6e2267201c27d3912b592c5e323b60",
"sha256:42b0e23f119b2b456d07ca91b307ae167cc3f6c846a7b169fca5326e32fdc6cf",
"sha256:45cf8588c066860b623cd11c4ba687f8d7175d5f7ef65f7129df8a394c502de5",
"sha256:45d9c5eb9273aa50999ad6adc6be5e0ecea7e09dbd0d31bd0c65a55a2592ca08",
"sha256:4603137322c18eaf2e06a4495f426aa8d8388940f3c457e7548145011bb68e05",
"sha256:46ccfe3032b3915586e469d4972973f893c0a2bb65669194a5bdea9bacc088c2",
"sha256:4fefee876e07a6e9aad7a8c8c9f85b0cdbe7df52b8a9552307b09050f7512c7e",
"sha256:5556470f1a2157031e676f776c2bc20acd34c1990ca5f7e56f1ebf938b9ab57c",
"sha256:57866a76e0b3823e0b56692d1a0bf722bffb324839bb5b7226a7dbd6c9a40b17",
"sha256:5897bec80a09b4084aee23f9b73a9477a46c3304ad1d2d07acca19723fb1de62",
"sha256:58ca98a950171f3151c603aeea9303ef6c235f692fe555e883591103da709b23",
"sha256:5ca038c7f6a0afd0b2448941b6ef9d5e1949e999f9e5517692eb6da58e9d44be",
"sha256:5f6c8a66741c5f5447e047ab0ba7a1c61d1e95580d64bce852e3df1f895c4067",
"sha256:5f8c4718cd44ec1580e180cb739713ecda2bdee1341084c1467802a417fe0f02",
"sha256:5fde892e6c697ce3e30c61b239330fc5d569a71fefd4eb6512fc6caec9dd9e2f",
"sha256:62a763352879b84aa31058fc931884055fd75089cccbd9d58bb6afd01141b235",
"sha256:62ba45e21cf6571d7f716d903b5b7b6d2617e2d5d67c0923dc47b9d41369f840",
"sha256:64c65f40b4cd8b0e049a8edde07e38b476da7e3aaebe63287c899d2cff253fa5",
"sha256:655d7dd86f26cb15ce8a431036f66ce0318648f8853d709b4167786ec2fa4807",
"sha256:66ff044fd0bb1768688aecbe28b6190f6e799349221fb0de0e6f4048eca14c16",
"sha256:672ebbe820bb37988c4d136eca2652ee114992d5d41c7e4858cdd90ea94ffe5c",
"sha256:6b9af86e1d8e4cfc82c2022bfaa6f459381a50b94a29e95dcdda8442d6d83864",
"sha256:6e0bd57539da59a3e4671b90a502da9a28c72322a4f17866ba3ac63a82c4498e",
"sha256:71a5e35c75c021aaf400ac048dacc855f000bdfed91614b4a726f7432f1f3d6a",
"sha256:7597c07fbd11515f654d6ece3d0e4e5093edc30a436c63142d9a4b8e22f19c35",
"sha256:764be71193f87d460a03f1f7385a82e226639732214b402f9aa61f0d025f0737",
"sha256:7699b1df36a48169cdebda7ab5a2bac265204003f153b4bd17276153d997670a",
"sha256:7ccebf51efc61634f6c2344da73e366c75e735960b5654b63d7e6f69a5885fa3",
"sha256:7f7059ca8d64fea7f238994c97d91f75965216bcbe5f695bb44f354893f11d52",
"sha256:8065914ff79f7eab1599bd80406681f0ad08f8e47c880f17b416c9f8f7a26d05",
"sha256:816f5aa087094099fff7edabb5e01cc370eb21aa1a1d44fe2d2aefdfb5599b31",
"sha256:81f2ec23ddc1b476ff96563f2e8d723830b06dceae348ce02914a37cb4e74b89",
"sha256:84286494f6c5d05243456e04223d5a9417d7f443c3b76065e75001beb26f88de",
"sha256:8bf7b66ce12a2ac52d16f776b31d16d91033150266eb796967a7e4621707e4f6",
"sha256:8f1edcea27918d748c7e5e4d917297b2a0ab80cad10f86631e488b7cddf76a36",
"sha256:981fb88516bd1ae8b0cbbd2034678a39dedc98752f264ac9bc5839d3923fa04c",
"sha256:98476c98b02c8e9b2eec76ac4156fd006628b1b2d0ef27e548ffa978393fd154",
"sha256:992cea5f4f3b29d6b4f7f1726ed8ee46c8331c6b4eed6db5b40134c6fe1768bb",
"sha256:9a3b0793b1bbfd4146304e23d90045f2a9b5fd5823aa682665fbdaf2a6c28f3e",
"sha256:9a42d6a8156ff78981f8aa56eb6394114e0dedb217cf8b729f438f643608cbcd",
"sha256:9c10c309e18e443ddb108f0ef64e8729363adbfd92d6d57beec680f6261556f3",
"sha256:9cbd94fc661d2bab2bc702cddd2d3370bbdcc4cd0f8f57488a81bcce90c7a54f",
"sha256:9fdcf339322a3fae5cbd504edcefddd5a50d9ee00d968696846f089b4432cf78",
"sha256:a0697803ed7d4af5e4c1adf1670af078f8fcab7a86350e969f454daf598c4960",
"sha256:a28af0695a45f7060e6f9b7092558a928a28553366519f64083c63a44f70e618",
"sha256:a2e02889071850bbfd36b56fd6bc98945e23670773bc7a76657e90e6b6603c08",
"sha256:a33cd6ad9017bbeaa9ed78a2e0752c5e250eafb9534f308e7a5f7849b0b1bfb4",
"sha256:a3cb37038123447cf0f3ea4c74751f6a9d7afef0eb71aa07bf5f652b5e6a132c",
"sha256:a57847b090d7892f123726202b7daa20df6694cbd583b67a592e856bff603d6c",
"sha256:a5a8e19d7c707c4cadb8c18f5f60c843052ae83c20fa7d44f41594c644a1d330",
"sha256:ac3b20653bdbe160febbea8aa6c079d3df19310d50ac314911ed8cc4eb7f8cb8",
"sha256:ac6c2c45c847bbf8f91930d88716a0fb924b51e0c6dad329b793d670ec5db792",
"sha256:acc07b2cfc5b835444b44a9956846b578d27beeacd4b52e45489e93276241025",
"sha256:aee66be87825cdf72ac64cb03ad4c15ffef4143dbf5c113f64a5ff4f81477bf9",
"sha256:af52d26579b308921b73b956153066481f064875140ccd1dfd4e77db89dbb12f",
"sha256:b94d4ba43739bbe8b0ce4262bcc3b7b9f31459ad120fb595627eaeb7f9b9ca01",
"sha256:ba630d5e3db74c79300d9a5bdaaf6200172b107f263c98a0539eeecb857b2337",
"sha256:bed0f8a0eeea9fb72937ba118f9db0cb7e90773462af7962d382445f3005e5a4",
"sha256:bf99c8404f008750c846cb4ac4667b798a9f7de673ff719d705d9b2d6de49c5f",
"sha256:c3027001c28434e7ca5a6e1e527487051136aa81803ac812be51802150d880dd",
"sha256:c65af9088ac534313e1963443d0ec360bb2b9cba6c2909478d22c2e363d98a51",
"sha256:d0165ab2914379bd56908c02294ed8405c252250668ebcb438a55494c69f44ab",
"sha256:d1b26e1dff225c31897696cab7d4f0a315d4c0d9e8666dbffdb28216f3b17fdc",
"sha256:d950caa237bb1954f1b8c9227b5065ba6875ac9771bb8ec790d956a699b78676",
"sha256:dc61505e73298a84a2f317255fcc72b710b72980f3a1f670447a21efc88f8381",
"sha256:e173486019cc283dc9778315fa29a363579372fe67045e971e89b6365cc035ed",
"sha256:e1f735dc43da318cad19b4173dd1ffce1d84aafd6c9b782b3abc04a0d5a6f5bb",
"sha256:e9386266798d64eeb19dd3677051f5705bf873e98e15897ddb7d76f477131967",
"sha256:f216dbce0e60e4d03e0c4353c7023b202d95cbaeff12e5fd2e82ea0a66905073",
"sha256:f4e5658dbffe8843a0f12366a4c2d1c316dbe09bb4dfbdc9d2d9cd6031de8aae",
"sha256:f5a823165e6d04ccea61a9f0576f345f8ce40ed533013580e087bd4d7442b52c",
"sha256:f69ed81ab24d5a3bd93861c8c4436f54afdf8e8cc421562b0c7504cf3be58206",
"sha256:f82d068a2d6ecfc6e054726080af69a6764a10015467d7d7b9f66d6ed5afa23b"
"sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278",
"sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50",
"sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9",
"sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f",
"sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6",
"sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc",
"sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54",
"sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630",
"sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9",
"sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236",
"sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7",
"sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee",
"sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b",
"sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048",
"sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc",
"sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130",
"sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4",
"sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd",
"sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4",
"sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7",
"sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7",
"sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4",
"sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e",
"sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa",
"sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6",
"sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962",
"sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b",
"sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f",
"sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474",
"sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5",
"sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459",
"sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf",
"sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a",
"sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c",
"sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76",
"sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362",
"sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4",
"sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934",
"sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320",
"sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118",
"sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96",
"sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306",
"sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046",
"sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3",
"sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2",
"sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af",
"sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9",
"sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67",
"sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a",
"sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27",
"sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35",
"sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b",
"sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151",
"sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b",
"sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154",
"sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133",
"sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef",
"sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145",
"sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15",
"sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4",
"sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc",
"sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee",
"sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c",
"sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0",
"sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5",
"sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57",
"sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b",
"sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8",
"sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1",
"sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da",
"sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e",
"sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc",
"sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993",
"sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656",
"sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4",
"sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c",
"sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb",
"sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d",
"sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9",
"sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e",
"sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1",
"sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc",
"sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a",
"sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9",
"sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506",
"sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b",
"sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1",
"sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d",
"sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99",
"sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3",
"sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31",
"sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c",
"sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39",
"sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a",
"sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308",
"sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2",
"sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228",
"sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b",
"sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9",
"sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"
],
"markers": "python_version >= '3.8'",
"version": "==2.27.1"
"version": "==2.27.2"
},
"pydantic-settings": {
"hashes": [
@@ -2026,12 +2026,12 @@
},
"python-multipart": {
"hashes": [
"sha256:905502ef39050557b7a6af411f454bc19526529ca46ae6831508438890ce12cc",
"sha256:f8d5b0b9c618575bf9df01c684ded1d94a338839bdd8223838afacfb4bb2082d"
"sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104",
"sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==0.0.19"
"version": "==0.0.20"
},
"python-socks": {
"extras": [
@@ -2128,97 +2128,97 @@
},
"rapidfuzz": {
"hashes": [
"sha256:00d02cbd75d283c287471b5b3738b3e05c9096150f93f2d2dfa10b3d700f2db9",
"sha256:031f8b367e5d92f7a1e27f7322012f3c321c3110137b43cc3bf678505583ef48",
"sha256:073a5b107e17ebd264198b78614c0206fa438cce749692af5bc5f8f484883f50",
"sha256:0b75fe506c8e02769cc47f5ab21ce3e09b6211d3edaa8f8f27331cb6988779be",
"sha256:0e06d99ad1ad97cb2ef7f51ec6b1fedd74a3a700e4949353871cf331d07b382a",
"sha256:0fff4a6b87c07366662b62ae994ffbeadc472e72f725923f94b72a3db49f4671",
"sha256:10746c1d4c8cd8881c28a87fd7ba0c9c102346dfe7ff1b0d021cdf093e9adbff",
"sha256:1340b56340896bede246f612b6ecf685f661a56aabef3d2512481bfe23ac5835",
"sha256:18123168cba156ab5794ea6de66db50f21bb3c66ae748d03316e71b27d907b95",
"sha256:187d9747149321607be4ccd6f9f366730078bed806178ec3eeb31d05545e9e8f",
"sha256:191633722203f5b7717efcb73a14f76f3b124877d0608c070b827c5226d0b972",
"sha256:195baad28057ec9609e40385991004e470af9ef87401e24ebe72c064431524ab",
"sha256:1996feb7a61609fa842e6b5e0c549983222ffdedaf29644cc67e479902846dfe",
"sha256:1b35a118d61d6f008e8e3fb3a77674d10806a8972c7b8be433d6598df4d60b01",
"sha256:1e6bbca9246d9eedaa1c84e04a7f555493ba324d52ae4d9f3d9ddd1b740dcd87",
"sha256:1e96c84d6c2a0ca94e15acb5399118fff669f4306beb98a6d8ec6f5dccab4412",
"sha256:2316515169b7b5a453f0ce3adbc46c42aa332cae9f2edb668e24d1fc92b2f2bb",
"sha256:231ef1ec9cf7b59809ce3301006500b9d564ddb324635f4ea8f16b3e2a1780da",
"sha256:237bec5dd1bfc9b40bbd786cd27949ef0c0eb5fab5eb491904c6b5df59d39d3c",
"sha256:26f71582c0d62445067ee338ddad99b655a8f4e4ed517a90dcbfbb7d19310474",
"sha256:2cf44d01bfe8ee605b7eaeecbc2b9ca64fc55765f17b304b40ed8995f69d7716",
"sha256:335fee93188f8cd585552bb8057228ce0111bd227fa81bfd40b7df6b75def8ab",
"sha256:3611c8f45379a12063d70075c75134f2a8bd2e4e9b8a7995112ddae95ca1c982",
"sha256:365e4fc1a2b95082c890f5e98489b894e6bf8c338c6ac89bb6523c2ca6e9f086",
"sha256:36c0e1483e21f918d0f2f26799fe5ac91c7b0c34220b73007301c4f831a9c4c7",
"sha256:38b0dac2c8e057562b8f0d8ae5b663d2d6a28c5ab624de5b73cef9abb6129a24",
"sha256:39c4983e2e2ccb9732f3ac7d81617088822f4a12291d416b09b8a1eadebb3e29",
"sha256:3c3b537b97ac30da4b73930fa8a4fe2f79c6d1c10ad535c5c09726612cd6bed9",
"sha256:425f4ac80b22153d391ee3f94bc854668a0c6c129f05cf2eaf5ee74474ddb69e",
"sha256:440b5608ab12650d0390128d6858bc839ae77ffe5edf0b33a1551f2fa9860651",
"sha256:4ffed25f9fdc0b287f30a98467493d1e1ce5b583f6317f70ec0263b3c97dbba6",
"sha256:54bcf4efaaee8e015822be0c2c28214815f4f6b4f70d8362cfecbd58a71188ac",
"sha256:565c2bd4f7d23c32834652b27b51dd711814ab614b4e12add8476be4e20d1cf5",
"sha256:567f88180f2c1423b4fe3f3ad6e6310fc97b85bdba574801548597287fc07028",
"sha256:5a15546d847a915b3f42dc79ef9b0c78b998b4e2c53b252e7166284066585979",
"sha256:616290fb9a8fa87e48cb0326d26f98d4e29f17c3b762c2d586f2b35c1fd2034b",
"sha256:65a2fa13e8a219f9b5dcb9e74abe3ced5838a7327e629f426d333dfc8c5a6e66",
"sha256:666d5d8b17becc3f53447bcb2b6b33ce6c2df78792495d1fa82b2924cd48701a",
"sha256:6729b856166a9e95c278410f73683957ea6100c8a9d0a8dbe434c49663689255",
"sha256:6b2cd7c29d6ecdf0b780deb587198f13213ac01c430ada6913452fd0c40190fc",
"sha256:6fde3bbb14e92ce8fcb5c2edfff72e474d0080cadda1c97785bf4822f037a309",
"sha256:75561f3df9a906aaa23787e9992b228b1ab69007932dc42070f747103e177ba8",
"sha256:779027d3307e1a2b1dc0c03c34df87a470a368a1a0840a9d2908baf2d4067956",
"sha256:7b6015da2e707bf632a71772a2dbf0703cff6525732c005ad24987fe86e8ec32",
"sha256:7f4f43f2204b56a61448ec2dd061e26fd344c404da99fb19f3458200c5874ba2",
"sha256:82cac41a411e07a6f3dc80dfbd33f6be70ea0abd72e99c59310819d09f07d945",
"sha256:8a2ef08b27167bcff230ffbfeedd4c4fa6353563d6aaa015d725dd3632fc3de7",
"sha256:8d1b7082104d596a3eb012e0549b2634ed15015b569f48879701e9d8db959dbb",
"sha256:8e06fe6a12241ec1b72c0566c6b28cda714d61965d86569595ad24793d1ab259",
"sha256:9141fb0592e55f98fe9ac0f3ce883199b9c13e262e0bf40c5b18cdf926109d16",
"sha256:92958ae075c87fef393f835ed02d4fe8d5ee2059a0934c6c447ea3417dfbf0e8",
"sha256:958473c9f0bca250590200fd520b75be0dbdbc4a7327dc87a55b6d7dc8d68552",
"sha256:9a0d519ff39db887cd73f4e297922786d548f5c05d6b51f4e6754f452a7f4296",
"sha256:9d81bf186a453a2757472133b24915768abc7c3964194406ed93e170e16c21cb",
"sha256:9da82aa4b46973aaf9e03bb4c3d6977004648c8638febfc0f9d237e865761270",
"sha256:9ef60dfa73749ef91cb6073be1a3e135f4846ec809cc115f3cbfc6fe283a5584",
"sha256:9f912d459e46607ce276128f52bea21ebc3e9a5ccf4cccfef30dd5bddcf47be8",
"sha256:a1d9aa156ed52d3446388ba4c2f335e312191d1ca9d1f5762ee983cf23e4ecf6",
"sha256:a7fbac18f2c19fc983838a60611e67e3262e36859994c26f2ee85bb268de2355",
"sha256:aaf83e9170cb1338922ae42d320699dccbbdca8ffed07faeb0b9257822c26e24",
"sha256:ac4452f182243cfab30ba4668ef2de101effaedc30f9faabb06a095a8c90fd16",
"sha256:ac7adee6bcf0c6fee495d877edad1540a7e0f5fc208da03ccb64734b43522d7a",
"sha256:b31f358a70efc143909fb3d75ac6cd3c139cd41339aa8f2a3a0ead8315731f2b",
"sha256:ba7521e072c53e33c384e78615d0718e645cab3c366ecd3cc8cb732befd94967",
"sha256:bc308d79a7e877226f36bdf4e149e3ed398d8277c140be5c1fd892ec41739e6d",
"sha256:bebb7bc6aeb91cc57e4881b222484c26759ca865794187217c9dcea6c33adae6",
"sha256:bfa48a4a2d45a41457f0840c48e579db157a927f4e97acf6e20df8fc521c79de",
"sha256:c0c955e32afdbfdf6e9ee663d24afb25210152d98c26d22d399712d29a9b976b",
"sha256:c34c022d5ad564f1a5a57a4a89793bd70d7bad428150fb8ff2760b223407cdcf",
"sha256:c5da802a0d085ad81b0f62828fb55557996c497b2d0b551bbdfeafd6d447892f",
"sha256:cf654702f144beaa093103841a2ea6910d617d0bb3fccb1d1fd63c54dde2cd49",
"sha256:cfcc8feccf63245a22dfdd16e222f1a39771a44b870beb748117a0e09cbb4a62",
"sha256:d02cf8e5af89a9ac8f53c438ddff6d773f62c25c6619b29db96f4aae248177c0",
"sha256:d99c1cd9443b19164ec185a7d752f4b4db19c066c136f028991a480720472e23",
"sha256:dfa64b89dcb906835e275187569e51aa9d546a444489e97aaf2cc84011565fbe",
"sha256:e8e154b84a311263e1aca86818c962e1fa9eefdd643d1d5d197fcd2738f88cb9",
"sha256:ec108bf25de674781d0a9a935030ba090c78d49def3d60f8724f3fc1e8e75024",
"sha256:ed4f3adc1294834955b7e74edd3c6bd1aad5831c007f2d91ea839e76461a5879",
"sha256:edd062490537e97ca125bc6c7f2b7331c2b73d21dc304615afe61ad1691e15d5",
"sha256:efa1582a397da038e2f2576c9cd49b842f56fde37d84a6b0200ffebc08d82350",
"sha256:f017dbfecc172e2d0c37cf9e3d519179d71a7f16094b57430dffc496a098aa17",
"sha256:f12912acee1f506f974f58de9fdc2e62eea5667377a7e9156de53241c05fdba8",
"sha256:f17d9f21bf2f2f785d74f7b0d407805468b4c173fa3e52c86ec94436b338e74a",
"sha256:f1da2028cb4e41be55ee797a82d6c1cf589442504244249dfeb32efc608edee7",
"sha256:f3bb81d4fe6a5d20650f8c0afcc8f6e1941f6fecdb434f11b874c42467baded0",
"sha256:f98f36c6a1bb9a6c8bbec99ad87c8c0e364f34761739b5ea9adf7b48129ae8cf",
"sha256:fc22d69a1c9cccd560a5c434c0371b2df0f47c309c635a01a913e03bbf183710",
"sha256:fe07f8b9c3bb5c5ad1d2c66884253e03800f4189a60eb6acd6119ebaf3eb9894"
"sha256:0b488b244931d0291412917e6e46ee9f6a14376625e150056fe7c4426ef28225",
"sha256:1315cd2a351144572e31fe3df68340d4b83ddec0af8b2e207cd32930c6acd037",
"sha256:1bac4873f6186f5233b0084b266bfb459e997f4c21fc9f029918f44a9eccd304",
"sha256:1cb1965a28b0fa64abdee130c788a0bc0bb3cf9ef7e3a70bf055c086c14a3d7e",
"sha256:22033677982b9c4c49676f215b794b0404073f8974f98739cb7234e4a9ade9ad",
"sha256:231c8b2efbd7f8d2ecd1ae900363ba168b8870644bb8f2b5aa96e4a7573bde19",
"sha256:25398d9ac7294e99876a3027ffc52c6bebeb2d702b1895af6ae9c541ee676702",
"sha256:2c87319b0ab9d269ab84f6453601fd49b35d9e4a601bbaef43743f26fabf496c",
"sha256:3048c6ed29d693fba7d2a7caf165f5e0bb2b9743a0989012a98a47b975355cca",
"sha256:339607394941801e6e3f6c1ecd413a36e18454e7136ed1161388de674f47f9d9",
"sha256:3794df87313dfb56fafd679b962e0613c88a293fd9bd5dd5c2793d66bf06a101",
"sha256:3857e335f97058c4b46fa39ca831290b70de554a5c5af0323d2f163b19c5f2a6",
"sha256:3871fa7dfcef00bad3c7e8ae8d8fd58089bad6fb21f608d2bf42832267ca9663",
"sha256:3f28952da055dbfe75828891cd3c9abf0984edc8640573c18b48c14c68ca5e06",
"sha256:42f4dd264ada7a9aa0805ea0da776dc063533917773cf2df5217f14eb4429eae",
"sha256:4416ca69af933d4a8ad30910149d3db6d084781d5c5fdedb713205389f535385",
"sha256:4469307f464ae3089acf3210b8fc279110d26d10f79e576f385a98f4429f7d97",
"sha256:4513dd01cee11e354c31b75f652d4d466c9440b6859f84e600bdebfccb17735a",
"sha256:45b15b8a118856ac9caac6877f70f38b8a0d310475d50bc814698659eabc1cdb",
"sha256:494eef2c68305ab75139034ea25328a04a548d297712d9cf887bf27c158c388b",
"sha256:4d0d26c7172bdb64f86ee0765c5b26ea1dc45c52389175888ec073b9b28f4305",
"sha256:4f9f12c2d0aa52b86206d2059916153876a9b1cf9dfb3cf2f344913167f1c3d4",
"sha256:51f24cb39e64256221e6952f22545b8ce21cacd59c0d3e367225da8fc4b868d8",
"sha256:54e7f442fb9cca81e9df32333fb075ef729052bcabe05b0afc0441f462299114",
"sha256:5a167344c1d6db06915fb0225592afdc24d8bafaaf02de07d4788ddd37f4bc2f",
"sha256:5b659e1e2ea2784a9a397075a7fc395bfa4fe66424042161c4bcaf6e4f637b38",
"sha256:5bb636b0150daa6d3331b738f7c0f8b25eadc47f04a40e5c23c4bfb4c4e20ae3",
"sha256:5e8ea35f2419c7d56b3e75fbde2698766daedb374f20eea28ac9b1f668ef4f74",
"sha256:5e8f93bc736020351a6f8e71666e1f486bb8bd5ce8112c443a30c77bfde0eb68",
"sha256:62171b270ecc4071be1c1f99960317db261d4c8c83c169e7f8ad119211fe7397",
"sha256:6668321f90aa02a5a789d4e16058f2e4f2692c5230252425c3532a8a62bc3424",
"sha256:6ad02bab756751c90fa27f3069d7b12146613061341459abf55f8190d899649f",
"sha256:6b01c1ddbb054283797967ddc5433d5c108d680e8fa2684cf368be05407b07e4",
"sha256:714a7ba31ba46b64d30fccfe95f8013ea41a2e6237ba11a805a27cdd3bce2573",
"sha256:76a4a11ba8f678c9e5876a7d465ab86def047a4fcc043617578368755d63a1bc",
"sha256:7864e80a0d4e23eb6194254a81ee1216abdc53f9dc85b7f4d56668eced022eb8",
"sha256:82497f244aac10b20710448645f347d862364cc4f7d8b9ba14bd66b5ce4dec18",
"sha256:84819390a36d6166cec706b9d8f0941f115f700b7faecab5a7e22fc367408bc3",
"sha256:8724a978f8af7059c5323d523870bf272a097478e1471295511cf58b2642ff83",
"sha256:8b63cb1f2eb371ef20fb155e95efd96e060147bdd4ab9fc400c97325dfee9fe1",
"sha256:8c7af25bda96ac799378ac8aba54a8ece732835c7b74cfc201b688a87ed11152",
"sha256:8dd501de6f7a8f83557d20613b58734d1cb5f0be78d794cde64fe43cfc63f5f2",
"sha256:8ed59044aea9eb6c663112170f2399b040d5d7b162828b141f2673e822093fa8",
"sha256:906f1f2a1b91c06599b3dd1be207449c5d4fc7bd1e1fa2f6aef161ea6223f165",
"sha256:92ebb7c12f682b5906ed98429f48a3dd80dd0f9721de30c97a01473d1a346576",
"sha256:99aebef8268f2bc0b445b5640fd3312e080bd17efd3fbae4486b20ac00466308",
"sha256:9a1b3ebc62d4bcdfdeba110944a25ab40916d5383c5e57e7c4a8dc0b6c17211a",
"sha256:9a52eea839e4bdc72c5e60a444d26004da00bb5bc6301e99b3dde18212e41465",
"sha256:9c6d7fea39cb33e71de86397d38bf7ff1a6273e40367f31d05761662ffda49e4",
"sha256:a53ca4d3f52f00b393fab9b5913c5bafb9afc27d030c8a1db1283da6917a860f",
"sha256:a7743cca45b4684c54407e8638f6d07b910d8d811347b9d42ff21262c7c23245",
"sha256:aaf391fb6715866bc14681c76dc0308f46877f7c06f61d62cc993b79fc3c4a2a",
"sha256:ab9eab33ee3213f7751dc07a1a61b8d9a3d748ca4458fffddd9defa6f0493c16",
"sha256:b04f29735bad9f06bb731c214f27253bd8bedb248ef9b8a1b4c5bde65b838454",
"sha256:b1472986fd9c5d318399a01a0881f4a0bf4950264131bb8e2deba9df6d8c362b",
"sha256:b1d67d67f89e4e013a5295e7523bc34a7a96f2dba5dd812c7c8cb65d113cbf28",
"sha256:b1f7efdd7b7adb32102c2fa481ad6f11923e2deb191f651274be559d56fc913b",
"sha256:b2669eafee38c5884a6e7cc9769d25c19428549dcdf57de8541cf9e82822e7db",
"sha256:ba26d87fe7fcb56c4a53b549a9e0e9143f6b0df56d35fe6ad800c902447acd5b",
"sha256:be15496e7244361ff0efcd86e52559bacda9cd975eccf19426a0025f9547c792",
"sha256:c36539ed2c0173b053dafb221458812e178cfa3224ade0960599bec194637048",
"sha256:c408f09649cbff8da76f8d3ad878b64ba7f7abdad1471efb293d2c075e80c822",
"sha256:cd340bbd025302276b5aa221dccfe43040c7babfc32f107c36ad783f2ffd8775",
"sha256:d0edecc3f90c2653298d380f6ea73b536944b767520c2179ec5d40b9145e47aa",
"sha256:d2a0f7e17f33e7890257367a1662b05fecaf56625f7dbb6446227aaa2b86448b",
"sha256:d71da0012face6f45432a11bc59af19e62fac5a41f8ce489e80c0add8153c3d1",
"sha256:d895998fec712544c13cfe833890e0226585cf0391dd3948412441d5d68a2b8c",
"sha256:d95f9e9f3777b96241d8a00d6377cc9c716981d828b5091082d0fe3a2924b43e",
"sha256:d9727b85511b912571a76ce53c7640ba2c44c364e71cef6d7359b5412739c570",
"sha256:d98a46cf07c0c875d27e8a7ed50f304d83063e49b9ab63f21c19c154b4c0d08d",
"sha256:d994cf27e2f874069884d9bddf0864f9b90ad201fcc9cb2f5b82bacc17c8d5f2",
"sha256:dc0e0d41ad8a056a9886bac91ff9d9978e54a244deb61c2972cc76b66752de9c",
"sha256:dfaefe08af2a928e72344c800dcbaf6508e86a4ed481e28355e8d4b6a6a5230e",
"sha256:e60814edd0c9b511b5f377d48b9782b88cfe8be07a98f99973669299c8bb318a",
"sha256:eb8a54543d16ab1b69e2c5ed96cabbff16db044a50eddfc028000138ca9ddf33",
"sha256:eb97c53112b593f89a90b4f6218635a9d1eea1d7f9521a3b7d24864228bbc0aa",
"sha256:ebadd5b8624d8ad503e505a99b8eb26fe3ea9f8e9c2234e805a27b269e585842",
"sha256:ec8d7d8567e14af34a7911c98f5ac74a3d4a743cd848643341fc92b12b3784ff",
"sha256:ed78c8e94f57b44292c1a0350f580e18d3a3c5c0800e253f1583580c1b417ad2",
"sha256:eea8d9e20632d68f653455265b18c35f90965e26f30d4d92f831899d6682149b",
"sha256:ef8937dae823b889c0273dfa0f0f6c46a3658ac0d851349c464d1b00e7ff4252",
"sha256:f06e3c4c0a8badfc4910b9fd15beb1ad8f3b8fafa8ea82c023e5e607b66a78e4",
"sha256:f0821b9bdf18c5b7d51722b906b233a39b17f602501a966cfbd9b285f8ab83cd",
"sha256:f0ba13557fec9d5ffc0a22826754a7457cc77f1b25145be10b7bb1d143ce84c6",
"sha256:f382fec4a7891d66fb7163c90754454030bb9200a13f82ee7860b6359f3f2fa8",
"sha256:fe7aaf5a54821d340d21412f7f6e6272a9b17a0cbafc1d68f77f2fc11009dcd5",
"sha256:ff38378346b7018f42cbc1f6d1d3778e36e16d8595f79a312b31e7c25c50bd08",
"sha256:ffa1bb0e26297b0f22881b219ffc82a33a3c84ce6174a9d69406239b14575bd5"
],
"markers": "python_version >= '3.9'",
"version": "==3.10.1"
"version": "==3.11.0"
},
"ratelimit": {
"hashes": [
@@ -3041,11 +3041,11 @@
"develop": {
"attrs": {
"hashes": [
"sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346",
"sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"
"sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff",
"sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308"
],
"markers": "python_version >= '3.7'",
"version": "==24.2.0"
"markers": "python_version >= '3.8'",
"version": "==24.3.0"
},
"cattrs": {
"hashes": [
+5 -1
View File
@@ -380,7 +380,11 @@ async def get_cached_torrent_streams(
# Serialize the data and store it in the Redis cache for 30 minutes
await REDIS_ASYNC_CLIENT.set(
cache_key, torrent_streams.model_dump_json(exclude_none=True), ex=1800
cache_key,
torrent_streams.model_dump_json(
exclude_none=True, exclude={"streams": {"__all__": {"torrent_file"}}}
),
ex=1800,
)
return streams
+25
View File
@@ -0,0 +1,25 @@
from enum import StrEnum
# Enums
class MediaType(StrEnum):
MOVIE = "movie"
SERIES = "series"
TV = "tv"
EVENTS = "events"
class TorrentType(StrEnum):
PUBLIC = "public"
SEMI_PRIVATE = "semi-private"
PRIVATE = "private"
WEB_SEED = "web-seed"
class NudityStatus(StrEnum):
NONE = "None"
MILD = "Mild"
MODERATE = "Moderate"
SEVERE = "Severe"
UNKNOWN = "Unknown"
DISABLE = "Disable"
+5 -2
View File
@@ -7,6 +7,8 @@ from beanie import Document
from pydantic import BaseModel, Field, ConfigDict, field_validator
from pymongo import IndexModel, ASCENDING, DESCENDING
from db.enums import TorrentType, NudityStatus
class Episode(BaseModel):
episode_number: int
@@ -43,8 +45,9 @@ class TorrentStreams(Document):
quality: Optional[str] = None
audio: Optional[str] = None
seeders: Optional[int] = None
indexer_flags: Optional[list[str]] = Field(default_factory=list)
torrent_type: Optional[TorrentType] = TorrentType.PUBLIC
is_blocked: Optional[bool] = False
torrent_file: bytes | None = None
def __eq__(self, other):
if not isinstance(other, TorrentStreams):
@@ -174,7 +177,7 @@ class MediaFusionMetaData(Document):
class MediaFusionMovieMetaData(MediaFusionMetaData):
type: str = "movie"
imdb_rating: Optional[float] = None
parent_guide_nudity_status: Optional[str] = "None"
parent_guide_nudity_status: Optional[NudityStatus] = NudityStatus.UNKNOWN
parent_guide_certificates: Optional[list[str]] = Field(default_factory=list)
stars: Optional[list[str]] = Field(default_factory=list)
+2 -3
View File
@@ -4,6 +4,7 @@ from typing import Literal, Optional
from pydantic import BaseModel, Field, field_validator, model_validator, HttpUrl
from db.config import settings
from db.enums import NudityStatus
from db.models import TorrentStreams
from utils import const
@@ -209,9 +210,7 @@ class UserData(BaseModel):
],
alias="tsp",
)
nudity_filter: list[
Literal["Disable", "Unknown", "None", "Mild", "Moderate", "Severe"]
] = Field(default=["Severe"], alias="nf")
nudity_filter: list[NudityStatus] = Field(default=[NudityStatus.SEVERE], alias="nf")
certification_filter: list[
Literal[
"Disable",
+10
View File
@@ -138,6 +138,16 @@
<div class="card mb-3">
<div class="card-body">
<h6 class="card-subtitle mb-3 text-muted">Recommended: Torrent File Upload</h6>
<!-- Select torrent type public, semi-private, private or web-seed -->
<div class="mb-3">
<label for="torrentType" class="form-label">Torrent Type</label>
<select class="form-select" id="torrentType" name="torrentType">
<option value="public">Public</option>
<option value="semi-private">Semi-Private</option>
<option value="private">Private</option>
<option value="web-seed">Web-Seed</option>
</select>
</div>
<div class="mb-3">
<label for="torrentFile" class="form-label">Torrent File</label>
<input type="file" class="form-control" id="torrentFile" name="torrentFile" accept=".torrent"
+8
View File
@@ -452,12 +452,20 @@ async function handleAddTorrent(submitBtn, loadingSpinner, forceImport = false)
const magnetLink = document.getElementById('magnetLink').value;
const torrentFile = document.getElementById('torrentFile').files[0];
const torrentType = document.getElementById('torrentType').value;
if (!magnetLink && !torrentFile) {
showNotification('Either Magnet Link or Torrent File is required.', 'error');
resetButton(submitBtn, loadingSpinner);
return;
}
if (torrentType !== 'public' && !torrentFile) {
showNotification(`Torrent File is required for ${torrentType} torrents.`, 'error');
resetButton(submitBtn, loadingSpinner);
return;
}
formData.append('torrent_type', torrentType);
if (magnetLink) {
formData.append('magnet_link', magnetLink);
} else {
+17 -1
View File
@@ -20,6 +20,7 @@ from tenacity import retry, stop_after_attempt, wait_exponential
from torf import Magnet, MagnetError
from db.config import settings
from db.enums import TorrentType
from db.models import MediaFusionMovieMetaData, MediaFusionSeriesMetaData
from db.models import (
TorrentStreams,
@@ -1009,6 +1010,10 @@ class IndexerBaseScraper(BaseScraper, abc.ABC):
def get_indexer(self, item: dict) -> str:
pass
@abc.abstractmethod
def get_torrent_type(self, item: dict) -> TorrentType:
pass
async def scrape_movie_by_imdb(
self,
processed_info_hashes: set[str],
@@ -1264,6 +1269,8 @@ class IndexerBaseScraper(BaseScraper, abc.ABC):
self.metrics.record_skip("Duplicated info_hash")
return None
torrent_type = self.get_torrent_type(stream_data)
torrent_stream = TorrentStreams(
id=parsed_data["info_hash"],
meta_id=metadata.id,
@@ -1289,7 +1296,12 @@ class IndexerBaseScraper(BaseScraper, abc.ABC):
seeders=parsed_data["seeders"],
created_at=parsed_data["created_at"],
announce_list=parsed_data["announce_list"],
indexer_flags=stream_data.get("indexerFlags", []),
torrent_type=torrent_type,
torrent_file=(
parsed_data.get("torrent_file")
if torrent_type in [TorrentType.PRIVATE, TorrentType.SEMI_PRIVATE]
else None
),
)
if catalog_type == "series":
@@ -1396,6 +1408,10 @@ class IndexerBaseScraper(BaseScraper, abc.ABC):
guid = self.get_guid(indexer_data) or ""
magnet_url = self.get_magent_link(indexer_data) or ""
download_url = self.get_download_link(indexer_data) or ""
torrent_type = self.get_torrent_type(indexer_data)
if torrent_type in [TorrentType.PRIVATE, TorrentType.SEMI_PRIVATE]:
return download_url
if guid and guid.startswith("magnet:"):
return guid
+4
View File
@@ -5,6 +5,7 @@ from xml.etree import ElementTree
import httpx
from db.config import settings
from db.enums import TorrentType
from db.models import (
TorrentStreams,
MediaFusionMetaData,
@@ -71,6 +72,9 @@ class JackettScraper(IndexerBaseScraper):
def get_indexer(self, item: dict) -> str:
return item.get("Tracker")
def get_torrent_type(self, item: dict) -> TorrentType:
return TorrentType(item.get("TrackerType"))
@IndexerBaseScraper.cache(ttl=JACKETT_SEARCH_TTL)
@IndexerBaseScraper.rate_limit(calls=5, period=timedelta(seconds=1))
async def _scrape_and_parse(
+5
View File
@@ -5,6 +5,7 @@ from typing import List, Dict, Any, Optional, Literal
import httpx
from db.config import settings
from db.enums import TorrentType
from db.models import TorrentStreams, MediaFusionMetaData
from scrapers.base_scraper import IndexerBaseScraper
from utils.network import CircuitBreaker
@@ -83,6 +84,10 @@ class ProwlarrScraper(IndexerBaseScraper):
def get_indexer(self, item: dict) -> str:
return item.get("indexer")
def get_torrent_type(self, item: dict) -> TorrentType:
flag = item.get("indexerFlags", ["public"])[0]
return TorrentType.PUBLIC if flag == "freeleech" else TorrentType(flag)
async def get_healthy_indexers(self) -> List[dict]:
"""Fetch and return list of healthy Prowlarr indexers with their capabilities"""
try:
+16 -1
View File
@@ -15,6 +15,7 @@ from db.crud import (
get_stream_by_info_hash,
store_new_torrent_streams,
)
from db.enums import TorrentType
from db.models import TorrentStreams, Episode, Season
from db.redis_database import REDIS_ASYNC_CLIENT
from mediafusion_scrapy.task import run_spider
@@ -175,6 +176,7 @@ async def add_torrent(
created_at: date = Form(...),
season: int | None = Form(None),
episodes: str | None = Form(None),
torrent_type: TorrentType = Form(TorrentType.PUBLIC),
magnet_link: str = Form(None),
torrent_file: UploadFile = File(None),
force_import: bool = Form(False),
@@ -185,6 +187,8 @@ async def add_torrent(
# Basic validation
if not magnet_link and not torrent_file:
raise_error("Either magnet link or torrent file must be provided.")
if torrent_type != TorrentType.PUBLIC and not torrent_file:
raise_error(f"Torrent file must be provided for {torrent_type} torrents.")
if not meta_id.startswith("tt") or not meta_id[2:].isdigit():
raise_error("Invalid IMDb ID. Must start with 'tt'.")
@@ -232,8 +236,15 @@ async def add_torrent(
source = "Contribution Stream"
languages = set(language_list).union(torrent_data.get("languages", []))
torrent_data.update(
{"source": source, "created_at": created_at, "languages": languages}
{
"source": source,
"created_at": created_at,
"languages": languages,
"torrent_type": torrent_type,
}
)
if torrent_type == TorrentType.PUBLIC:
torrent_data.pop("torrent_file", None)
# Add contribution_stream to catalogs if provided
if catalog_list:
@@ -383,6 +394,8 @@ async def handle_movie_stream_store(info_hash, parsed_data, video_id):
seeders=parsed_data.get("seeders"),
created_at=parsed_data.get("created_at"),
meta_id=video_id,
torrent_type=parsed_data.get("torrent_type"),
torrent_file=parsed_data.get("torrent_file"),
)
await store_new_torrent_streams([torrent_stream])
@@ -440,6 +453,8 @@ async def handle_series_stream_store(info_hash, parsed_data, video_id, season):
created_at=parsed_data.get("created_at"),
meta_id=video_id,
season=Season(season_number=season_number, episodes=episode_data),
torrent_type=parsed_data.get("torrent_type"),
torrent_file=parsed_data.get("torrent_file"),
)
await store_new_torrent_streams([torrent_stream])
+19
View File
@@ -1,5 +1,7 @@
from typing import Any, Optional
import aiohttp
from streaming_providers.debrid_client import DebridClient
from streaming_providers.exceptions import ProviderException
@@ -72,6 +74,23 @@ class AllDebrid(DebridClient):
self._validate_error_response(response_data)
return response_data
async def add_torrent_file(self, torrent_file: bytes, torrent_name: str):
data = aiohttp.FormData()
data.add_field(
"files[]",
torrent_file,
filename=(
torrent_name
if torrent_name.endswith(".torrent")
else torrent_name + ".torrent"
),
)
response_data = await self._make_request(
"POST", "/magnet/upload/file", data=data
)
self._validate_error_response(response_data)
return response_data
async def get_user_torrent_list(self, status: str = None):
params = {}
if status:
+14 -8
View File
@@ -14,20 +14,26 @@ from streaming_providers.parser import (
async def get_torrent_info(ad_client, info_hash):
torrent_info = await ad_client.get_available_torrent(info_hash)
if torrent_info and torrent_info["status"] == "Ready":
return torrent_info
elif torrent_info and torrent_info["statusCode"] == 7:
if torrent_info and torrent_info["statusCode"] == 7:
await ad_client.delete_torrents([torrent_info.get("id")])
raise ProviderException(
"Not enough seeders available to parse magnet link",
"transfer_error.mp4",
)
return None
return torrent_info
async def add_new_torrent(ad_client, magnet_link):
response_data = await ad_client.add_magnet_link(magnet_link)
return response_data["data"]["magnets"][0]["id"]
async def add_new_torrent(
ad_client: AllDebrid, magnet_link: str, stream: TorrentStreams
):
if stream.torrent_file:
response_data = await ad_client.add_torrent_file(
stream.torrent_file, stream.torrent_name or "torrent"
)
return response_data["data"]["files"][0]["id"]
else:
response_data = await ad_client.add_magnet_link(magnet_link)
return response_data["data"]["magnets"][0]["id"]
def flatten_files(files):
@@ -126,7 +132,7 @@ async def get_video_url_from_alldebrid(
) as ad_client:
torrent_info = await get_torrent_info(ad_client, info_hash)
if not torrent_info:
torrent_id = await add_new_torrent(ad_client, magnet_link)
torrent_id = await add_new_torrent(ad_client, magnet_link, stream)
else:
torrent_id = torrent_info.get("id")
+2 -2
View File
@@ -6,7 +6,7 @@ from contextlib import AsyncContextDecorator
from typing import Optional, Dict, Union
import aiohttp
from aiohttp import ClientResponse, ClientTimeout, ContentTypeError
from aiohttp import ClientResponse, ClientTimeout, ContentTypeError, FormData
from aiohttp_socks import ProxyConnector
from db.config import settings
@@ -60,7 +60,7 @@ class DebridClient(AsyncContextDecorator):
self,
method: str,
url: str,
data: Optional[dict | str] = None,
data: Optional[dict | str | FormData] = None,
json: Optional[dict] = None,
params: Optional[dict] = None,
is_return_none: bool = False,
+23
View File
@@ -1,5 +1,7 @@
from typing import Any, Optional
import aiohttp
from streaming_providers.debrid_client import DebridClient
from streaming_providers.exceptions import ProviderException
@@ -113,6 +115,27 @@ class DebridLink(DebridClient):
)
return response.get("value", {})
async def add_torrent_file(self, torrent_file: bytes, torrent_name: Optional[str]):
data = aiohttp.FormData()
data.add_field(
"file",
torrent_file,
filename=torrent_name,
content_type="application/x-bittorrent",
)
response = await self._make_request(
"POST",
f"{self.BASE_URL}/seedbox/add",
data={"file": torrent_file},
)
if response.get("error"):
self._handle_error_message(response.get("error"))
raise ProviderException(
f"Failed to add torrent file to Debrid-Link: {response.get('error')}",
"transfer_error.mp4",
)
return response.get("value", {})
async def get_user_torrent_list(self) -> dict[str, Any]:
return await self._make_request("GET", f"{self.BASE_URL}/seedbox/list")
+7 -2
View File
@@ -59,7 +59,12 @@ async def get_video_url_from_debridlink(
async with DebridLink(token=user_data.streaming_provider.token) as dl_client:
torrent_info = await dl_client.get_available_torrent(info_hash)
if not torrent_info:
torrent_info = await dl_client.add_magnet_link(magnet_link)
if stream.torrent_file:
torrent_info = await dl_client.add_torrent_file(
stream.torrent_file, stream.torrent_name
)
else:
torrent_info = await dl_client.add_magnet_link(magnet_link)
torrent_id = torrent_info.get("id")
if not torrent_id:
@@ -67,7 +72,7 @@ async def get_video_url_from_debridlink(
"Failed to add magnet link to DebridLink", "transfer_error.mp4"
)
if torrent_info.get("error"):
if torrent_info.get("errorString"):
await dl_client.delete_torrent(torrent_id)
raise ProviderException(
f"Torrent cannot be downloaded due to error: {torrent_info.get('errorString')}",
+26 -12
View File
@@ -15,8 +15,7 @@ from streaming_providers.parser import (
class OffCloud(DebridClient):
BASE_URL = "https://offcloud.com/api"
DELETE_URL = "https://offcloud.com"
BASE_URL = "https://offcloud.com"
async def initialize_headers(self):
pass
@@ -37,19 +36,18 @@ class OffCloud(DebridClient):
method: str,
url: str,
params: Optional[dict] = None,
delete: bool = False,
**kwargs,
) -> dict | list:
params = params or {}
params["key"] = self.token
full_url = (self.DELETE_URL if delete else self.BASE_URL) + url
full_url = self.BASE_URL + url
return await super()._make_request(
method=method, url=full_url, params=params, **kwargs
)
async def add_magnet_link(self, magnet_link: str) -> dict:
response_data = await self._make_request(
"POST", "/cloud", data={"url": magnet_link}
"POST", "/api/cloud", data={"url": magnet_link}
)
if "requestId" not in response_data:
@@ -64,18 +62,36 @@ class OffCloud(DebridClient):
)
return response_data
async def add_torrent_file(
self, torrent_file: bytes, torrent_name: Optional[str]
) -> dict:
data = aiohttp.FormData()
data.add_field(
"file",
torrent_file,
filename=torrent_name,
content_type="application/x-bittorrent",
)
response_data = await self._make_request("POST", "/torrent/upload", data=data)
if response_data.get("success") is False:
raise ProviderException(
f"Failed to add torrent file to OffCloud {response_data}",
"transfer_error.mp4",
)
return await self.add_magnet_link(response_data["url"])
async def get_user_torrent_list(self) -> List[dict]:
return await self._make_request("GET", "/cloud/history")
return await self._make_request("GET", "/api/cloud/history")
async def get_torrent_info(self, request_id: str) -> dict:
response = await self._make_request(
"POST", "/cloud/status", data={"requestIds": [request_id]}
"POST", "/api/cloud/status", data={"requestIds": [request_id]}
)
return response.get("requests", [{}])[0]
async def get_torrent_instant_availability(self, magnet_links: List[str]) -> dict:
response = await self._make_request(
"POST", "/cache", data={"hashes": magnet_links}
"POST", "/api/cache", data={"hashes": magnet_links}
)
return response.get("cachedItems", {})
@@ -91,7 +107,7 @@ class OffCloud(DebridClient):
)
async def explore_folder_links(self, request_id: str) -> List[str]:
return await self._make_request("GET", f"/cloud/explore/{request_id}")
return await self._make_request("GET", f"/api/cloud/explore/{request_id}")
async def update_file_sizes(self, files_data: list[dict]):
"""
@@ -165,6 +181,4 @@ class OffCloud(DebridClient):
return selected_file_url
async def delete_torrent(self, request_id: str) -> dict:
return await self._make_request(
"GET", f"/cloud/remove/{request_id}", delete=True
)
return await self._make_request("GET", f"/cloud/remove/{request_id}")
+6 -1
View File
@@ -45,7 +45,12 @@ async def get_video_url_from_offcloud(
)
else:
# If torrent doesn't exist, add it
response_data = await oc_client.add_magnet_link(magnet_link)
if stream.torrent_file:
response_data = await oc_client.add_torrent_file(
stream.torrent_file, stream.torrent_name
)
else:
response_data = await oc_client.add_magnet_link(magnet_link)
request_id = response_data["requestId"]
# Wait for download completion and get the direct link
+16
View File
@@ -70,6 +70,22 @@ class Premiumize(DebridClient):
data={"src": magnet_link, "folder_id": folder_id},
)
async def add_torrent_file(
self, torrent_file: bytes, torrent_name: Optional[str], folder_id: str = None
):
data = aiohttp.FormData()
data.add_field(
"file",
torrent_file,
filename=torrent_name,
content_type="application/x-bittorrent",
)
data.add_field("folder_id", folder_id)
return await self._make_request(
"POST",
f"{self.BASE_URL}/transfer/create",
data={"file": torrent_file, "folder_id": folder_id},
)
async def create_direct_download(self, magnet_link: str):
return await self._make_request(
+28 -13
View File
@@ -18,6 +18,7 @@ from aioqbt.exc import LoginError, AddTorrentError, NotFoundError
from aiowebdav.client import Client as WebDavClient
from aiowebdav.exceptions import RemoteResourceNotFound, NoConnection
from db.enums import TorrentType
from db.models import TorrentStreams
from db.schemas import UserData
from streaming_providers.exceptions import ProviderException
@@ -32,15 +33,26 @@ async def check_torrent_status(
return available_torrents[0] if available_torrents else None
async def add_magnet(
qbittorrent: APIClient, magnet_link: str, info_hash: str, user_data: UserData
async def add_torrent_or_magnet(
qbittorrent: APIClient,
magnet_link: str,
info_hash: str,
user_data: UserData,
stream: TorrentStreams,
):
"""Adds a magnet link to the qbittorrent server."""
try:
await qbittorrent.torrents.add(
AddFormBuilder.with_client(qbittorrent)
.include_url(magnet_link)
.savepath(info_hash)
torrent_form = AddFormBuilder.with_client(qbittorrent)
if stream.torrent_type != TorrentType.PUBLIC and stream.torrent_file:
torrent_form = torrent_form.include_file(
stream.torrent_file, stream.torrent_name
)
else:
torrent_form = torrent_form.include_url(magnet_link)
torrent_form = (
torrent_form.savepath(info_hash)
.sequential_download(True)
.seeding_time_limit(
timedelta(
minutes=user_data.streaming_provider.qbittorrent_config.seeding_time_limit
@@ -52,6 +64,7 @@ async def add_magnet(
.category(user_data.streaming_provider.qbittorrent_config.category)
.build()
)
await qbittorrent.torrents.add(torrent_form)
except AddTorrentError:
raise ProviderException(
"Failed to add the torrent to qBittorrent", "add_torrent_failed.mp4"
@@ -223,8 +236,8 @@ async def handle_torrent_status(
return torrent
async def set_qbittorrent_preferences(qbittorrent, indexer_type):
if indexer_type == "private":
async def set_qbittorrent_preferences(qbittorrent, torrent_type):
if torrent_type == "private":
await qbittorrent.app.set_preferences(
{"dht": False, "pex": False, "lsd": False}
)
@@ -240,7 +253,7 @@ async def retrieve_or_download_file(
play_video_after: int,
magnet_link: str,
info_hash: str,
indexer_type: str,
stream: TorrentStreams,
filename: Optional[str],
episode: Optional[int],
max_retries: int,
@@ -250,8 +263,10 @@ async def retrieve_or_download_file(
webdav, user_data, info_hash, filename, episode
)
if not selected_file:
await set_qbittorrent_preferences(qbittorrent, indexer_type)
await add_magnet(qbittorrent, magnet_link, info_hash, user_data)
await set_qbittorrent_preferences(qbittorrent, stream.torrent_type)
await add_torrent_or_magnet(
qbittorrent, magnet_link, info_hash, user_data, stream
)
await wait_for_torrent_to_complete(
qbittorrent, info_hash, play_video_after, max_retries, retry_interval
)
@@ -291,7 +306,7 @@ async def get_video_url_from_qbittorrent(
info_hash: str,
magnet_link: str,
user_data: UserData,
indexer_type: str,
stream: TorrentStreams,
filename: Optional[str],
episode: Optional[int],
max_retries=5,
@@ -318,7 +333,7 @@ async def get_video_url_from_qbittorrent(
play_video_after,
magnet_link,
info_hash,
indexer_type,
stream,
filename,
episode,
max_retries,
+9 -2
View File
@@ -41,10 +41,10 @@ class RealDebrid(DebridClient):
self,
method: str,
url: str,
data: Optional[dict] = None,
data: Optional[dict | bytes] = None,
**kwargs,
) -> dict:
if method == "POST" and self.user_ip:
if method in ["POST", "PUT"] and self.user_ip:
data = data or {}
data["ip"] = self.user_ip
return await super()._make_request(method=method, url=url, data=data, **kwargs)
@@ -131,6 +131,13 @@ class RealDebrid(DebridClient):
"POST", f"{self.BASE_URL}/torrents/addMagnet", data={"magnet": magnet_link}
)
async def add_torrent_file(self, torrent_file: bytes):
return await self._make_request(
"PUT",
f"{self.BASE_URL}/torrents/addTorrent",
data=torrent_file,
)
async def get_active_torrents(self):
return await self._make_request("GET", f"{self.BASE_URL}/torrents/activeCount")
+9 -3
View File
@@ -105,7 +105,9 @@ async def get_video_url_from_realdebrid(
torrent_info = await rd_client.get_available_torrent(info_hash)
if not torrent_info:
torrent_info = await add_new_torrent(rd_client, magnet_link, info_hash)
torrent_info = await add_new_torrent(
rd_client, magnet_link, info_hash, stream
)
torrent_id = torrent_info["id"]
status = torrent_info["status"]
@@ -155,7 +157,7 @@ async def get_video_url_from_realdebrid(
)
async def add_new_torrent(rd_client, magnet_link, info_hash):
async def add_new_torrent(rd_client, magnet_link, info_hash, stream):
response = await rd_client.get_active_torrents()
if response["limit"] == response["nb"]:
raise ProviderException(
@@ -166,7 +168,11 @@ async def add_new_torrent(rd_client, magnet_link, info_hash):
"Torrent is already being downloading", "torrent_not_downloaded.mp4"
)
torrent_id = (await rd_client.add_magnet_link(magnet_link)).get("id")
if stream.torrent_file:
torrent_id = (await rd_client.add_torrent_file(stream.torrent_file)).get("id")
else:
torrent_id = (await rd_client.add_magnet_link(magnet_link)).get("id")
if not torrent_id:
raise ProviderException(
"Failed to add magnet link to Real-Debrid", "transfer_error.mp4"
-3
View File
@@ -108,9 +108,6 @@ async def get_or_create_video_url(
stream=stream,
torrent_name=stream.torrent_name,
background_tasks=background_tasks,
indexer_type=(
"public" if stream.indexer_flags in [[], ["freeleech"]] else "private"
),
)
return await get_video_url(**kwargs)
+14 -3
View File
@@ -112,14 +112,25 @@ async def ensure_space_available(seedr: Seedr, required_space: int | float) -> N
available_space += folder["size"]
async def add_torrent(seedr: Seedr, magnet_link: str, info_hash: str) -> None:
async def add_torrent(
seedr: Seedr, magnet_link: str, info_hash: str, stream: TorrentStreams
) -> None:
"""Add a new torrent to Seedr."""
await seedr.add_folder(info_hash)
folder = await get_folder_by_info_hash(seedr, info_hash)
if not folder:
raise ProviderException("Failed to create folder", "folder_creation_error.mp4")
transfer = await seedr.add_torrent(magnet_link=magnet_link, folder_id=folder["id"])
if stream.torrent_file:
transfer = await seedr.add_torrent(
torrent_file_content=stream.torrent_file,
folder_id=folder["id"],
torrent_file=stream.torrent_name,
)
else:
transfer = await seedr.add_torrent(
magnet_link=magnet_link, folder_id=folder["id"]
)
if transfer["result"] is True:
return
@@ -188,7 +199,7 @@ async def get_video_url_from_seedr(
if status == TorrentStatus.NOT_FOUND:
await ensure_space_available(seedr, stream.size)
await add_torrent(seedr, magnet_link, info_hash)
await add_torrent(seedr, magnet_link, info_hash, stream)
await wait_for_completion(seedr, info_hash)
status, data = await check_torrent_status(seedr, info_hash)
+41 -10
View File
@@ -1,5 +1,7 @@
from typing import Any, Optional
import aiohttp
from streaming_providers.debrid_client import DebridClient
from streaming_providers.exceptions import ProviderException
@@ -61,13 +63,34 @@ class Torbox(DebridClient):
is_expected_to_fail=True,
)
if response_data.get("detail") is False:
if response_data.get("error"):
raise ProviderException(
f"Failed to add magnet link to Torbox {response_data}",
"transfer_error.mp4",
)
return response_data
async def add_torrent_file(self, torrent_file: bytes, torrent_name: Optional[str]):
data = aiohttp.FormData()
data.add_field(
"file",
torrent_file,
filename=torrent_name,
content_type="application/x-bittorrent",
)
response = await self._make_request(
"POST",
"/torrents/createtorrent",
data=data,
is_expected_to_fail=True,
)
if response.get("error"):
raise ProviderException(
f"Failed to add torrent file to Torbox {response.get('error')}",
"transfer_error.mp4",
)
return response
async def get_user_torrent_list(self):
response = await self._make_request(
"GET",
@@ -99,23 +122,31 @@ class Torbox(DebridClient):
response = await self.get_user_torrent_list()
torrent_list = response.get("data", [])
for torrent in torrent_list:
if torrent.get("hash", "") == info_hash:
if torrent.get("hash") == info_hash:
return torrent
return {}
async def create_download_link(self, torrent_id, filename, user_ip):
async def get_queued_torrents(self):
response = await self._make_request("GET", "/torrents/getqueued")
return response
async def create_download_link(
self, torrent_id: int, file_id: int, user_ip: Optional[str]
) -> dict:
params = {
"token": self.token,
"torrent_id": torrent_id,
"file_id": file_id,
}
if user_ip:
params["user_ip"] = user_ip
response = await self._make_request(
"GET",
"/torrents/requestdl",
params={
"token": self.token,
"torrent_id": torrent_id,
"file_id": filename,
"user_ip": user_ip,
},
params=params,
is_expected_to_fail=True,
)
if "successfully" in response.get("detail"):
if response.get("success"):
return response
raise ProviderException(
f"Failed to create download link from Torbox {response}",
+16 -3
View File
@@ -15,6 +15,7 @@ async def get_video_url_from_torbox(
user_data: UserData,
filename: str,
user_ip: str,
stream: TorrentStreams,
episode: Optional[int] = None,
**kwargs: Any,
) -> str:
@@ -30,14 +31,26 @@ async def get_video_url_from_torbox(
torrent_info, filename, episode
)
response = await torbox_client.create_download_link(
torrent_info.get("id", ""),
torrent_info["id"],
file_id,
user_ip,
)
return response["data"]
else:
queued_torrents = await torbox_client.get_queued_torrents()
for torrent in queued_torrents.get("data", []):
if torrent.get("hash") == info_hash:
raise ProviderException(
"Torrent did not reach downloaded status.",
"torrent_not_downloaded.mp4",
)
# If torrent doesn't exist, add it
response = await torbox_client.add_magnet_link(magnet_link)
if stream.torrent_file:
response = await torbox_client.add_torrent_file(
stream.torrent_file, stream.torrent_name
)
else:
response = await torbox_client.add_magnet_link(magnet_link)
# Response detail has "Found Cached Torrent" If it's a cached torrent,
# create a download link from it directly in the same call.
if "Found Cached" in response.get("detail", ""):
@@ -47,7 +60,7 @@ async def get_video_url_from_torbox(
torrent_info, filename, episode
)
response = await torbox_client.create_download_link(
torrent_info.get("id", ""),
torrent_info["id"],
file_id,
user_ip,
)
+6
View File
@@ -295,3 +295,9 @@ QUALITY_RANKING = {
for rank, qualities in enumerate(reversed(QUALITY_GROUPS.values()))
for quality in qualities
}
SUPPORTED_PRIVATE_TRACKER_STREAMING_PROVIDERS = {
"debridlink",
"qbittorrent",
"torbox",
}
+14 -4
View File
@@ -2,17 +2,17 @@ import asyncio
import functools
import json
import logging
from datetime import datetime, timezone
from typing import Optional, List, Any
import math
import re
from datetime import datetime, timezone
from typing import Optional, List, Any
from thefuzz import fuzz
from db.config import settings
from db.enums import TorrentType
from db.models import TorrentStreams, TVStreams
from db.schemas import Stream, StreamingProvider, UserData, SortingOption
from db.schemas import Stream, UserData, SortingOption
from streaming_providers import mapper
from streaming_providers.cache_helpers import (
get_cached_status,
@@ -45,6 +45,16 @@ async def filter_and_sort_streams(
# Step 1: Filter streams and add normalized attributes
filtered_streams = []
for stream in streams:
# Skip private torrents if streaming provider is not supported
if stream.torrent_type != TorrentType.PUBLIC:
if not user_data.streaming_provider:
continue
if (
stream.torrent_type != TorrentType.WEB_SEED
and user_data.streaming_provider.service
not in const.SUPPORTED_PRIVATE_TRACKER_STREAMING_PROVIDERS
):
continue
# Create a copy of the stream model to avoid modifying the original
stream = stream.model_copy()
# Add normalized attributes as dynamic properties
+6 -5
View File
@@ -53,16 +53,16 @@ def extract_torrent_metadata(
)
if not is_video_file(filename):
continue
parsed_data = PTT.parse_title(filename)
seasons.update(parsed_data.get("seasons", []))
episodes.update(parsed_data.get("episodes", []))
episode_parsed_data = PTT.parse_title(filename)
seasons.update(episode_parsed_data.get("seasons", []))
episodes.update(episode_parsed_data.get("episodes", []))
file_data.append(
{
"filename": filename,
"size": file[b"length"],
"index": idx,
"seasons": parsed_data.get("seasons"),
"episodes": parsed_data.get("episodes"),
"seasons": episode_parsed_data.get("seasons"),
"episodes": episode_parsed_data.get("episodes"),
}
)
if not file_data:
@@ -92,6 +92,7 @@ def extract_torrent_metadata(
"file_data": file_data,
"torrent_name": torrent_name,
"largest_file": largest_file,
"torrent_file": content,
}
if parsed_data:
metadata.update(parsed_data)