github.com/wtfutil/wtf@v0.43.0/modules/football/widget.go (about) 1 package football 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io" 8 "strconv" 9 "strings" 10 11 "github.com/rivo/tview" 12 "github.com/wtfutil/wtf/view" 13 ) 14 15 var leagueID = map[string]leagueInfo{ 16 "BSA": {2013, "Brazil Série A"}, 17 "PL": {2021, "English Premier League"}, 18 "EC": {2016, "English Championship"}, 19 "EUC": {2018, "European Championship"}, 20 "EL2": {444, "Campeonato Brasileiro da Série A"}, 21 "CL": {2001, "UEFA Champions League"}, 22 "FL1": {2015, "French Ligue 1"}, 23 "GB": {2002, "German Bundesliga"}, 24 "ISA": {2019, "Italy Serie A"}, 25 "NE": {2003, "Netherlands Eredivisie"}, 26 "PPL": {2017, "Portugal Primeira Liga"}, 27 "SPD": {2014, "Spain Primera Division"}, 28 "WC": {2000, "FIFA World Cup"}, 29 } 30 31 type Widget struct { 32 view.TextWidget 33 *Client 34 settings *Settings 35 League leagueInfo 36 err error 37 } 38 39 func NewWidget(tviewApp *tview.Application, redrawChan chan bool, pages *tview.Pages, settings *Settings) *Widget { 40 var widget Widget 41 42 leagueId, err := getLeague(settings.league) 43 if err != nil { 44 widget = Widget{ 45 err: fmt.Errorf("unable to get the league id for provided league '%s'", settings.league), 46 Client: NewClient(settings.apiKey), 47 settings: settings, 48 } 49 50 return &widget 51 } 52 53 widget = Widget{ 54 TextWidget: view.NewTextWidget(tviewApp, redrawChan, pages, settings.Common), 55 Client: NewClient(settings.apiKey), 56 League: leagueId, 57 settings: settings, 58 } 59 60 return &widget 61 } 62 63 func (widget *Widget) Refresh() { 64 widget.Redraw(widget.content) 65 } 66 67 func (widget *Widget) content() (string, string, bool) { 68 69 var content string 70 title := fmt.Sprintf("%s %s", widget.CommonSettings().Title, widget.League.caption) 71 wrap := false 72 if widget.err != nil { 73 return title, widget.err.Error(), true 74 } 75 content += widget.GetStandings(widget.League.id) 76 content += widget.GetMatches(widget.League.id) 77 78 return title, content, wrap 79 } 80 81 func getLeague(league string) (leagueInfo, error) { 82 83 var l leagueInfo 84 if val, ok := leagueID[league]; ok { 85 return val, nil 86 } 87 return l, fmt.Errorf("no such league") 88 } 89 90 // GetStandings of particular league 91 func (widget *Widget) GetStandings(leagueId int) string { 92 93 var l LeagueStandings 94 var content string 95 content += "Standings:\n\n" 96 buf := new(bytes.Buffer) 97 tStandings := createTable([]string{"No.", "Team", "MP", "Won", "Draw", "Lost", "GD", "Points"}, buf) 98 resp, err := widget.Client.footballRequest("standings", leagueId) 99 if err != nil { 100 return fmt.Sprintf("Error fetching standings: %s", err.Error()) 101 } 102 defer func() { _ = resp.Body.Close() }() 103 data, err := io.ReadAll(resp.Body) 104 if err != nil { 105 return fmt.Sprintf("Error fetching standings: %s", err.Error()) 106 } 107 err = json.Unmarshal(data, &l) 108 if err != nil { 109 return "Error fetching standings" 110 } 111 112 if len(l.Standings) == 0 { 113 return "Error fetching standings" 114 } 115 116 for _, i := range l.Standings[0].Table { 117 if i.Position <= widget.settings.standingCount { 118 row := []string{strconv.Itoa(i.Position), i.Team.Name, strconv.Itoa(i.PlayedGames), strconv.Itoa(i.Won), strconv.Itoa(i.Draw), strconv.Itoa(i.Lost), strconv.Itoa(i.GoalDifference), strconv.Itoa(i.Points)} 119 tStandings.Append(row) 120 } 121 } 122 123 tStandings.Render() 124 content += buf.String() 125 126 return content 127 } 128 129 // GetMatches of particular league 130 func (widget *Widget) GetMatches(leagueId int) string { 131 132 var l LeagueFixtuers 133 var content string 134 scheduledBuf := new(bytes.Buffer) 135 playedBuf := new(bytes.Buffer) 136 137 tScheduled := createTable([]string{}, scheduledBuf) 138 tPlayed := createTable([]string{}, playedBuf) 139 140 from := getDateString(-widget.settings.matchesFrom) 141 to := getDateString(widget.settings.matchesTo) 142 143 requestPath := fmt.Sprintf("matches?dateFrom=%s&dateTo=%s", from, to) 144 resp, err := widget.Client.footballRequest(requestPath, leagueId) 145 if err != nil { 146 return fmt.Sprintf("Error fetching matches: %s", err.Error()) 147 } 148 defer func() { _ = resp.Body.Close() }() 149 data, err := io.ReadAll(resp.Body) 150 if err != nil { 151 return fmt.Sprintf("Error fetching matches: %s", err.Error()) 152 } 153 err = json.Unmarshal(data, &l) 154 if err != nil { 155 return fmt.Sprintf("Error fetching matches: %s", err.Error()) 156 } 157 158 if len(l.Matches) == 0 { 159 return "Error fetching matches" 160 } 161 162 for _, m := range l.Matches { 163 164 widget.markFavorite(&m) 165 166 if m.Status == "SCHEDULED" { 167 row := []string{m.HomeTeam.Name, "🆚", m.AwayTeam.Name, parseDateString(m.Date)} 168 tScheduled.Append(row) 169 } else if m.Status == "FINISHED" { 170 row := []string{m.HomeTeam.Name, strconv.Itoa(m.Score.FullTime.HomeTeam), "🆚", m.AwayTeam.Name, strconv.Itoa(m.Score.FullTime.AwayTeam)} 171 tPlayed.Append(row) 172 } 173 } 174 175 tScheduled.Render() 176 tPlayed.Render() 177 if playedBuf.String() != "" { 178 content += "\nMatches Played:\n\n" 179 content += playedBuf.String() 180 181 } 182 if scheduledBuf.String() != "" { 183 content += "\nUpcoming Matches:\n\n" 184 content += scheduledBuf.String() 185 } 186 187 return content 188 } 189 190 func (widget *Widget) markFavorite(m *Matches) { 191 192 switch { 193 194 case widget.settings.favTeam == "": 195 return 196 case strings.Contains(m.AwayTeam.Name, widget.settings.favTeam): 197 m.AwayTeam.Name = fmt.Sprintf("%s ⭐", m.AwayTeam.Name) 198 case strings.Contains(m.HomeTeam.Name, widget.settings.favTeam): 199 m.HomeTeam.Name = fmt.Sprintf("%s ⭐", m.HomeTeam.Name) 200 } 201 }