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.