Skip to content

fix(kobo): update resources to match live values#1502

Merged
imnotjames merged 1 commit into
grimmory-tools:developfrom
imnotjames:fix/1500/update-resources-kobo
May 26, 2026
Merged

fix(kobo): update resources to match live values#1502
imnotjames merged 1 commit into
grimmory-tools:developfrom
imnotjames:fix/1500/update-resources-kobo

Conversation

@imnotjames

@imnotjames imnotjames commented May 25, 2026

Copy link
Copy Markdown
Contributor

Description

Moves the kobo resources to a "resource" & updates to the current live list of resources

Linked Issue

fixes #1500

Changes

  • creates a resource kobo/resources.json for storing JSON string
  • updates kobo/resources.json to match live values

Manual Testing Steps

  1. spin up local server
  2. update kobo device to point at local server
  3. disable forward to rakuten
  4. run sync

Screenshots (Optional)

Additional Context (Optional)

AI Disclosure

None

Checklist

  • This PR links and implements an accepted issue.
  • This PR is a single focused change.
  • There are new or updated tests validating this change.
  • I ran just ui check and just api check.
  • I have added screenshots if there were any UI changes.
  • I have disclosed any AI usage as per the organization AI Policy above.
  • I understand all of my submitted changes.

Summary by CodeRabbit

  • Refactor
    • Reorganized Kobo resource configuration by extracting hardcoded data into a separate external resource file, improving maintainability and making configuration more accessible without code changes.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

KoboResourcesComponent refactors from embedding large Kobo resource JSON directly in code to loading it from an external classpath file. A new helper method loads kobo/resources.json as UTF-8 with error logging and fallback. The getResources() method now parses the external resource file. All resource URLs and configuration flags move to the new JSON file.

Changes

Kobo Resources Externalization

Layer / File(s) Summary
Classpath resource loading support
backend/src/main/java/org/booklore/service/kobo/KoboResourcesComponent.java
Adds @Slf4j annotation and imports. Private helper getFileFromClassPath() loads files from classpath as UTF-8, logs IOException, and returns "{}" on failure.
Update getResources() to use external resource
backend/src/main/java/org/booklore/service/kobo/KoboResourcesComponent.java
getResources() calls the helper to load kobo/resources.json, parses it into an ObjectNode via objectMapper.readTree(), and returns the result.
Kobo resources JSON configuration
backend/src/main/resources/kobo/resources.json
Complete resource file with Kobo endpoint templates (library sync, metadata, auth, analytics), host URLs, localized free-books pages (EN/FR/IT/NL/PT), blackstone headers, and feature flags (kobo_*_enabled, display_*_enabled, cache, link/account integrations).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested labels

backend, enhancement

