This commit is contained in:
Lee 2024-07-04 15:59:16 +01:00
parent 16e956d718
commit f637faf0b6
9 changed files with 4 additions and 436 deletions

@ -16,7 +16,10 @@ import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData; import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
import net.dv8tion.jda.internal.interactions.CommandDataImpl; import net.dv8tion.jda.internal.interactions.CommandDataImpl;
import java.util.*; import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
/** /**
* @author Braydon * @author Braydon

@ -11,9 +11,7 @@ import cc.fascinated.bat.model.BatUser;
import cc.fascinated.bat.service.CommandService; import cc.fascinated.bat.service.CommandService;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.MessageReference;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.entities.emoji.Emoji; import net.dv8tion.jda.api.entities.emoji.Emoji;
import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent; import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent;

@ -13,7 +13,6 @@ import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;

@ -9,14 +9,11 @@ import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.NumberFormatter; import cc.fascinated.bat.common.NumberFormatter;
import cc.fascinated.bat.exception.RateLimitException; import cc.fascinated.bat.exception.RateLimitException;
import cc.fascinated.bat.features.scoresaber.profile.user.ScoreSaberProfile; import cc.fascinated.bat.features.scoresaber.profile.user.ScoreSaberProfile;
import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.model.BatUser;
import cc.fascinated.bat.model.token.beatsaber.scoresaber.ScoreSaberAccountToken; import cc.fascinated.bat.model.token.beatsaber.scoresaber.ScoreSaberAccountToken;
import cc.fascinated.bat.service.ScoreSaberService; import cc.fascinated.bat.service.ScoreSaberService;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;

@ -1,97 +0,0 @@
package cc.fascinated.bat.features.tmdb;
import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.NumberFormatter;
import cc.fascinated.bat.features.Feature;
import cc.fascinated.bat.features.tmdb.command.TMDBCommand;
import cc.fascinated.bat.service.CommandService;
import cc.fascinated.bat.service.TMDBService;
import info.movito.themoviedbapi.model.core.Movie;
import info.movito.themoviedbapi.model.core.TvSeries;
import lombok.NonNull;
import net.dv8tion.jda.api.EmbedBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author Nick (okNick)
*/
@Component
public class TMDBFeature extends Feature {
@Autowired
public TMDBFeature(@NonNull ApplicationContext context, @NonNull CommandService commandService) {
super("TMDB", true);
super.registerCommand(commandService, context.getBean(TMDBCommand.class));
}
/**
* Create an embed for a movie page.
*
* @param tmdbService The TMDB service.
* @param query The query to search for.
* @param language The language to search in.
* @param primaryReleaseYear The primary release year to filter by.
* @param region The region to search in.
* @param year The year to filter by.
* @param movie The movie index.
* @param adult Whether to include adult content.
* @return The movie page embed.
*/
public static EmbedBuilder pageMovie(@NonNull TMDBService tmdbService, @NonNull String query, String language, String primaryReleaseYear, String region, String year, int movie, boolean adult) {
List<Movie> movieList = tmdbService.lookupMovies(query, adult, language, primaryReleaseYear, region, year);
if (movieList == null || movieList.isEmpty()) {
return null;
}
// Adjust movie index to stay within bounds
if (movie >= movieList.size()) {
movie = movieList.size() - 1; // Set to the last movie if index exceeds list size
}
return EmbedUtils.genericEmbed()
.setAuthor(movieList.get(movie).getTitle(), "https://www.themoviedb.org/movie/%s".formatted(movieList.get(movie).getId()))
.setThumbnail("https://media.themoviedb.org/t/p/w220_and_h330_face%s".formatted(movieList.get(movie).getPosterPath()))
.setDescription(movieList.get(movie).getOverview())
.addField("Release Date", movieList.get(movie).getReleaseDate(), true)
.addField("Rating", NumberFormatter.format(movieList.get(movie).getVoteAverage()) + "/10", true)
.addField("Language", movieList.get(movie).getOriginalLanguage(), true)
.setFooter("Page %s of %s".formatted(movie + 1, movieList.size()));
}
/**
* Create an embed for a series page.
*
* @param tmdbService The TMDB service.
* @param query The query to search for.
* @param language The language to search in.
* @param firstAirDateYear The first air date year to filter by.
* @param year The year to filter by.
* @param series The series index.
* @param adult Whether to include adult content.
* @return The series page embed.
*/
public static EmbedBuilder pageSeries(@NonNull TMDBService tmdbService, @NonNull String query, String language, int firstAirDateYear, int year, int series, boolean adult) {
List<TvSeries> seriesList = tmdbService.lookupSeries(query, adult, language, firstAirDateYear, year);
if (seriesList == null || seriesList.isEmpty()) {
return null;
}
// Adjust series index to stay within bounds
if (series >= seriesList.size()) {
series = seriesList.size() - 1; // Set to the last series if index exceeds list size
}
return EmbedUtils.genericEmbed()
.setAuthor(seriesList.get(series).getName(), "https://www.themoviedb.org/tv/%s".formatted(seriesList.get(series).getId()))
.setThumbnail("https://media.themoviedb.org/t/p/w220_and_h330_face%s".formatted(seriesList.get(series).getPosterPath()))
.setDescription(seriesList.get(series).getOverview())
.addField("First Air Date", seriesList.get(series).getFirstAirDate(), true)
.addField("Rating", NumberFormatter.format(seriesList.get(series).getVoteAverage()) + "/10", true)
.addField("Language", seriesList.get(series).getOriginalLanguage(), true)
.setFooter("Page %s of %s".formatted(series + 1, seriesList.size()));
}
}

