Download protocol.py from ElJoker63/THOR: direct link, hf CLI and curl.
- Browser
- Download file 3.1 kB
-
https://huggingface.co/spaces/ElJoker63/THOR/resolve/main/protocol.py
- Command line
-
hf download hf://spaces/ElJoker63/THOR/protocol.py
-
curl -L -o protocol.py https://huggingface.co/spaces/ElJoker63/THOR/resolve/main/protocol.py
3.1 kB
| """ | |
| Definición de protocolo WebSocket y serialización de mensajes para comunicación con el Manager. | |
| 100% idéntico a internal/protocol/messages.go. | |
| """ | |
| import json | |
| import base64 | |
| from typing import Any, Tuple, Dict, List, Optional | |
| from dataclasses import dataclass, asdict | |
| from config import logger | |
| # Tipos de mensajes | |
| TYPE_HANDSHAKE = "handshake" | |
| TYPE_HANDSHAKE_ACK = "handshake_ack" | |
| TYPE_PING = "ping" | |
| TYPE_PONG = "pong" | |
| TYPE_TASK_ASSIGN = "task_assign" | |
| TYPE_TASK_PROGRESS = "task_progress" | |
| TYPE_TASK_COMPLETE = "task_complete" | |
| TYPE_TASK_FAILED = "task_failed" | |
| TYPE_TASK_CANCEL = "task_cancel" | |
| class VideoSettings: | |
| resolution: str = "" | |
| crf: str = "" | |
| audio_bitrate: str = "" | |
| fps: str = "" | |
| preset: str = "" | |
| codec: str = "" | |
| watermark: str = "" | |
| watermark_pos: str = "" | |
| watermark_image_file_id: str = "" | |
| format: str = "" | |
| thumbnail_file_id: str = "" | |
| class TaskState: | |
| task_id: str | |
| status: str # "converting", "completed" | |
| upload_url: str = "" | |
| class Handshake: | |
| worker_id: str | |
| secret: str | |
| cpu_cores: int | |
| max_jobs: int | |
| active_tasks: List[Dict[str, Any]] | |
| class TaskProgress: | |
| task_id: str | |
| percent: float | |
| speed: str | |
| time: str | |
| eta: str | |
| class TaskComplete: | |
| task_id: str | |
| original_size: int | |
| compressed_size: int | |
| duration_sec: float | |
| class TaskFailed: | |
| task_id: str | |
| error: str | |
| class TaskCancel: | |
| task_id: str | |
| def build_ws_packet(msg_type: str, payload_obj: Any = None) -> str: | |
| """ | |
| Empaqueta el mensaje en formato WebSocket esperado por el Manager en Go: | |
| type WSMessage struct { | |
| Type MessageType `json:"type"` | |
| Payload []byte `json:"payload,omitempty"` | |
| } | |
| En Go, un campo `[]byte` se codifica/decodifica como una cadena Base64. | |
| """ | |
| if payload_obj is not None: | |
| if hasattr(payload_obj, "__dataclass_fields__"): | |
| payload_data = asdict(payload_obj) | |
| elif isinstance(payload_obj, dict): | |
| payload_data = payload_obj | |
| else: | |
| payload_data = payload_obj | |
| raw_json = json.dumps(payload_data).encode("utf-8") | |
| b64_payload = base64.b64encode(raw_json).decode("ascii") | |
| return json.dumps({"type": msg_type, "payload": b64_payload}) | |
| return json.dumps({"type": msg_type}) | |
| def parse_ws_packet(raw_text: str) -> Tuple[str, Any]: | |
| """ | |
| Decodifica el mensaje JSON entrante soportando tanto payload en Base64 | |
| como payload embebido directamente como diccionario/objeto. | |
| """ | |
| try: | |
| data = json.loads(raw_text) | |
| msg_type = data.get("type", "") | |
| payload = data.get("payload") | |
| if isinstance(payload, str): | |
| try: | |
| decoded_bytes = base64.b64decode(payload) | |
| payload = json.loads(decoded_bytes.decode("utf-8")) | |
| except Exception: | |
| pass | |
| return msg_type, payload | |
| except Exception as e: | |
| logger.error(f"Error decodificando paquete WS: {e}") | |
| return "", None | |