fix: extend CORS origins to comix and kagane, preserve progress on unparseable chapters
- .env.example, DEPLOY.md, docker-compose.yml: add comix.to/kagane.to to ALLOWED_ORIGINS so the userscript isn't CORS-blocked on either new site - .env.example: comment out BROWSER_WS_URL's DNS-name default, which overrides the working compose default and 500s Chrome's DevTools handler - userscript: updateToCurrentChapter() now falls back to the stored chapter/label when chapterNum is unparseable, instead of wiping progress (kagane's og:title lacks a number when a chapter has no episode suffix) - README.md: document comix/kagane in the config table, adapter reference, and key examples
This commit is contained in:
+7
-3
@@ -5,8 +5,8 @@
|
|||||||
API_TOKEN=changeme-generate-a-long-random-token
|
API_TOKEN=changeme-generate-a-long-random-token
|
||||||
|
|
||||||
# Comma-separated origins allowed to call the API (CORS). Both Asura domains
|
# Comma-separated origins allowed to call the API (CORS). Both Asura domains
|
||||||
# plus Demonic. Add/remove as the sites' hostnames change.
|
# plus Demonic, Comix, and Kagane. Add/remove as the sites' hostnames change.
|
||||||
ALLOWED_ORIGINS=https://asuracomic.net,https://asurascans.com,https://demonicscans.org
|
ALLOWED_ORIGINS=https://asuracomic.net,https://asurascans.com,https://demonicscans.org,https://comix.to,https://kagane.to
|
||||||
|
|
||||||
# --- Prod override (Traefik) only ---
|
# --- Prod override (Traefik) only ---
|
||||||
# Subdomain Traefik routes to this service (required by the prod override).
|
# Subdomain Traefik routes to this service (required by the prod override).
|
||||||
@@ -55,4 +55,8 @@ WEB_PASSWORD=
|
|||||||
|
|
||||||
# Headless-shell CDP endpoint for sites behind a JavaScript challenge (kagane).
|
# Headless-shell CDP endpoint for sites behind a JavaScript challenge (kagane).
|
||||||
# Unset disables browser polling; those sites then rely on the userscript alone.
|
# Unset disables browser polling; those sites then rely on the userscript alone.
|
||||||
BROWSER_WS_URL=ws://headless-shell:9222
|
# Leave commented — the compose files' own default (ws://172.28.0.10:9222) is
|
||||||
|
# correct. Do NOT set this to the "headless-shell" DNS name: Chrome's DevTools
|
||||||
|
# HTTP handler 500s any /json/version request whose Host header isn't an IP or
|
||||||
|
# "localhost", which silently breaks every kagane poll.
|
||||||
|
# BROWSER_WS_URL=ws://172.28.0.10:9222
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ Edit `.env`:
|
|||||||
API_TOKEN=<paste output of: openssl rand -hex 32>
|
API_TOKEN=<paste output of: openssl rand -hex 32>
|
||||||
|
|
||||||
# CORS allowlist — leave as-is unless a site changes hostname.
|
# CORS allowlist — leave as-is unless a site changes hostname.
|
||||||
ALLOWED_ORIGINS=https://asuracomic.net,https://asurascans.com,https://demonicscans.org
|
ALLOWED_ORIGINS=https://asuracomic.net,https://asurascans.com,https://demonicscans.org,https://comix.to,https://kagane.to
|
||||||
|
|
||||||
# Required for the Traefik override. Both have no fallback — compose refuses
|
# Required for the Traefik override. Both have no fallback — compose refuses
|
||||||
# to start without them. MANGA_WEB_HOST is required even if you never set
|
# to start without them. MANGA_WEB_HOST is required even if you never set
|
||||||
|
|||||||
@@ -26,9 +26,10 @@ Bromite userscript (isolated world, Shadow DOM UI, localStorage cache)
|
|||||||
| Var | Default | Notes |
|
| Var | Default | Notes |
|
||||||
|-----|---------|-------|
|
|-----|---------|-------|
|
||||||
| `API_TOKEN` | *(required)* | Bearer token shared with the userscript. |
|
| `API_TOKEN` | *(required)* | Bearer token shared with the userscript. |
|
||||||
| `ALLOWED_ORIGINS` | Asura + Demonic origins | Comma-separated CORS allowlist. |
|
| `ALLOWED_ORIGINS` | Asura + Demonic + Comix + Kagane origins | Comma-separated CORS allowlist. |
|
||||||
| `DB_PATH` | `/data/bookmarks.db` | SQLite file location. |
|
| `DB_PATH` | `/data/bookmarks.db` | SQLite file location. |
|
||||||
| `PORT` | `8080` | Plain HTTP; TLS terminated by the proxy. |
|
| `PORT` | `8080` | Plain HTTP; TLS terminated by the proxy. |
|
||||||
|
| `BROWSER_WS_URL` | `ws://172.28.0.10:9222` | Headless-shell CDP endpoint used to poll Kagane past its JS challenge. Must be an IP or `localhost` — Chrome's DevTools handler 500s any other Host header. |
|
||||||
|
|
||||||
### Endpoints
|
### Endpoints
|
||||||
|
|
||||||
@@ -40,8 +41,9 @@ Bromite userscript (isolated world, Shadow DOM UI, localStorage cache)
|
|||||||
| `GET` | `/healthz` | none | `200 ok`. |
|
| `GET` | `/healthz` | none | `200 ok`. |
|
||||||
| `GET` | `/u/{token}/manga-bookmark.user.js` | token in path | Serves the userscript with an mtime-derived `@version`. |
|
| `GET` | `/u/{token}/manga-bookmark.user.js` | token in path | Serves the userscript with an mtime-derived `@version`. |
|
||||||
|
|
||||||
`key` is `<site>:<series_id>` — e.g. `asura:trash-of-the-counts-family-f886a8af`
|
`key` is `<site>:<series_id>` — e.g. `asura:trash-of-the-counts-family-f886a8af`,
|
||||||
or `demonic:Infinite-Level-Up-in-Murim`. Sync is last-write-wins.
|
`demonic:Infinite-Level-Up-in-Murim`, `comix:12345`, or
|
||||||
|
`kagane:3fa85f64-5717-4562-b3fc-2c963f66afa6`. Sync is last-write-wins.
|
||||||
|
|
||||||
`updated_at` orders the bookmark list, so it moves only on real reading
|
`updated_at` orders the bookmark list, so it moves only on real reading
|
||||||
progress: the server applies its timestamp when the row is new or
|
progress: the server applies its timestamp when the row is new or
|
||||||
@@ -200,6 +202,8 @@ The site adapters key everything off URL regex, with `title`/`cover` from
|
|||||||
|------|-----------|-------------|-------------|
|
|------|-----------|-------------|-------------|
|
||||||
| **Asura** (`asurascans.com`) | `/comics/<slug-hash>` | `/comics/<slug-hash>/chapter/<n>` | `<slug-hash>` |
|
| **Asura** (`asurascans.com`) | `/comics/<slug-hash>` | `/comics/<slug-hash>/chapter/<n>` | `<slug-hash>` |
|
||||||
| **Demonic** (`demonicscans.org`) | `/manga/<slug>` | `/title/<slug>/chapter/<n>/<page>` (`chaptered.php?manga=<id>&chapter=<n>` 301s here) | `<slug>` |
|
| **Demonic** (`demonicscans.org`) | `/manga/<slug>` | `/title/<slug>/chapter/<n>/<page>` (`chaptered.php?manga=<id>&chapter=<n>` 301s here) | `<slug>` |
|
||||||
|
| **Comix** (`comix.to`) | `/title/<id>-<slug>` | `/title/<id>-<slug>/<uploadId>-chapter-<n>` | `<id>` |
|
||||||
|
| **Kagane** (`kagane.to`) | `/series/<uuid>` | `/series/<uuid>/reader/<bookUuid>` | `<uuid>` |
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
- **`asuracomic.net` deep links are dead (re-checked 2026-07-25).** They 301 to
|
- **`asuracomic.net` deep links are dead (re-checked 2026-07-25).** They 301 to
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
# API_TOKEN is required — compose refuses to start without it.
|
# API_TOKEN is required — compose refuses to start without it.
|
||||||
API_TOKEN: ${API_TOKEN:?set API_TOKEN in .env}
|
API_TOKEN: ${API_TOKEN:?set API_TOKEN in .env}
|
||||||
ALLOWED_ORIGINS: ${ALLOWED_ORIGINS:-https://asuracomic.net,https://asurascans.com,https://demonicscans.org}
|
ALLOWED_ORIGINS: ${ALLOWED_ORIGINS:-https://asuracomic.net,https://asurascans.com,https://demonicscans.org,https://comix.to,https://kagane.to}
|
||||||
DB_PATH: /data/bookmarks.db
|
DB_PATH: /data/bookmarks.db
|
||||||
PORT: "8080"
|
PORT: "8080"
|
||||||
# Gates the browser UI. Unset means the web routes are not served at all.
|
# Gates the browser UI. Unset means the web routes are not served at all.
|
||||||
|
|||||||
@@ -838,8 +838,8 @@
|
|||||||
title: existing.title || p.title || p.seriesId,
|
title: existing.title || p.title || p.seriesId,
|
||||||
series_url: existing.series_url || p.seriesUrl || "",
|
series_url: existing.series_url || p.seriesUrl || "",
|
||||||
cover: existing.cover || p.cover || "",
|
cover: existing.cover || p.cover || "",
|
||||||
last_chapter: p.chapterLabel || "",
|
last_chapter: p.chapterLabel || existing.last_chapter || "",
|
||||||
last_chapter_num: p.chapterNum,
|
last_chapter_num: p.chapterNum != null ? p.chapterNum : existing.last_chapter_num,
|
||||||
last_chapter_url: p.chapterUrl || "",
|
last_chapter_url: p.chapterUrl || "",
|
||||||
updated_at: Date.now(),
|
updated_at: Date.now(),
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user