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
|
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):
|
for attempt in range(self.retries):
|
||||||
self._debug_panel(
|
self._debug_panel(
|
||||||
"HTTP request",
|
"HTTP request",
|
||||||
@@ -466,6 +489,16 @@ class HTTPClient:
|
|||||||
("follow_redirects", kwargs.get("follow_redirects", False)),
|
("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:
|
try:
|
||||||
response = self._client.request(method, url, **kwargs)
|
response = self._client.request(method, url, **kwargs)
|
||||||
self._debug_panel(
|
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:
|
if raise_for_status:
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
return response
|
return response
|
||||||
|
|||||||
@@ -622,7 +622,7 @@
|
|||||||
"(simfileshare\\.net/download/[0-9]+/)"
|
"(simfileshare\\.net/download/[0-9]+/)"
|
||||||
],
|
],
|
||||||
"regexp": "(simfileshare\\.net/download/[0-9]+/)",
|
"regexp": "(simfileshare\\.net/download/[0-9]+/)",
|
||||||
"status": true
|
"status": false
|
||||||
},
|
},
|
||||||
"streamtape": {
|
"streamtape": {
|
||||||
"name": "streamtape",
|
"name": "streamtape",
|
||||||
|
|||||||
@@ -23,13 +23,46 @@ _KNOWN_EXTS = {
|
|||||||
|
|
||||||
|
|
||||||
def _resolve_ext_from_meta(meta: Dict[str, Any], mime_type: Optional[str]) -> str:
|
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:
|
if ext and ext not in _KNOWN_EXTS:
|
||||||
ext = ""
|
ext = ""
|
||||||
if ext.lower() == "ebook":
|
if ext.lower() == "ebook":
|
||||||
ext = ""
|
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:
|
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 category in mime_maps.values():
|
||||||
for _ext_key, info in category.items():
|
for _ext_key, info in category.items():
|
||||||
if mime_type in info.get("mimes", []):
|
if mime_type in info.get("mimes", []):
|
||||||
@@ -1070,7 +1103,29 @@ class HydrusNetwork(Store):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# Extra pass: match a full title phrase when the query includes
|
||||||
|
# spaces or punctuation (e.g., "i've been down").
|
||||||
try:
|
try:
|
||||||
|
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(
|
payloads.append(
|
||||||
client.search_files(
|
client.search_files(
|
||||||
tags=freeform_predicates,
|
tags=freeform_predicates,
|
||||||
|
|||||||
@@ -816,6 +816,12 @@ class Add_Tag(Cmdlet):
|
|||||||
if new_tag.lower() not in existing_lower:
|
if new_tag.lower() not in existing_lower:
|
||||||
item_tag_to_add.append(new_tag)
|
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] = []
|
removed_namespace_tag: list[str] = []
|
||||||
for new_tag in item_tag_to_add:
|
for new_tag in item_tag_to_add:
|
||||||
if not isinstance(new_tag, str) or ":" not in new_tag:
|
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.extend(actual_tag_to_add)
|
||||||
|
|
||||||
|
updated_tag_list = collapse_namespace_tag(
|
||||||
|
updated_tag_list,
|
||||||
|
"title",
|
||||||
|
prefer="last"
|
||||||
|
)
|
||||||
|
|
||||||
_set_item_tags(res, updated_tag_list)
|
_set_item_tags(res, updated_tag_list)
|
||||||
final_title = _extract_title_tag(updated_tag_list)
|
final_title = _extract_title_tag(updated_tag_list)
|
||||||
_apply_title_to_result(res, final_title)
|
_apply_title_to_result(res, final_title)
|
||||||
@@ -981,6 +993,28 @@ class Add_Tag(Cmdlet):
|
|||||||
if new_tag.lower() not in existing_lower:
|
if new_tag.lower() not in existing_lower:
|
||||||
item_tag_to_add.append(new_tag)
|
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
|
changed = False
|
||||||
refreshed_list = list(existing_tag_list)
|
refreshed_list = list(existing_tag_list)
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ class search_file(Cmdlet):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Ensure we have ext field
|
# 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", ""))
|
title = str(payload.get("title", ""))
|
||||||
path_obj = Path(title)
|
path_obj = Path(title)
|
||||||
if path_obj.suffix:
|
if path_obj.suffix:
|
||||||
|
|||||||
Reference in New Issue
Block a user