Suggested reviewers

  • balazs-szucs
  • zachyale
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title follows the conventional commit format with 'fix' type and clear scope/subject.
Description check ✅ Passed The description includes all required sections (Description, Linked Issue, Changes, Manual Testing Steps, AI Disclosure, Checklist) with substantive content.
Linked Issues check ✅ Passed The changes directly address issue #1500 by moving Kobo resources to an external JSON file and updating values to match live endpoints needed for device sync.
Out of Scope Changes check ✅ Passed All changes are directly related to resolving issue #1500; modifications refactor resource loading and ensure complete endpoint availability without unrelated alterations.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
✨ Simplify code
  • Create PR with simplified code

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@imnotjames imnotjames marked this pull request as ready for review May 25, 2026 12:29

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/src/main/java/org/booklore/service/kobo/KoboResourcesComponent.java`:
- Around line 24-31: Replace the unsafe runtime assert in
KoboResourcesComponent's resource-loading block with an explicit null check:
after calling getResourceAsStream(path) in the try-with-resources, test if is ==
null and if so log an error (using log.error with context like the path) and
return the fallback ("{}") immediately; then proceed to readAllBytes only when
the stream is non-null so NullPointerException is avoided and the IOException
catch remains meaningful.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 059485f4-7fec-43db-982b-20392d68972d

📥 Commits

Reviewing files that changed from the base of the PR and between 673f008 and 1dcbcce.

📒 Files selected for processing (2)
  • backend/src/main/java/org/booklore/service/kobo/KoboResourcesComponent.java
  • backend/src/main/resources/kobo/resources.json
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Packaging Smoke Test
🧰 Additional context used
📓 Path-based instructions (3)
**/*

⚙️ CodeRabbit configuration file

**/*: This project is being developed using current and future-facing technologies:

  • Java 25 with --enable-preview (preview features are INTENTIONAL and encouraged)
  • Spring Boot 4 (latest major version, check APIs accordingly)
  • Jackson 3 (new package: tools.jackson.* instead of com.fasterxml.jackson.*)
  • Hibernate 7.3.x (Jakarta Persistence 3.2, new APIs; avoid deprecated Hibernate 5/6 patterns)
  • Angular 21 (signals-based reactivity, no NgModules unless legacy)

Grimmory Internal Tools

Metadata Standards and Compliance

  • For all metadata writing and parsing logic, double-check against Dublin Core and ANSI standards to ensure perfect official compliance.
  • We strictly follow the widespread and official XML-compliant methods for EPUB2, EPUB3, CBX, and PDF formats.

General Java and Spring rules

  • ALWAYS prefer modern, idiomatic Java 25 constructs over legacy patterns.
  • Preview features (--enable-preview) are enabled and intentional; do NOT flag them as risky unless there is a concrete runtime issue.
  • Prefer: records, sealed classes/interfaces, pattern matching (switch expressions, instanceof), structured concurrency (StructuredTaskScope), scoped values, string templates, unnamed patterns/variables.
  • Prefer virtual threads (Thread.ofVirtual(), Executors.newVirtualThreadPerTaskExecutor()) over platform threads for I/O-bound work.
  • Prefer the new Sequenced Collections API (SequencedCollection, SequencedMap) where applicable.
  • Prefer var for local variables when the type is obvious from context.
  • Use stream().toList() instead of stream().collect(Collectors.toList()) for imm...

Files:

  • backend/src/main/resources/kobo/resources.json
  • backend/src/main/java/org/booklore/service/kobo/KoboResourcesComponent.java
backend/src/**/*.java

📄 CodeRabbit inference engine (AGENTS.md)

backend/src/**/*.java: Use 4-space indentation and match surrounding Java style in backend code
Prefer constructor injection via Lombok patterns already used in the codebase. Do not introduce @Autowired field injection in backend code
Use MapStruct for entity/DTO mapping in backend code
Keep JPA entities on the *Entity suffix in backend code

Files:

  • backend/src/main/java/org/booklore/service/kobo/KoboResourcesComponent.java
**/service/**/*.java

⚙️ CodeRabbit configuration file

**/service/**/*.java: Spring Framework 7 service layer review:

  • Flag missing @Transactional on methods that perform multiple writes.
  • Prefer constructor injection over @Autowired field injection. Use @AllArgsConstructor.
  • Use ApiError enum for throwing exceptions.
  • Flag checked exceptions swallowed silently; must log or rethrow.
  • Flag Thread.sleep(); prefer Duration-based overloads or ScheduledExecutorService.
  • Prefer virtual threads (Thread.ofVirtual()) for I/O-bound operations.
  • Flag mutable shared state in singleton beans.

Files:

  • backend/src/main/java/org/booklore/service/kobo/KoboResourcesComponent.java
🧠 Learnings (10)
📚 Learning: 2026-05-18T14:54:39.422Z
Learnt from: alexhb1
Repo: grimmory-tools/grimmory PR: 1379
File: frontend/src/assets/styles/tailwind.css:3-4
Timestamp: 2026-05-18T14:54:39.422Z
Learning: In the grimmory-tools/grimmory repository, Biome is not used for linting/formatting (no `biome.json` and no Biome dependency in `package.json`). During code reviews, do not raise Biome-related issues or recommend adding/changing `biome.json`/Biome dependencies for formatting or linting in this project.

Applied to files:

  • backend/src/main/resources/kobo/resources.json
📚 Learning: 2026-04-10T08:15:37.436Z
Learnt from: imnotjames
Repo: grimmory-tools/grimmory PR: 449
File: booklore-api/src/main/java/org/booklore/service/book/BookDownloadService.java:139-145
Timestamp: 2026-04-10T08:15:37.436Z
Learning: When using Spring `ContentDisposition.builder(...).filename(name, StandardCharsets.UTF_8).build()` (i.e., explicitly providing UTF-8), the resulting header value should include both the quoted `filename="=?UTF-8?..."` and the RFC 5987 `filename*=` parameters. In this case, any extra ASCII fallback computation (e.g., deriving an ASCII `fallbackFilename` via `NON_ASCII_PATTERN` and calling `.filename(fallbackFilename)`) is likely redundant—prefer calling only `.filename(fallbackName?, StandardCharsets.UTF_8)` as appropriate and let Spring handle the UTF-8 header parameters. Verify by comparing the emitted header for `filename` and `filename*` before deciding to keep an ASCII fallback.

Applied to files:

  • backend/src/main/java/org/booklore/service/kobo/KoboResourcesComponent.java
📚 Learning: 2026-04-14T12:43:08.698Z
Learnt from: balazs-szucs
Repo: grimmory-tools/grimmory PR: 502
File: booklore-api/src/main/java/org/booklore/service/reader/ChapterCacheService.java:0-0
Timestamp: 2026-04-14T12:43:08.698Z
Learning: For this codebase (booklore-api), target Java 25 with `--enable-preview`, so `_` is intentionally used as an unnamed/ignored variable (e.g., lambda parameter or pattern variable) per Java’s preview feature JEP 456. Do not flag `_` in those contexts as an invalid/reserved identifier; only flag it if it’s used in a non-supported position (e.g., where an unnamed variable is not applicable for the Java preview rules).

Applied to files:

  • backend/src/main/java/org/booklore/service/kobo/KoboResourcesComponent.java
📚 Learning: 2026-05-07T21:21:55.233Z
Learnt from: imnotjames
Repo: grimmory-tools/grimmory PR: 1194
File: backend/src/main/java/org/booklore/service/ReadingSessionService.java:0-0
Timestamp: 2026-05-07T21:21:55.233Z
Learning: When reviewing Java 23+ code, treat `java.time.Instant#until(Instant endExclusive)` as a valid API/method call (it returns a `Duration`, equivalent to `Duration.between(this, endExclusive)`). Do not flag `instant.until(otherInstant)` as a compile error or API misuse when the project targets Java 25+ (as in grimmory-tools/grimmory); the call should be considered correct and returns a `Duration`.

