Skip to content

Commit e311648

Browse files
authored
Merge pull request #1 from Simplexity-Development/remove-twitch
Remove twitch
2 parents 6d0c85b + 98ae6ce commit e311648

37 files changed

+1160
-799
lines changed

.idea/.gitignore

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
-77.7 KB
Binary file not shown.
-89.7 KB
Binary file not shown.

pom.xml

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>simplexity</groupId>
88
<artifactId>CLI-TTS</artifactId>
9-
<version>1.0.0</version>
9+
<version>2.0.0</version>
1010
<packaging>jar</packaging>
1111

1212
<properties>
@@ -80,17 +80,6 @@
8080
<artifactId>jlayer</artifactId>
8181
<version>1.0.1-1</version>
8282
</dependency>
83-
<dependency>
84-
<groupId>com.github.twitch4j</groupId>
85-
<artifactId>twitch4j</artifactId>
86-
<version>1.20.0</version>
87-
</dependency>
88-
<!-- https://mvnrepository.com/artifact/org.json/json -->
89-
<dependency>
90-
<groupId>org.json</groupId>
91-
<artifactId>json</artifactId>
92-
<version>20240303</version>
93-
</dependency>
9483
<dependency>
9584
<groupId>org.slf4j</groupId>
9685
<artifactId>slf4j-api</artifactId>
@@ -99,9 +88,19 @@
9988
<dependency>
10089
<groupId>ch.qos.logback</groupId>
10190
<artifactId>logback-classic</artifactId>
102-
<version>1.5.6</version>
91+
<version>1.5.16</version>
92+
</dependency>
93+
<dependency>
94+
<groupId>org.jetbrains</groupId>
95+
<artifactId>annotations</artifactId>
96+
<version>26.0.2</version>
97+
<scope>compile</scope>
98+
</dependency>
99+
<dependency>
100+
<groupId>org.yaml</groupId>
101+
<artifactId>snakeyaml</artifactId>
102+
<version>2.4</version>
103103
</dependency>
104-
105104
</dependencies>
106105

107-
</project>
106+
</project>

src/main/java/simplexity/Main.java

Lines changed: 40 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,53 @@
11
package simplexity;
22

3-
import com.amazonaws.regions.Region;
43
import org.slf4j.Logger;
54
import org.slf4j.LoggerFactory;
5+
import org.slf4j.event.Level;
66
import simplexity.amazon.PollyHandler;
7+
import simplexity.amazon.PollySetup;
78
import simplexity.amazon.SpeechHandler;
89
import simplexity.commands.CommandManager;
910
import simplexity.commands.ExitCommand;
1011
import simplexity.commands.HelpCommand;
1112
import simplexity.commands.ReloadCommand;
12-
import simplexity.config.TTSConfig;
13-
import simplexity.messages.Errors;
14-
import simplexity.twitch.TwitchClientHandler;
15-
import simplexity.twitch.TwitchSetup;
13+
import simplexity.config.config.ConfigHandler;
14+
import simplexity.config.config.YmlConfig;
15+
import simplexity.httpserver.LocalServer;
16+
import simplexity.util.Logging;
1617

18+
import java.io.File;
19+
import java.io.IOException;
1720
import java.util.Scanner;
1821

