Increase rate limit for lighting state requests and enhance error handling for Cync device operations. Improve lyric search processing by splitting lyrics based on line breaks and cleaning special characters (bugfix for subsearch/seek).

This commit is contained in:
2025-10-15 10:10:56 -04:00
parent 0029a9ec19
commit c493f2aabf
2 changed files with 66 additions and 46 deletions

View File

@@ -179,7 +179,7 @@ class Lighting(FastAPI):
methods=["GET"], methods=["GET"],
include_in_schema=True, include_in_schema=True,
dependencies=[ dependencies=[
Depends(RateLimiter(times=10, seconds=2)), Depends(RateLimiter(times=25, seconds=2)),
Depends(get_current_user), Depends(get_current_user),
], ],
) )
@@ -190,7 +190,7 @@ class Lighting(FastAPI):
methods=["POST"], methods=["POST"],
include_in_schema=True, include_in_schema=True,
dependencies=[ dependencies=[
Depends(RateLimiter(times=10, seconds=2)), Depends(RateLimiter(times=25, seconds=2)),
Depends(get_current_user), Depends(get_current_user),
], ],
) )
@@ -266,7 +266,7 @@ class Lighting(FastAPI):
await self.ensure_cync_connection() await self.ensure_cync_connection()
# Apply to Cync device # Validate and extract state values
power = state.get("power", "off") power = state.get("power", "off")
if power not in ["on", "off"]: if power not in ["on", "off"]:
raise HTTPException( raise HTTPException(
@@ -296,14 +296,16 @@ class Lighting(FastAPI):
else: else:
rgb = None rgb = None
# Apply to Cync device with retry on connection issues
max_retries = 2
for attempt in range(max_retries):
try:
# Use persistent Cync API object # Use persistent Cync API object
if not self.cync_api: if not self.cync_api:
raise HTTPException(status_code=500, detail="Cync API not initialized.") raise Exception("Cync API not initialized.")
devices = self.cync_api.get_devices() devices = self.cync_api.get_devices()
if not devices or not isinstance(devices, (list, tuple)): if not devices or not isinstance(devices, (list, tuple)):
raise HTTPException( raise Exception("No devices returned from Cync API.")
status_code=500, detail="No devices returned from Cync API."
)
light = next( light = next(
( (
d d
@@ -313,10 +315,7 @@ class Lighting(FastAPI):
None, None,
) )
if not light: if not light:
raise HTTPException( raise Exception(f"Device '{self.cync_device_name}' not found")
status_code=404,
detail=f"Device '{self.cync_device_name}' not found",
)
# Set power # Set power
if power == "on": if power == "on":
@@ -332,6 +331,24 @@ class Lighting(FastAPI):
if rgb: if rgb:
await light.set_rgb(rgb) await light.set_rgb(rgb)
break # Success, exit retry loop
except Exception as e:
if attempt < max_retries - 1:
logging.warning(
"Device operation failed (attempt %d/%d): %s. Retrying with reconnection.",
attempt + 1,
max_retries,
e,
)
await self.ensure_cync_connection()
else:
logging.error(
"Device operation failed after %d attempts: %s",
max_retries,
e,
)
raise
logging.info( logging.info(
"Successfully applied state to device '%s': %s", "Successfully applied state to device '%s': %s",
self.cync_device_name, self.cync_device_name,

View File

@@ -210,20 +210,20 @@ class LyricSearch(FastAPI):
if data.sub and not data.lrc: if data.sub and not data.lrc:
seeked_found_line: Optional[int] = None seeked_found_line: Optional[int] = None
lyric_lines: list[str] = result["lyrics"].strip().split(" / ") # Split lyrics into lines based on <br> or newline characters
lyrics_text = result["lyrics"].strip()
if "<br>" in lyrics_text:
lyric_lines = lyrics_text.split("<br>")
else:
lyric_lines = lyrics_text.split("\n")
for i, line in enumerate(lyric_lines): for i, line in enumerate(lyric_lines):
line = regex.sub(r"\u2064", "", line.strip()) # Remove any special characters and extra spaces
if data.sub.strip().lower() in line.strip().lower(): cleaned_line = regex.sub(r"\u2064", "", line.strip())
if data.sub.strip().lower() in cleaned_line.lower():
seeked_found_line = i seeked_found_line = i
logging.debug(
"Found %s at %s, match for %s!",
line,
seeked_found_line,
data.sub,
) # REMOVEME: DEBUG
break break
if not seeked_found_line: if seeked_found_line is None:
return JSONResponse( return JSONResponse(
status_code=500, status_code=500,
content={ content={
@@ -232,7 +232,10 @@ class LyricSearch(FastAPI):
"failed_seek": True, "failed_seek": True,
}, },
) )
result["lyrics"] = " / ".join(lyric_lines[seeked_found_line:]) # Only include lines strictly starting from the matched line
# Use the same separator that was used to split
separator = "<br>" if "<br>" in result["lyrics"] else "\n"
result["lyrics"] = separator.join(lyric_lines[seeked_found_line:])
result["confidence"] = int(result["confidence"]) result["confidence"] = int(result["confidence"])
result["time"] = f"{float(result['time']):.4f}" result["time"] = f"{float(result['time']):.4f}"