Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Kobo Database Schema

This document describes the Kobo SQLite database schema and the key tables used by the plugin.

Database Location

The Kobo database is located at:

/mnt/onboard/.kobo/KoboReader.sqlite

Key Tables

Content Table

The primary table containing book and chapter information.

Relevant Fields

FieldTypePurposeExample
ContentIDTEXTUnique identifier (PRIMARY KEY)"0N3773Z7HFPXB"
ContentTypeINTEGER6 = Book entry, 9 = Chapter entry6
BookTitleTEXTBook title"The Great Gatsby"
AttributionTEXTAuthor information"F. Scott Fitzgerald"
___PercentReadINTEGERReading progress (0-100)67
___FileOffsetINTEGERCumulative percentage where chapter starts50 (chapter starts at 50%)
___FileSizeINTEGERPercentage size of this chapter10 (chapter is 10% of book)
DateLastReadTEXTLast reading timestamp (ISO 8601)"2024-01-15 14:30:00.000+00:00"
ReadStatusINTEGERReading status code (see below)1
ChapterIDBookmarkedTEXTCurrent chapter bookmark"chapter1.html#kobo.1.1"

ReadStatus Codes

0 = Unread/Unopened  -- Book never opened
1 = Reading          -- Currently reading
2 = Finished         -- Book completed
3 = Reading (alt)    -- Alternative reading status

ContentType Values

6 = Book entry       -- Main book record
9 = Chapter entry    -- Individual chapter records

Content Keys Table

The content_keys table stores encrypted decryption keys for DRM-protected books. Used by the virtual library to detect KDRM-encrypted books.

Schema

CREATE TABLE content_keys (
    volumeId TEXT NOT NULL,
    elementId TEXT NOT NULL,
    elementKey TEXT,
    PRIMARY KEY (volumeId, elementId)
);
CREATE INDEX content_keys_volume ON content_keys (volumeId);

Fields

FieldTypePurposeExample
volumeIdTEXTBook identifier (matches ContentID)"0N3773Z7HFPXB"
elementIdTEXTFile identifier within EPUB (part of PK)"chapter1.xhtml"
elementKeyTEXTEncrypted content key for decrypting the file(encrypted blob)

Index

The content_keys_volume index on volumeId enables O(1) lookups for DRM detection. This makes the database query in isBookEncrypted() extremely fast, as it only needs to check if any row exists for a given volumeId.

Usage in DRM detection:

SELECT 1 FROM content_keys WHERE volumeId = ? LIMIT 1

If rows exist, the book is KDRM-encrypted. If no rows exist, the book is DRM-free (typically sideloaded).

See: DRM Detection Documentation

Timestamp Format

Kobo uses ISO 8601 format:

2024-01-15 14:30:00.000+00:00

The plugin converts between Unix timestamps and this format:

-- Parse Kobo timestamp to Unix timestamp
function parseKoboTimestamp(date_string)
    local year, month, day, hour, min, sec =
        date_string:match("(%d+)-(%d+)-(%d+)[T ](%d+):(%d+):(%d+)")
    return os.time({
        year = tonumber(year),
        month = tonumber(month),
        day = tonumber(day),
        hour = tonumber(hour),
        min = tonumber(min),
        sec = tonumber(sec),
    })
end

-- Format Unix timestamp to Kobo format
function formatKoboTimestamp(timestamp)
    return os.date("!%Y-%m-%d %H:%M:%S.000+00:00", timestamp)
end