2024-05-19 21:24:09 +00:00
|
|
|
package torrent
|
2024-01-28 20:22:49 +00:00
|
|
|
|
|
|
|
import (
|
2024-03-17 21:00:34 +00:00
|
|
|
"context"
|
2024-01-28 20:22:49 +00:00
|
|
|
"slices"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/anacrolix/torrent"
|
|
|
|
)
|
|
|
|
|
2024-05-19 21:24:09 +00:00
|
|
|
type Controller struct {
|
2024-01-28 20:22:49 +00:00
|
|
|
torrentFilePath string
|
|
|
|
t *torrent.Torrent
|
2024-05-19 21:24:09 +00:00
|
|
|
rep *filesMappingsStore
|
2024-01-28 20:22:49 +00:00
|
|
|
}
|
|
|
|
|
2024-05-19 21:24:09 +00:00
|
|
|
func newController(t *torrent.Torrent, rep *filesMappingsStore) *Controller {
|
|
|
|
return &Controller{t: t, rep: rep}
|
2024-01-28 20:22:49 +00:00
|
|
|
}
|
|
|
|
|
2024-05-19 21:24:09 +00:00
|
|
|
func (s *Controller) TorrentFilePath() string {
|
2024-01-28 20:22:49 +00:00
|
|
|
return s.torrentFilePath
|
|
|
|
}
|
|
|
|
|
2024-05-19 21:24:09 +00:00
|
|
|
func (s *Controller) Torrent() *torrent.Torrent {
|
2024-01-28 20:22:49 +00:00
|
|
|
return s.t
|
|
|
|
}
|
|
|
|
|
2024-05-19 21:24:09 +00:00
|
|
|
func (c *Controller) Name() string {
|
2024-03-17 21:00:34 +00:00
|
|
|
<-c.t.GotInfo()
|
|
|
|
if name := c.t.Name(); name != "" {
|
2024-02-22 22:54:56 +00:00
|
|
|
return name
|
|
|
|
}
|
|
|
|
|
2024-03-17 21:00:34 +00:00
|
|
|
return c.InfoHash()
|
2024-01-28 20:22:49 +00:00
|
|
|
}
|
|
|
|
|
2024-05-19 21:24:09 +00:00
|
|
|
func (s *Controller) InfoHash() string {
|
2024-01-28 20:22:49 +00:00
|
|
|
<-s.t.GotInfo()
|
|
|
|
return s.t.InfoHash().HexString()
|
|
|
|
}
|
|
|
|
|
2024-05-19 21:24:09 +00:00
|
|
|
func (s *Controller) BytesCompleted() int64 {
|
2024-01-28 20:22:49 +00:00
|
|
|
<-s.t.GotInfo()
|
|
|
|
return s.t.BytesCompleted()
|
|
|
|
}
|
|
|
|
|
2024-05-19 21:24:09 +00:00
|
|
|
func (s *Controller) BytesMissing() int64 {
|
2024-01-28 20:22:49 +00:00
|
|
|
<-s.t.GotInfo()
|
|
|
|
return s.t.BytesMissing()
|
|
|
|
}
|
|
|
|
|
2024-05-19 21:24:09 +00:00
|
|
|
func (s *Controller) Length() int64 {
|
2024-03-17 21:00:34 +00:00
|
|
|
<-s.t.GotInfo()
|
|
|
|
return s.t.Length()
|
|
|
|
}
|
|
|
|
|
2024-05-19 21:24:09 +00:00
|
|
|
func (s *Controller) Files(ctx context.Context) ([]*torrent.File, error) {
|
2024-03-17 21:00:34 +00:00
|
|
|
fileMappings, err := s.rep.FileMappings(ctx, s.t.InfoHash())
|
2024-01-28 20:22:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2024-04-27 11:00:34 +00:00
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
return nil, ctx.Err()
|
|
|
|
case <-s.t.GotInfo():
|
|
|
|
}
|
|
|
|
|
2024-01-28 20:22:49 +00:00
|
|
|
files := s.t.Files()
|
|
|
|
files = slices.DeleteFunc(files, func(file *torrent.File) bool {
|
2024-04-27 11:00:34 +00:00
|
|
|
if file == nil {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2024-01-28 20:22:49 +00:00
|
|
|
p := file.Path()
|
|
|
|
if strings.Contains(p, "/.pad/") {
|
2024-03-17 21:00:34 +00:00
|
|
|
return true
|
2024-01-28 20:22:49 +00:00
|
|
|
}
|
2024-03-17 21:00:34 +00:00
|
|
|
if target, ok := fileMappings[p]; ok && target == "" {
|
|
|
|
return true
|
2024-01-28 20:22:49 +00:00
|
|
|
}
|
2024-03-17 21:00:34 +00:00
|
|
|
return false
|
2024-01-28 20:22:49 +00:00
|
|
|
})
|
|
|
|
|
2024-03-17 21:00:34 +00:00
|
|
|
return files, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func Map[T, U any](ts []T, f func(T) U) []U {
|
|
|
|
us := make([]U, len(ts))
|
|
|
|
for i := range ts {
|
|
|
|
us[i] = f(ts[i])
|
2024-02-22 22:54:56 +00:00
|
|
|
}
|
2024-03-17 21:00:34 +00:00
|
|
|
return us
|
|
|
|
}
|
2024-02-22 22:54:56 +00:00
|
|
|
|
2024-05-19 21:24:09 +00:00
|
|
|
func (s *Controller) ExcludeFile(ctx context.Context, f *torrent.File) error {
|
2024-03-17 21:00:34 +00:00
|
|
|
return s.rep.ExcludeFile(ctx, f)
|
2024-01-28 20:22:49 +00:00
|
|
|
}
|
|
|
|
|
2024-05-19 21:24:09 +00:00
|
|
|
func (s *Controller) isFileComplete(startIndex int, endIndex int) bool {
|
2024-02-22 22:54:56 +00:00
|
|
|
for i := startIndex; i < endIndex; i++ {
|
|
|
|
if !s.t.Piece(i).State().Complete {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2024-05-19 21:24:09 +00:00
|
|
|
func (s *Controller) ValidateTorrent() error {
|
2024-01-28 20:22:49 +00:00
|
|
|
<-s.t.GotInfo()
|
|
|
|
s.t.VerifyData()
|
|
|
|
return nil
|
|
|
|
}
|