Exporter: XMNote support exporting read time and mark book source#14144
Conversation
|
Hi, sorry to bother you. Perhaps pazos is busy and hasn’t had time to review my code. Would it be possible to assign this review to someone else? Thanks! @Frenzie |
|
I'm not really sure if anybody else knows the Exporter plugin nearly as well but I'll take a quick look. |
| function XMNoteExporter:getBookReadingDurations(id_book) | ||
| local conn = SQ3.open(db_location) |
There was a problem hiding this comment.
I see two presumably fairly minor issues with this:
- It assumes the DB exists, but that's predicated on the statistics plugin being enabled. You'd have to include something like
if not self.ui.statistics then return end. - This seems to look sufficiently generic that most of it should probably be located somewhere else, like ReaderStatistics itself or Exporter base. I'd go for ReaderStatistics itself unless there's a good reason not to.
There was a problem hiding this comment.
The purpose of this query is to align with the field requirements defined by the export App’s API, which makes it fairly specific to the export logic. From a modular perspective, I agree that reading statistics generally belongs in ReaderStatistics. However, since this query is strongly coupled to the API field definitions, I decided to keep it in xmnote.lua to avoid introducing API-specific logic into a generic module.
Would you agree with this reasoning, or do you think it would still be better to move the core query into ReaderStatistics and leave only the API adaptation in xmnote.lua?
There was a problem hiding this comment.
No strong opinion.
It indeed feels strange to have in this "remote" module some SQL query with internal knowledge about how the stats db is set up.
But I'm fine with not having in the statistics plugin tons of functions with SQL queries that are not used in it or by core :)
I wondered what this SQL query returns. I see that it gives results like:
dates last_page durations min_start_time
---------- --------- --------- --------------
2025-09-10 9 78 1757538978
2025-08-31 11 14 1756656993
2025-08-30 11 20 1756560788
2025-08-28 11 46 1756367532
2025-08-25 12 126 1756125006
2025-08-09 14 417 1754694878
So, dunno. If put in the stats plugin, it should have a more explicite name, maybe getBookReadingDurationsByDay(id_book).
There was a problem hiding this comment.
Mainly I was thinking that if this is useful for one export implementation maybe it also is for others. For example for Markdown/HTML the output from the same query could be written as a table at the bottom. But for now let's keep it in here, just with that early return right at the start.
There was a problem hiding this comment.
If multiple export implementations need something from the stats db, may be it could just be an other specific module inside the exporter plugin (with a not in the statistics plugin that there are additional SQL queries in the exporter plugin).
There was a problem hiding this comment.
I did write "or Exporter base." ;-)
There was a problem hiding this comment.
No strong opinion. It indeed feels strange to have in this "remote" module some SQL query with internal knowledge about how the stats db is set up. But I'm fine with not having in the statistics plugin tons of functions with SQL queries that are not used in it or by core :)
I wondered what this SQL query returns. I see that it gives results like:
dates last_page durations min_start_time ---------- --------- --------- -------------- 2025-09-10 9 78 1757538978 2025-08-31 11 14 1756656993 2025-08-30 11 20 1756560788 2025-08-28 11 46 1756367532 2025-08-25 12 126 1756125006 2025-08-09 14 417 1754694878So, dunno. If put in the stats plugin, it should have a more explicite name, maybe
getBookReadingDurationsByDay(id_book).
I’m querying a book’s daily reading stats across all dates, capturing each day’s first reading time, the last page read, and the total reading duration. I’ll also adjust the SQL aliases to make them clearer and easier to understand.
| SELECT | ||
| id | ||
| FROM | ||
| book | ||
| WHERE | ||
| title = "%s" | ||
| LIMIT 1 |
There was a problem hiding this comment.
Not important but for such a simple query this seems a bit silly. :-)
There was a problem hiding this comment.
I’ll change it to a single line. Thanks!
| return reading_durations | ||
| end | ||
|
|
||
| function XMNoteExporter:getBookIdByTitle(title) |
There was a problem hiding this comment.
Rare case, but book title may be not unique.
koreader/plugins/statistics.koplugin/main.lua
Lines 718 to 727 in 105694e
There was a problem hiding this comment.
If needed we can fetch the md5 from doc_settings along with title and author
koreader/plugins/exporter.koplugin/clip.lua
Lines 347 to 352 in af50d71
There was a problem hiding this comment.
I’ll work on optimizing it.
| local util = require("util") | ||
| local ffiUtil = require("ffi/util") | ||
| local datetime = require("datetime") | ||
| local T = ffiUtil.template |
There was a problem hiding this comment.
Could you sort the new additions as per the coding style? https://github.com/koreader/koreader-base/wiki/Coding-style#order-of-requires
datetime
ffiUtil
logger
util
_
T
There was a problem hiding this comment.
Sorry, I haven’t paid attention to that document before. If I had known, I would have done it. I’ll make the changes now!
|
Hello, the CI check for this PR did not pass. After reviewing the logs, the error doesn't appear to be related to my code changes, which only involved adjusting the order of require statements. Would it be possible to manually re-trigger the pipeline? Thank you for your time. |
| end | ||
|
|
||
| function XMNoteExporter:getBookReadingDurationsByDay(id_book) | ||
| if util.fileExists(db_location) then |
There was a problem hiding this comment.
No need to check again, already done in findBookIdByTitleAndMD5().
|
Everything looks correct, just a small note: do we need a separate Of course, if there are plans to get other info from the db in the future, it's okay. |
|
In this case, there’s no need to split it. |
…educe db operations
XMNote users have long requested the ability to export daily reading time records from KOReader. This PR adds support for exporting reading time within the existing XMNote exporter plugin.
Additionally, to help XMNote App better organize imported books, each exported book is now marked with its source as “KOReader”.
This change is