go-transmission-stats/html/main.go

241 lines
5.7 KiB
Go
Raw Permalink Normal View History

2023-04-02 00:23:09 +02:00
package main
import (
"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)
}
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
)
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 := `<!DOCTYPE html>
<html>
<head>
2023-12-12 01:54:32 +01:00
<title>Torrent Stats - hyperreal.coffee</title>
<link href="style.css" rel="stylesheet">
</head>
<style>
body {
max-width: 96%;
}
</style>
<body>
<div class="container">
<h1>Torrent Stats</h1>
<p>As of {{.Date}}</p>
<h2>Session Stats</h2>
<table>
{{range .SessionStats}}
<tr>
<td>{{.Label}}</td>
<td>{{.Value}}</td>
</tr>
{{end}}
</table>
<h2>Current Stats</h2>
<table>
{{range .CurrentStats}}
<tr>
<td>{{.Label}}</td>
<td>{{.Value}}</td>
</tr>
{{end}}
</table>
<h2>Cumulative Stats</h2>
<table>
{{range .CumulativeStats}}
<tr>
<td>{{.Label}}</td>
<td>{{.Value}}</td>
</tr>
{{end}}
</table>
<h2>Torrent Info</h2>
<table>
<tr>
<th>Name</th>
<th>Activity Date</th>
<th>Total Size</th>
<th>Leechers</th>
<th>Seeders</th>
</tr>
{{range .TorrentInfo}}
<tr>
<td>{{.Name}}</td>
<td>{{.ActivityDate}}</td>
<td>{{.TotalSize}}</td>
<td>{{.Leechers}}</td>
<td>{{.Seeders}}</td>
</tr>
{{end}}
</table>
</div>
</body>
</html>
`
html, err := template.New("torrentstats").Parse(htmlTemplate)
2023-05-18 01:19:34 +02:00
if err != nil {
log.Fatalln(err)
}
htmlOutputFile, err := os.Create(os.Getenv("HTML_FILE"))
2023-05-18 01:19:34 +02:00
if err != nil {
log.Fatalln(err)
}
defer htmlOutputFile.Close()
2023-05-18 01:19:34 +02:00
if err = html.Execute(htmlOutputFile, data); err != nil {
2023-05-18 01:19:34 +02:00
log.Fatalln(err)
2023-04-02 00:23:09 +02:00
}
}