From 5dc8a4f2f12b3ed07ea9d779c2813fab27695c6a Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 28 Sep 2026 05:19:36 +0000 Subject: [PATCH] Add Docker image, Compose, CI/CD workflows and docs - Multi-arch (amd64/arm64) panel image: static musl binary on scratch, cross-compiled with cargo-zigbuild (no QEMU), non-root, healthcheck - docker-compose.yml + .env.example for one-command deployment - CI: fmt, clippy, tests, web type-checks, Windows launcher build, real-network installs of vanilla/Fabric/Quilt/Forge/NeoForge, Docker build - Release: Windows NSIS installer with baked-in panel URL, GHCR image push and GitHub release (tag push or manual dispatch) - README, admin guide, Microsoft auth setup, architecture, development - rustfmt config and formatting pass Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_011ARcGWxLx21FwXJ3yfGriS --- .dockerignore | 10 ++ .env.example | 8 ++ .github/workflows/ci.yml | 99 +++++++++++++ .github/workflows/release.yml | 165 ++++++++++++++++++++++ .gitignore | 1 + Cargo.toml | 1 - Dockerfile | 55 ++++++++ README.md | 123 +++++++++++++++- crates/core/Cargo.toml | 1 - crates/core/src/assets.rs | 9 +- crates/core/src/http.rs | 6 +- crates/core/src/install.rs | 33 ++--- crates/core/src/java.rs | 29 ++-- crates/core/src/launch.rs | 21 ++- crates/core/src/libraries.rs | 17 +-- crates/core/src/loaders/forge.rs | 7 +- crates/core/src/meta.rs | 15 +- crates/core/src/msa.rs | 27 +--- crates/core/src/paths.rs | 17 ++- crates/core/src/ping.rs | 3 +- crates/core/src/rules.rs | 11 +- crates/core/src/servers_dat.rs | 11 +- crates/core/src/sync.rs | 6 +- crates/core/src/version.rs | 6 +- crates/core/tests/online.rs | 21 ++- crates/shared/Cargo.toml | 1 - docker-compose.yml | 36 +++++ docs/admin-guide.md | 78 ++++++++++ docs/architecture.md | 60 ++++++++ docs/development.md | 36 +++++ docs/microsoft-auth.md | 25 ++++ docs/screenshots/launcher-appearance.webp | Bin 0 -> 20952 bytes docs/screenshots/launcher-controls.webp | Bin 0 -> 24976 bytes docs/screenshots/launcher-home.webp | Bin 0 -> 28200 bytes docs/screenshots/launcher-install.webp | Bin 0 -> 27922 bytes docs/screenshots/launcher-login.webp | Bin 0 -> 11136 bytes docs/screenshots/panel-dashboard.webp | Bin 0 -> 37884 bytes docs/screenshots/panel-design.webp | Bin 0 -> 31322 bytes docs/screenshots/panel-instance.webp | Bin 0 -> 23256 bytes docs/screenshots/panel-players.webp | Bin 0 -> 32970 bytes launcher/src-tauri/Cargo.toml | 1 - launcher/src-tauri/src/accounts.rs | 6 +- launcher/src-tauri/src/game.rs | 21 ++- panel/server/Cargo.toml | 1 - panel/server/src/auth.rs | 10 +- panel/server/src/lib.rs | 5 +- panel/server/src/main.rs | 4 +- panel/server/src/packs.rs | 65 +++++++-- panel/server/src/routes/admin.rs | 85 ++++++++--- panel/server/src/routes/meta.rs | 36 +++-- panel/server/src/routes/public.rs | 12 +- panel/server/src/store.rs | 11 +- panel/server/tests/api.rs | 41 ++++-- rustfmt.toml | 2 + 54 files changed, 1019 insertions(+), 219 deletions(-) create mode 100644 .dockerignore create mode 100644 .env.example create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release.yml create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 docs/admin-guide.md create mode 100644 docs/architecture.md create mode 100644 docs/development.md create mode 100644 docs/microsoft-auth.md create mode 100644 docs/screenshots/launcher-appearance.webp create mode 100644 docs/screenshots/launcher-controls.webp create mode 100644 docs/screenshots/launcher-home.webp create mode 100644 docs/screenshots/launcher-install.webp create mode 100644 docs/screenshots/launcher-login.webp create mode 100644 docs/screenshots/panel-dashboard.webp create mode 100644 docs/screenshots/panel-design.webp create mode 100644 docs/screenshots/panel-instance.webp create mode 100644 docs/screenshots/panel-players.webp create mode 100644 rustfmt.toml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..7e333c9 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +target +**/node_modules +**/dist +.git +.github +data +docs +launcher/src +launcher/src-tauri/icons +launcher/src-tauri/gen diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..504866a --- /dev/null +++ b/.env.example @@ -0,0 +1,8 @@ +# Copy to .env and adjust. Only ADMIN_PASSWORD really matters. +PANEL_PORT=8080 +ADMIN_USERNAME=admin +ADMIN_PASSWORD=change-me-please +JWT_SECRET= +CURSEFORGE_API_KEY= +MAX_UPLOAD_MB=2048 +RUST_LOG=info diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..4976391 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,99 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +env: + CARGO_TERM_COLOR: always + +jobs: + rust: + name: Rust (fmt, clippy, tests) + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt, clippy + - uses: Swatinem/rust-cache@v2 + - name: Install Tauri system dependencies + run: | + sudo apt-get update + sudo apt-get install -y libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev + - name: Placeholder launcher frontend (tauri::generate_context needs it) + run: mkdir -p launcher/dist && echo '' > launcher/dist/index.html + - run: cargo fmt --all --check + - run: cargo clippy --workspace --all-targets --locked -- -D warnings + - run: cargo test --workspace --locked + + web: + name: Web UIs (type-check + build) + runs-on: ubuntu-24.04 + strategy: + matrix: + app: [panel/web, launcher] + defaults: + run: + working-directory: ${{ matrix.app }} + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-node@v5 + with: + node-version: 22 + cache: npm + cache-dependency-path: ${{ matrix.app }}/package-lock.json + - run: npm ci --no-audit --no-fund + - run: npm run check + - run: npm run build + + launcher-windows: + name: Launcher (Windows build check) + runs-on: windows-latest + steps: + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + - uses: actions/setup-node@v5 + with: + node-version: 22 + cache: npm + cache-dependency-path: launcher/package-lock.json + - run: npm ci --no-audit --no-fund + working-directory: launcher + - run: npm run build + working-directory: launcher + - run: cargo clippy -p scopenet-launcher --locked -- -D warnings + - run: cargo test -p scopenet-launcher -p scopenet-core -p scopenet-shared --locked + + engine-online: + name: Real installs (Mojang, Fabric, Quilt, Forge, NeoForge) + runs-on: ubuntu-24.04 + # Talks to third-party servers; a hiccup there shouldn't block merges. + continue-on-error: true + steps: + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + - name: Install games (vanilla, legacy, Fabric, Quilt, Forge, NeoForge) + run: cargo test -p scopenet-core --test online --locked -- --ignored --test-threads=2 --nocapture + + docker: + name: Docker image builds + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v5 + - uses: docker/setup-buildx-action@v3 + - uses: docker/build-push-action@v6 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: false + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..bc1742d --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,165 @@ +name: Release + +# Publish a release by pushing a tag (`git tag v0.2.0 && git push origin v0.2.0`) +# or from the Actions tab → Release → Run workflow (enter a version). +# +# Optional repository variables (Settings → Secrets and variables → Actions → Variables): +# PANEL_URL https://panel.example.com — baked into the launcher as the default server +# LOCK_PANEL "1" to stop players from changing the server +# LAUNCHER_NAME Installer / window name (default "ScopeNet Launcher") + +on: + push: + tags: ['v*.*.*'] + workflow_dispatch: + inputs: + version: + description: 'Version to release (e.g. 0.2.0)' + required: true + +permissions: + contents: write + packages: write + +env: + CARGO_TERM_COLOR: always + +jobs: + version: + runs-on: ubuntu-24.04 + outputs: + version: ${{ steps.v.outputs.version }} + tag: ${{ steps.v.outputs.tag }} + steps: + - id: v + shell: bash + run: | + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then v="${{ inputs.version }}"; else v="${GITHUB_REF_NAME}"; fi + v="${v#v}" + if ! [[ "$v" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.]+)?$ ]]; then echo "::error::'$v' is not a semantic version"; exit 1; fi + echo "version=$v" >> "$GITHUB_OUTPUT" + echo "tag=v$v" >> "$GITHUB_OUTPUT" + + launcher: + name: Windows installer + needs: version + runs-on: windows-latest + steps: + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + with: + key: release + - uses: actions/setup-node@v5 + with: + node-version: 22 + cache: npm + cache-dependency-path: launcher/package-lock.json + + - name: Stamp version + shell: bash + env: + VERSION: ${{ needs.version.outputs.version }} + run: | + sed -i "0,/^version = \".*\"/s//version = \"$VERSION\"/" Cargo.toml + node -e "const f='launcher/src-tauri/tauri.conf.json';const c=require('./'+f);c.version=process.env.VERSION;require('fs').writeFileSync(f,JSON.stringify(c,null,2))" + node -e "const f='launcher/package.json';const c=require('./'+f);c.version=process.env.VERSION;require('fs').writeFileSync(f,JSON.stringify(c,null,2))" + + - run: npm ci --no-audit --no-fund + working-directory: launcher + + - name: Build installer + working-directory: launcher + shell: bash + env: + SCOPENET_PANEL_URL: ${{ vars.PANEL_URL }} + SCOPENET_LOCK_PANEL: ${{ vars.LOCK_PANEL }} + SCOPENET_REPO: ${{ github.repository }} + LAUNCHER_NAME: ${{ vars.LAUNCHER_NAME }} + run: | + if [ -n "$LAUNCHER_NAME" ]; then + CONFIG=$(node -e "console.log(JSON.stringify({productName: process.env.LAUNCHER_NAME, app: {windows: [{...require('./src-tauri/tauri.conf.json').app.windows[0], title: process.env.LAUNCHER_NAME}]}}))") + npx tauri build --bundles nsis --config "$CONFIG" + else + npx tauri build --bundles nsis + fi + + - name: Collect installer + shell: bash + run: | + mkdir -p out + cp target/release/bundle/nsis/*-setup.exe out/ + ls -la out + + - uses: actions/upload-artifact@v4 + with: + name: windows-installer + path: out/*-setup.exe + if-no-files-found: error + + panel-image: + name: Panel image (GHCR) + needs: version + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v5 + - name: Image name (GHCR needs lowercase) + run: echo "IMAGE=ghcr.io/${GITHUB_REPOSITORY_OWNER,,}/scopenet-mc-panel" >> "$GITHUB_ENV" + - name: Stamp version + run: sed -i "0,/^version = \".*\"/s//version = \"${{ needs.version.outputs.version }}\"/" Cargo.toml + - uses: docker/setup-buildx-action@v3 + - uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.IMAGE }} + tags: | + type=semver,pattern={{version}},value=${{ needs.version.outputs.tag }} + type=semver,pattern={{major}}.{{minor}},value=${{ needs.version.outputs.tag }} + type=raw,value=latest,enable=${{ !contains(needs.version.outputs.version, '-') }} + - uses: docker/build-push-action@v6 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + + release: + name: GitHub release + needs: [version, launcher, panel-image] + runs-on: ubuntu-24.04 + steps: + - uses: actions/download-artifact@v4 + with: + name: windows-installer + path: dist + - name: Release notes + run: | + IMAGE="ghcr.io/${GITHUB_REPOSITORY_OWNER,,}/scopenet-mc-panel" + cat > notes.md <&2; exit 1 ;; \ + esac > /rust-target \ + && rustup target add "$(cat /rust-target)" +WORKDIR /src +COPY . . +# No --locked: release builds stamp the version into Cargo.toml. Dependencies +# stay pinned by Cargo.lock either way (CI enforces --locked). +RUN --mount=type=cache,target=/usr/local/cargo/registry,id=cargo-registry \ + --mount=type=cache,target=/src/target,id=scopenet-target-$TARGETARCH \ + cargo zigbuild --release -p scopenet-panel --target "$(cat /rust-target)" \ + && cp "target/$(cat /rust-target)/release/scopenet-panel" /scopenet-panel +# Data dir owned by the non-root runtime user. +RUN mkdir -p /out/data && chown 65532:65532 /out/data + +# ---- 3. Runtime -------------------------------------------------------------- +FROM scratch +LABEL org.opencontainers.image.title="ScopeNet Panel" \ + org.opencontainers.image.description="Admin panel for the ScopeNet Minecraft launcher" \ + org.opencontainers.image.source="https://github.com/scopeddlol/SCOPENET-MC" +COPY --from=build /scopenet-panel /scopenet-panel +COPY --from=web /src/panel/web/dist /web +COPY --from=build --chown=65532:65532 /out/data /data +ENV SCOPENET_BIND=0.0.0.0:8080 \ + SCOPENET_DATA_DIR=/data \ + SCOPENET_WEB_DIR=/web \ + RUST_LOG=info +USER 65532:65532 +VOLUME ["/data"] +EXPOSE 8080 +HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 CMD ["/scopenet-panel", "healthcheck"] +ENTRYPOINT ["/scopenet-panel"] diff --git a/README.md b/README.md index 961bebe..cdf4580 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,121 @@ -# SCOPENET-MC -A Windows/Linux Minecraft Launcher with a Docker-hosted admin panel. +
+ + + +# ScopeNet + +**A fast, fully customisable Minecraft launcher — and the self-hosted admin panel that controls it.** + +Brand it, publish vanilla versions or modpacks, manage players, and push changes to every launcher instantly. + +
+ +

+ Launcher home + Panel launcher designer +

+ +## What's inside + +| | | +|---|---| +| **Launcher** (Windows) | Tauri 2 + Rust + Svelte. Uses the system WebView2 instead of bundling Chromium, so the installer stays small and memory use low. | +| **Admin panel** (Docker) | Rust (Axum) + SQLite + Svelte. 14 MB image; measured ~2 MB RAM at idle. | +| **Engine** | `scopenet-core`: installs Minecraft, Java, Fabric/Quilt/Forge/NeoForge and launches the game. | + +### Launcher features + +- **Accounts** — panel accounts (username + password, offline-mode play), **Microsoft** sign-in, and local **offline** usernames. Tokens are encrypted with a key stored in Windows Credential Manager. +- **Instances** — every instance the admin publishes shows up in the sidebar; group-restricted ones only for the right players. +- **One-click play** — downloads the right **Java automatically**, the game, the mod loader and the modpack, with live speed/ETA. Files are shared between instances and verified by SHA-1. +- **Built-in server** — the instance's server is added to the multiplayer list, **auto-joined** (Quick Play on 1.20+), and its live status (players, MOTD, ping) is shown on the home screen. +- **Settings** — memory with a recommendation for your PC, resolution, fullscreen, what happens on launch, Java path, GC presets (G1 / ZGC), JVM args, **Minecraft keybind editor** (applied to every instance), custom accent colour, glass/animation toggles, UI scale, storage manager, per-instance overrides. +- **Quality of life** — game console, crash dialog with plain-English hints, repair files, offline launch from cache, self-updates from GitHub Releases, single-instance window, `Ctrl+Enter` to play. +- **Branding from the panel** — name, logo, colours, font, corner radius, glass, image/video background, news feed, social links, custom CSS. No rebuild needed. + +### Admin panel features + +- **Instances** — pick a Minecraft version + loader, or import a modpack from **Modrinth**, **CurseForge** or a **.zip** (`.mrpack`, CurseForge export, or any instance folder). Upload extra mods/configs. CurseForge mods that block third-party downloads are flagged with a download link. +- **Access control** — public, signed-in players, or specific **groups**. +- **Players** — create/approve/disable accounts, roles, groups; sign-ups closed / approval / open. +- **Launcher design** — every branding option with a **live preview** and 7 colour presets. +- **Dashboard** — launches per day, active players, popular instances, recent activity. + +

+ + + +

