main.go (2847B)
1 // This program looks up words from Wiktionary, and creates Anki flashcards 2 // from them. 3 package main 4 5 import ( 6 "database/sql" 7 "errors" 8 "flag" 9 "log" 10 "net/http" 11 "os" 12 "time" 13 14 tea "github.com/charmbracelet/bubbletea" 15 _ "github.com/mattn/go-sqlite3" 16 ) 17 18 func main() { 19 rawDict := flag.String( 20 "rawDictionary", 21 "raw-wiktextract-data.jsonl", 22 "Path to the raw wiktionary data. You can get this by downloading and gunzipping https://kaikki.org/frwiktionary/raw-wiktextract-data.jsonl.gz (for French).", 23 ) 24 dict := flag.String( 25 "dictionary", 26 "dictionary.sqlite3", 27 "Path to the parsed dictionary data. This will be generated from rawDictionary.", 28 ) 29 deckName := flag.String( 30 "deck", 31 "", 32 "Name of the deck where new Anki cards will be created.", 33 ) 34 modelName := flag.String( 35 "model", 36 "", 37 "Name of the card type ('model') for new Anki cards.", 38 ) 39 apiURL := flag.String( 40 "apiURL", 41 "http://localhost:8765", 42 "Base URL to access the anki-connect plugin API.", 43 ) 44 initialWord := flag.String("initialWord", 45 "", 46 "Optional: first word to look up on program launch.", 47 ) 48 autoSync := flag.Bool( 49 "autosync", 50 false, 51 "Whether to sync automatically with Ankiweb", 52 ) 53 54 flag.Parse() 55 56 if *dict == "" { 57 log.Fatal("The -dictionary flag cannot be empty. (Defaults to dictionary.sqlite3.)") 58 } 59 60 if *rawDict == "raw-wiktextract-data.jsonl" { 61 // Check if we have a sqlite dictionary first 62 if _, err := os.Stat(*dict); errors.Is(err, os.ErrNotExist) { 63 // If we don't have a sqlite3 dictionary, that's okay, but, we're 64 // going to have to read the rawDictionary in order to create it. 65 // So, make sure that it exists! 66 if _, err := os.Stat("./raw-wiktextract-data.jsonl"); errors.Is(err, os.ErrNotExist) { 67 log.Fatal("Could not find raw dictionary data file! You can get this by downloading and gunzipping https://kaikki.org/frwiktionary/raw-wiktextract-data.jsonl.gz.") 68 } 69 } 70 } 71 if *deckName == "" { 72 log.Fatal("The -deck flag must be provided (name of the deck where Anki cards will be created).") 73 } 74 if *modelName == "" { 75 log.Fatal("The -model flag must be provided. This is the name of the card type ('model') for any Anki cards created by this program. This appears under 'Type' on the dialog for creating new cards in Anki.") 76 } 77 78 db, err := sql.Open("sqlite3", *dict) 79 if err != nil { 80 log.Fatalf("Failed to create or open dictionary at '%s': %s", *dict, err) 81 } 82 defer db.Close() 83 if err = setupTables(db); err != nil { 84 log.Fatalf("Failed to create database tables in dictionary '%s': %s", *dict, err) 85 } 86 87 c := http.DefaultClient 88 c.Timeout = 5 * time.Second 89 90 p := tea.NewProgram(initialModel(c, db, *apiURL, *deckName, *modelName, *rawDict, *initialWord, *autoSync)) 91 if _, err := p.Run(); err != nil { 92 log.Fatalf("Unexpected error encountered while running program: %s", err) 93 } 94 }