package qbittorrent import ( "bytes" "context" "path" "git.kmsign.ru/royalcat/tstor/src/vfs" "github.com/anacrolix/torrent/metainfo" "github.com/anacrolix/torrent/types/infohash" "github.com/royalcat/ctxio" "github.com/xuthus5/qbittorrent-client-go/qbittorrent" ) type Daemon struct { qb qbittorrent.Client client *client dataDir string } func NewDaemon(dir string) (*Daemon, error) { dataDir := dir + "/data" qb, err := qbittorrent.NewClient(&qbittorrent.Config{ Address: "localhost:8080", }) if err != nil { return nil, err } return &Daemon{ qb: qb, dataDir: dataDir, client: wrapClient(qb), }, nil } func (fs *Daemon) torrentPath(ih infohash.T) string { return path.Join(fs.dataDir, ih.HexString()) } func (fs *Daemon) addTorrent(ctx context.Context, f vfs.File) error { file, err := ctxio.ReadAll(ctx, f) if err != nil { return err } mi, err := metainfo.Load(bytes.NewBuffer(file)) if err != nil { return err } ih := mi.HashInfoBytes() err = fs.qb.Torrent().AddNewTorrent(&qbittorrent.TorrentAddOption{ Torrents: []*qbittorrent.TorrentAddFileMetadata{ { Data: file, }, }, SavePath: fs.torrentPath(ih), // SequentialDownload: "true", // FirstLastPiecePrio: "true", }) if err != nil { return err } return nil } func (fs *Daemon) TorrentFS(ctx context.Context, file vfs.File) (*FS, error) { ih, err := readInfoHash(ctx, file) if err != nil { return nil, err } existing, err := fs.qb.Torrent().GetTorrents(&qbittorrent.TorrentOption{ Hashes: []string{ih.HexString()}, }) if err != nil { return nil, err } if len(existing) == 0 { err := fs.addTorrent(ctx, file) if err != nil { return nil, err } } return newTorrentFS(fs.client, file.Name(), ih.HexString(), fs.torrentPath(ih)) } // TODO caching func readInfoHash(ctx context.Context, file vfs.File) (infohash.T, error) { mi, err := metainfo.Load(ctxio.IoReader(ctx, file)) if err != nil { return infohash.T{}, err } return mi.HashInfoBytes(), nil }