commit 8c5ae7fb10818c635cbecf9272cdbe260a3f53c4 Author: Louis Dalibard Date: Sat Apr 27 12:16:43 2024 +0200 init:first commit diff --git a/assets/images/diricon.png b/assets/images/diricon.png new file mode 100644 index 0000000..52791c2 Binary files /dev/null and b/assets/images/diricon.png differ diff --git a/assets/images/fileicon.png b/assets/images/fileicon.png new file mode 100644 index 0000000..c59c99a Binary files /dev/null and b/assets/images/fileicon.png differ diff --git a/assets/images/leech.png b/assets/images/leech.png new file mode 100644 index 0000000..ddf88a2 Binary files /dev/null and b/assets/images/leech.png differ diff --git a/assets/images/logo-64px-padded.png b/assets/images/logo-64px-padded.png new file mode 100644 index 0000000..617334d Binary files /dev/null and b/assets/images/logo-64px-padded.png differ diff --git a/assets/images/src/Leech-Big-Colored.png b/assets/images/src/Leech-Big-Colored.png new file mode 100644 index 0000000..f03982e Binary files /dev/null and b/assets/images/src/Leech-Big-Colored.png differ diff --git a/assets/images/src/Leech-Big-Scaled.png b/assets/images/src/Leech-Big-Scaled.png new file mode 100644 index 0000000..ddf88a2 Binary files /dev/null and b/assets/images/src/Leech-Big-Scaled.png differ diff --git a/assets/images/src/Leech-Big.png b/assets/images/src/Leech-Big.png new file mode 100644 index 0000000..33aa2fc Binary files /dev/null and b/assets/images/src/Leech-Big.png differ diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..57157d0 --- /dev/null +++ b/config/config.go @@ -0,0 +1,8 @@ +package config + +var Host = ":3125" +var InstallDir = "./" + +var ServeDirs = map[string]string{ + "leech": "/home/ontake/Dev/go/leech", +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..c238809 --- /dev/null +++ b/go.mod @@ -0,0 +1,22 @@ +module leech + +go 1.22.2 + +require ( + github.com/dustin/go-humanize v1.0.1 + github.com/gofiber/fiber/v2 v2.52.4 +) + +require ( + github.com/andybalholm/brotli v1.0.5 // indirect + github.com/google/uuid v1.5.0 // indirect + github.com/klauspost/compress v1.17.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.51.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + golang.org/x/sys v0.15.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..9b33019 --- /dev/null +++ b/go.sum @@ -0,0 +1,29 @@ +github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/gofiber/fiber/v2 v2.52.4 h1:P+T+4iK7VaqUsq2PALYEfBBo6bJZ4q3FP8cZ84EggTM= +github.com/gofiber/fiber/v2 v2.52.4/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= +github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= +github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA= +github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g= +github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/html/html.go b/html/html.go new file mode 100644 index 0000000..7311a64 --- /dev/null +++ b/html/html.go @@ -0,0 +1,126 @@ +package html + +import ( + "fmt" + "strings" + + "github.com/dustin/go-humanize" +) + +type Entry struct { + IsDir bool + Name string + Size int64 +} + +func FileListPage(req string, entries []Entry) string { + header := ` + + + + + + + home | leech.ontake.dev + + + + + + + + + +
` + + footer := `
` + + body := "" + entriesWithParent := []Entry{} + if req != "" { + entriesWithParent = append(entriesWithParent, Entry{ + IsDir: true, + Name: "..", + Size: -1, + }) + } + entriesWithParent = append(entriesWithParent, entries...) + for _, dirEntry := range entriesWithParent { + formattedSize := "" + if dirEntry.Size != -1 { + formattedSize = humanize.Bytes(uint64(dirEntry.Size)) + } + icon := "/assets/images/fileicon.png" + if dirEntry.IsDir { + icon = "/assets/images/diricon.png" + } + link := "/" + req + "." + dirEntry.Name + if dirEntry.Name == ".." { + splitReq := strings.Split(req, ".") + link = "/" + strings.Join(splitReq[:len(splitReq)-1], ".") + } + if req == "" { + link = "/" + req + dirEntry.Name + } + if !dirEntry.IsDir { + link = "/serve/" + strings.ReplaceAll(req, ".", "/") + "/" + dirEntry.Name + } + body += fmt.Sprintf(`
%s
%s
`, link, icon, dirEntry.Name, formattedSize) + } + return header + body + footer +} diff --git a/leech b/leech new file mode 100755 index 0000000..51cb351 Binary files /dev/null and b/leech differ diff --git a/main.go b/main.go new file mode 100644 index 0000000..f1cb9e1 --- /dev/null +++ b/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "leech/config" + "leech/route" + "path" + + "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v2/middleware/logger" +) + +func main() { + app := fiber.New() + app.Use(logger.New(logger.Config{ + Format: "[${ip}]:${port} ${status} - ${method} ${path}\n", + })) + app.Get("/:req", route.HandleList) + app.Get("/", route.HandleList) + + app.Static("/assets", path.Join(config.InstallDir, "assets")) + + for dirName, dirToServe := range config.ServeDirs { + app.Static("/serve/"+dirName, dirToServe) + } + + app.Listen(config.Host) +} diff --git a/route/route.go b/route/route.go new file mode 100644 index 0000000..7dbdc62 --- /dev/null +++ b/route/route.go @@ -0,0 +1,64 @@ +package route + +import ( + "leech/config" + "leech/html" + "log" + "os" + "path" + "sort" + "strings" + + "github.com/gofiber/fiber/v2" +) + +func HandleList(c *fiber.Ctx) error { + req := c.Params("req") + c.Set(fiber.HeaderContentType, fiber.MIMETextHTML) + if req == "" { + keys := make([]string, 0, len(config.ServeDirs)) + for k := range config.ServeDirs { + keys = append(keys, k) + } + sort.Slice(keys, func(i, j int) bool { + return i < j + }) + + entries := make([]html.Entry, 0, len(config.ServeDirs)) + for _, key := range keys { + entries = append(entries, html.Entry{ + Name: key, + Size: -1, + IsDir: true, + }) + } + + return c.SendString(html.FileListPage(req, entries)) + } else { + pathSlice := strings.Split(req, ".") + pathBase, ok := config.ServeDirs[pathSlice[0]] + if ok { + pathSlice[0] = pathBase + completePath := path.Join(pathSlice...) + files, err := os.ReadDir(completePath) + if err != nil { + log.Fatal(err) + } + entries := []html.Entry{} + for _, f := range files { + dirEntryInfo, err := f.Info() + if err != nil { + return c.Status(fiber.StatusInternalServerError).SendString("Internal server error!") + } + entries = append(entries, html.Entry{ + Name: f.Name(), + Size: dirEntryInfo.Size(), + IsDir: f.IsDir(), + }) + } + return c.SendString(html.FileListPage(req, entries)) + } else { + return c.Status(fiber.StatusNotFound).SendString("Sorry can't find that!") + } + } +}