diff --git a/.env.example b/.env.example index 9d1db55..4d61080 100644 --- a/.env.example +++ b/.env.example @@ -1 +1,2 @@ TRAEWELLING_TOKEN= +TRAEWELLING_USERNAMES= diff --git a/docker-compose.yml b/docker-compose.yml index ca05ed2..1c51c6b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,6 +10,7 @@ services: restart: always # Neustart bei Fehlern oder Updates environment: - TRAEWELLING_TOKEN=${TRAEWELLING_TOKEN} + - TRAEWELLING_USERNAMES=${TRAEWELLING_USERNAMES} networks: default: dns: diff --git a/go/main.go b/go/main.go index 35d50de..e592fbc 100644 --- a/go/main.go +++ b/go/main.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" "os" + "strings" "time" "github.com/prometheus/client_golang/prometheus" @@ -12,7 +13,7 @@ import ( "github.com/prometheus/client_golang/prometheus/promhttp" ) -type DashboardResponse struct { +type StatusResponse struct { Data []struct { ID int `json:"id"` User struct { @@ -65,8 +66,8 @@ var ( ) ) -func fetchTraewellingData() (*DashboardResponse, error) { - url := "https://traewelling.de/api/v1/dashboard" +func fetchStatuses(username string) (*StatusResponse, error) { + url := fmt.Sprintf("https://traewelling.de/api/v1/user/%s/statuses", username) client := &http.Client{Timeout: 10 * time.Second} req, err := http.NewRequest("GET", url, nil) if err != nil { @@ -82,79 +83,86 @@ func fetchTraewellingData() (*DashboardResponse, error) { resp, err := client.Do(req) if err != nil { - return nil, fmt.Errorf("Fehler beim Senden der Anfrage: %v", err) - } + return nil, fmt.Errorf("Fehler beim Senden der Anfrage für Benutzer '%s': %v", username, err) + } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("Fehlerhafte Antwort: %d", resp.StatusCode) - } + return nil, fmt.Errorf("Fehlerhafte Antwort für Benutzer '%s': %d", username, resp.StatusCode) + } - var apiResponse DashboardResponse + var apiResponse StatusResponse err = json.NewDecoder(resp.Body).Decode(&apiResponse) if err != nil { - return nil, fmt.Errorf("Fehler beim Parsen der JSON-Daten: %v", err) - } + return nil, fmt.Errorf("Fehler beim Parsen der JSON-Daten für Benutzer '%s': %v", username, err) + } - return &apiResponse, nil + return &apiResponse, nil } -func processAndPrintTripDetails(data *DashboardResponse) { - fmt.Println("Fahrtdetails der Benutzer:") +func processAndPrintTripDetails(username string, data *StatusResponse) { + fmt.Printf("Fahrtdetails für Benutzer '%s':\n", username) fmt.Println("==========================") - userStats := make(map[string]struct { - TotalDuration float64 - TotalPoints int - TotalDistance float64 - }) + var totalDuration float64 + var totalPoints int + var totalDistance float64 for _, trip := range data.Data { - fmt.Printf("Benutzer: %s (@%s)\n", trip.User.DisplayName, trip.User.Username) - fmt.Printf("Fahrt-ID: %d\n", trip.Train.Trip) - fmt.Printf("Kategorie: %s\n", trip.Train.Category) - fmt.Printf("Linie: %s (Nummer: %d)\n", trip.Train.LineName, trip.Train.JourneyNumber) - fmt.Printf("Startbahnhof: %s\n", trip.Train.Origin.Name) - fmt.Printf("\tGeplante Abfahrt: %s\n", trip.Train.Origin.DeparturePlanned) - fmt.Printf("\tTatsächliche Abfahrt: %s\n", trip.Train.Origin.DepartureReal) - fmt.Printf("Zielbahnhof: %s\n", trip.Train.Destination.Name) - fmt.Printf("\tGeplante Ankunft: %s\n", trip.Train.Destination.ArrivalPlanned) - fmt.Printf("\tTatsächliche Ankunft: %s\n", trip.Train.Destination.ArrivalReal) - fmt.Printf("Dauer: %d Minuten\n", trip.Train.Duration) - fmt.Printf("Entfernung: %.2f km\n", trip.Train.Distance/1000) - fmt.Printf("Punkte: %d\n", trip.Train.Points) - fmt.Println("--------------------------") + fmt.Printf("Fahrt-ID: %d\n", trip.Train.Trip) + fmt.Printf("Kategorie: %s\n", trip.Train.Category) + fmt.Printf("Linie: %s (Nummer: %d)\n", trip.Train.LineName, trip.Train.JourneyNumber) + fmt.Printf("Startbahnhof: %s\n", trip.Train.Origin.Name) + fmt.Printf("\tGeplante Abfahrt: %s\n", trip.Train.Origin.DeparturePlanned) + fmt.Printf("\tTatsächliche Abfahrt: %s\n", trip.Train.Origin.DepartureReal) + fmt.Printf("Zielbahnhof: %s\n", trip.Train.Destination.Name) + fmt.Printf("\tGeplante Ankunft: %s\n", trip.Train.Destination.ArrivalPlanned) + fmt.Printf("\tTatsächliche Ankunft: %s\n", trip.Train.Destination.ArrivalReal) + fmt.Printf("Dauer: %d Minuten\n", trip.Train.Duration) + fmt.Printf("Entfernung: %.2f km\n", trip.Train.Distance/1000) + fmt.Printf("Punkte: %d\n", trip.Train.Points) + fmt.Println("--------------------------") - stats := userStats[trip.User.Username] - stats.TotalDuration += float64(trip.Train.Duration) - stats.TotalPoints += trip.Train.Points - stats.TotalDistance += trip.Train.Distance / 1000 - userStats[trip.User.Username] = stats - } + totalDuration += float64(trip.Train.Duration) + totalPoints += trip.Train.Points + totalDistance += trip.Train.Distance / 1000 + } - for username, stats := range userStats { - totalTripDuration.WithLabelValues(username).Set(stats.TotalDuration) - totalTripPoints.WithLabelValues(username).Set(float64(stats.TotalPoints)) - totalTripDistance.WithLabelValues(username).Set(stats.TotalDistance) - } + totalTripDuration.WithLabelValues(username).Set(totalDuration) + totalTripPoints.WithLabelValues(username).Set(float64(totalPoints)) + totalTripDistance.WithLabelValues(username).Set(totalDistance) + + fmt.Printf("\nGesamtfahrzeit für %s: %.2f Minuten\n", username, totalDuration) + fmt.Printf("Gesamtpunkte für %s: %d Punkte\n", username, totalPoints) + fmt.Printf("Gesamtentfernung für %s: %.2f km\n", username, totalDistance) } func updateMetrics() { - data, err := fetchTraewellingData() - if err != nil { - fmt.Printf("Fehler beim Abrufen der Daten: %v\n", err) - return - } - processAndPrintTripDetails(data) + usernames := os.Getenv("TRAEWELLING_USERNAMES") + if usernames == "" { + fmt.Println("TRAEWELLING_USERNAMES ist nicht gesetzt") + return + } + + for _, username := range strings.Split(usernames, ",") { + username = strings.TrimSpace(username) // Entferne Leerzeichen + data, err := fetchStatuses(username) + if err != nil { + fmt.Printf("Fehler beim Abrufen der Daten für Benutzer '%s': %v\n", username, err) + continue + } + + processAndPrintTripDetails(username, data) + } } func main() { go func() { - for { - updateMetrics() - time.Sleep(5 * time.Minute) - } - }() + for { + updateMetrics() + time.Sleep(5 * time.Minute) // Aktualisierung alle 5 Minuten + } + }() http.Handle("/metrics", promhttp.Handler()) fmt.Println("Server läuft auf Port 8080...")