Basic POC for importing subtitles.

Signed-off-by: Louis Vallat <louis@louis-vallat.xyz>
This commit is contained in:
Louis Vallat 2020-10-29 00:38:25 +01:00
parent f0b757060a
commit d645ccb711
6 changed files with 49 additions and 159 deletions

View File

@ -4,6 +4,7 @@ import com.github.wtekiela.opensub4j.response.ListResponse;
import com.github.wtekiela.opensub4j.response.ResponseStatus; import com.github.wtekiela.opensub4j.response.ResponseStatus;
import com.github.wtekiela.opensub4j.response.SubtitleInfo; import com.github.wtekiela.opensub4j.response.SubtitleInfo;
import discord4j.core.event.domain.message.MessageCreateEvent; import discord4j.core.event.domain.message.MessageCreateEvent;
import discord4j.core.object.reaction.ReactionEmoji;
import discord4j.core.spec.EmbedCreateSpec; import discord4j.core.spec.EmbedCreateSpec;
import discord4j.rest.util.Color; import discord4j.rest.util.Color;
import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.XmlRpcException;
@ -16,6 +17,7 @@ import xyz.vallat.louis.subtitles.OpenSubtitles;
import java.io.IOException; import java.io.IOException;
import java.util.Comparator; import java.util.Comparator;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function; import java.util.function.Function;
@ -25,6 +27,7 @@ import java.util.stream.Stream;
public abstract class Command { public abstract class Command {
private static final Logger logger = LoggerFactory.getLogger(ListLangMovie.class.getCanonicalName()); private static final Logger logger = LoggerFactory.getLogger(ListLangMovie.class.getCanonicalName());
protected static final ReactionEmoji WAITING = ReactionEmoji.unicode("");
protected final String name; protected final String name;
protected final String description; protected final String description;
@ -72,7 +75,7 @@ public abstract class Command {
protected Mono<Void> badArgument(MessageCreateEvent event, String arg) { protected Mono<Void> badArgument(MessageCreateEvent event, String arg) {
return event.getMessage().getChannel() return event.getMessage().getChannel()
.flatMap(channel -> .flatMap(channel ->
channel.createMessage("Error, this argument isn't recognized: '" + arg + "'.\n" + getUsage())) channel.createMessage("Error, this argument isn't recognized: '" + arg + "'.\n Usage: " + getUsage()))
.then(); .then();
} }
@ -130,4 +133,8 @@ public abstract class Command {
+ " - " + subtitleInfo.getLanguage()) + " - " + subtitleInfo.getLanguage())
.limit(20); .limit(20);
} }
protected List<String> getArguments(MessageCreateEvent event) {
return List.of(event.getMessage().getContent().substring(Math.min(name.length() + 1, name.length())).split(" "));
}
} }

View File

@ -4,43 +4,52 @@ import com.github.wtekiela.opensub4j.response.ListResponse;
import com.github.wtekiela.opensub4j.response.ResponseStatus; import com.github.wtekiela.opensub4j.response.ResponseStatus;
import com.github.wtekiela.opensub4j.response.SubtitleFile; import com.github.wtekiela.opensub4j.response.SubtitleFile;
import discord4j.core.event.domain.message.MessageCreateEvent; import discord4j.core.event.domain.message.MessageCreateEvent;
import discord4j.rest.util.Color;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.XmlRpcException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import xyz.vallat.louis.database.SubtitleLineManager;
import xyz.vallat.louis.subtitles.OpenSubtitles; import xyz.vallat.louis.subtitles.OpenSubtitles;
import xyz.vallat.louis.subtitles.parser.SubtitleParser; import xyz.vallat.louis.subtitles.parser.SubtitleParser;
import java.time.Instant;
import java.util.List;
public class Download extends Command { public class Download extends Command {
private static final Logger logger = LoggerFactory.getLogger(Download.class.getCanonicalName());
public Download(String name) { public Download(String name) {
super(name, "Download a subtitle.", " subtitleId", 1, 1); super(name, "Download a subtitle.", name + " subtitleId", 1, 1);
} }
@Override @Override
public Mono<Void> execute(MessageCreateEvent event) { public Mono<Void> execute(MessageCreateEvent event) {
String[] args = event.getMessage().getContent().split(" "); List<String> args = getArguments(event);
if (args.length < minArgs || (args.length >= 1 && !StringUtils.isNumeric(args[1]))) if (args.isEmpty()) return notEnoughArguments(event);
return event.getMessage().getChannel() else if (!StringUtils.isNumeric(args.get(0))) return badArgument(event, args.get(0));
.flatMap(messageChannel -> messageChannel.createMessage("Error: malformed arguments. " + return event.getMessage().getChannel().flatMap(channel -> event.getMessage().addReaction(WAITING).then(
"Usage:" + usage)).then(); channel.createEmbed(embed -> {
try { embed.setTitle("Importation").setColor(Color.RED);
ListResponse<SubtitleFile> subs = OpenSubtitles.downloadSubtitle(Integer.parseInt(args[1])); try {
if (subs.getStatus().getCode() == ResponseStatus.OK.getCode()) { ListResponse<SubtitleFile> subs = OpenSubtitles.downloadSubtitle(Integer.parseInt(args.get(0)));
return event.getMessage().getChannel() if (subs.getStatus().getCode() == ResponseStatus.OK.getCode()) {
.flatMap(messageChannel -> SubtitleLineManager.importSubtitleLines(
{ new SubtitleParser().parseSRT(
String var = subs.getData().get(0).getContentAsString("cp1252"); subs.getData().get(0).getContentAsString("cp1252")));
SubtitleParser subtitleParser = new SubtitleParser(); embed.setColor(Color.MEDIUM_SEA_GREEN).setDescription("Everything went well.");
subtitleParser.parseSRT(var); } else {
return messageChannel.createMessage("Imported."); logger.error("Could not download subtitle '{}': {}", args.get(0), subs.getStatus());
embed.setDescription("An error occurred. Please contact my administrator.");
} }
) } catch (XmlRpcException e) {
.then(); logger.error("An error occurred while fetching the data from opensubtitles: {}", e.getMessage());
} else embed.setDescription("An error occurred, please contact my administrator.");
return event.getMessage().getChannel().flatMap(channel -> channel.createMessage("An error occurred.")).then(); }
} catch (XmlRpcException ignored) { embed.setTimestamp(Instant.now());
return event.getMessage().getChannel().flatMap(messageChannel -> messageChannel.createMessage("Error.")).then(); }
} ))).then(event.getMessage().removeSelfReaction(WAITING)).then();
} }
} }

