diff --git a/.gitignore b/.gitignore index 0f5b409..3e94f74 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ downloads .DS_Store build/ yt-dlp-webui +session.dat diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 261835d..ea32cdb 100755 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -32,7 +32,7 @@ import { RootState, store } from './stores/store' import AppBar from './components/AppBar' import Drawer from './components/Drawer' -import Downloaded from './Downloaded' +import Archive from './Archive' import { formatGiB } from './utils' function AppContent() { @@ -148,7 +148,7 @@ function AppContent() { - + }> - + } /> diff --git a/frontend/src/Downloaded.tsx b/frontend/src/Archive.tsx similarity index 97% rename from frontend/src/Downloaded.tsx rename to frontend/src/Archive.tsx index de47021..6d601f8 100644 --- a/frontend/src/Downloaded.tsx +++ b/frontend/src/Archive.tsx @@ -130,7 +130,11 @@ export default function Downloaded() { icon={} tooltipTitle={`Delete selected`} tooltipOpen - onClick={() => setOpenDialog(true)} + onClick={() => { + if (selected$.value.length > 0) { + setOpenDialog(true) + } + }} /> void } export function DownloadsCardView({ downloads, abortFunction }: Props) { diff --git a/frontend/src/components/StackableResult.tsx b/frontend/src/components/StackableResult.tsx index 24a6211..382e6d1 100644 --- a/frontend/src/components/StackableResult.tsx +++ b/frontend/src/components/StackableResult.tsx @@ -1,4 +1,4 @@ -import { EightK, FourK, Hd, Sd } from "@mui/icons-material"; +import { EightK, FourK, Hd, Sd } from '@mui/icons-material' import { Button, Card, @@ -11,9 +11,9 @@ import { Skeleton, Stack, Typography -} from "@mui/material"; -import { useEffect, useState } from "react"; -import { ellipsis, formatSpeedMiB, roundMiB } from "../utils"; +} from '@mui/material' +import { useEffect, useState } from 'react' +import { ellipsis, formatSpeedMiB, roundMiB } from '../utils' type Props = { title: string, @@ -97,7 +97,8 @@ export function StackableResult({ variant="contained" size="small" color="primary" - onClick={stopCallback}> + onClick={stopCallback} + > {isCompleted ? "Clear" : "Stop"} diff --git a/server/memory_db.go b/server/memory_db.go index 28f8aaa..2562709 100644 --- a/server/memory_db.go +++ b/server/memory_db.go @@ -108,4 +108,14 @@ func (m *MemoryDB) Restore() { feed, _ := os.ReadFile("session.dat") session := Session{} json.Unmarshal(feed, &session) + + for _, proc := range session.Processes { + db.table.Store(proc.Id, &Process{ + id: proc.Id, + url: proc.Info.URL, + Info: proc.Info, + Progress: proc.Progress, + mem: m, + }) + } } diff --git a/server/process.go b/server/process.go index 8f0f3c8..d348319 100644 --- a/server/process.go +++ b/server/process.go @@ -171,14 +171,17 @@ func (p *Process) Kill() error { // has been spawned with setPgid = true. To properly kill // all subprocesses a SIGTERM need to be sent to the correct // process group - pgid, err := syscall.Getpgid(p.proc.Pid) - if err != nil { + if p.proc != nil { + pgid, err := syscall.Getpgid(p.proc.Pid) + if err != nil { + return err + } + err = syscall.Kill(-pgid, syscall.SIGTERM) + + log.Println("Killed process", p.id) return err } - err = syscall.Kill(-pgid, syscall.SIGTERM) - - log.Println("Killed process", p.id) - return err + return nil } // Returns the available format for this URL diff --git a/server/rest/handlers.go b/server/rest/handlers.go index 5e98ba4..7a39aad 100644 --- a/server/rest/handlers.go +++ b/server/rest/handlers.go @@ -21,6 +21,13 @@ type DirectoryEntry struct { SHASum string `json:"shaSum"` } +func isValidEntry(d fs.DirEntry) bool { + return !d.IsDir() && + !strings.HasPrefix(d.Name(), ".") && + !strings.HasSuffix(d.Name(), ".part") && + !strings.HasSuffix(d.Name(), ".ytdl") +} + func walkDir(root string) (*[]DirectoryEntry, error) { files := []DirectoryEntry{} @@ -28,7 +35,7 @@ func walkDir(root string) (*[]DirectoryEntry, error) { if err != nil { return err } - if !d.IsDir() && !strings.HasPrefix(d.Name(), ".") { + if isValidEntry(d) { h := sha256.New() h.Write([]byte(path)) diff --git a/server/server.go b/server/server.go index 54b9ae8..b430457 100644 --- a/server/server.go +++ b/server/server.go @@ -1,12 +1,17 @@ package server import ( + "context" "fmt" "io" "io/fs" "log" "net/http" "net/rpc" + "os" + "os/signal" + "syscall" + "time" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/cors" @@ -18,6 +23,8 @@ import ( var db MemoryDB func RunBlocking(port int, frontend fs.FS) { + db.Restore() + service := new(Service) rpc.Register(service) @@ -73,5 +80,34 @@ func RunBlocking(port int, frontend fs.FS) { app.Server().StreamRequestBody = true + go periodicallyPersist() + go gracefulShutdown(app) + log.Fatal(app.Listen(fmt.Sprintf(":%d", port))) } + +func gracefulShutdown(app *fiber.App) { + ctx, stop := signal.NotifyContext(context.Background(), + os.Interrupt, + syscall.SIGTERM, + syscall.SIGQUIT, + ) + + go func() { + <-ctx.Done() + log.Println("shutdown signal received") + + defer func() { + db.Persist() + stop() + app.ShutdownWithTimeout(time.Second * 5) + }() + }() +} + +func periodicallyPersist() { + for { + db.Persist() + time.Sleep(time.Minute * 5) + } +} diff --git a/server/service.go b/server/service.go index 6d2de79..7d92407 100644 --- a/server/service.go +++ b/server/service.go @@ -72,12 +72,15 @@ func (t *Service) Running(args NoArgs, running *Running) error { func (t *Service) Kill(args string, killed *string) error { log.Println("Trying killing process with id", args) proc, err := db.Get(args) + if err != nil { return err } if proc != nil { err = proc.Kill() } + + db.Delete(proc.id) return err }