66import com .adityachandel .booklore .model .dto .kobo .KoboReadingStateWrapper ;
77import com .adityachandel .booklore .model .dto .kobo .KoboResources ;
88import com .adityachandel .booklore .model .dto .kobo .KoboTestResponse ;
9- import com .adityachandel .booklore .service .* ;
9+ import com .adityachandel .booklore .service .ShelfService ;
1010import com .adityachandel .booklore .service .book .BookDownloadService ;
1111import com .adityachandel .booklore .service .book .BookService ;
1212import com .adityachandel .booklore .service .kobo .*;
@@ -70,53 +70,73 @@ public ResponseEntity<?> syncLibrary(@AuthenticationPrincipal BookLoreUser user)
7070 return koboLibrarySyncService .syncLibrary (user , token );
7171 }
7272
73- @ Operation (summary = "Get book thumbnail" , description = "Retrieve the thumbnail image for a book." )
73+ @ Operation (summary = "Get book thumbnail (versioned)" , description = "Retrieve the thumbnail image for a local book with cache-busting version." )
74+ @ ApiResponse (responseCode = "200" , description = "Thumbnail returned successfully" )
75+ @ GetMapping ("/v1/books/{imageId}/{version}/thumbnail/{width}/{height}/false/image.jpg" )
76+ public ResponseEntity <Resource > getVersionedThumbnail (
77+ @ Parameter (description = "Book ID" ) @ PathVariable String imageId ,
78+ @ Parameter (description = "Cover version (timestamp)" ) @ PathVariable String version ,
79+ @ Parameter (description = "Width of the thumbnail" ) @ PathVariable int width ,
80+ @ Parameter (description = "Height of the thumbnail" ) @ PathVariable int height ) {
81+ return koboThumbnailService .getThumbnail (imageId );
82+ }
83+
84+ @ Operation (summary = "Get book thumbnail" , description = "Retrieve the thumbnail image for a Kobo store book." )
7485 @ ApiResponse (responseCode = "200" , description = "Thumbnail returned successfully" )
7586 @ GetMapping ("/v1/books/{imageId}/thumbnail/{width}/{height}/false/image.jpg" )
7687 public ResponseEntity <Resource > getThumbnail (
7788 @ Parameter (description = "Image ID" ) @ PathVariable String imageId ,
7889 @ Parameter (description = "Width of the thumbnail" ) @ PathVariable int width ,
7990 @ Parameter (description = "Height of the thumbnail" ) @ PathVariable int height ) {
80-
81- if (StringUtils .isNumeric (imageId )) {
82- return koboThumbnailService .getThumbnail (Long .valueOf (imageId ));
91+ if (imageId .startsWith ("BL-" )) {
92+ return koboThumbnailService .getThumbnail (imageId );
8393 } else {
84- String cdnUrl = String .format ("https://cdn.kobo.com/book-images/%s/%d/%d/image.jpg" , imageId , width , height );
94+ String cdnUrl = String .format ("https://cdn.kobo.com/book-images/%s/%d/%d/false/ image.jpg" , imageId , width , height );
8595 return koboServerProxy .proxyExternalUrl (cdnUrl );
8696 }
8797 }
8898
89- @ Operation (summary = "Get greyscale book thumbnail" , description = "Retrieve a greyscale thumbnail image for a book." )
99+ @ Operation (summary = "Get greyscale book thumbnail (versioned) " , description = "Retrieve a greyscale thumbnail for a local book with cache-busting version ." )
90100 @ ApiResponse (responseCode = "200" , description = "Greyscale thumbnail returned successfully" )
91- @ GetMapping ("/v1/books/{bookId}/thumbnail/{width}/{height}/{quality}/{isGreyscale}/image.jpg" )
92- public ResponseEntity <Resource > getGreyThumbnail (
93- @ Parameter (description = "Book ID" ) @ PathVariable String bookId ,
101+ @ GetMapping ("/v1/books/{imageId}/{version}/thumbnail/{width}/{height}/{quality}/{isGreyscale}/image.jpg" )
102+ public ResponseEntity <Resource > getVersionedGreyThumbnail (
103+ @ Parameter (description = "Book ID" ) @ PathVariable String imageId ,
104+ @ Parameter (description = "Cover version (timestamp)" ) @ PathVariable String version ,
94105 @ Parameter (description = "Width of the thumbnail" ) @ PathVariable int width ,
95106 @ Parameter (description = "Height of the thumbnail" ) @ PathVariable int height ,
96107 @ Parameter (description = "Quality of the thumbnail" ) @ PathVariable int quality ,
97108 @ Parameter (description = "Is greyscale" ) @ PathVariable boolean isGreyscale ) {
109+ return koboThumbnailService .getThumbnail (imageId );
110+ }
98111
99- if (StringUtils .isNumeric (bookId )) {
100- return koboThumbnailService .getThumbnail (Long .valueOf (bookId ));
112+ @ Operation (summary = "Get greyscale book thumbnail" , description = "Retrieve a greyscale thumbnail image for a Kobo store book." )
113+ @ ApiResponse (responseCode = "200" , description = "Greyscale thumbnail returned successfully" )
114+ @ GetMapping ("/v1/books/{imageId}/thumbnail/{width}/{height}/{quality}/{isGreyscale}/image.jpg" )
115+ public ResponseEntity <Resource > getGreyThumbnail (
116+ @ Parameter (description = "Image ID" ) @ PathVariable String imageId ,
117+ @ Parameter (description = "Width of the thumbnail" ) @ PathVariable int width ,
118+ @ Parameter (description = "Height of the thumbnail" ) @ PathVariable int height ,
119+ @ Parameter (description = "Quality of the thumbnail" ) @ PathVariable int quality ,
120+ @ Parameter (description = "Is greyscale" ) @ PathVariable boolean isGreyscale ) {
121+ if (imageId .startsWith ("BL-" )) {
122+ return koboThumbnailService .getThumbnail (imageId );
101123 } else {
102- String cdnUrl = String .format ("https://cdn.kobo.com/book-images/%s/%d/%d/%d/%b/image.jpg" , bookId , width , height , quality , isGreyscale );
124+ String cdnUrl = String .format ("https://cdn.kobo.com/book-images/%s/%d/%d/%d/%b/image.jpg" , imageId , width , height , quality , isGreyscale );
103125 return koboServerProxy .proxyExternalUrl (cdnUrl );
104126 }
105127 }
106128
107129 @ Operation (summary = "Authenticate Kobo device" , description = "Authenticate a Kobo device." )
108130 @ ApiResponse (responseCode = "200" , description = "Device authenticated successfully" )
109131 @ PostMapping ("/v1/auth/device" )
110- public ResponseEntity <KoboAuthentication > authenticateDevice (
111- @ Parameter (description = "Authentication request body" ) @ RequestBody JsonNode body ) {
132+ public ResponseEntity <KoboAuthentication > authenticateDevice (@ Parameter (description = "Authentication request body" ) @ RequestBody JsonNode body ) {
112133 return koboDeviceAuthService .authenticateDevice (body );
113134 }
114135
115136 @ Operation (summary = "Get book metadata" , description = "Retrieve metadata for a book in the Kobo library." )
116137 @ ApiResponse (responseCode = "200" , description = "Metadata returned successfully" )
117138 @ GetMapping ("/v1/library/{bookId}/metadata" )
118- public ResponseEntity <?> getBookMetadata (
119- @ Parameter (description = "Book ID" ) @ PathVariable String bookId ) {
139+ public ResponseEntity <?> getBookMetadata (@ Parameter (description = "Book ID" ) @ PathVariable String bookId ) {
120140 if (StringUtils .isNumeric (bookId )) {
121141 return ResponseEntity .ok (List .of (koboEntitlementService .getMetadataForBook (Long .parseLong (bookId ), token )));
122142 } else {
@@ -127,8 +147,7 @@ public ResponseEntity<?> getBookMetadata(
127147 @ Operation (summary = "Get reading state" , description = "Retrieve the reading state for a book." )
128148 @ ApiResponse (responseCode = "200" , description = "Reading state returned successfully" )
129149 @ GetMapping ("/v1/library/{bookId}/state" )
130- public ResponseEntity <?> getState (
131- @ Parameter (description = "Book ID" ) @ PathVariable String bookId ) {
150+ public ResponseEntity <?> getState (@ Parameter (description = "Book ID" ) @ PathVariable String bookId ) {
132151 if (StringUtils .isNumeric (bookId )) {
133152 return ResponseEntity .ok (koboReadingStateService .getReadingState (bookId ));
134153 } else {
@@ -152,8 +171,7 @@ public ResponseEntity<?> updateState(
152171 @ Operation (summary = "Get Kobo test analytics" , description = "Get test analytics for Kobo." )
153172 @ ApiResponse (responseCode = "200" , description = "Test analytics returned successfully" )
154173 @ PostMapping ("/v1/analytics/gettests" )
155- public ResponseEntity <?> getTests (
156- @ Parameter (description = "Test analytics request body" ) @ RequestBody Object body ) {
174+ public ResponseEntity <?> getTests (@ Parameter (description = "Test analytics request body" ) @ RequestBody Object body ) {
157175 return ResponseEntity .ok (KoboTestResponse .builder ()
158176 .result ("Success" )
159177 .testKey (RandomStringUtils .secure ().nextAlphanumeric (24 ))
@@ -163,8 +181,7 @@ public ResponseEntity<?> getTests(
163181 @ Operation (summary = "Download Kobo book" , description = "Download a book from the Kobo library." )
164182 @ ApiResponse (responseCode = "200" , description = "Book downloaded successfully" )
165183 @ GetMapping ("/v1/books/{bookId}/download" )
166- public void downloadBook (
167- @ Parameter (description = "Book ID" ) @ PathVariable String bookId , HttpServletResponse response ) {
184+ public void downloadBook (@ Parameter (description = "Book ID" ) @ PathVariable String bookId , HttpServletResponse response ) {
168185 if (StringUtils .isNumeric (bookId )) {
169186 bookDownloadService .downloadKoboBook (Long .parseLong (bookId ), response );
170187 } else {
@@ -175,8 +192,7 @@ public void downloadBook(
175192 @ Operation (summary = "Delete book from Kobo library" , description = "Delete a book from the user's Kobo library." )
176193 @ ApiResponse (responseCode = "200" , description = "Book deleted successfully" )
177194 @ DeleteMapping ("/v1/library/{bookId}" )
178- public ResponseEntity <?> deleteBookFromLibrary (
179- @ Parameter (description = "Book ID" ) @ PathVariable String bookId ) {
195+ public ResponseEntity <?> deleteBookFromLibrary (@ Parameter (description = "Book ID" ) @ PathVariable String bookId ) {
180196 if (StringUtils .isNumeric (bookId )) {
181197 Shelf userKoboShelf = shelfService .getUserKoboShelf ();
182198 if (userKoboShelf != null ) {
0 commit comments