@ashdev/codex-plugin-sync-anilist 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,218 @@
1
+ # @ashdev/codex-plugin-sync-anilist
2
+
3
+ A Codex plugin for syncing manga reading progress between Codex and [AniList](https://anilist.co). Supports push/pull of reading status, volumes/chapters read, scores, dates, and notes.
4
+
5
+ ## Features
6
+
7
+ - Two-way sync of manga reading progress with AniList
8
+ - Push reading status, progress, scores, dates, and notes to AniList
9
+ - Pull updates from AniList back to Codex
10
+ - Configurable progress unit (volumes or chapters)
11
+ - Auto-pause/auto-drop stale series based on reading inactivity
12
+ - Rate limit handling with automatic retry
13
+ - Highest-progress-wins conflict resolution (progress only moves forward)
14
+ - External ID matching via AniList API IDs (`api:anilist`)
15
+
16
+ ## Authentication
17
+
18
+ This plugin supports two authentication methods:
19
+
20
+ ### OAuth (Recommended)
21
+
22
+ If your Codex administrator has configured OAuth:
23
+
24
+ 1. Go to **Settings** > **Integrations**
25
+ 2. Click **Connect with AniList Sync**
26
+ 3. Authorize Codex on AniList
27
+ 4. You're connected!
28
+
29
+ ### Personal Access Token
30
+
31
+ If OAuth is not configured by the admin:
32
+
33
+ 1. Go to [AniList Developer Settings](https://anilist.co/settings/developer)
34
+ 2. Click **Create New Client**
35
+ 3. Set the redirect URL to `https://anilist.co/api/v2/oauth/pin`
36
+ 4. Click **Save**, then **Authorize** your new client
37
+ 5. Copy the token shown on the pin page
38
+ 6. In Codex, go to **Settings** > **Integrations**
39
+ 7. Paste the token in the access token field and click **Save Token**
40
+
41
+ ## Admin Setup
42
+
43
+ ### Adding the Plugin to Codex
44
+
45
+ 1. Log in to Codex as an administrator
46
+ 2. Navigate to **Settings** > **Plugins**
47
+ 3. Click **Add Plugin**
48
+ 4. Fill in the form:
49
+ - **Name**: `sync-anilist`
50
+ - **Display Name**: `AniList Sync`
51
+ - **Command**: `npx`
52
+ - **Arguments**: `-y @ashdev/codex-plugin-sync-anilist@1.9.3`
53
+ 5. Click **Save**
54
+ 6. Click **Test Connection** to verify the plugin works
55
+
56
+ ### Configuring OAuth (Optional)
57
+
58
+ To enable OAuth login for your users:
59
+
60
+ 1. Go to [AniList Developer Settings](https://anilist.co/settings/developer)
61
+ 2. Click **Create New Client**
62
+ 3. Set the redirect URL to `{your-codex-url}/api/v1/user/plugins/oauth/callback`
63
+ 4. Save and copy the **Client ID**
64
+ 5. In Codex, go to **Settings** > **Plugins** > click the gear icon on AniList Sync
65
+ 6. Go to the **OAuth** tab
66
+ 7. Paste the **Client ID** (and optionally the **Client Secret**)
67
+ 8. Click **Save Changes**
68
+
69
+ Without OAuth configured, users can still connect by pasting a personal access token.
70
+
71
+ ### npx Options
72
+
73
+ | Configuration | Arguments | Description |
74
+ |--------------|-----------|-------------|
75
+ | Latest version | `-y @ashdev/codex-plugin-sync-anilist` | Always uses latest |
76
+ | Pinned version | `-y @ashdev/codex-plugin-sync-anilist@1.9.3` | Recommended for production |
77
+ | Fast startup | `-y --prefer-offline @ashdev/codex-plugin-sync-anilist@1.9.3` | Skips version check if cached |
78
+
79
+ ## Configuration
80
+
81
+ ### Codex Sync Settings
82
+
83
+ These settings are managed in the **Sync Settings** section of the plugin settings modal. They control which data the Codex server sends to the plugin and are shared across all sync plugins.
84
+
85
+ | Setting | Default | Description |
86
+ |---------|---------|-------------|
87
+ | Include completed series | On | Include series where all local books are read |
88
+ | Include in-progress series | On | Include series where at least one book has been started |
89
+ | Count partially-read books | Off | Whether partially-read books count toward the progress number |
90
+ | Sync ratings & notes | On | Include user ratings and notes in sync |
91
+
92
+ ### Plugin-Specific Settings
93
+
94
+ These settings are specific to the AniList plugin and appear under **Plugin Settings** in the settings modal.
95
+
96
+ | Setting | Type | Default | Description |
97
+ |---------|------|---------|-------------|
98
+ | Progress Unit | string | `volumes` | Whether each Codex book counts as a "volume" or "chapter" on AniList. Use "volumes" to avoid misleading "Read chapter X" activity on AniList. |
99
+ | Auto-Pause After Days | number | `0` (disabled) | Number of days without reading activity before an in-progress series is set to Paused on AniList |
100
+ | Auto-Drop After Days | number | `0` (disabled) | Number of days without reading activity before an in-progress series is set to Dropped on AniList |
101
+
102
+ ## Using the Plugin
103
+
104
+ Once connected, the sync plugin works automatically:
105
+
106
+ 1. Go to **Settings** > **Integrations**
107
+ 2. Click **Sync Now** to trigger a manual sync
108
+ 3. View sync status including pulled/pushed/applied counts
109
+
110
+ The plugin matches Codex series to AniList entries using external IDs stored in the `series_external_ids` table with the `api:anilist` source.
111
+
112
+ ## Sync Behavior
113
+
114
+ ### Sync Modes
115
+
116
+ You can configure which direction data flows in **Settings** > **Integrations** > **Settings**:
117
+
118
+ | Mode | Description |
119
+ |------|-------------|
120
+ | **Pull & Push** (default) | Import progress from AniList, then export Codex progress to AniList |
121
+ | **Pull Only** | Import progress from AniList without writing anything back |
122
+ | **Push Only** | Export Codex progress to AniList without importing |
123
+
124
+ ### How Sync Works
125
+
126
+ When sync runs in **Pull & Push** mode, it executes two phases in order:
127
+
128
+ 1. **Pull** — Fetches your reading list from AniList, matches entries to Codex series via external IDs, and marks the corresponding books as read in Codex.
129
+ 2. **Push** — Reads your current Codex reading progress and sends it to AniList, overwriting the remote entry.
130
+
131
+ ### Conflict Resolution
132
+
133
+ Codex uses a **highest progress wins** strategy. There is no manual conflict resolution — instead, progress can only move forward:
134
+
135
+ | Scenario | Result |
136
+ |----------|--------|
137
+ | AniList ahead (e.g., 5 vols read) and Codex behind (3 vols read) | Pull marks books 4–5 as read in Codex. Push sends 5 to AniList. Both agree. |
138
+ | Codex ahead (5 vols read) and AniList behind (3 vols read) | Pull tries to mark first 3 as read — already completed, skipped. Push sends 5 to AniList. **Codex wins.** |
139
+ | Both changed differently | Pull applies remote progress first (additive only), then Push sends local state to AniList. Effectively **Codex wins** because push runs last. |
140
+
141
+ Key behaviors:
142
+
143
+ - **Pull is additive only** — it marks unread books as read but never un-reads a book. If you lower your chapter count on AniList, that change is ignored.
144
+ - **Push overwrites the remote** — after pulling, Codex sends its current state to AniList, which may overwrite changes made directly on AniList.
145
+ - **Progress is monotonic** — once a book is marked as read, sync will not undo it. Progress only moves forward.
146
+
147
+ ### Completed Status
148
+
149
+ The plugin is conservative about marking series as "Completed" on AniList:
150
+
151
+ - A series is pushed as **Completed** only when all local books are read **and** the series metadata includes a `total_book_count` that matches.
152
+ - Otherwise, the series is pushed as **Reading** — even if all local books are read — because Codex can't be sure the library contains the full series.
153
+
154
+ ### Rating & Notes Sync
155
+
156
+ When **Sync Ratings & Notes** is enabled in plugin settings:
157
+
158
+ - **Push**: Codex ratings (1-100 scale) and notes are sent to AniList, converted to the user's chosen AniList score format (auto-detected from their profile).
159
+ - **Pull**: AniList scores and notes are imported into Codex, but only when Codex has **no existing rating** for that series. Existing Codex ratings are never overwritten (**Codex wins**).
160
+ - Notes without a score are skipped on pull (Codex requires a rating to store notes).
161
+
162
+ ### Auto-Pause & Auto-Drop
163
+
164
+ You can configure automatic status changes for series you haven't read in a while:
165
+
166
+ | Configuration | Behavior |
167
+ |--------------|----------|
168
+ | Pause=5, Drop=0 | Not read in 5 days -> Paused |
169
+ | Pause=5, Drop=7 | Not read in 5 days -> Paused; not read in 7 days -> Dropped |
170
+ | Pause=5, Drop=3 | Not read in 3 days -> Dropped (drop fires first since threshold is shorter) |
171
+ | Pause=0, Drop=4 | Not read in 4 days -> Dropped (no pause step) |
172
+ | Pause=0, Drop=0 | Disabled (default) |
173
+
174
+ Key behaviors:
175
+
176
+ - **Only affects in-progress series** — completed series are never auto-paused or auto-dropped.
177
+ - **Based on last reading activity** — the timer resets every time you read any book in the series.
178
+ - **Drop takes priority** — if both pause and drop thresholds are met, the series is dropped (not paused).
179
+
180
+ ## Development
181
+
182
+ ```bash
183
+ # Install dependencies
184
+ npm install
185
+
186
+ # Build the plugin
187
+ npm run build
188
+
189
+ # Type check
190
+ npm run typecheck
191
+
192
+ # Run tests
193
+ npm test
194
+
195
+ # Lint
196
+ npm run lint
197
+ ```
198
+
199
+ ## Project Structure
200
+
201
+ ```
202
+ plugins/sync-anilist/
203
+ ├── src/
204
+ │ ├── index.ts # Plugin entry point & staleness logic
205
+ │ ├── index.test.ts # Staleness logic tests
206
+ │ ├── manifest.ts # Plugin manifest
207
+ │ ├── anilist.ts # AniList API client & utility functions
208
+ │ └── anilist.test.ts # API client & utility tests
209
+ ├── dist/
210
+ │ └── index.js # Built bundle (excluded from git)
211
+ ├── package.json
212
+ ├── tsconfig.json
213
+ └── README.md
214
+ ```
215
+
216
+ ## License
217
+
218
+ MIT