add betteruptime support
Some checks failed
Build and Push Docker Image to GHCR / build-and-push (push) Failing after 18m42s
Some checks failed
Build and Push Docker Image to GHCR / build-and-push (push) Failing after 18m42s
This commit is contained in:
2
.github/workflows/docker-publish.yml
vendored
2
.github/workflows/docker-publish.yml
vendored
@@ -10,8 +10,6 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-and-push:
|
build-and-push:
|
||||||
env:
|
|
||||||
RUNNER_TOOL_CACHE: /toolcache
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
|
|||||||
17
README.md
17
README.md
@@ -10,10 +10,10 @@ Passport is a simple, fast, and lightweight web dashboard/new tab replacement.
|
|||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
- [ZQDGR](https://github.com/juls0730/zqdgr)
|
- [ZQDGR](https://github.com/juls0730/zqdgr)
|
||||||
- [Go](https://go.dev/doc/install)
|
- [Go](https://go.dev/doc/install)
|
||||||
- [sqlite3](https://www.sqlite.org/download.html)
|
- [sqlite3](https://www.sqlite.org/download.html)
|
||||||
- [TailwdinCSS CLI](https://github.com/tailwindlabs/tailwindcss/releases/latest)
|
- [TailwdinCSS CLI](https://github.com/tailwindlabs/tailwindcss/releases/latest)
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@@ -85,10 +85,11 @@ The weather integration is optional, and will be enabled automatically if you pr
|
|||||||
|
|
||||||
The uptime integration is optional, and will be enabled automatically if you provide an API key. The following only applies if you are using the UptimeRobot integration.
|
The uptime integration is optional, and will be enabled automatically if you provide an API key. The following only applies if you are using the UptimeRobot integration.
|
||||||
|
|
||||||
| Environment Variable | Description | Required | Default |
|
| Environment Variable | Description | Required | Default |
|
||||||
| ------------------------- | ------------------------------------------------- | -------- | ------- |
|
| ------------------------- | ------------------------------------------------------------------ | -------- | ----------- |
|
||||||
| `PASSPORT_UPTIME_API_KEY` | The UptimeRobot API key | true | |
|
| `UPTIME_PROVIDER` | The uptime provider to use, either `uptimerobot` or `betteruptime` | false | uptimerobot |
|
||||||
| `UPTIME_UPDATE_INTERVAL` | The interval in seconds to update the uptime data | false | 300 |
|
| `PASSPORT_UPTIME_API_KEY` | The UptimeRobot API key | true | |
|
||||||
|
| `UPTIME_UPDATE_INTERVAL` | The interval in seconds to update the uptime data | false | 300 |
|
||||||
|
|
||||||
### Adding links and categories
|
### Adding links and categories
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -16,19 +17,20 @@ type DepricatedUptimeConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type UptimeConfig struct {
|
type UptimeConfig struct {
|
||||||
|
Provider string `env:"UPTIME_PROVIDER" envDefault:"uptimerobot"`
|
||||||
APIKey string
|
APIKey string
|
||||||
UpdateInterval int `env:"UPTIME_UPDATE_INTERVAL" envDefault:"300"`
|
UpdateInterval int `env:"UPTIME_UPDATE_INTERVAL" envDefault:"300"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UptimeRobotSite struct {
|
type UptimeSite struct {
|
||||||
FriendlyName string `json:"friendly_name"`
|
FriendlyName string
|
||||||
Url string `json:"url"`
|
Url string
|
||||||
Status int `json:"status"`
|
Up bool
|
||||||
Up bool `json:"-"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type UptimeManager struct {
|
type UptimeManager struct {
|
||||||
sites []UptimeRobotSite
|
provider string
|
||||||
|
sites []UptimeSite
|
||||||
lastUpdate time.Time
|
lastUpdate time.Time
|
||||||
mutex sync.RWMutex
|
mutex sync.RWMutex
|
||||||
updateChan chan struct{}
|
updateChan chan struct{}
|
||||||
@@ -38,7 +40,7 @@ type UptimeManager struct {
|
|||||||
|
|
||||||
func NewUptimeManager(config *UptimeConfig) *UptimeManager {
|
func NewUptimeManager(config *UptimeConfig) *UptimeManager {
|
||||||
if config.APIKey == "" {
|
if config.APIKey == "" {
|
||||||
log.Fatalln("UptimeRobot API Key is required!")
|
log.Fatalln("An API Key is required to use Uptime Monitoring!")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,10 +50,11 @@ func NewUptimeManager(config *UptimeConfig) *UptimeManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uptimeManager := &UptimeManager{
|
uptimeManager := &UptimeManager{
|
||||||
|
provider: config.Provider,
|
||||||
updateChan: make(chan struct{}),
|
updateChan: make(chan struct{}),
|
||||||
updateInterval: updateInterval,
|
updateInterval: updateInterval,
|
||||||
apiKey: config.APIKey,
|
apiKey: config.APIKey,
|
||||||
sites: []UptimeRobotSite{},
|
sites: []UptimeSite{},
|
||||||
}
|
}
|
||||||
|
|
||||||
go uptimeManager.updateWorker()
|
go uptimeManager.updateWorker()
|
||||||
@@ -61,7 +64,7 @@ func NewUptimeManager(config *UptimeConfig) *UptimeManager {
|
|||||||
return uptimeManager
|
return uptimeManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UptimeManager) GetUptime() []UptimeRobotSite {
|
func (u *UptimeManager) GetUptime() []UptimeSite {
|
||||||
u.mutex.RLock()
|
u.mutex.RLock()
|
||||||
defer u.mutex.RUnlock()
|
defer u.mutex.RUnlock()
|
||||||
return u.sites
|
return u.sites
|
||||||
@@ -81,36 +84,119 @@ func (u *UptimeManager) updateWorker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UptimeRobotSite struct {
|
||||||
|
FriendlyName string `json:"friendly_name"`
|
||||||
|
Url string `json:"url"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
type UptimeRobotResponse struct {
|
type UptimeRobotResponse struct {
|
||||||
Monitors []UptimeRobotSite `json:"monitors"`
|
Monitors []UptimeRobotSite `json:"monitors"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BetterUptimeSite struct {
|
||||||
|
MonitorType string `json:"type"`
|
||||||
|
Attributes struct {
|
||||||
|
PronounceableName string `json:"pronounceable_name"`
|
||||||
|
Url string `json:"url"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
} `json:"attributes"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BetterUptimeResponse struct {
|
||||||
|
Monitors []BetterUptimeSite `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
func (u *UptimeManager) update() {
|
func (u *UptimeManager) update() {
|
||||||
|
var monitors []UptimeSite
|
||||||
|
switch u.provider {
|
||||||
|
case "uptimerobot":
|
||||||
|
monitors = u.updateUptimeRobot()
|
||||||
|
case "betteruptime":
|
||||||
|
monitors = u.updateBetterUptime()
|
||||||
|
default:
|
||||||
|
log.Fatalln("Invalid Uptime Provider!")
|
||||||
|
}
|
||||||
|
|
||||||
|
u.mutex.Lock()
|
||||||
|
u.sites = monitors
|
||||||
|
u.lastUpdate = time.Now()
|
||||||
|
u.mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UptimeManager) updateUptimeRobot() []UptimeSite {
|
||||||
resp, err := http.Post("https://api.uptimerobot.com/v2/getMonitors?api_key="+u.apiKey, "application/json", nil)
|
resp, err := http.Post("https://api.uptimerobot.com/v2/getMonitors?api_key="+u.apiKey, "application/json", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error fetching uptime data: %v\n", err)
|
fmt.Printf("Error fetching uptime data: %v\n", err)
|
||||||
return
|
return []UptimeSite{}
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
body, err := io.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error reading response: %v\n", err)
|
fmt.Printf("Error reading response: %v\n", err)
|
||||||
return
|
return []UptimeSite{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var monitors UptimeRobotResponse
|
var rawMonitors UptimeRobotResponse
|
||||||
if err := json.Unmarshal(body, &monitors); err != nil {
|
if err := json.Unmarshal(body, &rawMonitors); err != nil {
|
||||||
fmt.Printf("Error parsing uptime data: %v\n", err)
|
fmt.Printf("Error parsing uptime data: %v\n", err)
|
||||||
return
|
return []UptimeSite{}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, monitor := range monitors.Monitors {
|
var monitors []UptimeSite
|
||||||
monitors.Monitors[i].Up = monitor.Status == 2
|
for _, rawMonitor := range rawMonitors.Monitors {
|
||||||
|
monitors = append(monitors, UptimeSite{
|
||||||
|
FriendlyName: rawMonitor.FriendlyName,
|
||||||
|
Url: rawMonitor.Url,
|
||||||
|
Up: rawMonitor.Status == 2,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
u.mutex.Lock()
|
return monitors
|
||||||
u.sites = monitors.Monitors
|
}
|
||||||
u.lastUpdate = time.Now()
|
|
||||||
u.mutex.Unlock()
|
func (u *UptimeManager) updateBetterUptime() []UptimeSite {
|
||||||
|
client := &http.Client{}
|
||||||
|
req, err := http.NewRequest("GET", "https://uptime.betterstack.com/api/v2/monitors", nil)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error fetching uptime data: %v\n", err)
|
||||||
|
return []UptimeSite{}
|
||||||
|
}
|
||||||
|
req.Header.Add("Authorization", "Bearer "+u.apiKey)
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error fetching uptime data: %v\n", err)
|
||||||
|
return []UptimeSite{}
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error reading response: %v\n", err)
|
||||||
|
return []UptimeSite{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var rawMonitors BetterUptimeResponse
|
||||||
|
if err := json.Unmarshal(body, &rawMonitors); err != nil {
|
||||||
|
fmt.Printf("Error parsing uptime data: %v\n", err)
|
||||||
|
return []UptimeSite{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// alphabetically sort the monitors because UptimeRobot does, but BetterUptime doesnt (or sorts by something else?), and I want them to be consistent
|
||||||
|
sort.Slice(rawMonitors.Monitors, func(i, j int) bool {
|
||||||
|
return rawMonitors.Monitors[i].Attributes.PronounceableName < rawMonitors.Monitors[j].Attributes.PronounceableName
|
||||||
|
})
|
||||||
|
|
||||||
|
var monitors []UptimeSite
|
||||||
|
for _, rawMonitor := range rawMonitors.Monitors {
|
||||||
|
monitors = append(monitors, UptimeSite{
|
||||||
|
FriendlyName: rawMonitor.Attributes.PronounceableName,
|
||||||
|
Url: rawMonitor.Attributes.Url,
|
||||||
|
Up: rawMonitor.Attributes.Status == "up",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return monitors
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "passport",
|
"name": "passport",
|
||||||
"version": "0.3.4",
|
"version": "0.3.5",
|
||||||
"description": "Passport is a simple, lightweight, and fast dashboard/new tab page for your browser.",
|
"description": "Passport is a simple, lightweight, and fast dashboard/new tab page for your browser.",
|
||||||
"author": "juls0730",
|
"author": "juls0730",
|
||||||
"license": "BSL-1.0",
|
"license": "BSL-1.0",
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
"build:arm64": "zqdgr generate && GOOS=linux GOARCH=arm64 go build -tags netgo,prod -ldflags=\"-w -s\" -o passport-linux-arm64 src/main.go && upx passport-linux-arm64"
|
"build:arm64": "zqdgr generate && GOOS=linux GOARCH=arm64 go build -tags netgo,prod -ldflags=\"-w -s\" -o passport-linux-arm64 src/main.go && upx passport-linux-arm64"
|
||||||
},
|
},
|
||||||
"pattern": "src/**/*.{go,hbs,css,js,svg,png,jpg,jpeg,webp,woff2,ico,webp}",
|
"pattern": "src/**/*.{go,hbs,css,js,svg,png,jpg,jpeg,webp,woff2,ico,webp}",
|
||||||
"excluded_files": [
|
"excluded_globs": [
|
||||||
"src/assets/styles"
|
"src/assets/styles"
|
||||||
],
|
],
|
||||||
"shutdown_signal": "SIGINT"
|
"shutdown_signal": "SIGINT"
|
||||||
|
|||||||
Reference in New Issue
Block a user