Production-readiness pass: security hardening, performance improvements, new services (send_message, set_repeat, refresh_library), diagnostics, reauth flow, image proxy, per-instance device IDs, exponential WS reconnect backoff, ID validation, stale device cleanup, and supporting integration plumbing. Three rounds of independent code review applied. See RELEASE_NOTES.md for the full changelog.
This commit is contained in:
@@ -9,31 +9,55 @@ CONF_HOST: Final = "host"
|
||||
CONF_PORT: Final = "port"
|
||||
CONF_API_KEY: Final = "api_key"
|
||||
CONF_SSL: Final = "ssl"
|
||||
CONF_VERIFY_SSL: Final = "verify_ssl"
|
||||
CONF_USER_ID: Final = "user_id"
|
||||
CONF_SCAN_INTERVAL: Final = "scan_interval"
|
||||
|
||||
# Defaults
|
||||
DEFAULT_PORT: Final = 8096
|
||||
DEFAULT_SSL: Final = False
|
||||
DEFAULT_SCAN_INTERVAL: Final = 10 # seconds
|
||||
DEFAULT_VERIFY_SSL: Final = True
|
||||
DEFAULT_SCAN_INTERVAL: Final = 10 # seconds (polling fallback)
|
||||
DEFAULT_SCAN_INTERVAL_WS: Final = 300 # seconds, when WebSocket is connected
|
||||
|
||||
# Emby ticks conversion (1 tick = 100 nanoseconds = 0.0000001 seconds)
|
||||
TICKS_PER_SECOND: Final = 10_000_000
|
||||
|
||||
# API endpoints (with /emby prefix for Emby Server)
|
||||
ENDPOINT_SYSTEM_INFO: Final = "/emby/System/Info"
|
||||
ENDPOINT_SYSTEM_PING: Final = "/emby/System/Ping"
|
||||
ENDPOINT_USERS: Final = "/emby/Users"
|
||||
ENDPOINT_SESSIONS: Final = "/emby/Sessions"
|
||||
ENDPOINT_ITEMS: Final = "/emby/Items"
|
||||
ENDPOINT_PREFIX_EMBY: Final = "/emby"
|
||||
ENDPOINT_PREFIX_NONE: Final = ""
|
||||
ENDPOINT_SYSTEM_INFO: Final = "/System/Info"
|
||||
ENDPOINT_SYSTEM_PING: Final = "/System/Ping"
|
||||
ENDPOINT_USERS: Final = "/Users"
|
||||
ENDPOINT_USERS_PUBLIC: Final = "/Users/Public"
|
||||
ENDPOINT_SESSIONS: Final = "/Sessions"
|
||||
ENDPOINT_ITEMS: Final = "/Items"
|
||||
ENDPOINT_ARTISTS: Final = "/Artists"
|
||||
ENDPOINT_LIBRARY_REFRESH: Final = "/Library/Refresh"
|
||||
|
||||
# WebSocket
|
||||
WEBSOCKET_PATH: Final = "/embywebsocket"
|
||||
WS_RECONNECT_MIN_DELAY: Final = 5 # seconds
|
||||
WS_RECONNECT_MAX_DELAY: Final = 300 # seconds (5 min cap)
|
||||
WS_HEARTBEAT: Final = 30 # seconds
|
||||
|
||||
# Device identification for Home Assistant
|
||||
DEVICE_ID: Final = "homeassistant_emby_player"
|
||||
DEVICE_NAME: Final = "Home Assistant"
|
||||
DEVICE_VERSION: Final = "1.0.0"
|
||||
# Fallback version string when the manifest version can't be read.
|
||||
DEFAULT_DEVICE_VERSION: Final = "0.0.0"
|
||||
|
||||
# Emby IDs are typically 32-char hex (with optional dashes / underscores);
|
||||
# bound length to reject pathological inputs while still allowing the slight
|
||||
# variations seen across Emby Server versions.
|
||||
EMBY_ID_PATTERN: Final = r"^[A-Za-z0-9_-]{1,128}$"
|
||||
|
||||
# Whitelist of Emby image types we may request.
|
||||
ALLOWED_IMAGE_TYPES: Final = frozenset(
|
||||
{"Primary", "Backdrop", "Thumb", "Logo", "Banner", "Art", "Disc", "Box"}
|
||||
)
|
||||
|
||||
# Image fetches can be larger than regular API calls.
|
||||
IMAGE_FETCH_TIMEOUT_SECONDS: Final = 30
|
||||
|
||||
# Media types
|
||||
MEDIA_TYPE_VIDEO: Final = "Video"
|
||||
@@ -70,6 +94,18 @@ COMMAND_SET_VOLUME: Final = "SetVolume"
|
||||
COMMAND_MUTE: Final = "Mute"
|
||||
COMMAND_UNMUTE: Final = "Unmute"
|
||||
COMMAND_TOGGLE_MUTE: Final = "ToggleMute"
|
||||
COMMAND_SET_REPEAT_MODE: Final = "SetRepeatMode"
|
||||
COMMAND_DISPLAY_MESSAGE: Final = "DisplayMessage"
|
||||
COMMAND_SEND_STRING: Final = "SendString"
|
||||
|
||||
# Repeat modes (Emby)
|
||||
REPEAT_MODE_NONE: Final = "RepeatNone"
|
||||
REPEAT_MODE_ONE: Final = "RepeatOne"
|
||||
REPEAT_MODE_ALL: Final = "RepeatAll"
|
||||
|
||||
# Shuffle modes (Emby)
|
||||
SHUFFLE_MODE_SORTED: Final = "Sorted"
|
||||
SHUFFLE_MODE_SHUFFLE: Final = "Shuffle"
|
||||
|
||||
# WebSocket message types
|
||||
WS_MESSAGE_SESSIONS_START: Final = "SessionsStart"
|
||||
@@ -78,6 +114,8 @@ WS_MESSAGE_SESSIONS: Final = "Sessions"
|
||||
WS_MESSAGE_PLAYBACK_START: Final = "PlaybackStart"
|
||||
WS_MESSAGE_PLAYBACK_STOP: Final = "PlaybackStopped"
|
||||
WS_MESSAGE_PLAYBACK_PROGRESS: Final = "PlaybackProgress"
|
||||
WS_MESSAGE_KEEP_ALIVE: Final = "KeepAlive"
|
||||
WS_MESSAGE_FORCE_KEEP_ALIVE: Final = "ForceKeepAlive"
|
||||
|
||||
# Attributes for extra state
|
||||
ATTR_ITEM_ID: Final = "item_id"
|
||||
@@ -87,3 +125,16 @@ ATTR_DEVICE_ID: Final = "device_id"
|
||||
ATTR_DEVICE_NAME: Final = "device_name"
|
||||
ATTR_CLIENT_NAME: Final = "client_name"
|
||||
ATTR_USER_NAME: Final = "user_name"
|
||||
ATTR_PLAY_METHOD: Final = "play_method"
|
||||
|
||||
# Service attributes
|
||||
ATTR_MESSAGE: Final = "message"
|
||||
ATTR_HEADER: Final = "header"
|
||||
ATTR_TIMEOUT_MS: Final = "timeout_ms"
|
||||
ATTR_REPEAT_MODE: Final = "repeat_mode"
|
||||
|
||||
# Stale session cleanup
|
||||
STALE_SESSION_TIMEOUT: Final = 1800 # 30 minutes
|
||||
# Don't prune devices until the integration has been running this long, to
|
||||
# avoid wiping freshly restarted entities before they reappear.
|
||||
STALE_PRUNE_GRACE_SECONDS: Final = 600 # 10 minutes
|
||||
|
||||
Reference in New Issue
Block a user