Nice Work
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
"""Client to request media sync from the server."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import base64
|
||||
from dataclasses import dataclass
|
||||
from typing import Callable
|
||||
from urllib import request, error
|
||||
|
||||
|
||||
@dataclass
|
||||
class MediaSyncClient:
|
||||
server_url: str
|
||||
box_id: str
|
||||
token_provider: Callable[[], str | None]
|
||||
timeout_seconds: int = 5
|
||||
|
||||
def request_tag_media(self, uid: str) -> bool:
|
||||
token = self.token_provider()
|
||||
if not token:
|
||||
return False
|
||||
endpoint = f"{self.server_url.rstrip('/')}/api/boxes/{self.box_id}/media-sync"
|
||||
payload = json.dumps({"uid": uid}).encode("utf-8")
|
||||
req = request.Request(
|
||||
endpoint,
|
||||
data=payload,
|
||||
method="POST",
|
||||
headers={
|
||||
"Content-Type": "application/json",
|
||||
"X-API-Token": token,
|
||||
},
|
||||
)
|
||||
try:
|
||||
with request.urlopen(req, timeout=self.timeout_seconds) as response:
|
||||
return 200 <= response.status < 300
|
||||
except error.HTTPError:
|
||||
return False
|
||||
except error.URLError:
|
||||
return False
|
||||
|
||||
def resolve_tag(self, uid: str) -> tuple[str | None, str | None]:
|
||||
token = self.token_provider()
|
||||
if not token:
|
||||
return None, None
|
||||
endpoint = (
|
||||
f"{self.server_url.rstrip('/')}/api/boxes/{self.box_id}/resolve-tag"
|
||||
)
|
||||
payload = json.dumps({"uid": uid}).encode("utf-8")
|
||||
req = request.Request(
|
||||
endpoint,
|
||||
data=payload,
|
||||
method="POST",
|
||||
headers={
|
||||
"Content-Type": "application/json",
|
||||
"X-API-Token": token,
|
||||
},
|
||||
)
|
||||
try:
|
||||
with request.urlopen(req, timeout=self.timeout_seconds) as response:
|
||||
body = response.read().decode("utf-8")
|
||||
except error.HTTPError as http_error:
|
||||
try:
|
||||
detail = json.loads(http_error.read().decode("utf-8")).get("detail")
|
||||
except Exception:
|
||||
detail = None
|
||||
if detail == "tag_blocked":
|
||||
return None, "tag_blocked"
|
||||
return None, None
|
||||
except error.URLError:
|
||||
return None, None
|
||||
|
||||
try:
|
||||
data = json.loads(body)
|
||||
except json.JSONDecodeError:
|
||||
return None, None
|
||||
media_path = data.get("media_path")
|
||||
if isinstance(media_path, str) and media_path:
|
||||
return media_path, None
|
||||
return None, None
|
||||
|
||||
def upload_media_file(self, target_folder: str, rel_path: str, data: bytes) -> bool:
|
||||
token = self.token_provider()
|
||||
if not token:
|
||||
return False
|
||||
endpoint = (
|
||||
f"{self.server_url.rstrip('/')}/api/boxes/{self.box_id}/media-import"
|
||||
)
|
||||
payload = json.dumps(
|
||||
{
|
||||
"target_folder": target_folder,
|
||||
"rel_path": rel_path,
|
||||
"content_base64": base64.b64encode(data).decode("ascii"),
|
||||
}
|
||||
).encode("utf-8")
|
||||
req = request.Request(
|
||||
endpoint,
|
||||
data=payload,
|
||||
method="POST",
|
||||
headers={
|
||||
"Content-Type": "application/json",
|
||||
"X-API-Token": token,
|
||||
},
|
||||
)
|
||||
try:
|
||||
with request.urlopen(req, timeout=self.timeout_seconds) as response:
|
||||
return 200 <= response.status < 300
|
||||
except error.HTTPError:
|
||||
return False
|
||||
except error.URLError:
|
||||
return False
|
||||
Reference in New Issue
Block a user