Skip to content

Commit 4f0f930

Browse files
feat: delete tokens if addon is uninstalled
1 parent 0e5343d commit 4f0f930

File tree

5 files changed

+30
-7
lines changed

5 files changed

+30
-7
lines changed

app/api/endpoints/tokens.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ async def create_token(payload: TokenRequest, request: Request) -> TokenResponse
126126
await refresh_catalogs_for_credentials(payload_to_store, auth_key=verified_auth_key)
127127
except Exception as exc: # pragma: no cover - remote dependency
128128
logger.error(f"[{redact_token(token)}] Initial catalog refresh failed: {{}}", exc, exc_info=True)
129-
await token_store.delete_token(token)
129+
await token_store.delete_token(token=token)
130130
raise HTTPException(
131131
status_code=502,
132132
detail="Credentials verified, but Watchly couldn't refresh your catalogs yet. Please try again.",

app/core/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class Settings(BaseSettings):
1717
PORT: int = 8000
1818
ADDON_ID: str = "com.bimal.watchly"
1919
ADDON_NAME: str = "Watchly"
20-
APP_VERSION: str = "0.1.4"
20+
APP_VERSION: str = "0.1.5"
2121
REDIS_URL: str = "redis://redis:6379/0"
2222
TOKEN_SALT: str = "change-me"
2323
TOKEN_TTL_SECONDS: int = 0 # 0 = never expire

app/services/catalog_updater.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,25 @@
1616
MAX_CONCURRENT_UPDATES = 5
1717

1818

19-
async def refresh_catalogs_for_credentials(credentials: dict[str, Any], auth_key: str | None = None) -> bool:
19+
async def refresh_catalogs_for_credentials(
20+
credentials: dict[str, Any], auth_key: str | None = None, key: str | None = None
21+
) -> bool:
2022
"""Regenerate catalogs for the provided credentials and push them to Stremio."""
2123
stremio_service = StremioService(
2224
username=credentials.get("username") or "",
2325
password=credentials.get("password") or "",
2426
auth_key=auth_key or credentials.get("authKey"),
2527
)
28+
# check if user has addon installed or not
29+
try:
30+
addon_installed = await stremio_service.is_addon_installed()
31+
if not addon_installed:
32+
logger.info("User has not installed addon. Removing token from redis")
33+
await token_store.delete_token(key=key)
34+
return True
35+
except Exception as e:
36+
logger.exception(f"Failed to check if addon is installed: {e}")
37+
2638
try:
2739
library_items = await stremio_service.get_library_items()
2840
dynamic_catalog_service = DynamicCatalogService(stremio_service=stremio_service)
@@ -104,7 +116,7 @@ async def _update_safe(key: str, payload: dict[str, Any]) -> None:
104116

105117
async with sem:
106118
try:
107-
updated = await refresh_catalogs_for_credentials(payload)
119+
updated = await refresh_catalogs_for_credentials(payload, key=key)
108120
logger.info(
109121
f"Background refresh for {self._mask_key(key)} completed (updated={updated})",
110122
)

app/services/stremio_service.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,3 +302,11 @@ async def update_catalogs(self, catalogs: list[dict], auth_key: str | None = Non
302302
addon["manifest"]["catalogs"] = catalogs
303303
break
304304
return await self.update_addon(addons, auth_key)
305+
306+
async def is_addon_installed(self, auth_key: str | None = None):
307+
auth_key = auth_key or await self.get_auth_key()
308+
addons = await self.get_addons(auth_key)
309+
for addon in addons:
310+
if addon.get("manifest", {}).get("id") == settings.ADDON_ID:
311+
return True
312+
return False

app/services/token_store.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,12 @@ async def get_payload(self, token: str) -> dict[str, Any] | None:
133133
logger.warning("Failed to decrypt or decode cached payload for token. Key might have changed.")
134134
return None
135135

136-
async def delete_token(self, token: str) -> None:
137-
hashed = self._hash_token(token)
138-
key = self._format_key(hashed)
136+
async def delete_token(self, token: str = None, key: str = None) -> None:
137+
if not token and not key:
138+
raise ValueError("Either token or key must be provided")
139+
if token:
140+
hashed = self._hash_token(token)
141+
key = self._format_key(hashed)
139142
client = await self._get_client()
140143
await client.delete(key)
141144

0 commit comments

Comments
 (0)