From 264d73cdc5346931e21c0c47aca2a24bf8f37ee4 Mon Sep 17 00:00:00 2001 From: itexpert228 <67105314+fdaser1337@users.noreply.github.com> Date: Mon, 20 Jul 2026 19:07:13 +0300 Subject: [PATCH] fix: panic on resume and pause download before starting to allow file priority selection --- dummy.torrent | 1 + internal/app/controller.go | 4 ++++ internal/torrent/engine.go | 47 +++++++++++++++++++++++++++++++++++--- multi.torrent | 1 + ui/ui.go | 9 ++++---- 5 files changed, 55 insertions(+), 7 deletions(-) create mode 100644 dummy.torrent create mode 100644 multi.torrent diff --git a/dummy.torrent b/dummy.torrent new file mode 100644 index 0000000..b8d1cf3 --- /dev/null +++ b/dummy.torrent @@ -0,0 +1 @@ +d8:announce15:http://a.b.c/tr13:creation datei1e4:infod6:lengthi100e4:name9:dummy.txt12:piece lengthi16384e6:pieces20:12345678901234567890ee diff --git a/internal/app/controller.go b/internal/app/controller.go index ab38039..a6b3e70 100644 --- a/internal/app/controller.go +++ b/internal/app/controller.go @@ -65,6 +65,10 @@ func (c *Controller) StartTorrent(path, outputRoot string) error { return nil } +func (c *Controller) StartTorrentDownload() { + c.engine.StartDownload() +} + func (c *Controller) DownloadMagnet(magnetURI string) error { cfg, _ := config.Load() outDir := "." diff --git a/internal/torrent/engine.go b/internal/torrent/engine.go index dbc94f3..71f93e2 100644 --- a/internal/torrent/engine.go +++ b/internal/torrent/engine.go @@ -47,6 +47,7 @@ type Engine struct { portManager *portforward.PortManager cancel context.CancelFunc + downloadCtx context.Context incomingConns chan net.Conn @@ -345,6 +346,9 @@ func (e *Engine) LoadTorrent(path, outputRoot string) error { downloadCtx, cancel := context.WithCancel(context.Background()) e.swapCancel(cancel) + e.mu.Lock() + e.downloadCtx = downloadCtx + e.mu.Unlock() if strings.HasPrefix(path, "magnet:") { go e.loadMagnet(downloadCtx, path, outputRoot) @@ -360,10 +364,38 @@ func (e *Engine) LoadTorrent(path, outputRoot string) error { return err } - e.startTorrent(downloadCtx, tf, outputRoot) + e.mu.Lock() + e.torrent = tf + if tf.InfoHash != [20]byte{} && len(tf.PieceHashes) > 0 { + e.totalPieces = len(tf.PieceHashes) + e.pieceStates = make([]PieceState, len(tf.PieceHashes)) + e.outputPath = buildOutputPath(tf, outputRoot) + } + e.phase = "stopped" + e.mu.Unlock() + return nil } +func (e *Engine) StartDownload() { + e.mu.Lock() + tf := e.torrent + out := e.outputRoot + phase := e.phase + + if tf == nil || phase != "stopped" && phase != "failed" { + e.mu.Unlock() + return + } + + downloadCtx, cancel := context.WithCancel(context.Background()) + e.downloadCtx = downloadCtx + e.cancel = cancel + e.mu.Unlock() + + go e.startTorrent(downloadCtx, tf, out) +} + func (e *Engine) loadMagnet(ctx context.Context, uri, outputRoot string) { ml, err := magnet.Parse(uri) if err != nil { @@ -423,7 +455,13 @@ func (e *Engine) loadMagnet(ctx context.Context, uri, outputRoot string) { tf.Name = hex.EncodeToString(ml.InfoHash[:]) } - e.startTorrent(ctx, tf, outputRoot) + e.mu.Lock() + e.torrent = tf + e.totalPieces = len(tf.PieceHashes) + e.pieceStates = make([]PieceState, len(tf.PieceHashes)) + e.outputPath = buildOutputPath(tf, outputRoot) + e.phase = "stopped" + e.mu.Unlock() } func (e *Engine) downloadMetadataFromPeers(ctx context.Context, infoHash [20]byte, name string, peersCh <-chan []PeerStatus, initialPeers []PeerStatus) (*torrentfile.TorrentFile, error) { @@ -603,7 +641,10 @@ func (e *Engine) Status() Status { status.TotalBytes = int64(e.torrent.Length) status.PieceLength = e.torrent.PieceLength status.PieceCount = len(e.torrent.PieceHashes) - status.Files = append(status.Files, e.torrent.Files...) + + status.Files = make([]torrentfile.File, len(e.torrent.Files)) + copy(status.Files, e.torrent.Files) + status.Announce = e.torrent.Announce } if e.lastErr != nil { diff --git a/multi.torrent b/multi.torrent new file mode 100644 index 0000000..99d2218 --- /dev/null +++ b/multi.torrent @@ -0,0 +1 @@ +d8:announce30:http://localhost:8000/announce4:infod5:filesld6:lengthi100e4:pathl9:file1.txteed6:lengthi200e4:pathl9:file2.txteee4:name7:testdir12:piece lengthi16384e6:pieces20:12345678901234567890ee \ No newline at end of file diff --git a/ui/ui.go b/ui/ui.go index e792040..88df3d4 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -637,11 +637,12 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case key.Matches(msg, keys.PauseResume): phase := m.status.Phase - if phase == "stopped" || phase == "failed" || phase == "" { - m.loadingMetadata = true - return m, tea.Batch(m.spinner.Tick, startTorrentCmd(m.controller, m.torrentPath, m.outputDir, m.inputs[2].Value())) + if phase == "stopped" || phase == "failed" { + m.controller.StartTorrentDownload() + return m, nil + } else if phase != "" { + m.controller.StopTorrent() } - m.controller.StopTorrent() case key.Matches(msg, keys.OpenNew): m.controller.StopTorrent() m.mainMenuMode = true