From 549dffeb2479d7dd51c35846b09f59f4c01803ad Mon Sep 17 00:00:00 2001 From: Chew Date: Mon, 29 Jul 2024 20:44:02 -0400 Subject: [PATCH 1/3] initial team command --- src/main/java/pw/chew/mlb/MLBBot.java | 3 +- .../chew/mlb/commands/StandingsCommand.java | 9 +- .../pw/chew/mlb/commands/TeamCommand.java | 175 ++++++++++++++++++ .../mlb/listeners/InteractionHandler.java | 14 ++ .../java/pw/chew/mlb/objects/MLBTeam.java | 12 ++ .../java/pw/chew/mlb/util/MLBAPIUtil.java | 160 +++++++++++++++- 6 files changed, 367 insertions(+), 6 deletions(-) create mode 100644 src/main/java/pw/chew/mlb/commands/TeamCommand.java diff --git a/src/main/java/pw/chew/mlb/MLBBot.java b/src/main/java/pw/chew/mlb/MLBBot.java index d7a9ffa..95eea93 100644 --- a/src/main/java/pw/chew/mlb/MLBBot.java +++ b/src/main/java/pw/chew/mlb/MLBBot.java @@ -20,6 +20,7 @@ import pw.chew.mlb.commands.StandingsCommand; import pw.chew.mlb.commands.StartGameCommand; import pw.chew.mlb.commands.StopGameCommand; +import pw.chew.mlb.commands.TeamCommand; import pw.chew.mlb.listeners.InteractionHandler; import pw.chew.mlb.listeners.JDAListeners; import pw.chew.mlb.util.TeamEmoji; @@ -65,7 +66,7 @@ public static void main(String[] args) throws IOException { new StartGameCommand(), new StopGameCommand(), new ScoreCommand(), new SetInfoCommand(), new ConfigCommand(), new PlanGameCommand() , // Util Commands - new StandingsCommand() + new StandingsCommand(), new TeamCommand() ); //client.forceGuildOnly("148195924567392257"); diff --git a/src/main/java/pw/chew/mlb/commands/StandingsCommand.java b/src/main/java/pw/chew/mlb/commands/StandingsCommand.java index bd2d7b2..4aa6095 100644 --- a/src/main/java/pw/chew/mlb/commands/StandingsCommand.java +++ b/src/main/java/pw/chew/mlb/commands/StandingsCommand.java @@ -3,6 +3,7 @@ import com.jagrosh.jdautilities.command.SlashCommand; import com.jagrosh.jdautilities.command.SlashCommandEvent; import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.interactions.DiscordLocale; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; @@ -43,8 +44,12 @@ public StandingsCommand() { protected void execute(SlashCommandEvent event) { String division = event.optString("division", "American League West"); + event.replyEmbeds(buildDivisionEmbed(division)).setEphemeral(true).queue(); + } + + public static MessageEmbed buildDivisionEmbed(String division) { // first we get standings - var standings = MLBAPIUtil.getStandings().get(division); + var standings = MLBAPIUtil.getStandings("103,104").get(division); List teams = new ArrayList<>(); for (MLBAPIUtil.Standing standing : standings) { @@ -65,6 +70,6 @@ protected void execute(SlashCommandEvent event) { .setTitle("Standings for " + division) .setDescription(String.join("\n", teams)); - event.replyEmbeds(embed.build()).setEphemeral(true).queue(); + return embed.build(); } } diff --git a/src/main/java/pw/chew/mlb/commands/TeamCommand.java b/src/main/java/pw/chew/mlb/commands/TeamCommand.java new file mode 100644 index 0000000..555ea81 --- /dev/null +++ b/src/main/java/pw/chew/mlb/commands/TeamCommand.java @@ -0,0 +1,175 @@ +package pw.chew.mlb.commands; + +import com.jagrosh.jdautilities.command.SlashCommand; +import com.jagrosh.jdautilities.command.SlashCommandEvent; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.entities.emoji.Emoji; +import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent; +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; +import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent; +import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.api.interactions.commands.build.OptionData; +import net.dv8tion.jda.api.interactions.components.ActionRow; +import net.dv8tion.jda.api.interactions.components.buttons.Button; +import net.dv8tion.jda.api.interactions.components.selections.SelectOption; +import net.dv8tion.jda.api.interactions.components.selections.StringSelectMenu; +import org.json.JSONArray; +import org.json.JSONObject; +import pw.chew.chewbotcca.util.RestClient; +import pw.chew.mlb.util.AutocompleteUtil; +import pw.chew.mlb.util.MLBAPIUtil; +import pw.chew.mlb.util.TeamEmoji; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static pw.chew.mlb.MLBBot.SEASON; + +public class TeamCommand extends SlashCommand { + public TeamCommand() { + this.name = "team"; + this.help = "Get information about a team."; + this.guildOnly = false; + this.options = List.of( + new OptionData(OptionType.STRING, "team", "Type to search for a team!", true, true) + ); + + // TODO: Future, make this installable in user contexts + } + + @Override + protected void execute(SlashCommandEvent event) { + String teamId = event.optString("team", "140"); + List affiliates = MLBAPIUtil.getAffiliates(teamId); + MLBAPIUtil.Affiliate currentAffiliate = affiliates.stream().filter(af -> (af.id() + "").equals(teamId)).findFirst().orElse(null); + if (currentAffiliate == null) { + event.reply("I couldn't find a team with that ID!").setEphemeral(true).queue(); + return; + } + + String componentKeyBase = "team:" + teamId + ":"; + + EmbedBuilder embed = new EmbedBuilder() + .setTitle("Information for " + currentAffiliate.name()) + .setDescription("Yeah this sure is some information, huh?") + .addField("Record", "%s-%s".formatted(currentAffiliate.wins(), currentAffiliate.losses()), true) + .setFooter("Team ID: " + teamId); + + // Build the affiliate list :3 + List options = new ArrayList<>(); + for (MLBAPIUtil.Affiliate affiliate : affiliates) { + options.add(SelectOption.of(affiliate.name(), affiliate.id() + "").withDescription(affiliate.sport().name()).withEmoji(TeamEmoji.fromName(affiliate.name()))); + } + + StringSelectMenu menu = StringSelectMenu.create(componentKeyBase + "affiliates") + .setPlaceholder("Select an Affiliate!") + .addOptions(options) + .build(); + + event.replyEmbeds(embed.build()) + .addActionRow(menu) + .addActionRow( + Button.primary(componentKeyBase + "standings:" + currentAffiliate.leagueId(), "Standings").withEmoji(Emoji.fromUnicode("📊")), + Button.primary(componentKeyBase + "roster", "Roster").withEmoji(Emoji.fromUnicode("📋")), + Button.primary(componentKeyBase + "transactions", "Transactions").withEmoji(Emoji.fromUnicode("💸")), + Button.primary(componentKeyBase + "schedule", "Schedule").withEmoji(Emoji.fromUnicode("📅")), + Button.primary(componentKeyBase + "stats", "Stats").withEmoji(Emoji.fromUnicode("📈")) + ).setEphemeral(true).queue(); + } + + @Override + public void onAutoComplete(CommandAutoCompleteInteractionEvent event) { + event.replyChoices(AutocompleteUtil.getTeams("1", event.getFocusedOption().getValue())).queue(); + } + + public static void handleButton(ButtonInteractionEvent event) { + // 0 => always "team", irrelevant + // 1 => always team ID + // 2 => action + // 3 => sub-action if applicable + String[] components = event.getComponentId().split(":"); + String teamId = components[1]; + String action = components[2]; + String subAction = components.length > 3 ? components[3] : null; + + switch (action) { + case "standings" -> event.getInteraction().editMessageEmbeds(handleStandingsEmbed(teamId)).queue(); + case "roster" -> event.getInteraction().editMessageEmbeds(handleRosterEmbed(teamId)).queue(); + case "transactions" -> event.getInteraction().editMessageEmbeds(handleTransactionsEmbed(teamId)).queue(); + case "schedule" -> event.getInteraction().editMessageEmbeds(handleScheduleEmbed(teamId)).queue(); + case "stats" -> event.getInteraction().editMessageEmbeds(handleStatsEmbed(teamId)).queue(); + } + } + + public static void handleSelect(StringSelectInteractionEvent event) {} + + private static List buildBaseActionRows(String teamId) { + return Collections.emptyList(); + } + + private static MessageEmbed handleStandingsEmbed(String teamId) { + return new EmbedBuilder() + .build(); + } + + private static MessageEmbed handleRosterEmbed(String teamId) { + return new EmbedBuilder() + .build(); + } + + private static MessageEmbed handleTransactionsEmbed(String teamId) { + return new EmbedBuilder() + .build(); + } + + private static MessageEmbed handleScheduleEmbed(String teamId) { + JSONObject data = new JSONObject(RestClient.get("https://statsapi.mlb.com/api/v1/teams/%s?season=%s&hydrate=previousSchedule,nextSchedule" + .formatted(teamId, SEASON))).getJSONArray("teams").getJSONObject(0); + + List games = new ArrayList<>(); + List gamePks = new ArrayList<>(); + JSONArray prevGames = data.getJSONObject("previousGameSchedule").getJSONArray("dates"); + JSONArray nextGames = data.getJSONObject("nextGameSchedule").getJSONArray("dates"); + + for (JSONArray ar : new JSONArray[]{prevGames, nextGames}) { + for (int i = 0; i < ar.length(); i++) { + JSONArray gamesForDate = ar.getJSONObject(i).getJSONArray("games"); + for (int j = 0; j < gamesForDate.length(); j++) { + gamePks.add(gamesForDate.getJSONObject(j).getInt("gamePk")); + } + } + } + + // now we get games cus mlb is silly :3 + JSONObject gameData = new JSONObject(RestClient.get("https://statsapi.mlb.com/api/v1/schedule?language=en&gamePks=%s&useLatestGames=true&hydrate=team" + .formatted(gamePks.stream().distinct().map(String::valueOf).reduce((a, b) -> a + "," + b).orElse("")))); + + // now we do the wrapping + JSONArray gameDates = gameData.getJSONArray("dates"); + for (int i = 0; i < gameDates.length(); i++) { + JSONArray gamesForDate = gameDates.getJSONObject(i).getJSONArray("games"); + for (int j = 0; j < gamesForDate.length(); j++) { + games.add(new MLBAPIUtil.Game(gamesForDate.getJSONObject(j))); + } + } + + int teamIdInt = Integer.parseInt(teamId); + + StringBuilder res = new StringBuilder(); + for (MLBAPIUtil.Game game : games) { + //res.append(ScheduleCommand.gameToString(game, teamIdInt, -1)).append("\n"); + } + + return new EmbedBuilder() + .setTitle("Schedule for %s".formatted(data.getString("name"))) + .setDescription(res.toString()) + .build(); + } + + private static MessageEmbed handleStatsEmbed(String teamId) { + return new EmbedBuilder() + .build(); + } +} diff --git a/src/main/java/pw/chew/mlb/listeners/InteractionHandler.java b/src/main/java/pw/chew/mlb/listeners/InteractionHandler.java index 15df5fe..d7a7292 100644 --- a/src/main/java/pw/chew/mlb/listeners/InteractionHandler.java +++ b/src/main/java/pw/chew/mlb/listeners/InteractionHandler.java @@ -2,12 +2,14 @@ import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; +import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import org.jetbrains.annotations.NotNull; import pw.chew.mlb.commands.PlanGameCommand; import pw.chew.mlb.commands.StartGameCommand; import pw.chew.mlb.objects.GameBlurb; import pw.chew.mlb.util.EmbedUtil; +import pw.chew.mlb.commands.TeamCommand; import pw.chew.mlb.util.MLBAPIUtil; import java.util.ArrayList; @@ -16,6 +18,11 @@ public class InteractionHandler extends ListenerAdapter { @Override public void onButtonInteraction(@NotNull ButtonInteractionEvent event) { + if (event.getComponentId().startsWith("team:")) { + TeamCommand.handleButton(event); + return; + } + if (event.getComponentId().startsWith("plangame:")) { String action = event.getComponentId().split(":")[1]; String gamePk = event.getComponentId().split(":")[2]; @@ -70,4 +77,11 @@ public void onButtonInteraction(@NotNull ButtonInteractionEvent event) { } } } + + @Override + public void onStringSelectInteraction(@NotNull StringSelectInteractionEvent event) { + if (event.getComponentId().startsWith("team:")) { + TeamCommand.handleSelect(event); + } + } } diff --git a/src/main/java/pw/chew/mlb/objects/MLBTeam.java b/src/main/java/pw/chew/mlb/objects/MLBTeam.java index 0f46153..36968bb 100644 --- a/src/main/java/pw/chew/mlb/objects/MLBTeam.java +++ b/src/main/java/pw/chew/mlb/objects/MLBTeam.java @@ -11,6 +11,14 @@ public String name() { return data.getJSONObject("team").getString("teamName"); } + public String clubName() { + return data.getJSONObject("team").getString("clubName"); + } + + public String abbreviation() { + return data.getJSONObject("team").getString("abbreviation"); + } + public JSONObject record() { return data.getJSONObject("leagueRecord"); } @@ -23,6 +31,10 @@ public int losses() { return record().getInt("losses"); } + public int score() { + return data.getInt("score"); + } + public String probablePitcher() { JSONObject fallback = new JSONObject().put("fullName", "TBD"); return data.optJSONObject("probablePitcher", fallback).getString("fullName"); diff --git a/src/main/java/pw/chew/mlb/util/MLBAPIUtil.java b/src/main/java/pw/chew/mlb/util/MLBAPIUtil.java index 0a1919d..f99f9a5 100644 --- a/src/main/java/pw/chew/mlb/util/MLBAPIUtil.java +++ b/src/main/java/pw/chew/mlb/util/MLBAPIUtil.java @@ -7,16 +7,20 @@ import org.json.JSONArray; import org.json.JSONObject; import pw.chew.chewbotcca.util.RestClient; +import pw.chew.mlb.objects.MLBTeam; import java.time.Duration; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAccessor; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import static pw.chew.mlb.MLBBot.SEASON; -import static pw.chew.mlb.MLBBot.TEAMS; public class MLBAPIUtil { /// CACHING /// @@ -93,13 +97,26 @@ public static Map> getLineup(String gamePk, String homeAway return response; } + public static List getAffiliates(String teamId) { + JSONArray affiliates = new JSONObject(RestClient.get("https://statsapi.mlb.com/api/v1/teams/affiliates?teamIds=%s&season=%s&hydrate=standings,sport&fields=teams,name,id,venue,name,league,division,sport,abbreviation,sortOrder,record,wins,losses,winningPercentage,active" + .formatted(teamId, SEASON))).getJSONArray("teams"); + + // wrap each array item as an affiliate object + List affiliatesList = new ArrayList<>(); + for (int i = 0; i < affiliates.length(); i++) { + affiliatesList.add(new Affiliate(affiliates.getJSONObject(i))); + } + affiliatesList.sort(Comparator.comparingInt(Affiliate::sortOrder)); + return affiliatesList; + } + /** * Gets the current MLB standings. * * TODO: Support MiLB. */ - public static Map> getStandings() { - JSONArray standings = new JSONObject(RestClient.get("https://statsapi.mlb.com/api/v1/standings?leagueId=103,104&hydrate=division&season=%s".formatted(SEASON))).getJSONArray("records"); + public static Map> getStandings(String leagueId) { + JSONArray standings = new JSONObject(RestClient.get("https://statsapi.mlb.com/api/v1/standings?leagueId=%s&hydrate=division&season=%s".formatted(leagueId, SEASON))).getJSONArray("records"); HashMap> standingsMap = new HashMap<>(); for (int i = 0; i < standings.length(); i++) { JSONObject division = standings.getJSONObject(i); @@ -121,6 +138,31 @@ public static Map> getStandings() { } + + public static List getSchedule(int teamId, String sportId) { + JSONArray games = new JSONObject(RestClient.get("https://statsapi.mlb.com/api/v1/schedule?lang=en&sportId=%s&season=%s&teamId=%s&hydrate=team&fields=totalGames,totalGamesInProgress,dates,date,games,gamePk,gameType,gameDate,status,detailedState,abstractGameState,teams,away,home,team,name,id,clubName,abbreviation,score,seriesGameNumber,seriesDescription" + .formatted(sportId, SEASON, teamId))) + .getJSONArray("dates"); + + // iterate through date + List schedule = new ArrayList<>(); + for (int i = 0; i < games.length(); i++) { + // Formatted as YYYY-MM-DD + String date = games.getJSONObject(i).getString("date"); + + // iterate through games + JSONArray dayGames = games.getJSONObject(i).getJSONArray("games"); + for (int j = 0; j < dayGames.length(); j++) { + JSONObject game = dayGames.getJSONObject(j); + schedule.add(new Game(game)); + } + } + + return schedule; + } + + /// Records for data wrapping /// + public record Sports(JSONArray raw) { public List asChoices() { List choices = new ArrayList<>(); @@ -241,6 +283,70 @@ public String abbreviation() { } } + public record Affiliate(JSONObject raw) { + public int id() { + return raw.getInt("id"); + } + + public String name() { + return raw.getString("name"); + } + + public String venueName() { + return raw.getJSONObject("venue").getString("name"); + } + + public String abbreviation() { + return raw.getString("abbreviation"); + } + + public int leagueId() { + return raw.getJSONObject("league").getInt("id"); + } + + public String leagueName() { + return raw.getJSONObject("league").getString("name"); + } + + public String divisionName() { + return raw.getJSONObject("division").getString("name"); + } + + public Sport sport() { + return new Sport(raw.getJSONObject("sport")); + } + + public int wins() { + return raw.getJSONObject("record").getInt("wins"); + } + + public int losses() { + return raw.getJSONObject("record").getInt("losses"); + } + + public String pct() { + return raw.getJSONObject("record").getString("winningPercentage"); + } + + public boolean active() { + return raw.getBoolean("active"); + } + + public record Sport(JSONObject raw) { + public String name() { + return raw.getString("name"); + } + + public String abbreviation() { + return raw.getString("abbreviation"); + } + } + + public int sortOrder() { + return raw.getJSONObject("sport").getInt("sortOrder"); + } + } + public record Standing(JSONObject raw) { public String teamName() { // team > name @@ -303,4 +409,52 @@ public String lastTen() { return "%s-%s".formatted(lastTen.getInt("wins"), lastTen.getInt("losses")); } } + + public record Game(JSONObject raw) { + public String gamePk() { + return raw.getString("gamePk"); + } + + public String gameType() { + return raw.getString("gameType"); + } + + public OffsetDateTime gameDate() { + TemporalAccessor accessor = DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(raw.getString("gameDate")); + return OffsetDateTime.from(accessor); + } + + public String abstractGameState() { + return raw.getJSONObject("status").getString("abstractGameState"); + } + + public String detailedState() { + return raw.getJSONObject("status").getString("detailedState"); + } + + public boolean isCancelled() { + // detailedState == "Cancelled" + return detailedState().equals("Cancelled"); + } + + public boolean isFinal() { + return abstractGameState().equals("Final"); + } + + public MLBTeam away() { + return new MLBTeam(raw.getJSONObject("teams").getJSONObject("away")); + } + + public MLBTeam home() { + return new MLBTeam(raw.getJSONObject("teams").getJSONObject("home")); + } + + public int seriesGameNumber() { + return raw.getInt("seriesGameNumber"); + } + + public String seriesDescription() { + return raw.getString("seriesDescription"); + } + } } From 84f8a343f08c8a2220811415f3ad8006b9ce3cd2 Mon Sep 17 00:00:00 2001 From: Chew Date: Mon, 14 Apr 2025 14:53:04 -0400 Subject: [PATCH 2/3] initial attempt at roster --- .../pw/chew/mlb/commands/TeamCommand.java | 90 +++++++++++++++++-- .../mlb/listeners/InteractionHandler.java | 13 +-- .../java/pw/chew/mlb/util/MLBAPIUtil.java | 4 +- 3 files changed, 86 insertions(+), 21 deletions(-) diff --git a/src/main/java/pw/chew/mlb/commands/TeamCommand.java b/src/main/java/pw/chew/mlb/commands/TeamCommand.java index 555ea81..52d15f0 100644 --- a/src/main/java/pw/chew/mlb/commands/TeamCommand.java +++ b/src/main/java/pw/chew/mlb/commands/TeamCommand.java @@ -8,6 +8,7 @@ import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent; import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent; +import net.dv8tion.jda.api.interactions.InteractionContextType; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; import net.dv8tion.jda.api.interactions.components.ActionRow; @@ -16,6 +17,7 @@ import net.dv8tion.jda.api.interactions.components.selections.StringSelectMenu; import org.json.JSONArray; import org.json.JSONObject; +import pw.chew.chewbotcca.util.MiscUtil; import pw.chew.chewbotcca.util.RestClient; import pw.chew.mlb.util.AutocompleteUtil; import pw.chew.mlb.util.MLBAPIUtil; @@ -23,7 +25,10 @@ import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import static pw.chew.mlb.MLBBot.SEASON; @@ -31,12 +36,16 @@ public class TeamCommand extends SlashCommand { public TeamCommand() { this.name = "team"; this.help = "Get information about a team."; - this.guildOnly = false; this.options = List.of( new OptionData(OptionType.STRING, "team", "Type to search for a team!", true, true) ); - // TODO: Future, make this installable in user contexts + // Installable everywhere, since info and always ephemeral + this.contexts = new InteractionContextType[]{ + InteractionContextType.GUILD, + InteractionContextType.BOT_DM, + InteractionContextType.PRIVATE_CHANNEL + }; } @Override @@ -115,8 +124,73 @@ private static MessageEmbed handleStandingsEmbed(String teamId) { } private static MessageEmbed handleRosterEmbed(String teamId) { - return new EmbedBuilder() - .build(); + // get roster + JSONObject roster = RestClient.get("https://statsapi.mlb.com/api/v1/teams/%s/roster?rosterType=depthChart&season=2025&fields=roster,person,primaryNumber,fullName,position,name,type,status,code,description" + .formatted(teamId)).asJSONObject(); + + Map> players = new LinkedHashMap<>(); + players.put("Starting Pitcher", new ArrayList<>()); + players.put("Infielder", new ArrayList<>()); + players.put("Outfielder", new ArrayList<>()); + players.put("Bullpen", new ArrayList<>()); + players.put("Catcher", new ArrayList<>()); + players.put("Designated Hitter", new ArrayList<>()); + + for (JSONObject player : MiscUtil.toList(roster.getJSONArray("roster"), JSONObject.class)) { + JSONObject position = player.getJSONObject("position"); + String name = player.getJSONObject("person").getString("fullName"); + switch (player.getJSONObject("status").getString("code")) { + case "D60": + case "RM": + // skip this player entirely + break; + case "D10": + case "D15": + // append injury emoji to end of name + name += " " + "+"; // TODO: Replace with actual injury emoji + case "A": + // time to get ready + switch (position.getString("type")) { + case "Catcher", "Infielder", "Outfielder" -> { + players.get(position.getString("type")).add(name); + } + case "Pitcher" -> { + if (position.getString("name").equals("Starting Pitcher")) { + players.get("Starting Pitcher").add(name); + } else { + players.get("Bullpen").add(name); + } + } + case "Hitter" -> { + players.get("Designated Hitter").add(name); + } + } + } + } + + + + EmbedBuilder embed = new EmbedBuilder() + .setTitle("Roster") + .setDescription("Only shows active roster."); + + for (Map.Entry> entry : players.entrySet()) { + String position = entry.getKey(); + List playerList = entry.getValue(); + + if (playerList.isEmpty()) { + continue; + } + + StringBuilder sb = new StringBuilder(); + for (String player : playerList) { + sb.append(player).append("\n"); + } + + embed.addField(position + (position.equals("Bullpen") ? "" : "s"), sb.toString(), true); + } + + return embed.build(); } private static MessageEmbed handleTransactionsEmbed(String teamId) { @@ -125,8 +199,8 @@ private static MessageEmbed handleTransactionsEmbed(String teamId) { } private static MessageEmbed handleScheduleEmbed(String teamId) { - JSONObject data = new JSONObject(RestClient.get("https://statsapi.mlb.com/api/v1/teams/%s?season=%s&hydrate=previousSchedule,nextSchedule" - .formatted(teamId, SEASON))).getJSONArray("teams").getJSONObject(0); + JSONObject data = RestClient.get("https://statsapi.mlb.com/api/v1/teams/%s?season=%s&hydrate=previousSchedule,nextSchedule" + .formatted(teamId, SEASON)).asJSONObject().getJSONArray("teams").getJSONObject(0); List games = new ArrayList<>(); List gamePks = new ArrayList<>(); @@ -143,8 +217,8 @@ private static MessageEmbed handleScheduleEmbed(String teamId) { } // now we get games cus mlb is silly :3 - JSONObject gameData = new JSONObject(RestClient.get("https://statsapi.mlb.com/api/v1/schedule?language=en&gamePks=%s&useLatestGames=true&hydrate=team" - .formatted(gamePks.stream().distinct().map(String::valueOf).reduce((a, b) -> a + "," + b).orElse("")))); + JSONObject gameData = RestClient.get("https://statsapi.mlb.com/api/v1/schedule?language=en&gamePks=%s&useLatestGames=true&hydrate=team" + .formatted(gamePks.stream().distinct().map(String::valueOf).reduce((a, b) -> a + "," + b).orElse(""))).asJSONObject(); // now we do the wrapping JSONArray gameDates = gameData.getJSONArray("dates"); diff --git a/src/main/java/pw/chew/mlb/listeners/InteractionHandler.java b/src/main/java/pw/chew/mlb/listeners/InteractionHandler.java index 2a5e5b7..81836f0 100644 --- a/src/main/java/pw/chew/mlb/listeners/InteractionHandler.java +++ b/src/main/java/pw/chew/mlb/listeners/InteractionHandler.java @@ -95,18 +95,9 @@ public void onStringSelectInteraction(StringSelectInteractionEvent event) { String type = parts[0]; // Future proofing - //noinspection SwitchStatementWithTooFewBranches switch (type) { - case "gameinfo" -> { - GameInfoCommand.handleSelectMenu(event); - } - } - } - - @Override - public void onStringSelectInteraction(@NotNull StringSelectInteractionEvent event) { - if (event.getComponentId().startsWith("team:")) { - TeamCommand.handleSelect(event); + case "gameinfo" -> GameInfoCommand.handleSelectMenu(event); + case "team" -> TeamCommand.handleSelect(event); } } } diff --git a/src/main/java/pw/chew/mlb/util/MLBAPIUtil.java b/src/main/java/pw/chew/mlb/util/MLBAPIUtil.java index 19a5034..e2335d9 100644 --- a/src/main/java/pw/chew/mlb/util/MLBAPIUtil.java +++ b/src/main/java/pw/chew/mlb/util/MLBAPIUtil.java @@ -99,8 +99,8 @@ public static Map> getLineup(String gamePk, String homeAway } public static List getAffiliates(String teamId) { - JSONArray affiliates = new JSONObject(RestClient.get("https://statsapi.mlb.com/api/v1/teams/affiliates?teamIds=%s&season=%s&hydrate=standings,sport&fields=teams,name,id,venue,name,league,division,sport,abbreviation,sortOrder,record,wins,losses,winningPercentage,active" - .formatted(teamId, SEASON))).getJSONArray("teams"); + JSONArray affiliates = RestClient.get("https://statsapi.mlb.com/api/v1/teams/affiliates?teamIds=%s&season=%s&hydrate=standings,sport&fields=teams,name,id,venue,name,league,division,sport,abbreviation,sortOrder,record,wins,losses,winningPercentage,active" + .formatted(teamId, SEASON)).asJSONObject().getJSONArray("teams"); // wrap each array item as an affiliate object List affiliatesList = new ArrayList<>(); From 1472e08d2e8495e5684c7b26751852e43cfc3605 Mon Sep 17 00:00:00 2001 From: Chew Date: Thu, 8 May 2025 22:46:47 -0500 Subject: [PATCH 3/3] add Scheduled events cache flag --- src/main/java/pw/chew/mlb/MLBBot.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/pw/chew/mlb/MLBBot.java b/src/main/java/pw/chew/mlb/MLBBot.java index 7ad7c6a..c1fd2bd 100644 --- a/src/main/java/pw/chew/mlb/MLBBot.java +++ b/src/main/java/pw/chew/mlb/MLBBot.java @@ -77,6 +77,7 @@ public static void main(String[] args) throws IOException { // Register JDA jda = JDABuilder.createDefault(prop.getProperty("token")) .setStatus(OnlineStatus.ONLINE) + .enableCache(CacheFlag.SCHEDULED_EVENTS) .setActivity(Activity.playing("Booting...")) .addEventListeners( waiter, commandClient // JDA-Chewtils stuff