Applied to files:

  • backend/src/main/java/org/booklore/service/kobo/KoboResourcesComponent.java
📚 Learning: 2026-05-08T06:19:20.621Z
Learnt from: imnotjames
Repo: grimmory-tools/grimmory PR: 1201
File: backend/src/main/java/org/booklore/model/dto/AccessTokenDto.java:3-10
Timestamp: 2026-05-08T06:19:20.621Z
Learning: For Jackson 3 codebases, do not treat imports from `com.fasterxml.jackson.annotation.*` (e.g., `JsonInclude`, `JsonProperty`, `JsonView`) as incorrect. In Jackson 3, `jackson-annotations` intentionally remains under `com.fasterxml.jackson.annotation.*` for backward compatibility, while only the core processing packages (e.g., `jackson-core`, `jackson-databind`) move to the `tools.jackson.*` namespace.

Applied to files:

  • backend/src/main/java/org/booklore/service/kobo/KoboResourcesComponent.java
📚 Learning: 2026-05-04T20:31:11.075Z
Learnt from: imnotjames
Repo: grimmory-tools/grimmory PR: 1086
File: backend/src/main/java/org/booklore/service/metadata/BookReviewUpdateService.java:63-66
Timestamp: 2026-05-04T20:31:11.075Z
Learning: For this repository, reviewers should treat string truncation done via `String.length()` and `String.substring(0, maxLength)` (UTF-16 code units) as an accepted, consistent convention. Do not flag individual occurrences of this pattern as bugs, even though it is not code-point-aware for surrogate pairs. A separate global effort is already tracked to move toward code-point-aware truncation, so per-site fixes should be avoided during code review.

