Complete rewrite to support new API.

This commit is contained in:
Kevin Thompson 2024-11-10 18:10:04 -06:00
parent 856e1b1cbd
commit 60130e243c
3 changed files with 105 additions and 84 deletions

View File

@ -1,9 +1,13 @@
package config
var (
BotToken = "REDACTED"
CFBDAPIKey = "ay2L+7JSttYQP9e10qxpAkluht7NHcyEnSqbBUsqWrwVjBcl02QH2XjOaVDnPRBy"
)
var BotToken = ""
var CustomTeamNames = map[string]string{
"UGA": "Georgia",
"Booger Eaters": "Auburn",
"Rape Enablers": "LSU",
"Checkerboard Clowns": "Tennessee",
}
func LoadConfig() {
}

View File

@ -1,41 +1,41 @@
package bot
import (
"fmt"
"strings"
"discord-cfb-bot/internal/clients/cfb" // Adjust this import path as needed
"github.com/bwmarrin/discordgo"
"discord-cfb-bot/config"
"discord-cfb-bot/internal/clients"
"github.com/bwmarrin/discordgo"
"fmt"
"strings"
)
// MessageCreate handles incoming messages and triggers the appropriate response
func MessageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
// Ignore messages from the bot itself
if m.Author.ID == s.State.User.ID {
return
}
var Bot *discordgo.Session
// Command for fetching college football scores
if strings.HasPrefix(m.Content, "!cfb") {
// Extract any arguments (e.g., week number) if needed
weekNumber := 10 // Replace this with dynamic parsing if necessary
games, err := cfb.FetchScoreboard(weekNumber)
func Start() error {
var err error
Bot, err = discordgo.New("Bot " + config.BotToken)
if err != nil {
s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("Error fetching games: %s", err))
return
return fmt.Errorf("error creating a Discord session: %w", err)
}
if len(games) == 0 {
s.ChannelMessageSend(m.ChannelID, "No games found for this week.")
return
}
fmt.Println("Discord session created successfully")
// Send formatted game summaries
for _, game := range games {
gameSummary := cfb.FormatGameOutput(game)
s.ChannelMessageSend(m.ChannelID, gameSummary)
Bot.AddHandler(commandHandler)
err = Bot.Open()
if err != nil {
return fmt.Errorf("Error opening connection: %w", err)
}
}
fmt.Println("Bot is now running.")
return nil
}
func commandHandler(s *discordgo.Session, m *discordgo.MessageCreate) {
if m.Author.Bot {
return
}
if strings.HasPrefix(m.Content, "!cfb ") {
teamName := strings.TrimSpace(strings.TrimPrefix(m.Content, "!cfb "))
response := cfb.GetGameInfo(teamName)
s.ChannelMessageSend(m.ChannelID, response)
}
}

View File

@ -1,81 +1,98 @@
package cfb
ipackage cfb
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"os"
"time"
"strings"
"discord-cfb-bot/config"
)
// Game represents the structure of a single game
type Game struct {
AwayTeam string `json:"away_team"`
AwayScore string `json:"away_score"`
HomeTeam string `json:"home_team"`
HomeScore string `json:"home_score"`
GameState string `json:"game_state"`
CurrentPeriod string `json:"current_period"`
StartTime string `json:"start_time"`
ContestClock string `json:"contest_clock"`
StartTimeEpoch int64 `json:"start_time_epoch"`
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"`
}
// FetchScoreboard retrieves and parses the scoreboard data from the specified API URL
func FetchScoreboard(weekNumber int) ([]Game, error) {
apiKey := os.Getenv("CFBD_API_KEY")
if apiKey == "" {
return nil, errors.New("missing API key")
type Team struct {
Score string `json:"score"`
Names struct {
Short string `json:"short"`
Full string `json:"full"`
} `json:"names"`
}
func GetGameInfo(teamName string) string {
// Make the teamName input lowercase
teamNameLower := strings.ToLower(teamName)
// Check if the lowercase teamName matches a custom abbreviation
for key, value := range config.CustomTeamNames {
if strings.ToLower(key) == teamNameLower {
teamNameLower = strings.ToLower(value)
break
}
}
url := fmt.Sprintf("https://ncaa.ewnix.net/scoreboard/football/fbs/2024/%d/all-conf", weekNumber)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", apiKey))
client := &http.Client{}
resp, err := client.Do(req)
apiURL := "https://ncaa.ewnix.net/scoreboard/football/fbs/2024/all-conf"
resp, err := http.Get(apiURL)
if err != nil {
return nil, err
return fmt.Sprintf("Failed to reach the scoreboard API: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to fetch scoreboard, status code: %d", resp.StatusCode)
return fmt.Sprintf("Failed to reach the scoreboard API. Status code: %d", resp.StatusCode)
}
body, _ := ioutil.ReadAll(resp.Body)
var data struct {
Games []struct {
Game Game `json:"game"`
} `json:"games"`
var apiResponse struct {
Games []Game `json:"games"`
}
if err := json.Unmarshal(body, &apiResponse); err != nil {
return "Error parsing the API response."
}
if err := json.Unmarshal(body, &data); err != nil {
return nil, fmt.Errorf("error parsing scoreboard: %w", err)
}
var results []string
games := make([]Game, len(data.Games))
for i, g := range data.Games {
// Adjust start time by subtracting 5 hours for upcoming games
if g.Game.GameState == "upcoming" {
epochTime := time.Unix(g.Game.StartTimeEpoch, 0).Add(-5 * time.Hour)
g.Game.StartTime = epochTime.Format("03:04PM ET")
for _, game := range apiResponse.Games {
// Filter games by team name (either home or away)
if strings.ToLower(game.Game.Home.Names.Short) == teamNameLower ||
strings.ToLower(game.Game.Away.Names.Short) == teamNameLower {
var gameInfo string
if game.Game.GameState == "in_progress" {
gameInfo = fmt.Sprintf("%s: **%s** %s: **%s** | Quarter: %s | Time Remaining: %s",
game.Game.Away.Names.Short, game.Game.Away.Score,
game.Game.Home.Names.Short, game.Game.Home.Score,
game.Game.CurrentPeriod, game.Game.ContestClock)
} else if game.Game.GameState == "scheduled" {
gameInfo = fmt.Sprintf("Upcoming: %s @ %s on %s at %s ET",
game.Game.Away.Names.Short, game.Game.Home.Names.Short, game.Game.StartDate, game.Game.StartTime)
} else if game.Game.GameState == "final" {
gameInfo = fmt.Sprintf("Final: %s: %s %s: %s",
game.Game.Away.Names.Short, game.Game.Away.Score,
game.Game.Home.Names.Short, game.Game.Home.Score)
}
results = append(results, gameInfo)
}
games[i] = g.Game
}
return games, nil
}
// FormatGameOutput formats the game data into a string
func FormatGameOutput(game Game) string {
if game.GameState == "live" {
return fmt.Sprintf("%s: *%s* %s: *%s* Quarter: %s Time Remaining: %s",
game.AwayTeam, game.AwayScore, game.HomeTeam, game.HomeScore, game.CurrentPeriod, game.ContestClock)
if len(results) > 0 {
return strings.Join(results, "\n")
}
return fmt.Sprintf("%s: %s %s: %s Final",
game.AwayTeam, game.AwayScore, game.HomeTeam, game.HomeScore)
}
return "No game found for the specified team."
}