hydrusvideodeduplicator / hydrus-video-deduplicator

Video Deduplicator for the Hydrus Network
https://hydrusvideodeduplicator.github.io/hydrus-video-deduplicator/
MIT License
41 stars 7 forks source link

Critical Bug: HVD Incompatible with Hydrus v539+ Due to Bad Search Query String #36

Closed prof-m closed 1 year ago

prof-m commented 1 year ago

Summary

hydrus-video-deduplicator no longer functions when interacting with the Hydrus Client API for all clients of hydrusnetwork v539a or higher.

Severity

I'm gonna go out on a limb here and say High, cause the whole dang program can't really work if this query fails.

Cause

As of Hydrus v539a, 'gif' is no longer an accepted filetype - it has been replaced with 'static gif' and 'animated gif'. Because of this, the file search query that the program makes to fetch the appropriate file ids - which always contains 'system:filetype=video, gif, apng' as a search tag paramters - will always receive a HTTP 400 response from any updated Hydrus Client API.

Full Stack Trace ``` ╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮ │ /home/profmoose/personalProjects/hydrus-video-deduplicator/src/hydrusvideodeduplicator/hydrus_ap │ │ i/__init__.py:322 in _api_request │ │ │ │ 319 │ │ │ raise ConnectionError(*error.args) │ │ 320 │ │ │ │ 321 │ │ try: │ │ ❱ 322 │ │ │ response.raise_for_status() │ │ 323 │ │ except requests.HTTPError: │ │ 324 │ │ │ if response.status_code == requests.codes.bad_request: │ │ 325 │ │ │ │ raise MissingParameter(response) │ │ │ │ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │ │ │ json_data = None │ │ │ │ kwargs = { │ │ │ │ │ 'params': { │ │ │ │ │ │ 'tags': '["system:filetype=video, gif, apng", "system:has duration", │ │ │ │ "system:file service'+28, │ │ │ │ │ │ 'file_service_keys': │ │ │ │ '["6969696969696969nah-bruv696969696969696969696969696969696969696"]', │ │ │ │ │ │ 'file_sort_type': , │ │ │ │ │ │ 'file_sort_asc': 'true', │ │ │ │ │ │ 'return_file_ids': 'false', │ │ │ │ │ │ 'return_hashes': 'true' │ │ │ │ │ }, │ │ │ │ │ 'headers': { │ │ │ │ │ │ 'Hydrus-Client-API-Access-Key': │ │ │ │ '6969696969696969nah-bruv696969696969696969696969696969696969696' │ │ │ │ │ }, │ │ │ │ │ 'verify': False │ │ │ │ } │ │ │ │ method = 'GET' │ │ │ │ path = '/get_files/search_files' │ │ │ │ response = │ │ │ │ self = │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │ │ │ │ /home/profmoose/personalProjects/hydrus-video-deduplicator/venv/lib/python3.10/site-packages/req │ │ uests/models.py:1021 in raise_for_status │ │ │ │ 1018 │ │ │ ) │ │ 1019 │ │ │ │ 1020 │ │ if http_error_msg: │ │ ❱ 1021 │ │ │ raise HTTPError(http_error_msg, response=self) │ │ 1022 │ │ │ 1023 │ def close(self): │ │ 1024 │ │ """Releases the connection back to the pool. Once this method has been │ │ │ │ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │ │ │ http_error_msg = '400 Client Error: Bad Request for url: │ │ │ │ http://nah-bruv.local:45869/get_files'+331 │ │ │ │ reason = 'Bad Request' │ │ │ │ self = │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ HTTPError: 400 Client Error: Bad Request for url: http://nah-bruv.local:45869/get_files/search_files?tags=%5B%22system%3Afiletype%3Dvideo%2C+gif%2C+apng%22%2C+%22system%3Ahas+duration%22%2C+ %22system%3Afile+service+is+not+currently+in+trash%22%5D&file_service_keys=%5B%226969696969696969nah-bruv69696969696969696969696969696969696963 b%22%5D&file_sort_type=0&file_sort_asc=true&return_file_ids=false&return_hashes=true During handling of the above exception, another exception occurred: ╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮ │ /home/profmoose/personalProjects/hydrus-video-deduplicator/src/hydrusvideodeduplicator/__main__. │ │ py:146 in main │ │ │ │ 143 │ superdeduper.clear_trashed_files_from_db() │ │ 144 │ │ │ 145 │ # Run all deduplicate functionality │ │ ❱ 146 │ superdeduper.deduplicate( │ │ 147 │ │ overwrite=overwrite, │ │ 148 │ │ custom_query=query, │ │ 149 │ │ skip_hashing=skip_hashing, │ │ │ │ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │ │ │ api_key = '6969696969696969nah-bruv69696969696969696969696969696969… │ │ │ │ api_url = 'http://nah-bruv.local:45869' │ │ │ │ clear_search_cache = False │ │ │ │ debug = True │ │ │ │ error_connecting = False │ │ │ │ error_connecting_exception = '' │ │ │ │ error_connecting_exception_msg = '' │ │ │ │ file_service_key = [ │ │ │ │ │ │ │ │ │ '6969696969696969nah-bruv69696969696969696969696969696969… │ │ │ │ ] │ │ │ │ hydrus_client = │ │ │ │ job_count = -2 │ │ │ │ loglevel = 10 │ │ │ │ overwrite = False │ │ │ │ query = [] │ │ │ │ skip_hashing = False │ │ │ │ superdeduper = │ │ │ │ threshold = 75.0 │ │ │ │ verbose = True │ │ │ │ verify_cert = None │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │ │ │ │ /home/profmoose/personalProjects/hydrus-video-deduplicator/src/hydrusvideodeduplicator/dedup.py: │ │ 115 in deduplicate │ │ │ │ 112 │ │ if skip_hashing: │ │ 113 │ │ │ print("[yellow] Skipping perceptual hashing") │ │ 114 │ │ else: │ │ ❱ 115 │ │ │ video_hashes = list(self.retrieve_video_hashes(search_tags)) │ │ 116 │ │ │ self.add_perceptual_hashes_to_db(overwrite=overwrite, video_hashes=video_has │ │ 117 │ │ │ │ 118 │ │ self._find_potential_duplicates() │ │ │ │ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │ │ │ custom_query = [] │ │ │ │ overwrite = False │ │ │ │ search_tags = [ │ │ │ │ │ 'system:filetype=video, gif, apng', │ │ │ │ │ 'system:has duration', │ │ │ │ │ 'system:file service is not currently in trash' │ │ │ │ ] │ │ │ │ self = │ │ │ │ skip_hashing = False │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │ │ │ │ /home/profmoose/personalProjects/hydrus-video-deduplicator/src/hydrusvideodeduplicator/dedup.py: │ │ 131 in retrieve_video_hashes │ │ │ │ 128 │ │ │ 129 │ def retrieve_video_hashes(self, search_tags: Iterable[str]) -> Iterable[str]: │ │ 130 │ │ """Retrieve video hashes from Hydrus""" │ │ ❱ 131 │ │ all_video_hashes = self.client.search_files( │ │ 132 │ │ │ tags=search_tags, │ │ 133 │ │ │ file_service_keys=self.file_service_keys, │ │ 134 │ │ │ file_sort_type=hydrus_api.FileSortType.FILE_SIZE, │ │ │ │ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │ │ │ search_tags = [ │ │ │ │ │ 'system:filetype=video, gif, apng', │ │ │ │ │ 'system:has duration', │ │ │ │ │ 'system:file service is not currently in trash' │ │ │ │ ] │ │ │ │ self = │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │ │ │ │ /home/profmoose/personalProjects/hydrus-video-deduplicator/src/hydrusvideodeduplicator/hydrus_ap │ │ i/__init__.py:652 in search_files │ │ │ │ 649 │ │ if return_hashes is not None: │ │ 650 │ │ │ params["return_hashes"] = json.dumps(return_hashes) │ │ 651 │ │ │ │ ❱ 652 │ │ response = self._api_request("GET", self._SEARCH_FILES_PATH, params=params) │ │ 653 │ │ return response.json() │ │ 654 │ │ │ 655 │ def get_file_hashes( │ │ │ │ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │ │ │ deleted_file_service_keys = None │ │ │ │ file_service_keys = [ │ │ │ │ │ │ │ │ │ '6969696969696969nah-bruv6969696969696969696969696969696969696… │ │ │ │ ] │ │ │ │ file_sort_asc = True │ │ │ │ file_sort_type = │ │ │ │ params = { │ │ │ │ │ 'tags': '["system:filetype=video, gif, apng", "system:has │ │ │ │ duration", "system:file service'+28, │ │ │ │ │ 'file_service_keys': │ │ │ │ '["6969696969696969nah-bruv69696969696969696969696969696969696… │ │ │ │ │ 'file_sort_type': , │ │ │ │ │ 'file_sort_asc': 'true', │ │ │ │ │ 'return_file_ids': 'false', │ │ │ │ │ 'return_hashes': 'true' │ │ │ │ } │ │ │ │ return_file_ids = False │ │ │ │ return_hashes = True │ │ │ │ self = │ │ │ │ tag_service_key = None │ │ │ │ tags = [ │ │ │ │ │ 'system:filetype=video, gif, apng', │ │ │ │ │ 'system:has duration', │ │ │ │ │ 'system:file service is not currently in trash' │ │ │ │ ] │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │ │ │ │ /home/profmoose/personalProjects/hydrus-video-deduplicator/src/hydrusvideodeduplicator/hydrus_ap │ │ i/__init__.py:325 in _api_request │ │ │ │ 322 │ │ │ response.raise_for_status() │ │ 323 │ │ except requests.HTTPError: │ │ 324 │ │ │ if response.status_code == requests.codes.bad_request: │ │ ❱ 325 │ │ │ │ raise MissingParameter(response) │ │ 326 │ │ │ elif response.status_code in { │ │ 327 │ │ │ │ requests.codes.unauthorized, │ │ 328 │ │ │ │ requests.codes.forbidden, │ │ │ │ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │ │ │ json_data = None │ │ │ │ kwargs = { │ │ │ │ │ 'params': { │ │ │ │ │ │ 'tags': '["system:filetype=video, gif, apng", "system:has duration", │ │ │ │ "system:file service'+28, │ │ │ │ │ │ 'file_service_keys': │ │ │ │ '["6969696969696969nah-bruv696969696969696969696969696969696969696"]', │ │ │ │ │ │ 'file_sort_type': , │ │ │ │ │ │ 'file_sort_asc': 'true', │ │ │ │ │ │ 'return_file_ids': 'false', │ │ │ │ │ │ 'return_hashes': 'true' │ │ │ │ │ }, │ │ │ │ │ 'headers': { │ │ │ │ │ │ 'Hydrus-Client-API-Access-Key': │ │ │ │ '6969696969696969nah-bruv696969696969696969696969696969696969696' │ │ │ │ │ }, │ │ │ │ │ 'verify': False │ │ │ │ } │ │ │ │ method = 'GET' │ │ │ │ path = '/get_files/search_files' │ │ │ │ response = │ │ │ │ self = │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ MissingParameter: Could not parse system predicate "system:filetype=video, gif, apng"! ```

Solution

Should be a fairly straightforward fix - just update that query string parameter to be "system:filetype=video, animated gif, apng". I tested and confirmed that string works fine with the Client API

prof-m commented 1 year ago

This was fixed on Hydrus' side as of v542 - see final comment in #37 for details.