@ -1,154 +0,0 @@
package cc.fascinated.bat.features.tmdb.command;
import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.event.EventListener;
import cc.fascinated.bat.features.tmdb.TMDBFeature;
import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser;
import cc.fascinated.bat.service.TMDBService;
import lombok.NonNull;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.entities.emoji.Emoji;
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.interactions.components.buttons.Button;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
@CommandInfo(name = "movie", description = "Get information about a movie")
public class MovieSubCommand extends BatCommand implements EventListener {
private final TMDBService tmdbService;
private final Map<String, Map<String, String>> userCommands; // Map to store user commands and their parameters
@Autowired
public MovieSubCommand(@NonNull TMDBService tmdbService) {
this.tmdbService = tmdbService;
this.userCommands = new HashMap<>();
super.addOptions(
new OptionData(OptionType.STRING, "title", "The title of the movie", true),
new OptionData(OptionType.STRING, "language", "A locale code (en-US) to lookup movies in a specific language", false),
new OptionData(OptionType.STRING, "primary_release_year", "Filter the results so that only the primary release dates have this value", false),
new OptionData(OptionType.STRING, "region", "An ISO 3166-1 code (US) to lookup movies from a specific region", false)
);
}
@Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
OptionMapping titleOption = event.getOption("title");
if (titleOption == null) {
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("You must provide a title to search for!")
.build())
.queue();
return;
}
// Determine if the channel is NSFW. If so, allow adult content
boolean adult = false;
if (event.getChannel() instanceof TextChannel textChannel) {
adult = textChannel.isNSFW();
}
OptionMapping languageOption = event.getOption("language");
OptionMapping primaryReleaseYearOption = event.getOption("primary_release_year");
OptionMapping regionOption = event.getOption("region");
OptionMapping yearOption = event.getOption("year");
// Store user command and parameters for later use
Map<String, String> params = new HashMap<>();
params.put("title", titleOption.getAsString());
if (languageOption != null) params.put("language", languageOption.getAsString());
if (primaryReleaseYearOption != null) params.put("primary_release_year", primaryReleaseYearOption.getAsString());
if (regionOption != null) params.put("region", regionOption.getAsString());
if (yearOption != null) params.put("year", yearOption.getAsString());
params.put("adult", String.valueOf(adult));
userCommands.put(user.getId(), params);
EmbedBuilder embedBuilder = TMDBFeature.pageMovie(
tmdbService,
titleOption.getAsString(),
(languageOption != null ? languageOption.getAsString() : null),
(primaryReleaseYearOption != null ? primaryReleaseYearOption.getAsString() : null),
(regionOption != null ? regionOption.getAsString() : null),
(yearOption != null ? yearOption.getAsString() : null),
0, // Initial page number
adult
);
if (embedBuilder == null) {
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("No movies found with the given parameters!")
.build())
.queue();
return;
}
event.replyEmbeds(embedBuilder.build()).addActionRow(
Button.primary("backMovie", "Back").withEmoji(Emoji.fromFormatted("⬅️")),
Button.primary("nextMovie", "Next").withEmoji(Emoji.fromFormatted("➡️"))
).queue();
}
@Override
public void onButtonInteraction(BatGuild guild, @NonNull BatUser user, @NonNull ButtonInteractionEvent event) {
Map<String, String> params = userCommands.get(user.getId());
if (params == null) {
return;
}
int currentPage = Integer.parseInt(params.getOrDefault("page", "0"));
boolean adult = Boolean.parseBoolean(params.get("adult"));
// Retrieve stored parameters
String title = params.get("title");
String language = params.get("language");
String primaryReleaseYear = params.get("primary_release_year");
String region = params.get("region");
String year = params.get("year");
if (event.getComponentId().equals("backMovie")) {
currentPage--;
if (currentPage < 0) {
currentPage = 0; // Ensure currentPage doesn't go negative
}
} else if (event.getComponentId().equals("nextMovie")) {
currentPage++;
}
params.put("page", String.valueOf(currentPage));
EmbedBuilder embedBuilder = TMDBFeature.pageMovie(
tmdbService,
title,
language,
primaryReleaseYear,
region,
year,
currentPage,
adult
);
if (embedBuilder == null) {
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("No movies found with the given parameters!")
.build())
.queue();
return;
}
event.editMessageEmbeds(embedBuilder.build()).queue();
}
}

