diff --git a/API/HTTP.py b/API/HTTP.py index 83e05e1..66bb30b 100644 --- a/API/HTTP.py +++ b/API/HTTP.py @@ -453,6 +453,29 @@ class HTTPClient: last_exception: Exception | None = None + def _raw_debug_enabled() -> bool: + try: + val = str(os.environ.get("MM_HTTP_RAW", "")).strip().lower() + if val in {"0", "false", "no", "off"}: + return False + return is_debug_enabled() + except Exception: + return is_debug_enabled() + + def _preview(value: Any, *, limit: int = 2000) -> str: + if value is None: + return "" + try: + if isinstance(value, (dict, list, tuple)): + text = json.dumps(value, ensure_ascii=False) + else: + text = str(value) + except Exception: + text = repr(value) + if len(text) > limit: + return text[:limit] + "..." + return text + for attempt in range(self.retries): self._debug_panel( "HTTP request", @@ -466,6 +489,16 @@ class HTTPClient: ("follow_redirects", kwargs.get("follow_redirects", False)), ], ) + if _raw_debug_enabled(): + self._debug_panel( + "HTTP request raw", + [ + ("params", _preview(kwargs.get("params"))), + ("data", _preview(kwargs.get("data"))), + ("json", _preview(kwargs.get("json"))), + ("content", _preview(kwargs.get("content"))), + ], + ) try: response = self._client.request(method, url, **kwargs) self._debug_panel( @@ -481,6 +514,35 @@ class HTTPClient: ), ], ) + if _raw_debug_enabled(): + content_type = "" + try: + content_type = response.headers.get("content-type", "") + except Exception: + content_type = "" + body_preview = "" + try: + if isinstance(content_type, str) and ( + content_type.startswith("application/json") + or content_type.startswith("text/") + ): + body_preview = _preview(response.text, limit=4000) + else: + raw = response.content + if raw is None: + body_preview = "" + else: + body_preview = raw[:400].hex() + except Exception: + body_preview = "" + self._debug_panel( + "HTTP response raw", + [ + ("content_type", content_type), + ("body_preview", body_preview), + ("body_length", len(response.content) if response is not None else ""), + ], + ) if raise_for_status: response.raise_for_status() return response diff --git a/API/data/alldebrid.json b/API/data/alldebrid.json index c490d08..f092372 100644 --- a/API/data/alldebrid.json +++ b/API/data/alldebrid.json @@ -622,7 +622,7 @@ "(simfileshare\\.net/download/[0-9]+/)" ], "regexp": "(simfileshare\\.net/download/[0-9]+/)", - "status": true + "status": false }, "streamtape": { "name": "streamtape", diff --git a/Store/HydrusNetwork.py b/Store/HydrusNetwork.py index c5bffc5..eab8757 100644 --- a/Store/HydrusNetwork.py +++ b/Store/HydrusNetwork.py @@ -23,13 +23,46 @@ _KNOWN_EXTS = { def _resolve_ext_from_meta(meta: Dict[str, Any], mime_type: Optional[str]) -> str: - ext = str(meta.get("ext") or "").strip().lstrip(".") + ext = "" + for key in ("ext", "file_ext", "extension", "file_extension"): + raw = meta.get(key) + if raw: + ext = str(raw).strip().lstrip(".") + break if ext and ext not in _KNOWN_EXTS: ext = "" if ext.lower() == "ebook": ext = "" + if not ext: + filetype_human = ( + meta.get("filetype_human") + or meta.get("mime_human") + or meta.get("mime_string") + or meta.get("filetype") + ) + ft = str(filetype_human or "").strip().lstrip(".").lower() + if ft and ft != "unknown filetype": + if ft.isalnum() and len(ft) <= 8: + ext = ft + else: + try: + for token in re.findall(r"[a-z0-9]+", ft): + if token in _KNOWN_EXTS: + ext = token + break + except Exception: + pass + + if not ext: + if not mime_type or not isinstance(mime_type, str) or "/" not in mime_type: + mime_type = meta.get("mime_string") or meta.get("mime_human") or meta.get("filetype_mime") or mime_type + if not ext and mime_type: + try: + mime_type = str(mime_type).split(";", 1)[0].strip().lower() + except Exception: + mime_type = str(mime_type) for category in mime_maps.values(): for _ext_key, info in category.items(): if mime_type in info.get("mimes", []): @@ -1070,14 +1103,36 @@ class HydrusNetwork(Store): except Exception: pass + # Extra pass: match a full title phrase when the query includes + # spaces or punctuation (e.g., "i've been down"). try: - payloads.append( - client.search_files( - tags=freeform_predicates, - return_hashes=True, - return_file_ids=True, - ) + if query_lower and query_lower != "*" and "*" not in query_lower: + if any(ch in query_lower for ch in (" ", "'", "-", "_")): + payloads.append( + client.search_files( + tags=[f"title:{query_lower}*"], + return_hashes=True, + return_file_ids=True, + ) + ) + except Exception: + pass + + try: + title_ids, title_hashes = _extract_search_ids( + payloads[0] if payloads else None ) + # Optimization: for single-term queries, skip the freeform query + # to avoid duplicate requests. + single_term = bool(search_terms and len(search_terms) == 1) + if not single_term: + payloads.append( + client.search_files( + tags=freeform_predicates, + return_hashes=True, + return_file_ids=True, + ) + ) except Exception: pass diff --git a/cmdlet/add_tag.py b/cmdlet/add_tag.py index 20e58b8..03f04a8 100644 --- a/cmdlet/add_tag.py +++ b/cmdlet/add_tag.py @@ -816,6 +816,12 @@ class Add_Tag(Cmdlet): if new_tag.lower() not in existing_lower: item_tag_to_add.append(new_tag) + item_tag_to_add = collapse_namespace_tag( + item_tag_to_add, + "title", + prefer="last" + ) + removed_namespace_tag: list[str] = [] for new_tag in item_tag_to_add: if not isinstance(new_tag, str) or ":" not in new_tag: @@ -844,6 +850,12 @@ class Add_Tag(Cmdlet): ] updated_tag_list.extend(actual_tag_to_add) + updated_tag_list = collapse_namespace_tag( + updated_tag_list, + "title", + prefer="last" + ) + _set_item_tags(res, updated_tag_list) final_title = _extract_title_tag(updated_tag_list) _apply_title_to_result(res, final_title) @@ -981,6 +993,28 @@ class Add_Tag(Cmdlet): if new_tag.lower() not in existing_lower: item_tag_to_add.append(new_tag) + item_tag_to_add = collapse_namespace_tag( + item_tag_to_add, + "title", + prefer="last" + ) + + if not any( + isinstance(t, str) and t.strip().lower().startswith("title:") + for t in item_tag_to_add + ): + existing_title_tags = [ + t for t in existing_tag_list + if isinstance(t, str) and t.strip().lower().startswith("title:") + ] + if len(existing_title_tags) > 1: + item_tag_to_add.append(existing_title_tags[-1]) + item_tag_to_add = collapse_namespace_tag( + item_tag_to_add, + "title", + prefer="last" + ) + changed = False refreshed_list = list(existing_tag_list) try: diff --git a/cmdlet/search_file.py b/cmdlet/search_file.py index 5a9777f..f9f9969 100644 --- a/cmdlet/search_file.py +++ b/cmdlet/search_file.py @@ -155,7 +155,7 @@ class search_file(Cmdlet): ) # Ensure we have ext field - if "ext" not in payload: + if ("ext" not in payload) or (not str(payload.get("ext") or "").strip()): title = str(payload.get("title", "")) path_obj = Path(title) if path_obj.suffix: