102 lines
2 KiB
Go
102 lines
2 KiB
Go
|
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
|
||
|
}
|