class Anki2
Constants
- SEPARATOR
- VERSION
Attributes
options[RW]
Public Class Methods
new(options = {})
click to toggle source
# File lib/anki2.rb, line 14 def initialize(options = {}) @options = { output_path: File.join('anki', 'deck.apkg'), name: 'Anki2 Rubygem Deck', template_sql_path: File.join(File.dirname(__FILE__), 'template.sql'), }.merge(options) @options[:model_name] = @options[:name] unless @options[:model_name] @options[:css] = default_css + @options[:css].to_s @options[:model] = model_config.call(default_model) if block_given? @media = [] FileUtils.mkdir_p(File.dirname(@options[:output_path])) @tmpdir = Dir.mktmpdir @db = SQLite3::Database.open(File.join(@tmpdir, 'collection.anki2')) @db.execute_batch File.read(@options[:template_sql_path]) @top_deck_id = rand(10**13) decks = @db.execute('select decks from col') decks = JSON.parse(decks.first.first.gsub('\"', '"')) deck = decks.delete(decks.keys.last) deck['name'] = @options[:name] deck['id'] = @top_deck_id decks[@top_deck_id.to_s] = deck @db.execute('update col set decks=? where id=1', decks.to_json) @top_model_id = rand(10**13) models = @db.execute('select models from col') models = JSON.parse(models.first.first.gsub('\"', '"')) model = models.delete(models.keys.first) if @options[:model] model = @options[:model] else model['name'] = @options[:model_name] model['css'] = @options[:css] end model['did'] = @top_deck_id model['id'] = @top_model_id models[@top_model_id.to_s] = model @db.execute('update col set models=? where id=1', models.to_json) end
Public Instance Methods
add_card(front, back, tags = [], deck = nil)
click to toggle source
# File lib/anki2.rb, line 85 def add_card(front, back, tags = [], deck = nil) if deck.is_a?(String) deck = [@options[:name], deck].join('::') puts deck deck_id = find_or_create_deck(deck) elsif deck.is_a?(Integer) deck_id = deck else deck_id = @top_deck_id end note_id = rand(10**13) tags = tags.map { |t| t.tr(' ','_')}.join(' ') @db.execute "insert into notes values(?,?,?,?,?,?,?,?,?,?,?)", note_id, rand(10**10).to_s(36), @top_model_id, Time.now.to_i,-1, tags, front + SEPARATOR + back, strip_html(front), checksum(strip_html(front+SEPARATOR+back)), 0,'' @db.execute "insert into cards values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", rand(10**13), note_id, deck_id, 0, Time.now.to_i, -1,0,0,179,0,0,0,0,0,0,0,0,'' true end
add_media(media_path)
click to toggle source
# File lib/anki2.rb, line 122 def add_media(media_path) if File.directory?(media_path) Dir.glob(File.join(media_path, '**.**')).each do |single_media_path| copy_media(single_media_path) end else copy_media(media_path) end end
find_or_create_deck(deck_name)
click to toggle source
# File lib/anki2.rb, line 60 def find_or_create_deck(deck_name) existing_decks = {} decks = @db.execute('select decks from col') decks = JSON.parse(decks.first.first.gsub('\"', '"')) decks.each_pair do |id, deck| next if id.eql?(1) existing_decks[deck['name']] = id end if existing_decks.keys.any? { |name| name.eql?(deck_name) } id = existing_decks[deck_name] else id = rand(10**13) new_deck = decks[decks.keys.last] new_deck['name'] = deck_name new_deck['id'] = id decks[id.to_s] = new_deck @db.execute('update col set decks=? where id=1', decks.to_json) add_model_for_deck(id) end id end
save()
click to toggle source
# File lib/anki2.rb, line 132 def save tmp_media = [] @media.each do |media| tmp_media << '"' + media[:index] + '": "' + media[:filename] + '"' end File.open(File.join(@tmpdir, 'media'), 'a') { |f| f.puts '{' + tmp_media.join(', ') + '}' } FileUtils.mkdir_p(File.dirname(@options[:output_path])) File.delete(@options[:output_path]) if File.exist?(@options[:output_path]) Zip::File.open(@options[:output_path], Zip::File::CREATE) do |zip| Dir.glob(File.join(@tmpdir, '**')).each do |file_path| zip.add(File.basename(file_path), file_path) end end @db.close if @db FileUtils.rm_rf(@tmpdir) if File.exist?(@tmpdir) @options[:output_path] end
Private Instance Methods
add_model_for_deck(deck_id)
click to toggle source
# File lib/anki2.rb, line 155 def add_model_for_deck(deck_id) model_id = rand(10**13) models = @db.execute('select models from col') models = JSON.parse(models.first.first.gsub('\"', '"')) model = models[models.keys.first] model['name'] = @options[:model_name] model['did'] = deck_id model['id'] = model_id model['css'] = @options[:css] models[model_id.to_s] = model model_id end
checksum(str)
click to toggle source
# File lib/anki2.rb, line 176 def checksum(str) Digest::SHA1.hexdigest(str)[0...8].to_i(16) end
copy_media(source_path)
click to toggle source
# File lib/anki2.rb, line 168 def copy_media(source_path) raise Errno::ENOENT.new(source_path) unless File.exist?(source_path) destination_path = File.join(@tmpdir, @media.count.to_s) FileUtils.cp(source_path, destination_path) @media << { index: @media.count.to_s, filename: File.basename(source_path) } true end
default_css()
click to toggle source
# File lib/anki2.rb, line 184 def default_css <<-CSS .card { font-family: arial; font-size: 20px; text-align: center; color: black; } CSS end
default_model()
click to toggle source
# File lib/anki2.rb, line 195 def default_model { 'name' => 'Anki2 Rubygem Template', 'flds' => [ { 'name' => 'Front', 'rtl' => false, 'sticky' => false, 'media' => [], 'ord' => 0, 'font' => 'Arial', 'size' => 12 }, { 'name' => 'Back', 'rtl' => false, 'sticky' => false, 'media' => [], 'ord' => 0, 'font' => 'Arial', 'size' => 12 } ], 'tmpls' => [ { 'name' => 'Forward', 'qfmt' => '{{Front}}', 'did' => nil, 'bafmt' => '', 'afmt' => '{{Back}}', 'ord' => 0, 'bqfmt' => '' } ], } end
strip_html(str)
click to toggle source
# File lib/anki2.rb, line 180 def strip_html(str) str end