From e9be061576695874c23d13767dd044fc42f2ceaa Mon Sep 17 00:00:00 2001 From: Louis Vallat Date: Mon, 26 Oct 2020 15:04:42 +0100 Subject: [PATCH] Added OpenSubtitles basic search capability Signed-off-by: Louis Vallat --- .../java/xyz/vallat/louis/MovieQuoteBot.java | 84 ++++++------------- .../xyz/vallat/louis/commands/Search.java | 41 +++++++++ .../vallat/louis/subtitles/OpenSubtitles.java | 59 +++++++++++++ 3 files changed, 126 insertions(+), 58 deletions(-) create mode 100644 src/main/java/xyz/vallat/louis/commands/Search.java create mode 100644 src/main/java/xyz/vallat/louis/subtitles/OpenSubtitles.java diff --git a/src/main/java/xyz/vallat/louis/MovieQuoteBot.java b/src/main/java/xyz/vallat/louis/MovieQuoteBot.java index ec6f791..596f5cf 100644 --- a/src/main/java/xyz/vallat/louis/MovieQuoteBot.java +++ b/src/main/java/xyz/vallat/louis/MovieQuoteBot.java @@ -1,8 +1,5 @@ package xyz.vallat.louis; -import com.github.wtekiela.opensub4j.api.OpenSubtitlesClient; -import com.github.wtekiela.opensub4j.impl.OpenSubtitlesClientImpl; -import com.github.wtekiela.opensub4j.response.ResponseStatus; import discord4j.core.DiscordClientBuilder; import discord4j.core.GatewayDiscordClient; import discord4j.core.event.domain.lifecycle.ReadyEvent; @@ -10,18 +7,15 @@ import discord4j.core.event.domain.message.MessageCreateEvent; import discord4j.core.object.entity.User; import discord4j.core.object.presence.Activity; import discord4j.core.object.presence.Presence; -import org.apache.xmlrpc.XmlRpcException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import xyz.vallat.louis.commands.Command; import xyz.vallat.louis.commands.Ping; import xyz.vallat.louis.commands.Search; import xyz.vallat.louis.commands.Version; +import xyz.vallat.louis.subtitles.OpenSubtitles; -import java.net.MalformedURLException; -import java.net.URL; import java.util.HashMap; import java.util.Map; @@ -39,11 +33,6 @@ public class MovieQuoteBot { private static final Logger logger = LoggerFactory.getLogger(MovieQuoteBot.class.getCanonicalName()); private static final Map commands = new HashMap<>(); private static GatewayDiscordClient discordClient; - private static OpenSubtitlesClient openSubtitlesClient; - private static String discordToken; - private static String osUsername; - private static String osPassword; - private static String osUa; static { commands.put("ping", new Ping()); @@ -61,9 +50,23 @@ public class MovieQuoteBot { System.exit(1); } - setVariables(args); - osLogin(); - discordLogin(); + String discordToken = System.getenv(DISCORD_TOKEN_ENVIRONMENT) == null ? + args[0] : + System.getenv(DISCORD_TOKEN_ENVIRONMENT); + + OpenSubtitles.login( + System.getenv(OS_USERNAME_ENVIRONMENT) == null ? + args[1] : + System.getenv(OS_USERNAME_ENVIRONMENT), + System.getenv(OS_PASSWORD_ENVIRONMENT) == null ? + args[2] : + System.getenv(OS_PASSWORD_ENVIRONMENT), + "en", + System.getenv(OS_UA_ENVIRONMENT) == null ? + args[3] : + System.getenv(OS_UA_ENVIRONMENT) + ); + discordLogin(discordToken); registerDiscordCommands(); Runtime.getRuntime().addShutdownHook(new Thread(() -> { @@ -75,17 +78,16 @@ public class MovieQuoteBot { } private static void registerDiscordCommands() { - discordClient.getEventDispatcher().on(MessageCreateEvent.class) - .flatMap(event -> Mono.just(event.getMessage().getContent()) - .flatMap(content -> Flux.fromIterable(commands.entrySet()) - .filter(entry -> content.split(" ")[0].equals(PREFIX + entry.getKey())) - .flatMap(entry -> entry.getValue().execute(event)) - .next())) - .subscribe(); + for (Map.Entry command : commands.entrySet()) + discordClient.getEventDispatcher().on(MessageCreateEvent.class) + .filter(event -> event.getMessage().getAuthor().map(user -> !user.isBot()).orElse(false)) + .filter(event -> event.getMessage().getContent().split(" ")[0].equals(PREFIX + command.getKey())) + .flatMap(event -> command.getValue().execute(event).then()) + .subscribe(); } - private static void discordLogin() { - discordClient = DiscordClientBuilder.create(discordToken).build().login().block(); + private static void discordLogin(String token) { + discordClient = DiscordClientBuilder.create(token).build().login().block(); assert discordClient != null; discordClient.updatePresence(Presence.online(Activity.watching("some more films"))).subscribe(); discordClient.getEventDispatcher().on(ReadyEvent.class) @@ -95,40 +97,6 @@ public class MovieQuoteBot { }); } - private static void setVariables(String[] args) { - discordToken = System.getenv(DISCORD_TOKEN_ENVIRONMENT) == null ? - args[0] : - System.getenv(DISCORD_TOKEN_ENVIRONMENT); - osUsername = System.getenv(OS_USERNAME_ENVIRONMENT) == null ? - args[1] : - System.getenv(OS_USERNAME_ENVIRONMENT); - osPassword = System.getenv(OS_PASSWORD_ENVIRONMENT) == null ? - args[2] : - System.getenv(OS_PASSWORD_ENVIRONMENT); - osUa = System.getenv(OS_UA_ENVIRONMENT) == null ? - args[3] : - System.getenv(OS_UA_ENVIRONMENT); - } - - public static void osLogin() { - try { - URL serverUrl = new URL("https", "api.opensubtitles.org", 443, "/xml-rpc"); - openSubtitlesClient = new OpenSubtitlesClientImpl(serverUrl); - ResponseStatus status = openSubtitlesClient.login(osUsername, osPassword, "en", osUa).getStatus(); - if (!openSubtitlesClient.isLoggedIn()) { - logger.error("Cannot login on OpenSubtitles.org."); - logger.error("Message: [{}] - {}", status.getCode(), status.getMessage()); - } else logger.info("Logged in on OpenSubtitles.org."); - } catch (MalformedURLException | XmlRpcException e) { - logger.error(e.getMessage()); - System.exit(3); - } - } - - public static boolean isOsLoggedIn() { - return openSubtitlesClient != null && openSubtitlesClient.isLoggedIn(); - } - public static Mono getGuilds() { return discordClient.getGuilds().count(); } diff --git a/src/main/java/xyz/vallat/louis/commands/Search.java b/src/main/java/xyz/vallat/louis/commands/Search.java new file mode 100644 index 0000000..fef97c2 --- /dev/null +++ b/src/main/java/xyz/vallat/louis/commands/Search.java @@ -0,0 +1,41 @@ +package xyz.vallat.louis.commands; + +import com.github.wtekiela.opensub4j.response.ListResponse; +import com.github.wtekiela.opensub4j.response.MovieInfo; +import discord4j.core.event.domain.message.MessageCreateEvent; +import discord4j.core.object.reaction.ReactionEmoji; +import org.apache.xmlrpc.XmlRpcException; +import reactor.core.publisher.Mono; +import xyz.vallat.louis.subtitles.OpenSubtitles; + +public class Search implements Command { + + private static final ReactionEmoji WAITING = ReactionEmoji.unicode("⌛"); + + @Override + public Mono execute(MessageCreateEvent event) { + String[] args = event.getMessage().getContent().split(" "); + if (args.length != 1) return event.getMessage().getChannel().flatMap(channel -> channel.createMessage("Misuse")).then(); + return event.getMessage().getChannel() + .flatMap(channel -> { + if (OpenSubtitles.isLoggedIn()) { + return event.getMessage().addReaction(WAITING) + .then(event.getMessage().getChannel().flatMap(messageChannel -> messageChannel.createMessage(args[1]))) + .then(event.getMessage().getChannel().flatMap(messageChannel -> { + try { + ListResponse response = OpenSubtitles.searchImdb(args[1]); + StringBuilder b = new StringBuilder(); + for (MovieInfo m : response.getData()) + b.append(m.getId()).append(" > ").append(m.getTitle()).append("\n"); + return messageChannel.createMessage(String.valueOf(b)); + } catch (XmlRpcException e) { + return channel.createMessage("Error"); + } + })) + .then(event.getMessage().removeSelfReaction(WAITING)) + .then(); + } else return channel.createMessage("I cannot search for subtitles right now. Sorry."); + }) + .then(); + } +} diff --git a/src/main/java/xyz/vallat/louis/subtitles/OpenSubtitles.java b/src/main/java/xyz/vallat/louis/subtitles/OpenSubtitles.java new file mode 100644 index 0000000..3cb7c66 --- /dev/null +++ b/src/main/java/xyz/vallat/louis/subtitles/OpenSubtitles.java @@ -0,0 +1,59 @@ +package xyz.vallat.louis.subtitles; + +import com.github.wtekiela.opensub4j.api.OpenSubtitlesClient; +import com.github.wtekiela.opensub4j.impl.OpenSubtitlesClientImpl; +import com.github.wtekiela.opensub4j.response.ListResponse; +import com.github.wtekiela.opensub4j.response.MovieInfo; +import com.github.wtekiela.opensub4j.response.ResponseStatus; +import org.apache.xmlrpc.XmlRpcException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Map; + +public final class OpenSubtitles { + + private static final Logger logger = LoggerFactory.getLogger(OpenSubtitles.class.getCanonicalName()); + + private static String username; + private static String password; + private static String lang; + private static String userAgent; + private static OpenSubtitlesClient client; + + private OpenSubtitles() { + } + + public static void login(String username, String password, String lang, String userAgent) { + OpenSubtitles.username = username; + OpenSubtitles.password = password; + OpenSubtitles.lang = lang; + OpenSubtitles.userAgent = userAgent; + login(); + } + + public static void login() { + try { + URL serverUrl = new URL("https", "api.opensubtitles.org", 443, "/xml-rpc"); + client = new OpenSubtitlesClientImpl(serverUrl); + ResponseStatus status = client.login(username, password, lang, userAgent).getStatus(); + if (!client.isLoggedIn()) { + logger.error("Cannot login on OpenSubtitles.org."); + logger.error("Message: [{}] - {}", status.getCode(), status.getMessage()); + } else logger.info("Logged in on OpenSubtitles.org."); + } catch (MalformedURLException | XmlRpcException e) { + logger.error(e.getMessage()); + System.exit(3); + } + } + + public static ListResponse searchImdb (String name) throws XmlRpcException { + return client.searchMoviesOnImdb(name); + } + + public static boolean isLoggedIn() { + return client != null && client.isLoggedIn(); + } +}