15 "github.com/anacrolix/dht/v2"
16 "github.com/anacrolix/torrent"
17 "github.com/anacrolix/torrent/metainfo"
18 "github.com/dustin/go-humanize"
29 TorrentStats = map[metainfo.Hash]torrent.TorrentStats{}
30 TorrentStatsM sync.RWMutex
33 func recreateFIFO(pth string) {
35 if err := syscall.Mkfifo(pth, 0666); err != nil {
40 func shortenName(name string) string {
42 if len(s) > MaxListNameWidth {
43 s = s[:MaxListNameWidth]
48 func fifoList(c *torrent.Client) {
49 pth := path.Join(FIFOsDir, "list")
52 fd, err := os.OpenFile(pth, os.O_WRONLY|os.O_APPEND, os.FileMode(0666))
54 log.Println("OpenFile:", pth, err)
55 time.Sleep(time.Second)
59 sort.Sort(ByInfoHash(ts))
60 for _, t := range ts {
62 fmt.Fprintf(fd, "%s not ready\n", t.Name())
66 done := t.BytesCompleted() * 100 / t.Length()
71 tx := stats.BytesWrittenData.Int64()
72 tx += TxStats[t.InfoHash()]
73 ratio := float64(tx) / float64(t.Length())
75 prev := TorrentStats[t.InfoHash()]
76 TorrentStatsM.RUnlock()
77 rxSpeed := stats.BytesReadData.Int64() - prev.BytesReadData.Int64()
78 txSpeed := stats.BytesWrittenData.Int64() - prev.BytesWrittenData.Int64()
80 if done < 100 && rxSpeed > 0 {
81 etaRaw := time.Duration((t.Length() - t.BytesCompleted()) / rxSpeed)
86 "%s%s%s %s%40s%s %8s %s%3d%%%s %4.1f %s%d%s/%s%d%s %d/%d/%d/%d %s\n",
87 Blue, t.InfoHash().HexString(), Reset,
88 Green, shortenName(t.Name()), Reset,
89 humanize.IBytes(uint64(t.Length())),
90 percColour, done, Reset,
92 Green, rxSpeed/1024, Reset,
93 Magenta, txSpeed/1024, Reset,
97 stats.ConnectedSeeders,
102 time.Sleep(time.Second)
106 func fifoPeerList(t *torrent.Torrent) {
107 pth := path.Join(FIFOsDir, PeersDir, t.InfoHash().HexString())
110 fd, err := os.OpenFile(pth, os.O_WRONLY|os.O_APPEND, os.FileMode(0666))
112 if os.IsNotExist(err) {
115 log.Println("OpenFile:", pth, err)
116 time.Sleep(time.Second)
120 sort.Sort(ByPeerID(pcs))
121 for _, pc := range pcs {
122 completed := pc.CompletedString()
123 completedColour := Red
124 cols := strings.Split(completed, "/")
125 if cols[0] == cols[1] {
126 completedColour = Green
128 stats := pc.Peer.Stats()
130 "%s%s%s %10s %s%11s%s %s%d%s/%s%d%s %s / %s | %s%s%s %q\n",
131 Blue, hex.EncodeToString(pc.PeerID[:]), Reset,
133 completedColour, pc.CompletedString(), Reset,
134 Green, int(pc.DownloadRate()/1024), Reset,
135 Magenta, int(pc.UploadRate()/1024), Reset,
136 humanize.IBytes(uint64(stats.BytesReadData.Int64())),
137 humanize.IBytes(uint64(stats.BytesWrittenData.Int64())),
138 Green, pc.RemoteAddr, Reset,
143 time.Sleep(time.Second)
147 func fifoFileList(t *torrent.Torrent) {
148 pth := path.Join(FIFOsDir, FilesDir, t.InfoHash().HexString())
151 fd, err := os.OpenFile(pth, os.O_WRONLY|os.O_APPEND, os.FileMode(0666))
153 if os.IsNotExist(err) {
156 log.Println("OpenFile:", pth, err)
157 time.Sleep(time.Second)
160 for n, f := range t.Files() {
163 done = (f.BytesCompleted() * 100) / f.Length()
170 "%5d %8s %3d%% | %s%s%s\n",
171 n, humanize.IBytes(uint64(f.Length())), done,
172 percColour, f.Path(), Reset,
176 time.Sleep(time.Second)
180 func fifoDHTList(c *torrent.Client) {
181 pth := path.Join(FIFOsDir, "dht")
184 fd, err := os.OpenFile(pth, os.O_WRONLY|os.O_APPEND, os.FileMode(0666))
186 if os.IsNotExist(err) {
189 log.Println("OpenFile:", pth, err)
190 time.Sleep(time.Second)
193 for _, s := range c.DhtServers() {
194 stats := s.Stats().(dht.ServerStats)
196 fd, "%s%s%s all:%d good:%d await:%d succ:%d bad:%d\n",
197 Green, s.Addr().String(), Reset,
200 stats.OutstandingTransactions,
201 stats.SuccessfulOutboundAnnouncePeerQueries,
206 time.Sleep(time.Second)