package cbb import ( "encoding/json" "fmt" "io/ioutil" "log" "net/http" "strings" "time" "unicode" ) // Game represents the nested game structure from the API response. type Game struct { Game struct { GameID string `json:"gameID"` StartDate string `json:"startDate"` StartTime string `json:"startTime"` 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 score and name details. type Team struct { Score string `json:"score"` Names struct { Short string `json:"short"` Full string `json:"full"` } `json:"names"` } // GetGameInfo fetches and returns basketball game info for a team on a given date. func GetGameInfo(teamName, date string) string { teamKey := strings.ToLower(strings.TrimSpace(teamName)) // Determine date: today in Central Time if none provided if date == "" { loc, err := time.LoadLocation("America/Chicago") if err != nil { loc = time.FixedZone("CST", -6*60*60) } date = time.Now().In(loc).Format("2006/01/02") } else { // Accept MM/DD and convert r := []rune(date) if len(r) == 5 && unicode.IsDigit(r[0]) && unicode.IsDigit(r[1]) && r[2] == '/' && unicode.IsDigit(r[3]) && unicode.IsDigit(r[4]) { date = fmt.Sprintf("2025/%s", date) } else { return "Invalid date format. Please use MM/DD." } } apiURL := fmt.Sprintf("https://ncaa.ewnix.net/scoreboard/basketball-men/d1/%s", date) log.Printf("Fetching CBB data from API: %s", apiURL) resp, err := http.Get(apiURL) 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{} 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 { s := g.Game var info string if s.GameState == "live" { period := s.CurrentPeriod if period == "" { period = "HALFTIME" } info = fmt.Sprintf("Live: %s: %s %s: %s | Half: %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" { startTime, err := time.Parse("03:04PM ET", s.StartTime) if err == nil { startTime = startTime.Add(-1 * time.Hour) info = fmt.Sprintf("Upcoming: %s @ %s on %s at %s CT", s.Away.Names.Short, s.Home.Names.Short, s.StartDate, startTime.Format("03:04 PM CT")) } else { info = fmt.Sprintf("Upcoming: %s @ %s on %s at %s", s.Away.Names.Short, s.Home.Names.Short, s.StartDate, s.StartTime) } } 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." }