package main import ( "embed" _ "embed" "encoding/json" "fmt" "net/http" "os" "os/exec" "strconv" "strings" "time" "velvettear/go-scan/config" "velvettear/go-scan/log" "velvettear/go-scan/util/date" ) //go:embed resources var resources embed.FS var configuration config.Config func main() { configuration = config.New() startServer() } func startServer() { serverAddress := configuration.ServerConfig.Address + ":" + configuration.ServerConfig.Port http.HandleFunc("/favicon.ico", serveResources) http.HandleFunc("/resources/", serveResources) http.HandleFunc("/", handleHTTPRequests) log.Info("starting server '" + serverAddress + "'...") error := http.ListenAndServe(serverAddress, nil) if error != nil { log.Fatal("an error occured starting the server", error.Error()) } } func serveResources(writer http.ResponseWriter, request *http.Request) { var resource string if strings.HasSuffix(request.URL.Path, "favicon.ico") { resource = "resources/gopher.png" } else { resource = strings.TrimPrefix(request.URL.Path, "/") } bytes, error := resources.ReadFile(resource) if error != nil { log.Error("an error occured serving the resource '"+resource+"'", error.Error()) return } log.Debug("serving '" + resource + "'...") if strings.HasSuffix(resource, "svg") { writer.Header().Set("Content-Type", "image/svg+xml") } writer.Write(bytes) } func handleHTTPRequests(writer http.ResponseWriter, request *http.Request) { if strings.ToLower(request.Method) == "post" { result := handleScan(request) writer.Header().Set("Content-Type", "application/json") json, _ := json.Marshal(result) writer.Write(json) return } resource := "resources/index.html" bytes, error := resources.ReadFile(resource) if error != nil { log.Error("an error occured serving the resource '"+resource+"'", error.Error()) return } log.Debug("serving '" + resource + "'...") writer.Write(bytes) } func handleScan(request *http.Request) *result { log.Info("starting scan...") timestamp := date.Milliseconds() var parameters requestParameters parseErr := json.NewDecoder(request.Body).Decode(¶meters) if parseErr != nil { log.Error("error parsing request parameters", parseErr.Error()) } scanName := generateScanName(parameters.Filename) args := []string{} if len(configuration.ScannerConfig.Scanner) > 0 { args = append(args, "-d") args = append(args, configuration.ScannerConfig.Scanner) } args = append(args, "-o") args = append(args, scanName) extraArgs := strings.Split(configuration.ScannerConfig.Arguments, " ") for index := 0; index < len(extraArgs); index++ { args = append(args, extraArgs[index]) } log.Debug("executing command 'scanimage'...", args...) scanCmd := exec.Command( "scanimage", args..., ) _, err := scanCmd.Output() if err != nil { log.Error("an error occured executing the scan", err.Error()) result := &result{ State: "error", Message: err.Error(), } return result } result := &result{ State: "ok", Message: scanName, } log.Info("finished scan after "+strconv.Itoa(date.GetTimeDifference(timestamp))+"ms", scanName) return result } func generateScanName(filename string) string { if len(filename) == 0 { day := fmt.Sprint(time.Now().Day()) if len(day) < 2 { day = "0" + day } month := fmt.Sprint(int(time.Now().Month())) if len(month) < 2 { month = "0" + month } hour := fmt.Sprint(time.Now().Hour()) if len(hour) < 2 { hour = "0" + hour } minute := fmt.Sprint(time.Now().Minute()) if len(minute) < 2 { minute = "0" + minute } second := fmt.Sprint(time.Now().Second()) if len(second) < 2 { second = "0" + second } filename = day + month + fmt.Sprint(time.Now().Year()) + "-" + hour + minute + second } if !strings.HasSuffix(filename, ".png") { filename += ".png" } error := os.MkdirAll(configuration.ScannerConfig.OutputDirectory, 0755) if error != nil { log.Fatal("an error occurred creating the output directory", error.Error()) } return configuration.ScannerConfig.OutputDirectory + filename } // structs type result struct { State string Message string } type requestParameters struct { Filename string }