View File

@ -1,7 +1,6 @@
package xyz.vallat.louis.commands; package xyz.vallat.louis.commands;
import discord4j.core.event.domain.message.MessageCreateEvent; import discord4j.core.event.domain.message.MessageCreateEvent;
import discord4j.core.object.reaction.ReactionEmoji;
import discord4j.rest.util.Color; import discord4j.rest.util.Color;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -13,16 +12,15 @@ import java.util.List;
public class ListLangMovie extends Command { public class ListLangMovie extends Command {
private static final Logger logger = LoggerFactory.getLogger(ListLangMovie.class.getCanonicalName()); private static final Logger logger = LoggerFactory.getLogger(ListLangMovie.class.getCanonicalName());
private static final ReactionEmoji WAITING = ReactionEmoji.unicode("");
public ListLangMovie(String name) { public ListLangMovie(String name) {
super(name, "List all languages attached to a film title or an IMDB Identifier.", super(name, "List all languages attached to a film title or an IMDB Identifier.",
name + " imdb|title value", 3, 3); name + " imdb|title value", 2, 2);
} }
@Override @Override
public Mono<Void> execute(MessageCreateEvent event) { public Mono<Void> execute(MessageCreateEvent event) {
List<String> arguments = List.of(event.getMessage().getContent().split(" ")); List<String> arguments = getArguments(event);
if (arguments.size() < minArgs) return notEnoughArguments(event); if (arguments.size() < minArgs) return notEnoughArguments(event);
else if (!arguments.get(1).equalsIgnoreCase("imdb") && else if (!arguments.get(1).equalsIgnoreCase("imdb") &&
!arguments.get(1).equalsIgnoreCase("title")) !arguments.get(1).equalsIgnoreCase("title"))

View File

@ -1,67 +0,0 @@
package xyz.vallat.louis.commands;
import com.github.wtekiela.opensub4j.response.ListResponse;
import com.github.wtekiela.opensub4j.response.ResponseStatus;
import com.github.wtekiela.opensub4j.response.SubtitleInfo;
import discord4j.core.event.domain.message.MessageCreateEvent;
import discord4j.core.object.entity.Message;
import discord4j.core.object.entity.channel.MessageChannel;
import discord4j.core.object.reaction.ReactionEmoji;
import discord4j.rest.util.Color;
import org.apache.xmlrpc.XmlRpcException;
import reactor.core.publisher.Mono;
import xyz.vallat.louis.subtitles.OpenSubtitles;
public class ListLangMovieImdb extends Command {
private static final ReactionEmoji WAITING = ReactionEmoji.unicode("");
public ListLangMovieImdb(String name) {
super(name, "List all languages attached to a film using its IMDB Identifier.", name + " IMDB_ID", 1, 2);
}
@Override
public Mono<Void> execute(MessageCreateEvent event) {
String arg = event.getMessage().getContent().substring(name.length() + 1);
if (arg.isBlank()) return notEnoughArguments(event);
return event.getMessage().getChannel()
.flatMap(channel -> {
if (OpenSubtitles.isLoggedIn()) {
return event.getMessage().addReaction(WAITING)
.then(event.getMessage().getChannel().flatMap(messageChannel ->
searchAndShowFilms(arg, channel, messageChannel)))
.then(event.getMessage().removeSelfReaction(WAITING))
.then();
} else return channel.createMessage("I cannot search for subtitle languages right now. Sorry.");
})
.then();
}
// TODO: ADD MOVIE TITLE
private Mono<? extends Message> searchAndShowFilms(String arg, MessageChannel channel, MessageChannel messageChannel) {
try {
ListResponse<SubtitleInfo> subtitles = OpenSubtitles.searchSubtitles("", arg);
if (subtitles.getStatus().getCode() == ResponseStatus.OK.getCode()) {
return messageChannel.createEmbed(
embed -> {
embed.setTitle("Results")
.setDescription("Found " + subtitles.getData().size() + " results.")
.setColor(Color.BISMARK);
if (!subtitles.getData().isEmpty()) {
StringBuilder s = new StringBuilder();
for (SubtitleInfo info : subtitles.getData().subList(0, Math.min(10, subtitles.getData().size())))
s.append(info.getSubtitleFileId()).append(" - ").append(info.getLanguage()).append("\n");
embed.addField("Languages found", s.toString(), false);
}
});
} else if (subtitles.getStatus().getCode() == ResponseStatus.INVALID_PARAMETERS.getCode()) {
return messageChannel.createMessage("It looks like it is an invalid IMDB identifier.");
} else {
return messageChannel.createMessage("An error happened while fetching the results. " +
"Try again later, or contact my administrator." + subtitles.getStatus());
}
} catch (XmlRpcException e) {
return channel.createMessage("It seems like OpenSubtitles had a stroke.");
}
}
}

View File

@ -1,63 +0,0 @@
package xyz.vallat.louis.commands;
import com.github.wtekiela.opensub4j.response.ListResponse;
import com.github.wtekiela.opensub4j.response.MovieInfo;
import com.github.wtekiela.opensub4j.response.ResponseStatus;
import discord4j.core.event.domain.message.MessageCreateEvent;
import discord4j.core.object.entity.Message;
import discord4j.core.object.entity.channel.MessageChannel;
import discord4j.core.object.reaction.ReactionEmoji;
import discord4j.rest.util.Color;
import org.apache.xmlrpc.XmlRpcException;
import reactor.core.publisher.Mono;
import xyz.vallat.louis.subtitles.OpenSubtitles;
public class SearchTitle extends Command {
private static final ReactionEmoji WAITING = ReactionEmoji.unicode("");
private static final String FORMAT = "%1$-7s - %2$s\n";
public SearchTitle(String name) {
super(name, "A command to search some subtitles.", name + " <name>", 1, 1);
}
@Override
public Mono<Void> execute(MessageCreateEvent event) {
String arg = event.getMessage().getContent().substring(name.length() + 1);
if (arg.replace(" ", "").length() == 0)
return notEnoughArguments(event);
return event.getMessage().getChannel()
.flatMap(channel -> {
if (OpenSubtitles.isLoggedIn()) {
return event.getMessage().addReaction(WAITING)
.then(event.getMessage().getChannel().flatMap(messageChannel ->
searchAndShowFilms(arg, channel, messageChannel)))
.then(event.getMessage().removeSelfReaction(WAITING))
.then();
} else return channel.createMessage("I cannot search for subtitles right now. Sorry.");
})
.then();
}
private Mono<? extends Message> searchAndShowFilms(String arg, MessageChannel channel, MessageChannel messageChannel) {
try {
ListResponse<MovieInfo> response = OpenSubtitles.searchImdb(arg);
if (response.getStatus().getCode() == ResponseStatus.OK.getCode()) {
return messageChannel.createEmbed(
embed -> {
embed.setTitle("Results")
.setDescription("Found " + response.getData().size() + " results.")
.setColor(Color.BISMARK);
StringBuilder s = new StringBuilder("```txt\n");
for (MovieInfo info : response.getData().subList(0, Math.min(10, response.getData().size())))
s.append(String.format(FORMAT, info.getId(), info.getTitle()));
s.append("```");
embed.addField("First 10 results:", s.toString(), false);
});
} else
return messageChannel.createMessage("An error happened while fetching the results. Try again later, or contact my administrator.");
} catch (XmlRpcException e) {
return channel.createMessage("It seems like OpenSubtitles had a stroke.");
}
}
}

View File

@ -3,11 +3,13 @@ package xyz.vallat.louis.database;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import xyz.vallat.louis.codes.ExitCodes; import xyz.vallat.louis.codes.ExitCodes;
import xyz.vallat.louis.subtitles.parser.SubtitleBlock;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.util.List;
public final class SubtitleLineManager { public final class SubtitleLineManager {
@ -69,4 +71,8 @@ public final class SubtitleLineManager {
} }
} }
public static void importSubtitleLines(List<SubtitleBlock> subtitleBlocks) {
}
} }