diff --git a/.dockerignore b/.dockerignore index 49c31d1..078564e 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,9 +1,9 @@ # Build context for the Adventure Land image. The game itself is cloned from -# GitHub inside the Dockerfile, so only the Dockerfile and helper scripts are -# needed here. -config -data -*.md -.env -.git -.gitignore +# GitHub inside the Dockerfile, so only the Dockerfile and the helper scripts +# in docker/ are needed. Runtime data (files/, source-repos/, deploy/) stays +# out of the context - files/db holds the live MongoDB and is not readable by +# the build user. +!Dockerfile +!docker +!docker/** +.env \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 2c7662e..255ddd5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -48,6 +48,16 @@ RUN npm install --omit=dev --no-audit --no-fund \ COPY docker/patch-drm-check.js /tmp/patch-drm-check.js RUN node /tmp/patch-drm-check.js /app/node/server.js +# Local patch: self-host attribution (docker/patch-attribution.js). +# The license requires a crawlable link back to https://adventure.land, and +# the original project should not appear to support this instance. The phrase +# ships as docker/attribution/{en.js,de.json}; other languages fall back to +# English. Kept after the npm install so dependency layers stay cached. +COPY --chown=node:node docker/attribution/en.js /app/languages/en/attribution.js +COPY --chown=node:node docker/attribution/de.json /app/languages/de/attribution.json +COPY docker/patch-attribution.js /tmp/patch-attribution.js +RUN node /tmp/patch-attribution.js /app/htmls/contents/account_help.html + FROM ${NODE_IMAGE} AS runtime diff --git a/README.md b/README.md index bbc942c..552ed07 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,13 @@ Der Build wendet zusätzlich den lokalen Patch aus `docker/patch-drm-check.js` a `node/server.js`, bricht der Build mit einer klaren Meldung ab – dann das Suchmuster im Skript anpassen. +Ebenso ersetzt `docker/patch-attribution.js` die Hilfe-Zeile im Login +(„E-Mail, für alles“) durch einen Self-Host-Hinweis mit Link auf +https://adventure.land. Die Texte liegen in `docker/attribution/en.js` und +`docker/attribution/de.json`, alle anderen Sprachen fallen auf Englisch zurück. +Auch dieser Patch bricht den Build ab, wenn die Upstream-Vorlage nicht mehr +passt. + ## Gut zu wissen - **E-Mail-Verifizierung:** AWS SES ist nicht konfiguriert. Beim Registrieren @@ -161,6 +168,11 @@ Suchmuster im Skript anpassen. Backend-Containers wäre das es selbst, deshalb leitet ein kleines `socat`-Relay `127.0.0.1:7192` an den `game`-Container weiter. Ohne das schlagen Admin-/Server-Funktionen (`server_eval`) fehl. +- **Lizenz/Attribution:** Die AdventureLandOnlyUse-Lizenz verlangt einen + crawlable Link auf https://adventure.land. Der ersetzt deshalb die + „E-Mail, für alles“-Zeile im Login (siehe `docker/patch-attribution.js`). + Zusätzlich ist einmalig eine kurze Mail an hello@adventure.land fällig, wenn + die Instanz öffentlich erreichbar geht – das ist keine Code-Änderung. - **Nur lokal erreichbar:** Die Ports sind standardmäßig an `127.0.0.1` des Hosts gebunden. Für Zugriff aus dem LAN in `docker-compose.yml` die `127.0.0.1:`-Präfixe entfernen und `base_url` (sowie ggf. diff --git a/docker/attribution/de.json b/docker/attribution/de.json new file mode 100644 index 0000000..41e2c51 --- /dev/null +++ b/docker/attribution/de.json @@ -0,0 +1,3 @@ +{ + "pages.attribution.self-hosted": "Self-Hosted-Version von Adventure Land.
Original & Lizenz: adventure.land
Kein Support durch das Originalprojekt." +} diff --git a/docker/attribution/en.js b/docker/attribution/en.js new file mode 100644 index 0000000..f62c328 --- /dev/null +++ b/docker/attribution/en.js @@ -0,0 +1,14 @@ +// Self-host attribution line, copied into /app/languages/en/ at image build. +// +// The license of Adventure Land requires a crawlable link back to +// https://adventure.land and forbids implying that the original project +// supports a self-hosted instance. docker/patch-attribution.js points the +// login/selection help box at this phrase instead of the upstream +// "Email, for anything" line. +// +// English is also the fallback for every language without its own +// attribution.json, so keep the markup identical to docker/attribution/de.json. +module.exports = { + "pages.attribution.self-hosted": + 'Self-hosted version of Adventure Land.
Original & license: adventure.land
No support by the original project.', +}; diff --git a/docker/patch-attribution.js b/docker/patch-attribution.js new file mode 100644 index 0000000..bca96a3 --- /dev/null +++ b/docker/patch-attribution.js @@ -0,0 +1,55 @@ +#!/usr/bin/env node +// Local patch: self-host attribution box (applied at image build time). +// +// The AdventureLandOnlyUse license requires a crawlable link back to +// https://adventure.land, and the original project should not appear to +// support a self-hosted instance. The upstream login/character-selection help +// box (htmls/contents/account_help.html) shows "Email, for anything: +// hello@adventure.land" from a phrase. This patch points that component at +// pages.attribution.self-hosted instead, which ships as +// docker/attribution/{en.js,de.json}; all other languages fall back to English. +// +// The script fails loudly when the upstream phrase is gone or the shipped +// catalog is incomplete, so a code update cannot silently drop the attribution. + +const fs = require("node:fs"); +const path = require("node:path"); + +const template = process.argv[2] || "/app/htmls/contents/account_help.html"; +const app = path.resolve(path.dirname(template), "..", ".."); + +const upstream_id = "pages.contents.selection_features.email-for-anything-hello-adventure-land"; +const phrase_id = "pages.attribution.self-hosted"; +const license_url = "https://adventure.land"; + +function fail(message) { + console.error("patch-attribution: " + message); + process.exit(1); +} + +const catalogs = [ + ["en", require(path.join(app, "languages", "en", "attribution.js"))], + ["de", JSON.parse(fs.readFileSync(path.join(app, "languages", "de", "attribution.json"), "utf8"))], +]; + +for (const [language, catalog] of catalogs) { + const text = catalog[phrase_id]; + if (typeof text !== "string") fail("missing " + phrase_id + " in languages/" + language + "/attribution"); + if (!text.includes('href="' + license_url + '"')) { + fail("languages/" + language + "/attribution does not link to " + license_url); + } +} + +const source = fs.readFileSync(template, "utf8"); + +if (source.includes('"' + phrase_id + '"')) { + console.log("patch-attribution: already applied"); + process.exit(0); +} + +if (source.split(upstream_id).length !== 2) { + fail("expected exactly one occurrence of " + upstream_id + " in " + template); +} + +fs.writeFileSync(template, source.replace(upstream_id, phrase_id)); +console.log("patch-attribution: applied to " + template);