+ +## Quick start + +### 1. Run the panel + +```bash +curl -O https://raw.githubusercontent.com/scopeddlol/SCOPENET-MC/main/docker-compose.yml +curl -o .env https://raw.githubusercontent.com/scopeddlol/SCOPENET-MC/main/.env.example +# edit .env → set ADMIN_PASSWORD +docker compose up -d +``` + +Open `http://your-server:8080`, sign in as `admin`, then: + +1. **Launcher design** → name, logo, colours, news. +2. **Instances** → *New instance* → a version, or a Modrinth / CurseForge / .zip modpack. +3. **Settings** → how players sign in. + +> Put the panel behind HTTPS (Caddy, Traefik, nginx, Cloudflare Tunnel…) before sharing it. See [docs/admin-guide.md](docs/admin-guide.md). + +### 2. Build your branded launcher + +1. In GitHub → **Settings → Secrets and variables → Actions → Variables**, add: + - `PANEL_URL` = `https://panel.example.com` (players connect automatically) + - `LOCK_PANEL` = `1` (optional: hide the "change server" option) + - `LAUNCHER_NAME` = `MyServer Launcher` (optional) +2. **Actions → Release → Run workflow**, enter a version like `1.0.0` — or push a tag `v1.0.0`. + +The workflow builds the **Windows installer**, pushes the **panel image to GHCR** (`ghcr.io//scopenet-mc-panel`, amd64 + arm64) and publishes a **GitHub release**. Installed launchers pick up new releases automatically. + +> The GHCR package is private by default the first time — make it public under your GitHub profile → Packages if you want `docker pull` without logging in. + +## Repository layout + +``` +crates/shared Wire types shared by launcher and panel (manifest, branding, auth) +crates/core Launcher engine: Mojang/Java/loaders, file sync, launch, MS auth, ping +panel/server Admin panel API (Axum + SQLite) +panel/web Admin panel UI (Svelte 5) +launcher/ Desktop launcher UI (Svelte 5) +launcher/src-tauri Desktop launcher shell (Tauri 2) +Dockerfile Panel image (static binary on scratch) +docker-compose.yml Panel deployment +.github/workflows CI + release (installer, GitHub release, GHCR image) +``` + +## Documentation + +- [Admin guide](docs/admin-guide.md) — deploying, HTTPS, modpacks, players, backups +- [Microsoft sign-in setup](docs/microsoft-auth.md) — Azure app registration +- [Architecture](docs/architecture.md) — how the pieces fit, API reference +- [Development](docs/development.md) — running everything locally, tests + +## Configuration reference + +**Panel (environment variables)** + +| Variable | Default | | +|---|---|---| +| `ADMIN_USERNAME` | `admin` | First admin account (created on first start) | +| `ADMIN_PASSWORD` | random, printed in logs | First admin password | +| `JWT_SECRET` | auto-generated in `/data` | Signs login tokens | +| `CURSEFORGE_API_KEY` | – | Also settable in the panel | +| `MAX_UPLOAD_MB` | `2048` | Largest modpack upload | +| `SCOPENET_BIND` | `0.0.0.0:8080` | Listen address | +| `SCOPENET_DATA_DIR` | `/data` | Database, hosted files, uploads | + +**Launcher (build-time, via repository variables)** — `PANEL_URL`, `LOCK_PANEL`, `LAUNCHER_NAME`. + +## Notes + +- Minecraft is a trademark of Mojang Studios. ScopeNet is not affiliated with Mojang or Microsoft. Offline mode is intended for your own community servers. +- No license has been chosen yet — add a `LICENSE` file before distributing. diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index ff5a7cc..c240206 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -3,7 +3,6 @@ name = "scopenet-core" description = "Minecraft install / launch engine used by the ScopeNet launcher (and meta lookups in the panel)" version.workspace = true edition.workspace = true -license.workspace = true [dependencies] scopenet-shared.workspace = true diff --git a/crates/core/src/assets.rs b/crates/core/src/assets.rs index eda7a66..44dbe08 100644 --- a/crates/core/src/assets.rs +++ b/crates/core/src/assets.rs @@ -33,8 +33,7 @@ pub fn object_path(layout: &Layout, hash: &str) -> PathBuf { pub async fn load_index(client: &reqwest::Client, layout: &Layout, index: &AssetIndexRef) -> Result { let path = layout.assets().join("indexes").join(format!("{}.json", index.id)); if !http::file_ok(&path, index.sha1.as_deref(), index.size, true) { - http::download_one(client, &Download::new(index.url.clone(), path.clone(), index.sha1.clone(), index.size), &|_| {}) - .await?; + http::download_one(client, &Download::new(index.url.clone(), path.clone(), index.sha1.clone(), index.size), &|_| {}).await?; } Ok(serde_json::from_slice(&std::fs::read(&path)?)?) } @@ -64,11 +63,7 @@ pub fn materialize_legacy(layout: &Layout, index_id: &str, index: &AssetIndex, g if !index.is_virtual && !index.map_to_resources { return Ok(None); } - let target = if index.map_to_resources { - game_dir.join("resources") - } else { - layout.assets().join("virtual").join(index_id) - }; + let target = if index.map_to_resources { game_dir.join("resources") } else { layout.assets().join("virtual").join(index_id) }; for (name, obj) in &index.objects { let Some(dest) = crate::paths::safe_join(&target, name) else { continue }; if dest.exists() { diff --git a/crates/core/src/http.rs b/crates/core/src/http.rs index 9d501b2..a9967f7 100644 --- a/crates/core/src/http.rs +++ b/crates/core/src/http.rs @@ -129,10 +129,8 @@ async fn try_download(client: &reqwest::Client, dl: &Download, on_bytes: &(dyn F tokio::fs::create_dir_all(dir).await?; } let resp = client.get(&dl.url).send().await?.error_for_status()?; - let part = dl.dest.with_extension(format!( - "{}part", - dl.dest.extension().map(|e| format!("{}.", e.to_string_lossy())).unwrap_or_default() - )); + let part = + dl.dest.with_extension(format!("{}part", dl.dest.extension().map(|e| format!("{}.", e.to_string_lossy())).unwrap_or_default())); let mut file = tokio::fs::File::create(&part).await?; let mut hasher = Sha1::new(); let mut stream = resp.bytes_stream(); diff --git a/crates/core/src/install.rs b/crates/core/src/install.rs index 09a4fda..843f80f 100644 --- a/crates/core/src/install.rs +++ b/crates/core/src/install.rs @@ -47,13 +47,8 @@ impl Installed { pub fn classpath(&self, layout: &Layout) -> Vec { let libs_dir = layout.libraries(); let mut seen = std::collections::HashSet::new(); - let mut cp: Vec = self - .libraries - .iter() - .filter(|l| l.classpath) - .map(|l| l.file(&libs_dir)) - .filter(|p| seen.insert(p.clone())) - .collect(); + let mut cp: Vec = + self.libraries.iter().filter(|l| l.classpath).map(|l| l.file(&libs_dir)).filter(|p| seen.insert(p.clone())).collect(); cp.push(self.client_jar.clone()); cp } @@ -69,11 +64,8 @@ async fn vanilla_json(client: &reqwest::Client, layout: &Layout, mc: &str) -> Re return Ok(serde_json::from_slice(&bytes)?); } }; - let entry = manifest - .versions - .iter() - .find(|v| v.id == mc) - .ok_or_else(|| anyhow!("Minecraft {mc} doesn't exist in Mojang's version list"))?; + let entry = + manifest.versions.iter().find(|v| v.id == mc).ok_or_else(|| anyhow!("Minecraft {mc} doesn't exist in Mojang's version list"))?; if !http::file_ok(&path, entry.sha1.as_deref(), None, true) { http::download_one(client, &Download::new(entry.url.clone(), path.clone(), entry.sha1.clone(), None), &|_| {}).await?; } @@ -82,11 +74,8 @@ async fn vanilla_json(client: &reqwest::Client, layout: &Layout, mc: &str) -> Re fn library_downloads(libs: &[ResolvedLib], layout: &Layout, deep: bool) -> Vec { let dir = layout.libraries(); - let mut out: Vec = libs - .iter() - .filter(|l| !http::file_ok(&l.file(&dir), l.sha1.as_deref(), l.size, deep)) - .filter_map(|l| l.download(&dir)) - .collect(); + let mut out: Vec = + libs.iter().filter(|l| !http::file_ok(&l.file(&dir), l.sha1.as_deref(), l.size, deep)).filter_map(|l| l.download(&dir)).collect(); out.sort_by(|a, b| a.dest.cmp(&b.dest)); out.dedup_by(|a, b| a.dest == b.dest); out @@ -146,7 +135,11 @@ pub async fn install(client: &reqwest::Client, layout: &Layout, spec: &InstallSp Loader::Vanilla => None, Loader::Fabric | Loader::Quilt => { let lv = meta::resolve_loader_version(client, spec.loader, mc, spec.loader_version.as_deref()).await?.unwrap(); - progress::stage(reporter, Stage::Loader, format!("Installing {} {lv}", if spec.loader == Loader::Fabric { "Fabric" } else { "Quilt" })); + progress::stage( + reporter, + Stage::Loader, + format!("Installing {} {lv}", if spec.loader == Loader::Fabric { "Fabric" } else { "Quilt" }), + ); Some(loaders::fabric::profile(client, layout, spec.loader, mc, &lv).await?) } Loader::Forge | Loader::NeoForge => { @@ -204,8 +197,8 @@ pub async fn install(client: &reqwest::Client, layout: &Layout, spec: &InstallSp }; let assets_root = layout.assets(); - let game_assets = assets::materialize_legacy(layout, &asset_ref.id, &asset_index, &spec.game_dir)? - .unwrap_or_else(|| assets_root.clone()); + let game_assets = + assets::materialize_legacy(layout, &asset_ref.id, &asset_index, &spec.game_dir)?.unwrap_or_else(|| assets_root.clone()); Ok(Installed { java: java_windowed, diff --git a/crates/core/src/java.rs b/crates/core/src/java.rs index e917de1..5f94ac0 100644 --- a/crates/core/src/java.rs +++ b/crates/core/src/java.rs @@ -86,7 +86,11 @@ pub fn sibling_exe(java: &Path, windowed: bool) -> PathBuf { } let name = if windowed { "javaw.exe" } else { "java.exe" }; let candidate = java.with_file_name(name); - if candidate.exists() { candidate } else { java.to_path_buf() } + if candidate.exists() { + candidate + } else { + java.to_path_buf() + } } /// Make sure the Mojang runtime `component` (e.g. `java-runtime-delta`) is @@ -102,15 +106,14 @@ pub async fn ensure_runtime( let marker = dir.join(".scopenet-runtime"); let installed = std::fs::read_to_string(&marker).ok(); - let index: HashMap>> = - match http::get_json(client, RUNTIME_INDEX).await { - Ok(i) => i, - Err(e) if installed.is_some() && java_exe(&dir, false).exists() => { - tracing::warn!("java index unreachable ({e}); using installed {component}"); - return Ok(dir); - } - Err(e) => return Err(e).context("fetching Java runtime index"), - }; + let index: HashMap>> = match http::get_json(client, RUNTIME_INDEX).await { + Ok(i) => i, + Err(e) if installed.is_some() && java_exe(&dir, false).exists() => { + tracing::warn!("java index unreachable ({e}); using installed {component}"); + return Ok(dir); + } + Err(e) => return Err(e).context("fetching Java runtime index"), + }; let entry = index .get(platform_key()) .and_then(|p| p.get(component)) @@ -188,7 +191,11 @@ pub fn parse_java_version(text: &str) -> Option { let ver = &rest[..rest.find('"')?]; let mut parts = ver.split(['.', '_', '-', '+']); let first: u32 = parts.next()?.parse().ok()?; - if first == 1 { parts.next()?.parse().ok() } else { Some(first) } + if first == 1 { + parts.next()?.parse().ok() + } else { + Some(first) + } } #[cfg(test)] diff --git a/crates/core/src/launch.rs b/crates/core/src/launch.rs index d6625ff..ee82876 100644 --- a/crates/core/src/launch.rs +++ b/crates/core/src/launch.rs @@ -167,12 +167,7 @@ pub struct Command { pub fn build(installed: &Installed, layout: &Layout, opts: &LaunchOptions) -> Command { let v = &installed.version; let sep = if cfg!(windows) { ";" } else { ":" }; - let classpath = installed - .classpath(layout) - .iter() - .map(|p| p.to_string_lossy().into_owned()) - .collect::>() - .join(sep); + let classpath = installed.classpath(layout).iter().map(|p| p.to_string_lossy().into_owned()).collect::>().join(sep); let quick_play = v.supports_quick_play(); let env = Env::current() @@ -259,11 +254,7 @@ pub fn build(installed: &Installed, layout: &Layout, opts: &LaunchOptions) -> Co /// Java 9+ can read arguments from a file, which sidesteps Windows' /// 32k command-line limit on huge modpacks. fn write_argfile(path: &Path, args: &[String]) -> Result<()> { - let body = args - .iter() - .map(|a| format!("\"{}\"", a.replace('\\', "\\\\").replace('"', "\\\""))) - .collect::>() - .join("\n"); + let body = args.iter().map(|a| format!("\"{}\"", a.replace('\\', "\\\\").replace('"', "\\\""))).collect::>().join("\n"); std::fs::write(path, body)?; Ok(()) } @@ -340,7 +331,13 @@ mod tests { fn opts(join: bool) -> LaunchOptions { LaunchOptions { - auth: Auth { username: "Steve".into(), uuid: "b50ad385-829d-3141-a216-7e7d7539ba7f".into(), access_token: "0".into(), user_type: "legacy".into(), xuid: None }, + auth: Auth { + username: "Steve".into(), + uuid: "b50ad385-829d-3141-a216-7e7d7539ba7f".into(), + access_token: "0".into(), + user_type: "legacy".into(), + xuid: None, + }, game_dir: "/g".into(), memory_min_mb: 1024, memory_max_mb: 4096, diff --git a/crates/core/src/libraries.rs b/crates/core/src/libraries.rs index 5a86ecc..40673d3 100644 --- a/crates/core/src/libraries.rs +++ b/crates/core/src/libraries.rs @@ -37,7 +37,11 @@ impl ResolvedLib { } fn join_url(base: &str, path: &str) -> String { - if base.ends_with('/') { format!("{base}{path}") } else { format!("{base}/{path}") } + if base.ends_with('/') { + format!("{base}{path}") + } else { + format!("{base}/{path}") + } } pub fn resolve(libs: &[Library], env: &Env) -> Vec { @@ -56,11 +60,7 @@ pub fn resolve(libs: &[Library], env: &Env) -> Vec { if let Some(natives) = &lib.natives { if let Some(classifier) = natives.get(env.os) { let classifier = classifier.replace("${arch}", env.bits()); - let from_downloads = lib - .downloads - .as_ref() - .and_then(|d| d.classifiers.as_ref()) - .and_then(|c| c.get(&classifier)); + let from_downloads = lib.downloads.as_ref().and_then(|d| d.classifiers.as_ref()).and_then(|c| c.get(&classifier)); let native_coord = coord.with_classifier(&classifier); let (path, url, sha1, size) = match from_downloads { Some(a) => ( @@ -207,10 +207,7 @@ mod tests { assert_eq!(libs.len(), 3); assert!(libs[0].native && !libs[0].classpath); assert_eq!(libs[0].path, "p/w64.jar"); - assert_eq!( - libs[1].url.as_deref(), - Some("https://maven.fabricmc.net/net/fabricmc/intermediary/1.20.1/intermediary-1.20.1.jar") - ); + assert_eq!(libs[1].url.as_deref(), Some("https://maven.fabricmc.net/net/fabricmc/intermediary/1.20.1/intermediary-1.20.1.jar")); assert!(libs[2].url.is_none(), "empty url = bundled in installer"); } } diff --git a/crates/core/src/loaders/forge.rs b/crates/core/src/loaders/forge.rs index f40314a..cb83c7c 100644 --- a/crates/core/src/loaders/forge.rs +++ b/crates/core/src/loaders/forge.rs @@ -253,11 +253,8 @@ async fn run_processors(ctx: &ForgeInstall<'_>, zip: &mut Zip, profile: &Install data.insert("LIBRARY_DIR".into(), libs_dir.to_string_lossy().into_owned()); let sep = if cfg!(windows) { ";" } else { ":" }; - let processors: Vec<&Processor> = profile - .processors - .iter() - .filter(|p| p.sides.as_ref().map(|s| s.iter().any(|x| x == "client")).unwrap_or(true)) - .collect(); + let processors: Vec<&Processor> = + profile.processors.iter().filter(|p| p.sides.as_ref().map(|s| s.iter().any(|x| x == "client")).unwrap_or(true)).collect(); let total = processors.len() as u32; for (i, proc) in processors.into_iter().enumerate() { diff --git a/crates/core/src/meta.rs b/crates/core/src/meta.rs index e8ca63b..0349b02 100644 --- a/crates/core/src/meta.rs +++ b/crates/core/src/meta.rs @@ -106,11 +106,9 @@ pub async fn loader_versions(client: &reqwest::Client, loader: Loader, mc: &str) .collect() } Loader::Forge => { - let all: HashMap> = - get_json(client, &format!("{FORGE_FILES}/maven-metadata.json")).await?; - let promos: ForgePromos = get_json(client, &format!("{FORGE_FILES}/promotions_slim.json")) - .await - .unwrap_or(ForgePromos { promos: HashMap::new() }); + let all: HashMap> = get_json(client, &format!("{FORGE_FILES}/maven-metadata.json")).await?; + let promos: ForgePromos = + get_json(client, &format!("{FORGE_FILES}/promotions_slim.json")).await.unwrap_or(ForgePromos { promos: HashMap::new() }); let recommended = promos.promos.get(&format!("{mc}-recommended")).map(|v| format!("{mc}-{v}")); let mut list: Vec = all .get(mc) @@ -137,12 +135,7 @@ pub async fn loader_versions(client: &reqwest::Client, loader: Loader, mc: &str) } /// Turn "latest"/"recommended"/empty into a concrete loader version. -pub async fn resolve_loader_version( - client: &reqwest::Client, - loader: Loader, - mc: &str, - requested: Option<&str>, -) -> Result> { +pub async fn resolve_loader_version(client: &reqwest::Client, loader: Loader, mc: &str, requested: Option<&str>) -> Result> { if loader == Loader::Vanilla { return Ok(None); } diff --git a/crates/core/src/msa.rs b/crates/core/src/msa.rs index 3e2c60b..533ef06 100644 --- a/crates/core/src/msa.rs +++ b/crates/core/src/msa.rs @@ -64,11 +64,7 @@ pub struct McSkin { } pub async fn start_device_code(client: &reqwest::Client, client_id: &str) -> Result { - let resp = client - .post(DEVICE_CODE_URL) - .form(&[("client_id", client_id), ("scope", SCOPE)]) - .send() - .await?; + let resp = client.post(DEVICE_CODE_URL).form(&[("client_id", client_id), ("scope", SCOPE)]).send().await?; if !resp.status().is_success() { let body = resp.text().await.unwrap_or_default(); bail!("Microsoft rejected the sign-in request: {body}"); @@ -116,12 +112,7 @@ pub async fn finish_device_code(client: &reqwest::Client, client_id: &str, code: pub async fn refresh(client: &reqwest::Client, client_id: &str, refresh_token: &str) -> Result { let resp: TokenResponse = client .post(TOKEN_URL) - .form(&[ - ("grant_type", "refresh_token"), - ("client_id", client_id), - ("refresh_token", refresh_token), - ("scope", SCOPE), - ]) + .form(&[("grant_type", "refresh_token"), ("client_id", client_id), ("refresh_token", refresh_token), ("scope", SCOPE)]) .send() .await? .json() @@ -210,22 +201,12 @@ async fn complete(client: &reqwest::Client, ms_access: &str, refresh_token: Stri .json() .await?; - let resp = client - .get("https://api.minecraftservices.com/minecraft/profile") - .bearer_auth(&mc.access_token) - .send() - .await?; + let resp = client.get("https://api.minecraftservices.com/minecraft/profile").bearer_auth(&mc.access_token).send().await?; if resp.status().as_u16() == 404 { bail!("this Microsoft account doesn't own Minecraft: Java Edition"); } let profile: McProfile = resp.error_for_status()?.json().await?; let now = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as i64; - Ok(MsaSession { - refresh_token, - mc_access_token: mc.access_token, - mc_expires_at: now + mc.expires_in, - profile, - xuid, - }) + Ok(MsaSession { refresh_token, mc_access_token: mc.access_token, mc_expires_at: now + mc.expires_in, profile, xuid }) } diff --git a/crates/core/src/paths.rs b/crates/core/src/paths.rs index 17d18fc..99dff59 100644 --- a/crates/core/src/paths.rs +++ b/crates/core/src/paths.rs @@ -49,12 +49,13 @@ impl Layout { /// Keep instance ids filesystem-safe no matter what the panel sends. pub fn sanitize_id(id: &str) -> String { - let s: String = id - .chars() - .map(|c| if c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '.' { c } else { '_' }) - .collect(); + let s: String = id.chars().map(|c| if c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '.' { c } else { '_' }).collect(); let s = s.trim_matches('.').to_string(); - if s.is_empty() { "_".into() } else { s } + if s.is_empty() { + "_".into() + } else { + s + } } /// Join a server-provided relative path onto `base`, refusing anything that @@ -72,7 +73,11 @@ pub fn safe_join(base: &Path, rel: &str) -> Option { p => out.push(p), } } - if out == base { None } else { Some(out) } + if out == base { + None + } else { + Some(out) + } } #[cfg(test)] diff --git a/crates/core/src/ping.rs b/crates/core/src/ping.rs index d5f4c0e..f1d497d 100644 --- a/crates/core/src/ping.rs +++ b/crates/core/src/ping.rs @@ -231,7 +231,8 @@ mod tests { #[test] fn flattens_motd() { - let v: serde_json::Value = serde_json::from_str(r#"{"text":"","extra":[{"text":"Scope","color":"aqua","bold":true},{"text":"Net"}]}"#).unwrap(); + let v: serde_json::Value = + serde_json::from_str(r#"{"text":"","extra":[{"text":"Scope","color":"aqua","bold":true},{"text":"Net"}]}"#).unwrap(); assert_eq!(flatten_chat(&v), "§b§lScope§rNet"); assert_eq!(flatten_chat(&serde_json::json!("§aHello")), "§aHello"); } diff --git a/crates/core/src/rules.rs b/crates/core/src/rules.rs index 5015c7e..352085f 100644 --- a/crates/core/src/rules.rs +++ b/crates/core/src/rules.rs @@ -57,7 +57,11 @@ impl Env { /// `${arch}` substitution used in legacy native classifiers. pub fn bits(&self) -> &'static str { - if self.arch == "x86" { "32" } else { "64" } + if self.arch == "x86" { + "32" + } else { + "64" + } } } @@ -126,10 +130,7 @@ mod tests { #[test] fn evaluates_rules() { - let rules: Vec = serde_json::from_str( - r#"[{"action":"allow"},{"action":"disallow","os":{"name":"osx"}}]"#, - ) - .unwrap(); + let rules: Vec = serde_json::from_str(r#"[{"action":"allow"},{"action":"disallow","os":{"name":"osx"}}]"#).unwrap(); assert!(allowed(&rules, &env("windows"))); assert!(!allowed(&rules, &env("osx"))); diff --git a/crates/core/src/servers_dat.rs b/crates/core/src/servers_dat.rs index 5bb4e9b..70918e7 100644 --- a/crates/core/src/servers_dat.rs +++ b/crates/core/src/servers_dat.rs @@ -46,7 +46,11 @@ pub fn upsert(game_dir: &Path, name: &str, address: &str) -> Result<()> { } pub fn format_address(host: &str, port: u16) -> String { - if port == 25565 { host.to_string() } else { format!("{host}:{port}") } + if port == 25565 { + host.to_string() + } else { + format!("{host}:{port}") + } } #[cfg(test)] @@ -74,10 +78,7 @@ mod tests { upsert(dir.path(), "Friend", "friend.net").unwrap(); upsert(dir.path(), "ScopeNet", "play.scopenet.gg").unwrap(); upsert(dir.path(), "ScopeNet SMP", "play.scopenet.gg").unwrap(); - assert_eq!( - names(dir.path()), - vec![("ScopeNet SMP".into(), "play.scopenet.gg".into()), ("Friend".into(), "friend.net".into())] - ); + assert_eq!(names(dir.path()), vec![("ScopeNet SMP".into(), "play.scopenet.gg".into()), ("Friend".into(), "friend.net".into())]); assert_eq!(format_address("a.b", 25565), "a.b"); assert_eq!(format_address("a.b", 25570), "a.b:25570"); } diff --git a/crates/core/src/sync.rs b/crates/core/src/sync.rs index a876adb..0da4dea 100644 --- a/crates/core/src/sync.rs +++ b/crates/core/src/sync.rs @@ -76,11 +76,7 @@ pub async fn sync( continue; }; wanted.insert(f.path.replace('\\', "/")); - let ok = if changed { - http::file_ok(&dest, Some(&f.sha1), Some(f.size), true) - } else { - dest.exists() - }; + let ok = if changed { http::file_ok(&dest, Some(&f.sha1), Some(f.size), true) } else { dest.exists() }; if !ok { downloads.push(Download::new(resolve_url(panel_base, &f.url), dest, Some(f.sha1.clone()), Some(f.size))); } diff --git a/crates/core/src/version.rs b/crates/core/src/version.rs index 31dd4b6..c92f423 100644 --- a/crates/core/src/version.rs +++ b/crates/core/src/version.rs @@ -170,11 +170,7 @@ impl VersionJson { } pub fn java_component(&self) -> String { - self.java_version - .as_ref() - .map(|j| j.component.clone()) - .filter(|c| !c.is_empty()) - .unwrap_or_else(|| "jre-legacy".into()) + self.java_version.as_ref().map(|j| j.component.clone()).filter(|c| !c.is_empty()).unwrap_or_else(|| "jre-legacy".into()) } /// True for 1.13+ style argument lists. diff --git a/crates/core/tests/online.rs b/crates/core/tests/online.rs index 6dbc830..880e13f 100644 --- a/crates/core/tests/online.rs +++ b/crates/core/tests/online.rs @@ -7,11 +7,20 @@ use scopenet_core::{progress, Layout}; use scopenet_shared::Loader; async fn run(mc: &str, loader: Loader) { - let root = std::env::var("SCOPENET_TEST_ROOT").map(std::path::PathBuf::from).unwrap_or_else(|_| std::env::temp_dir().join("scopenet-online")); + let root = + std::env::var("SCOPENET_TEST_ROOT").map(std::path::PathBuf::from).unwrap_or_else(|_| std::env::temp_dir().join("scopenet-online")); let layout = Layout::new(&root); let client = scopenet_core::http::client(); let game_dir = layout.instance_dir(&format!("{mc}-{}", loader.as_str())); - let spec = InstallSpec { mc_version: mc.into(), loader, loader_version: None, java_override: None, game_dir: game_dir.clone(), concurrency: 16, deep_verify: false }; + let spec = InstallSpec { + mc_version: mc.into(), + loader, + loader_version: None, + java_override: None, + game_dir: game_dir.clone(), + concurrency: 16, + deep_verify: false, + }; let installed = install(&client, &layout, &spec, &progress::noop()).await.unwrap_or_else(|e| panic!("{mc} {loader:?}: {e:#}")); for path in installed.classpath(&layout) { @@ -20,7 +29,13 @@ async fn run(mc: &str, loader: Loader) { assert!(installed.java.exists(), "java missing at {}", installed.java.display()); let opts = LaunchOptions { - auth: Auth { username: "CiBot".into(), uuid: scopenet_shared::offline_uuid("CiBot"), access_token: "0".into(), user_type: "legacy".into(), xuid: None }, + auth: Auth { + username: "CiBot".into(), + uuid: scopenet_shared::offline_uuid("CiBot"), + access_token: "0".into(), + user_type: "legacy".into(), + xuid: None, + }, game_dir, memory_min_mb: 512, memory_max_mb: 2048, diff --git a/crates/shared/Cargo.toml b/crates/shared/Cargo.toml index d07fd5f..ff08c23 100644 --- a/crates/shared/Cargo.toml +++ b/crates/shared/Cargo.toml @@ -3,7 +3,6 @@ name = "scopenet-shared" description = "Types shared between the ScopeNet launcher and admin panel" version.workspace = true edition.workspace = true -license.workspace = true [dependencies] serde.workspace = true diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..c149d7f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,36 @@ +# ScopeNet admin panel +# +# cp .env.example .env # set ADMIN_PASSWORD at least +# docker compose up -d +# +# Then open http://localhost:8080 (or your domain behind a reverse proxy). +services: + panel: + image: ghcr.io/scopeddlol/scopenet-mc-panel:latest + # Or build from source: docker compose build + build: . + container_name: scopenet-panel + restart: unless-stopped + ports: + - "${PANEL_PORT:-8080}:8080" + environment: + ADMIN_USERNAME: ${ADMIN_USERNAME:-admin} + # First start only: creates the admin account. If empty, a random + # password is printed in `docker compose logs panel`. + ADMIN_PASSWORD: ${ADMIN_PASSWORD:-} + # Signs login tokens. Auto-generated into the data volume if empty. + JWT_SECRET: ${JWT_SECRET:-} + # Optional — can also be set in the panel's Settings page. + CURSEFORGE_API_KEY: ${CURSEFORGE_API_KEY:-} + MAX_UPLOAD_MB: ${MAX_UPLOAD_MB:-2048} + RUST_LOG: ${RUST_LOG:-info} + volumes: + - panel-data:/data + # Very small footprint: the panel idles at ~10 MB RAM. + deploy: + resources: + limits: + memory: 256M + +volumes: + panel-data: diff --git a/docs/admin-guide.md b/docs/admin-guide.md new file mode 100644 index 0000000..cc63fee --- /dev/null +++ b/docs/admin-guide.md @@ -0,0 +1,78 @@ +# Admin guide + +## Deploying the panel + +```bash +cp .env.example .env # set ADMIN_PASSWORD +docker compose up -d +docker compose logs -f panel # first start prints the admin account +``` + +Everything the panel stores lives in the `panel-data` volume (`/data`): + +| Path | What | +|---|---| +| `panel.db` | SQLite database (users, instances, settings, stats) | +| `files//` | Configs and uploads hosted for launchers | +| `uploads/` | Logos, backgrounds, icons | +| `jwt.secret` | Token signing key (unless `JWT_SECRET` is set) | + +**Backups:** stop the container (or use `sqlite3 panel.db ".backup backup.db"`) and copy the volume. + +**Updating:** `docker compose pull && docker compose up -d`. Database migrations run automatically. + +### HTTPS + +Launchers talk to the panel over the internet, so serve it over HTTPS. Example with Caddy: + +```caddyfile +panel.example.com { + reverse_proxy localhost:8080 +} +``` + +Large modpack uploads go through the proxy — raise its body-size limit if needed (nginx: `client_max_body_size 2g;`). + +## Instances + +An instance = one playable profile: a Minecraft version, an optional mod loader, files (mods, configs…) and an optional server. + +- **Version** — choose any Minecraft version and Vanilla / Fabric / Quilt / Forge / NeoForge. Leave the loader version empty for the latest recommended build (it's pinned when you save). +- **Modrinth** — search, pick a version, *Use*. Mods are downloaded by players straight from Modrinth's CDN; configs (`overrides/`) are hosted by the panel. +- **CurseForge** — needs a free API key from [console.curseforge.com](https://console.curseforge.com) (Settings → Integrations, or `CURSEFORGE_API_KEY`). Some authors block third-party downloads; those files show up under **Files** with a link — download them yourself and upload them into the same folder. +- **Upload .zip** — a `.mrpack`, a CurseForge export, or any zipped instance folder (with `mods/`, `config/`, … or a `.minecraft/` inside). For plain zips, pick the Minecraft version and loader. +- **Files** — add or remove individual files at any time. Files players add themselves are never touched; files you remove are deleted from players' instances on their next launch. + +Every save bumps the instance **revision**; launchers re-verify files when it changes, otherwise launching is instant. + +### Built-in server + +On the **Server** tab: name, address, port. + +- *Add to multiplayer list* writes the server into `servers.dat` (keeping servers players added). +- *Join automatically* connects on start (Quick Play on 1.20+, `--server` on older versions). + +Your server must allow the accounts you use: offline-mode (`online-mode=false`) for panel/offline accounts, or online-mode for Microsoft accounts. Protect offline-mode servers with a whitelist or an auth plugin. + +### Access + +- **Everyone** — any launcher, including offline and Microsoft accounts. +- **Signed-in players** — any panel account. +- **Specific groups** — members of the selected groups (create groups on the Players page). Admins see everything. + +## Players + +- **Sign-ups:** Settings → *Closed* (admins create accounts), *Needs approval*, or *Open*. +- Panel accounts play under their username with the offline-mode UUID an offline server computes, so inventories and permissions stay consistent. +- Disabling an account signs it out everywhere on the next request. +- Ten failed logins lock an account for five minutes. + +## Launcher design + +Everything on this page is pushed to launchers when they start or refresh — no reinstall. The **Features** tab lets you allow or block players from changing the theme or Java settings. **Custom CSS** is injected last; handy variables are `--accent`, `--accent-2`, `--surface`, `--radius`. + +## Releasing the launcher + +See the README's *Build your branded launcher*. Players get updates automatically: the launcher checks GitHub Releases on start and offers the new installer. + +**Code signing:** unsigned installers trigger a Windows SmartScreen warning ("More info → Run anyway"). To avoid it, sign the installer with a code-signing certificate (e.g. Azure Trusted Signing) — Tauri supports this via `bundle.windows.signCommand`. diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..77a6b21 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,60 @@ +# Architecture + +``` +┌──────────────────────────┐ HTTPS (JSON) ┌──────────────────────────┐ +│ Launcher (Tauri) │ ─────────────────────────▶ │ Panel (Axum + SQLite) │ +│ Svelte UI ⇄ Rust shell │ manifest, instances, │ Svelte admin UI │ +│ │ │ auth, stats │ /files, /uploads │ +│ scopenet-core engine │ └──────────────────────────┘ +│ ├─ Mojang / Java │ ──▶ piston-meta, libraries.minecraft.net, resources +│ ├─ Fabric/Quilt/Forge │ ──▶ meta.fabricmc.net, maven.minecraftforge.net, … +│ └─ modpack files │ ──▶ Modrinth/CurseForge CDNs, panel /files +└──────────────────────────┘ +``` + +- **`crates/shared`** defines every JSON type exchanged, so the panel and launcher can't drift apart. +- **`crates/core`** has no UI dependencies. It's unit-tested, and CI runs real installs of vanilla, legacy, Fabric, Quilt, Forge and NeoForge against the live servers. +- The **panel** also uses `core` for version and loader lookups. + +## Launch pipeline + +1. Resolve the account (refreshing Microsoft tokens if needed). +2. Fetch the instance from the panel (cached for offline play). +3. `install`: vanilla version JSON → Java runtime (Mojang's own builds) → client jar, libraries, assets → loader profile (Fabric/Quilt), or replay the Forge/NeoForge installer's processors → merge → natives. +4. `sync`: download the admin's files; remove files the admin removed; never touch the player's own files. With an unchanged revision, only existence is checked. +5. Write `servers.dat` and keybinds, build the Java command (quick play / `--server`, memory, GC presets, `@argfile` for long classpaths), and start the game. +6. Stream logs to the console; on a crash, show the tail of the log with hints. + +## Disk layout (launcher) + +``` +%APPDATA%\net.scopenet.launcher\ + settings.json, accounts.json, secrets.bin (encrypted), manifest.json (cache) + minecraft\ + versions\ libraries\ assets\ runtimes\ natives\ cache\ + instances\\ ← game directory (saves, mods, options.txt, …) +``` + +## HTTP API + +Public (used by launchers). Send `Authorization: Bearer ` to see restricted instances: + +| Method | Path | | +|---|---|---| +| GET | `/api/v1/launcher/manifest` | Branding, auth options, visible instances | +| GET | `/api/v1/launcher/instances/{id}` | Instance + file list | +| POST | `/api/v1/launcher/events` | Launch stats | +| POST | `/api/v1/auth/login` · `/register` | Panel accounts | +| GET | `/api/v1/auth/me` | Current user | +| GET | `/files/{instance}/{path}` | Hosted instance files | +| GET | `/healthz` | Health check | + +Admin (`role = admin`): `/api/admin/{stats,users,groups,branding,settings,instances,uploads}` plus `instances/{id}/{import/modrinth,import/curseforge,import/upload,files,reset}` and meta/search proxies under `/api/admin/{meta,modrinth,curseforge}`. + +## Security notes + +- Passwords are hashed with Argon2id; tokens are HS256 JWTs (30 days); disabled accounts are rejected on every request. +- Server-provided paths are sanitised (`safe_join`) on both sides — no `..` or absolute paths. +- The panel never returns the CurseForge key; SVG uploads are refused (script risk). +- The launcher's CSP only allows scripts from the app itself; media may load from any HTTPS host (admin-chosen images). +- Hosted `/files` are public URLs. Don't put secrets in instance files. diff --git a/docs/development.md b/docs/development.md new file mode 100644 index 0000000..60e89a7 --- /dev/null +++ b/docs/development.md @@ -0,0 +1,36 @@ +# Development + +**Requirements:** Rust (stable), Node 22. On Linux, also the Tauri deps: `libwebkit2gtk-4.1-dev librsvg2-dev libayatana-appindicator3-dev`. + +## Panel + +```bash +cd panel/web && npm install && npm run build && cd ../.. +ADMIN_PASSWORD=adminadmin cargo run -p scopenet-panel # http://localhost:8080 +# UI hot reload: (cd panel/web && npm run dev) # http://localhost:5173, proxies /api +``` + +## Launcher + +```bash +cd launcher && npm install +npm run tauri dev # full desktop app +npm run dev # UI only in a browser, with a mock backend (http://localhost:1420) +``` + +Browser mock scenarios: `?mock=setup`, `?mock=login`, `?mock=progress`. + +Build-time options (environment variables when building): `SCOPENET_PANEL_URL`, `SCOPENET_LOCK_PANEL=1`, `SCOPENET_REPO=owner/repo`. + +## Tests + +```bash +cargo test --workspace # unit + panel API tests +cargo test -p scopenet-core --test online -- --ignored # real installs (needs internet, ~2 GB) +(cd panel/web && npm run check) && (cd launcher && npm run check) +cargo fmt --all && cargo clippy --workspace --all-targets -- -D warnings +``` + +## Releasing + +Push a tag `vX.Y.Z` or run the **Release** workflow. It stamps the version into `Cargo.toml` and `tauri.conf.json`, builds the NSIS installer on Windows, pushes the multi-arch panel image to GHCR, and publishes the release. diff --git a/docs/microsoft-auth.md b/docs/microsoft-auth.md new file mode 100644 index 0000000..aff3913 --- /dev/null +++ b/docs/microsoft-auth.md @@ -0,0 +1,25 @@ +# Microsoft sign-in + +Microsoft accounts give players their real skin and let them join online-mode servers. It needs an Azure app registration that Mojang has approved for the Minecraft API. + +## 1. Register an app + +1. Go to [portal.azure.com](https://portal.azure.com) → **Microsoft Entra ID → App registrations → New registration**. +2. Name: your launcher's name. Supported account types: **Personal Microsoft accounts only**. +3. Redirect URI: leave empty. +4. After creating it, open **Authentication** → enable **Allow public client flows** (needed for the device-code flow) → Save. +5. Copy the **Application (client) ID**. + +## 2. Request Minecraft API access + +New apps can't call the Minecraft services API until Mojang approves them. Submit the form at with your client ID. Approval can take a while; until then sign-in fails with *"Minecraft services rejected the Xbox token"*. + +## 3. Enable it in the panel + +**Settings → Microsoft accounts** → turn on *Sign in with Microsoft* and paste the client ID. Launchers show the Microsoft tab on their next refresh. + +## How it works + +The launcher uses the OAuth **device-code flow**: it shows a short code, opens `microsoft.com/link`, and waits. The chain is Microsoft → Xbox Live → XSTS → Minecraft services → profile. The refresh token is stored encrypted on the player's PC and renewed silently before launches. The panel never sees Microsoft credentials. + +Common errors are translated for players (no Xbox profile yet, child account, game not owned). diff --git a/docs/screenshots/launcher-appearance.webp b/docs/screenshots/launcher-appearance.webp new file mode 100644 index 0000000000000000000000000000000000000000..08ba17a0de837ef748182a2bbeb928d5d96a8c99 GIT binary patch literal 20952 zcmV)sK$yQ$Nk&G{Q2+o}MM6+kP&gpOQ2+q2#sQrHDqsY>0zQ#QpG+mBBO;-ZSm>}4 z31@EZubs^mJJIkldS0x)b}a#S_}%PYc>LewpGgNkeUJ3!Qolq0&i?i6@BQzpA21Kq zpVx0N4|qOczixeD|KI-7d(ZzL>H+>2{vTPNpg-}?_g0P3ge z_xS%({~P^3```Fa+wbq5nf@j7AKw3Cf8BcDWpC1dqWzrp8~H!nFVO#n{o?hL{SWw$ z75_E;v;DXDuif8(FUfzD|C|2h~u`m-*z{pQ?5? zbVeD$P8eowQeu7{(@9Vr1Ft#CGSDQux)6o4rT5vUQv1Q&h-5;;ijZ*k;IqPe`6Hv? z050UN?GJ#;hvJ>%9Iw-Icqp>!S4RN=1V88fl#nk+N!1N-q&unQzd&bi zZZf)()3S{D{Y{5`-lo*rn^TD=0S0V4uvz-_#HK@zr0^Eg0bnleAvS9@t4S(x`T)(2 z#a!@hNQ>)B|7tGcR|!5HHzwrPfEwC7&kcEAA#XVBA&hwwo9f3%%p@sofh0S;HAE2F zoJbwP&3q_m6BQMZiiJg5lXp!J0G{dBv~b))AVhmK6+lBb=%OSweSq?zpzTHuDj+M! z3orWl!^O#7h0KkcD?1yod^&DT$*lk_7K?xBZR0~I9cY)BVq)jipITUxm26k!c>Tb5 z0MQ2QP0O#C=Qe_j9L7Kgpz(5It@_5+9s?=I8nq)YbYcEEA1OI%nyR}3URUUjlxX*? zsv(!UHYqj5puf&t`D(o+x_Ixxp$7%L=s)l?`0S75Ajbp|4EiY}d;m#OfLml+>A?q9>Y9xXu<&f>FuNEyr%u+eFmm5@k zE#`1>a=9Ln5}MIS&s0y0`tc=viCVJo2M~F(O`%2fU6Ug6D&^Ln_w7&}1n=?!s=y!_ zS=(-VmM|VCH=|3zF=Tpv;|R-@k`N&;MBbX04Ys=3WDaPLc3}d1ao&sn)PY9JlRsX| zvECjqU1t4s5sWFRNw~lf5{1&*`Gp(akk-p zUg^u}OGablk;Vwc^-UDS{m{}$J)qqOzg!4tWfDd)ILiY~SCjJ8X{V)q=H~us+y(*{ z7T9F&N=i{BKNOBco)=2b%Np_+%O_jbz^32!Ts&ICXsFSaI{7nZrxxLTSz|mn-RW+zE0s z2TbOS_Q4n{vq)IXOsU5+@%U70DW!Kk2Vst*O{={Zvbbr#oVPUtcB}t!^`E-)#Elx> zU89@jjQYS>gU()OhSbX=kqDeBARf3*|2;N4?1*0LU!z)#y~|eq5Fc|=^CH#JcZ?`c z6iAa;@wbhLlIfL-ZRjaX6)O(~>^||wV6GM4yVme5U@HGSi*rRd>kX>2zsfXxHSltT zCNrV3;{cJ>tfkFO6O&&|7V;vzFxywS)xDaU@hg>=91c7YrASNs_6heU7Jx30@r#%a zQ5CJsZwrg!QVBj(==IMRrr1wJ7zkNFP)1dL19!Aj8}KVc_?TgB7$m|6%YKxbfl!a}UC z8zsWFrrD}p0{XQW2z2!u#~+qNHAKGLfVe$=8Po96Q*t^@#66ftuJwx8tT~^TOJ6r) zHoh5(WQu{#h^geE`hWP~se16h0{u_uqZ8VkTfu>lO=3>EB&?Qz!ndBZ-g4@YzN`C1 z>0&(hWk5R@7ON5KaxEJu+^+maS^S0tCrqI@j=KQV6!GUI2v33kpg2ORIt0ipQgflD z$OiSRybKs0TyN6;pKcoSq;u;GyQ7*HL2?&IZ8t-6CNYC#d@e4AwqLAwFCPqiBTJsq zaoTvWct-|fPryg5WT}4k*=)Lh=&T*72cF<6E@uhD%0Y201LdvQEfkbZf}xS$E5nj# znBzipK*n<%E|$iP2ziaBQggx6YJR9=^J0|6zN*)7!3hI(&fRx{4$*t}k>4@j3RwAc zv-u1PPLcwrsEut4ozS2AxDD3Uvhz|Ros5|#QWdq~e==hFRXt)PeJiyw)7PP_lnA&H zQ+1>&p^p>DgH&XR@5gqbFagfbp@F$7E0MB9u=UZPWz#ZUOQCKK4t*}YT0sHy2D z;>3kWmQfkfYfjW9J)(YJLPiR#jv_X@Kf^CtQz;A+((~Y>?Q>AC|6KTCV;2R)ZL>^u zKj(8>kiVy>;pStCs?NL4_fkHPMHQ^+%Ls4ZzlWeArLa<>`uVI?dGNjpPj!`mA$!2@ zqFI?%!~lyrrqv)sp!sAecKt;a`lEj5b<^HW06i{$pGm(gHBm#i*n!q_w{r_0c%o(m3v&L#E zsxqfGnr>>B5q5PoM?(^gG%*6RprK4cEV|&nke9L0JM(-a$5#9OkCz~2xiu{Re z90h=|76z03l04NOks(nU@e>x!1sno-WQNcN{H8eF&_fkZ8)V-KI*@XCpdfO5G4Q+P zm_8NB8GKZtr8COf9=h`36L4d~FmZ(jradqwRdrQR&>;)W$(W$gWZu%7(@5fb07CaB zxNHT0!%(@xa`Js~yK}`U8r=@tpUNVVfjx}Cl>wX_y^QW*7O$g_Ik;KFjAx$B$o=f`wqMSD~#p7IF zn#T^B%)nOBLv&I?A8}jv@M6h+T`dx|y%qge8saJ}!aaB8s`QlHAN0Jv(Thr078xSv zcCi)0Pz#yim%4L>j)E;lfFXbZ;ZyxI;xUqA5#1 z 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 literal 0 HcmV?d00001 diff --git a/docs/screenshots/launcher-controls.webp b/docs/screenshots/launcher-controls.webp new file mode 100644 index 0000000000000000000000000000000000000000..1ee7a3b2cdfd06c61f4da0cc873091becc01b04b GIT binary patch literal 24976 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 z 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 literal 0 HcmV?d00001 diff --git a/docs/screenshots/launcher-install.webp b/docs/screenshots/launcher-install.webp new file mode 100644 index 0000000000000000000000000000000000000000..a47ff4eaa522ad620127759ae2e63a1464a7dbe1 GIT binary patch literal 27922 zcmV)SK(fD5Nk&ErZ2$mQMM6+kP&gp|Yybd|AOf8MDqsY>0zQ#Qpi8BsCZeMA85qzK z32AQb;T1PtkuttfWNCRgrgAnidF}lQoLkl3m^VFtFdlAS@V#6Ae)SIi<>!0siT$hn z_poQ|2d7`MSNCuHnO0s<{}27U_HW?t#s5$K;rZ~Tw4f9QY4{#SY<@W=bl^B%yzmH#&Xas9K_cjAB7e~s>V z(?8CCxc@`!1?#8L|LgyV|26w}?YHY6>3_fe^M8#0|NsB!Z_NL_f4Tn={xkO1><9T@ z_22g2;r}Q;X#Z>AQ}|Ey{=k3Cf4G0k|0DUY^rQUe{{Qs*EmLF*kkq<|tx^L1(zZpQ7s5Bkd9cfx)FKIv>1-s(VDSUhba`9+`D7dJBmIzf45F+5j z>6QKBC$bW_?{ql>wt$n?q$=vBHq^q`Mqbi@IpzXh$Q$YHBCMs*cA(cauF5VV;-Ufr zl`~ynzgP|aR$UTAqs#jc0z4H<2uKvajaAu33@a0buOt z(rci*>M2@>5-l)7sC~9n!o3M3Uk$7D4h9`13pK@qRCd z9E~*VhHke>Hz$w1^R73KN6pb-g;8LoQyXe27&r-yxhbG2Tj|(At>CJc-KB};MlF-E z3iqUvI!%37szEo25@i#j1A5SOV#N@7VFaQpWe6_w8k6ZS-b?FGh1|8$Z+Y9TDwy1( z%Z7Xm)(4htsMFY(k#n^g-**&g+E?}Vi*gjn1U)TePcm3iqAMbtLf1Tj_ZJNNP&}ar4GGmhmt!DAfU6~lTRIzUq3YCA zp;cW3^qZTzA$`&>enzk&5%v-rO!FLJ)@TiL9;?GwHr4iJ-uTo#`|MRjd!poLKY z?vF2%8)_+3X(y@7PuLVLkIf4Q#f<+&Um7a?29yGGEDAfZ5yRS~PHa;M0Vp#?iU3QR zWXK_pL-weK2vej6aIqmHlV#>I=zo*5+d#U{4WdQ%q9DG)^!1EW0iDJ4Xf6Af*BG2> z*61-Zvf9@{3Zf5JK>Wxrg!nWPD8e08`#GTW9yNdh>guQxDO<-1S1mx2;z1C%2q0l4 zH=wdgk9y8E9_BOewp~z6Ms*&8bjN;KwOj!I23mCvSh|U$XE-|AH{|Aa`MHGwPo#nV z;vhUL-is`+p2}ZsIm}URg^H4N5UL;@1V_W8+6jF$uc|zqs#i_x%x7W?94Y7<73MA- zZucCI$)|k4zf0M3cMV$ZDr+uA%#kqU(gzvq4)YtpC=@$js%K7r`l&xKJk8z6z`p6# zP~!%q1Y#XVpG0K0W6h(DV+?S#2YT@a`#oi|qDK*L5rArfS%*5;sHH$vHwv)6k53Tc z>9-*I+^t-1^SM;d*7S0rp946!XZ|chgrHZgj)2?F&-sgvTA~@RJ*<$J+t_aZ%%8DZ6rRY@TEJh!!hhpSRO0!`IMfs$sxyO93SZu{9 zWDZ79?=aguJT+N_;OfDZy$?G0eb}}47Yz6w4_7EC4%LUx46!TC4lVb#TuHWWuLqp6 zpHBods$*!``~lde{7FP!v_D&X|m}8eM=Jt1-7LVIz=W-3F z(I$WOkMu0HRs(9(cu;isu~>IHdRLg^k9>N?$cKrSSbB26C0V!YPR1QDMm6;rG->o}bs7i6 z1Qj(xa8z5sUvbF`w&C?!QO)ECIC~YnRfO$~F+QSlR}V8P$-XyNcTRg8j;b*E4eR>6rj*;BEYq};WxMr;fK(fI1BxW2S3~|Ch z6?e4tTByC;24Z+0-<8w*#pMl*Xyef%PR;>Qss@b=%UlT1_ASZLOp-(`uPD_~(+j#3 zT|KhJ+DH{=FIXzg(5=cjnoetWI_&Ui_`}WczdNlU5Q+Tdq#4Xp=$>OfYt&v` zPkYL}?b+cppvv~;*Gk54^8p84KY%c)5(8$=wOfKe(sqUHv1<+_QmjT%!RB<0+F39E zqh-L3yfH<^L=J9W2zFxp%|<9d^TYx0?;I9!eCHPUM8c;}hC>%>Wg>$K6?8z5o@k#r z0aSA4yo-mZMr}AxQbG&f}gQdF- zyApNCoyk+ytoP*);D>rH`257K4d9yLpfgP%v+s|13!P(DA&$M{q^5*;T757zK%LaO zJwF21oo^9g&8w2unqG!?RSLB6oqY*r`1_3P9*>?Zb0&K3b(94jvwp52)Zr~QCN0k3 z7vEp%(#8qeXR&e0)HjPV@q51a^fP2C{ea^*>@zbFXa4zEg!+P){d!^FAbvK8-Tb-% z(hZB@BC?7g!I5t52<4=xnPrLd4YZpkOar%pUqW$kHN-U@c=Z=%fvn9}x@wg)mP7?h zVk&IsOou9lj6bGukxH={R6e$^3D#Zd6Wd{$)2%#zRkLZeG|ottw7p@#?185>9arPL zX#&4fnMuRR_)$?wzIi zvNjf#_T&|~aY{)o@q=dd$4%`px(G#P{oHKfIcE?7)pJ2VV#_=cSVObZG~L@F1Y5ZC zpm8QfhLK++bcFN2)`N8iq)B|bZG2u!nu8;jlvczqO$4Uca7(V|hOl(?}Y`i~9au6I*I0+{t* zp3W`$(%bT5N*;K#Vk&QsZc5cxdX!PYN^Up){fva7C}R5h=+j`Zrt2Rf_?ma+_C#!# z<`RWDH_uc-qB7k6#P8K6mcbmKjM0MfheK1K8Tn4Wg z2r$sMi7uDm+uc7gjQAlmFoKUb>^DP^t*>B818Di~C}W7Bp946!711mnH2DL3hPW1H zz~PRiS{{VkAH;(5;BA22Lp?bLNe~mS!We>kmSK8_ya*lS#@c<)pEJfIAlA|y#ru0n zn&l5NN;5$#TgN}B2Ee(a4JdKlhepE8B)td2(X86jySskJab|u)9|oc!tzo+Ol;jG; z5^JtCYRAjG-jzmLARPoMh&@@l@jQK&oOShrI9v+a*O+{+e(VtPQZIks(TC|(Vfgc0b>}3DG4UdF~(i4#UE)WW(7Lf+50ED#d5T@FSRWY{lb_XZ*0N5P5 zZ(1C<`w3_ScKBNXDAlQ{pM;r#L2a1lG@d~&SHQ|UpS8X6 zx|rKf&a|pyZAB`W+fhodObo>Az={|Rx--0b*`7fgSIQiOx zE+)DNTid~)UfI*Ib3WH_JZSeMzLdW@>qIR-hsml`Vy>wlh@9L(PMuj{8ufBT1h`Da zAf&qZspv7CRX$TL%a#T8jc-lNwwu+B?RviFLLcH9Ms};iOW+Fy%2nss&6V=`q}E}M zE_v#DL%cNwP_2t|>G{9La3AM(R(mdMshb9shQMy(8*dIeDtS;b0pCI(89M2<&9xM& zV@dr|)BcTtHY;LVfPzVW>k9h`sVNWpkx*i*wZNzY0sTpP_9QpQgkw{fH4_O|({cS$ zk3EUxD#5AB;2%NFI^j5W8y_!>#Mfk*>2Y^fMdF?`cT}FAnv*K+A?LFUX>1YAM=uFY z@a@T6@VW?95DtO(Mms2gZwjKIn*$WVjvmb?c+V)8B|RA@v-5$?J^yFXRtE$EcE2i( zIpp19+KN>%xi)}02vracf)z@k&_a9w0RGA5OEm&m*MiUGK{iZm%~#8b=B80>?_hc` z5>mZgr_KT09vic2n_i)vp+FC~UCk*E^PC-KdI<^OtP{PwtDZJvCveK%)v*gvW;?Q4 zSG7b%xf1f5oT(?KrX!{S?_NgZ-g2o|J&XrWxK<{d-pBS*JCC2!#k`hYPI;SD)4$C3 z@uAPqG0nf-0`Mxi?7k=o=G)zn6FZ>U4AowbEEt~NmVgQ-LJaC55Zlda1GhXjXe`0U z65knHE2B~T9JB-YrM1~6P8jEt`s>p=5qdjIIbW&ieBtX2=Nn0uy=1Q6GRBN>4+}wJ z(f~M2NzS|&cC8l7Wa+m`S+*HXaXt9rjbjV9GAyEb@Nsj*4egf+l%c$F{Onql&cwx6 zAV-q%Q%JuB+|Q~R<0HVF347<23&FXfJih5OCo-*&bn}|t!~Q*nkhO19Ckcb8D9V?e z6I^fA*ENcu7K`a2msa*8YUhEDJ12uR?pQmJ*}`7u@Sf{o;u;#O=NR5oRO!hA?!Re* zuNkZHJyoRwX56dMwFD2eb&;g&E*-lh)}-h?#WhrKSk~$4(44E=9Ch@|!!$O+$pdEj z$t-FuTfChB!z7sMkL_z-5L~pb9ad%_*I4~FY1!yJ9eN^vP zJ^u?Ls}__?#ihmXaTJs$P9;w7ZdV=*RHMUPgokBFK2|1s-|G{(Ao(}~(cyp%U5NY( zH=wXZE;biyS?;DO@~B6<&9-}B#B>$VM19AE3~-aFIH}bAv2-KF-9njxwtA2Z>JUHm zn^EE{L zpsd9};nr-g-o(N+gxZ=&41Cc(yrkOM&RcGDZ$OB$JKzKX8nGtN*o4i~`nt11cz+yV z86Ti0*x?N$KS_yDe=$6)c6%yka>G!4+4r0|_&RirnZaP<%9#oG#ty=8ARm`@a6vtt z9d%z6{X;daV9GOCPf&>8#F=O+Hf9FpzcCjw9t4;Oq1Rg+wI;htXMa+XHq7{JtiBeH zwy%8oBnX@o>8}NHN1i{B*FTNi0Be6 z@Zl5W4VeWK>0BgLm?MDyUi0pAh8x;~Yyu%L0gD9z%ECA4q(7iWSxkI5N#MmVyS!9!>YUosI6`0GFIXH$A+;SiWx8LrP3&oX^}b>hE{rJ30Zs8e?qjP zENV&!9Lj8=3ljC;~jEDBjwf6B8%^|$XE~@sAtd?g03K7pLp^jTT^Ai+|p3cQT{igWG6Pko61vr*llepO&@Y9aL&6iO}I~sq$Oq{R!-FKsOJa5 z(9s8_AEFv{9V(^M=;4k<4CfL}nZ@@H!4~6G5Nt!Xs}TZ@QPz1}F@P{qLT)ju+>3uu zYr)R%n>rWp+daVLuP!PGTBiH+1DSaw@|tu3;oLt% zn1lKvm$<6A`He&C!EuPh62GSRU#X4t2SGP~oXtE7w^5p;Hy~i-CK&+5s478xd}-SB zWJT{aAUb%rg0ZrMEgoMGrH-C4N5CBJffkX)U;dUt;-SkSx);NdSBh8M?MLk;&L=)6 z&&bgqMAld#o|W3j&;TH?J<&o^g!+lnY3+w))_WQYYu|ezVqOx1(W;fB!ffV=}l};jcNw+%Qx%Q z?-m!*=x-O~_}}`L-M8gL73Gr_;7Y&&Q5nh4D(!u%ea-T6^r9JWSGKbzaW0$9%T(HV zj$^LQkOD9SxdD31*gDTR1{8Sv;27snrpwEKrvDTtiE5I$F2*tdB&){X0^x4esA~?S z&fN8Npb*$p!{D$tg}Sn`E$m}a5+;xmWI)CUg}_W5o$5IrDFXIzBXgBkn<^8DD+ABx zkL3O!FzOAX+&tvDDCh_$)gH09{`W)^4`pj21!~Tz>Q)4;TD#m>m7BU-!#Jd`fae5t z0gY<&SAdRWEjZzLHmD{++VQWQ#L)*S6;bUM&bfWr_j8Q|e^he=G?KhgfJbEZ+idex zh%D&f^9;YqV%~f6W*iZ1bSxLXWHwsHW+wZH?vsA2*C_vd-+cMWCp+WJd25r(PfqW*Mi{Vnrh4R zMvrKOBePp`$u*;iNS3zN=ADfaRfggGr2=?u7WN`g-+GH&$j7{rNoy%2f5y!3;RV7) z%Qi@By^J4yB#_UtDeQrfDtdT(el7ZZk?50`(Sgzm!#vHau1Uathd?*rMDZTLq=sEIWsNd6_+|y9T2l$Hok9 zXc)a$3m2DbE8fSQ(RUkIiC0dkO_y`i0#@i2D(?3Cq8VmMu^uY-1jL_IRimKEp@6|UEs;!vg z=f7wR;=$3H7eX-Tc$C2Rr;7<=>?BSj=>W2TsC-(BP0pmCE*8Gf5%39 z(G3e4w|uU)wkF3B;nISQZt)u^m`-VeH0EJmw37UxhZR_=Lh{6<&Fc2xK}x_Y$k-hJ z#Si$d#-y(tdnu`g>>pGtlfID=_y?{?0&*__aBEqP7CC2*_B2b|rl)4|t4iWx70c&k zkgj0yTvySoC{{ra$IvvELz_v;iCHqn0G1?!$*2zjOkNXzR8WUWq|5Q2lVXO_K7ebo zFOI-Prq?=wS>9~{M#)!r`9xN!!Q$%8tQaZ$;9S z$sy{VdblKg2G`auHUuU*HyffafL;iiHl)`fr|N=LSz_}@BO<&2RA9%jU@u4K3}5}B zV&Pv8E^OTO2N_l}_kJq7=b3l_L&Ovi6d?$MHCfcnaa>LAyEah0rpMhi82TBE`}Pw0u8r&n~1q#Tv6qEu2Qe(15Y4 zyr;qyE`oSDBY$Z2uak%JkVe?8#v;TNO{@$#fVE{%T_ElcP=CKq?3xfgs;1rtu%lw2 za&*%jS+n2UWqga~|1a>6k$6vWL7jvR$ zXOQWH!w=Y#spEJ!>yEyhtn{Mg=VegV&d?+y&)>20Qzy^j2{w0`Q|K#y)fyj{S<}%% z4orgvF1}dyu>HH&O{bzj)Wjvd2zx%G8gW)3$yZ8?7<@}!5(JJ}R~iz(8*lht6|e`0 zZ&O&4@w@eaVOwyOFe>mqs=9)Z;PaA%Yu1`a%T);pZdL10^P}^R2$3xpMK_fSoo@tB zIhzrL>cTOdlwAa9QeAL2(U}s2$Ck~*p&glE>OOOX0RIMCO?pc*{wPaG+pH|<837Mw zxo)JIYGbR0#qb`FSc~NGZtc&O@0h|wYb4(g{SSIA8bb!yL6V72$B)5sCW@n_g(@jh ztu<0#)nu_|@@Nb6$&G0fliXR(V_Q|}agn>0`d5OgGX(qCE8(30p+s9!b=hqpsld$?vugca z<|>`cm5haKbOwD9MjS{!HkkxakMm^MX4V~4vxlwHfR-RpZ`W&b06hQOw;&AEL#RPG+F~@xSL8s@tO@Eb2WFC zIz+U@=y>r0g4Sui$yTX2>L=zmUX(#-ogkjmyamd&VtUEnjB(*{k~ra8F}dHG;df?w zg#I?*cJ*}0Ckx0WAmhuS`LB1-^=5tN#7b95=&Bf0YixX4!a7@W02CxzJwb(dC+S@H zwvf{Ayd_h@E#jRoPH;Ti?}&wUp+)umZa>1a{C<{&e0I`{@HC`I(Z@2Y;vE9-RW5cr|7*h{aqi;kO~#poOa{mwk3hMH4|Tkv{Du~*N~8EmOb z{PASVarAJ9LGf)C%cU=LW-BEt{;t}UNEd*@63B{x$c@%Xxz-II0Ba2EZ*dB37$_!H z9Q{4twX1PAbOk27ZIkZ5{4C9W?lc#LUjlwOP2b|Yr@2=D1IB|DFG`wBOX&r`uC(?x z<*NAU>>d5YQtDow4+o709lvn+!aDaKA+w&v+$UVcoG~x+=h3OZ2(6^B6A^DNW=X2xj1CK^Z@sxeQF|Jms}%tvQ8Bu>|z4VF3Lk zBP=YogUBlIY&>*EB2!|lGY1Sk&JXV4%RTE94EqeGN)?x8r#N=kuB6okF+Qo2 zcchh%ze1Dnb~z~|fvd#Hmoyuzi!_jWE5h`w?Yv^Ya4&hwZeYgP)Y68Y)%_)4ULPS! zfdZ`;R7r>X2w;B0zkE$k7@eF7e(Vw1cu-Sr7L{!o%rqnMm3*~idI0Dikk#xeWn03tb zJVPMYWgRJeSTg^{&r}cvw$CFHUg94MGsTxr9@z}v@w}^&WZR^l4E7gMqk(SN&ZZTZ))$19kLKMk}fX1sl z+0-vPn(5h6onXLqVBU@)707;>hWx{IOCnw|2YGKZQ6U_(qmW#@c1tUENhuv92WEf7 z@)gc{VT>DpGtBXUnh|fF){e*2%*+bQU~RuPjzHvHFspZmSIkQuR3W$n^qB)e#1=$i zt-FQ{UnCHhhLw_ODfpS19~ID!`n~94lXzEfSZD>CFt*8+&@Rtz+ouRfx#*!f+z$p1 zTB|`hjnQ-+@k5v3yv@Tdz|{5l4^DV@ch@m;-8$eW$p&u2Wzaa(5#I=1;~eMUmPPI_ z*hf+-it7_{;;jbuF^WLVfG;xM`ze1#n%$E0`=*zkfi^Yeuwac0>T%6;YMg@AvkHt3 z2-ZtIL%d6)`LNEwEwCKU(&yV0Tz_$Oi}&k;EJJKTk8uduZ&lo9@?g5!Np|<4@ZgO9 z#?=Dgi?M~cPJRKU{~#P3&<{@^a$P;HT^+qi*H<>{&g@19y0s|3mlN_$Hppoo9Wdl* zClxe{v0)Io^CtuHi4%eTK ze8dN;>j9F@#3p?%2lXM7({J;o%!3Cb9=IPP$@GV$f4f1WK{&bmM-jilggTy9%?!zo zBfL5PQNDF@=X2I~xrF>$_$6Wu^k2c!5L2e+@bn)rnAa;mWwjCLKb@?IrMrd=77z5Ndp*g0i)PNzOBvuUg5gG^zOdv+TqfTS@0}CT$NA^-vghbic{a!Kp^^A z_6YwFnAB1w5MC%1eNT8?1fwXRx-S}Mj+Vwx zU_vM$Sq+%B-9o!wMIh@UT$drgD(Wb@Vv$1&{;hl>Q=4 zh4!YxZdHym4X8%lqSAU7_3ZRRpt{Mfoy-{oWzH3R<+EP@f~m)wan>t|BDXmQ0I~V| zua%Kh>x>5%JGxrwSL(t7LZ#H{$*nf#v9VrN8F^c@dm@Qr^rttBS`w_>^fj3rDIt38 zu0V3&pSF7>q7x(nQ4%-+gHy?%nRo={K3bP8!A&}f_yf^j5A8n(vF+qNn1)8T7P<){ zc=MPrWB)TAkP=nMEc!a8;WcVug|y@wTroxi@3}YJ`h2TD(=A&hpe+!H;v#yhrW6H=_GeEFgpl?Zo*yuc=!eT8YPQstP-L}MW19p zRs1j!JFsy`G8st|T|cnqR9;`{5#+~r`eXc@ZmY6*KNwDVRY%WgjAB#yGzcI+M`wBd zM4@Fx?`s%(5f9|EWSw9Ymiutdy8v3GD<(;4Pp5V{AIQ`oQOS_T2n>_D+V$`@;D%NhIh~1Vl0NJuMrCJ&4T5!&Dnc0niFT3^+qMI~C?o$Qk*fL=y zmdAPO!2>jci(5S@OjfWxp~YX(%FT`vMwk}q6|m^kqc;s3tSeZ5;?lj<&zAjP15*A7 z+0k9JSO5xxq&yEp!`PuZDLDBxo@wGgI-kS!R0gY0L8)F6;=tYOHz|97CWp4oj$8@w z>H$liAC6n^6qJ>5G)N8(aKLv)CXw2ddT0H%m)}_g$fHMz06Pc$J1X-MvQ%@g;Y4$S z%|btH{QYj!&_6aZ^ArK~A3w}}X`z9COv%bea;`cFPhiOR^MFd!?g(hr@q@!;->+Of zNLr4uLg0drXbNpHkf5-->p#VM{ zi#)EN$|yD^upL+B>i$m(90U+ARroDaVQs!iI~k|64SrU9Lcwp(nQO~s^r^7I>>Mk7 zuubVG_eS7?%k6FhE2h0krbLMJjl?sL)qaVrRua?PP^I(ZmZ}zUHD#5#&?j)>$yXso z$gWJm_aWO#7P$Hc{YCG~WZ;5hO8GOzW-5`?^JUn44i*qj{era<>C*LK-^lK=Es?Nl zw(bQ$`2(=MCUJ*YW&gj*9fgJh0Rc}lQ>;$ol6q0yeTh)2bYfmsx*o)Nv@{A3Gg;AA z$y<_52A*yWgBIK&8P1`@>@fbQ+E7~y3^4XZI``B;^@>&VID2wA)E=)-Abh?AUL^fb z=NMjM{C3tF@96&vi4(PTT`z$)QQ!#ja8ejh1JD~aw;aT)u2_mck`NV2R|s1^tv~_u z82iAkiTf1PY5JWo+^7rbYeI&`PwB`KQCWa_A0{7pEGOx=Ebxn?@5}1kKJ!E2 zE+dfT2VuUxA069V{hin1b8%*428|GH76JU5V5Yg5;ZpFQ-9s-`ITc^|dFBna!`b_U zvG;QZalOKfLK>u4Jx{PIiqLI^L+=sR(y zDFx~aSR>$Y&JKy4c6!=S(cZVoSu0~bole9og^_``tZAx&VS$5g2vYJ)by>ITKJkI1 zD#O=UdxKfLf9o0glpmp7?2|Ly&Lf?oHMOR&6zaaPuF%dDt%?apD*Beta{Q0)(9lV+ z_i}F_>g3BTYgcGlobQ!ZUj{~*k#Kf+>IYJg`2Qwti7?5%xZE+YnxV?wgRx@U_$Ne< zjc~9~aixViCdlHc~s+#h|60jdf8UQj2&w*XnXAk(92-r99pJdTE_UaFLEXvj&IGQqw zwYF-aagGWj7g69&syJ%_`N9x&WgKOFc3M~o_}m=J{6y-DPZ{d%X=W(5s z+bqsFuC#PoOWh&_4FB?tlT0*b&t;h6a%G_7Pjox<2RJX;stbSt;v;|Hew$%Nc7j71 zb>=z~J!$Z%yG89I^;=KV_wZrXrHOyzoHL*Qs>^ofyhMIwijDka09(oug_otxBFL{4 zN_}p_Gk(iP)2)Q@Yi|;U6i;bA@{!Evq*k+lRk8RE^M%={d_Ty#1DUie4puE2v=yF` z+tj3Opa_xuh49ingu#=jj@Dds8UXcjlc}nq$mFID4xE7g(Yve{>$784m^}RM;SqK) z>g<96dT|HC?{& z6_*A&mdCbAWx|=`j1JZ%Pq5Qyh^^1SQfT^xatJy)5wcwZtJj8#Rc*|B9=$G(QnPP7k zum%i>e?>~CIk}gOw1xIoWtYh;208j`uGDYQlIhEYeh!91z^RFWPh~a{lu+?L8L=m0 z&@Vch7v9gjgMVn&LlX5is&$^41DvIWlr?_!^vu7H@SKCMGsH#tG`JnA10 zbLfny0S1}n_snTeost?PzLLiFESK$R$JN8DAAaNKlhQQyt~M7K!RES7I9@{(@enFZ zfR{8stC` zq0gNllx56d7V)-@+KIt)qI9}(2MpT(%-Br?DwN?5HYdzGvaeSIk`lZ0734|g*tTd* zO~lSOYBL%2$ktq%X+KedOa!`Q9&+wM0L+(9)XL@aVsN|wlj6aA|78T9JspP*?y%+W zUg=P z(DLJTqv&f{FT|KysT>RS6vTUs|C(;RTD}+Wqrv%AKrT3yuM{wdRWnAOA%~ZMYP<1*f(^^)ye#? z&H8DlZ{H$fRIc4SBN2tCfk_@zdU-#!V5M&FF8B`%kV%|vgDgOiD40L)e)>s@V(uW} z&I%DpFhbc5Wjd=iF!5Ua827pnc4l3P6vNPu_bJsyoNpT_Zy|nh7q!X58V4+6bzqwQ zl1NEGf243obD|!iLdNXge&arVLbqb0ncE0m5ox9`AQGB)o_6p7tjkn#9R3b2*4Hg? zQ6VK8J4%6^CPp$Pe;F3Uw%Im|gw!`dsrZUiXve1O{zs@x|MRRLxN}hQid$~~Wl#eG zF+Ch-=;As$(3$X*7fPUz2-zZ6UlP8|gKJBtj#>hYSiH?ZEme3+J9NyX8L!YQR>Qdr zP}tg14$@Vo&pr&IU!6?5yG%?1Rx9nUfsek#2mUwSu8i0AYri*Gi>*lkv-c6$SaW$? zaPggdZteQFTcFpwC`k1AfgBJ3W)MFE+aKghUF!7$&vTtj*=sP;T=JRv02Wk-CC50< zfe#fVsdx*S3}hfLhFO>nlUn3Yg1=2p%n};=AXw@xPLPp2v9p;T{k!uQf-ZHc?s2d3 zTfP(`F!jK1T$Ua=G)7kT8DKhxXHti~%Y{?h6DeDlkc^gN*}M$M@L?D;g#C~ZqT5`q zfy8*=Q!gbSOzaJrqTA%Vq&g^a^1Cg?^)K3wN<*z)Uh3`|xl2RRxt4@@EcI7RX*cT{ z*FwVb_cTIbM62%Z{aByHad>8NU=*!pa)0q#*Wahcf>KE^e|7e``6tJJ|BGQhVa%pb zJ25roOK667fjZ?a`hQ5!V`vrSUD4;tNQu2su-A21)S|X5atI_Px)bF8nMnt8hT)xN zdy4Dc>b$k!K>m2p1|=h}GdIq;;)k&brC>_WqA%e~rXaFPe?9U9BU&MWfW4Nm(>fA( z$pEcR)|D8ftA9~ z#dQkvv{5I;i4=yib7;3%N8yJ#~b~`C*s3K0BZeYONmsiC{6f_ zkpT~(ewTb4b3#lW)FXs{5SVN79-_4#i#8D>dm*~h5dT5LJ9xj2${Ti1XWw@R5GX%; z%a2C`*UQzd@b3Y7ZbzP{!ff9`0rh%8W1Uf)jYzz4p8uDrO*#fX?=&1xcFgSzb0(*3 zFSNX;KulVuYDCgi7zQ^aWe-v&lBmB{^YoDWW}Fj>Mm6z1(Qi*#rfz7(u^UFH50JRv zC8FSg-MAXosMYv3th>^)F?O-go0lIeMYHUuUdHgEp$A#{&R_%c;* zatudca58kYj}XreC9-#iK2df>RTCl+F$+&TX!2`qDQaRN;V8t{nACU~k+k5~dk)nv{N-T+DAQAPxiW}i0x-@i}KO|gr zH!8?ZU^`EdVvQ($tdWHu)I+mUTRfan%|L#DZ{Bc|C>Z6qX_LgSpM~v-LwwXYzg3rL zqlwtK#oip|JDtB?@3sU33D^uzuF;e@k?Jr2&RC58dGlG>(UVl0JwM241R!wAO9fu!(5 zfk)o#K9ZT?BZe3baRaqu?>bM_zQg>4KP(A#l`_qubmCpMo0Ukk^$%v5`|;{{|WJ7Kj9g1^jgTWMs#{Lp^$FEVE%2 zvra6WL?46|6=E_7g}H`CXz=ZWpDnHO5^-0(DGFVYXS26L5`oFL4{B>f{Z}Uk!Y&AifL+$tO zs{dE9=azN^BCf?A>g8&FSJtQFfQ}C8Idl(~XW6`R!YIp_WcAN~Q-NXoMzkt@a<5g^ z5n2#zuJJ+zKNCs|r4c=n6METd(}yXG`FcY1|ENuCWUndf@eD7d(ea6t^N-j;$jT1- zF@@$RDioOS+8^9ez;rv58O=qqS*bBTEOn%#s^cbeR z#RDgTD=G9vw})F`wub~coK|O!oi}{TF?onj@jV|6tL+&ZUR~SdC#Wjr)Or`hAL&O# zYI|#VcFk1g8IZW9BKt?p9a)Yc+%^BiF*)%-Rh-bSB$`TT2muq$_QzUQSO3hCzOEr1 zR|m(j?`HbA%RVbU8)8ZsSPG0netv0{p8ti0uk$8qS##-ug~a>YYFo_p!L5{~8|6|~ zX-w4{LP#oSIsX#5Xm#X0KUwGUAA2^48hhvPT0_LcbKa!3%aG%rmW>m?SWZhaQ2*zW z#l4v`EadYq9X=m$epJ6%p2>lgmuP~mqc2YXg`kNXhR>@5OmF)cq9feC{-DK}l!$d+ z6JOn~{WvZo!t2j!H>P-T!UGI~%&BygB9rclQQ*opJHH1k6=&-ok9P4@-1Ct?1XGS^ zlUFe2-C9wMzhBZKy|0abb@mT=lBD2CJXI#i{^=&~K$1g9F)}&g>a-^bb2$_>cLHnP z90zkO-!Yx%7$!hOcg?ndEH|AU_pN-?z{=5>JR#V?rQwH)m+~dbVLMp4Fd3J>)sqr2 zH-!rZr%wp&H+)k1pj}rf(7}O=vZ%Z@^9U&ABYq_bwJ7^In(xcpA#nYebCaS|H{a%_ zf_#Tnk z6hdw0DfNv#1(wYVFU$jzwG8Dzz1XM9YEqF-Bi4%l$;t-{e_o7H-oN4Q4XKP-YjyP< ziN(mp_gzmYU%&z7$4b5+vr-SkVDZWaMrVpWJUsL#jS>)zvLT)uHKZe|-4i-e(bXIA zZ=2v@Aq!BSNGAds$elR&HrL+XmKq#0>w{}NWjDA?^77=_loY{m)o9x=8NXs{5Pt}7 z>X@vt%N3a6?Xw}2!Ii?HH6-`0zqAsCF@<$IOM5J;B)Cd5{+)S!NqIAd?x4X-g2{e8QTOuSVy%oPEHgX%`0(3~`2-&#eE+quA z1*Ogx4!AM@#j5`m3nGnQ;Wj(k$rJAQO1YPUDYzihShgdG(i<(N%afccRD>et4t0hj~mG6evXZi}(V$wEr{i9JfgFN}E8M`#&3PfAB zP5l1f`VAVqQMpD8g9ibm=KJlhFJIi@yMrcM$(^CEq5i=+3Via@K%_AIW8SY!jm<1c4m4gfOy2}u1}GoneD?$>1{p2rShW(Izf)ZFI!+$I?-UZbIg|jidp(MotCI!Y-b7+hIS$e0)(ezl< zZW7*Hsj>+7onOy?T4kc1SO`JqVXbSR*OmTDBfEpNh~M;t-3mBy0dAzDmQg@+@C}sR zc`n*lumAjfyOxcLo>L>Vk{Gd6rivZ6vI5mTnc|BhYgZgF)^Mk+K56)^7Q9$-9A^EL zN;B|)jsDG%6kiai2?G>om9Z24;EA{TRN-C1eqe~d3lmfN?mNY(+wsoME_G4>X^%h; zrbl9ishwS^wOAC69eZ5#y#i9fbDVKnmADS6`j5U{KN9{WThpAytS+O=KlDqdLJeFu zdBIn!X^9~srUwOEgtPv~mC4BPAy}>yhtF)164x@+FX%)B)f3JEL`TxTD-JW*6!MrL ztiWL~E-ezj6k~@mwp6(6qmDmu5=u10_-g_lyR~JTV3<>4datQ^8uD`at zf5kHDxknh(8G6uCNU9=I#^wt8X6Ci1#c!{YOTHG<`aW3i0mUpj(>YAHgmg;TfD#%x zZY3%L`)DQWWj|IsT7;OJ3w~O^635MlVVJ|G5mNqzk{ub z!{{FMfai5yI}DD?0l@{k3Jr3&;?z(xyensVORRbT))ljNGR|!|6j-5F zrv*%ZtavhskgA+oho?kO3woE-v|^?$;dp8>P5O{xLWlB*dip;?r=!7ib$sc1&sZ=t z5@if)w4Cofbhl{tn9+gk*sB`0%34My!P^_jnK;dcq<(gL&F2VBiKK&DJ(e#2LdC&y z@e;24Di>z--`O7RnDQ4%93w3_B0R;=z$*6{X&{H}lwIudhd%UbaBG3(F<@Q8{9 z(*tzb(rT^r^`Ftc^x4w?D(rH{MtFgyq*ZNG_KlTM47<|e{T>%@8gg4WaAZRc%^5ow zQm7?&BWQ$O-D+OjJLUhlV$HQ7Hz#kti_O0$;JjXUG&`u#88|{VUH$>jaWSYt;GG{k zozZfiAj3hn%{V1RkYy>7i`2RB`{ZhY(dN|_hI@!plE?6-<3?!lZi%caN&tyd|Xs z+w)Q9n^Lw3hh1ChF(scZ8N|Nq_e+p)W6 zD|FohIH3FI=*K|2wPO<|0{^^V!W9!s!7z-oI%^7*b_5?cmGEJuv=6Nt{-~p&(CoGp zr9bL>7||<3-h$Zzw7B7!I;I#B;M~6whMO>X$8DHAWr)QigC=5e1XwlO%mXxy?c&s! zdgDDlCJpqP=Td>t(J6uCsC0pEUV|Qz_paxsFqseT+ADnD>UQ1h6V_I%RVqV1(7BFZ zeSv;#j`ni>@1bbiv&cf4)xcID!Qh9OOQzR6D8_9?N<}&@BaQ_Ub zxILJG-(pxBLy+F$plwjCT>3*{R6+A=G9c1uI^+V16jQ__2SlQ6LByZe0{5s|k{`EtMWZ%2l}Z9MkrXM-!r-upb$Xs*;+ zIEcoB%P&a;g9oZUOWLEfllGT5bCI@CdaYJnFjlKxv3x+w& z){0s+NYJPW33@#abSF-W{op67XIoI(Xw!K&`}I#7+f}WUa(B=%yNd!f8Src?W@Y{_hvz08^L>32@iip15Q8ai1HxZ_A zr&iJHc`0coUD5{KX95W(=>v~uUJISGx)Wv!JJw~%W*3vKaR6YS)BQy)0Y{Y$S{Rl^ zMw>InmDk{;#f@oqUz9l|8bSAt66@sc*t_>sJzGh#=s5_CsVTMafzVx?n#qF9x(72i z4Q1$7Eh3T#0F2X+mv7V_LVr_8G}Q<#^+*saGs8hy5CzhrD^3cq-tXks)XotoC_Eym znrnxTPKu+Dw${W|g;!f0YaR4v@+mAfvMV4f7|<6Tb=m$Ww~4p5fVvjmrh_CrCnLkt z$(-?U*dZyO*xOnE0P5t!PY3ERKW#y(!3D>ha?(#K6I-3HM_Wz+GXYNUOlx{F$QJ+fGJByju2BU^G9 zO>zq&nx!$|Q(GPK5L_SjJU#b#3I8Lwxq-KSK2GSTAKduZC$4NP2?t#@W8YI;@v^vz z|C>CcINH5dhG9gHGJUbcU*+Qoh!#=3nlNILixdKYb;2u=1e^gsJ3cpCJ+oVb%%t>C z>|&G9esFumY_go}lQ#r)Y{9Bx^d&GRhh_I$f|i%7w~IURhlDwstj2|_d-&9i0a&o! zY6Qm=1LmmhHcTNHRpGX+Z2;1XT!I!+@E`@WvHcI$We7>TUzdPVMiC)-LjAG4h7-{x`KERB;7I&z^c`;fW8lsTaC5&t!WWwgN56&2FNog}s44L_*Jmd26t+Dtg}TIEI+zf}FLze@Q7M-k*(7%dkAj0#S@ za8~cfvO(d=!dP2_pMiKvy*pkq{Gm3LT0h5*BG-%Qjdm|;xY$2Y-trDbgyxYP&}v%^05wjVQ`HL=YjZ zdU3}gZiTQJy*F^fX6sI9nr}D2rp`6NKryOF(&o{gcNxspLy!d(N^$zO=*#*=fD8%W z(gN6zabR5Az9%M#96Cg)TSo^b9=hL>Ve0wXO4c;$o9Rj&~wWYiGfk52S* zY?t+n<|SWZzrN>5q}gNYw%JXvwhCK})EasWsCQwb@$z-(S{bbDW+lZ2%!v`MxE~7m z(batrJaWuq+=C9mdu-=EA==4C)4I{I(+2gt{(GY`_t70Zx)m(Qn(58&N2Ql6ppn7H zQf4NOG!Y*c9W~Nw$sWjmJ?F}Un4*KL*CPdp%@cFmQnw^LJz_OkHt8AFBA<-bV>J9n zOz(u;wAa2__RqQ@k52EH3QVlCfOdRJ^+(=+0Ko<(%OOvg0PyQeK;@oQPMZ(O9j`gN zkOG*bE!b7f|1*sE_*N+i|5IE47UMEY2Djar5q9;1Wi-{r13gAPPMeT8Po#70HX%YW zLdIekuOuvJylBLCKU@}3MOOleULEIeW{GkC8-r1`Md!jFgs8zs6J-V)rVKkR=izkj z(TAqW%(B!?TrD9~{~Kd1DJbnN zNWKlCYiNFP12oqk5d66@S$kH z5Q6^-**Pk${ky@5O1XMtbCq6ctiQ zyzg+q0k%3KCJuvzP9Q2MpKH~jcB&xswCX{kNEl^p>5e2~tho{H96r=x7GzmZelc6~ zF>Q)AIcPsOQbLssmbMxYM3~%z)*dd0&YUpBLRIvpC)k;%#OL>gqYT1*FyvV?PaV5!Ty_Lw@-39!eASm!_NIlJ{YENdOF_8J| z8vx2Ek#zd_Glzxe0*1MXk1ThyHZ7sc8YQP_;HF#+ix3$pn=MJ;8X@p<$pV%q>il%g zF3?NRY)VOZtnFX+j$7rJ1B1d`O$qP=nd!zTWDi68DK_h~6d>_{sOwI;s3<(wnyc;c z7?(kjv2~BqLJH1;a_b%bAj&NMgeL7lbo!(URpLvdZ%X|Ietbv%K1f2z8x!<2FUP6; zk9{PfOLeBH>8jE+{1X*~92OR)yB$B1hPS{F15 z|F6s!RepJ02!`HkQmXsl2Qsrs&fs_QYl-=8B_fq0qW1hy6CVpEnOu_k7oXvTV-@_S zQo;;&e9}xYpWnY`yN5BXn{ed4PpY}xU6 z`B|R9Q+}#;?>xtVB6h;ysxYnGuabVWRM*~~36<_F_N8#XXIZ$A>|`lk8!A}kU!JmH zQt3nC@!7YV&HZ$)kC*WwT|Zew6%n9H{R-yxyIj32+JCKhA-6Gvl8gwaRm+l=h@*#i zk{F8QSA;tr&K~TL%t}Cl5qQxG``TzsiEs zUwk?RAER~N!(wcSZwW9B@iV_rTmy>UDhkxeGz0QwJw**0JGY#Oh@OP+bW-tmw6;H* zC671~VD|cw;M1RJkmF^PQ2qDIoaK`lvdj;iE8tz_l*sn~-Ry7J7A6-laOOQ-Xxi+H z(ooP*oswKHq{<&zNDw`RzU^HAZ1G_1o38y~ZJ5~rsA$NOnvSwS%kuxpkfh#A!vn%<63x-60;l|egFimyBN#Yh5>h<{x~qqZ8+|dzvv0XS;w4aPBGFV ze6V2=U&$-({PTl4@|cFIZ89JPohzP6RnK2_?>XiPAihcY)VDM@WiWhcVkY=7{M@ZfS^YbEZWf4}3euN7+L|h|crl z;JeTJ;B#bN_uaRq&W*GtmRKwR6YZ5WWSyhsFZr$ujfQluIPrP~F$OzovC#oRfDxio zX@Wj1S#E?>2A<2ST501jFh~i$e9Pi{ zUmXK!10xS5c|KhZO0~GNE!rxP6wHAlIe^``%fc0H+c@-FrNLyZZ!Bt=Y|2GiO2iu3 zJX%;1qExC1;PdW^WdSB?DxnF@EE=su%syBctpdOrwAKC8fhIz@B0T%U?Bl@NtdfUp zsnQWUzkPtx;vHB>6UorNHvwMwCT8Nqa>Tx~MkT!O7#bq~D9l(`)r%LRc1BAY#*Aol z&!CEi_SmqR?w?@_1ujsvpuViidZ_^w3np=yFg+p~W3LFmz@tudgYuW=3_&2yCx~MH zkt=3sNmY22&tmjga%BSZ6!iLG&*~)tfY@}3L0<#iLB$OjY<3c>uH7bhoR#0PNX!o6 zU_B|t>p4-_Hwv3X({FJLCv=@W=T`nW;(xGnm3S?3JW{=xMF5il)(Tuk0il}$N;$uU zVZe$WGiTjLKVZO`qWo_Yl`!QhLi52(z>p*+#+5A=_eNl^aIsTF5c%K-AWsf>4*a9? zNAY5Y2w}TonkEqhchcw$$NrQd?kvlK@cE?~e|V*rz=gz>SWXdF7?>B+EBJRng4YsJ zmMq-mWFS?|kRfANGJ)vNOOP_w?*X!42A7(XIGxW0@5ibsQ%m(o>aLp$ez#&)Es}|; ziRc{3JPESZEJ2)XoED5w{=J}ZfV+D%GV2FwTfOVjhK#1EJs9-Xy|^q-8^|+zr-L_G zt?&C{!Jw~O2XYbWiMUqEo9wr_dpc~2)r##yvCKljblcazV-8Jdpr{P1vtx5pW{2&X zvmyID;uHlk$=+yZ{@@ZhJ)2mfgQzA%lX{pxiGsSu>OWxS!?t%f1cu&HPU6@}1WfJ!*r)AMU4xa5k4(KA3bI(Fg*nkwfCM|2&o!_{QRqZ@I z@0<8QV;ao}32oTyLGZxW`2^vjxRwJgErgr;D^6z&mYi?^VGU5@B{U*SIV$FpM~;gX z@Sf1NWrrL&<~gwpK=OCg2wn6_FybKAW9}UBC(AYd92kt1eDDv8XN6>fIUKHMj%p)Tp9>hMKCkD5Yhjm2Z)ri z?_5ohH74x%{IEMEv#`&U+IzZ!&{ywBGIC z`;;n|s>;3p&UjUCZN1orZiiYu$d3W5CNw3{cdQJUsZ<@m))`p=9C6yD;`FN;rIiDu zd(6MN*1Fwxjnou?wwGazcnTW5!w0jg?Y$;Y*Ckoe6FpdvtMS8@IZ@bI>6ZNhia)4? z$XFL<5VgiJKS0(~>Id+dOUa;8)4lD)#;GKBVkF$@G%9R{3}A{#2J4B9Pzvc4*Ru!#Yze{3O-2lte^}&H3aJ}pP&&1IU7m93(GW?Rhvia0v&|5Ea0VuIW zgW6KVGOtY{FqQn^J|0L}i8#(|T>MV%tenRGU&5`=4GJ_>99+m5$VB0YTEv{=g%hd5 z%tkJl86S245qnk0khs@7sylLl5*U8x4$w?HwdEZX;C%2$iCx0GgqwYqFbc{h6pNzn zl-&i`1+=>xVAuIh1HUnygk$qN4n>>xjm5uzEqA5%G0+0}{gvdx3Ow&ez@be#t zMr>Qsz654e*bO`VXB=YA*IX_d21UPqd06@?GM*=Cj&S_`v$v#6O-sx9v8g(@gH(hhCk6nesh{H{eGF zbYJ!Gq4L9_m<8kxUB@%`NCr;C9|btD_u>#)Ui~D!9U@MxdQG0wejb<(!j}~bd)n}! zmTZbX%l~;vD~JmUx7&EcE|NvQWHFIhAKKPV{qNyV$Y=e4r%;;iwZX5)rVSUOd+$`2 zr&@AEP7Nnu+V>Pe%a|oK3Ei^A_xAGKmK49R1fthcsWbJw<(hi$Hrm?W!ss5or^@+w z4I41>(^EK=H0zlHCKet|ix!lS*6)jJZ9jR7OOcjFq(c1P=94{FoX^v*;%G<_w$&)g2DY^#!3D!#H@#K`)QZ_0Uok3O4-y^xutIcT>I z9bY?f$MRiFA7V%h?xHwJfzt)4ns|3gp`2N=itkJKU1SjQ9G=*;?Tv)||R7 z!gAlO>l-{qkWvikOTTo&!dUyrzhom5ul&?It|07P3jKFt52aisyce~1)jATAM;2 zJIeEcn7i!L|3)LpC?5@(zOC&@sWHVD4O1}xG~Trn9=z(Tn4eR=#$5c%eA+#kwpg<|2 zL(qY|aqIBiO{n62+E(Q#w#R{7{{9fFY8+xl z>%}1Z)-;2#*=L5Ki|}o=Dg*mF@TygDw011NhNq@elBnT zXN!;U@?f47*aj-GG8tF3eC27r#Oa(K=YG|=j@fe}K+^l`(|bW_+vlk;5v9CN6UkV* zZBUBkk!S)JsNCka=ex<)q5i%ScZYkZyR^S`T__StC7PH(?iJXZ+;89zZY6>df~RCb zLJ=$O{gO`YQ!{WMgb5EGWTNU-qA%Q3*$8BmY>=w>@hA3hQwLz;V$Ni(!VZ$B2%cIQ zO1dCFy>ep+gh~fOH36x5*pn0ycx-@9fOmDWsTeLT`xCLcD9USUtIimCD;O~SNhoVSxVkB~ZLUN|bd)W1; z@+TPgX*T z*VI962o#SAuvg88!%X;lR?9NAvz5k*Iqn{}8YOwRjMfDBhOr4br_6ht&(*@1G~KF1 zQbro5YHv?2%bQ-V@Ok*5C$*;}Ju0w*#Y#Ewd3#i`hr2j{K3p>dotd;*d6}A#@B<5i z-1i!Y#AdJqi?1u=yHag}jw(~$4>$guV{PToPOpXL2T7XDGfvJYxJi82dkKCe7!@Hd;sc4T7?orm)WV_b0-fhBA2m)u!ck61$XE!gf1N| znMM=c7)d0q%?YuUM%TFl(hWb4kG1^yqUcoWXJ&i!^<#bZy1{SrHupGz?!QLnqL6T) zJ``8Ir^XUqbYDp1SBi~n67Z8CKMfaryNNobX8wTskilP9Anr`*O-G zV32sl`8TzC9j4j?VxCybOYiDWTe_MN;)|B4)`FSI6Me7xI{z=ie{`^b(O>4`ECD zfJM=fzrZdJk(QhbG4YDN2U zc(#2Sn;DOy03@}r9a%bT#r;57xWa0O;52zM7v)f5c+Xz7QX2nYYO%loobjOs;MUkUtL)Lc*d>X~c#2HJ&%w+>h+9 zgYpDxx*i@0%d9ZVd`%R;>ak_bsyEa8TKFC@-pckWor>Os=fCyaz{FrW}JXKk4CRN|I^1RLSL+RuqQXfa13QN0qU`d((-hnycIF=PD(aSg?|^SxB_P28 z`=((;dp3Ih3==RKpTNx1%~+N0?C*)$I{*`nD`Y;e{E;v$1d-DdL%#=Hz{6=NT+YjU zk$$QJDxaxl$PVEf?^$i*p;*>B$T2`D^p?02VLuWYd;=V;SX1!G?+D6d=1<+xL;pH% zXH(!%arHrHz3m4G1?i40q0$Iv4F<)WO&8r10t*>+gekA?!35&{m1>8SG5Xkoq z!z`v-uiTVS1M1l}p{q?W)F>hb1G1G4Pl0DAkc2mnyy{o9kKl`FSu4j%n=#AtgJ_H5 z?JnK&itXljT910=og$N-*8Q6=SNPZJEhp)-mD5RVVRGHyP+s|)lwbT{Lc=-uGLtsn ztY+DXn2tI%F5Wz?r#nN#YAjmuCFbTX-2_(e@>Rl2lVT*9jXI!zHhemwa)TY~mK*JJ zG`5!HtSuk7%1I&09J>6NhW;ehG1qz}%V2;Fx1@<8sa&mxmr^5FH7CjCMvBYf8QTd3 ze=7WOQDg@+kK*B26MNJiC-@W)G zb?w&t>7?rGI4QtRm^99&P}Bjb#wk&&p7E9}dN*xZHprbZ4_8Yjn4Kq-xC83>4i6qf z6w#$|{`AxUXFZO?{R%9x*IvvKaYJ|>^VW%&tg=rscl4@L7rDByiFOwCX7rpFva?Im z+}PI68hn)ep8iye-1r-2hWEY9q0*Et+mmGtx?v>aSBwkhbeToxq3_`h=E`xu1HMNR zN!JNDWh);gxZ>G7n~4B)GsMD&5!-RefMfN0E7#{ip2zpbA30z;F_Jbh9?t7?e^p0F z&@*Td8joyj-SS6aKg2ucl76Z%)(cxsN$)?%pX-&r;4lLX z@aX}W=25YQ>vQ@Py`A<;b)sH;3u6n=GsefCHL8b=2aN}f2WM^T)Ps5h z@qr!^W%5VDc!1jvViZ@VzCkYI>VgWSh-~a#shY{jwq?IKoBs+#j N475ow11_jQ008$s089V? literal 0 HcmV?d00001 diff --git a/docs/screenshots/launcher-login.webp b/docs/screenshots/launcher-login.webp new file mode 100644 index 0000000000000000000000000000000000000000..11eddbe48452491c40c6311d00674051c3358e82 GIT binary patch literal 11136 zcmV-`D}U5dNk&F^D*ymjMM6+kP&goLD*ylxP63?(DqsY>0zQ#Qo=l~rBO;(uD5$U! z32AQX7uo__SFb((#9*wEfcv6`zoh6-l->kDj|n{yp~F^55M&>;F68ufz}TeL%k_{y+Yo`)7o& za;Dkl1?(Tu|LOhG`X~QM{TtNJv!1{o%D=Avvi0Zv4}zbne!YAFe=+{!|9AW+y3h3g z`@hn8>-_iq5B|^fe*r(wzqxh9{nGZK1=1wSV+H7&;1-glm@{q!LV8PcdMv`z5OAX1 z5%sQ#18BDnntceL)!RFWN7lL{>szKo$cbO`;0YDhi6K}QQQU*n=FLgm;x3Az zHhM#V^V0@J>C!P{d=NFfbto|+GooXM^>)tU5%sQ#CS$@qNvtSYpm3-OHtsN4t#ctWbego=7-RZi*HHq(SkB0a3&HyNK&u5%x<36}G0- zFcS(rk$~Yvx+Cjd5%sVyoNX6ieQXaVzSATeDFuQ&I@4LAP4_c?Q!d%V?R z2Edh`gM}9Y`KQgt5!SjR>s=A`v|ui&1c3klUD$xMzxc;`9HTFXJyx4R%8A^do2xHe zFWWeLkZ_{i5%sQ#O$O<%opxK%j1pqR<+P;kB)I-6+cXobpeWT})!av1A`TQ=qA#7( zPmxY;iGpZvb=8*ABfVy0uBdX2p4KAyfm9X@kA2fmlH8m=NIo$6AKeukL;_W}2{F-0 z@q>UQ)TZZH{on3%bqqeedga+Rp%?0`d7it)Kpf-Jip3D6fRlQwIJp)vi)lX+VS8If zuhu;!MyzyU@$*UOKMUtUha0BtmB_U9s4Q z^>)pzfPy6zw$a*zh7Yb02MR6GA5BMvT)7bG@FvT4-+izemv$%i-;#RH0C-?k8Zc2M zHIFps&J^uvXMd6o6kD12sNwxxvxmzfQ7sJPa#JSw_(=e8CV^^@9ROgA${o|_5hwv4 zMr0=siXgMzBE7Hy9yT*2hMwL)vLB*Czk~`9nu5jc$9pD_npOdVAmK&`gMGVRwb371 z>|B9_ivGrE>dt+vCPH(Z*A!nFV}%jWG~z$b&%7AGCm()j0CW%|T7k{BFMbA#n8plE z{INhTa%Q+G_rz<66tZp)!gvT}^vE2~ zNxl7XnK!L{*aV=a$L}xOzTZ%u?Z9x}7=QsHF*e>}8K_$JQt#YHTIi4j5*YtSns}1O zd3Q-c35gvVk3dsofM6Y55NQsI9zI@fb91D*`+vWK^anZO>Af?`W7i8c zSK_b1Mz^Sd!FDBo)VLE*k`5GHNduyzpK;w`T}cqKTjK|-%odOKA!#n`L3n5OmpOM^ z0Dlz1jvtEk7U++ybVt)8pan`;uB9+q<~V|QF3G3KEkx}*@!{a=Nlq5}zwUjGZ@CI) zr11UdOV0Jf;p^{AeKqc+(@GNy(C7AjNeYV#r}(JDNB2g{Z2)+)fMwj%bx<)ZRDYXU`o6}zh;?0b!Jt&?(QE|ownHPin43S)--!iz= zEQil>JyDcevBzv6g}S}+4{$ofah*TlaT|6QklArOjI9k9Kkq-HT^!7uybrkuX&zjP z!Ic04VN}6)Z0d$dH-nrv7M3^_#a4ld>OCwajh?hBX;qc!svtZP7XKz;1zy<2=VV6h z1_^667RZQ=G!{_YLPKlyWNly*%Y${H*VR`(5b+Hm2~o;}1eyiT&CyYSq^FK8Ea%(U zoN&rR6!$i0A&aWtH?rN;no<;pXqS}c{=0VEy!alW!$CSNHgPZ{i$gCp2Lrm3%;)y@ znQO7XB^!Zt#^Sphu+(iPJND>0ZevZ%o<1W$!?JHx&?Z;py*WJzG9!Tolo`hZ8Au#D z_;D68`^D(ix!5h1{%n>7Am=c$$s)?gx}LBkR=?es{rFHMpb?Ua&O;X=&*>RANOlgm zIbRS3$V+H}ZWXLcyT>eXoUySO@-)+gB033l)R1T9?{Y*NsFp#<8AP}d+{@gs#zWus zb{B(UZZdk5psWx<27zn)K_S~G8CO6cz&Sbm<#w$JW*Hkq<`F_1O#a(PGh8V8*0Y`i z^T`M4V2BiMf;WA}6|`#nx*g~|ksF)&-kzSGpqho1y!xKnbj(LYUovLnkHJ4{5sU1;nt-84z(xvb*Va`|GNv<<#hs%AJ0@}+ajEV z;pBEzVDqWE^@T6WgTHUhhsgaU?kUEfQNSnisNh8}9cDza$G!u>@^n>6C~*F+*|emy zd__<#<(E-0Xk1cmf?fr_LpXX4zAe?5n+$JbS@>{#jq2?KxDhoO_b%71bW071EdxyR z_zAh6j0#KX>S@B}lh`#hx)|Zsm;Vm6C*5Zbw7##Fp0-bO3~=jGeS73Ri^&2jofb8r ze5%@wYnZc8YK>)Yv1i#WaBEE|kMO!26Gjp)rCQ{Q1#Ck@*TzU!)E68JCwy*qSAQg-?3tsJIxWCut~-#wIf_@DpeG zji_*HJUX?jx;vZrlX=Bh|>X|B8s=A`u88{AMgF4Qg|{(wu+vBE-4XS+A@u@2(KSlB!QY4S_gkLvCtt#d+R zuk~C6-4XS!i3vuZBtE!&+-%|ULBfl4w{<|q53JkL4ir}^*imkX`qp-qmqzVHqN9@| zbVt^@BkNrhPU8yNHGZ=E=y6d@*nw_{`qqJ?SH}=77b+M&wb36;jx}o`(d2`KZ;PYr zT@m%Ji2Bz=edXZRf!=gT8yz(HAnI$>Ul*WpNI-U^DGV38SU$K!94NsWo7LMme2{UU ztF~~M0RGo2a4CDxG^9rn&6a*SGv-ZQTQw8v!mMEbQ@2RJVBE;E7uD&K6;hm()TX zH;C$yj-t4=6FBr6`6qH6krq<(HOpOCY&>OsVRqh=GfZ_%aD^)^lu8f>&xkkEgwT$~ zW9YbN$qg^Sc6*R^tWBjk6K4+GIyZz0h0%vn+DA2Zx+!6}@bQD)T$;WQbrRnF(%yDR zLG4l@23pEMaD38#BX`OZ8(#%rxYSLoMMk6Pyb@@9dkKXi}hyF@1*FYA8cY7!5;%4;ytpCQQo+a%w93KulML4=AqopXd;Z2MY z@kCyg5Z(l#AvZ^6I3r8f2Da*^?RonlK4u6{qO<#OZ*G#Kt&MO|D2yRB1+#xC{-tWa z|Au9(5Tl7<^~(2oySqI?@J~tG7y7=6D?BwcZ-8IKY=XwFaHH_i-vSqH#!Sy4YiX!+ z84j;M$AJlGBxQqbq(Tc#@8ST zKaZ!#A)4u-+mgMnGO_+%n#fFIdi((X{Y;-dzYjx$wloAfStIwWlf7dJW+hN8{Q*=? zz!s<(l;qX2qt__U$3Y@}fwg5|oz5~5;{F(1s<5pl_h7ud9r@J!0Rn9>M4bJI{-Y+b zi>_%BkKm|okLBMpN*pURzB-Bc;v>Zw=Nw|N&MHjw?AbJcJ#$iD1Kzg)80w+XFD}j7 zJS+WxpnZSS0bn1hF2Gx3#!)U!CdiI^Enj_viyw7y^z?$x31i$w5s~@KSn-m zZF-ONWRbxkd;&qC++;3Ta`F^l(QB2ikQ8|42sWPGo1@&x)*Mqx*e*u3v+MV2JqJi? zdgxlzwg%~fC6JACIn#p-O+dU3ytzes70#973ifnv&;~=S*g@e=2q)(t4tl*IngsjJ zdI96OfiPvDQV&5DaRHM4ArBjM;>C`04;LjzpwzptQ^Wvf{Qc+`6~n*bT8n1j1u8q1 z_jf0cJ^k~Ub8%hvito!PW=Gr?#yl#qX~DvMtb{QI1iDh;g#uy)9gGI-0(4hC6qk}0 z=MONtXHlIU|8`G@=jkssmVAA)>f`m87=G~N^Ya>!53PYI@evw;Mwp{p!31i*F6Oc3 zj0RLdP@kS^-whB>8MJw)a0}GMFon{OG&iOrVq9_~Rcd)JV+G z40uXSb5^ix|9Lbn(F6Zl9E)DqPE+Uu)lJu<{Xh)8y$p<5~o@^=;wE^GqS*Xw)nPY54tfpdnl2GbJ^EN((uH0N_f z7`z5jssP?t-WD-s?)GtF4vo%xhIO*#KUBdzQD1jF_nXI)^02gwv2D%Jz-wq~`pam6 z^_HPpCOJ>Scx1myoI7P@Y4tthua0_gQwf}--wY+F4YbdINBg<6YLJF8v-57)uuME3 z$t@ZuzcR0k!pb((*0yZa6G|@7?K9?yOP_HY2@9#9-oAjTU3wk(uevba+7V&?I ztkxXlvr|jt?kAF_HSkMB{++uR6N zOfYvDojcLY5xLhP?e+>y(D2#;NfD~p{dcs##)}7!oIIgxe6y(FRJJ*2q>|XT=RG_{ zIBLL~;;0=%}s6Gt134Qqd>RSN5>}b|U&dCrjKDgA8 z0|`%qu-+3MIr)Kd^Om|mPI`(WT>xhoP!AnXPI9(bJusS`7}ut|md@lG1Ska?ZQ`$| zt9o!WjxF~oN5>Yu5Cur?p02Pqo^uxB1^-e7Zh@r6A&ys7lMe>lQC@pA`H*-I7W4L3 z!acjR$YR-wflMLlATG%lSBR|Edy=$DfW}K|9Fv$AAq z4%$+sY%i$Yg&Ck7sneFi%do|xdMy&vaRz3gOP`OF)rRA6Afen4ekTupw9Sdj=G(W* zKT{S}ZGTEvDm9#)c@grs{!2166MC^RcAX3h~Mwr*BXK;|u!n|{UAPz4}DuyQ!79EGaSOp>MFJ0s`-4OOBTnND_L42OPqq0 zDxvA_iOT|-za~xwOt;j+ZIVgBb(DTV=GFfIu<6xJ^p~p69lR6MHRbID^{O(rAYuj& zX02%Ia?$e*YPb$(&XEaFi^d-life-J@xZ)YOWxb6r#}$V>WIY8j89LAMC!NOL|nL+-1TCc%)^n>*mi)-3;aBufmc&p`| z3*d-F{b|Z#u*U@{)L}iy0-I)TnM3l6RmG?d8O+otndM)Jcrm?H=&#AECjDz0?(pxGjeB)ryLMVx%5V(2kG@qCm0!nSPyYUTMim;f z>g}JeM`|3$6X*}BuQO@MCr4F~#RBFw7#Bx~vT|_dC=+J*EX8!!$|tqmQR^HQBy*|- zy7YYy%>H0kBMAi#ckKHx$v|PV-TMI^;w17!o=1F;>^mure6jL$dcycUGv~>s^NL-n z2I*XMt&&dNVE%-Kqh~cak52Fx2aAuFf?sXb|1y`B$*0<80J&>%kRC+-7e0aBR1j5Ozt)uXc^9~{WBdyP0${_?*gkYb0SnQH?+GAwLpYG9|jg=!%qmpHMdMTtO zm4AKT%=n{$Gub>F!fySWUXlK|#gJ)dn-lg3KdG?+_^ggmbq8YW{(|6nQ*23jyL7w& zQYYEd7a@V8_*k3$u&#CO&DSu|mO$eMvc=X~{SinK$Ol#$ zLl`~7J}s|Cfvio8WPP#*Eoqt8^G*p-3XcSoIU@#ql05@&I7L_k$9Wbs^20NV{of`@ z^7@p<1q(w}0yG3GTxq)U4YGldhj`Mm5)4x36#oQAZnZ$WG}9ed26|)~+%-|kkaM$x zj}V+J$F!6Rb}A>aj%o^Ns2j#e^Mu`S_0sU>T107-8iO_3)AbM1xjDD4--d?rg5=o7 z0!bd!TuD$qe40LbW;o&#&{1J>)RNFGU`C+TQai8#}&+{ zI+LgkGTKwU0Xj2gZAlE_dr|){)+ko)^E&~|E61Fq?QcHGY6vZiZOBzhK;%1k4p~RY zBI_X$w(-!h<0wq-JoIklR0R?8=SiaL-=P1WUZWAKVPQk!4`d>=rpLgfBXc>Ptd1lNVt2cpy~OdMZ(Lim$nF7S1$Po^QfP;07EG@EtuP@3@iVkfb3_K+Q0P(lV}j0yEE*KjqBXZC#lmj5e?VW`ihI}RV~w#Z zGyM?)t4UcHqjf151TU7BXQtqJwwGI@D?eq;}yqM7nP(S!fbm8-W6I_WJ84I0?;g<%<&l}9(} zeI8~bJqdH91i8d#qal>RYj;&-H{Iyb!saE!UTaL07`9%LD}?18b)--OcOg`3WT` z+Ded`YB}LqvKjlN1tpq4glfo8C)&!u~cYgH9pL(@zrnH9vU3m!m zpoE8v*OPMDlzihc_eYX+RuDCH35qsh=y&!2DRbZ-lPwbFq#n(QQOt3W&8 zsZ7rHgLEGc`q5n?_}^{NK9$I%+6=9C=D|XHTi{55Qbr!k^>n%0zcPd1THoE!lVMIw zVPXhZ@jG2Qav9+qY8byi-$h{{Mzf#6*3OY^e%B0(Sm8)CA5vebG(A7Sp_jFiV?_f; z4t483P6pO20L5X@V7y!X%b}p6QtLym?wT6H?jz9yo#4$mV_>lI<2Hs+pd#t1F7`8& zl&P{i_Sy?J@V0*Ak%dYb6Q`|CwiLWJ0TbZ!(QAf-&MeQ-of~4SI;`U%53j(|+0qj1 zZ2xnwwKN#880@WsE8A2bkBfJ(glP`}Xr&(NGM*fVKY;2ilSG}XvrW+yX6os3zJ+9S zJmEAv6;x{;YJCRU2Q5p@By>22unM1_yS$U6V6P*ZrjNsr(MF7p4ep%c(iE_uP_PNb z&&?cBi3MposNKtRT8GNq>2?eWkpAl8(l*Mpr#_mc)Cp!fOqy{YAoxvBo)${Icd}M3 zKPSP0iKnE6u0%7Y@|PA;weX04D3bBS#nhu}2KVE5r2bN0KN(!^sAYU3xYVB!=V~it zocrP}=Wdccy`Bb{4#>4Wo%4XoSX&-DmioKQ9I_bt3`w%i*fOOwnET<~qB|P2dSTp| z+O1^WKhX{gG`<=>&|>4|d=A>H;fFz7_C0qRQk;+~HsQckZ|JTmlFqE3VWkcwQmiQz zI8a&e8@SsAZlQf{K%(p7#aPa?={fg-vJLpH&0oS;%evl?QCn>TbZ;*6H6Ue0i@DyOc zxz8Mr>=I}{^aHWKeywis61D!z08czHh7?@!QDC6KIub2{K*M4Ph-$iylGN_Mo1c;H zJ)yLvOpL1>zlITBcJOkhn{L~Nb^arFzibSpzu*QtUG28ST5p@K4F}ksRkkYUQiX`~0mmdc$vg)h} z$Wdb;OpB6#z6Wz+ekQ5sQF|kk$ZyObqQwzInoTtaf-~sOkw;)`eH0iQ57~hyHk3A0 zh|pryq_uhAl&B2Mo{eU(v)Ql4`0Ag5&&Czbo<~J%cDsB}YGh;Fubz~8aXj23QGnh6 z=6@Q=u2J*Aq-)%NwXuBIdTHI6u% zJLZYSU?MudYy$2QN2t=CnR)75+dT&E1R6{>|A3X9bu|vPtBaP~(F-3>u7Bju^MvcF zyRGyK(tfyO-OAZeI;3Fo4Z~j5T^HE00@YJvYlnD1IxjZ@isWcfWTI^F=uK;c2z}2`PQc1v(T;tth)7@YQTCl7QD?(N%ZP; z>8b73&M(610m*0A`_1=JGW9ee$~|xw8Ps75-kiBJZ1WJw zSoD=hRD4b7eKxf=jF{t@#B-QzJ&b$E#9YM*ju8sePv;PL0&_!XM#@DxRHBTaJ}`v& z4vBK?CRo7dP<-j>7PXrTcH z@q6v}Oxi&t<^j`{yWof6eE7NB`~~iOMOUeVV)vWp(emDwz9gUOy}1RQhTvbyEQQB0 z8KzbO$ay}`FPV#OEJP%a$v!jSP7tvsWd6|P0^-mptZm(;}&`#z#n|;dBf+8jt!^lyv%<* zn-LZu8n|`sLZPwp-;r}=ZeWG>Q?rX8ja;`Ey5{<;+YHCbo)!RIFsF64N zQ6$6Q3jS*Fp`7f_ga$t@;|H8CTL za{n;Z&nTLJTVG)il66I|78#uEK&eHY0D+;1rj?{5dvv@Tg2x$G;avyCPx?|UOWGip{VIOG8YIiZTNbYgB{PUC ze39MV(lF59gT`jIg)ZO27<9c>XpKh0C~i0^Z^Vd12bkX-woR8u2dou#4-b zR--nGyq5%c%8AZWPAKo}(V8;vM?cfaw0-GF_}i`I-kpEqa=IQ1;@kS6`WQq{4LJpl&pGK~eNA{!6K-ObIz`xt}m zj%B*__Mr4pIJvaz?BU%Y3|~B~>HnldHG$Z3Up!sJ-C8C4oMKY^5}{piqyT4hBiLf} zGxM(X>?A94#Dgo0ZVa4f=v7|wIy@DizKDl|DkL;GRaK{vmRB+nt+tD0r#OreBO()v2&%4xPAyr<5 z3CoKUXvDj=M(m;DglYbA&;D%dsl?|X-1=_51!Ah1JO<_%fs`QRl?ics5S2?Szd?#*a4=A@nEaKo&>F^mY@f$0G}z_JfeiZ z09<=X;w!g6(`p^$sf*x=GG>%eI4mFKm0-B*+9XaoQB3H~TLX?vO}Jp3z71?Mf(4qy z(rIFHsuu@N0PO!o6E~HOm(`9v@(Dctp0HjUVCs+Q<3b`l&|IcU?DZp(XHBV5U>P}{ z*EP4Dr>E2~NEwAe@;fgd;i?ANe|;2;Z11&EHz8oU)lMpiTZn^9koKG6w>~g#j1rD%;r20 zDl-}9NZnHDhD}jG%E7PH){+35Sa0V(+IK@e=Vm#2wI6`T+97}~*)BNj;sz3gkfjx1 zn7W0cFyYS|B}p;>6+gSLS&iLVr1XS!pMT^sBE5ATGOiE*3R12k<&CP8is>mGwo!vz z0CP#T8GS!y9;j+jOMp{>W~|A+`E2CG z1ECh~(PN^_lU-3|@4ThBY#Kj=xz1jHq(ZRmb6jXh+@MKv%8Abj-?zLVrAETYTT{)< zgAiB%(uvZC9wVF#E)9dwN5<|6WZ3iPdRF$3M`(imAeB`n^=@6M-?8>ZA74}(D0YL^ zN{!eJm{sbJ7M-@z<9AEJLv^RIqoU^miBzJ(Fn5iD%AbD0Y5#Dx!tS_1TupqlB%Nn` z*kRzx*~xF#b5SxqV-M2b=lbJ}p@ z1oiG@c0mS&Anl`oaG-iV*zradhPRJs*w?bS(mwjXeuB)9jA#K}t&Tw72~R#1Mc-Uc zIaIe!HYD#Cdj91Vh2$o*Ct!xy<4gz?{@=3EM?cDC=u1UP^O2gMEkpwsPxv_zb1NB* zB*aMQm8nXNq6CKyeI){6znd4AE7&}ntaaYz&gzC)T>bY(fZza3Ux`#tiGd$1|Jdf& z0c%q?yjlkN`9e@Ztzt8(KE9Jh8-b=uL?`PW<1~v^sVA71TiTN390uqsxhxe^|4^p& zZ*1W(Mhq>wA>x}1&oRqR485jRh%RJvzN6w;3Nm%(GcE~s5(~&xD6_}0f_pHn8wB#E0AmaPY1;! zBU2EJ%0K|>1ocuN0CIQ$Nel$H$JB@tg8)IzM!b0*@qqXb9j^d%&j}Fz>c4FyA?Ze5 zF}SHW01B~_^nJfy&rN3pN}S@p*YP?42nM3F<-AMG{;V|{`)SE#+`@CopBMr}(*{_k Stv#81qqZtJiEV<}Pv8J*u#b8G literal 0 HcmV?d00001 diff --git a/docs/screenshots/panel-dashboard.webp b/docs/screenshots/panel-dashboard.webp new file mode 100644 index 0000000000000000000000000000000000000000..ff57cf8f67fde36897c6ce43813f5474775138ae GIT binary patch literal 37884 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 literal 0 HcmV?d00001 diff --git a/docs/screenshots/panel-instance.webp b/docs/screenshots/panel-instance.webp new file mode 100644 index 0000000000000000000000000000000000000000..4b7aea021758975c5c03790b4f558b9ce17dc93e GIT binary patch literal 23256 zcmagE19WBS7A<^YR&3k0ZQFJ#tk||~+eyWCQn78Tl8UX@-S_sr-LLQezjMYOdyg~r z_|E#)TyxF2_Sj02Vq!B|0D!uvkb;^52f^TP*H?_d*+5izU_l^!@e=tm#YMygc{grp zbx2T_wr>nPOo5Er5wh;P-ZHys%M~t7$M`+8GM|^OP4^$HGx;ZxAL?cDkGXPsv7G}x zs~Ljrzp@4BSD#;XmF!cmYV!_#FMXa?>|y_e_~iZtat`wB`+)!C>!?rpS#ZVorvG~RntSyD)RX7y z^*R0FxT*dU`|f-Cx#DyBYVr2^uKo%Czz_JG?rHNq`D9(kpT{8ay#qC!pIjt}#EEKm z@2o;hm1j>5U^+dzsT0%X*;0cXFU=h5!*sfJ*T7M8;FX9HYzit<4w7+{0Q%!cV!9kV z>fcv5G>D4ArgkU4;545zqb&2kjwf%2w9#q=yz{2m-v&#I#xDkD$c2DXZMd3!c{E?ghf7y=$CrWF} zaDn5++dhc;eykEoTFQnI>vw%*))u>(Z-yFw-9x+kqnZl|B(HO|J?ij)%WI(cCTpdQ z&}Y%U65*vVx{^t1>Aia%aLlp>D)X+*;t2c&y!lS`*dYUsAj~Z3 zA1V1GrS&Z{WQb^*7~|m#RcM7hh`3FEB)A@8&z-q8AIV2=VI!Jx$5!0zhf66m;@{whU!7?us(R96_g|2R znFWlngzK-&V7Qt(xsFNAZ-8l$LXXr)4^LzET~HzqGey@a@hZRay9Be`?V$1F4^l4Z zQQ1y|g8)!*coO%u$59h9!OD8yA4w)z9$YcNbK|%H?0Fb?8lOX0Wgc6n0Otjft9HXI z{y*yGH`IU67)lXnP2>B3cUQhi2~?Jn;DEv8l8%o^Crh^82*~HO`-ibG1^5kayuqAn zxl!?(HLZQ&NjI#H0=cBJ>8hl7NhmLUI&J4p)$Rn4pQkC_QF43X0Gh3AQ#xo=14l3@ zxY@;=1cZ(pZ?94#7nzex#vrbK#8V93MXdK$V~CPm7uly;DJp9G&5&CN&X~kD)aAlnXY8>La_S(PAetWg=0t=F>;+rIoMPm{ zgmAc2|FF2!OGvJWHpieH7GzdHKWBdR9W>nq3A+1Xjz%vlKRWH6Q!1EOJ2>0WBznhk z+`V_IS?Gdr(wK4JQhFlERnooRkKMwB#wqhxLS01hBd`J^8^>lNC7ePW6#@dVwtrC) z(kYrVn$z^4bG#Gzj5avev(vG}Jj%@XrSID|dU=`{TQBWYbBIRPbCI)HJlm^sQx=yO z3|jPWkbEU=E_q@9U~T6Zs*_py&rw3NGB_yen&&tzFRyKjIdQBJj;q=?J^ePYW}7g4nS*Pe5!cwdQRb_w)7Z97AV zBCS==ex@%q_THReh(>+q$z{972p49e^D?d^`p%|EhMc+fug3hZ{$*0JH~cxoh5)?r zdlOH_7kh*UX50D>%S2?P4VFFo)_!{Qk*9xygI4e@eMM0p7Lk_nJE$IzYZWA5clbSC zIDBo>P%XlCFzdE9-e2|)V*gtX;)MRH2f7O}O&X={ZgkmwRS~LGYO{V7*;S&pMtAv* zu%Osinqi&{ILp}>pJHH@b!cnV9`FNm6dy%$_uz7>9u(?OsZdm39d)shaoIo zdt_IC!?|x}%qe@3?}I$p_i-ISMqqr1l++e~XF%A|{acx!`wtTHiAU*Ugk zz$k7jM)+;EIi$Tesh2yn|o0i3QRX0G>^(kIFSjVp&tH?IE-!< z!@IU!Hy5>;e!KoBD}6$w-oLo;Z>^8B{@pEn*QA|PfdwJvvn3>UNTV4?K!qWsf)#Ne zrvr^7BR-N1&~f@q;}0zD`b#RdWtYW`)f7+uAR5l@3&Yz0!g3{rHw#tdcID` z`d!~64bu5AKP}eO%KxIhsq*T-1ILUus1Ua5n+#MbA$<-B!cU)nkZDnl6)jXsfd-jw z97qG91&{ljAc0{cHc!xh(}x=Kx&bmSu~6WD0aFT%tJ(H4b#>nwLbRZ)Ysr?tEKT|GyWK*_pjE+}XjHRO3+v2~) z{JctbnzlCrIKb7E0XQeQPWtYk3s{EHC4EH2QKJjI77a z7*>X|p{$~B#D-?&X7Tunf2Rz06=0gyd@ZrWFedkeh5u2?w>nx#tt6{*o$!NcUTpM ztVEM$7KjSxH@aKTw5L-LZm)za`P-(Ku4RJ&Er0s$K1!M2nmyJ!fyQ$$3KZ(URr6mF z9euw4!=P7O1h1bw>ge6TD~tW(fNkAqOIk%h{nHry5#TZHZ}shr9b$i<1*#>}jdPzB z^3}SB6m=`Yp}LRqKd12b_`en5A7ewa?>{5>`-pKX{<{a^ZTLL-E3E(10R7H+^uLza z{~l6`{;&>fME^mSjiH3PK&Kc=xi?_K=Ecn;P5OZNX3{Qt=6yaK7jKYG@mvHcZ8 zvE9Fu?SG+iGN%O4&bIq!QU5+I{u$rzgJFB{+XDhR>i;u2zXdRTw4uE?IP#Z)=70RN zZBk_lYBIc^Q28Y$Nb-pX<|_k8{iu7Ld;pEGy(AAk>Fokf>p0xW-*n)Aqy{yawZbVZ zUkJ%|q}8*K-M>KiZ%*SM1>Sk~;CORzE^`Z-*UL*hJfFj!~cvj4gmQ0 z^a8<3hYG{fQu`!-R005K9q{lbm2=;5yQ1ya-G+>%!0H-^kan;~o5!cb=FDkNiLeARbKEpiv|yA-S;11rj}XF1 z>M_X+eZSd4l^d4xd9u~1r{(1W0D$kG6ln0{s8_Jet9Pbi1&ydxM=tghS&omNA=PuAy=yC+q7mYP0yxdlaQTNu%JHqFPNT8KID?9C&%Z5_^VxG zOE6fC1c+>+>0=t#0XueLJ0+ehz#h55cKVnxZZxvMA8JD}(k5!<9fJHA7pQ;YzS}ax zKzc;=I2vKW!7)dIU_tWP1Ac1Hvmu%-<+xaC;Q{z_RzrS$x-Za}I^^n9FHPQ9$3_AE zS<9~KGpL`Umdi+lpin}NH)BSU)Pyj3nM`5s9>+s7CQGP%bG#{_aMf*lMk7^F{hGs1 z8O{SXJuHzn!@(2_;|_>S;)!7NBv;fD<15Q;emX_>nFi;DqenVfk4=#g5pmiB)vaqRP}M6u#L#!^jt5;CsFkj2Efp*I%i_Kh^{=R_)V{gETbyL3_t{t=o#9>w z@rD)Fx*R-rDGDT3Ui#mCk30nlgiHefxpLt4`b^U;x*B5;8psQr7RAhl7)LFM1qlp| zLeVF|y0+R;?aCxZWiLj__U~Khq>!rx^Z)W`k<4kfU`5P}Wg0M&zPh;`7hRa2ok$Ob(PBsh)i}OejQjV8*)wz=d1_&@I zg?E%%v{Z3E8tCtLQc|`(Q;phLkE_HW|1KjKJZaXYLxb73vuFd|udLq=!T2nbsF?ZD#`9(b;dL5AVRcf~J8uW%2)JhWkyQQ$mSL)Kv@p87c;<1kB}s?_!C(Qg z2!HV!RUv7ZCPAlWf$q+M&pn-^g@kt@X)g~L{y>B?b1^5e7) zy7>e8d!R*>-Tw3h-b3%|CUHR@w{9!=E1p`l7&<*kH{&uhI6Sx6r!n}Fj#uVQ9 zjj{B%fkBbO=na`w&b&QC3^9iSFJ=Psex(+l?S{~{Wqx!!?QSEE5_)G$JL+1ddG;kF z+06D{go7uo(OdbnWtyFEqSEPd4>IHy2tTYXqdVU6ukZIk=wTijkTj{XDzd7|(8i7*J9LWaB?G@e7Wz)pgXT>=x2pOSf ztfYL`e%P~?>hMfuNwH*uF75>#Y3CZBkfT(_3ZT{JO4}cHJn7UXnEa(BWpmm)LO12x z;R(3N{TRQHAX}sGa#(na9~PaDM;?|N;SL|bh&QIair3rQX4aCQK2!<)^yWJ0!R(YT zxz2&hQ!v$>IfQxFg*C?a|shG^GI76Q)xH`K)_0h6DAcDAxotCdHI@*Yy?34p(1p`ZOJ!`o5kj_RuR3 z>|3rbhJu;_v@+yR#feldg2>x7m9>y(W|`R>@l5@j8nTP1zC$EyR%sNBi&`}j+n1bO zE^x!1m11UG?k*;NI!NAr3gMOn3j}Wet!6r4_X#SP;=ZdAsQ495!KVKVW zfXb#-+S92UWm|lxZ6fIt3&j&oPsw*;rlNJF@9DmtW0#%gfpB!O*pMnFnBs#pF@X`QV_|p+S7jUL!BG78<;cUjuJ|Mz|K29J zO&IZ$>(Y-cH9(C~(91GK3!@&c?Lc2HyO@o}wn)HT_ECB+4Tn*a*G<|!64orCPU^}R zn^=BECn>zmJY}mOhj28hhT(ZJQ2VTqGKfu>b64)v6dPk|kjT@0?S06PF#=dO1K4%?m91IUC8}@WLLA z@m&e;Lb8jt)}Tc~_EM^O`}hPo_|>@qEq&93THEj#WwiRl!4--}VUW8Tm;#TVAep3_ z9H+7R&a8*K(w8cDvR!j!Chf#;3tMeTvW>_hwmGV0tBert7o$RKCAoGNUdAu_dI)r2 zJ((ZXsrGEfsZodp8b~vrl%O=iukG%Kk=pU|PY8_cUsIWRh&DfLY^nty0Qs8KT9yv5b@0u`8x zU=^T^-CHQJc75j{Y6xhQXliQP|uOgLZt0DCX)OxN0b<@Q}|1H>U${Z$yduKs;sBhWj z`JF;oa+0RAx0n}7rfuvKI z-@G?a1P5t)mqgi*5uC(AiHN}JN+kkaXg>h$IGMRQ`I*5qP?bnypH{q!CKrg+sGd>L zp6p}rEyj#!Sn)YeZCtj}Ovqn+8LLTzIXnvS&IL-(2K_IUH#cGwbYY8$6-hCRD*)*;Ec|V1lt6XjA2; znSE9dS?X^-oiLuGY?5Hneq}Zzeq;`kwi&&J?=A_m8)mJ0%W*Q--5#OJM2(1^pmmci znkOTos3?*nI8;8j$z&r!4KZ0d#gA(N!y<9&9J@f0q-#u&t8gFEB3iaD4knmyb41gQ z9~_9{N9nQBC2~OV<6gZ1uDAiIR&lZfJ1a*D-p(UlNgT zX3jhz&rlL}$#D+7q~YL7gLvJ#Sf^ahP`wAEgYkj8M{Hcl(Et`cD6sd{lfIR>W$*D3h*Fn(Ryirvwz@#Q zOJY6E+^&F=xB&6CJam2{0uyU_Rci>^86z7x%Vz#Z&?{|o@-+WZo|-``cnX0h%#n1a z9ByHpQc`@8_cUA{BB)c;rm+Qpnx!rVv-rz6Qx|HYlRa z#Fd3!kmt$yUq-;;a7C!4{w8`2VxM7=jL3R{66K<*JH09^etY9rlj8wgBde`$Gd-!Q z$3<=cLcQQyNa>?_Q0bq-_5<;La0<@(9^>cjhW@=B9N(Tl;U}x@HG-*R-sl-Shp*o} zt}S-`iu^cs%T7jzM!$yFlAMzVdZl8@2SlF1`5XyMU{6_kyl0m{%*|OCYmK5f6C7;) z+?Rly0-|Pq@-yH95O)Oc0G*Qwvx29g@3A|DMx)o33i#nUQ<$G_f^p}-1y1Hib~RiyJ(Z)UYuv{?IkX{SK%!9~nlL32KzRw{ zBO^@9%x{18ka_q4^b2l~>-9UU-W!MKx{h&ln>O)0(o8=!;?IlcyC^H9TbN_*O(k~# z6}ynsl*Bx&OmS+Ck$A;vA_)JGxsC) zxp*B5={`Tyw%JCFTROH+ zoOuKZV0qZ^t|EJ`H(9Ym!kb(Xx>0n12-E#zUs~XtP?d=7l}Yuo2%a``Xh`8HCpj zV5XSxsis8iYG`WExdaU+usaE7!T$`iDGc?$7V?&yjgSU{oqm#D#_xnld^{BxCS#nr2h&z_7={@B@G%TCxj4 zjEh74(nD_xFxU_Q(=OXIn?Q3r=2qZ?#k)(4{K0pf&XDPU2T3vTDjfanzOfmCZ}UL) ziC`-#OXF*sWW~1BSy(`;d6gjr9!+M+SLo=vNs44? zl|}NXv!|#@YHwZcag);3l+LhP^H-0XHOWGG{wu34TtF)}IuOt3x3sJ*bYh?ZWQ$|- zx_GDC2pQ#;%YoOEuXr6sy53;7g23`80}{=1ZCMTAbfnd01^W1pA0E)wNkf4cb;eNr zJVy8lHeJ8XJU{>n3dU}!=!3juB|hiNLJhgBIV~(?AfXGZ0N9WFNW zE;rF`vs~-^Az8RGQf;a3caCk#7E5dVWjz`|3*~+lZu&uj4WTYa$a`2L{1+q#7fZz= zJXgoXuLP|ZX=q$&XOh;J!qw|g(lu1cJkj`~etO+sc=y5c=f+iBiBuBP9B~y5HeEju zW-5uWM&grkC!(>1M$@0j@96wFUvC{D8rvXhH8?HgW#TqJwTd?NI!T8?3)y>YkTx1^ z*9L{2#1B=1#DTk)oxUQG-Y#W^ALJBw#klBM6V%iw*rrV?fX{OOZasY;CcB zD4mF0X~_4uAlNVtnm0l&5)@BBMZw}6n#>x8K*trFL#tOE6 z@BMFOK) z_>EEejGQVefX!Up&&QnkheAIwBOV4dBR4wQM+&97c>&9}JUqV9qgKL(Jok0*4J{ZgboOYBG#LyAzqNs75 zi2R_E5=6&(b1(`DRaVsKldW_>dwrb^5Ly*Wd*={a4~7(u==|~;C$mJ=X#l~oJReVX zlfUv1gPUhKNN@nnvP4d}7WjnGfjCalM zE~ajK`$O3jOyL}ei!ZdJW3uq${kIRp zEAz-&PG}!fcbEWp74#8JEjXDHesfyCpd7SS8=Yu)lGrK)ZMrO*R@qZ;ku#thzKVah1xw}WBy!fD~|aX4|Br_vhrN^+IuES_Npj01P)&L+8WB9 z{^KT1M}~F2#?f=@v?z)jojcg?oIck)KbH)ld;*ZVC?-9f@z|gU3N5t6e-O>^S_i^fJka`3IN- zr>Ofv4Q4lc{8?}So(#!g-gHEQ*m)nNTtEfOzO?tyzV4%kA(L!s8C*+R6OcV})d!{3 z8G^(=cD@tqGnp#`d9?qOc?^q>ud+Sl6(Ccp!y-0#?tSVgBkmmR{uR|Sq347GzeGU+ zOe(YFQ`_U97=N&frjkDtBT&Fm*0+YryvCPc-c?;K$wshzWKzB8qPDJmhmz{A9kq>e zDE^dt64Y5M`7Rh(>?&b5pgo;wmpZ^dU}v0ZI8&$SY+@_fBC1*x-e62%81G2Tjx>uSmjA9Up__m_|oybV1(Gp@I`hYt1X$tfV3*zbA$akc;na^?u|yI^9N5*$)O74V{;U9P$JIQpUD+U7CaFM zx)Rt2vb^3kVA~zJU`C6=PDJR@ z%oK*8^N5+@+%P^riInoki0WFbpv;Ww{S>xlau5!03ySKReAXf%p;hIt;GsA2X<#v| z2@pb~p%PFNf;ukTY^>_YnN+9e9mgG36CL)yuEJ|TLI_97f`TQg`ct>+}P zkSh<221rS?$c4`}txApWwu~^GQSj`(&yA(E)A8bNpgrIW3@muS{SJ8WtUm-5Bgr0v*mtNCg+-yvbTO5zUFDe9%EklI>CxSfUeGwtl>%x2i z)-&h+=?jZ-GmZ(~i^pds+%wn=hn`H5>h?)rCF6FmL6=RgzXmM!bYnysAAb@)MM24k z|EQC3CC0dC#ZI$sJhP9Aw0H#6H8E61H4^d#tIledN=D-Rc;0YGItckY*U=Fxr2l;; z9N|0>j~@UWyZhPZtU3V8YWuAlga@r5U)o7uT4^8K;Lb#kh3DK$Ms{Vg{i8kYkx2wq zjwU77#c#-}Tf8h5U7X;84sjDiao?XecAeo+q8!w~J95e7X3mjJ)v(MBD%At7YdFAf zy4#+0Pyq`e{c#Gs`}c2ZDd+8lJWF;!OFdN&oAho^i)cCua6);Dk?+OBkdVpX5DVg` zg5(*{qya>_vZ~4;z;sm(ghuD*=ICbl*Y3m`9X|$oRxe|7P=;38TQf7`-=7>KU5tk2 zQ?)iaog6#)+#M=3I+^M&)d^q23xo#JJkOACtAXHntbl7gY>JT?X7u+|8MATix23t& zaxkqr63&lyHjuy5o(*{NOER_KVOnS23*lL0BU@Ax3_7Ck>jE_1U zhfZ7El813VRe&Odo5}|7Q?u3^@Y7AhUahl?O%4(7l5(x|5r6H$t_*l;{&8tEjB`y% zA;yB9x#$tp6G}7(Rb^p~jK1gsuu8HsZoZ&GnN84gh=~YNxBj^$7k2^<;yB?N5Bv?Y z(GLq0Tll8u$P3n+q+<+4HNIr(hp~3>?3|%gcZc@IxDfWJYEtZwO8RttwE-t{eQZmt zeg|!*j*{*gyImh`n_HjOXOcPd4*wTV9Z#B9m!jU#uRrT-hm_5FICq5&VO+`T&V&0F z?F7Mvbv$ID9!20gf{imSUo}s|LE6<^SwGB=#H%Ryj;?WpYt(V2qxb!t#p%2G zw`||2f@`D95iv$NHYVURkQwhiYix$;_i&iv#cnCo;}l6Uy=^qA6PDfOq!-8mIs@fI zWI;c53fpK@t0Fp;^;Qt4BpU31V4-}4G8HOR=>O*h4XM&pEuctr^dt`e7?VKOaONXZ zMK0YTznOwzZ>U@=yrDM9GXM~eDpZjI>a@Cx(tv?n4t(dD@GFi`WVztpSy9El*Y_oO z&8KH^TV0sbw!PIKI^t#<)r9%4WIHi15J&8&7hDF9a@xb4tsM&)eVc_BF`(QI5eza9Dy`ne9hq~Z9l6K{er4AdluP_I$!q6fYVUWZ%DA`sfgb?j(JiqZ=q{!y4P6*O&$B6one;1o%qkDU zxcBgR6^vIoI*q+s3t5$V$fYw1L8IxKs1;pMSzd7|W~Kh6nEDZ}PMHPq#9T}0uGbOH z-D_R5(bDUAK1F4@5||&>mR8nAd{sfeOR4rJvYhr)6=g8|ux;K|ly($7Mi1O9#keH! zx3Q1h^$hiG9g?L~ON!k9K>L{{qY-j?tbgg2h$lX;nC^>NegdB~Gsl6>+Z=S5AjqAQ z(*dPj>pogJ_lIk}nHJ$mFy;4_Lrd+hp1V~SVlXOtM!{SwbN6i*lFbe`j9AdHwAwua z7--n3)OHTeWNsfi^ZsykEP3selyAl&*!`hU04H_#bV;YQszLNJ^pYA8=-_HgO4bz-JQ!k5g^R!5l4Nu)JqVzcaR+ z_{z9{#BY}+E!#NlrxBWZl8lFqSAGkObA&d)meT=Yk!Q ze8w}w(Y9?OjfSI~h7X_G)|D}K4ib}c2cAlG!3D2B#SDV6mo+n5i&)c4^^zM**FiVF z6)VoNB;dpehr1Cc!Fg7ewug;GbX4xywc&tywZlt-H%*uBcY0rrcBLaosE*cJ`us9%CExqt#tID%R{J;lI{{pcKN`O zh~3vjPGBrcJ~8@FO<#-s`6JIaW>)ox_3e!e@P(O6u;{;?zu2 z+T%Gl(=hH*x2i6WZ!TQj=6?y%Nl88mSC$pCq;8av8EfPWFiAT16}5lca!+KlicK- zH#j)FY=i}7WHV#Z;N|khJ!>W(xid+nDb6!7gWT$dyF_FyA59OZLjO+Zt500SymR8W zFZqOZd?5>{wh3|QD&~EslcjUR{Csf@@MAT?QnHJEJ>UD`zQ9^4f~W`k-Q_z3?NMj| zGub8VMyDJ$X;Vz>k#0)SDLAUY3w;zUAleZU1e8xs$T!G*DZV;hg@V4RO%je0#89|2RQ`B@wWWbeVSzxtrcyqe|p zF_K#fqv$P@biNl-bLx8)T8M>QtoH?-;yX6hb*|xlOLeaSw4j)wTL~Aprij6I){EvQ z{EHS+IjJC2{A~eed>Rz3wmNB!g%w&9vn<9_brq^(n`lN@2AV{#ZD+Ox^nDrqQ>38s z6bQ1@Pa=UpfJShpFzT**?J~UxDTy(0eGw~nkh1<-8i;U)E=~d)8}h!WVa>#%Lo{{! z!)v9K>_tar3RWK0{Kc<>jPcEsZ1NhjT30qF+T8l^A2_>YO18!a_i7H9&Z%rLY1|Bq zJ2=9X^!kBopCH?iKm&D_SgWTs9OTMt)TuiN=Ot^!$pNs436Gwy%0E``dbx>`O+X>Z zIlOUiTF;Pvh2x&cPV8TIld?`sF&(JbJ`iq4j6mhU#U27TU{(P4YvUs%eb_rPD1^Bn zlML7DeL1C5)LtLF32v^+L>=N|b+=HIv%lAj-Yr^FD9daQAFiTdatTDeAH3^eeT{O*Rdd~3g+ zvwl9Ith(CWgnbF(L_Y}X*=1XLmT_b`{Nw=>3l}X`D-}>AR&#zgVrVpYI<}L%Mucxk zYW?jo&w*G$WT$J5F0gq@RLTHS-WQXgZ(?1&m0NvVp9z!=^>zGdj`kHPRVaz-Y8nUQ zl9%rm2REjIjYrsLy|jC)(?-ghzHhIZehOy*jNCK4V8;b}0@AK+ze}1yf6I2I*V^|( zM1fjHnzU91qfma7tlwU6Xz^Gkp7v@GvZ2!kTvGWh11Kn|F?=Gk5%4G>Mg_ru$i@QM zRpwQa24Ep0`_GPcl3h?X-2}F%5t8CL5F>^L`X$}_*;|X^&BL8gU2n& zBjQxbS*%)!SAo>1Un ze_{cFwH-7;-);H2w+OVsbh)xYvm-n0NY_00B5H4M9yHw;5f?- zAYgPnC2dTY8;xLlGi!4Y2dc>!ON_mWtjek?&zFa7hg@bO87Uq-u)-X6UdL9wy9xi(Z&1g*U9RxIWMHCXuLUgszGx1M8v~VB{6VQOw0?|;&kvt2OnWo7pDye-|tzJ z<(GD^%=-gvWwvy5OTgTm%k+eSOj*L`psBf@<;({3(aIml<}3$70r<8FrEIwhDK9Dw zA9usUfx0;qS74=Pk;x%4le~k-(NqHBxFZzH?e0RGOyfts?X%2KyjOg{!zXWE9?PpS z%`X)L)Hw+CjU2RjqZYNCh-`s!#l>=1rIL|7eF{NTzVzWLBibJtGTLaVb1T&|I)EZx zIOW0(!;tH!*gkqx z`rUy4WEkrU=cIH}h_JO6o`sj<*3Vkzj!|oG({a*k>rJJI(gn8d2DZd#GO^yq=VL=>wv(*WC(PwtYotnWTbxtm<)`7Ff^ z__w!fT6(d8@IJp~w*JFo`j=6>G(2 zJzg%Jy_lChy6YBib^pSSHxWK6R1+@Ob^IoLNnLVhd8(M+*v4OK+BscvF7e=+ejDzf zlE`}-Ivd5_&!DB$=FuU5pJm3Us}yws)2@i=F&=Di$WNjPn|;_}Ss8`%<*DQt!E<5< zR$uhX^p_Cx55UK^IFyqB*?cu&9fL}fhB#g?vSk<2sqqdFp4lBUG{f1_Qfc?`u(#7$ zyD3~qX)Y<{ZrY3msbx?M1iu9xl&lC$#G&nfo-A1lPnydl$-RBUffcX8B( z^`Eqc`$WwpPSFo~gVevVd25byC*xLhUt`+LuTeuxk{N7rpO)Z6UZjGv!nSD0&3v-EZ}5G{%5&)dh!XnVy>BWZ7Z^l)T!5=oIboqy1}ILnHM zGr8d_ixksht~LtR2icgD-3kETvI|Ct!o~Y}v^{nS8#VDXT^HhnBlh#^YI&K15^9=| z!sxnCnOLrdC!AAYeQ%6t(kPIWK$d9<)6rV_of7w^ooC+?OD&Ye1O5CeOgW$;!gZ(X zK(cmCnUo3fnbVj>22qGNVJPFaV!C=3 zpH8(6003k6TQ6|;u~k$#7Mhj}m#9$V8-E|0B2CRo$@J$qc>-@PahYGfXNJveUM{@i z2I^!@t|6@)8lcagT&t@q{&xRNVQgF^xVK02!U=W~=ggs`$-9VS8q=AQ>;&6T=^QGq zrR#cY(>(G?y-m{g^Ig3wWWTraG}{%#y49lblDo68lv5UAs+`)(MBC2xRw_q>_H1tc zbt%q(_qj|2uPYZfX1O`4E76U9or~a7&M~kz)6AfL4-*vp10@~UyqRm5M4t$@ zd4s>mj4aQsC7W%x2Dpf9vn5@Vcx^t>&O(Qm3L^mLC3gC!bLJL8q1y#4y---NmGT4W zfz=-9^Z<421E>SawEWI#KGDYn`re_)CXxnR)9}K8YDG2Di$88ylm@*Z8KZp?goYK9 z@hwm5g7iZF5%^H11_KJKq(#2?x&Th7Wphq~?TB_#u8adbexa8Z*Fj+KJ0c}Q4^Hdo z5Br>;(RzyYD}0tq+x9-MeEpfExkhw)LQZ$^J(a#KnJXFX+Y_PX^3L!k1-r%69_NZR!rD-u9Z zxjW6o=LMf59#I7d*ZBPAdq<;T#sm;h2cZu|KJmrB9^n%S=KW3R<+JB1moY)5V9v+U%}WCkq0818gnZ z6H3eyf+)v6?6+!Cw8yWK;v9er)Ll3&>ttmDobdg{rqA~qqPZ7L^pG!Yr_=9Mb4Ti%aW3TQ8Wa3p04G!Yu;v>ZF~SA9Kb^#+#p{T`N4 zt%{G(2+O^kRgKO0nid%m{RuV8V*`mUZ^?F-==;Qn3Dok{!^}=Xv@fY-WXqa5K6GJ< zw=qfhzC5IL`~%t?z2RL!Km%L7$`_;}rIf+e9 zdG=2`fQY2@Lx936|Hd?1!uWbpz%SvwJn;iH3*eSzr$FJufN2qGX?P)bwd)UgKXf!6 zrHgj=k$X#BT#fZW!NP;I+6Qp2Z+UP?Wv{7ysq2$=ZkpI;d6t^b{)?^hr6=$$=+5AcM-*)BEAc%Lk%z^Z_b&m;*|jtB>I_aTF- zYnf2@b@~Mf>czfyowA_pmKX;u88_n-9P@6ShpKLeghtEn2_|pYgh%KUPgv4_H#<-z z3!hKW#9r0f`Ggx(`u5+T0H#8YD&FjiQgGy;^9 z)}OB^3kWyjRqd$XV%*Lbe#Y3oqNO$8aO9YwVft+L%*e?p1?`M3s|DkLbEl8$N&w#Q zx`Y<}MH#1JL>%|Fn+jnM2rq#oIu$FSM@HGM)tgXUMUt)K7@KSZq>I9e2H3njb(#x> zNg!VvHkNB;!pQndP$^=)yTJ`?R)lvOY)`w6Zc9cVcScpKMJ3iPaOxo*nlJ{|4htB;{trlUw$j40h(xd2xV$C{p1F{M)ehwg*CRaU;5}J8p0@`< zmrN<7Q3q^}Z{cT%rTj;Mx_vtM4U$};Oj6+}H_m>n~0Qdmr znr31KZFwctmjUL?c7#II>E{tArM6j8GV~eCX;Nl7!#=7-zJf_xB=u&wDBklQ;_f}A zO150CpQua0&3?^erKbr+I&f}*e}Zn!2t+J}tH0`#-`Mz02?Ud>%QV)nJFD+gnGy~6 z7y+0wBN4J!=v)<}|0`VVLqzdd3VH<~2mrgKAVvFESzZ)k9|egbJdL?Q0cAJaB5UNA zHnI)&z>P0`DV`qrIdmSj7Y4hiqLv2s#S9C*xlpZD;cRJZNwv>DFfSQ&<+PwXhE?Sm zP~16&$SqtTKOCpyL5fDDD%pTZUbA8Xs5@*jcUX>A&^J^a{iiZY^x+?DXSb4xe+4R8 zX!;g6b5nX73ro?RFqeV|;-DjDf)d`&T~`$y8O3m*PzKZPi!YOlIaUEcQV*em#;EP| zFmY1Ri(ijrX++@OU+xHdY4(aqum^&8K4P=NK7%N6T3N8ihI<)>LEuOSVZgDc?pOlnv@=4La$3?(ElaC<+V80oL0ZF$!CGTw* zT3R?5&Q<7@+z)qSp$S8mvF&h6?|H^D_F$JsFV4vcnJLAh#YY1*q9)`$sGhN+65Wak<`X8b6_U>z508hK*_>_| z(rZl(EL5W|r^>IF6~+R}C~lsMpy3B6)ds$g;sitTa*0F{mVW7DbZv2j%5!w7Zo7K! zY&J8NUCh+lE%FjiS3+GOR41e16;TbJ63atS8i3b#?FhNTKt&Bo7==Ng4gO$Bm%3ur zF-;&=+SgW<{d3Uj_djIsI+gwW`F2pHGpQOTZfVx|p{oL@i)?J( zm9%r;`jfXU-eVtp3+3x#FT5T%|01{ur0&xg|F2(Qq&rY%AMCA`K;VprpO9J;G z06xN#NLmIBwBtc>tphX&;SW9M5ZOBu7oKla$Z~3F8sr&5b!*e=3d{)bdG$m#PTzSy z$a8||6CM^a{Y+@U000$PK!W7nJwo7|vb|1+7&P?FT`2T& z#Cd&`;Gr+*rSJv+C=uR{C#SmZGQi}cRp((SyYkAp`_!>9#4;k7Du5Hrl*eiM4T}p8 zJhpcXk?~Q!Y)k)@l5wZVQ;>px7-cWr05%tPuq?uWEpqU&#uTPObLc7<#lOLl)WHGj zhn(D_0?QCXUK4r#l8giy4B58TVfOfEjz*gqhN&*H#!8`KA>zz2szDrVWytWcb#9*e zFzbnE`6dNSmBIXu{36jLi)?Yn>K@`igRoI;0~V7O#6Hna?V5Q8TO)XGK}K2t0Zstd z<tIsK6$58o9*fXu^2zWio=yDFo3Y zf=axKnPc_khRjl>>t_;DyBnfiqloQ&Z`2*}nxq(>cC9{03FeYNFRt~ep?p-DO~qp( zK}(^~WjdJ#h6K$PwoJxY@S;)p4(TE9nhluW7@azpDo09hU>y9h6P=!^3u7PP8Dtb5 zxWt7wv?{+Dv>vD`$bd^kraQdyQ+)_JI|?^gy{k=*pvrI59m0Y%5iz5dvE#!{ruq~d zx7w|;|11^?jl8Jor&VlV)ZcrB0B&46aeU`j|guK>v1aUT1*TxW=Ju7+EPz4w5roGr-CGw1*?bZ+lA?YK&G4D zHj}cG<%bQSn)|4#+}c$|QU;Gtw8nahon0{`Nha4554=qNYQ=ZZl&O>qBNA6TxYB~= ztfP4VEU@~$HJYS9J3qz#l*vomKMj1>PH`61kM%3-hqj|}TY3|YTj2cnM+HqzWh3i2 zZZD&>=#2o&egYr68h-722Hd@l?YbeWK4)<45f$g(HQSx%j_@!QJ-)6C%_o^pj2+I9 zI$sjG;o#*vubX**>{DaCWPEmywDfz7mA3Fw5$9=Uun>@S)|d)0X%3mP<%e1$q361% z44SCt>b}U47Z`Ec}0Dz~MCbl1g(wgQa8Xv*<|Fdmvcvbx&v_3#q zc#$e%Mt*_B(XAo-Wl{jD$fV2gFbGa4{dlT~3+(boxIM3Nb&!RP942d<%ktDNpBm%h zsPzwxpmsK3OsieQvqAl3fik~muugU+ZE?cBbtt~lt)?6#2ilj%;w+2Qr@ zOb_aYG==ISiG)XB6hppIXW*_jJ{AeUNcJS~SCI9`+VO|%0uv=+xTfRn6urSwh40Y( z8y=`imyp2SCuvMW2Yo%!u7Ll_1i-bHNm~H7Y{^d9{DtLz^J?pAF9YF;$DT`VB6=*w zFvINBy3-~3fo@>c!7iD_{V@)oZOs1gZT zyEzPGJ)D%M8%xGYpU=QD$3`pUN`dRBR!ca=+jT)haX8F*rr|2}OS(Z4O;I@(HEPu| zhFcX7j>VmH63Qv2w83OCJ!c45vkY!HO|i>OMCKOa30kS&J;Ft9SdyKgJ zyA&5`^Kn0q;pXCTkHaUhdaw-JP_dNG9G3UW!M7#PhzYs|+n(PGz?t~4S-UI-GEn@_ z`h#jwBTVlxQX=>Cl}EKEBeeVbVup%$(0unFH4hszE*D)T+HbecPiTlV0BY1f{!GCZ zW~2tO>aigLw+2w!q$W6DeGFrl#M5HeG{>-&Mp%A60F?K6#hxO^jPcsc-p0?%S2)zE zMjVj#N9yt*Pj>jG))Nvd)_KPq1FqLXQ$N(0Sd>-HrTfFcFc29N38WVui-9ZJL4TQ{ zQe)x?6BIX>nH5MXiH>U`##hP%6#B4GNeUnbf`Myg!lh80f)^r6Mo;w!kZJfyJOh&| z-;gAA2y?{{q5Cytxy=_t1k(=l7Tmw&OC9E6?pV>lJf)06(@wU}bU)*U4 zmjCXn#s>q_KJ3{#=vLrdTox_i{Mg^!X^O(sCsuae2X$PcoU?iqIaZb=?-81ql4qbQ zD7W0KsK2l`sAdF6FxeE#i#kG2nuFR#$$%FYbU#^-ZR3g;84e+L^u&irdxTuqCV^br zlGm#L8>%0*Hk66!7*82fUuT^M@31K+TA3d@{xX^N;{z3Fh}h_EL%5Z@ziTSHW}8<> zDj@^+r5Qb3fPPxl!{boQF_+u^a3ZqPDAg_xtpo`-aT*Sn>La;F!3>~29kW@p zkgW711(lK^DJUl$G!E5D-e$jw4twMPZ@_0CEjVM5!blPvkK^wg7_DQjx|}rcg5&?1 zrS@tbR#r@_UpqFwQMG9I<-a^h)4d0*$tG7z_H5uipUvLGUYcJp?3x8D%`^Y1B`)0r z;t!%Fg-jr4fVdl<)HjMO2nw*RGQTtNE@#MJ@4+F0(Vz|%DLomg*Sj@@LCPP@Y?6fz z`4lt;03nNspuv$DVX8s4Y5)LcwV(h2GmsG(F+z*RZXWn30>8d|Y;H4QGjHoV!(%uX zR%2>DcJNnul9TQ~K3XOoN2~bCMpy@m6}sENC!3KXAx_KGYou#dnFlk#KD1NZ8}pzE z9u*`c##}P#wuov(l=#R#eZE zn+Vt(y7M1pXBk6khnj?MS{;~TW%Lv4AwbP8>5u#3Wbt}T_{MjA8HtT{*yGLG@`{(z z`%3JD&m|bjc|FY~l(}Q4W73wNhHsv3<@CN-$_ZzM3`FNH7uCG^N?9^100000Y-|7k z000A}r8hx4Cfrm20ck)000002PapsQ0000006v;iAOHXW00002s~`XX0000006v;i zAOHXW00002s~`XX0iPfM000A(fB*my*#H0l2O@I-00000000000000H!pXpRyI3r#)_Fcza$rx|q>C=S)!QgI6NztGI zp9-+dTypqg*m0KLxps`Q>+NcRkMwF`j(AvTq+V0TY;OFqO#Mk-%^)$nZHjg9&)48S z_%%HNDipx-P2X-EqOM{D>3krmfp*uwsKkvpo^Kg&S(UJ7zTKKKu7>x3%D7!5<{f;# zAl6NW$_8svLI@%3O^c2acS))!my1!wt~8$-H%}ges?l9ngq*|SQftGS%e+BOEV6x$ z6*G9ml&tY=8QXMW0`%(VP4Dn4#K* z%X-wFJ|bl=^VzRHWK@m-Uh=TGgoqPxp`Lh*`eUl>zA2&S(JZ%W{&MY+BMF>n6^AN+UXaGV2T$>S20KK-!lHbESY`H#EO2HYV#2+h`!#mU z-_P1BwJUol@;YfP73_LIf`w!F!0g;Yf*-?_&`@jmTMu@$JDDsuatpP__}~x84RP?Y zlt``_BI<)s*JWwL*lpiALwDKrrxYz(1-xkZo$aIMvLb5LX^=YYS5GtXDIw#wNTiGB z(P&2z580Lj+pXJ#3ke!w{1NR;m)MY$YxQT^5#Ly;O_%1pKi&G& zhhx*_q++qzTJM9Y5^of+jhbh31dsJ4jm&O=eznfhLANZK=XYk*kd@{?&utBYG~fUL z1c(ae&0yN#7~DpPkT2BSs5ZODc8a&IuiV`2Q!sy@mh_Ysh=c+jhdPyTX_9j=HrePR zJH^WLOd|+)5xDL*Abeh$=!I~A1s!=y%DrO{N@jmfdEi4*(P-5_y!A*CYiPd11smc< zsE&c*_&r9+Vns^&(37k$P#2UWjP+t4-Ll(X^N<$-G=KmA2*e`!32a8;2mk;GX21Xd G0001UPLm)2 literal 0 HcmV?d00001 diff --git a/docs/screenshots/panel-players.webp b/docs/screenshots/panel-players.webp new file mode 100644 index 0000000000000000000000000000000000000000..97fa7e6762d8a497beff041c7773b65e4021f521 GIT binary patch literal 32970 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 MXRrVO000000Hkl-X#fBK literal 0 HcmV?d00001 diff --git a/launcher/src-tauri/Cargo.toml b/launcher/src-tauri/Cargo.toml index a738ecb..38b726d 100644 --- a/launcher/src-tauri/Cargo.toml +++ b/launcher/src-tauri/Cargo.toml @@ -3,7 +3,6 @@ name = "scopenet-launcher" description = "ScopeNet Minecraft launcher" version.workspace = true edition.workspace = true -license.workspace = true [lib] name = "scopenet_launcher_lib" diff --git a/launcher/src-tauri/src/accounts.rs b/launcher/src-tauri/src/accounts.rs index bd8535c..a9a8923 100644 --- a/launcher/src-tauri/src/accounts.rs +++ b/launcher/src-tauri/src/accounts.rs @@ -45,10 +45,8 @@ impl AccountsFile { /// Add or replace (same kind + uuid + panel) and make it active. pub fn upsert(&mut self, account: Account) -> Account { - if let Some(existing) = self - .accounts - .iter_mut() - .find(|a| a.kind == account.kind && a.uuid == account.uuid && a.panel_url == account.panel_url) + if let Some(existing) = + self.accounts.iter_mut().find(|a| a.kind == account.kind && a.uuid == account.uuid && a.panel_url == account.panel_url) { let id = existing.id.clone(); *existing = Account { id: id.clone(), ..account }; diff --git a/launcher/src-tauri/src/game.rs b/launcher/src-tauri/src/game.rs index 9f1ef4e..4890d69 100644 --- a/launcher/src-tauri/src/game.rs +++ b/launcher/src-tauri/src/game.rs @@ -134,7 +134,15 @@ pub async fn run(app: AppHandle, instance_id: String, start: bool, deep: bool) - let auth = auth.unwrap(); report(Event::Stage { stage: Stage::Launching, label: "Starting Minecraft".into() }); - let pick = |a: u32, b: u32, c: u32| if a > 0 { a } else if b > 0 { b } else { c }; + let pick = |a: u32, b: u32, c: u32| { + if a > 0 { + a + } else if b > 0 { + b + } else { + c + } + }; let max = pick(ov.memory_max_mb, settings.memory_max_mb, inst.memory.max_mb).max(512); let min = pick(ov.memory_min_mb, settings.memory_min_mb, inst.memory.min_mb).min(max); let mut jvm = launch::split_args(&inst.jvm_args); @@ -200,7 +208,13 @@ pub async fn run(app: AppHandle, instance_id: String, start: bool, deep: bool) - // Stream logs to the UI in small batches (cheap IPC), keep a tail for crash reports. let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::(); - for stream in [child.stdout.take().map(|s| Box::new(s) as Box), child.stderr.take().map(|s| Box::new(s) as Box)].into_iter().flatten() { + for stream in [ + child.stdout.take().map(|s| Box::new(s) as Box), + child.stderr.take().map(|s| Box::new(s) as Box), + ] + .into_iter() + .flatten() + { let tx = tx.clone(); tokio::spawn(async move { let mut lines = BufReader::new(stream).lines(); @@ -268,7 +282,8 @@ pub async fn run(app: AppHandle, instance_id: String, start: bool, deep: bool) - w.set_focus().ok(); } } - app2.emit("game://exit", ExitPayload { instance_id: id2.clone(), code, crashed, tail: tail.into_iter().collect(), crash_report }).ok(); + app2.emit("game://exit", ExitPayload { instance_id: id2.clone(), code, crashed, tail: tail.into_iter().collect(), crash_report }) + .ok(); emit_state(&app2, &id2, "idle", None); }); Ok(()) diff --git a/panel/server/Cargo.toml b/panel/server/Cargo.toml index 9a4a189..218967b 100644 --- a/panel/server/Cargo.toml +++ b/panel/server/Cargo.toml @@ -3,7 +3,6 @@ name = "scopenet-panel" description = "ScopeNet admin panel: manages instances, branding and players for the launcher" version.workspace = true edition.workspace = true -license.workspace = true [dependencies] scopenet-shared.workspace = true diff --git a/panel/server/src/auth.rs b/panel/server/src/auth.rs index c4f8be5..1503910 100644 --- a/panel/server/src/auth.rs +++ b/panel/server/src/auth.rs @@ -90,12 +90,10 @@ impl UserRow { } pub async fn user_groups(state: &AppState, user_id: i64) -> AppResult> { - Ok(sqlx::query_scalar( - "SELECT g.name FROM groups g JOIN user_groups ug ON ug.group_id = g.id WHERE ug.user_id = ? ORDER BY g.name", - ) - .bind(user_id) - .fetch_all(&state.db) - .await?) + Ok(sqlx::query_scalar("SELECT g.name FROM groups g JOIN user_groups ug ON ug.group_id = g.id WHERE ug.user_id = ? ORDER BY g.name") + .bind(user_id) + .fetch_all(&state.db) + .await?) } pub async fn public_user(state: &AppState, user: &UserRow) -> AppResult { diff --git a/panel/server/src/lib.rs b/panel/server/src/lib.rs index b3b06da..4215855 100644 --- a/panel/server/src/lib.rs +++ b/panel/server/src/lib.rs @@ -89,10 +89,7 @@ pub fn app(state: AppState) -> Router { .route("/healthz", axum::routing::get(routes::public::health)) .merge(routes::api(&state)) .nest_service("/files", ServeDir::new(state.cfg.files_dir())) - .nest_service( - "/uploads", - tower::ServiceBuilder::new().layer(long_cache).service(ServeDir::new(state.cfg.uploads_dir())), - ) + .nest_service("/uploads", tower::ServiceBuilder::new().layer(long_cache).service(ServeDir::new(state.cfg.uploads_dir()))) .fallback_service(spa) .layer(CompressionLayer::new()) .layer(TraceLayer::new_for_http()) diff --git a/panel/server/src/main.rs b/panel/server/src/main.rs index bc4a299..2fbdedf 100644 --- a/panel/server/src/main.rs +++ b/panel/server/src/main.rs @@ -30,7 +30,9 @@ async fn main() -> anyhow::Result<()> { } async fn shutdown() { - let ctrl_c = async { tokio::signal::ctrl_c().await.ok(); }; + let ctrl_c = async { + tokio::signal::ctrl_c().await.ok(); + }; #[cfg(unix)] let term = async { if let Ok(mut s) = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate()) { diff --git a/panel/server/src/packs.rs b/panel/server/src/packs.rs index 1587cb7..70f8a1b 100644 --- a/panel/server/src/packs.rs +++ b/panel/server/src/packs.rs @@ -56,14 +56,38 @@ fn read_json(zip: &mut Zip, name: &str) -> Optio /// Paths we never ship from a plain instance export. fn is_junk(rel: &str) -> bool { const DIRS: &[&str] = &[ - "logs/", "crash-reports/", "screenshots/", "versions/", "libraries/", "assets/", "natives/", "__MACOSX/", ".fabric/", ".scopenet/", + "logs/", + "crash-reports/", + "screenshots/", + "versions/", + "libraries/", + "assets/", + "natives/", + "__MACOSX/", + ".fabric/", + ".scopenet/", + ]; + const FILES: &[&str] = &[ + "usercache.json", + "usernamecache.json", + "launcher_profiles.json", + "launcher_accounts.json", + ".DS_Store", + "instance.cfg", + "mmc-pack.json", ]; - const FILES: &[&str] = &["usercache.json", "usernamecache.json", "launcher_profiles.json", "launcher_accounts.json", ".DS_Store", "instance.cfg", "mmc-pack.json"]; DIRS.iter().any(|d| rel.starts_with(d)) || FILES.iter().any(|f| rel == *f || rel.ends_with(&format!("/{f}"))) } /// Extract entries under `prefix` into the instance's file store. -fn extract_prefix(zip: &mut Zip, prefix: &str, dest_root: &Path, instance_id: &str, origin: &'static str, skip_junk: bool) -> AppResult> { +fn extract_prefix( + zip: &mut Zip, + prefix: &str, + dest_root: &Path, + instance_id: &str, + origin: &'static str, + skip_junk: bool, +) -> AppResult> { let mut out = Vec::new(); for i in 0..zip.len() { let mut entry = zip.by_index(i).map_err(|e| AppError::bad_request(format!("corrupt zip: {e}")))?; @@ -139,7 +163,14 @@ fn import_mrpack(zip: &mut Zip, index: MrIndex, dest_root: &Path, instance_id: & if safe_join(dest_root, &f.path).is_none() { continue; } - files.push(NewFile { path: f.path.replace('\\', "/"), url: url.clone(), sha1: sha1.clone(), size: f.file_size, origin: "pack", note: None }); + files.push(NewFile { + path: f.path.replace('\\', "/"), + url: url.clone(), + sha1: sha1.clone(), + size: f.file_size, + origin: "pack", + note: None, + }); } // client-overrides win over overrides. let mut overrides = extract_prefix(zip, "overrides/", dest_root, instance_id, "override", false)?; @@ -410,7 +441,9 @@ pub async fn fetch_curseforge(state: &AppState, mod_id: i64, file_id: i64) -> Ap } let info: Info = cf_get(state, &key, &format!("/mods/{mod_id}/files/{file_id}")).await?; let project: ModInfo = cf_get(state, &key, &format!("/mods/{mod_id}")).await?; - let url = info.download_url.ok_or_else(|| AppError::bad_request("this modpack can't be downloaded through the API; download the zip and upload it instead"))?; + let url = info + .download_url + .ok_or_else(|| AppError::bad_request("this modpack can't be downloaded through the API; download the zip and upload it instead"))?; let bytes = download_bytes(state, &url).await?; Ok((bytes, format!("CurseForge · {} ({})", project.name, info.display_name), project.logo.and_then(|l| l.thumbnail_url))) } @@ -464,7 +497,10 @@ pub async fn import_zip(state: &AppState, instance_id: &str, bytes: Vec, fal let (loader, loader_version) = primary.map(|l| parse_cf_loader(&mc, &l.id)).unwrap_or((Loader::Vanilla, None)); let mut files = resolve_cf_files(state, &manifest.files).await?; merge_files(&mut files, overrides); - return Ok((PackInfo { mc_version: mc, loader, loader_version, name: manifest.name, version: manifest.version, files }, "curseforge")); + return Ok(( + PackInfo { mc_version: mc, loader, loader_version, name: manifest.name, version: manifest.version, files }, + "curseforge", + )); } let (mut info, kind) = parsed.expect("parsed"); @@ -497,7 +533,14 @@ pub fn detect_root(names: &[String]) -> String { /// Replace the instance's pack/override files with `info.files`, keep files /// the admin uploaded by hand, update versions and bump the revision. -pub async fn apply(state: &AppState, instance_id: &str, info: &PackInfo, kind: &str, label: &str, source_ref: serde_json::Value) -> AppResult<()> { +pub async fn apply( + state: &AppState, + instance_id: &str, + info: &PackInfo, + kind: &str, + label: &str, + source_ref: serde_json::Value, +) -> AppResult<()> { let mut tx = state.db.begin().await?; sqlx::query("DELETE FROM instance_files WHERE instance_id = ? AND origin != 'upload'").bind(instance_id).execute(&mut *tx).await?; for f in &info.files { @@ -537,12 +580,8 @@ pub async fn apply(state: &AppState, instance_id: &str, info: &PackInfo, kind: & /// Delete stored files no longer referenced by the instance. pub async fn gc_files(state: &AppState, instance_id: &str) -> AppResult<()> { let root = state.cfg.files_dir().join(scopenet_core::paths::sanitize_id(instance_id)); - let referenced: std::collections::HashSet = store::instance_files(state, instance_id) - .await? - .into_iter() - .filter(|f| f.url.starts_with("/files/")) - .map(|f| f.path) - .collect(); + let referenced: std::collections::HashSet = + store::instance_files(state, instance_id).await?.into_iter().filter(|f| f.url.starts_with("/files/")).map(|f| f.path).collect(); tokio::task::spawn_blocking(move || { fn walk(dir: &Path, root: &Path, keep: &std::collections::HashSet) { let Ok(entries) = std::fs::read_dir(dir) else { return }; diff --git a/panel/server/src/routes/admin.rs b/panel/server/src/routes/admin.rs index c82d991..3153b94 100644 --- a/panel/server/src/routes/admin.rs +++ b/panel/server/src/routes/admin.rs @@ -35,12 +35,10 @@ pub async fn stats(_: AdminUser, State(state): State) -> AppResult, Option, String)> = sqlx::query_as("SELECT instance_id, username, created_at FROM events ORDER BY id DESC LIMIT 12").fetch_all(&state.db).await?; - let players_7d: i64 = sqlx::query_scalar( - "SELECT COUNT(DISTINCT username) FROM events WHERE created_at >= ?", - ) - .bind((chrono::Utc::now() - chrono::Duration::days(7)).to_rfc3339()) - .fetch_one(&state.db) - .await?; + let players_7d: i64 = sqlx::query_scalar("SELECT COUNT(DISTINCT username) FROM events WHERE created_at >= ?") + .bind((chrono::Utc::now() - chrono::Duration::days(7)).to_rfc3339()) + .fetch_one(&state.db) + .await?; // Fill in empty days so the chart is continuous. let mut days = Vec::new(); @@ -81,7 +79,8 @@ async fn view(state: &AppState, user: UserRow) -> AppResult { } pub async fn list_users(_: AdminUser, State(state): State) -> AppResult>> { - let users: Vec = sqlx::query_as("SELECT * FROM users ORDER BY status = 'pending' DESC, username COLLATE NOCASE").fetch_all(&state.db).await?; + let users: Vec = + sqlx::query_as("SELECT * FROM users ORDER BY status = 'pending' DESC, username COLLATE NOCASE").fetch_all(&state.db).await?; let mut out = Vec::with_capacity(users.len()); for u in users { out.push(view(&state, u).await?); @@ -158,7 +157,12 @@ pub async fn create_user(_: AdminUser, State(state): State, Json(input Ok(Json(view(&state, user).await?)) } -pub async fn update_user(AdminUser(me): AdminUser, State(state): State, Path(id): Path, Json(input): Json) -> AppResult> { +pub async fn update_user( + AdminUser(me): AdminUser, + State(state): State, + Path(id): Path, + Json(input): Json, +) -> AppResult> { let user: UserRow = sqlx::query_as("SELECT * FROM users WHERE id = ?") .bind(id) .fetch_optional(&state.db) @@ -166,10 +170,18 @@ pub async fn update_user(AdminUser(me): AdminUser, State(state): State .ok_or_else(|| AppError::not_found("user not found"))?; if let Some(password) = input.password.filter(|p| !p.is_empty()) { auth::validate_password(&password)?; - sqlx::query("UPDATE users SET password_hash = ? WHERE id = ?").bind(auth::hash_password(&password)?).bind(id).execute(&state.db).await?; + sqlx::query("UPDATE users SET password_hash = ? WHERE id = ?") + .bind(auth::hash_password(&password)?) + .bind(id) + .execute(&state.db) + .await?; } if let Some(email) = input.email { - sqlx::query("UPDATE users SET email = ? WHERE id = ?").bind(Some(email.trim()).filter(|e| !e.is_empty())).bind(id).execute(&state.db).await?; + sqlx::query("UPDATE users SET email = ? WHERE id = ?") + .bind(Some(email.trim()).filter(|e| !e.is_empty())) + .bind(id) + .execute(&state.db) + .await?; } if let Some(role) = input.role { check_role(&role)?; @@ -358,7 +370,11 @@ async fn validated(state: &AppState, mut input: InstanceInput) -> AppResult, Json(input): Json) -> AppResult> { +pub async fn create_instance( + _: AdminUser, + State(state): State, + Json(input): Json, +) -> AppResult> { let input = validated(&state, input).await?; let id = store::unique_slug(&state, &input.name).await?; let now = crate::db::now(); @@ -409,7 +425,12 @@ async fn detail(state: &AppState, id: String) -> AppResult> Ok(Json(InstanceDetail { instance: row.to_admin(stats), files: store::instance_files(state, &id).await? })) } -pub async fn update_instance(_: AdminUser, State(state): State, Path(id): Path, Json(input): Json) -> AppResult> { +pub async fn update_instance( + _: AdminUser, + State(state): State, + Path(id): Path, + Json(input): Json, +) -> AppResult> { let existing = store::get_instance(&state, &id).await?; let input = validated(&state, input).await?; let mem = input.memory.unwrap_or_default(); @@ -473,7 +494,12 @@ pub struct ModrinthImport { project_id: Option, } -pub async fn import_modrinth(_: AdminUser, State(state): State, Path(id): Path, Json(req): Json) -> AppResult> { +pub async fn import_modrinth( + _: AdminUser, + State(state): State, + Path(id): Path, + Json(req): Json, +) -> AppResult> { let row = store::get_instance(&state, &id).await?; let (bytes, label, icon) = packs::fetch_modrinth(&state, &req.version_id).await?; let (info, _) = packs::import_zip(&state, &id, bytes, Fallback::default()).await?; @@ -488,7 +514,12 @@ pub struct CurseForgeImport { file_id: i64, } -pub async fn import_curseforge(_: AdminUser, State(state): State, Path(id): Path, Json(req): Json) -> AppResult> { +pub async fn import_curseforge( + _: AdminUser, + State(state): State, + Path(id): Path, + Json(req): Json, +) -> AppResult> { let row = store::get_instance(&state, &id).await?; let (bytes, label, icon) = packs::fetch_curseforge(&state, req.mod_id, req.file_id).await?; let (info, _) = packs::import_zip(&state, &id, bytes, Fallback::default()).await?; @@ -507,7 +538,12 @@ async fn set_icon_if_missing(state: &AppState, row: &store::InstanceRow, icon: O } /// Upload a .mrpack / CurseForge zip / plain instance zip. -pub async fn import_upload(_: AdminUser, State(state): State, Path(id): Path, mut form: Multipart) -> AppResult> { +pub async fn import_upload( + _: AdminUser, + State(state): State, + Path(id): Path, + mut form: Multipart, +) -> AppResult> { store::get_instance(&state, &id).await?; let mut bytes = None; let mut filename = String::from("upload.zip"); @@ -528,7 +564,10 @@ pub async fn import_upload(_: AdminUser, State(state): State, Path(id) let (mut info, kind) = packs::import_zip(&state, &id, bytes, fallback).await?; if kind == "zip" && info.loader != Loader::Vanilla { info.loader_version = - scopenet_core::meta::resolve_loader_version(&state.http, info.loader, &info.mc_version, info.loader_version.as_deref()).await.ok().flatten(); + scopenet_core::meta::resolve_loader_version(&state.http, info.loader, &info.mc_version, info.loader_version.as_deref()) + .await + .ok() + .flatten(); } let label = match kind { "modrinth" | "curseforge" if !info.name.is_empty() => format!("{} {}", info.name, info.version).trim().to_string(), @@ -540,7 +579,12 @@ pub async fn import_upload(_: AdminUser, State(state): State, Path(id) /// Add individual files (extra mods, configs, or a CurseForge mod that /// can't be downloaded automatically). -pub async fn upload_files(_: AdminUser, State(state): State, Path(id): Path, mut form: Multipart) -> AppResult> { +pub async fn upload_files( + _: AdminUser, + State(state): State, + Path(id): Path, + mut form: Multipart, +) -> AppResult> { store::get_instance(&state, &id).await?; let root = state.cfg.files_dir().join(sanitize_id(&id)); let mut folder = String::from("mods"); @@ -591,7 +635,12 @@ pub struct PathQuery { path: String, } -pub async fn delete_file(_: AdminUser, State(state): State, Path(id): Path, Query(q): Query) -> AppResult> { +pub async fn delete_file( + _: AdminUser, + State(state): State, + Path(id): Path, + Query(q): Query, +) -> AppResult> { sqlx::query("DELETE FROM instance_files WHERE instance_id = ? AND path = ?").bind(&id).bind(&q.path).execute(&state.db).await?; store::bump_revision(&state, &id).await?; packs::gc_files(&state, &id).await?; diff --git a/panel/server/src/routes/meta.rs b/panel/server/src/routes/meta.rs index a45df78..710e272 100644 --- a/panel/server/src/routes/meta.rs +++ b/panel/server/src/routes/meta.rs @@ -20,11 +20,7 @@ pub struct McVersion { pub async fn minecraft(_: AdminUser, State(state): State) -> AppResult> { let m = meta::mojang_manifest(&state.http).await?; - let versions: Vec = m - .versions - .into_iter() - .map(|v| McVersion { id: v.id, kind: v.kind, released: v.release_time }) - .collect(); + let versions: Vec = m.versions.into_iter().map(|v| McVersion { id: v.id, kind: v.kind, released: v.release_time }).collect(); Ok(Json(serde_json::json!({ "latest": m.latest, "versions": versions }))) } @@ -33,7 +29,12 @@ pub struct LoaderQuery { mc: String, } -pub async fn loaders(_: AdminUser, State(state): State, Path(loader): Path, Query(q): Query) -> AppResult>> { +pub async fn loaders( + _: AdminUser, + State(state): State, + Path(loader): Path, + Query(q): Query, +) -> AppResult>> { let loader = Loader::parse(&loader).unwrap_or_default(); Ok(Json(meta::loader_versions(&state.http, loader, &q.mc).await?)) } @@ -44,7 +45,11 @@ pub struct SearchQuery { q: String, } -pub async fn modrinth_search(_: AdminUser, State(state): State, Query(q): Query) -> AppResult> { +pub async fn modrinth_search( + _: AdminUser, + State(state): State, + Query(q): Query, +) -> AppResult> { let resp = state .http .get("https://api.modrinth.com/v2/search") @@ -57,16 +62,21 @@ pub async fn modrinth_search(_: AdminUser, State(state): State, Query( Ok(Json(resp.json().await.map_err(anyhow::Error::from)?)) } -pub async fn modrinth_versions(_: AdminUser, State(state): State, Path(project): Path) -> AppResult>> { +pub async fn modrinth_versions( + _: AdminUser, + State(state): State, + Path(project): Path, +) -> AppResult>> { let url = format!("https://api.modrinth.com/v2/project/{}/version", urlencode(&project)); Ok(Json(scopenet_core::http::get_json(&state.http, &url).await?)) } -pub async fn curseforge_search(_: AdminUser, State(state): State, Query(q): Query) -> AppResult> { - let path = format!( - "/mods/search?gameId=432&classId=4471&pageSize=24&sortField=2&sortOrder=desc&searchFilter={}", - urlencode(&q.q) - ); +pub async fn curseforge_search( + _: AdminUser, + State(state): State, + Query(q): Query, +) -> AppResult> { + let path = format!("/mods/search?gameId=432&classId=4471&pageSize=24&sortField=2&sortOrder=desc&searchFilter={}", urlencode(&q.q)); Ok(Json(packs::cf_raw_get(&state, &path).await?)) } diff --git a/panel/server/src/routes/public.rs b/panel/server/src/routes/public.rs index 84f4507..919223b 100644 --- a/panel/server/src/routes/public.rs +++ b/panel/server/src/routes/public.rs @@ -43,7 +43,11 @@ pub async fn manifest(State(state): State, MaybeUser(user): MaybeUser) })) } -pub async fn instance_manifest(State(state): State, MaybeUser(user): MaybeUser, Path(id): Path) -> AppResult> { +pub async fn instance_manifest( + State(state): State, + MaybeUser(user): MaybeUser, + Path(id): Path, +) -> AppResult> { let row = store::get_instance(&state, &id).await?; let groups = match &user { Some(u) => auth::user_groups(&state, u.id).await?, @@ -120,7 +124,11 @@ pub async fn me(State(state): State, AuthUser(user): AuthUser) -> AppR Ok(Json(auth::public_user(&state, &user).await?)) } -pub async fn event(State(state): State, MaybeUser(user): MaybeUser, Json(ev): Json) -> AppResult> { +pub async fn event( + State(state): State, + MaybeUser(user): MaybeUser, + Json(ev): Json, +) -> AppResult> { let kind = if ev.kind == "launch" { "launch" } else { "other" }; let name = user.map(|u| u.username).or(ev.username).map(|n| n.chars().take(32).collect::()); sqlx::query("INSERT INTO events (instance_id, username, kind, created_at) VALUES (?, ?, ?, ?)") diff --git a/panel/server/src/store.rs b/panel/server/src/store.rs index b504632..0dc7da8 100644 --- a/panel/server/src/store.rs +++ b/panel/server/src/store.rs @@ -193,12 +193,11 @@ pub struct FileStats { } pub async fn file_stats(state: &AppState, instance_id: &str) -> AppResult { - let (count, size, missing): (i64, Option, Option) = sqlx::query_as( - "SELECT COUNT(*), SUM(size), SUM(CASE WHEN url = '' THEN 1 ELSE 0 END) FROM instance_files WHERE instance_id = ?", - ) - .bind(instance_id) - .fetch_one(&state.db) - .await?; + let (count, size, missing): (i64, Option, Option) = + sqlx::query_as("SELECT COUNT(*), SUM(size), SUM(CASE WHEN url = '' THEN 1 ELSE 0 END) FROM instance_files WHERE instance_id = ?") + .bind(instance_id) + .fetch_one(&state.db) + .await?; Ok(FileStats { count: count as u32, size: size.unwrap_or(0) as u64, missing: missing.unwrap_or(0) as u32 }) } diff --git a/panel/server/tests/api.rs b/panel/server/tests/api.rs index f008af4..6f10460 100644 --- a/panel/server/tests/api.rs +++ b/panel/server/tests/api.rs @@ -63,7 +63,12 @@ fn multipart(fields: &[(&str, &str)], file: (&str, &[u8])) -> (String, Vec) for (k, v) in fields { write!(body, "--{boundary}\r\nContent-Disposition: form-data; name=\"{k}\"\r\n\r\n{v}\r\n").unwrap(); } - write!(body, "--{boundary}\r\nContent-Disposition: form-data; name=\"file\"; filename=\"{}\"\r\nContent-Type: application/octet-stream\r\n\r\n", file.0).unwrap(); + write!( + body, + "--{boundary}\r\nContent-Disposition: form-data; name=\"file\"; filename=\"{}\"\r\nContent-Type: application/octet-stream\r\n\r\n", + file.0 + ) + .unwrap(); body.extend_from_slice(file.1); write!(body, "\r\n--{boundary}--\r\n").unwrap(); (format!("multipart/form-data; boundary={boundary}"), body) @@ -105,9 +110,7 @@ async fn admin_only_routes_are_guarded() { assert_eq!(s, StatusCode::UNAUTHORIZED); let admin = t.login("admin", "supersecret").await; - let (s, v) = t - .call("POST", "/api/admin/users", Some(&admin), Some(json!({"username": "Steve", "password": "password123"}))) - .await; + let (s, v) = t.call("POST", "/api/admin/users", Some(&admin), Some(json!({"username": "Steve", "password": "password123"}))).await; assert_eq!(s, StatusCode::OK, "{v}"); assert_eq!(v["uuid"], scopenet_shared::offline_uuid("Steve")); @@ -188,12 +191,20 @@ async fn instance_visibility_and_zip_upload() { // Plain zip without version info → needs the fallback fields. let zip = zip_bytes(&[("MyPack/mods/cool.jar", b"jarjar"), ("MyPack/config/x.toml", b"a=1"), ("MyPack/logs/latest.log", b"junk")]); let (ct, body) = multipart(&[], ("pack.zip", &zip)); - let req = Request::post("/api/admin/instances/public/import/upload").header("authorization", format!("Bearer {admin}")).header("content-type", &ct).body(Body::from(body)).unwrap(); + let req = Request::post("/api/admin/instances/public/import/upload") + .header("authorization", format!("Bearer {admin}")) + .header("content-type", &ct) + .body(Body::from(body)) + .unwrap(); let (s, v) = t.send(req).await; assert_eq!(s, StatusCode::BAD_REQUEST, "{v}"); let (ct, body) = multipart(&[("mc_version", "1.20.1"), ("loader", "vanilla")], ("pack.zip", &zip)); - let req = Request::post("/api/admin/instances/public/import/upload").header("authorization", format!("Bearer {admin}")).header("content-type", &ct).body(Body::from(body)).unwrap(); + let req = Request::post("/api/admin/instances/public/import/upload") + .header("authorization", format!("Bearer {admin}")) + .header("content-type", &ct) + .body(Body::from(body)) + .unwrap(); let (s, v) = t.send(req).await; assert_eq!(s, StatusCode::OK, "{v}"); let paths: Vec<&str> = v["files"].as_array().unwrap().iter().map(|f| f["path"].as_str().unwrap()).collect(); @@ -232,7 +243,11 @@ async fn mrpack_upload_sets_versions_and_overrides() { ("client-overrides/config/a.json", b"{\"client\":1}"), ]); let (ct, body) = multipart(&[], ("fab.mrpack", &zip)); - let req = Request::post("/api/admin/instances/pack/import/upload").header("authorization", format!("Bearer {admin}")).header("content-type", &ct).body(Body::from(body)).unwrap(); + let req = Request::post("/api/admin/instances/pack/import/upload") + .header("authorization", format!("Bearer {admin}")) + .header("content-type", &ct) + .body(Body::from(body)) + .unwrap(); let (s, v) = t.send(req).await; assert_eq!(s, StatusCode::OK, "{v}"); assert_eq!(v["instance"]["mc_version"], "1.21.1"); @@ -261,11 +276,19 @@ async fn branding_roundtrip_and_media_validation() { assert_eq!(m["branding"]["colors"]["accent"], "#ff5500"); let (ct, body) = multipart(&[], ("evil.svg", b"")); - let req = Request::post("/api/admin/uploads").header("authorization", format!("Bearer {admin}")).header("content-type", &ct).body(Body::from(body)).unwrap(); + let req = Request::post("/api/admin/uploads") + .header("authorization", format!("Bearer {admin}")) + .header("content-type", &ct) + .body(Body::from(body)) + .unwrap(); let (s, _) = t.send(req).await; assert_eq!(s, StatusCode::BAD_REQUEST); let (ct, body) = multipart(&[], ("logo.png", b"\x89PNG")); - let req = Request::post("/api/admin/uploads").header("authorization", format!("Bearer {admin}")).header("content-type", &ct).body(Body::from(body)).unwrap(); + let req = Request::post("/api/admin/uploads") + .header("authorization", format!("Bearer {admin}")) + .header("content-type", &ct) + .body(Body::from(body)) + .unwrap(); let (s, v) = t.send(req).await; assert_eq!(s, StatusCode::OK); assert!(v["url"].as_str().unwrap().starts_with("/uploads/")); diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..6677761 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,2 @@ +max_width = 140 +use_small_heuristics = "Max"