package controller import ( "context" "slices" "strings" "git.kmsign.ru/royalcat/tstor/src/host/store" "github.com/anacrolix/torrent" ) type Torrent struct { torrentFilePath string t *torrent.Torrent rep *store.FilesMappings } func NewTorrent(t *torrent.Torrent, rep *store.FilesMappings) *Torrent { return &Torrent{t: t, rep: rep} } func (s *Torrent) TorrentFilePath() string { return s.torrentFilePath } func (s *Torrent) Torrent() *torrent.Torrent { return s.t } func (c *Torrent) Name() string { <-c.t.GotInfo() if name := c.t.Name(); name != "" { return name } return c.InfoHash() } func (s *Torrent) InfoHash() string { <-s.t.GotInfo() return s.t.InfoHash().HexString() } func (s *Torrent) BytesCompleted() int64 { <-s.t.GotInfo() return s.t.BytesCompleted() } func (s *Torrent) BytesMissing() int64 { <-s.t.GotInfo() return s.t.BytesMissing() } func (s *Torrent) Length() int64 { <-s.t.GotInfo() return s.t.Length() } func (s *Torrent) Files(ctx context.Context) ([]*torrent.File, error) { fileMappings, err := s.rep.FileMappings(ctx, s.t.InfoHash()) if err != nil { return nil, err } select { case <-ctx.Done(): return nil, ctx.Err() case <-s.t.GotInfo(): } files := s.t.Files() files = slices.DeleteFunc(files, func(file *torrent.File) bool { if file == nil { return true } p := file.Path() if strings.Contains(p, "/.pad/") { return true } if target, ok := fileMappings[p]; ok && target == "" { return true } return false }) 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]) } return us } func (s *Torrent) ExcludeFile(ctx context.Context, f *torrent.File) error { return s.rep.ExcludeFile(ctx, f) } func (s *Torrent) isFileComplete(startIndex int, endIndex int) bool { for i := startIndex; i < endIndex; i++ { if !s.t.Piece(i).State().Complete { return false } } return true } func (s *Torrent) ValidateTorrent() error { <-s.t.GotInfo() s.t.VerifyData() return nil }