|
| 1 | +# Libby Downloader - Development Guide |
| 2 | + |
| 3 | +This document provides context for AI assistants (Claude) working on this codebase. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +A TypeScript CLI tool for downloading audiobooks from Libby with realistic user simulation to minimize detection risk. Built as a safer, more responsible alternative to the original TamperMonkey script. |
| 8 | + |
| 9 | +## Architecture |
| 10 | + |
| 11 | +### Core Modules |
| 12 | + |
| 13 | +1. **auth/** - Authentication and session management |
| 14 | + - `libby-auth.ts` - Manual login flow, cookie persistence |
| 15 | + |
| 16 | +2. **browser/** - Puppeteer automation with stealth |
| 17 | + - `manager.ts` - Browser lifecycle, session management |
| 18 | + - `stealth.ts` - User behavior simulation (mouse, scrolling, delays) |
| 19 | + |
| 20 | +3. **downloader/** - Libby API interaction and chapter downloading |
| 21 | + - `libby-api.ts` - Data extraction via JSON.parse hooks, BIF object access |
| 22 | + - `chapter-downloader.ts` - Sequential downloads with rate limiting |
| 23 | + |
| 24 | +4. **processor/** - Audio processing |
| 25 | + - `ffmpeg-processor.ts` - Chapter merging, metadata, chapter markers |
| 26 | + |
| 27 | +5. **metadata/** - ID3 tag embedding |
| 28 | + - `embedder.ts` - Cover art, metadata embedding with node-id3 |
| 29 | + |
| 30 | +6. **utils/** - Shared utilities |
| 31 | + - `delay.ts` - Random delays, sleep functions |
| 32 | + - `fs.ts` - File operations, sanitization |
| 33 | + - `logger.ts` - Structured logging |
| 34 | + - `rate-limiter.ts` - Three-mode rate limiting (safe/balanced/aggressive) |
| 35 | + |
| 36 | +7. **types/** - TypeScript definitions |
| 37 | + - Shared interfaces for books, chapters, configs |
| 38 | + |
| 39 | +8. **cli.ts** - Main CLI entry point using Commander.js |
| 40 | + |
| 41 | +## Key Technical Decisions |
| 42 | + |
| 43 | +### Why Puppeteer? |
| 44 | + |
| 45 | +- Real browser context prevents detection |
| 46 | +- Access to Libby's internal objects (BIF, odreadCmptParams) |
| 47 | +- Cookie persistence for session reuse |
| 48 | +- Stealth plugins for anti-detection |
| 49 | + |
| 50 | +### Why Sequential Downloads? |
| 51 | + |
| 52 | +- Parallel downloads are easily detected (original script's issue) |
| 53 | +- Humans read/listen sequentially, not all-at-once |
| 54 | +- Variable timing between chapters mimics real behavior |
| 55 | + |
| 56 | +### Rate Limiting Strategy |
| 57 | + |
| 58 | +- **Safe mode**: 8-20s delays, breaks every 3 chapters (1 book/hour max) |
| 59 | +- **Balanced mode**: 4-12s delays, breaks every 5 chapters (2 books/hour) |
| 60 | +- **Aggressive mode**: 2-6s delays, minimal breaks (5 books/hour) - HIGH RISK |
| 61 | + |
| 62 | +### Why Not Use Libby's API Directly? |
| 63 | + |
| 64 | +- No documented public API |
| 65 | +- Authentication is complex |
| 66 | +- TamperMonkey approach (hooking internal data) is proven |
| 67 | +- Browser context provides authenticated session automatically |
| 68 | + |
| 69 | +## Code Patterns |
| 70 | + |
| 71 | +### Error Handling |
| 72 | + |
| 73 | +- Use try/catch with logger.error() |
| 74 | +- Clean up resources in finally blocks |
| 75 | +- Provide helpful error messages to CLI users |
| 76 | + |
| 77 | +### Async Operations |
| 78 | + |
| 79 | +- All I/O operations are async |
| 80 | +- Use await for sequential operations |
| 81 | +- Rate limiter enforces delays between operations |
| 82 | + |
| 83 | +### Type Safety |
| 84 | + |
| 85 | +- Strict TypeScript mode enabled |
| 86 | +- Explicit interfaces for all data structures |
| 87 | +- No `any` types except for page.evaluate() contexts |
| 88 | + |
| 89 | +## Development Workflow |
| 90 | + |
| 91 | +### Running Locally |
| 92 | + |
| 93 | +```bash |
| 94 | +npm run dev -- login # Test login flow |
| 95 | +npm run dev -- list # Test book listing |
| 96 | +npm run dev -- download <id> # Test download (use safe mode!) |
| 97 | +``` |
| 98 | + |
| 99 | +### Before Committing |
| 100 | + |
| 101 | +```bash |
| 102 | +npm run check-all # Type check + lint + format + test |
| 103 | +``` |
| 104 | + |
| 105 | +### Pre-commit Hook |
| 106 | + |
| 107 | +Automatically formats and lints staged files. |
| 108 | + |
| 109 | +### Pre-push Hook |
| 110 | + |
| 111 | +Runs full validation suite before push. |
| 112 | + |
| 113 | +## Testing Strategy |
| 114 | + |
| 115 | +### Unit Tests |
| 116 | + |
| 117 | +- Focus on pure functions (utils/delay.ts, utils/fs.ts) |
| 118 | +- Mock external dependencies (Puppeteer, FFmpeg) |
| 119 | + |
| 120 | +### Integration Tests |
| 121 | + |
| 122 | +- Test rate limiter behavior |
| 123 | +- Test metadata embedding with sample files |
| 124 | + |
| 125 | +### Manual Testing |
| 126 | + |
| 127 | +- Always test downloads in safe mode first |
| 128 | +- Use test library card if possible |
| 129 | +- Monitor for detection/bans |
| 130 | + |
| 131 | +## Important Constraints |
| 132 | + |
| 133 | +### Security & Ethics |
| 134 | + |
| 135 | +- Tool is for educational purposes only |
| 136 | +- Users accept all responsibility for ToS violations |
| 137 | +- Emphasize detection risks in all documentation |
| 138 | +- No bypassing of DRM (only downloading already-accessible content) |
| 139 | + |
| 140 | +### Performance |
| 141 | + |
| 142 | +- Sequential downloads are intentionally slow |
| 143 | +- Rate limiting is critical for detection avoidance |
| 144 | +- FFmpeg operations can be memory-intensive |
| 145 | + |
| 146 | +### Dependencies |
| 147 | + |
| 148 | +- Requires FFmpeg installed on system (not bundled) |
| 149 | +- Large Puppeteer install (~300MB with Chromium) |
| 150 | +- Node-ID3 for metadata (simpler than FFmpeg metadata) |
| 151 | + |
| 152 | +## Common Issues |
| 153 | + |
| 154 | +### "Not logged in" errors |
| 155 | + |
| 156 | +- Cookie expiration - re-run login |
| 157 | +- Check ~/.libby-downloader/cookies.json exists |
| 158 | + |
| 159 | +### TypeScript errors in page.evaluate() |
| 160 | + |
| 161 | +- page.evaluate() runs in browser context (DOM types) |
| 162 | +- Use `(window as any)` for custom properties |
| 163 | +- Cast functions to `any` when needed for flexibility |
| 164 | + |
| 165 | +### FFmpeg not found |
| 166 | + |
| 167 | +- User must install separately (Homebrew, apt, etc.) |
| 168 | +- Check with `ffmpeg -version` before processing |
| 169 | + |
| 170 | +### Rate limit warnings |
| 171 | + |
| 172 | +- User tried to download too fast |
| 173 | +- Enforce cooldown periods |
| 174 | +- Suggest safe mode |
| 175 | + |
| 176 | +## Code Style |
| 177 | + |
| 178 | +### Formatting |
| 179 | + |
| 180 | +- Prettier with single quotes, 100 char width |
| 181 | +- 2-space indentation |
| 182 | +- Trailing commas (ES5 style) |
| 183 | + |
| 184 | +### Naming |
| 185 | + |
| 186 | +- PascalCase for classes |
| 187 | +- camelCase for functions/variables |
| 188 | +- SCREAMING_SNAKE_CASE for constants |
| 189 | +- Descriptive names over brevity |
| 190 | + |
| 191 | +### Comments |
| 192 | + |
| 193 | +- Explain "why", not "what" |
| 194 | +- TSDoc for public APIs |
| 195 | +- Inline comments for tricky logic only |
| 196 | + |
| 197 | +## Future Improvements |
| 198 | + |
| 199 | +### Potential Features |
| 200 | + |
| 201 | +- Resume interrupted downloads |
| 202 | +- Multiple library card support |
| 203 | +- Download queue management |
| 204 | +- Better chapter title detection |
| 205 | +- M4B output format option |
| 206 | + |
| 207 | +### Detection Avoidance Enhancements |
| 208 | + |
| 209 | +- ML-based timing patterns |
| 210 | +- Adaptive rate limiting based on success |
| 211 | +- Session replay from real user behavior |
| 212 | +- Proxy rotation support |
| 213 | + |
| 214 | +## Maintenance Notes |
| 215 | + |
| 216 | +### When Libby Changes |
| 217 | + |
| 218 | +- Monitor `BIF` object structure (core data source) |
| 219 | +- Check `odreadCmptParams` hook still works |
| 220 | +- Update selectors for shelf/book pages |
| 221 | +- Test login flow for changes |
| 222 | + |
| 223 | +### Dependency Updates |
| 224 | + |
| 225 | +- Puppeteer: Check for breaking changes in page API |
| 226 | +- Node-ID3: Verify metadata compatibility |
| 227 | +- FFmpeg: Test chapter merging still works |
| 228 | + |
| 229 | +## Resources |
| 230 | + |
| 231 | +- Original LibbyRip: https://github.com/PsychedelicPalimpsest/LibbyRip |
| 232 | +- Puppeteer Docs: https://pptr.dev |
| 233 | +- FFmpeg Docs: https://ffmpeg.org/documentation.html |
| 234 | +- Libby Web App: https://libbyapp.com |
| 235 | + |
| 236 | +## Contributing |
| 237 | + |
| 238 | +When adding new features: |
| 239 | + |
| 240 | +1. Create feature branch from main |
| 241 | +2. Write tests first (TDD when possible) |
| 242 | +3. Implement feature |
| 243 | +4. Update documentation |
| 244 | +5. Run `npm run check-all` |
| 245 | +6. Create pull request with clear description |
| 246 | + |
| 247 | +## Support and Issues |
| 248 | + |
| 249 | +- GitHub Issues: For bug reports and feature requests |
| 250 | +- Include: OS, Node version, error logs, steps to reproduce |
| 251 | +- Privacy: Never share library card details or personal info |
0 commit comments