From 1331f3b5642f521236fcb1ec21ee43d5b76c0b91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Sun, 14 Apr 2019 22:30:40 +0200 Subject: Move commands under cmd/ --- cmd/sklad/main.go | 271 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 cmd/sklad/main.go (limited to 'cmd/sklad/main.go') diff --git a/cmd/sklad/main.go b/cmd/sklad/main.go new file mode 100644 index 0000000..32dd68b --- /dev/null +++ b/cmd/sklad/main.go @@ -0,0 +1,271 @@ +package main + +import ( + "errors" + "html/template" + "io" + "log" + "math/rand" + "net/http" + "os" + "path/filepath" + "time" + + "janouch.name/sklad/imgutil" + "janouch.name/sklad/label" + "janouch.name/sklad/ql" +) + +var templates = map[string]*template.Template{} + +func executeTemplate(name string, w io.Writer, data interface{}) { + if err := templates[name].Execute(w, data); err != nil { + panic(err) + } +} + +func wrap(inner func(http.ResponseWriter, *http.Request)) func( + http.ResponseWriter, *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + if err := r.ParseForm(); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + if r.Method == http.MethodGet { + w.Header().Set("Cache-Control", "no-store") + } + inner(w, r) + } +} + +func handleLogin(w http.ResponseWriter, r *http.Request) { + redirect := r.FormValue("redirect") + if redirect == "" { + redirect = "/" + } + + session := sessionGet(w, r) + if session.LoggedIn { + http.Redirect(w, r, redirect, http.StatusSeeOther) + return + } + + params := struct { + IncorrectPassword bool + }{} + + switch r.Method { + case http.MethodGet: + // We're just going to render the template. + case http.MethodPost: + if r.FormValue("password") == db.Password { + session.LoggedIn = true + http.Redirect(w, r, redirect, http.StatusSeeOther) + return + } + params.IncorrectPassword = true + default: + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + + executeTemplate("login.tmpl", w, ¶ms) +} + +func handleLogout(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + + session := r.Context().Value(sessionContextKey{}).(*Session) + session.LoggedIn = false + http.Redirect(w, r, "/", http.StatusSeeOther) +} + +func handleContainer(w http.ResponseWriter, r *http.Request) { + if r.Method == http.MethodPost { + // TODO + } + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + + allSeries := map[string]string{} + for _, s := range indexSeries { + allSeries[s.Prefix] = s.Description + } + + var container *Container + children := []*Container{} + + if id := ContainerId(r.FormValue("id")); id == "" { + children = indexChildren[""] + } else if c, ok := indexContainer[id]; ok { + children = c.Children() + container = c + } + + params := struct { + Container *Container + Children []*Container + AllSeries map[string]string + }{ + Container: container, + Children: children, + AllSeries: allSeries, + } + + executeTemplate("container.tmpl", w, ¶ms) +} + +func handleSeries(w http.ResponseWriter, r *http.Request) { + if r.Method == http.MethodPost { + // TODO + } + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + + allSeries := map[string]string{} + for _, s := range indexSeries { + allSeries[s.Prefix] = s.Description + } + + prefix := r.FormValue("prefix") + description := "" + + if prefix == "" { + } else if series, ok := indexSeries[prefix]; ok { + description = series.Description + } + + params := struct { + Prefix string + Description string + AllSeries map[string]string + }{ + Prefix: prefix, + Description: description, + AllSeries: allSeries, + } + + executeTemplate("series.tmpl", w, ¶ms) +} + +func handleSearch(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + + query := r.FormValue("q") + params := struct { + Query string + Series []*Series + Containers []*Container + }{ + Query: query, + Series: dbSearchSeries(query), + Containers: dbSearchContainers(query), + } + + executeTemplate("search.tmpl", w, ¶ms) +} + +func printLabel(id string) error { + printer, err := ql.Open() + if err != nil { + return err + } + if printer == nil { + return errors.New("no suitable printer found") + } + defer printer.Close() + + /* + printer.StatusNotify = func(status *ql.Status) { + log.Printf("\x1b[1mreceived status\x1b[m\n%+v\n%s", + status[:], status) + } + */ + + if err := printer.Initialize(); err != nil { + return err + } + if err := printer.UpdateStatus(); err != nil { + return err + } + + mediaInfo := ql.GetMediaInfo( + printer.LastStatus.MediaWidthMM(), + printer.LastStatus.MediaLengthMM(), + ) + if mediaInfo == nil { + return errors.New("unknown media") + } + + return printer.Print(&imgutil.LeftRotate{Image: label.GenLabelForHeight( + labelFont, id, mediaInfo.PrintAreaPins, db.BDFScale)}) +} + +func handleLabel(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + + params := struct { + Id string + UnknownId bool + Error error + }{ + Id: r.FormValue("id"), + } + + if c := indexContainer[ContainerId(params.Id)]; c == nil { + params.UnknownId = true + } else { + params.Error = printLabel(params.Id) + } + + executeTemplate("label.tmpl", w, ¶ms) +} + +func main() { + // Randomize the RNG for session string generation. + rand.Seed(time.Now().UnixNano()) + + if len(os.Args) != 3 { + log.Fatalf("Usage: %s ADDRESS DATABASE-FILE\n", os.Args[0]) + } + + var address string + address, dbPath = os.Args[1], os.Args[2] + + // Load database. + if err := loadDatabase(); err != nil { + log.Fatalln(err) + } + + // Load HTML templates from the current working directory. + m, err := filepath.Glob("*.tmpl") + if err != nil { + log.Fatalln(err) + } + for _, name := range m { + templates[name] = template.Must(template.ParseFiles("base.tmpl", name)) + } + + http.HandleFunc("/login", wrap(handleLogin)) + http.HandleFunc("/logout", sessionWrap(wrap(handleLogout))) + + http.HandleFunc("/", sessionWrap(wrap(handleContainer))) + http.HandleFunc("/series", sessionWrap(wrap(handleSeries))) + http.HandleFunc("/search", sessionWrap(wrap(handleSearch))) + http.HandleFunc("/label", sessionWrap(wrap(handleLabel))) + + log.Fatalln(http.ListenAndServe(address, nil)) +} -- cgit v1.2.3