@ -1,149 +0,0 @@
package cc.fascinated.bat.features.tmdb.command;
import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.event.EventListener;
import cc.fascinated.bat.features.tmdb.TMDBFeature;
import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser;
import cc.fascinated.bat.service.TMDBService;
import lombok.NonNull;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.entities.emoji.Emoji;
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.interactions.components.buttons.Button;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
@CommandInfo(name = "series", description = "Get information about a series")
public class SeriesSubCommand extends BatCommand implements EventListener {
private final TMDBService tmdbService;
private final Map<String, Map<String, String>> userCommands; // Map to store user commands and their parameters
@Autowired
public SeriesSubCommand(@NonNull TMDBService tmdbService) {
this.tmdbService = tmdbService;
this.userCommands = new HashMap<>();
addOptions(
new OptionData(OptionType.STRING, "title", "The title of the series", true),
new OptionData(OptionType.STRING, "language", "A locale code (en-US) to lookup movies in a specific language", false),
new OptionData(OptionType.INTEGER, "first_air_year", "Filter the results so that only the first air year has this value", false),
new OptionData(OptionType.INTEGER, "year", "Filter the results release dates to matches that include this value", false)
);
}
@Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
OptionMapping titleOption = event.getOption("title");
if (titleOption == null) {
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("You must provide a title to search for!")
.build())
.queue();
return;
}
// Determine if the channel is NSFW. If so, allow adult content
boolean adult = false;
if (event.getChannel() instanceof TextChannel textChannel) {
adult = textChannel.isNSFW();
}
OptionMapping languageOption = event.getOption("language");
OptionMapping firstAirYearOption = event.getOption("first_air_year");
OptionMapping yearOption = event.getOption("year");
// Store user command and parameters for later use
Map<String, String> params = new HashMap<>();
params.put("title", titleOption.getAsString());
if (languageOption != null) params.put("language", languageOption.getAsString());
if (firstAirYearOption != null) params.put("first_air_year", String.valueOf(firstAirYearOption.getAsInt()));
if (yearOption != null) params.put("year", String.valueOf(yearOption.getAsInt()));
params.put("adult", String.valueOf(adult));
EmbedBuilder embedBuilder = TMDBFeature.pageSeries(
tmdbService,
titleOption.getAsString(),
(languageOption != null ? languageOption.getAsString() : null),
(firstAirYearOption != null ? firstAirYearOption.getAsInt() : -1),
(yearOption != null ? yearOption.getAsInt() : -1),
0, // Initial page number
adult
);
if (embedBuilder == null) {
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("No series found with the given parameters!")
.build())
.queue();
return;
}
userCommands.put(user.getId(), params);
event.replyEmbeds(embedBuilder.build()
).addActionRow(
Button.primary("backSeries", "Back").withEmoji(Emoji.fromFormatted("⬅️")),
Button.primary("nextSeries", "Next").withEmoji(Emoji.fromFormatted("➡️"))
).queue();
}
@Override
public void onButtonInteraction(BatGuild guild, @NonNull BatUser user, @NonNull ButtonInteractionEvent event) {
Map<String, String> params = userCommands.get(user.getId());
if (params == null) {
return;
}
int currentPage = Integer.parseInt(params.getOrDefault("page", "0"));
boolean adult = Boolean.parseBoolean(params.get("adult"));
// Retrieve stored parameters
String title = params.get("title");
String language = params.get("language");
int firstAirYear = (params.get("first_air_year") != null ? Integer.parseInt(params.get("first_air_year")) : -1);
int year = (params.get("year") != null ? Integer.parseInt(params.get("year")) : -1);
if (event.getComponentId().equals("backSeries")) {
currentPage--;
if (currentPage < 0) {
currentPage = 0; // Ensure currentPage doesn't go negative
}
} else if (event.getComponentId().equals("nextSeries")) {
currentPage++;
}
params.put("page", String.valueOf(currentPage));
EmbedBuilder embedBuilder = TMDBFeature.pageSeries(
tmdbService,
title,
language,
firstAirYear,
year,
currentPage,
adult
);
if (embedBuilder == null) {
event.editMessageEmbeds(EmbedUtils.errorEmbed()
.setDescription("No series found with the given parameters!")
.build())
.queue();
return;
}
event.editMessageEmbeds(embedBuilder.build()).queue();
}
}

@ -1,24 +0,0 @@
package cc.fascinated.bat.features.tmdb.command;
import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.Category;
import cc.fascinated.bat.command.CommandInfo;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
/**
* @author Nick (okNick)
*/
@Component
@CommandInfo(name = "tmdb", description = "Get information about movies and TV shows", guildOnly = false, userInstall = true, category = Category.MEDIA)
public class TMDBCommand extends BatCommand {
@Autowired
public TMDBCommand(@NonNull ApplicationContext context) {
super.addSubCommands(
context.getBean(MovieSubCommand.class),
context.getBean(SeriesSubCommand.class)
);
}
}

@ -39,11 +39,6 @@ spotify:
client-id: "spotify-client-id" client-id: "spotify-client-id"
client-secret: "spotify-client-secret" client-secret: "spotify-client-secret"
# TMDB Configuration
tmdb:
# API Read Access Token
api-key: "api-read-access-token"
# DO NOT TOUCH BELOW (unless you know what you're doing, ofc!) # DO NOT TOUCH BELOW (unless you know what you're doing, ofc!)
# MongoDB Migration Configuration # MongoDB Migration Configuration