From 07cd9ebac952428378ea311e73920fb607b4569a Mon Sep 17 00:00:00 2001 From: Sotig Date: Sat, 21 Mar 2026 15:35:50 +0200 Subject: [PATCH] intitial --- .gitignore | 1 + README.md | 2 + cmd/actions.go | 42 +++++++++++++++ cmd/main.go | 28 ++++++++++ docker/Dockerfile | 39 ++++++++++++++ docker/docker-compose.yml | 15 ++++++ go.mod | 8 +++ go.sum | 4 ++ internal/cli/cli.go | 104 ++++++++++++++++++++++++++++++++++++++ notes.txt | 16 ++++++ 10 files changed, 259 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 cmd/actions.go create mode 100644 cmd/main.go create mode 100644 docker/Dockerfile create mode 100644 docker/docker-compose.yml create mode 100644 go.mod create mode 100644 go.sum create mode 100644 internal/cli/cli.go create mode 100644 notes.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bb8b914 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +configs/* \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e8f4bdd --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +## 3D slicer Api +This is a simple api that slices 3d files using prusa-slicer, fff and sla modes are supported. \ No newline at end of file diff --git a/cmd/actions.go b/cmd/actions.go new file mode 100644 index 0000000..f647f20 --- /dev/null +++ b/cmd/actions.go @@ -0,0 +1,42 @@ +package main + +import "net/http" + +func actions(mux *http.ServeMux) { + + mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { + + if r.Method != http.MethodGet { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + w.WriteHeader(http.StatusOK) + w.Write([]byte("OK")) + + }) + + mux.HandleFunc("/analyze-fff", func(w http.ResponseWriter, r *http.Request) { + + if r.Method != http.MethodPost { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + w.WriteHeader(http.StatusOK) + w.Write([]byte("OK")) + + }) + + mux.HandleFunc("/analyze-sla", func(w http.ResponseWriter, r *http.Request) { + + if r.Method != http.MethodPost { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + w.WriteHeader(http.StatusOK) + w.Write([]byte("OK")) + + }) +} diff --git a/cmd/main.go b/cmd/main.go new file mode 100644 index 0000000..4ca85c4 --- /dev/null +++ b/cmd/main.go @@ -0,0 +1,28 @@ +package main + +import ( + "fmt" + "net/http" + "os" + + "golang.org/x/net/http2" +) + +func main() { + // Your code here + mux := http.NewServeMux() + + svr := &http.Server{ + Addr: fmt.Sprintf("%s:%s", os.Getenv("HOST"), os.Getenv("PORT")), + Handler: mux, + } + http2.ConfigureServer(svr, nil) + + actions(mux) // Register actions with the multiplexer + + fmt.Printf("Starting server on %s:%s\n", os.Getenv("HOST"), os.Getenv("PORT")) + err := svr.ListenAndServe() + if err != nil { + panic(err) + } +} diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..fbd8519 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,39 @@ +FROM ubuntu:plucky + +RUN echo "deb https://ppa.launchpadcontent.net/longsleep/golang-backports/ubuntu ubuntu-plucky main" | tee /etc/apt/sources.list.d/docker.list +RUN apt update + +ENV GO_VERSION=1.24 + +RUN apt install -y golang-${GO_VERSION} +RUN ln -s "/usr/lib/go-${GO_VERSION}/bin/go" /usr/local/bin/ + +RUN apt-get clean && apt-get update && apt-get install -y locales wget +RUN locale-gen en_US.UTF-8 +RUN update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 +ENV LANG=en_US.UTF-8 +ENV LC_CTYPE="en_US.UTF-8" +ENV LC_NUMERIC="en_US.UTF-8" +ENV LC_TIME="en_US.UTF-8" +ENV LC_COLLATE="en_US.UTF-8" +ENV LC_MONETARY="en_US.UTF-8" +ENV LC_MESSAGES="en_US.UTF-8" +ENV LC_PAPER="en_US.UTF-8" +ENV LC_NAME="en_US.UTF-8" +ENV LC_ADDRESS="en_US.UTF-8" +ENV LC_TELEPHONE="en_US.UTF-8" +ENV LC_MEASUREMENT="en_US.UTF-8" +ENV LC_IDENTIFICATION="en_US.UTF-8" +ENV LC_ALL= + +RUN apt install -y prusa-slicer + +WORKDIR /build + +COPY ../ . + +RUN go build -o /bin/slic3r-api ./cmd + +RUN rm -rf /build/* + +CMD [ "/bin/slic3r-api" ] \ No newline at end of file diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..9ed9688 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,15 @@ +services: + slic3r-api: + build: + context: ../ + dockerfile: docker/Dockerfile + command: /bin/bash -c "cd /src && go run ./cmd" + volumes: + - ../:/src + - ../configs:/configs + environment: + - PORT=3030 + - HOST=0.0.0.0 + - CONFIGS=/configs/ + ports: + - 3030:3030 \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..9f499fd --- /dev/null +++ b/go.mod @@ -0,0 +1,8 @@ +module github.com/sotigr/slic3r-api + +go 1.24.2 + +require ( + golang.org/x/net v0.41.0 // indirect + golang.org/x/text v0.26.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..bf3398a --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= +golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= +golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= diff --git a/internal/cli/cli.go b/internal/cli/cli.go new file mode 100644 index 0000000..9b62dd4 --- /dev/null +++ b/internal/cli/cli.go @@ -0,0 +1,104 @@ +package cli + +import ( + "context" + "errors" + "io" + "os/exec" + "regexp" + "strings" +) + +var re = regexp.MustCompile(`\w|\%|^(\+|,|\.|:|\/|\\|=|_|-|[a-z]|[A-Z]|[0-9]|\s)+$`) + +func validateCliArgument(arg string) bool { + return re.Match([]byte(arg)) +} + +func validateCliArguments(args []string) bool { + for _, p := range args { + if !validateCliArgument(p) { + return false + } + } + return true +} + +func execNoCheck(ctx context.Context, command string, args []string) (string, string, error) { + cmd := exec.CommandContext(ctx, command, args...) + cmdStr := cmd.String() + + pStdout, err := cmd.StdoutPipe() + if err != nil { + return "", cmdStr, err + } + + pStderr, err := cmd.StderrPipe() + if err != nil { + return "", cmdStr, err + } + + err = cmd.Start() + if err != nil { + return "", cmdStr, err + } + + stdout, _ := io.ReadAll(pStdout) + stderr, _ := io.ReadAll(pStderr) + + err = cmd.Wait() + if err != nil { + return "", cmdStr, errors.New(err.Error() + " | " + string(stderr) + " | " + string(stdout)) + } + return string(stdout), cmdStr, nil +} + +type Pipe struct { + Command string + Args []string +} + +func (p *Pipe) IsSanatory() bool { + return validateCliArguments(p.Args) && validateCliArgument(p.Command) +} + +func (p *Pipe) Execute(ctx context.Context) (string, string, error) { + if !p.IsSanatory() { + return "", "", errors.New("failed to execute cli command: " + p.Command + " " + strings.Join(p.Args, " ") + " some arguments are not allowed") + } else { + return execNoCheck(ctx, p.Command, p.Args) + } +} + +func ExecuteCLIPipeLine(ctx context.Context, pipes []Pipe) (string, string, error) { + + pipeLen := len(pipes) + if pipeLen == 0 { + return "", "", errors.New("failed to execute cli command: no pipes provided") + } + argLen := 0 + for _, p := range pipes { + if !p.IsSanatory() { + return "", "", errors.New("failed to execute cli command: " + p.Command + " " + strings.Join(p.Args, " ") + " some arguments are not allowed") + } + argLen += len(p.Args) + 1 + } + + command := "/bin/sh" + var args []string = []string{} + args = append(args, "-c") + pipeLen -= 1 + + cmdArg := "" + + for i, p := range pipes { + cmdArg += p.Command + " " + strings.Join(p.Args, " ") + if i != pipeLen { + cmdArg += " | " + } + } + + args = append(args, cmdArg) + + return execNoCheck(ctx, command, args) +} diff --git a/notes.txt b/notes.txt new file mode 100644 index 0000000..4acfa90 --- /dev/null +++ b/notes.txt @@ -0,0 +1,16 @@ +look at: + * https://github.com/prusa3d/PrusaSlicer/wiki/Command-Line-Interface + * https://manual.slic3r.org/advanced/command-line + +slice: + * prusa-slicer --load config.ini --export-gcode --info part.stl + * prusa-slicer --load config.ini --info --export-sla part.stl + +thumbnail: + * f3d 'model.stl' --resolution=512,512 -a --anti-aliasing-mode=taa --filename=false --metadata=false --color=#999 -t --grid=false --axis=false --no-background --output='output.png' + +post-process: + * this can preview print times for sla: https://github.com/oelmekki/sl1toctb?tab=readme-ov-file + + +