1922
public class Main {
2023
private static final Logger logger = LoggerFactory.getLogger(Main.class);
24+
private static YmlConfig ymlConfig;
2125
private static CommandManager commandManager;
22-
private static PollyHandler pollyHandler;
26+
public static PollyHandler pollyHandler;
2327
private static SpeechHandler speechHandler;
24-
private static TwitchClientHandler twitchClientHandler;
25-
private static TwitchSetup twitchSetup;
2628
public static Scanner scanner;
29+
public static boolean runApp = true;
2730

2831
public static void main(String[] args) {
29-
logger.info("Starting application");
32+
Logging.log(logger, "Starting application", Level.INFO);
3033
scanner = new Scanner(System.in);
3134
commandManager = new CommandManager();
3235
registerCommands(commandManager);
33-
TTSConfig.getInstance().reloadConfig();
34-
pollyHandler = createPollyHandler();
35-
speechHandler = new SpeechHandler();
36-
twitchClientHandler = new TwitchClientHandler();
37-
twitchSetup = new TwitchSetup();
38-
twitchSetup.setup();
39-
twitchClientHandler.setupClient();
40-
twitchClientHandler.getTwitchClient().getChat().joinChannel("RhythmWeHear");
41-
42-
while (true) {
36+
File file = new File("config/config.yml");
37+
try {
38+
ymlConfig = new YmlConfig(file, "config.yml");
39+
} catch (IOException e) {
40+
System.out.println("Fatal Error: Config was unable to be generated.");
41+
e.printStackTrace();
42+
return;
43+
}
44+
ConfigHandler.getInstance().reloadValues(ymlConfig);
45+
PollySetup.setupPollyAndSpeech();
46+
LocalServer.run();
47+
while (runApp) {
4348
String input = scanner.nextLine();
44-
if (input.equals("--exit")) {
45-
return;
46-
}
4749
if (!commandManager.runCommand(input)) {
48-
twitchClientHandler.getTwitchClient().getChat().sendMessage("RhythmWeHear", input);
49-
5050
speechHandler.processSpeech(input);
51-
} else {
52-
System.out.println("command executed");
5351
}
5452
}
5553
}
@@ -64,26 +62,24 @@ public static CommandManager getCommandManager() {
6462
return commandManager;
6563
}
6664

67-
public static PollyHandler createPollyHandler() {
68-
PollyHandler pollyHandler = null;
69-
String awsAccessID = TTSConfig.getInstance().getAwsAccessID();
70-
String awsSecretKey = TTSConfig.getInstance().getAwsSecretKey();
71-
Region awsRegion = TTSConfig.getInstance().getAwsRegion();
72-
if (awsAccessID.isEmpty() || awsSecretKey.isEmpty() || awsRegion == null) {
73-
System.out.println(Errors.NULL_AWS_CREDENTIALS);
74-
return null;
75-
}
76-
try {
77-
78-
pollyHandler = new PollyHandler(awsAccessID, awsSecretKey, awsRegion);
79-
} catch (IllegalArgumentException e) {
80-
System.out.println(Errors.NULL_AWS_CREDENTIALS);
81-
}
65+
public static PollyHandler getPollyHandler() {
8266
return pollyHandler;
8367
}
8468

69+
public static void setSpeechHandler(SpeechHandler speechHandlerToSet) {
70+
speechHandler = speechHandlerToSet;
71+
}
8572

86-
public static PollyHandler getPollyHandler() {
87-
return pollyHandler;
73+
public static void setPollyHandler(PollyHandler pollyHandlerToSet) {
74+
pollyHandler = pollyHandlerToSet;
8875
}
89-
}
76+
77+
public static Scanner getScanner() {
78+
return scanner;
79+
}
80+
81+
public static YmlConfig getYmlConfig(){
82+
return ymlConfig;
83+
}
84+
85+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package simplexity.amazon;
2+
3+
import com.amazonaws.regions.Region;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
import org.slf4j.event.Level;
7+
import simplexity.Main;
8+
import simplexity.config.config.ConfigHandler;
9+
import simplexity.config.locale.Message;
10+
import simplexity.util.Logging;
11+
12+
import java.util.Scanner;
13+
14+
public class PollySetup {
15+
private static final Logger logger = LoggerFactory.getLogger(PollySetup.class);
16+
private static final Scanner scanner = Main.getScanner();
17+
18+
public static void setupPollyAndSpeech() {
19+
connectToPolly();
20+
Main.setSpeechHandler(new SpeechHandler());
21+
}
22+
23+
public static PollyHandler createPollyHandler() {
24+
PollyHandler pollyHandler = null;
25+
String awsAccessID = ConfigHandler.getInstance().getAwsAccessID();
26+
String awsSecretKey = ConfigHandler.getInstance().getAwsSecretKey();
27+
Region awsRegion = ConfigHandler.getInstance().getAwsRegion();
28+
if (awsAccessID.isEmpty() || awsSecretKey.isEmpty() || awsRegion == null) {
29+
System.out.println(Message.NULL_AWS_CREDENTIALS);
30+
return null;
31+
}
32+
try {
33+
pollyHandler = new PollyHandler(awsAccessID, awsSecretKey, awsRegion);
34+
} catch (IllegalArgumentException e) {
35+
System.out.println(Message.NULL_AWS_CREDENTIALS);
36+
}
37+
return pollyHandler;
38+
}
39+
40+
public static void connectToPolly() {
41+
while (true) {
42+
Main.setPollyHandler(createPollyHandler());
43+
if (Main.getPollyHandler() != null) {
44+
return;
45+
}
46+
Logging.logAndPrint(logger, Message.PLEASE_SAVE_AWS_INFO_IN_CONFIG.getMessage(), Level.INFO);
47+
scanner.nextLine();
48+
ConfigHandler.getInstance().reloadValues(Main.getYmlConfig());
49+
if (Main.getPollyHandler() != null) {
50+
return;
51+
}
52+
}
53+
}
54+
}

src/main/java/simplexity/amazon/SpeechHandler.java

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
import org.slf4j.LoggerFactory;
1212
import org.slf4j.event.Level;
1313
import simplexity.Main;
14-
import simplexity.config.TTSConfig;
15-
import simplexity.messages.Errors;
16-
import simplexity.util.Util;
14+
import simplexity.config.config.ConfigHandler;
15+
import simplexity.config.config.SpeechEffectRule;
16+
import simplexity.config.locale.Message;
17+
import simplexity.util.Logging;
1718

1819
import java.io.InputStream;
1920

@@ -22,73 +23,100 @@ public class SpeechHandler {
2223
private VoiceId voiceId;
2324

2425
public SpeechHandler() {
25-
this.voiceId = TTSConfig.getInstance().getDefaultVoice();
26+
this.voiceId = ConfigHandler.getInstance().getDefaultVoice();
27+
Logging.log(logger, "Initialized SpeechHandler with default voice: " + voiceId.toString(), Level.INFO);
2628
}
2729

30+
/**
31+
* Processes the given text, optionally replacing it based on configurations,
32+
* and synthesizes and plays the speech.
33+
*/
2834
public void processSpeech(String text) {
29-
System.out.println(text);
35+
// Replace text and determine if SSML is needed
3036
String processedText = replaceText(text);
31-
System.out.println(processedText);
3237
boolean useSSML = !text.equals(processedText);
38+
39+
//Synthesize speech
3340
InputStream speechStream;
3441
if (useSSML) {
3542
speechStream = synthesizeSSMLSpeech(processedText, voiceId);
3643
} else {
3744
speechStream = synthesizeSpeech(processedText, voiceId);
3845
}
3946
if (speechStream == null) {
40-
Util.logAndPrint(logger, Errors.CAUGHT_EXCEPTION.replace("%error%", "Speech stream is null"), Level.ERROR);
47+
Logging.logAndPrint(logger, Message.GENERAL_ERROR.getMessage().replace("%error%", "Speech stream is null"), Level.ERROR);
4148
return;
4249
}
50+
51+
//play it
4352
playSpeech(speechStream);
4453
}
4554

55+
/**
56+
* Replaces text based on replacement mappings and updates the voice if a prefix is matched.
57+
*/
58+
4659
public String replaceText(String text) {
47-
for (String key : TTSConfig.getInstance().getReplaceText().keySet()) {
48-
text = text.replace(key, TTSConfig.getInstance().getReplaceText().get(key));
60+
for (SpeechEffectRule effectRule : ConfigHandler.getInstance().getEffectRules()) {
61+
text = effectRule.applyRule(text);
4962
}
50-
for (String key : TTSConfig.getInstance().getVoicePrefixes().keySet()) {
63+
for (String key : ConfigHandler.getInstance().getVoicePrefixes().keySet()) {
5164
if (text.startsWith(key)) {
5265
text = text.replace(key, "");
53-
voiceId = TTSConfig.getInstance().getVoicePrefixes().get(key);
66+
voiceId = ConfigHandler.getInstance().getVoicePrefixes().get(key);
5467
}
5568
}
5669
return text;
5770
}
5871

5972
public InputStream synthesizeSSMLSpeech(String text, VoiceId voice) {
60-
text = "<speak>" + text + "</speak>";
61-
SynthesizeSpeechRequest synthesizeSpeechRequest;
73+
String ssmlText = "<speak>" + text + "</speak>";
6274
try {
63-
synthesizeSpeechRequest = new SynthesizeSpeechRequest()
64-
.withText(text)
75+
SynthesizeSpeechRequest request = new SynthesizeSpeechRequest()
76+
.withText(ssmlText)
6577
.withTextType(TextType.Ssml)
6678
.withVoiceId(voice)
6779
.withOutputFormat(OutputFormat.Mp3);
68-
SynthesizeSpeechResult synthesizeSpeechResult = Main.getPollyHandler().getPolly().synthesizeSpeech(synthesizeSpeechRequest);
69-
return synthesizeSpeechResult.getAudioStream();
80+
SynthesizeSpeechResult result = Main.getPollyHandler().getPolly().synthesizeSpeech(request);
81+
return result.getAudioStream();
7082
} catch (RuntimeException exception) {
71-
Util.logAndPrint(logger, Errors.CAUGHT_EXCEPTION.replace("%error%", exception.getMessage()), Level.ERROR);
83+
logSynthesisError(exception, ssmlText);
7284
return null;
7385
}
7486
}
7587

7688
public InputStream synthesizeSpeech(String text, VoiceId voice) {
77-
SynthesizeSpeechRequest synthesizeSpeechRequest = new SynthesizeSpeechRequest()
78-
.withText(text)
79-
.withVoiceId(voice)
80-
.withOutputFormat(OutputFormat.Mp3);
81-
SynthesizeSpeechResult synthesizeSpeechResult = Main.getPollyHandler().getPolly().synthesizeSpeech(synthesizeSpeechRequest);
82-
return synthesizeSpeechResult.getAudioStream();
89+
try {
90+
SynthesizeSpeechRequest request = new SynthesizeSpeechRequest()
91+
.withText(text)
92+
.withVoiceId(voice)
93+
.withOutputFormat(OutputFormat.Mp3);
94+
SynthesizeSpeechResult result = Main.getPollyHandler().getPolly().synthesizeSpeech(request);
95+
return result.getAudioStream();
96+
} catch (RuntimeException exception) {
97+
logSynthesisError(exception, text);
98+
return null;
99+
}
83100
}
84101

102+
/**
103+
* Plays the text as speech
104+
*/
85105
public void playSpeech(InputStream speechStream) {
86106
AdvancedPlayer player;
87107
try {
88108
player = new AdvancedPlayer(speechStream, FactoryRegistry.systemRegistry().createAudioDevice());
89109
player.play();
90110
} catch (Exception exception) {
91-
Util.logAndPrint(logger, Errors.CAUGHT_EXCEPTION.replace("%error%", exception.getMessage()), Level.ERROR);
111+
Logging.logAndPrint(logger, Message.GENERAL_ERROR.getMessage().replace("%error%", exception.getMessage()), Level.ERROR);
92112
}
93113
}
114+
115+
/**
116+
* Logs errors during speech synthesis.
117+
*/
118+
private void logSynthesisError(Exception e, String text) {
119+
Logging.logAndPrint(logger, Message.GENERAL_ERROR.getMessage().replace("%error%", e.getMessage()), Level.ERROR);
120+
Logging.logAndPrint(logger, Message.MESSAGE_NOT_PARSABLE.getMessage().replace("%message%", text), Level.ERROR);
121+
}
94122
}

0 commit comments

Comments
 (0)