package main import ( "encoding/json" "fmt" "log" "net/http" "os" "strings" "foosoft.net/projects/jmdict" "git.elnu.com/ElnuDev/jichanorg/httputils" "github.com/gorilla/mux" ) var dict jmdict.Jmdict func LoadDict() error { const jmdictFile = "JMdict.xml" reader, err := os.Open(jmdictFile) if err != nil { return err } dict, _, err = jmdict.LoadJmdict(reader) if err != nil { return err } return nil } type Entry struct { Kanji string Reading string Definitions []Definition } type Definition struct { Definition string PartOfSpeech []string } func ParseEntry(entry jmdict.JmdictEntry) Entry { kanji := "" if len(entry.Kanji) > 0 { kanji = entry.Kanji[0].Expression } reading := "" if len(entry.Readings) > 0 { reading = entry.Readings[0].Reading } var definitions []Definition definitions = make([]Definition, len(entry.Sense)) for i, sense := range entry.Sense { definition := sense.Glossary[0].Content if len(sense.Glossary) > 1 { for _, glossary := range sense.Glossary[1:] { definition += "; " + glossary.Content } } definitions[i] = Definition{ Definition: definition, PartOfSpeech: sense.PartsOfSpeech, } } return Entry{ Kanji: kanji, Reading: reading, Definitions: definitions, } } func Search(query string) []Entry { query = strings.TrimSpace(query) entries := make([]Entry, 0) for _, jmdictEntry := range dict.Entries { for _, kanji := range jmdictEntry.Kanji { if kanji.Expression == query { goto match } } for _, reading := range jmdictEntry.Readings { if reading.Reading == query { goto match } } continue match: entry := ParseEntry(jmdictEntry) entries = append(entries, entry) } return entries } func main() { err := LoadDict() if err != nil { fmt.Println(err) return } fmt.Println("JMdict loaded!") r := mux.NewRouter() r.HandleFunc("/api/search", httputils.GenerateHandler( "search.html", func(w http.ResponseWriter, r *http.Request) bool { if r.Header.Get("Accept") != "application/json" { return true } w.Header().Set("Content-Type", "application/json; charset=utf-8") r.ParseMultipartForm(0) query := r.FormValue("q") entries := Search(query) jsonBytes, _ := json.Marshal(entries) fmt.Fprint(w, string(jsonBytes)) return false }, func(w http.ResponseWriter, r *http.Request) any { r.ParseMultipartForm(0) query := r.FormValue("q") entry := Search(query) return entry }, []string{http.MethodGet, http.MethodPost}, )) r.Handle("/", http.FileServer(http.Dir("static"))) log.Fatal(http.ListenAndServe(":3334", r)) }