Documentation ¶
Overview ¶
Package anki provides a library to read *.apkg files produced by Anki (http://ankisrs.net/).
A *.apkg file is simply a zip-compressed archive, which contains a the following files:
- collection.anki2 -- An SQLite3 database
- media -- A JSON blob mapping media file filenames to numbers
- [files numbered 0..n] -- Media files (referenced in the media file above)
The SQLite3 Database contains the following tables. Detailed explanations of each column's use can be found inline below, in the struct definitions.
CREATE TABLE col ( id integer primary key, crt integer not null, mod integer not null, scm integer not null, ver integer not null, dty integer not null, usn integer not null, ls integer not null, conf text not null, models text not null, decks text not null, dconf text not null, tags text not null ); CREATE TABLE notes ( id integer primary key, /* 0 */ guid text not null, /* 1 */ mid integer not null, /* 2 */ mod integer not null, /* 3 */ usn integer not null, /* 4 */ tags text not null, /* 5 */ flds text not null, /* 6 */ sfld integer not null, /* 7 */ csum integer not null, /* 8 */ flags integer not null, /* 9 */ data text not null /* 10 */ ); CREATE TABLE cards ( id integer primary key, /* 0 */ nid integer not null, /* 1 */ did integer not null, /* 2 */ ord integer not null, /* 3 */ mod integer not null, /* 4 */ usn integer not null, /* 5 */ type integer not null, /* 6 */ queue integer not null, /* 7 */ due integer not null, /* 8 */ ivl integer not null, /* 9 */ factor integer not null, /* 10 */ reps integer not null, /* 11 */ lapses integer not null, /* 12 */ left integer not null, /* 13 */ odue integer not null, /* 14 */ odid integer not null, /* 15 */ flags integer not null, /* 16 */ data text not null /* 17 */ ); CREATE TABLE graves ( usn integer not null, oid integer not null, type integer not null ); CREATE TABLE revlog ( id integer primary key, cid integer not null, usn integer not null, ease integer not null, ivl integer not null, lastIvl integer not null, factor integer not null, time integer not null, type integer not null );
When it is obvious that a column is no longer used by Anki, it is ommitted from these Go data structures. When it is not obvious, it is included, but typically with a comment to the effect that its use is unknown. If you know of any inaccuracies or recent changes to the Anki schema, please create an issue.
Index ¶
- Constants
- type Apkg
- type BoolInt
- type Card
- type CardConstraint
- type CardQueue
- type CardType
- type Cards
- type Collection
- type Config
- type DB
- type Deck
- type DeckConfig
- type DeckConfigs
- type Decks
- type DurationDays
- type DurationMilliseconds
- type DurationMinutes
- type DurationSeconds
- type Field
- type FieldValues
- type ID
- type LeechAction
- type Model
- type ModelType
- type Models
- type NewCardOrder
- type Note
- type Notes
- type Review
- type ReviewEase
- type ReviewType
- type Reviews
- type Tags
- type Template
- type TimestampMilliseconds
- type TimestampSeconds
Constants ¶
const FieldValuesDelimiter = "\x1f"
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Apkg ¶
type Apkg struct {
// contains filtered or unexported fields
}
Apkg manages state of an Anki package file during processing.
func ReadBytes ¶
ReadBytes reads an *.apkg file from a bytestring, returning an Apkg struct for processing.
func ReadReader ¶
ReadReader reads an *.apkg file from an io.Reader, returning an Apkg struct for processing.
func (*Apkg) Cards ¶
Cards returns a Cards struct represeting all of the non-deleted cards in the *.apkg package file.
func (*Apkg) Close ¶
Close closes any opened resources (io.Reader, SQLite handles, etc). Any subsequent calls to extant objects (Collection, Decks, Notes, etc) which depend on these resources may fail. Only call this method after you're completely done reading the Apkg file.
func (*Apkg) Collection ¶
func (a *Apkg) Collection() (*Collection, error)
type BoolInt ¶
type BoolInt bool
BoolInt represents a boolean value stored as an int
func (*BoolInt) UnmarshalJSON ¶
UnmarshalJSON implements the json.Unmarshaler interface for the BoolInt type.
type Card ¶
type Card struct { ID ID `db:"id"` // Primary key NoteID ID `db:"nid"` // Foreign Key to a Note DeckID ID `db:"did"` // Foreign key to a Deck TemplateID int `db:"ord"` // The Template ID, within the Model, to which this card corresponds. Modified *TimestampSeconds `db:"mod"` // Last modified time UpdateSequence int `db:"usn"` // Update sequence number Type CardType `db:"type"` // Card type: new, learning, due Queue CardQueue `db:"queue"` // Queue: suspended, user buried, sched buried Due *TimestampSeconds `db:"due"` // Time when the card is next due Interval *DurationSeconds `db:"ivl"` // SRS interval in seconds Factor float32 `db:"factor"` // SRS factor ReviewCount int `db:"reps"` // Number of reviews Lapses int `db:"lapses"` // Number of times card went from "answered correctly" to "answered incorrectly" state Left int `db:"left"` // Reviews remaining until graduation OriginalDue *TimestampSeconds `db:"odue"` // Original due time. Only used when card is in filtered deck. OriginalDeckID ID `db:"odid"` // Original Deck ID. Only used when card is in filtered deck. }
Card definition
This definition excludes the `flags` and `data` fields, which are no longer used. Additionally, this definition modifies the original senses of `due`, `odue`, and `ivl` by converting them to a consistent representation. `Specifically
`due` and `odue` are stored in one of three states:
- For card queue 0 (new), the due time is ignored. Here we convert it to 0.
- For card queue 1 (learning), the due time is stored as seconds since epoch. We leave this as-is.
- For card queue 2 (due), the due time is stored as days since the collection was created. We convert this to seconds since epoch.
`ivl` is stored either as negative seconds, or as positive days. We convert both to positive seconds.
func (*Card) Created ¶
func (c *Card) Created() *TimestampMilliseconds
Returns the cards's creation timestamp (based on its ID)
type CardConstraint ¶
type CardConstraint struct { Index int // Card index MatchType string // "any" or "all" Fields []int // Array of fields which must exist }
A card constraint defines which fields are necessary for a particular card type to be generated. This is (apparently) auto-calculated whenever a note is created or modified.
func (*CardConstraint) UnmarshalJSON ¶
func (c *CardConstraint) UnmarshalJSON(src []byte) error
UnmarshalJSON implements the json.Unmarshaler interface for the CardConstraint type
type CardQueue ¶
type CardQueue int
const ( CardQueueSchedBuried CardQueue = -3 // Sched Buried (??, possibly unused) CardQueueBuried CardQueue = -2 // Buried CardQueueSuspended CardQueue = -1 // Suspended CardQueueNew CardQueue = 0 // New/Cram CardQueueLearning CardQueue = 1 // Learning CardQueueReview CardQueue = 2 // Review CardQueueRelearning CardQueue = 3 // Day Learn (Relearn?) )
CardQueue specifies the card's queue type
See https://github.com/dae/anki/blob/master/anki/sched.py#L17 and https://github.com/dae/anki/blob/master/anki/cards.py#L14
type Cards ¶
Cards is a wrapper around sqlx.Rows, which means that any standard sqlx.Rows or sql.Rows methods may be called on it. Generally, you should only ever need to call Next() and Close(), in addition to Card() which is defined in this package.
type Collection ¶
type Collection struct { ID ID `db:"id"` // Primary key; should always be 1, as there's only ever one collection per *.apkg file Created *TimestampSeconds `db:"crt"` // Created timestamp (seconds) Modified *TimestampMilliseconds `db:"mod"` // Last modified timestamp (milliseconds) SchemaModified *TimestampMilliseconds `db:"scm"` // Schema modification time (milliseconds) Version int `db:"ver"` // Version? Dirty BoolInt `db:"dty"` // Dirty? No longer used. See https://github.com/dae/anki/blob/master/anki/collection.py#L90 UpdateSequence int `db:"usn"` // update sequence number. used to figure out diffs when syncing LastSync *TimestampMilliseconds `db:"ls"` // Last sync time (milliseconds) Config Config `db:"conf"` // JSON blob containing configuration options Models Models `db:"models"` // JSON array of json objects containing the models (aka Note types) Decks Decks `db:"decks"` // JSON array of json objects containing decks DeckConfigs DeckConfigs `db:"dconf"` // JSON blob containing deck configuration options Tags string `db:"tags"` // a cache of tags used in the collection }
Collection is an Anki Collection, stored in the `col` table.
type Config ¶
type Config struct { NextPos int `json:"nextPos"` EstimateTimes bool `json:"estTimes"` ActiveDecks []ID `json:"activeDecks"` // Array of active decks(?) SortType string `json:"sortType"` TimeLimit DurationSeconds `json:"timeLimit"` SortBackwards BoolInt `json:"sortBackwards"` AddToCurrent bool `json:"addToCur"` // Add new cards to current deck(?) CurrentDeck ID `json:"curDeck"` NewBury bool `json:"newBury"` NewSpread int `json:"newSpread"` DueCounts bool `json:"dueCounts"` CurrentModel ID `json:"curModel"` CollapseTime int `json:"collapseTime"` }
Config represents basic global configuration for the Anki client.
type DB ¶
func OpenOriginalDB ¶
func (*DB) Collection ¶
func (db *DB) Collection() (*Collection, error)
type Deck ¶
type Deck struct { ID ID `json:"id"` // Deck ID Name string `json:"name"` // Deck name Description string `json:"desc"` // Deck description Modified *TimestampSeconds `json:"mod"` // Last modification time in seconds UpdateSequence int `json:"usn"` // Update sequence number. Used in the same way as the other USN values Collapsed bool `json:"collapsed"` // True when the deck is collapsed BrowserCollapsed bool `json:"browserCollapsed"` // True when the deck is collapsed in the browser ExtendedNewCardLimit int `json:"extendedNew"` // Extended new card limit for custom study ExtendedReviewCardLimit int `json:"extendedRev"` // Extended review card limit for custom study Dynamic BoolInt `json:"dyn"` // True for a dynamic (aka filtered) deck ConfigID ID `json:"conf"` // ID of option group from dconf in `col` table NewToday [2]int `json:"newToday"` // two number array used somehow for custom study ReviewsToday [2]int `json:"revToday"` // two number array used somehow for custom study LearnToday [2]int `json:"lrnToday"` // two number array used somehow for custom study TimeToday [2]int `json:"timeToday"` // two number array used somehow for custom study (in ms) Config *DeckConfig `json:"-"` }
A Deck definition
func (*Deck) Created ¶
func (d *Deck) Created() *TimestampMilliseconds
Returns the deck's creation timestamp (based on its ID)
type DeckConfig ¶
type DeckConfig struct { ID ID `json:"id"` // Deck ID Name string `json:"name"` // Deck Name ReplayAudio bool `json:"replayq"` // When answer shown, replay both question and answer audio ShowTimer BoolInt `json:"timer"` // Show answer timer MaxAnswerSeconds int `json:"maxTaken"` // Ignore answers that take longer than this many seconds Modified *TimestampSeconds `json:"mod"` // Modified timestamp AutoPlay bool `json:"autoplay"` // Automatically play audio Lapses struct { LeechFails int `json:"leechFails"` // Leech threshold MinimumInterval DurationDays `json:"minInt"` // Minimum interval in days LeechAction LeechAction `json:"leechAction"` // Leech action: Suspend or Tag Only Delays []DurationMinutes `json:"delays"` // Steps in minutes NewInterval float32 `json:"mult"` // New Interval Multiplier } `json:"lapse"` Reviews struct { PerDay int `json:"perDay"` // Maximum reviews per day Fuzz float32 `json:"fuzz"` // Apparently not used? IntervalModifier float32 `json:"ivlFct"` // Interval modifier (fraction) MaxInterval DurationDays `json:"maxIvl"` // Maximum interval in days EasyBonus float32 `json:"ease4"` // Easy bonus Bury bool `json:"bury"` // Bury related reviews until next day } `json:"rev"` New struct { PerDay int `json:"perDay"` // Maximum new cards per day Delays []DurationMinutes `json:"delays"` // Steps in minutes Bury bool `json:"bury"` // Bury related cards until the next day Separate bool `json:"separate"` // Unused?? Intervals [3]DurationDays `json:"ints"` // Intervals?? InitialFactor float32 `json:"initialFactor"` // Starting Ease Order NewCardOrder `json:"order"` // New card order: Random, or order added } `json:"new"` }
Per-Deck configuration options.
Excluded from this definition is the `minSpace` field from Reviews, as it is no longer used.
type DeckConfigs ¶
type DeckConfigs map[ID]*DeckConfig
Collection of per-deck configurations
func (*DeckConfigs) Scan ¶
func (dc *DeckConfigs) Scan(src interface{}) error
Scan implements the sql.Scanner interface for the DeckConfigs type.
func (*DeckConfigs) UnmarshalJSON ¶
func (dc *DeckConfigs) UnmarshalJSON(src []byte) error
UnmarshalJSON implements the json.Unmarshaler interface for the DeckConfigs type.
type Decks ¶
A collection of Decks
func (*Decks) UnmarshalJSON ¶
UnmarshalJSON implements the json.Unmarshaler interface for the Decks type.
type DurationDays ¶
type DurationDays int
DurationDays represents a duration in days.
func (*DurationDays) Scan ¶
func (d *DurationDays) Scan(src interface{}) error
type DurationMilliseconds ¶
DurationMilliseconds represents a time.Duration value stored as milliseconds.
func (*DurationMilliseconds) Scan ¶
func (d *DurationMilliseconds) Scan(src interface{}) error
Scan implements the sql.Scanner interface for the DurationMilliseconds type.
type DurationMinutes ¶
DurationMinutes represents a time.Duration value stored as minutes.
func (*DurationMinutes) Scan ¶
func (d *DurationMinutes) Scan(src interface{}) error
Scan implements the sql.Scanner interface for the DurationMinutes type.
type DurationSeconds ¶
DurationSeconds represents a time.Duration value stored as seconds.
func (*DurationSeconds) Scan ¶
func (d *DurationSeconds) Scan(src interface{}) error
Scan implements the sql.Scanner interface for the DurationSeconds type.
type Field ¶
type Field struct { Name string `json:"name"` // Field name Sticky bool `json:"sticky"` // Sticky fields retain the value that was last added when adding new notes RTL bool `json:"rtl"` // boolean to indicate if this field uses Right-to-Left script Ordinal int `json:"ord"` // Ordinal of the field. Goes from 0 to num fields -1. Font string `json:"font"` // Display font FontSize int `json:"size"` // Font size }
A field of a model
Excluded from this definition is the `media` field, which appears to no longer be used.
type FieldValues ¶
type FieldValues []string
func (*FieldValues) Scan ¶
func (fv *FieldValues) Scan(src interface{}) error
Scan implements the sql.Scanner interface for the FieldValues type.
type ID ¶
type ID int64
ID represents an Anki object ID (deck, card, note, etc) as an int64.
func (*ID) UnmarshalJSON ¶
UnmarshalJSON implements the json.Unmarshaler interface for the ID type.
type LeechAction ¶
type LeechAction int
Enum of available leech actions
const ( LeechActionSuspendCard LeechAction = iota LeechActoinTagOnly )
type Model ¶
type Model struct { ID ID `json:"id"` // Model ID Name string `json:"name"` // Model name Tags []string `json:"tags"` // Anki saves the tags of the last added note to the current model DeckID ID `json:"did"` // Deck ID of deck where cards are added by default Fields []*Field `json:"flds"` // Array of Field objects SortField int `json:"sortf"` // Integer specifying which field is used for sorting in the browser Templates []*Template `json:"tmpls"` Type ModelType `json:"type"` // Model type: Standard or Cloze LatexPre string `json:"latexPre"` // preamble for LaTeX expressions LatexPost string `json:"latexPost"` // String added to end of LaTeX expressions (usually \\end{document}) CSS string `json:"css"` // CSS, shared for all templates Modified *TimestampSeconds `json:"mod"` // Modification time in seconds RequiredFields []*CardConstraint `json:"req"` // Array of card constraints describing which fields are required for each card to be generated UpdateSequence int `json:"usn"` // Update sequence number: used in same way as other usn vales in db }
Model (aka Note Type)
Excluded from this definition is the `vers` field, which is no longer used by Anki.
func (*Model) Created ¶
func (m *Model) Created() *TimestampMilliseconds
Returns the model's creation timestamp (based on its ID)
type ModelType ¶
type ModelType int
Enum representing the available Note Type Types (confusing, eh?)
type Models ¶
Models is a collection of Models (aka note types), stored as JSON in the `models` column of the `col` table.
func (*Models) UnmarshalJSON ¶
UnmarshalJSON implements the json.Unmarshaler interface for the Models type.
type NewCardOrder ¶
type NewCardOrder int
Enum of new card order options
const ( NewCardOrderOrderAdded NewCardOrder = iota NewCardOrderRandomOrder )
type Note ¶
type Note struct { ID ID `db:"id"` // Primary key GUID string `db:"guid"` // globally unique id, almost certainly used for syncing ModelID ID `db:"mid"` // Model ID Modified *TimestampSeconds `db:"mod"` // Last modified time UpdateSequence int `db:"usn"` // Update sequence number (no longer used?) Tags string `db:"tags"` // List of the note's tags FieldValues FieldValues `db:"flds"` // Values for the note's fields UniqueField string `db:"sfld"` // The text of the first field, used for Anki's simplistic uniqueness checking Checksum int64 `db:"csum"` // Field checksum used for duplicate check. Integer representation of first 8 digits of sha1 hash of the first field }
Note definition
Excludes the `flags` and `data` columns, which are no longer used
func (*Note) Created ¶
func (n *Note) Created() *TimestampMilliseconds
Returns the notes's creation timestamp (based on its ID)
type Notes ¶
Notes is a wrapper around sqlx.Rows, which means that any standard sqlx.Rows or sql.Rows methods may be called on it. Generally, you should only ever need to call Next() and Close(), in addition to Note() which is defined in this package.
type Review ¶
type Review struct { Timestamp *TimestampSeconds `db:"id"` // Times when the review was done CardID ID `db:"cid"` // Foreign key to a Card UpdateSequence int `db:"usn"` // Update sequence number Ease ReviewEase `db:"ease"` // Button pushed to score recall: wrong, hard, ok, easy Interval DurationSeconds `db:"ivl"` // SRS interval in seconds LastInterval DurationSeconds `db:"lastIvl"` // Prevoius SRS interval in seconds Factor float32 `db:"factor"` // SRS factor ReviewTime DurationMilliseconds `db:"time"` // Time spent on the review Type ReviewType `db:"type"` // Review type: learn, review, relearn, cram }
Review definition
`ivl` is stored either as negative seconds, or as positive days. We convert both to positive seconds.
type ReviewEase ¶
type ReviewEase int
const ( ReviewEaseWrong ReviewEase = 1 ReviewEaseHard ReviewEase = 2 ReviewEaseOK ReviewEase = 3 ReviewEaseEasy ReviewEase = 4 )
type ReviewType ¶
type ReviewType int
const ( ReviewTypeLearn ReviewType = iota ReviewTypeReview ReviewTypeRelearn ReviewTypeCram )
type Template ¶
type Template struct { Name string `json:"name"` // Template name Ordinal int `json:"ord"` // Template number QuestionFormat string `json:"qfmt"` // Question format AnswerFormat string `json:"afmt"` // Answer format BrowserQuestionFormat string `json:"bqfmt"` // Browser question format BrowserAnswerFormat string `json:"bafmt"` // Browser answer format DeckOverride ID `json:"did"` // Deck override (null by default) (??) }
A Template definition. A template definition represents a single card type, and is stored as part of a Model.
type TimestampMilliseconds ¶
TimestampMilliseconds represents a time.Time value stored as milliseconds.
func (*TimestampMilliseconds) Scan ¶
func (t *TimestampMilliseconds) Scan(src interface{}) error
Scan implements the sql.Scanner interface for the TimestampMilliseconds type.
type TimestampSeconds ¶
TimestampSeconds represents a time.Time value stored as seconds.
func (*TimestampSeconds) Scan ¶
func (t *TimestampSeconds) Scan(src interface{}) error
Scan implements the sql.Scanner interface for the TimestampSeconds type.
func (*TimestampSeconds) UnmarshalJSON ¶
func (t *TimestampSeconds) UnmarshalJSON(src []byte) error
UnmarshalJSON implements the json.Unmarshaler interface for the TimestampSeconds type.