added more error handling for the server and db closing added more css to improve scaling
@@ -6,7 +6,6 @@ "os"
"strings" ) -var OtpPath string var DbPath string var HttpDir string var Port string@@ -30,12 +29,11 @@ func checkAbsDir(path string) bool {
return checkAbs(path) && checkDir(path) } -func Get() { - OtpPath = strings.TrimSpace(os.Getenv("OTP_PATH")) +func init() { DbPath = strings.TrimSpace(os.Getenv("DB_PATH")) HttpDir = strings.TrimSpace(os.Getenv("HTTP_DIR")) - if !checkAbs(DbPath) || !checkAbs(OtpPath) || !checkAbsDir(HttpDir) { - fmt.Println("Please set the environment variables OTP_PATH, DB_PATH and HTTP_DIR to absolute paths.") + if !checkAbs(DbPath) || !checkAbsDir(HttpDir) { + fmt.Println("Please set the environment variables DB_PATH and HTTP_DIR to absolute paths.") os.Exit(1) } Port = strings.TrimSpace(os.Getenv("PORT"))
@@ -5,14 +5,12 @@
toolchain go1.24.1 require ( + github.com/asdine/storm/v3 v3.2.1 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 github.com/pquerna/otp v1.4.0 go.etcd.io/bbolt v1.3.11 golang.org/x/image v0.25.0 + golang.org/x/sys v0.4.0 ) -require ( - github.com/asdine/storm/v3 v3.2.1 // indirect - github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect - golang.org/x/sys v0.4.0 // indirect -) +require github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
@@ -1,4 +1,6 @@
+github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM= github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/Sereal/Sereal v0.0.0-20190618215532-0b8ac451a863 h1:BRrxwOZBolJN4gIwvZMJY1tzqBvQgpaZiQRuIDD40jM= github.com/Sereal/Sereal v0.0.0-20190618215532-0b8ac451a863/go.mod h1:D0JMgToj/WdxCgd30Kc1UcA9E+WdZoJqeVOuYW7iTBM= github.com/asdine/storm/v3 v3.2.1 h1:I5AqhkPK6nBZ/qJXySdI7ot5BlXSZ7qvDY1zAn5ZJac= github.com/asdine/storm/v3 v3.2.1/go.mod h1:LEpXwGt4pIqrE/XcTvCnZHT5MgZCV6Ub9q7yQzOFWr0=@@ -8,7 +10,9 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=@@ -24,6 +28,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0=@@ -32,6 +37,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ= golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20191105084925-a882066a44e0 h1:QPlSTtPE2k6PZPasQUbzuK3p9JbS+vMXYVto8g/yrsg= golang.org/x/net v0.0.0-20191105084925-a882066a44e0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=@@ -42,6 +48,7 @@ golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
@@ -1,11 +1,12 @@
{{ define "head" }} <meta charset="UTF-8"> +<meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> :root{ color:white; background: #262833; @media (min-width: 2000px){ - font-size: 115%; + font-size: 110%; } @media (max-width: 2000px) and (min-width: 1500px) { font-size: 100%;@@ -13,18 +14,34 @@ }
@media (max-width: 1500px) and (min-width: 1200px) { font-size: 85%; } - @media (max-width: 1200px) and (min-width: 800px) { + @media (max-width: 1200px) and (min-width: 1000px) { font-size: 75%; } - - @media (max-width: 800px) and (min-width: 600px) { + @media (max-width: 1000px) and (min-width: 800px) { font-size: 70%; } - @media (max-width: 600px) and (min-width: 400px) { + @media (max-width: 800px) and (min-width: 700px) { + font-size: 65%; + } + @media (max-width: 700px) and (min-width: 600px) { + font-size: 70%; + --phone: 1.2; + } + @media (max-width: 600px) and (min-width: 500px) { + font-size: 65%; + --phone: 1.25; + } + @media (max-width: 500px) and (min-width: 400px) { + font-size: 60%; + --phone: 1.3; + } + @media (max-width: 400px) and (min-width: 300px) { font-size: 55%; + --phone: 1.35; } - @media (max-width: 400px) { - font-size: 35%; + @media (max-width: 300px) { + font-size: 45%; + --phone: 1.5; } }@@ -73,7 +90,7 @@ .filelabel, div.filelabel {
padding: 1ch 2ch; margin: 0; display: grid; - grid-template-columns: 2.5em calc(60% - 4em - 2ch) max(15ch,20%) max(20ch,20%); + grid-template-columns: 2.5em calc(calc(60% / var(--phone,1) - 4em - 2ch)) max(15ch,calc(20% / var(--phone,1))) max(20ch,calc(20% / var(--phone,1))); justify-content: space-between; align-items: center; border-radius: 1em;
@@ -112,7 +112,7 @@ let t =new Date(Date.parse(elem.title));
if (elem.innerText[0] >= '0' && elem.innerText[0] <= '9') { elem.innerText = t.getFullYear()+"-"+ZeroPad((t.getMonth()+1),2)+"-"+ZeroPad(t.getDate(),2); } else { - elem.innerText = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][t.getDay()] + ", " + ZeroPad(t.getHours(),2) + ":" + ZeroPad(t.getMinutes(),2); + elem.innerText = ["Sun","Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][t.getDay()] + ", " + ZeroPad(t.getHours(),2) + ":" + ZeroPad(t.getMinutes(),2); } }); currentSort = localStorage.getItem("sort");
@@ -4,21 +4,17 @@ import (
"bytes" "fmt" "github.com/nfnt/resize" - "image/gif" - "os" - "os/exec" - "strings" - - // "gocv.io/x/gocv" "golang.org/x/image/webp" "image" + "image/gif" "image/jpeg" "image/png" "io" + "os" + "os/exec" "path/filepath" + "strings" ) - -// ffmpeg -i file.mp4 -vf "select='eq(n\,20)+eq(n\,40)+eq(n\,60)+eq(n\,80)'" -vsync 0 frame%d.png func scaleEncode(img image.Image) ([]byte, error) { var w, h uint@@ -40,9 +36,6 @@ return buf.Bytes(), nil
} func getFirstFrame(path string) (image.Image, error) { - - // ffmpeg -i input.mp4 -vframes 1 -f image2pipe -vcodec png - - // -vf "select='eq(pict_type\,I)'" -frames:v 1 var out bytes.Buffer cmd := exec.Command("ffmpeg", "-hide_banner", "-loglevel", "error", "-i", path, "-vf", "select='eq(pict_type\\,I)'", "-frames:v", "1", "-vsync", "0", "-f", "image2pipe", "-c:v", "png", "-") // cmd.Stdin = file@@ -90,29 +83,3 @@ return nil, fmt.Errorf("error decoding image: %v", err)
} return scaleEncode(img) } - -/* -func getFirstFrameAsPNGBytes(videoPath string) ([]byte, error) { - // Open the video file - video, err := gocv.VideoCaptureFile(videoPath) - if err != nil { - return nil, fmt.Errorf("error opening video: %v", err) - } - img := gocv.NewMat() - ok := video.Read(&img) - - if !ok || img.Empty() { - img.Close() - video.Close() - return nil, fmt.Errorf("failed to read the first frame") - } - - imgImg, err := img.ToImage() - img.Close() - video.Close() - if err != nil { - return nil, fmt.Errorf("failed to convert frame to image: %v", err) - } - return scaleEncode(imgImg) -} -*/
@@ -78,6 +78,7 @@ a.SizeN = func() int64 {
n, _ := os.ReadDir(filepath.Join(config.HttpDir, a.Url)) return int64(len(n)) }() + a.Url += "/" a.Size = fmt.Sprintf("%d items", a.SizeN) a.Icon = "F" t.Dirs = append(t.Dirs, a)@@ -152,7 +153,7 @@ }
return filepath.Join(dir, path), nil } -func customFileServer(root http.Dir) http.Handler { +func CustomFileServer(root http.Dir) http.Handler { iconFunc := func(w http.ResponseWriter, r *http.Request) { qq := r.URL.Query() var icon ImgIcon@@ -230,34 +231,39 @@
var DB *storm.DB func main() { + Temp = template.Must(template.ParseFS(embedHtml, "html/*")) + db, err := storm.Open(config.DbPath, storm.BoltOptions(0600, &bbolt.Options{Timeout: 1 * time.Second})) + if err != nil { + fmt.Println("Failed to open database:", err) + os.Exit(1) + } + DB = db server := http.Server{ Addr: config.Addr + ":" + config.Port, - Handler: customFileServer(http.Dir(config.HttpDir)), + Handler: CustomFileServer(http.Dir(config.HttpDir)), } fmt.Printf("starting cdn server with pid: %d\n\tlistening on %s\n\tserving directory: %s\n", os.Getpid(), server.Addr, config.HttpDir) + + closeDB := func() { + err1 := DB.Close() + if err1 != nil { + fmt.Fprintf(os.Stderr, "error closing database: %s\n", err1) + os.Exit(1) + } + fmt.Println("Database closed safely") + } + go func() { - if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { - fmt.Fprintf(os.Stderr, "error: %s\n", err) - DB.Close() + if err1 := server.ListenAndServe(); err1 != nil && !errors.Is(err1, http.ErrServerClosed) { + fmt.Fprintf(os.Stderr, "error: %s\n", err1) + closeDB() os.Exit(1) } }() + sigChan := make(chan os.Signal) signal.Notify(sigChan, unix.SIGINT, unix.SIGTERM) fmt.Printf("got signal %v, stopping\n", <-sigChan) server.Shutdown(context.Background()) - DB.Close() - fmt.Println("Server stopped") - os.Exit(0) -} - -func init() { - Temp = template.Must(template.ParseFS(embedHtml, "html/*")) - config.Get() - db, err := storm.Open(config.DbPath, storm.BoltOptions(0600, &bbolt.Options{Timeout: 1 * time.Second})) - if err != nil { - fmt.Println("Failed to open database:", err) - os.Exit(1) - } - DB = db + closeDB() }