Want to contribute? Fork me on Codeberg.org!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

125 lines
2.6 KiB

package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"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
if len(entry.Sense) > 0 && len(entry.Sense[0].Glossary) > 0 {
definitions = make([]Definition, len(entry.Sense[0].Glossary))
for i, glossary := range entry.Sense[0].Glossary {
var pos string
if len(entry.Sense[0].PartsOfSpeech) > i+1 {
pos = entry.Sense[0].PartsOfSpeech[i]
}
definitions[i] = Definition{
Definition: glossary.Content,
PartOfSpeech: pos,
}
}
}
return Entry{
Kanji: kanji,
Reading: reading,
Definitions: definitions,
}
}
func Search(query string) []Entry {
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))
}