Skip to content
Snippets Groups Projects
Select Git revision
  • 70d9f40fab87f9924e4349b944004268177d585e
  • consistent_config default protected
2 results

conf.py

Blame
  • create_from_scratch_with_csv.py 5.84 KiB
    from anki.collection import *
    from anki.import_export_pb2 import *
    import os
    from libfaketime import fake_time, reexec_if_needed
    import csv
    from kanjiconv import KanjiConv
    
    reexec_if_needed() # setup for faking the time later, which may require a restart
    
    # Step 1: create a temporary collection
    try:
        # delete if exists already
        os.remove("temporary.anki2")
        os.remove("temporary.media.db2")
    except OSError:
      pass
    # then start fresh
    col = Collection("temporary.anki2")
    
    # Step 2: add a new note type
    with open("dist/kanji/front.html", "r") as front_file:
      with open("dist/kanji/back.html", "r") as back_file:
        kanji_front_html = front_file.read()
        kanji_back_html = back_file.read()
    with open("dist/hiragana/front.html", "r") as front_file:
      with open("dist/hiragana/back.html", "r") as back_file:
        hiragana_front_html = front_file.read()
        hiragana_back_html = back_file.read()
    hiragana_deck_id = col.decks.add_normal_deck_with_name("Lots of Hiragana").id
    note_type = {
        'id': 0, # the 0 has no effect, the actual ID will be the timestamp at the time of adding the note type
        'name': "My cool note type",
        'type': 0,
        'mod': 0,
        'usn': 0,
        'sortf': 0,
        'did': None,
        'tmpls': [
            {
                'name': 'English to Japanese',
                'ord': 0,
                'qfmt': kanji_front_html,
                'afmt': kanji_back_html,
                'bqfmt': '',
                'bafmt': '',
                'did': None,
                'bfont': '',
                'bsize': 0,
            },
            {
                'name': 'Hiragana to English',
                'ord': 1,
                'qfmt': hiragana_front_html,
                'afmt': hiragana_back_html,
                'bqfmt': '',
                'bafmt': '',
                # Hiragana should ignore the deck below and always be stored in
                # a separate deck
                'did': hiragana_deck_id,
                'bfont': '',
                'bsize': 0,
            }
        ],
        'flds': [
            # Example
            {
                'name': "Front",
                'ord': 0, # Field No.1, this one must always be non-empty
                # not sure what this stuff does, just use CSS for styling
                'sticky': False,
                'rtl': False,
                'font': 'Arial',
                'size': 20,
                'description': '',
                'plainText': False,
                'collapsed': False,
                'excludeFromSearch': False,
                'id': 0,
                'tag': None,
                'preventDeletion': False
            },
            {
                'name': "Back",
                'ord': 1, # Field No.2, can be empty
                'sticky': False,
                'rtl': False,
                'font': 'Arial',
                'size': 20,
                'description': '',
                'plainText': False,
                'collapsed': False,
                'excludeFromSearch': False,
                'id': 1,
                'tag': None,
                'preventDeletion': False
            },
            {
                'name': "Hiragana",
                'ord': 2,
                'sticky': False,
                'rtl': False,
                'font': 'Arial',
                'size': 20,
                'description': '',
                'plainText': False,
                'collapsed': False,
                'excludeFromSearch': False,
                'id': 2,
                'tag': None,
                'preventDeletion': False
            },
            {
                'name': "Fake images",
                'ord': 3,
                'sticky': False,
                'rtl': False,
                'font': 'Arial',
                'size': 20,
                'description': '',
                'plainText': False,
                'collapsed': False,
                'excludeFromSearch': False,
                'id': 3,
                'tag': None,
                'preventDeletion': False
            }
        ],
        'css': '', # instead of putting it into the HTML you could also set CSS here
        # note sure what the rest does
        'latexPre':'\\documentclass[12pt]{article}\n\\special{papersize=3in,5in}\n\\usepackage[utf8]{inputenc}\n\\usepackage{amssymb,amsmath}\n\\pagestyle{empty}\n\\setlength{\\parindent}{0in}\n\\begin{document}\n',
        'latexPost':'\\end{document}',
        'latexSvg': False,
        'req': [
            [
                0,
                'any',
                [ 0 ]
            ]
        ],
        'originalStockKind': 1
    }
    
    # Step 3: add the note type with a predictable ID
    with fake_time("2025-04-07 18:45:00"):
        # add the note in the past (or the future)
        note_type_id = col.models.add_dict(note_type).id
    
    # Step 4: add Kanji data from CSV, and calculate Hiragana
    kanji_conv = KanjiConv(separator="/")
    deck_id = col.decks.add_normal_deck_with_name("Lots of Kanji").id
    with open("jouyou-kanji.csv", "r") as csv_file:
       # make sure to use space as the delimiter (interesting choice but very readable in the raw form)
       # example line: '譜 "musical score" fu'
       csv_lines = csv.reader(csv_file, delimiter=" ")
       for line in csv_lines:
          note = Note(col, note_type_id)
          # make up a unique ID by assuming the Kanjis are unique
          note.guid = f'kanji-{line[0]}'
          # first column is Kanji
          note["Back"] = line[0]
          # second is english translation
          note["Front"] = line[1]
          # calculate Hiragana automatically from Kanji
          note["Hiragana"] = kanji_conv.to_hiragana(line[0])
          # if HanziWriter supports the character, ask Anki to include the JSON-P file for HanziWriter for this Kanji in the APKG export
          hanzi_writer_data = f'./media/{line[0]}.js'
          if os.path.isfile(hanzi_writer_data):
            note["Fake images"] = f'<img src="{line[0]}.js">'
            col.media.add_file(f'./media/{line[0]}.js')
          # save the note
          col.add_note(note, deck_id)
    
    # Step 5: Done, now we just need to export an APKG
    col.export_anki_package(
        # anki fails if this is just an apkg filename without a dir,
        # with ./ it's fine
        out_path="./lots_of_kanji.apkg",
        options=ExportAnkiPackageOptions(
            with_deck_configs=False,
            with_media=True,
            with_scheduling=False,
            legacy=True,
        ),
        limit=None)