2023-04-02 00:23:09 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2023-07-20 00:01:54 +02:00
|
|
|
"context"
|
2023-04-02 00:23:09 +02:00
|
|
|
"fmt"
|
2023-05-18 01:19:34 +02:00
|
|
|
"html/template"
|
2023-04-02 00:23:09 +02:00
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"sort"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/hekmon/cunits/v2"
|
2023-07-19 18:35:00 +02:00
|
|
|
"github.com/hyperreal64/transmissionrpc"
|
2023-04-02 00:23:09 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
func byteCountIEC(b int64) string {
|
|
|
|
const unit = 1024
|
|
|
|
if b < unit {
|
|
|
|
return fmt.Sprintf("%d B", b)
|
|
|
|
}
|
|
|
|
|
|
|
|
div, exp := int64(unit), 0
|
|
|
|
for n := b / unit; n >= unit; n /= unit {
|
|
|
|
div *= unit
|
|
|
|
exp++
|
|
|
|
}
|
|
|
|
|
|
|
|
return fmt.Sprintf("%.1f %ciB", float64(b)/float64(div), "KMGTPE"[exp])
|
|
|
|
}
|
|
|
|
|
|
|
|
func convertTime(seconds int64) string {
|
|
|
|
switch {
|
|
|
|
case seconds > 86400:
|
|
|
|
day := seconds / 86400
|
|
|
|
remainder := seconds % 86400
|
|
|
|
hour := remainder / 3600
|
|
|
|
remainder = remainder % 3600
|
|
|
|
minutes := remainder / 60
|
|
|
|
remainder = remainder % 60
|
|
|
|
|
|
|
|
return fmt.Sprintf("%d days, %d hours, %d minutes, %d seconds", day, hour, minutes, remainder)
|
|
|
|
|
|
|
|
case seconds < 86400 && seconds > 3600:
|
|
|
|
hour := seconds / 3600
|
|
|
|
remainder := seconds % 3600
|
|
|
|
minutes := remainder / 60
|
|
|
|
remainder = remainder % 60
|
|
|
|
|
|
|
|
return fmt.Sprintf("%d hours, %d minutes, %d seconds", hour, minutes, remainder)
|
|
|
|
|
|
|
|
case seconds < 3600 && seconds > 60:
|
|
|
|
minutes := seconds / 60
|
|
|
|
remainder := seconds % 60
|
|
|
|
|
|
|
|
return fmt.Sprintf("%d minutes, %d seconds", minutes, remainder)
|
|
|
|
|
|
|
|
default:
|
|
|
|
return fmt.Sprintf("%d seconds", seconds)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-05-18 01:19:34 +02:00
|
|
|
type SessionStat struct {
|
|
|
|
Label string
|
|
|
|
Value string
|
2023-04-16 23:45:38 +02:00
|
|
|
}
|
|
|
|
|
2023-04-02 00:23:09 +02:00
|
|
|
type TorrentInfo struct {
|
2023-04-16 23:45:38 +02:00
|
|
|
Name string
|
|
|
|
ActivityDate time.Time
|
|
|
|
TotalSize cunits.Bits
|
|
|
|
Leechers int64
|
|
|
|
Seeders int64
|
2023-04-02 00:23:09 +02:00
|
|
|
}
|
|
|
|
|
2023-05-18 01:19:34 +02:00
|
|
|
type TorrentStatsPageData struct {
|
|
|
|
Date string
|
|
|
|
SessionStats []SessionStat
|
|
|
|
CurrentStats []SessionStat
|
|
|
|
CumulativeStats []SessionStat
|
|
|
|
TorrentInfo []TorrentInfo
|
2023-04-05 22:52:26 +02:00
|
|
|
}
|
|
|
|
|
2023-04-02 00:23:09 +02:00
|
|
|
func main() {
|
2023-07-25 02:46:49 +02:00
|
|
|
transmissionbt, err := transmissionrpc.New(os.Getenv("TRANSMISSION_RPC_URL"), os.Getenv("TRANSMISSION_RPC_USER"), os.Getenv("TRANSMISSION_RPC_PASSWORD"), nil)
|
2023-04-02 00:23:09 +02:00
|
|
|
if err != nil {
|
|
|
|
log.Fatalln(err)
|
|
|
|
}
|
|
|
|
|
2023-07-20 00:01:54 +02:00
|
|
|
stats, err := transmissionbt.SessionStats(context.TODO())
|
2023-04-02 00:23:09 +02:00
|
|
|
if err != nil {
|
|
|
|
log.Fatalln(err)
|
|
|
|
}
|
|
|
|
|
2023-05-18 01:19:34 +02:00
|
|
|
sessionStats := []SessionStat{
|
|
|
|
{Label: "Active torrent count", Value: fmt.Sprintf("%d", stats.ActiveTorrentCount)},
|
|
|
|
{Label: "Download speed", Value: fmt.Sprintf("%s/sec", byteCountIEC(stats.DownloadSpeed))},
|
|
|
|
{Label: "Upload speed", Value: fmt.Sprintf("%s/sec", byteCountIEC(stats.UploadSpeed))},
|
|
|
|
{Label: "Paused torrent count", Value: fmt.Sprintf("%d", stats.PausedTorrentCount)},
|
|
|
|
{Label: "Torrent count", Value: fmt.Sprintf("%d", stats.TorrentCount)},
|
2023-04-02 00:23:09 +02:00
|
|
|
}
|
|
|
|
|
2023-05-18 01:19:34 +02:00
|
|
|
currentStats := []SessionStat{
|
|
|
|
{Label: "Uploaded bytes", Value: fmt.Sprintf("%s", byteCountIEC(stats.CurrentStats.UploadedBytes))},
|
|
|
|
{Label: "Downloaded bytes", Value: fmt.Sprintf("%s", byteCountIEC(stats.CurrentStats.DownloadedBytes))},
|
|
|
|
{Label: "Files added", Value: fmt.Sprintf("%d", stats.CurrentStats.FilesAdded)},
|
|
|
|
{Label: "Session count", Value: fmt.Sprintf("%d", stats.CurrentStats.SessionCount)},
|
|
|
|
{Label: "Time active", Value: convertTime(stats.CurrentStats.SecondsActive)},
|
2023-04-02 00:23:09 +02:00
|
|
|
}
|
|
|
|
|
2023-05-18 01:19:34 +02:00
|
|
|
cumulativeStats := []SessionStat{
|
|
|
|
{Label: "Uploaded bytes", Value: fmt.Sprintf("%s", byteCountIEC(stats.CumulativeStats.UploadedBytes))},
|
|
|
|
{Label: "Downloaded bytes", Value: fmt.Sprintf("%s", byteCountIEC(stats.CumulativeStats.DownloadedBytes))},
|
|
|
|
{Label: "Files added", Value: fmt.Sprintf("%d", stats.CumulativeStats.FilesAdded)},
|
|
|
|
{Label: "Session count", Value: fmt.Sprintf("%d", stats.CumulativeStats.SessionCount)},
|
|
|
|
{Label: "Time active", Value: convertTime(stats.CumulativeStats.SecondsActive)},
|
2023-04-02 00:23:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
var torrentInfo = []TorrentInfo{}
|
2023-04-16 23:45:38 +02:00
|
|
|
var (
|
|
|
|
leecherCount int64
|
|
|
|
seederCount int64
|
|
|
|
)
|
|
|
|
|
2023-07-20 00:01:54 +02:00
|
|
|
torrents, err := transmissionbt.TorrentGet(context.TODO(), []string{"name", "activityDate", "totalSize", "trackerStats"}, nil)
|
2023-04-02 00:23:09 +02:00
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintln(os.Stderr, err)
|
|
|
|
} else {
|
|
|
|
for _, torrent := range torrents {
|
2023-04-16 23:45:38 +02:00
|
|
|
for _, stat := range torrent.TrackerStats {
|
|
|
|
leecherCount = stat.LeecherCount
|
|
|
|
seederCount = stat.SeederCount
|
|
|
|
}
|
|
|
|
torrentInfo = append(torrentInfo, TorrentInfo{
|
|
|
|
Name: *torrent.Name,
|
|
|
|
ActivityDate: *torrent.ActivityDate,
|
|
|
|
TotalSize: *torrent.TotalSize,
|
|
|
|
Leechers: leecherCount,
|
|
|
|
Seeders: seederCount,
|
|
|
|
})
|
2023-04-02 00:23:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sort.Slice(torrentInfo, func(i, j int) bool {
|
|
|
|
return torrentInfo[i].Name < torrentInfo[j].Name
|
|
|
|
})
|
|
|
|
|
2023-05-18 01:19:34 +02:00
|
|
|
data := TorrentStatsPageData{
|
|
|
|
Date: time.Now().Format(time.UnixDate),
|
|
|
|
SessionStats: sessionStats,
|
|
|
|
CurrentStats: currentStats,
|
|
|
|
CumulativeStats: cumulativeStats,
|
|
|
|
TorrentInfo: torrentInfo,
|
|
|
|
}
|
|
|
|
|
|
|
|
htmlTemplate, err := template.ParseFiles("template.html")
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalln(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
htmlFile, err := os.Create(os.Getenv("HTML_FILE"))
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalln(err)
|
|
|
|
}
|
|
|
|
defer htmlFile.Close()
|
|
|
|
|
|
|
|
if err = htmlTemplate.Execute(htmlFile, data); err != nil {
|
|
|
|
log.Fatalln(err)
|
2023-04-02 00:23:09 +02:00
|
|
|
}
|
|
|
|
}
|