v0.3.2: percent-encode Seerr query strings

Seerr's URL validator rejects aiohttp's default '+' for spaces and
demands %20. Switch the Seerr client to RFC 3986-style encoding via
urllib.parse.quote(safe='') so multi-word searches work.

Reported: '!media search Sheep Detectives' → 400.
This commit is contained in:
Maddox 2026-04-28 18:49:26 -04:00
parent 4995b746c2
commit 8f825bd65a
2 changed files with 11 additions and 2 deletions

View file

@ -1,6 +1,6 @@
maubot: 0.3.1 maubot: 0.3.1
id: com.3ddbrewery.media id: com.3ddbrewery.media
version: 0.3.1 version: 0.3.2
license: MIT license: MIT
modules: modules:
- media_bot - media_bot

View file

@ -10,6 +10,7 @@ Docs reference (Overseerr-compatible):
from __future__ import annotations from __future__ import annotations
from typing import Optional from typing import Optional
from urllib.parse import quote
import aiohttp import aiohttp
@ -18,6 +19,11 @@ class SeerrError(RuntimeError):
pass pass
def _qs(params: dict) -> str:
"""RFC 3986 query string — Seerr rejects aiohttp's default '+' for spaces."""
return "&".join(f"{quote(k, safe='')}={quote(str(v), safe='')}" for k, v in params.items())
class SeerrClient: class SeerrClient:
def __init__(self, session: aiohttp.ClientSession, base_url: str, api_key: str) -> None: def __init__(self, session: aiohttp.ClientSession, base_url: str, api_key: str) -> None:
self.session = session self.session = session
@ -25,7 +31,10 @@ class SeerrClient:
self.headers = {"X-Api-Key": api_key, "Accept": "application/json"} self.headers = {"X-Api-Key": api_key, "Accept": "application/json"}
async def _get(self, path: str, params: dict | None = None) -> dict | list: async def _get(self, path: str, params: dict | None = None) -> dict | list:
async with self.session.get(f"{self.base}{path}", headers=self.headers, params=params) as r: url = f"{self.base}{path}"
if params:
url += "?" + _qs(params)
async with self.session.get(url, headers=self.headers) as r:
if r.status >= 400: if r.status >= 400:
raise SeerrError(f"GET {path}{r.status}: {(await r.text())[:200]}") raise SeerrError(f"GET {path}{r.status}: {(await r.text())[:200]}")
return await r.json() return await r.json()