# JW Library Sync System **Date:** 2026-03-31 **Status:** Working — E2E Verified (Tablet) **Stack:** Android (Tablet/Phone), Tasker, AutoInput, GitSync, Gitea, n8n, jwlFusion --- ## System Overview Syncs JW Library backups (`.jwlibrary`) across multiple Android devices via a central server-side merge. Each device exports its backup, pushes it to Gitea, the server merges everything into a single `master.jwlibrary`, and each device restores from that master. --- ## Daily Sequence (4:30 AM) | Time | Device | Action | |------|--------|--------| | 04:30 | Tablet | Backup → GitSync push → trigger n8n merge | | 04:35 | Phone | Backup → GitSync push | | 04:45 | Tablet | (after n8n responds) GitSync pull → restore master | --- ## Tasker Tasks ### JWL_Backup_To_Git 1. **Kill App** — `org.jw.jwlibrary.mobile` 2. **Wait** — 2s 3. **Launch App** — JW Library 4. **Wait** — 3s 5. **AutoInput** — `nav_personal_study` → `action_backup_restore` → `Create Backup` 6. **Wait** — 3s 7. **AutoInput** — `Save Locally` → confirm (`android:id/button1`) 8. **Perform Task** — `Git Sync` ### Git Sync 1. **AutoInput** — `openApp(com.viscouspot.gitsync)` → `click(text,SYNC CHANGES)` → `backOutOfApp()` 2. **Perform Task** — `JWL_Merge` (wait for return) ### JWL_Merge 1. **HTTP POST** — `http://n8n.bunny-wyvern.ts.net:5678/webhook/sync-jw-backup` - Body: `{"device": "Samsung-Tablet-S10+"}` - Timeout: 60s 2. **Wait** — 2s 3. **If** `%http_data` matches `*Successful*`: - **Wait** — 3s - **Perform Task** — `JWL_Restore_From_Git` 4. **End If** - *(Discord notification fires on n8n side if merge fails)* ### JWL_Restore_From_Git 1. **Kill App** — `org.jw.jwlibrary.mobile` 2. **Wait** — 2s 3. **Launch App** — JW Library 4. **Wait** — 3s 5. **AutoInput** — `nav_personal_study` → `action_backup_restore` → `Restore Backup` 6. **Wait** — 3s 7. **Open File** (Tasker) — `/storage/emulated/0/vault/JW_Backups/master.jwlibrary` - JW Library intercepts the file directly — no file picker navigation needed --- ## n8n Workflow **Webhook** → **SSH (Execute command)** → success: **Respond "Merge Successful"** / error: **Discord notification** → **Respond "Merge Failed"** - Webhook path: `POST /webhook/sync-jw-backup` - SSH credential: `Homelab Login` - Script: `bash /home/artanis/Documents/JW_Backup_Sync_Engine.sh` - No Wait node between SSH and response — removed, was causing indefinite hang --- ## Server Script — JW_Backup_Sync_Engine.sh **Path:** `/home/artanis/Documents/JW_Backup_Sync_Engine.sh` **Source copy:** `stacks/n8n/JW_Backup/JW_Backup_Sync_Engine.sh` **What it does:** 1. `git pull origin main` — fetch latest device backups 2. Rename all `.jwlibrary` files (except `master.jwlibrary`) to `incoming_N.jwlibrary` 3. Run `jwlFusion` to merge all incoming files into `master_tmp.jwlibrary` - If only one file and no master exists: promotes it directly 4. Delete all `incoming_*.jwlibrary` files 5. Rename `master_tmp.jwlibrary` → `master.jwlibrary` 6. `git add -A` → commit → `git push origin main` - `git add -A` is critical — stages deletions of old device files so they don't reappear on next pull **After script runs:** only `master.jwlibrary` remains in the repo. --- ## Reference | Item | Value | |------|-------| | Vault (device) | `/storage/emulated/0/vault` | | JW_Backups (device) | `/storage/emulated/0/vault/JW_Backups` | | JW_Backups (server) | `/home/artanis/Inanis_Vault/JW_Backups` | | n8n Webhook | `http://n8n.bunny-wyvern.ts.net:5678/webhook/sync-jw-backup` | | Sync script | `/home/artanis/Documents/JW_Backup_Sync_Engine.sh` | --- ## Known Issues & Workarounds | Issue | Workaround | |-------|-----------| | Termux:Tasker fails ("Missing/Disabled Receiver") | Use AutoInput to physically click GitSync UI instead | | GitSync doesn't respond to `com.viscouspot.gitsync.action.SYNC` intents | AutoInput clicks "SYNC CHANGES" button directly | | JW Library `android.intent.action.VIEW` intent does nothing | Tasker **Open File** action works instead | | JW Library on wrong screen breaks AutoInput | Force-stop app before every launch | | Old device backups persisted in repo across runs | `git add -A` instead of `git add master.jwlibrary` | --- ## Adding a New Device All task files for a new device are in `stacks/n8n/JW_Backup/` — the `(1)` suffixed files are the phone templates. ### 1. Install Apps - **Tasker** (Play Store) - **AutoInput** (Play Store — same source as Tasker) - **GitSync** (Play Store) - **JW Library** (Play Store) ### 2. Configure GitSync 1. Open GitSync → add a new repository 2. Clone URL: `https://gitea.bunny-wyvern.ts.net/artanis/Inanis_Vault` 3. Local path: `/storage/emulated/0/vault` 4. Credentials: Gitea username + password (see `credentials.gpg`) 5. Do an initial sync to confirm the repo clones correctly — `JW_Backups/` folder should appear at `/storage/emulated/0/vault/JW_Backups/` ### 3. Import Tasker Tasks Import the following files from `stacks/n8n/JW_Backup/` into Tasker (long-press task list → Import): - `JWL_Backup_To_Git.tsk(1).xml` - `Git_Sync.tsk(1).xml` - `JWL_Merge.tsk(1).xml` - `JWL_Restore_From_Git.tsk(1).xml` ### 4. Update Device Name In `JWL_Merge`, find the HTTP POST body and update the device identifier: ```json {"device": "YOUR-DEVICE-NAME-HERE"} ``` This is only used for logging — set it to something recognizable (e.g., `Samsung-Phone-A55`). ### 5. Grant Permissions - **Tasker:** grant accessibility service, notification access, and storage permissions - **AutoInput:** grant accessibility service - **GitSync:** grant storage permissions - **JW Library:** grant storage permissions ### 6. Set Up Tasker Profile Create a **Time** profile to trigger `JWL_Backup_To_Git` at the device's scheduled time (e.g., 04:35 for phone). The task chain handles everything from there: backup → git push → n8n merge → git pull → restore. ### 7. Test Run `JWL_Backup_To_Git` manually and verify each step completes. Check n8n Executions tab to confirm the webhook fired and the SSH script succeeded. --- ## Open Items - [ ] **Screen-off handling** — verify AutoInput sequence works when device screen is off (may need `Turn On Display` + `Dismiss Keyguard` actions before AutoInput steps) - [ ] **Phone e2e test** — tablet verified, phone not yet tested end-to-end - [ ] **Stagger validation** — confirm 5-min gap between phone push (04:35) and tablet n8n trigger (04:45) is sufficient on slow networks