Add HTTPProber widget and API to display website statuses

This commit is contained in:
Arindy 2025-12-28 14:25:14 +01:00
parent 598e93c9d2
commit a83958500e
4 changed files with 160 additions and 0 deletions

2
.gitignore vendored
View File

@ -108,4 +108,6 @@ go.work.sum
config.toml
devices.json
websites.json
old

86
apis/httpprober/main.go Normal file
View File

@ -0,0 +1,86 @@
package httpprober
import (
"crypto/tls"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
const websitesFile = "websites.json"
type Website struct {
URL string `json:"url"`
Icon string `json:"icon"`
Status int `json:"status"`
}
func RunProbe() []Website {
results := make([]Website, 0)
websites := websites()
client, err := buildHTTPClient()
if err != nil {
return websites
}
for _, website := range websites {
if website.URL != "" && !strings.Contains(website.URL, "://") {
website.URL = "https://" + website.URL
}
website.Status = testMethod(client, website)
results = append(results, website)
}
return results
}
func websites() []Website {
websites := make([]Website, 0)
file, err := os.ReadFile(websitesFile)
if err == nil {
if err := json.Unmarshal(file, &websites); err != nil {
panic(err)
}
}
return websites
}
func buildHTTPClient() (*http.Client, error) {
timeout := 10
client := &http.Client{
Timeout: time.Duration(timeout) * time.Second,
}
transport := &http.Transport{
TLSClientConfig: &tls.Config{},
}
client.Transport = transport
return client, nil
}
func testMethod(client *http.Client, target Website) int {
req, err := http.NewRequest("GET", target.URL, nil)
if err != nil {
fmt.Println(err)
return -2
}
resp, err := client.Do(req)
if err != nil {
fmt.Println(err)
return -1
}
defer func(body io.ReadCloser) {
_ = body.Close()
}(resp.Body)
return resp.StatusCode
}

View File

@ -38,6 +38,7 @@ func initWidgets(ctx context.Context, term *tcell.Terminal) {
widgets.New("Wifi", widgets.WifiQRCode()),
widgets.New("NetworkDevices", widgets.NetworkDevices()),
widgets.New("Docker", widgets.DockerList()),
widgets.New("HTTPProber", widgets.HTTPProber()),
widgets.New("PiHole", widgets.PiholeStats()),
widgets.New("PiHoleBlocked", widgets.PiholeBlocked()),
)
@ -104,6 +105,13 @@ func layout() []container.Option {
),
),
grid.ColWidthPerc(35,
grid.RowHeightPerc(20,
grid.Widget(widgets.Get["HTTPProber"],
container.BorderTitle("Website Status"),
container.Border(linestyle.Light),
container.BorderColor(cell.ColorWhite),
),
),
grid.RowHeightPerc(25,
grid.Widget(widgets.Get["Docker"],
container.BorderTitle("Docker"),

64
widgets/httpProber.go Normal file
View File

@ -0,0 +1,64 @@
package widgets
import (
"ArinDash/apis/httpprober"
"ArinDash/util"
"context"
"fmt"
"sort"
"strings"
"time"
"github.com/mum4k/termdash/cell"
"github.com/mum4k/termdash/terminal/terminalapi"
"github.com/mum4k/termdash/widgetapi"
"github.com/mum4k/termdash/widgets/text"
)
type HTTPProberOptions struct {
}
func HTTPProber() HTTPProberOptions {
widgetOptions["HTTPProberOptions"] = createHTTPProberList
return HTTPProberOptions{}
}
func createHTTPProberList(ctx context.Context, _ terminalapi.Terminal, _ interface{}) widgetapi.Widget {
list := util.PanicOnErrorWithResult(text.New())
go util.Periodic(ctx, 1*time.Minute, func() error {
websites := httpprober.RunProbe()
sort.Slice(websites, func(i, j int) bool {
return websites[i].Status < websites[j].Status
})
sort.Slice(websites, func(i, j int) bool {
return websites[i].URL < websites[j].URL
})
list.Reset()
for _, website := range websites {
var status []cell.Option
if website.Status >= 500 {
status = append(status, cell.FgColor(cell.ColorRed))
status = append(status, cell.BgColor(cell.ColorBlack))
} else if website.Status >= 400 {
status = append(status, cell.FgColor(cell.ColorYellow))
status = append(status, cell.BgColor(cell.ColorDefault))
} else if website.Status >= 200 {
status = append(status, cell.FgColor(cell.ColorGreen))
status = append(status, cell.BgColor(cell.ColorDefault))
} else {
status = append(status, cell.FgColor(cell.ColorGray))
status = append(status, cell.BgColor(cell.ColorDefault))
}
if err := list.Write(fmt.Sprintf("%2s ", website.Icon), text.WriteCellOpts(status...)); err != nil {
return err
}
if err := list.Write(fmt.Sprintf("%s\n", strings.Split(website.URL, "://")[1]), text.WriteCellOpts(status...)); err != nil {
return err
}
}
return nil
})
return list
}