d
This commit is contained in:
62
API/HTTP.py
62
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 "<null>"
|
||||
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 = "<no content>"
|
||||
else:
|
||||
body_preview = raw[:400].hex()
|
||||
except Exception:
|
||||
body_preview = "<unavailable>"
|
||||
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
|
||||
|
||||
@@ -622,7 +622,7 @@
|
||||
"(simfileshare\\.net/download/[0-9]+/)"
|
||||
],
|
||||
"regexp": "(simfileshare\\.net/download/[0-9]+/)",
|
||||
"status": true
|
||||
"status": false
|
||||
},
|
||||
"streamtape": {
|
||||
"name": "streamtape",
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user