diff --git a/.gitignore b/.gitignore index ade51d6..3bd3447 100644 --- a/.gitignore +++ b/.gitignore @@ -193,4 +193,5 @@ gradle-app.setting .classpath rsc/* -!rsc/Ordnerstruktur.txt \ No newline at end of file +!rsc/Ordnerstruktur.txt +!rsc/tts.py \ No newline at end of file diff --git a/README.md b/README.md index 0d5b0ad..a52faed 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ Werte enthalten: (dieses Verzeichnis sollte natürlich existieren) - restrict_commands_to_channel -> Textkanalname, auf dem die Botkommandos empfangen werden +Python gTTS installieren mit pip install gTTS + ##Export Zum Exportieren der Applikation führe den Befehl "gradlew clean build" im Root Verzeichnis aus. Die fertige Jar liegt diff --git a/app/src/main/java/de/yannicpunktdee/yoshibot/audio/AudioControllerManager.java b/app/src/main/java/de/yannicpunktdee/yoshibot/audio/AudioControllerManager.java index 095ab58..f8dfb66 100644 --- a/app/src/main/java/de/yannicpunktdee/yoshibot/audio/AudioControllerManager.java +++ b/app/src/main/java/de/yannicpunktdee/yoshibot/audio/AudioControllerManager.java @@ -1,7 +1,6 @@ package de.yannicpunktdee.yoshibot.audio; import java.util.Map; -import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import de.yannicpunktdee.yoshibot.main.YoshiBot; @@ -17,10 +16,10 @@ public class AudioControllerManager { public AudioController getController(long guildId) { AudioController ac = null; - if (audioController.containsKey(guildId)) + if(audioController.containsKey(guildId)) ac = audioController.get(guildId); else { - ac = new AudioController(Objects.requireNonNull(YoshiBot.getInstance().jda.getGuildById(guildId))); + ac = new AudioController(YoshiBot.getInstance().jda.getGuildById(guildId)); audioController.put(guildId, ac); } return ac; diff --git a/app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/JokeCommand.java b/app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/JokeCommand.java index 44c8362..2df2d51 100644 --- a/app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/JokeCommand.java +++ b/app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/JokeCommand.java @@ -8,7 +8,6 @@ import java.net.URL; import java.util.List; import java.util.Random; -import de.yannicpunktdee.yoshibot.utils.RestHelper; import org.apache.commons.lang3.StringEscapeUtils; import org.json.JSONException; import org.json.JSONObject; @@ -20,9 +19,9 @@ import net.dv8tion.jda.api.entities.TextChannel; /** * Schickt einen zufälligen Jokus aus einer zufällig ausgewählten Quelle in den Textchannel. - * * @author Yannic Link */ +@SuppressWarnings("deprecation") public class JokeCommand extends YoshiCommand { /** @@ -35,56 +34,71 @@ public class JokeCommand extends YoshiCommand { /** * {@inheritDoc} */ - @Override - public synchronized boolean execute() { + @Override public synchronized boolean execute() { String message = "Jokus"; Random random = new Random(); int number = random.nextInt(3); - switch (number) { - case 0: - message = jokeApi(); - break; - case 1: - message = officialJokeApi(); - break; - case 2: - message = chuckNorris(); - break; - default: - message = "Jokus"; - break; + switch(number) { + case 0: message = jokeApi(); break; + case 1: message = officialJokeApi(); break; + case 2: message = chuckNorris(); break; + default: message = "Jokus"; break; } - if (context.containsArguments(new String[]{"channel"})) { + if(context.containsArguments(new String[] {"channel"})) { String arg = context.getArgument("channel"); - if (arg == null) { + if(arg == null) { sendMessage("Es wurde kein channel angegeben."); return false; } - List channels = YoshiBot.getInstance().jda - .getTextChannelsByName(context.getArgument("channel"), true); - if (channels.isEmpty()) { + List channels = YoshiBot.getInstance().jda.getTextChannelsByName(context.getArgument("channel"), true); + if(channels.isEmpty()) { sendMessage("Der Kanalname konnte nicht gefunden werden."); return false; } channels.get(0).sendMessage(message).queue(); - } else { + }else { sendMessage(message); } return true; } + private String getFromURL(String url) throws IOException { + StringBuilder response = new StringBuilder(""); + + HttpURLConnection con = null; + + try{ + con = (HttpURLConnection)(new URL(url)).openConnection(); + con.setRequestMethod("GET"); + BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream())); + + String line; + while((line = br.readLine()) != null) { + response.append(StringEscapeUtils.unescapeHtml4(line)); + } + + br.close(); + }catch(IOException e) { + return null; + }finally { + if(con != null) con.disconnect(); + } + + return response.toString(); + } + private String chuckNorris() { String url = "http://api.icndb.com/jokes/random"; JSONObject json = null; try { - String raw = RestHelper.getFromURL(url); + String raw = getFromURL(url); json = new JSONObject(raw); return json.getJSONObject("value").getString("joke"); - } catch (JSONException | IOException e) { + }catch(JSONException | IOException e) { return "Konnte keinen Jokus von \"" + url + "\" laden."; } } @@ -95,13 +109,13 @@ public class JokeCommand extends YoshiCommand { JSONObject json = null; try { - String raw = RestHelper.getFromURL(url); + String raw = getFromURL(url); json = new JSONObject(raw); String result = json.getString("setup"); result += " - "; result += json.getString("punchline"); return result; - } catch (JSONException | IOException e) { + }catch(JSONException | IOException e) { return "Konnte keinen Jokus von \"" + url + "\" laden."; } } @@ -112,15 +126,15 @@ public class JokeCommand extends YoshiCommand { JSONObject json = null; try { - String raw = RestHelper.getFromURL(url); + String raw = getFromURL(url); json = new JSONObject(raw); String result = json.getString("setup"); result += " - "; result += json.getString("delivery"); return result; - } catch (JSONException | IOException e) { + }catch(JSONException | IOException e) { return "Konnte keinen Jokus von \"" + url + "\" laden."; } } - + } diff --git a/app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/SayCommand.java b/app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/SayCommand.java index 3c77ec2..37c4409 100644 --- a/app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/SayCommand.java +++ b/app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/SayCommand.java @@ -1,15 +1,68 @@ package de.yannicpunktdee.yoshibot.command.commands; +import de.yannicpunktdee.yoshibot.audio.AudioController; +import de.yannicpunktdee.yoshibot.audio.AudioLoadResultHandlerImpl; import de.yannicpunktdee.yoshibot.command.YoshiCommand; import de.yannicpunktdee.yoshibot.command.YoshiCommandContext; +import de.yannicpunktdee.yoshibot.main.Resources; +import de.yannicpunktdee.yoshibot.main.YoshiBot; +import de.yannicpunktdee.yoshibot.utils.Logger; +import net.dv8tion.jda.api.entities.VoiceChannel; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.UUID; public class SayCommand extends YoshiCommand { + protected final String[] requiredArguments = {"text", "channel"}; + + public SayCommand(YoshiCommandContext context) { super(context); } @Override - public boolean execute() {return true;} + public boolean execute() { + if(!super.execute()) return false; + + String path = Resources.buildTempAudioFilePath("tts"); + + try { + ProcessBuilder pb = new ProcessBuilder( + "python", + "rsc/tts.py", + "--text", + context.getArgument("text"), + "--lang", + "de", + "--out", + path); + pb.redirectError(); + + Process p = pb.start(); + int exitCode = p.waitFor(); + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + return false; + } + + List channels = YoshiBot.getInstance().jda.getVoiceChannelsByName(context.getArgument("channel"), true); + if(!(channels.size() > 0)) { + context.getEvent().getTextChannel().sendMessage("Der Kanalname konnte nicht gefunden werden.").queue(); + return false; + } + VoiceChannel vc = channels.get(0); + + AudioController ac = YoshiBot.getInstance().audioControllerManager.getController(vc.getGuild().getIdLong()); + YoshiBot.getInstance().audioPlayerManager.loadItem(path, new AudioLoadResultHandlerImpl(ac)); + vc.getGuild().getAudioManager().openAudioConnection(vc); + + File deleteFile = new File(path); + deleteFile.delete(); //FIXME Funktioniert noch nicht + + return false; + } } diff --git a/app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/StopCommand.java b/app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/StopCommand.java index 3c226fc..a29de19 100644 --- a/app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/StopCommand.java +++ b/app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/StopCommand.java @@ -8,16 +8,16 @@ public class StopCommand extends YoshiCommand { protected final String[] requiredArguments = {"please", "uwu"}; - + public StopCommand(YoshiCommandContext context) { super(context); } @Override public boolean execute() { - if (!super.execute()) return false; + if(!super.execute()) return false; YoshiBot.getInstance().stop(); return true; } - + } diff --git a/app/src/main/java/de/yannicpunktdee/yoshibot/main/Main.java b/app/src/main/java/de/yannicpunktdee/yoshibot/main/Main.java index 35dd85a..05883d8 100644 --- a/app/src/main/java/de/yannicpunktdee/yoshibot/main/Main.java +++ b/app/src/main/java/de/yannicpunktdee/yoshibot/main/Main.java @@ -1,7 +1,11 @@ package de.yannicpunktdee.yoshibot.main; +import java.io.BufferedReader; import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; import java.net.URISyntaxException; +import java.util.UUID; import javax.security.auth.login.LoginException; /** diff --git a/app/src/main/java/de/yannicpunktdee/yoshibot/main/Resources.java b/app/src/main/java/de/yannicpunktdee/yoshibot/main/Resources.java index 5bdb186..5bed2c5 100644 --- a/app/src/main/java/de/yannicpunktdee/yoshibot/main/Resources.java +++ b/app/src/main/java/de/yannicpunktdee/yoshibot/main/Resources.java @@ -14,7 +14,7 @@ import java.util.stream.Collectors; public class Resources { - private static final String default_propertiesFilePath = "../rsc/Config.properties"; + private static final String default_propertiesFilePath = "rsc/Config.properties"; private static String propertiesFilePath = default_propertiesFilePath; private static Properties propertiesFile; @@ -25,14 +25,14 @@ public class Resources { private static final String[] default_restrict_commands_to_channel = null; private static String[] restrict_commands_to_channel = default_restrict_commands_to_channel; - + private static String[] filtered_tags; private static Map> feedDetails; - + public synchronized static boolean init(String pathToConfig) { Logger.log("Lade Config.properties ...", Type.INFO); - + if (pathToConfig != null) { if (!(new File(pathToConfig)).exists()) { Logger.log("Der in den Argumenten angegebene Pfad zur Config.properties existiert nicht.", Type.ERROR); @@ -44,26 +44,26 @@ public class Resources { Type.ERROR); return false; } - + propertiesFile = new Properties(); try { propertiesFile.load( new FileInputStream(propertiesFilePath) - ); + ); Logger.log("Config-Datei erfolgreich geladen.", Type.INFO); } catch (IOException e) { Logger.log("Es ist ein Fehler beim Öffnen der Config.propeties aufgetreten.", Type.ERROR); return false; } - + boolean isOk = initJdaBuilderString(); if (isOk) isOk = initChannelRestrict(); if (isOk) isOk = initAudio(); initTagFilter(); - + if (isOk) Logger.log("Die Konfigurationen wurden erfolgreich geladen.", Type.INFO); else Logger.log("Die Konfiguration konnte nicht geladen werden", Type.ERROR); - + return isOk; } @@ -75,12 +75,12 @@ public class Resources { jda_builder_string = propertiesFile.getProperty("jda_builder_string"); return true; } - + public static String getJdaBuilderString() { return jda_builder_string; } - + private static void initTagFilter() { if (!propertiesFile.containsKey("tags_general_filter")) { Logger.log("Kein Attribut 'tags_general_filter' gefunden", Type.WARNING); @@ -96,32 +96,39 @@ public class Resources { list -> Arrays.asList(list).subList(1, list.length))); } } - + private static boolean initAudio() { if (propertiesFile.containsKey("audio_source_directory")) { audio_source_directory = propertiesFile.getProperty("audio_source_directory"); } else { Logger.log("Die Config.properties spezifiziert kein audio_source_directory. Lade default.", Type.WARNING); } - + File file = new File(audio_source_directory); if (!file.exists() || !file.isDirectory()) { Logger.log("Das Audio-Verzeichnis wurde nicht gefunden.", Type.ERROR); return false; } - + if (file.listFiles().length < 1) Logger.log("Das Audio-Verzeichnis ist leer.", Type.WARNING); - + return true; } - + public static String getAudioFilePath(String name) { name = audio_source_directory + (audio_source_directory.endsWith("/") ? "" : "/") + name + ".opus"; if ((new File(name)).exists()) return name; else return null; } - + public static String getTempAudioFilePath(String name) { + name = audio_source_directory + (audio_source_directory.endsWith("/")? "" : "/") + "temp/" + name + ".opus"; + if((new File(name)).exists()) return name; + else return null; + } + public static String buildTempAudioFilePath(String name){ + return audio_source_directory + (audio_source_directory.endsWith("/")? "" : "/") + "temp/" + name + ".opus"; + } public static String getAudioSourceDirectory() { return audio_source_directory; } @@ -131,17 +138,17 @@ public class Resources { restrict_commands_to_channel = propertiesFile.getProperty("restrict_commands_to_channel").split(" "); return true; } - + public static String[] getRestrictCommandsToChannel() { return restrict_commands_to_channel; } - + public static Map> getFeedDetails() { return feedDetails; } - + public static String[] getGeneralFilterTags() { return filtered_tags; } - + } diff --git a/rsc/Ordnerstruktur.txt b/rsc/Ordnerstruktur.txt index 359a5f5..3800272 100644 --- a/rsc/Ordnerstruktur.txt +++ b/rsc/Ordnerstruktur.txt @@ -2,6 +2,7 @@ rsc |-- .gitkeep |-- Ordnerstruktur.txt |-- Config.properties + |-- tts.py |-- audio |-- temp |-- temp_1.opus diff --git a/rsc/tts.py b/rsc/tts.py new file mode 100644 index 0000000..2d4a8d4 --- /dev/null +++ b/rsc/tts.py @@ -0,0 +1,18 @@ +import sys +from gtts import gTTS +import os +import argparse + +parser = argparse.ArgumentParser() +parser.add_argument("--text") +parser.add_argument("--lang") +parser.add_argument("--out") +args = parser.parse_args() + +mytext = args.text +language = args.lang +output = args.out + +myobj = gTTS(text=mytext, lang=language, slow=False) + +myobj.save(output) \ No newline at end of file