Applied to files:

  • backend/src/main/java/org/booklore/service/kobo/KoboResourcesComponent.java
📚 Learning: 2026-05-13T12:34:49.607Z
Learnt from: balazs-szucs
Repo: grimmory-tools/grimmory PR: 1293
File: backend/src/main/java/org/booklore/service/metadata/DuckDuckGoCoverService.java:246-252
Timestamp: 2026-05-13T12:34:49.607Z
Learning: In this repo’s Java code, when catching Jsoup `org.jsoup.HttpStatusException` (and similar exceptions originating from external libraries) and wrapping/rethrowing them, do not require preserving the original exception stack trace (e.g., as flagged by PMD `PreserveStackTrace`) as long as the application already captures the actionable diagnostics in logs or the thrown exception message (such as HTTP status code and the requested URL). Reviewers should still ensure the log/message contains those details; the intent is to avoid noisy stack traces that only reflect external-library internals rather than application code.

Applied to files:

  • backend/src/main/java/org/booklore/service/kobo/KoboResourcesComponent.java
📚 Learning: 2026-05-17T13:38:16.462Z
Learnt from: balazs-szucs
Repo: grimmory-tools/grimmory PR: 1366
File: backend/src/main/java/org/booklore/service/FileStreamingService.java:65-66
Timestamp: 2026-05-17T13:38:16.462Z
Learning: In the grimmory-tools/grimmory repo, it’s an accepted pattern to pass the raw AccessDeniedException.getMessage() (even if it may include filesystem path details) into ApiError.PERMISSION_DENIED.createException(...). During code review, do not raise a security/information-disclosure issue solely based on that exception message being propagated to the API when using ApiError.PERMISSION_DENIED.createException with the AccessDeniedException message.

Applied to files:

  • backend/src/main/java/org/booklore/service/kobo/KoboResourcesComponent.java
📚 Learning: 2026-05-23T23:01:25.769Z
Learnt from: imnotjames
Repo: grimmory-tools/grimmory PR: 1456
File: backend/src/main/java/org/booklore/service/metadata/parser/GoodReadsParser.java:618-630
Timestamp: 2026-05-23T23:01:25.769Z
Learning: In this codebase (grimmory-tools/grimmory), it’s intentional to omit per-request timeouts on individual Java HttpRequest.Builder instances (e.g., GoodReadsParser.fetchJson). During reviews, do not flag missing builder-level timeouts as a best-practice violation; rely on framework-level and/or HttpClient-level timeouts configured elsewhere for consistent behavior. Only raise an issue if you can verify that no effective timeout is configured at the HttpClient/framework level.

Applied to files:

  • backend/src/main/java/org/booklore/service/kobo/KoboResourcesComponent.java
📚 Learning: 2026-05-07T21:37:46.988Z
Learnt from: imnotjames
Repo: grimmory-tools/grimmory PR: 1194
File: backend/src/main/java/org/booklore/service/ReadingSessionService.java:121-123
Timestamp: 2026-05-07T21:37:46.988Z
Learning: In grimmory-tools/grimmory service-layer code, if arithmetic overflow occurs inside inference/business-logic (e.g., when deriving inferred fields like durationSeconds from start/end timestamps), treat it as a server-side anomaly. Prefer letting the global exception handler translate it into a generic 5xx response rather than throwing an explicit ApiError 4xx (e.g., do not convert overflow into a client error).

Applied to files:

  • backend/src/main/java/org/booklore/service/kobo/KoboResourcesComponent.java
🪛 Betterleaks (1.2.0)
backend/src/main/resources/kobo/resources.json

[high] 131-131: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🔇 Additional comments (1)
backend/src/main/resources/kobo/resources.json (1)

1-196: LGTM!

@imnotjames imnotjames merged commit 3211d78 into grimmory-tools:develop May 26, 2026
17 checks passed
@imnotjames imnotjames deleted the fix/1500/update-resources-kobo branch May 26, 2026 04:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Kobo Sync Initialization payload is out of date

2 participants