package cfb import ( "encoding/json" "fmt" "io/ioutil" "log" "net/http" "strconv" "strings" "time" "unicode" "matrix-scores-bot/config" ) // Game holds the nested game data structure from the API. type Game struct { Game struct { GameID string `json:"gameID"` StartDate string `json:"startDate"` StartTime string `json:"startTime"` StartTimeEpoch string `json:"startTimeEpoch"` GameState string `json:"gameState"` CurrentPeriod string `json:"currentPeriod"` ContestClock string `json:"contestClock"` Home Team `json:"home"` Away Team `json:"away"` FinalMessage string `json:"finalMessage"` } `json:"game"` } // Team holds the team's score and names. type Team struct { Score string `json:"score"` Names struct { Short string `json:"short"` Full string `json:"full"` } `json:"names"` } // GetGameInfo fetches and returns information for a specific team or week. func GetGameInfo(input string) string { teamName := strings.TrimSpace(strings.ToLower(input)) week := "" // Replace custom team name if configured if custom, ok := config.CustomTeamNames[teamName]; ok { log.Printf("Custom team name detected: %s -> %s", teamName, custom) teamName = custom } // Detect week if last two chars are digits if len(teamName) >= 2 { last2 := teamName[len(teamName)-2:] if unicode.IsDigit(rune(last2[0])) && unicode.IsDigit(rune(last2[1])) { week = last2 teamName = strings.TrimSpace(teamName[:len(teamName)-2]) log.Printf("Week detected: %s", week) } } // Build URL url := fmt.Sprintf("https://ncaa.ewnix.net/scoreboard/football/fbs/2024/%s/all-conf", week) if week == "" { url = "https://ncaa.ewnix.net/scoreboard/football/fbs/2024/current/all-conf" } log.Printf("Fetching CFB data from API: %s", url) resp, err := http.Get(url) if err != nil { return fmt.Sprintf("Failed to reach the scoreboard API: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return fmt.Sprintf("API error: status code %d", resp.StatusCode) } body, err := ioutil.ReadAll(resp.Body) if err != nil { return fmt.Sprintf("Error reading API response: %v", err) } var apiResponse struct { Games []Game `json:"games"` } if err := json.Unmarshal(body, &apiResponse); err != nil { return "Error parsing the API response." } results := []string{} teamKey := strings.ToLower(teamName) for _, g := range apiResponse.Games { h := strings.ToLower(g.Game.Home.Names.Short) a := strings.ToLower(g.Game.Away.Names.Short) if h == teamKey || a == teamKey { var info string s := g.Game if s.GameState == "live" { period := s.CurrentPeriod if period == "" { period = "HALFTIME" } info = fmt.Sprintf("%s: %s %s: %s | Quarter: %s | Time Remaining: %s", s.Away.Names.Short, s.Away.Score, s.Home.Names.Short, s.Home.Score, period, s.ContestClock) } else if s.GameState == "pre" { timeCT, err := convertEpochToCentralTime(s.StartTimeEpoch) if err != nil { timeCT = s.StartTime } info = fmt.Sprintf("Upcoming: %s @ %s on %s at %s CT", s.Away.Names.Short, s.Home.Names.Short, s.StartDate, timeCT) } else if s.GameState == "final" { info = fmt.Sprintf("Final: %s: %s %s: %s", s.Away.Names.Short, s.Away.Score, s.Home.Names.Short, s.Home.Score) } results = append(results, info) } } if len(results) > 0 { return strings.Join(results, "\n") } return "No game found for the specified team." } func convertEpochToCentralTime(epochStr string) (string, error) { epoch, err := strconv.ParseInt(epochStr, 10, 64) if err != nil { return "", fmt.Errorf("error parsing epoch: %w", err) } t := time.Unix(epoch, 0).UTC() loc, err := time.LoadLocation("America/Chicago") if err != nil { return "", fmt.Errorf("error loading location: %w", err) } return t.In(loc).Format("03:04 PM"), nil }