french-wiktionary-flashcards

Easily create Anki flashcards from Wiktionary data.
Log | Files | Refs | README

add.go (2171B)


      1 package main
      2 
      3 import (
      4 	"bytes"
      5 	"encoding/json"
      6 	"errors"
      7 	"fmt"
      8 	"io"
      9 	"net/http"
     10 	"strings"
     11 
     12 	tea "github.com/charmbracelet/bubbletea"
     13 )
     14 
     15 const apiVersion = 6
     16 
     17 type addNote struct {
     18 	Action  string        `json:"action"`
     19 	Version int           `json:"version"`
     20 	Params  addNoteParams `json:"params"`
     21 }
     22 
     23 type addNoteParams struct {
     24 	Note note `json:"note"`
     25 }
     26 
     27 type note struct {
     28 	DeckName  string `json:"deckName"`
     29 	ModelName string `json:"modelName"`
     30 	// Fields will not be trivial to generalize
     31 	Fields  fields  `json:"fields"`
     32 	Options options `json:"options"`
     33 }
     34 
     35 type fields struct {
     36 	Front string `json:"Front"`
     37 	Back  string `json:"Back"`
     38 }
     39 
     40 type options struct {
     41 	AllowDuplicate bool   `json:"allowDuplicate"`
     42 	DuplicateScope string `json:"duplicateScope"`
     43 }
     44 
     45 func addCard(c *http.Client, apiURL, deckName, modelName, front, back string) tea.Cmd {
     46 	return func() tea.Msg {
     47 		front = strings.TrimSpace(front)
     48 		// Replace apostrophes (possible if copy-pasting) with single quotes
     49 		front = strings.ReplaceAll(front, `’`, `'`)
     50 		if back == "" {
     51 			return errMsg(errors.New("definition is blank"))
     52 		}
     53 		if front == "" {
     54 			return errMsg(errors.New("word is blank"))
     55 		}
     56 
     57 		noteRequest := addNote{
     58 			Action:  "addNote",
     59 			Version: apiVersion,
     60 			Params: addNoteParams{
     61 				Note: note{
     62 					DeckName:  deckName,
     63 					ModelName: modelName,
     64 					Fields: fields{
     65 						Front: front,
     66 						Back:  back,
     67 					},
     68 					Options: options{
     69 						AllowDuplicate: false,
     70 						DuplicateScope: "deck",
     71 					},
     72 				},
     73 			},
     74 		}
     75 
     76 		jsonBytes, err := json.Marshal(noteRequest)
     77 		if err != nil {
     78 			return errMsg(fmt.Errorf("marshaling JSON: %s", err))
     79 		}
     80 
     81 		req, err := http.NewRequest("POST", apiURL, bytes.NewBuffer(jsonBytes))
     82 		req.Header.Set("Content-Type", "application/json")
     83 
     84 		resp, err := c.Do(req)
     85 		if err != nil {
     86 			return errMsg(fmt.Errorf("making request: %s", err))
     87 		}
     88 		defer resp.Body.Close()
     89 
     90 		body, _ := io.ReadAll(resp.Body)
     91 
     92 		var jsonResp struct {
     93 			Error string `json:"error"`
     94 		}
     95 
     96 		json.Unmarshal(body, &jsonResp)
     97 		if jsonResp.Error != "" {
     98 			return errMsg(fmt.Errorf("creating card: %s", jsonResp.Error))
     99 		}
    100 
    101 		return wordAddedMsg(front)
    102 	}
    103 }