package qbittorrent import ( "context" "fmt" "slices" "time" "github.com/xuthus5/qbittorrent-client-go/qbittorrent" ) type client struct { qb qbittorrent.Client } func wrapClient(qb qbittorrent.Client) *client { return &client{qb: qb} } func (f *client) getFileContent(ctx context.Context, hash string, contextIndex int) (*qbittorrent.TorrentContent, error) { contents, err := f.qb.Torrent().GetContents(hash) if err != nil { return nil, err } contentIndex := slices.IndexFunc(contents, func(c *qbittorrent.TorrentContent) bool { return c.Index == contextIndex }) if contentIndex == -1 { return nil, fmt.Errorf("content not found") } return contents[contentIndex], nil } func (f *client) isPieceComplete(ctx context.Context, hash string, pieceIndex int) (bool, error) { completion, err := f.qb.Torrent().GetPiecesStates(hash) if err != nil { return false, err } if completion[pieceIndex] == 2 { return true, nil } return false, nil } func (f *client) waitPieceToComplete(ctx context.Context, hash string, pieceIndex int) error { const checkingInterval = 1 * time.Second ok, err := f.isPieceComplete(ctx, hash, pieceIndex) if err != nil { return err } if ok { return nil } if deadline, ok := ctx.Deadline(); ok && time.Until(deadline) < checkingInterval { return context.DeadlineExceeded } ticker := time.NewTicker(checkingInterval) defer ticker.Stop() for { select { case <-ctx.Done(): return ctx.Err() case <-ticker.C: ok, err := f.isPieceComplete(ctx, hash, pieceIndex) if err != nil { return err } if ok { return nil } if deadline, ok := ctx.Deadline(); ok && time.Until(deadline) < checkingInterval { return context.DeadlineExceeded } } } }