cyberdrop-dl-patched 5.7.2.dev2__tar.gz → 5.7.2.dev4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/CHANGELOG.md +5 -5
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/PKG-INFO +1 -1
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/clients/download_client.py +3 -3
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/clients/scraper_client.py +3 -3
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/downloader/downloader.py +1 -2
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/main.py +38 -20
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/managers/client_manager.py +147 -10
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/managers/config_manager.py +88 -118
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/managers/download_manager.py +6 -6
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/managers/live_manager.py +2 -10
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/managers/manager.py +1 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/managers/real_debrid/api.py +1 -1
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawler.py +1 -2
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/celebforum_crawler.py +1 -1
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/chevereto_crawler.py +2 -1
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/coomer_crawler.py +11 -5
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/cyberfile_crawler.py +1 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/erome_crawler.py +1 -1
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/f95zone_crawler.py +1 -1
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/kemono_crawler.py +7 -4
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/nudostar_crawler.py +1 -1
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/pixeldrain_crawler.py +1 -1
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/saint_crawler.py +1 -1
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/simpcity_crawler.py +1 -1
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/socialmediagirls_crawler.py +3 -2
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/xbunker_crawler.py +1 -1
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/jdownloader.py +1 -1
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/scraper.py +6 -1
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/ui/prompts/settings_authentication_prompts.py +19 -7
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/ui/prompts/settings_hash_prompts.py +1 -3
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/ui/prompts/settings_user_prompts.py +111 -2
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/ui/ui.py +1 -1
- cyberdrop_dl_patched-5.7.2.dev4/cyberdrop_dl/utils/args/browser_cookie_extraction.py +134 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/args/config_definitions.py +5 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/utilities.py +9 -9
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/pyproject.toml +16 -12
- cyberdrop_dl_patched-5.7.2.dev2/cyberdrop_dl/utils/args/browser_cookie_extraction.py +0 -78
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/LICENSE +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/README.md +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/__init__.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/clients/__init__.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/clients/errors.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/clients/hash_client.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/downloader/__init__.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/managers/__init__.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/managers/args_manager.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/managers/cache_manager.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/managers/db_manager.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/managers/hash_manager.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/managers/leaky.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/managers/log_manager.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/managers/path_manager.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/managers/progress_manager.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/managers/real_debrid/__init__.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/managers/real_debrid/errors.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/managers/realdebrid_manager.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/__init__.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/__init__.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/bunkrr_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/cyberdrop_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/ehentai_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/fapello_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/gofile_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/hotpic_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/imageban_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/imgbb_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/imgbox_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/imgur_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/leakedmodels_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/mediafire_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/nekohouse_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/nudostartv_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/omegascans_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/pimpandhost_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/postimg_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/realbooru_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/realdebrid_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/reddit_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/redgifs_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/rule34vault_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/rule34xxx_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/rule34xyz_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/scrolller_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/tokyomotion_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/toonily_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/xbunkr_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/crawlers/xxxbunker_crawler.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/scraper/filters.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/ui/__init__.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/ui/progress/__init__.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/ui/progress/downloads_progress.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/ui/progress/file_progress.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/ui/progress/hash_progress.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/ui/progress/scraping_progress.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/ui/progress/sort_progress.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/ui/progress/statistic_progress.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/ui/prompts/__init__.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/ui/prompts/continue_prompt.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/ui/prompts/general_prompts.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/ui/prompts/settings_global_prompts.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/ui/prompts/url_file_prompts.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/__init__.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/args/__init__.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/args/args.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/constants.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/database/__init__.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/database/table_definitions.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/database/tables/__init__.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/database/tables/hash_table.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/database/tables/history_table.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/database/tables/temp_referer_table.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/database/tables/temp_table.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/dataclasses/__init__.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/dataclasses/supported_domains.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/dataclasses/url_objects.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/logger.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/sorting.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/transfer/__init__.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/transfer/first_time_setup.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/transfer/transfer_v4_config.py +0 -0
- {cyberdrop_dl_patched-5.7.2.dev2 → cyberdrop_dl_patched-5.7.2.dev4}/cyberdrop_dl/utils/transfer/transfer_v4_db.py +0 -0
|
@@ -13,7 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
13
13
|
|
|
14
14
|
This update introduces the following changes:
|
|
15
15
|
|
|
16
|
-
1. Adds the option to limit how many items are scraped
|
|
16
|
+
1. Adds the option to limit how many items are scraped
|
|
17
17
|
2. Add support for scraping a users' coomer favorites
|
|
18
18
|
3. Add integration to handle downloads supported by https://real-debrid.com
|
|
19
19
|
4. Add support for https://nekohouse.su profiles and posts
|
|
@@ -29,7 +29,7 @@ This update introduces the following changes:
|
|
|
29
29
|
|
|
30
30
|
- Users can limit the number of items to scrape by type, using the `--maximum-number-of-children` parameter. For more details on how to use this feature, visit the wiki: https://script-ware.gitbook.io/cyberdrop-dl/reference/configuration-options/settings#download-options
|
|
31
31
|
- Add support for scraping a users' coomer favorites by allowing the user to pass the coomer favorites page URL as an input URL (https://coomer.su/favorites). This requires them to have their coomer session token in the `authentication.yaml` file.
|
|
32
|
-
- Add real-debrid integration to download from any site that they support (`mega.nz`,`rapidgator`, `google drive`, `k2s`, etc). User needs to provide their API key in the `authentication.yaml` file in order to allow downloads
|
|
32
|
+
- Add real-debrid integration to download from any site that they support (`mega.nz`,`rapidgator`, `google drive`, `k2s`, etc). User needs to provide their API key in the `authentication.yaml` file in order to allow downloads
|
|
33
33
|
- Nekohouse URLs can now be scraped and downloaded by CDL
|
|
34
34
|
- Users can now get the stats report of the run via multiple services and include the main log as an attachment. For more information on how to setup notifications, visit: https://script-ware.gitbook.io/cyberdrop-dl/reference/notifications
|
|
35
35
|
- Fix parsing of bunkr file extensions when `--remove-generated-id` is enabled
|
|
@@ -41,7 +41,7 @@ This update introduces the following changes:
|
|
|
41
41
|
## [5.7.0] - 2024-10-25
|
|
42
42
|
|
|
43
43
|
This update introduces the following changes:
|
|
44
|
-
1. Rotating log files
|
|
44
|
+
1. Rotating log files
|
|
45
45
|
2. Overhaul hashing functions
|
|
46
46
|
3. Add support for https://tokyomotion.net URLs
|
|
47
47
|
4. Add support for https://xxxbunker.com URLs
|
|
@@ -69,7 +69,7 @@ This update introduces the following changes:
|
|
|
69
69
|
- Fix error during program exit when referers table no longer exists
|
|
70
70
|
- Prevents crashes when there are insufficient permissions to move a file
|
|
71
71
|
- Fix an issue where CDL would delete URLs input file
|
|
72
|
-
- Move functions for after download to `post_runtime`
|
|
72
|
+
- Move functions for after download to `post_runtime`
|
|
73
73
|
- Fix handling of deleted imgbox albums if they return `HTTP 200`
|
|
74
74
|
- Fix cyberfile deleted folders not being correctly scraped
|
|
75
75
|
- Update logging to include when a file is being downloaded with no crawler
|
|
@@ -164,7 +164,7 @@ This update introduces the following changes:
|
|
|
164
164
|
## [5.6.40] - 2024-10-01
|
|
165
165
|
|
|
166
166
|
This update introduces the following changes:
|
|
167
|
-
1. Fixes empty folder cleanup
|
|
167
|
+
1. Fixes empty folder cleanup
|
|
168
168
|
|
|
169
169
|
#### Details:
|
|
170
170
|
- Fixes incorrent path objects on post-runtime folder cleanup
|
|
@@ -76,12 +76,12 @@ class DownloadClient:
|
|
|
76
76
|
def add_request_log_hooks(self) -> None:
|
|
77
77
|
async def on_request_start(*args):
|
|
78
78
|
params: aiohttp.TraceRequestStartParams = args[2]
|
|
79
|
-
log(f"Starting download {params.method} request to {params.url}",
|
|
79
|
+
log(f"Starting download {params.method} request to {params.url}", 20)
|
|
80
80
|
|
|
81
81
|
async def on_request_end(*args):
|
|
82
82
|
params: aiohttp.TraceRequestEndParams = args[2]
|
|
83
|
-
log(f"Finishing download {params.method} request to {params.url}",
|
|
84
|
-
log(f"Response status for {params.url}: {params.response.status}",
|
|
83
|
+
log(f"Finishing download {params.method} request to {params.url}", 20)
|
|
84
|
+
log(f"Response status for {params.url}: {params.response.status}", 20)
|
|
85
85
|
|
|
86
86
|
trace_config = aiohttp.TraceConfig()
|
|
87
87
|
trace_config.on_request_start.append(on_request_start)
|
|
@@ -65,12 +65,12 @@ class ScraperClient:
|
|
|
65
65
|
def add_request_log_hooks(self) -> None:
|
|
66
66
|
async def on_request_start(*args):
|
|
67
67
|
params: aiohttp.TraceRequestStartParams = args[2]
|
|
68
|
-
log(f"Starting download {params.method} request to {params.url}",
|
|
68
|
+
log(f"Starting download {params.method} request to {params.url}", 20)
|
|
69
69
|
|
|
70
70
|
async def on_request_end(*args):
|
|
71
71
|
params: aiohttp.TraceRequestEndParams = args[2]
|
|
72
|
-
log(f"Finishing download {params.method} request to {params.url}",
|
|
73
|
-
log(f"Response status for {params.url}: {params.response.status}",
|
|
72
|
+
log(f"Finishing download {params.method} request to {params.url}", 20)
|
|
73
|
+
log(f"Response status for {params.url}: {params.response.status}", 20)
|
|
74
74
|
|
|
75
75
|
trace_config = aiohttp.TraceConfig()
|
|
76
76
|
trace_config.on_request_start.append(on_request_start)
|
|
@@ -144,8 +144,6 @@ class Downloader:
|
|
|
144
144
|
log(f"{self.log_prefix} failed: {media_item.url} with error {e}", 40, exc_info=True)
|
|
145
145
|
self.manager.progress_manager.download_stats_progress.add_failure("Unknown")
|
|
146
146
|
self.manager.progress_manager.download_progress.add_failed()
|
|
147
|
-
else:
|
|
148
|
-
log(f"{self.log_prefix} finished: {media_item.url}", 20)
|
|
149
147
|
finally:
|
|
150
148
|
await self._file_lock.release_lock(media_item.file_lock_reference_name)
|
|
151
149
|
self._semaphore.release()
|
|
@@ -195,6 +193,7 @@ class Downloader:
|
|
|
195
193
|
self.set_file_datetime(media_item, media_item.complete_file)
|
|
196
194
|
self.attempt_task_removal(media_item)
|
|
197
195
|
self.manager.progress_manager.download_progress.add_completed()
|
|
196
|
+
log(f"Download finished: {media_item.url}", 20)
|
|
198
197
|
|
|
199
198
|
except RestrictedFiletypeError:
|
|
200
199
|
self.manager.progress_manager.download_progress.add_skipped()
|
|
@@ -5,8 +5,11 @@ import contextlib
|
|
|
5
5
|
import logging
|
|
6
6
|
import os
|
|
7
7
|
import sys
|
|
8
|
+
from functools import wraps
|
|
8
9
|
from pathlib import Path
|
|
10
|
+
from textwrap import indent
|
|
9
11
|
from time import perf_counter
|
|
12
|
+
from typing import TYPE_CHECKING
|
|
10
13
|
|
|
11
14
|
from rich.console import Console
|
|
12
15
|
from rich.logging import RichHandler
|
|
@@ -15,6 +18,7 @@ from cyberdrop_dl.clients.errors import InvalidYamlError
|
|
|
15
18
|
from cyberdrop_dl.managers.manager import Manager
|
|
16
19
|
from cyberdrop_dl.scraper.scraper import ScrapeMapper
|
|
17
20
|
from cyberdrop_dl.ui.ui import program_ui
|
|
21
|
+
from cyberdrop_dl.utils.args.browser_cookie_extraction import get_cookies_from_browser
|
|
18
22
|
from cyberdrop_dl.utils.logger import (
|
|
19
23
|
log,
|
|
20
24
|
log_spacer,
|
|
@@ -29,6 +33,9 @@ from cyberdrop_dl.utils.utilities import (
|
|
|
29
33
|
sent_apprise_notifications,
|
|
30
34
|
)
|
|
31
35
|
|
|
36
|
+
if TYPE_CHECKING:
|
|
37
|
+
from collections.abc import Callable
|
|
38
|
+
|
|
32
39
|
|
|
33
40
|
def startup() -> Manager:
|
|
34
41
|
"""Starts the program and returns the manager.
|
|
@@ -67,6 +74,12 @@ async def runtime(manager: Manager) -> None:
|
|
|
67
74
|
await scrape_mapper.start()
|
|
68
75
|
|
|
69
76
|
|
|
77
|
+
def pre_runtime(manager: Manager) -> None:
|
|
78
|
+
"""Actions to complete before main runtime."""
|
|
79
|
+
if manager.config_manager.settings_data["Browser_Cookies"]["auto_import"]:
|
|
80
|
+
get_cookies_from_browser(manager)
|
|
81
|
+
|
|
82
|
+
|
|
70
83
|
async def post_runtime(manager: Manager) -> None:
|
|
71
84
|
"""Actions to complete after main runtime, and before ui shutdown."""
|
|
72
85
|
log_spacer(20)
|
|
@@ -158,6 +171,25 @@ def setup_logger(manager: Manager, config_name: str) -> None:
|
|
|
158
171
|
constants.CONSOLE_LEVEL = manager.config_manager.settings_data["Runtime_Options"]["console_log_level"]
|
|
159
172
|
|
|
160
173
|
|
|
174
|
+
def ui_error_handling_wrapper(func: Callable) -> None:
|
|
175
|
+
"""Wrapper handles errors from the main UI"""
|
|
176
|
+
|
|
177
|
+
@wraps(func)
|
|
178
|
+
async def wrapper(*args, **kwargs):
|
|
179
|
+
try:
|
|
180
|
+
return await func(*args, **kwargs)
|
|
181
|
+
except* Exception as e:
|
|
182
|
+
exc_list = str(e)
|
|
183
|
+
if isinstance(e, ExceptionGroup):
|
|
184
|
+
exc_list = "\n".join(map(str, e.exceptions))
|
|
185
|
+
exc_list = indent(exc_list, " ")
|
|
186
|
+
msg = f"An error occurred, please report this to the developer with your logs file:\n{exc_list}"
|
|
187
|
+
log_with_color(msg, "bold red", 50, show_in_stats=False, exc_info=e)
|
|
188
|
+
|
|
189
|
+
return wrapper
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
@ui_error_handling_wrapper
|
|
161
193
|
async def director(manager: Manager) -> None:
|
|
162
194
|
"""Runs the program and handles the UI."""
|
|
163
195
|
manager.path_manager.startup()
|
|
@@ -182,18 +214,9 @@ async def director(manager: Manager) -> None:
|
|
|
182
214
|
log_spacer(20)
|
|
183
215
|
log("Starting CDL...\n", 20)
|
|
184
216
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
except* Exception as e:
|
|
189
|
-
log_with_color(
|
|
190
|
-
f"An error occurred, please report this to the developer: {e}",
|
|
191
|
-
"bold red",
|
|
192
|
-
50,
|
|
193
|
-
show_in_stats=False,
|
|
194
|
-
exc_info=True,
|
|
195
|
-
)
|
|
196
|
-
sys.exit(1)
|
|
217
|
+
pre_runtime(manager)
|
|
218
|
+
await runtime(manager)
|
|
219
|
+
await post_runtime(manager)
|
|
197
220
|
|
|
198
221
|
log_spacer(20)
|
|
199
222
|
manager.progress_manager.print_stats(start_time)
|
|
@@ -204,7 +227,6 @@ async def director(manager: Manager) -> None:
|
|
|
204
227
|
check_latest_pypi()
|
|
205
228
|
log_spacer(20)
|
|
206
229
|
log("Closing Program...", 20)
|
|
207
|
-
await manager.close()
|
|
208
230
|
log_with_color("Finished downloading. Enjoy :)", "green", 20, show_in_stats=False)
|
|
209
231
|
|
|
210
232
|
await send_webhook_message(manager)
|
|
@@ -217,18 +239,14 @@ def main() -> None:
|
|
|
217
239
|
asyncio.set_event_loop(loop)
|
|
218
240
|
exit_code = 1
|
|
219
241
|
manager = startup()
|
|
220
|
-
with contextlib.suppress(
|
|
242
|
+
with contextlib.suppress(Exception):
|
|
221
243
|
try:
|
|
222
244
|
asyncio.run(director(manager))
|
|
223
245
|
exit_code = 0
|
|
224
246
|
except KeyboardInterrupt:
|
|
225
247
|
print_to_console("Trying to Exit ...")
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
sys.exit(1)
|
|
229
|
-
loop.close()
|
|
230
|
-
sys.exit(0)
|
|
231
|
-
|
|
248
|
+
finally:
|
|
249
|
+
asyncio.run(manager.close())
|
|
232
250
|
loop.close()
|
|
233
251
|
sys.exit(exit_code)
|
|
234
252
|
|
|
@@ -8,18 +8,19 @@ from typing import TYPE_CHECKING
|
|
|
8
8
|
|
|
9
9
|
import aiohttp
|
|
10
10
|
import certifi
|
|
11
|
-
from aiohttp import ClientResponse, ContentTypeError
|
|
11
|
+
from aiohttp import ClientResponse, ClientSession, ContentTypeError
|
|
12
12
|
from aiolimiter import AsyncLimiter
|
|
13
|
+
from bs4 import BeautifulSoup
|
|
14
|
+
from yarl import URL
|
|
13
15
|
|
|
14
16
|
from cyberdrop_dl.clients.download_client import DownloadClient
|
|
15
17
|
from cyberdrop_dl.clients.errors import DDOSGuardError, DownloadError, ScrapeError
|
|
16
18
|
from cyberdrop_dl.clients.scraper_client import ScraperClient
|
|
17
19
|
from cyberdrop_dl.managers.leaky import LeakyBucket
|
|
18
20
|
from cyberdrop_dl.utils.constants import CustomHTTPStatus
|
|
21
|
+
from cyberdrop_dl.utils.logger import log
|
|
19
22
|
|
|
20
23
|
if TYPE_CHECKING:
|
|
21
|
-
from yarl import URL
|
|
22
|
-
|
|
23
24
|
from cyberdrop_dl.managers.manager import Manager
|
|
24
25
|
from cyberdrop_dl.scraper.crawler import ScrapeItem
|
|
25
26
|
|
|
@@ -28,6 +29,18 @@ DOWNLOAD_ERROR_ETAGS = {
|
|
|
28
29
|
"65b7753c-528a": "SC Scrape Image",
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
DDOS_GUARD_CHALLENGE_TITLES = ["Just a moment...", "DDoS-Guard"]
|
|
33
|
+
DDOS_GUARD_CHALLENGE_SELECTORS = [
|
|
34
|
+
"#cf-challenge-running",
|
|
35
|
+
".ray_id",
|
|
36
|
+
".attack-box",
|
|
37
|
+
"#cf-please-wait",
|
|
38
|
+
"#challenge-spinner",
|
|
39
|
+
"#trk_jschal_js",
|
|
40
|
+
"#turnstile-wrapper",
|
|
41
|
+
".lds-ring",
|
|
42
|
+
]
|
|
43
|
+
|
|
31
44
|
|
|
32
45
|
class ClientManager:
|
|
33
46
|
"""Creates a 'client' that can be referenced by scraping or download sessions."""
|
|
@@ -54,11 +67,6 @@ class ClientManager:
|
|
|
54
67
|
if not manager.args_manager.proxy
|
|
55
68
|
else manager.args_manager.proxy
|
|
56
69
|
)
|
|
57
|
-
self.flaresolverr = (
|
|
58
|
-
manager.config_manager.global_settings_data["General"]["flaresolverr"]
|
|
59
|
-
if not manager.args_manager.flaresolverr
|
|
60
|
-
else manager.args_manager.flaresolverr
|
|
61
|
-
)
|
|
62
70
|
|
|
63
71
|
self.domain_rate_limits = {
|
|
64
72
|
"bunkrr": AsyncLimiter(5, 1),
|
|
@@ -88,6 +96,7 @@ class ClientManager:
|
|
|
88
96
|
self.scraper_session = ScraperClient(self)
|
|
89
97
|
self.downloader_session = DownloadClient(manager, self)
|
|
90
98
|
self._leaky_bucket = LeakyBucket(manager)
|
|
99
|
+
self.flaresolverr = Flaresolverr(self)
|
|
91
100
|
|
|
92
101
|
"""~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"""
|
|
93
102
|
|
|
@@ -105,8 +114,9 @@ class ClientManager:
|
|
|
105
114
|
|
|
106
115
|
"""~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"""
|
|
107
116
|
|
|
108
|
-
@
|
|
117
|
+
@classmethod
|
|
109
118
|
async def check_http_status(
|
|
119
|
+
cls,
|
|
110
120
|
response: ClientResponse,
|
|
111
121
|
download: bool = False,
|
|
112
122
|
origin: ScrapeItem | URL | None = None,
|
|
@@ -130,9 +140,13 @@ class ClientManager:
|
|
|
130
140
|
if "data" in JSON_Resp and "error" in JSON_Resp["data"]:
|
|
131
141
|
raise ScrapeError(JSON_Resp["status"], JSON_Resp["data"]["error"], origin=origin)
|
|
132
142
|
|
|
143
|
+
response_text = None
|
|
133
144
|
with contextlib.suppress(UnicodeDecodeError):
|
|
134
145
|
response_text = await response.text()
|
|
135
|
-
|
|
146
|
+
|
|
147
|
+
if response_text:
|
|
148
|
+
soup = BeautifulSoup(response_text, "html.parser")
|
|
149
|
+
if cls.check_ddos_guard(soup):
|
|
136
150
|
raise DDOSGuardError(origin=origin)
|
|
137
151
|
|
|
138
152
|
status = status if headers.get("Content-Type") else CustomHTTPStatus.IM_A_TEAPOT
|
|
@@ -147,3 +161,126 @@ class ClientManager:
|
|
|
147
161
|
|
|
148
162
|
async def check_bucket(self, size: float) -> None:
|
|
149
163
|
await self._leaky_bucket.acquire(size)
|
|
164
|
+
|
|
165
|
+
@staticmethod
|
|
166
|
+
def check_ddos_guard(soup: BeautifulSoup) -> bool:
|
|
167
|
+
if soup.title:
|
|
168
|
+
for title in DDOS_GUARD_CHALLENGE_TITLES:
|
|
169
|
+
challenge_found = title.casefold() == soup.title.string.casefold()
|
|
170
|
+
if challenge_found:
|
|
171
|
+
return True
|
|
172
|
+
|
|
173
|
+
for selector in DDOS_GUARD_CHALLENGE_SELECTORS:
|
|
174
|
+
challenge_found = soup.find(selector)
|
|
175
|
+
if challenge_found:
|
|
176
|
+
return True
|
|
177
|
+
|
|
178
|
+
return False
|
|
179
|
+
|
|
180
|
+
async def close(self) -> None:
|
|
181
|
+
await self.flaresolverr._destroy_session()
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class Flaresolverr:
|
|
185
|
+
"""Class that handles communication with flaresolverr."""
|
|
186
|
+
|
|
187
|
+
def __init__(self, client_manager: ClientManager) -> None:
|
|
188
|
+
self.client_manager = client_manager
|
|
189
|
+
self.flaresolverr_host = (
|
|
190
|
+
client_manager.manager.args_manager.flaresolverr
|
|
191
|
+
or client_manager.manager.config_manager.global_settings_data["General"]["flaresolverr"]
|
|
192
|
+
)
|
|
193
|
+
self.enabled = bool(self.flaresolverr_host)
|
|
194
|
+
if "http" not in self.flaresolverr_host:
|
|
195
|
+
self.flaresolverr_host = f"http://{self.flaresolverr_host}"
|
|
196
|
+
self.session_id = None
|
|
197
|
+
self.flaresolverr_host = URL(self.flaresolverr_host)
|
|
198
|
+
|
|
199
|
+
async def _request(
|
|
200
|
+
self,
|
|
201
|
+
command: str,
|
|
202
|
+
client_session: ClientSession,
|
|
203
|
+
origin: ScrapeItem | URL | None = None,
|
|
204
|
+
**kwargs,
|
|
205
|
+
) -> dict:
|
|
206
|
+
"""Base request function to call flaresolverr."""
|
|
207
|
+
if not self.enabled:
|
|
208
|
+
raise DDOSGuardError(message="FlareSolverr is not configured", origin=origin)
|
|
209
|
+
|
|
210
|
+
if not (self.session_id or kwargs.get("session")):
|
|
211
|
+
await self._create_session()
|
|
212
|
+
|
|
213
|
+
headers = client_session.headers.copy()
|
|
214
|
+
headers.update({"Content-Type": "application/json"})
|
|
215
|
+
for key, value in kwargs.items():
|
|
216
|
+
if isinstance(value, URL):
|
|
217
|
+
kwargs[key] = str(value)
|
|
218
|
+
|
|
219
|
+
data = {"cmd": command, "maxTimeout": 60000, "session": self.session_id} | kwargs
|
|
220
|
+
|
|
221
|
+
async with client_session.post(
|
|
222
|
+
self.flaresolverr_host / "v1",
|
|
223
|
+
headers=headers,
|
|
224
|
+
ssl=self.client_manager.ssl_context,
|
|
225
|
+
proxy=self.client_manager.proxy,
|
|
226
|
+
json=data,
|
|
227
|
+
) as response:
|
|
228
|
+
json_obj: dict = await response.json() # type: ignore
|
|
229
|
+
|
|
230
|
+
return json_obj
|
|
231
|
+
|
|
232
|
+
async def _create_session(self) -> None:
|
|
233
|
+
"""Creates a permanet flaresolverr session."""
|
|
234
|
+
session_id = "cyberdrop-dl"
|
|
235
|
+
async with ClientSession() as client_session:
|
|
236
|
+
flaresolverr_resp = await self._request("sessions.create", client_session, session=session_id)
|
|
237
|
+
status = flaresolverr_resp.get("status")
|
|
238
|
+
if status != "ok":
|
|
239
|
+
raise DDOSGuardError(message="Failed to create flaresolverr session")
|
|
240
|
+
self.session_id = session_id
|
|
241
|
+
|
|
242
|
+
async def _destroy_session(self):
|
|
243
|
+
if self.session_id:
|
|
244
|
+
async with ClientSession() as client_session:
|
|
245
|
+
await self._request("sessions.destroy", client_session, session=self.session_id)
|
|
246
|
+
|
|
247
|
+
async def get(
|
|
248
|
+
self,
|
|
249
|
+
url: URL,
|
|
250
|
+
client_session: ClientSession,
|
|
251
|
+
origin: ScrapeItem | URL | None = None,
|
|
252
|
+
update_cookies: bool = True,
|
|
253
|
+
) -> tuple[BeautifulSoup, URL]:
|
|
254
|
+
"""Returns the resolved URL from the given URL."""
|
|
255
|
+
flaresolverr_resp: dict = await self._request("request.get", client_session, origin, url=url)
|
|
256
|
+
|
|
257
|
+
status = flaresolverr_resp.get("status")
|
|
258
|
+
if status != "ok":
|
|
259
|
+
raise DDOSGuardError(message="Failed to resolve URL with flaresolverr", origin=origin)
|
|
260
|
+
|
|
261
|
+
solution: dict = flaresolverr_resp.get("solution")
|
|
262
|
+
if not solution:
|
|
263
|
+
raise DDOSGuardError(message="Invalid response from flaresolverr", origin=origin)
|
|
264
|
+
response = BeautifulSoup(solution.get("response"), "html.parser")
|
|
265
|
+
response_url = URL(solution.get("url"))
|
|
266
|
+
cookies: list[dict] = solution.get("cookies")
|
|
267
|
+
user_agent = client_session.headers.get("User-Agent").strip()
|
|
268
|
+
flaresolverr_user_agent = solution.get("userAgent").strip()
|
|
269
|
+
mismatch_msg = f"Config user_agent and flaresolverr user_agent do not match:\n Cyberdrop-DL: {user_agent}\n Flaresolverr: {flaresolverr_user_agent}"
|
|
270
|
+
|
|
271
|
+
if self.client_manager.check_ddos_guard(response):
|
|
272
|
+
if not update_cookies:
|
|
273
|
+
raise DDOSGuardError(message="Invalid response from flaresolverr", origin=origin)
|
|
274
|
+
if flaresolverr_user_agent != user_agent:
|
|
275
|
+
raise DDOSGuardError(message=mismatch_msg, origin=origin)
|
|
276
|
+
|
|
277
|
+
if update_cookies:
|
|
278
|
+
if flaresolverr_user_agent != user_agent:
|
|
279
|
+
log(f"{mismatch_msg}\nResponse was successful but cookies will not be valid", 30)
|
|
280
|
+
|
|
281
|
+
for cookie in cookies:
|
|
282
|
+
self.client_manager.cookies.update_cookies(
|
|
283
|
+
{cookie["name"]: cookie["value"]}, URL(f"https://{cookie['domain']}")
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
return response, response_url
|