Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion py_modules/adapters/romm/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"""

import base64
import gzip
import json
import logging
import os
Expand Down Expand Up @@ -198,9 +199,13 @@ def request(self, path: str):
def _do_request():
req = urllib.request.Request(url, method="GET")
req.add_header("Authorization", self.auth_header())
req.add_header("Accept-Encoding", "gzip")
try:
with urllib.request.urlopen(req, context=self.ssl_context(), timeout=30) as resp:
return json.loads(resp.read().decode())
data = resp.read()
if resp.headers.get("Content-Encoding") == "gzip":
data = gzip.decompress(data)
return json.loads(data.decode())
except RommApiError:
raise
except Exception as exc:
Expand Down
4 changes: 2 additions & 2 deletions py_modules/services/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ async def _try_incremental_skip(
async def _full_fetch_platform_roms(self, platform_id, platform_name, platform_slug, all_roms, pi, total_platforms):
"""Full paginated fetch of ROMs for a single platform."""
offset = 0
limit = 50
limit = 250
await self._emit_progress(
"roms",
current=len(all_roms),
Expand Down Expand Up @@ -689,7 +689,7 @@ async def _fetch_single_collection_roms(
coll_rom_ids: list[int] = []

offset = 0
limit = 50
limit = 250
while True:
self._check_cancelling()
if is_virtual:
Expand Down
6 changes: 4 additions & 2 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { DownloadQueue } from "./components/DownloadQueue";
import { initSyncManager } from "./utils/syncManager";
import { setSyncProgress } from "./utils/syncProgress";
import { updateDownload, getDownloadState } from "./utils/downloadStore";
import { registerGameDetailPatch, unregisterGameDetailPatch, registerRomMAppId } from "./patches/gameDetailPatch";
import { unregisterGameDetailPatch, registerRomMAppId } from "./patches/gameDetailPatch";
import { registerMetadataPatches, unregisterMetadataPatches, applyAllPlaytime } from "./patches/metadataPatches";
import { registerLaunchInterceptor, unregisterLaunchInterceptor } from "./utils/launchInterceptor";
import { getAllMetadataCache, getAppIdRomIdMap, ensureDeviceRegistered, getSaveSyncSettings, getAllPlaytime, getMigrationStatus, getSaveSortMigrationStatus, logError, logInfo } from "./api/backend";
Expand Down Expand Up @@ -48,7 +48,9 @@ const QAMPanel: FC = () => {
};

export default definePlugin(() => {
registerGameDetailPatch();
// registerGameDetailPatch() intentionally removed — it calls
// routerHook.addPatch() which triggers Decky route re-renders that crash
// Steam's Library page (GetAppCountWithToolsFilter TypeError).
registerLaunchInterceptor();

// Load metadata cache, register store patches, and populate RomM app ID set.
Expand Down
26 changes: 26 additions & 0 deletions tests/adapters/romm/test_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ def test_uses_auth_header(self, plugin):

fake_resp = MagicMock()
fake_resp.read.return_value = _json.dumps({"ok": True}).encode()
fake_resp.headers = {"Content-Type": "application/json"}
fake_resp.__enter__ = MagicMock(return_value=fake_resp)
fake_resp.__exit__ = MagicMock(return_value=False)

Expand All @@ -166,6 +167,31 @@ def test_uses_auth_header(self, plugin):
assert result == {"ok": True}
req = mock_open.call_args[0][0]
assert "Basic " in req.get_header("Authorization")
assert req.get_header("Accept-encoding") == "gzip"

def test_decompresses_gzip_response(self, plugin):
import gzip as _gzip
import json as _json
from unittest.mock import MagicMock, patch

plugin.settings["romm_url"] = "http://romm.local"
plugin.settings["romm_user"] = "user"
plugin.settings["romm_pass"] = "pass"
plugin.settings["romm_allow_insecure_ssl"] = False

payload = _json.dumps({"items": [1, 2, 3]}).encode()
compressed = _gzip.compress(payload)

fake_resp = MagicMock()
fake_resp.read.return_value = compressed
fake_resp.headers = {"Content-Encoding": "gzip", "Content-Type": "application/json"}
fake_resp.__enter__ = MagicMock(return_value=fake_resp)
fake_resp.__exit__ = MagicMock(return_value=False)

with patch("urllib.request.urlopen", return_value=fake_resp):
result = plugin._http_adapter.request("/api/roms")

assert result == {"items": [1, 2, 3]}


class TestRommJsonRequest:
Expand Down