diff --git a/languages/cs.yml b/languages/cs.yml
index 88aea7fbe..3cf651e10 100644
--- a/languages/cs.yml
+++ b/languages/cs.yml
@@ -1,7 +1,7 @@
language:
name: "Czech"
locale: "cs"
- version: "2.3.7"
+ version: "2.4.0"
author: "Pogy__"
logging:
banned: ":airplane_departure: %s **zablokován.**"
@@ -182,6 +182,10 @@ label:
position: "Pozice %s"
feedback: "Zpětná vazba"
github: "Github"
+ queueAdd: "Přidat do fronty"
+ song: "Skladba"
+ shuffle: "Zamíchat"
+ loop: "Smyčka"
message:
default:
usage: "Použití {guild_prefix}%s."
@@ -208,6 +212,10 @@ message:
invalidOptionChannel: "Daný kanál neexistuje, jak jej vybrat? Jste průvodce?"
missingOption: "Musíte zadat hodnotu pro možnost %s!"
nameChangeFailed: "Nelze změnit mou vlastní přezdívku!"
+ time:
+ date: "Použijte platné datum!\nVezměte prosím na vědomí, že používáme formát dd.MM.yyyy (day.month.year)!"
+ time: "Použijte prosím platný čas!\\nPamatuj, že používáme formát HH/mm (hodina/minuta)!"
+ notEnough: "Zadaný čas nestačí!"
birthday:
added:
self: "Vaše narozeniny byly přidány!"
@@ -217,8 +225,6 @@ message:
self: "Vaše narozeniny byly odstraněny!"
other: "Narozeniny %s byly odstraněny!"
noPerms: "Nemáte oprávnění k odstranění narozenin!"
- other:
- dateError: "Použijte platné datum!\nVezměte prosím na vědomí, že používáme formát dd.MM.yyyy (day.month.year)!"
instagramNotifier:
added: "Bylo vytvořeno oznámení Instagram pro uživatele %s!"
list: "Zde jsou všechny Instagram oznámení které byly nastaveny:\n```%s```"
@@ -349,6 +355,7 @@ message:
resume: "Hráč byl obnoven!"
shuffle: "Fronta byla zamíchána!"
songInfo: "**Skladba:**```%s od %s```\n%s `[%s/%s]` %s"
+ songInfoSlim: "%s od %s"
songQueueEmpty: "Fronta je prázdná!"
songQueue: "Fronta obsahuje následující skladby: %s"
volume:
@@ -512,6 +519,12 @@ message:
infractions:
success: "Uživatel %s má %s přestupků!"
empty: "Uživatel %s nema žádné přestupky!"
+ schedule:
+ added: "The schedule has been successfully created!"
+ delete:
+ success: "The schedule has been successfully deleted!"
+ failed: "The given schedule does not exist!"
+ list: "Here is a list of all schedules: ```%s```"
game:
description:
blackjack: "Hrajte Blackjack se svými přáteli!"
@@ -606,6 +619,8 @@ command:
warn: "Upozornit uživatele a nechat je potrestat automaticky."
infractions: "Zobrazit všechna varování uživatele."
musicquiz: "Zahrajte si s přáteli hudební kvíz!"
+ musicpanel: "Přístup k jednoduchému uživatelskému rozhraní pro správu hudebního systému!"
+ schedule: "Naplánovat zprávy na později nebo na opakovaný čas!"
category:
info: "Slouží ke shromažďování informací nebo poskytování informací."
moderation: "Nástroje pro moderování, které vám mohou pomoci spravovat uživatele nebo zabránit porušení pravidel na serveru."
diff --git a/languages/de.yml b/languages/de.yml
index f6d49652c..628de4d91 100644
--- a/languages/de.yml
+++ b/languages/de.yml
@@ -1,7 +1,7 @@
language:
name: "German"
locale: "de"
- version: "2.3.7"
+ version: "2.4.0"
author: "Presti"
logging:
banned: ":airplane_departure: %s **gebannt.**"
@@ -182,6 +182,10 @@ label:
position: "Position %s"
feedback: "Feedback"
github: "Github"
+ queueAdd: "Zur Song-Liste hinzufügen"
+ song: "Song"
+ shuffle: "Mischen"
+ loop: "Song-Schleife"
message:
default:
usage: "Nutzung {guild_prefix}%s."
@@ -208,6 +212,10 @@ message:
invalidOptionChannel: "Dieser Channel ist nicht bekannt. Kannst du zaubern?"
missingOption: "Du musst einen Wert für die Option %s angeben!"
nameChangeFailed: "Ich konnte meinen eigenen Nickname nicht bearbeiten!"
+ time:
+ date: "Bitte gebe ein richtiges Datum an!\nTipp wir nutzen das dd.MM.yyy (tag.monat.jahr) Format!"
+ time: "Bitte gebe eine richtige Zeit an!\nTipp wir nutzen das HH/mm (stunde/minute (24-stunden)) Format!"
+ notEnough: "Die angegebene Zeit ist nicht genügend!"
birthday:
added:
self: "Dein Geburtstag wurde hinzugefügt!"
@@ -217,8 +225,6 @@ message:
self: "Dein Geburtstag wurde entfernt!"
other: "Der Geburtstag von %s wurde entfernt!"
noPerms: "Du hast keine Berechtigung um Geburtstage zu entfernen!"
- other:
- dateError: "Bitte nutze das richtige Datums format! (day.month.year)!"
instagramNotifier:
added: "Ein Instagram Notifier wurde für %s erstellt!"
list: "Hier ist eine Liste mit allen Instagram Notifier:\n```%s```"
@@ -349,6 +355,7 @@ message:
resume: "Der Musikspieler wurde fortgesetzt!"
shuffle: "Die Songliste wurde gemischt!"
songInfo: "**Song:**```%s von %s```\n%s `[%s/%s]` %s"
+ songInfoSlim: "%s von %s"
songQueueEmpty: "Die Songliste ist leer!"
songQueue: "Die Songliste enthält diese Songs: %s"
volume:
@@ -512,6 +519,12 @@ message:
infractions:
success: "Der Nutzer %s hat %s Verwarnungen!"
empty: "Der Nutzer %s hat keine Verwarnungen!"
+ schedule:
+ added: "Eine geplante Nachricht wurde erfolgreich erstellt!"
+ delete:
+ success: "Eine geplante Nachricht wurde erfolgreich gelöscht!"
+ failed: "Die angegebene geplante Nachricht existiert nicht!"
+ list: "Hier ist eine Liste aller geplanten Nachrichten: ```%s```"
game:
description:
blackjack: "Spiele Blackjack mit deinen Freunden!"
@@ -606,6 +619,8 @@ command:
warn: "Warne einen Nutzer und lass ihn automatisch bestraft werden."
infractions: "Zeige alle Verwarnungen eines Nutzers an."
musicquiz: "Spiele mit deinen Freunden eine Runde Musik Quiz!"
+ musicpanel: "Ein simples UI zum Nutzen vom Musik System!"
+ schedule: "Plane Nachrichten für später und für eine wiederholte Zeit!"
category:
info: "Wird verwendet, um Informationen zu sammeln oder Informationen zu geben."
moderation: "Moderations-Tools, die Ihnen beim Verwalten von Benutzern helfen oder das Missachten von Regeln auf dem Server verhindern können."
diff --git a/languages/en-GB.yml b/languages/en-GB.yml
index 914332b5d..fb0ecd8e1 100644
--- a/languages/en-GB.yml
+++ b/languages/en-GB.yml
@@ -1,7 +1,7 @@
language:
name: "English (UK)"
locale: "en-GB"
- version: "2.3.7"
+ version: "2.4.0"
author: "Presti"
logging:
banned: ":airplane_departure: %s **banned.**"
@@ -214,7 +214,7 @@ message:
nameChangeFailed: "Could not change the my own nickname!"
time:
date: "Please use a valid Date!\nNote that we use the the format dd.MM.yyyy (day.month.year)!"
- time: "Please use a valid Time!\Note that we use the format HH/mm (hour/minute (24-hour))"
+ time: "Please use a valid Time!\nNote that we use the format HH/mm (hour/minute (24-hour))!"
notEnough: "The entered time is not enough!"
birthday:
added:
@@ -519,6 +519,12 @@ message:
infractions:
success: "The User %s has %s infractions!"
empty: "The User %s has no infractions!"
+ schedule:
+ added: "The schedule has been successfully created!"
+ delete:
+ success: "The schedule has been successfully deleted!"
+ failed: "The given schedule does not exist!"
+ list: "Here is a list of all schedules: ```%s```"
game:
description:
blackjack: "Play Blackjack with your friends!"
diff --git a/languages/id.yml b/languages/id.yml
index d65fd681c..2abc03dbd 100644
--- a/languages/id.yml
+++ b/languages/id.yml
@@ -1,7 +1,7 @@
language:
name: "Indonesia"
locale: "id"
- version: "2.3.7"
+ version: "2.4.0"
author: "Gorengan_Hunter, SpyCat"
logging:
banned: ":airplane_departure: %s **telah diban.**"
@@ -182,6 +182,10 @@ label:
position: "Posisi %s"
feedback: "Masukan"
github: "Github"
+ queueAdd: "Tambahkan ke antrian"
+ song: "Lagu"
+ shuffle: "Acak"
+ loop: "Ulang"
message:
default:
usage: "Penggunaan {guild_prefix}%s."
@@ -208,6 +212,10 @@ message:
invalidOptionChannel: "Channel yang diberikan tidak ada, bagaimana kamu memilih ini? Apakah kamu seorang penyihir?"
missingOption: "Kamu perlu memberikan nilai untuk opsi %s!"
nameChangeFailed: "Tidak dapat mengganti nickname ku!"
+ time:
+ date: "Harap gunakan tanggal yang valid!\nPerhatikan bahwa kami menggunakan format dd.MM.yyyy (day.month.year)!"
+ time: "Harap gunakan waktu yang valid!\nPerhatikan bahwa kami menggunakan format HH/mm (jam/menit (24-jam))!"
+ notEnough: "Waktu yang dimasukkan tidak cukup!"
birthday:
added:
self: "Ulang Tahun mu telah ditambahkan!"
@@ -217,8 +225,6 @@ message:
self: "Ulang Tahun mu telah dihapus!"
other: "Ulang Tahun %s telah dihapus!"
noPerms: "Kamu tidak punya izin untuk menghapus Ulang Tahun!"
- other:
- dateError: "Harap gunakan tanggal yang valid!\nPerhatikan bahwa kami menggunakan format dd.MM.yyyy (day.month.year)!"
instagramNotifier:
added: "Pemberitahuan Instagram telah dibuat untuk %s!"
list: "Dibawah ini daftar Notifier Instagram yang telah disetup:\n```%s```"
@@ -349,6 +355,7 @@ message:
resume: "Pemutar telah di ditemukan!"
shuffle: "Antrian telah diacak!"
songInfo: "**Lagu:**```%s oleh %s```\n%s `[%s/%s]` %s"
+ songInfoSlim: "%s oleh %s"
songQueueEmpty: "Antrian kosong!"
songQueue: "Di antrian terdapat musik berikut: %s"
volume:
@@ -512,6 +519,12 @@ message:
infractions:
success: "User %s memiliki %s pelanggaran!"
empty: "User %s tidak memiliki pelanggaran!"
+ schedule:
+ added: "The schedule has been successfully created!"
+ delete:
+ success: "The schedule has been successfully deleted!"
+ failed: "The given schedule does not exist!"
+ list: "Here is a list of all schedules: ```%s```"
game:
description:
blackjack: "Mainkan Blackjack dengan temanmu!"
@@ -606,6 +619,8 @@ command:
warn: "Peringati user dan biarkan dia dihukum otomatis."
infractions: "Tampilkan semua peringatan yang dimiliki user."
musicquiz: "Mainkan Kuis Musik dengan teman anda!"
+ musicpanel: "Akses UI sederhana untuk mengelola Sistem Musik!"
+ schedule: "Jadwalkan pesan untuk nanti atau untuk diulang!"
category:
info: "Dipakai untuk mendapatkan informasi atau memberi informasi."
moderation: "Alat moderasi untuk membantumu menjaga servermu!"
diff --git a/languages/pl.yml b/languages/pl.yml
index 763dcc18e..76024cd31 100644
--- a/languages/pl.yml
+++ b/languages/pl.yml
@@ -1,7 +1,7 @@
language:
name: "Polish"
locale: "pl"
- version: "2.3.7"
+ version: "2.4.0"
author: "Trust"
logging:
banned: ":airplane_departure: %s **zbanowany/a.**"
@@ -182,6 +182,10 @@ label:
position: "Pozycja %s"
feedback: "Informacja do producenta"
github: "GitHub"
+ queueAdd: "Dodaj do kolejki"
+ song: "Pieśń"
+ shuffle: "Losuj"
+ loop: "Pętla"
message:
default:
usage: "Użycie {guild_prefix}%s."
@@ -208,6 +212,10 @@ message:
invalidOptionChannel: "Podany kanał nie istnieje, jak go wybrałeś? Czy jesteś Czarodziejem?"
missingOption: "Musisz podać wartość dla opcji %s!"
nameChangeFailed: "Nie mogłem zmienić swoje imię!"
+ time:
+ date: "Proszę użyć poprawnej daty!\nZauważ, że używamy formatu dd.mm.rrrr (dzień.miesiąc.rok)!"
+ time: "Proszę użyć poprawnego czasu!\nPamiętaj, że używamy formatu HH/mm (godzina/minuta (24-godziny))!"
+ notEnough: "Wprowadzony czas nie wystarczy!"
birthday:
added:
self: "Twoje urodziny zostały dodane!"
@@ -217,8 +225,6 @@ message:
self: "Twoje urodziny zostały usunięte!"
other: "Urodziny %s zostały usunięte!"
noPerms: "Nie masz uprawnień do usunięcia urodzin!"
- other:
- dateError: "Proszę użyć poprawnej daty!\nZauważ, że używamy formatu dd.mm.rrrr (dzień.miesiąc.rok)!"
instagramNotifier:
added: "Powiadomienie o Instagramie zostało utworzone dla użytkownika %s!"
list: "Tutaj są wszystkie powiadomienia o Instagram'u, które zostały skonfigurowane:\n```%s```"
@@ -349,6 +355,7 @@ message:
resume: "Odtwarzacz został wznowiony!"
shuffle: "Kolejka została zlosowana!"
songInfo: "**Pieśń:**```%s autorstwa %s```\n%s `[%s/%s]` %s"
+ songInfoSlim: "%s autorstwa %s"
songQueueEmpty: "Kolejka jest pusta!"
songQueue: "Kolejka zawiera następujące pieśni: %s"
volume:
@@ -512,6 +519,12 @@ message:
infractions:
success: "Użytkownik %s ma %s infrakcji!"
empty: "Użytkownik %s nie ma żadnych infrakcji!"
+ schedule:
+ added: "Harmonogram został utworzony!"
+ delete:
+ success: "Harmonogram został usunięty!"
+ failed: "Podany harmonogram nie istnieje!"
+ list: "Oto lista wszystkich harmonogramów: ```%s```"
game:
description:
blackjack: "Zagraj w Blackjack z przyjaciółmi!"
@@ -606,6 +619,8 @@ command:
warn: "Ostrzegaj użytkownika i pozwól im być karani automatycznie."
infractions: "Pokaż wszystkie ostrzeżenia użytkownika."
musicquiz: "Zagraj z przyjaciółmi grę w Quiz!"
+ musicpanel: "Uzyskaj dostęp do prostego interfejsu użytkownika, aby zarządzać systemem muzycznym!"
+ schedule: "Zaplanuj wiadomości na później lub na powtarzający się czas!"
category:
info: "Wykorzystywane do gromadzenia informacji lub przekazywania informacji."
moderation: "Narzędzia moderacyjne, które mogą pomóc ci zarządzać użytkownikami lub zapobiec łamania zasad na serwerze."
diff --git a/pom.xml b/pom.xml
index 5e5fc45bb..b05b55cb1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
de.presti
Ree6
- 2.3.9
+ 2.4.0
jar
@@ -52,7 +52,7 @@
net.dv8tion
JDA
- 5.0.0-beta.5
+ 5.0.0-beta.6
com.github.walkyst
@@ -74,7 +74,7 @@
io.sentry
sentry
- 6.15.0
+ 6.16.0
me.carleslc.Simple-YAML
@@ -144,19 +144,19 @@
com.github.Ree6-Applications
Ree6-SQL
- 1b00250427
+ 433261d192
org.slf4j
slf4j-api
- 2.0.6
+ 2.0.7
ch.qos.logback
logback-classic
- 1.4.5
+ 1.4.6
diff --git a/src/main/java/de/presti/ree6/audio/music/MusicWorker.java b/src/main/java/de/presti/ree6/audio/music/MusicWorker.java
index 9dbfe9ebe..b8f68d8e7 100644
--- a/src/main/java/de/presti/ree6/audio/music/MusicWorker.java
+++ b/src/main/java/de/presti/ree6/audio/music/MusicWorker.java
@@ -4,7 +4,6 @@
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.source.bandcamp.BandcampAudioSourceManager;
-import com.sedmelluq.discord.lavaplayer.source.local.LocalAudioSourceManager;
import com.sedmelluq.discord.lavaplayer.source.soundcloud.SoundCloudAudioSourceManager;
import com.sedmelluq.discord.lavaplayer.source.twitch.TwitchStreamAudioSourceManager;
import com.sedmelluq.discord.lavaplayer.source.vimeo.VimeoAudioSourceManager;
@@ -12,6 +11,7 @@
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
+import de.presti.ree6.audio.music.source.RestrictedHttpAudioSourceManager;
import de.presti.ree6.commands.CommandEvent;
import de.presti.ree6.language.LanguageService;
import de.presti.ree6.main.Main;
@@ -66,7 +66,7 @@ public MusicWorker() {
playerManager.registerSourceManager(new VimeoAudioSourceManager());
playerManager.registerSourceManager(new TwitchStreamAudioSourceManager());
playerManager.registerSourceManager(new YoutubeAudioSourceManager());
- playerManager.registerSourceManager(new LocalAudioSourceManager());
+ playerManager.registerSourceManager(new RestrictedHttpAudioSourceManager());
}
/**
diff --git a/src/main/java/de/presti/ree6/audio/music/source/RestrictedHttpAudioSourceManager.java b/src/main/java/de/presti/ree6/audio/music/source/RestrictedHttpAudioSourceManager.java
new file mode 100644
index 000000000..392e325ae
--- /dev/null
+++ b/src/main/java/de/presti/ree6/audio/music/source/RestrictedHttpAudioSourceManager.java
@@ -0,0 +1,48 @@
+package de.presti.ree6.audio.music.source;
+
+import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
+import com.sedmelluq.discord.lavaplayer.source.http.HttpAudioSourceManager;
+import com.sedmelluq.discord.lavaplayer.track.AudioItem;
+import com.sedmelluq.discord.lavaplayer.track.AudioReference;
+
+import java.util.Arrays;
+
+/**
+ * A restricted version of {@link HttpAudioSourceManager}.
+ */
+public class RestrictedHttpAudioSourceManager extends HttpAudioSourceManager {
+
+ /**
+ * A whitelist for every URL that is allowed.
+ */
+ static final String[] WHITELIST = {
+ "https://cdn.blurp.com",
+ "https://api.streamelements.com/kappa/v2/speech",
+ };
+
+ /**
+ * A {@link AudioReference} for later use as return value if the URL is not whitelisted.
+ */
+ static final AudioReference invalidReference = new AudioReference("INVALID", "Blocked URL!");
+
+ @Override
+ public AudioItem loadItem(AudioPlayerManager manager, AudioReference reference) {
+ reference = checkWhitelisting(reference);
+ return super.loadItem(manager, reference);
+ }
+
+ /**
+ * A method used to check everything
+ * @param reference the {@link AudioReference} parsed from above.
+ * @return either the invalid Reference or the input back.
+ */
+ public AudioReference checkWhitelisting(AudioReference reference) {
+ String url = reference.identifier;
+
+ if (Arrays.stream(WHITELIST).anyMatch(url::startsWith)) {
+ return reference;
+ }
+
+ return invalidReference;
+ }
+}
diff --git a/src/main/java/de/presti/ree6/commands/impl/community/Schedule.java b/src/main/java/de/presti/ree6/commands/impl/community/Schedule.java
index 674bba340..996c50dfe 100644
--- a/src/main/java/de/presti/ree6/commands/impl/community/Schedule.java
+++ b/src/main/java/de/presti/ree6/commands/impl/community/Schedule.java
@@ -6,22 +6,21 @@
import de.presti.ree6.commands.interfaces.ICommand;
import de.presti.ree6.sql.SQLSession;
import de.presti.ree6.sql.entities.ScheduledMessage;
+import de.presti.ree6.sql.entities.webhook.WebhookScheduledMessage;
import net.dv8tion.jda.api.Permission;
+import net.dv8tion.jda.api.entities.Webhook;
+import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
import net.dv8tion.jda.internal.interactions.CommandDataImpl;
-import org.apache.commons.validator.GenericValidator;
-import org.apache.commons.validator.routines.DateValidator;
import java.time.Duration;
import java.time.Instant;
-import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
-import java.time.format.DateTimeParseException;
import java.util.Map;
/**
@@ -66,7 +65,8 @@ public void onPerform(CommandEvent commandEvent) {
.append(Instant.ofEpochMilli(scheduledMessage.getDelayAmount())
.atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH/mm")));
}
- // TODO:: list response message.
+
+ commandEvent.reply(commandEvent.getResource("message.schedule.list"));
}
case "delete" -> {
@@ -77,19 +77,20 @@ public void onPerform(CommandEvent commandEvent) {
Map.of("gid", commandEvent.getGuild().getIdLong(), "id", id.getAsLong()));
if (scheduledMessage != null) {
- // TODO:: add success message.
SQLSession.getSqlConnector().getSqlWorker().deleteEntity(scheduledMessage);
+ commandEvent.reply(commandEvent.getResource("message.schedule.delete.success"));
} else {
- // TODO:: add failed message.
+ commandEvent.reply(commandEvent.getResource("message.schedule.delete.failed"));
}
}
case "create" -> {
- OptionMapping repeat = commandEvent.getOption("repeat");
OptionMapping month = commandEvent.getOption("month");
OptionMapping day = commandEvent.getOption("day");
OptionMapping hour = commandEvent.getOption("hour");
OptionMapping minute = commandEvent.getOption("minute");
+ OptionMapping channel = commandEvent.getOption("channel");
+ OptionMapping repeat = commandEvent.getOption("repeat");
long fullTime = 0;
if (month != null) fullTime += Duration.ofDays(31 * month.getAsLong()).toMillis();
@@ -102,11 +103,26 @@ public void onPerform(CommandEvent commandEvent) {
return;
}
- // TODO:: check for webhook and use existing one.
+ GuildChannelUnion guildChannel = channel.getAsChannel();
+
ScheduledMessage scheduledMessage = new ScheduledMessage();
+
+ WebhookScheduledMessage webhookScheduledMessage =
+ SQLSession.getSqlConnector().getSqlWorker().getEntity(new WebhookScheduledMessage(),
+ "SELECT * FROM ScheduledMessageWebhooks WHERE gid = :gid AND actualChannelId = :channel",
+ Map.of("gid", commandEvent.getGuild().getId(),"channel", guildChannel.getIdLong()));
+
+ if (webhookScheduledMessage == null) {
+ Webhook webhook = guildChannel.asStandardGuildMessageChannel().createWebhook("Ree6-Schedule").complete();
+
+ webhookScheduledMessage = SQLSession.getSqlConnector().getSqlWorker()
+ .updateEntity(new WebhookScheduledMessage(commandEvent.getGuild().getId(), webhook.getId(), webhook.getToken(), guildChannel.getIdLong()));
+ }
+
+ scheduledMessage.setScheduledMessageWebhook(webhookScheduledMessage);
scheduledMessage.setDelayAmount(fullTime);
scheduledMessage.setRepeated(repeat.getAsBoolean());
- // TODO:: add success message.
+ commandEvent.reply(commandEvent.getResource("message.schedule.added"));
}
default -> commandEvent.reply(commandEvent.getResource("message.default.invalidOption"));
@@ -120,12 +136,13 @@ public void onPerform(CommandEvent commandEvent) {
public CommandData getCommandData() {
return new CommandDataImpl("schedule", "command.description.schedule")
.addSubcommands(new SubcommandData("create", "Create a new scheduled Message.")
- .addOption(OptionType.INTEGER, "month", "The months of the delay.", false)
- .addOption(OptionType.INTEGER, "day", "The days of the delay.", false)
- .addOption(OptionType.INTEGER, "hour", "The hours of the delay.", false)
- .addOption(OptionType.INTEGER, "minute", "The minutes of the delay.", false)
- .addOption(OptionType.BOOLEAN, "repeat", "If the schedule should be repeated.", true),
- new SubcommandData("list", "List all scheduled Messages."),
+ .addOption(OptionType.CHANNEL, "channel", "The channel it should be sent to.", true)
+ .addOption(OptionType.BOOLEAN, "repeat", "If the schedule should be repeated.", true)
+ .addOption(OptionType.INTEGER, "month", "The months of the delay.", false)
+ .addOption(OptionType.INTEGER, "day", "The days of the delay.", false)
+ .addOption(OptionType.INTEGER, "hour", "The hours of the delay.", false)
+ .addOption(OptionType.INTEGER, "minute", "The minutes of the delay.", false),
+ new SubcommandData("list", "List all scheduled Messages."),
new SubcommandData("delete", "Delete a scheduled Message.")
.addOptions(new OptionData(OptionType.INTEGER, "id", "The ID of the scheduled Message", true).setMinValue(1)));
}
diff --git a/src/main/java/de/presti/ree6/commands/impl/community/Ticket.java b/src/main/java/de/presti/ree6/commands/impl/community/Ticket.java
index b33a57156..fbd227a01 100644
--- a/src/main/java/de/presti/ree6/commands/impl/community/Ticket.java
+++ b/src/main/java/de/presti/ree6/commands/impl/community/Ticket.java
@@ -68,7 +68,7 @@ public void onPerform(CommandEvent commandEvent) {
Tickets finalTickets = tickets;
- logChannel.getAsChannel().asTextChannel().createWebhook("Ticket-Log").queue(webhook -> {
+ logChannel.getAsChannel().asStandardGuildMessageChannel().createWebhook("Ticket-Log").queue(webhook -> {
finalTickets.setLogChannelId(webhook.getIdLong());
finalTickets.setLogChannelWebhookToken(webhook.getToken());
commandEvent.getGuild().createCategory("Tickets").addPermissionOverride(commandEvent.getGuild().getPublicRole(), null, EnumSet.of(Permission.VIEW_CHANNEL)).queue(category1 -> {
diff --git a/src/main/java/de/presti/ree6/events/MenuEvents.java b/src/main/java/de/presti/ree6/events/MenuEvents.java
index 6906d6096..7ea9f4e4c 100644
--- a/src/main/java/de/presti/ree6/events/MenuEvents.java
+++ b/src/main/java/de/presti/ree6/events/MenuEvents.java
@@ -184,6 +184,9 @@ public void onButtonInteraction(@NotNull ButtonInteractionEvent event) {
} else {
guildMusicManager.getPlayer().setPaused(true);
}
+ } else {
+ Main.getInstance().getCommandManager().sendMessage(LanguageService.getByGuild(event.getGuild(), "message.music.notConnected"),
+ event.getChannel(), event.getHook());
}
}
@@ -191,14 +194,24 @@ public void onButtonInteraction(@NotNull ButtonInteractionEvent event) {
event.deferReply(true).queue();
GuildMusicManager guildMusicManager = Main.getInstance().getMusicWorker().getGuildAudioPlayer(event.getGuild());
- if (guildMusicManager != null) guildMusicManager.getPlayer().setPaused(true);
+ if (guildMusicManager != null) {
+ guildMusicManager.getPlayer().setPaused(true);
+ } else {
+ Main.getInstance().getCommandManager().sendMessage(LanguageService.getByGuild(event.getGuild(), "message.music.notConnected"),
+ event.getChannel(), event.getHook());
+ }
}
case "re_music_skip" -> {
event.deferReply(true).queue();
GuildMusicManager guildMusicManager = Main.getInstance().getMusicWorker().getGuildAudioPlayer(event.getGuild());
- if (guildMusicManager != null) guildMusicManager.getScheduler().nextTrack(event.getChannel(), true);
+ if (guildMusicManager != null) {
+ Main.getInstance().getMusicWorker().skipTrack(event.getChannel(), event.getHook(),1,true);
+ } else {
+ Main.getInstance().getCommandManager().sendMessage(LanguageService.getByGuild(event.getGuild(), "message.music.notConnected"),
+ event.getChannel(), event.getHook());
+ }
}
case "re_music_loop" -> {
@@ -219,6 +232,9 @@ public void onButtonInteraction(@NotNull ButtonInteractionEvent event) {
em.setFooter(event.getGuild().getName() + " - " + Data.ADVERTISEMENT, event.getGuild().getIconUrl());
Main.getInstance().getCommandManager().sendMessage(em, event.getChannel(), event.getHook());
+ } else {
+ Main.getInstance().getCommandManager().sendMessage(LanguageService.getByGuild(event.getGuild(), "message.music.notConnected"),
+ event.getChannel(), event.getHook());
}
}
@@ -240,6 +256,9 @@ public void onButtonInteraction(@NotNull ButtonInteractionEvent event) {
em.setFooter(event.getGuild().getName() + " - " + Data.ADVERTISEMENT, event.getGuild().getIconUrl());
Main.getInstance().getCommandManager().sendMessage(em, event.getChannel(), event.getHook());
+ } else {
+ Main.getInstance().getCommandManager().sendMessage(LanguageService.getByGuild(event.getGuild(), "message.music.notConnected"),
+ event.getChannel(), event.getHook());
}
}
@@ -303,8 +322,8 @@ public void onModalInteraction(@NotNull ModalInteractionEvent event) {
case "re_music_add_modal" -> {
event.deferReply(true).queue();
-
- Main.getInstance().getMusicWorker().playSong(event.getValue("re_music_add_modal_song").getAsString(), event.getGuild(), event.getMember(), event.getChannel(), event.getInteraction().getHook());
+ Main.getInstance().getMusicWorker().playSong(event.getValue("re_music_add_modal_song").getAsString(),
+ event.getGuild(), event.getMember(), event.getChannel(), event.getInteraction().getHook());
}
case "statisticsSetupTwitchModal" -> {
diff --git a/src/main/java/de/presti/ree6/streamtools/StreamActionContainer.java b/src/main/java/de/presti/ree6/streamtools/StreamActionContainer.java
index 2a8ff74fd..aed480c81 100644
--- a/src/main/java/de/presti/ree6/streamtools/StreamActionContainer.java
+++ b/src/main/java/de/presti/ree6/streamtools/StreamActionContainer.java
@@ -1,5 +1,6 @@
package de.presti.ree6.streamtools;
+import com.github.twitch4j.common.events.TwitchEvent;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@@ -86,9 +87,10 @@ public StreamActionContainer(StreamAction streamAction) {
/**
* Run all Actions.
*
+ * @param twitchEvent The related Twitch event.
* @param userInput The User Input.
*/
- public void runActions(String userInput) {
+ public void runActions(TwitchEvent twitchEvent, String userInput) {
actions.forEach((run) -> {
String[] args = run.getArguments();
@@ -100,7 +102,7 @@ public void runActions(String userInput) {
}
}
- run.getAction().runAction(guild, args);
+ run.getAction().runAction(guild, twitchEvent, args);
});
}
}
diff --git a/src/main/java/de/presti/ree6/streamtools/action/IStreamAction.java b/src/main/java/de/presti/ree6/streamtools/action/IStreamAction.java
index 87151ae9e..bd5622811 100644
--- a/src/main/java/de/presti/ree6/streamtools/action/IStreamAction.java
+++ b/src/main/java/de/presti/ree6/streamtools/action/IStreamAction.java
@@ -1,5 +1,6 @@
package de.presti.ree6.streamtools.action;
+import com.github.twitch4j.common.events.TwitchEvent;
import net.dv8tion.jda.api.entities.Guild;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -12,7 +13,8 @@ public interface IStreamAction {
/**
* Run the specific action.
* @param guild The guild where the action should be executed.
+ * @param twitchEvent The twitch event that was fired.
* @param arguments Arguments for the action. (Can be null)
*/
- void runAction(@NotNull Guild guild, @Nullable String[] arguments);
+ void runAction(@NotNull Guild guild, @Nullable TwitchEvent twitchEvent, @Nullable String[] arguments);
}
diff --git a/src/main/java/de/presti/ree6/streamtools/action/impl/PlayBlerpStreamAction.java b/src/main/java/de/presti/ree6/streamtools/action/impl/PlayBlerpStreamAction.java
new file mode 100644
index 000000000..0764ee96f
--- /dev/null
+++ b/src/main/java/de/presti/ree6/streamtools/action/impl/PlayBlerpStreamAction.java
@@ -0,0 +1,68 @@
+package de.presti.ree6.streamtools.action.impl;
+
+import com.github.twitch4j.common.events.TwitchEvent;
+import com.github.twitch4j.pubsub.events.RewardRedeemedEvent;
+import de.presti.ree6.main.Main;
+import de.presti.ree6.streamtools.action.IStreamAction;
+import de.presti.ree6.streamtools.action.StreamActionInfo;
+import de.presti.ree6.utils.external.RequestUtility;
+import lombok.NoArgsConstructor;
+import net.dv8tion.jda.api.entities.Guild;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * StreamAction used to play a blerp sound that is bound to a specific channel reward.
+ */
+@NoArgsConstructor
+@StreamActionInfo(name = "PlayBlerp", command = "play-blerp", description = "Plays the blerp audio of a reward.", introduced = "2.4.0")
+public class PlayBlerpStreamAction implements IStreamAction {
+
+ /**
+ * RegEx to detect a Blerp link in the redemption itself.
+ */
+ String blerpRegEx = "https:\\/\\/blerp\\.com\\/soundbites\\/[a-zA-Z0-9]+";
+
+ /**
+ * RegEx to take the CDN Url of that sound out of the HTML content.
+ */
+ String blerpPageRegEx = "https:\\/\\/cdn\\.blerp\\.com\\/normalized\\/[a-zA-Z0-9]+";
+
+ /**
+ * A {@link Pattern} to actually detect it.
+ */
+ Pattern blerpPattern = Pattern.compile(blerpRegEx);
+
+ /**
+ * A {@link Pattern} to actually detect it.
+ */
+ Pattern blerpPagePattern = Pattern.compile(blerpPageRegEx);
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public void runAction(@NotNull Guild guild, TwitchEvent twitchEvent, String[] arguments) {
+ if (twitchEvent == null) return;
+
+ if (!Main.getInstance().getMusicWorker().isConnectedMember(guild.getSelfMember())) return;
+
+ if (twitchEvent instanceof RewardRedeemedEvent rewardRedeemedEvent) {
+ String prompt = rewardRedeemedEvent.getRedemption().getReward().getPrompt().toLowerCase();
+ Matcher matcher = blerpPattern.matcher(prompt);
+ if (matcher.find()) {
+ String blerpUrl = matcher.group(1);
+
+ String blerpPageResponse = RequestUtility.requestString(RequestUtility.Request.builder().url(blerpUrl).GET().build());
+
+ Matcher pageMatcher = blerpPagePattern.matcher(blerpPageResponse);
+ if (matcher.find()) {
+ Main.getInstance().getMusicWorker().loadAndPlay(guild, null, null,
+ pageMatcher.group(1),null, true, false);
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/de/presti/ree6/streamtools/action/impl/PlayTTSStreamAction.java b/src/main/java/de/presti/ree6/streamtools/action/impl/PlayTTSStreamAction.java
index 43d08e409..1e0fb7330 100644
--- a/src/main/java/de/presti/ree6/streamtools/action/impl/PlayTTSStreamAction.java
+++ b/src/main/java/de/presti/ree6/streamtools/action/impl/PlayTTSStreamAction.java
@@ -1,5 +1,6 @@
package de.presti.ree6.streamtools.action.impl;
+import com.github.twitch4j.common.events.TwitchEvent;
import de.presti.ree6.main.Main;
import de.presti.ree6.streamtools.action.StreamActionInfo;
import de.presti.ree6.streamtools.action.IStreamAction;
@@ -25,26 +26,15 @@ public class PlayTTSStreamAction implements IStreamAction {
* @inheritDoc
*/
@Override
- public void runAction(@NotNull Guild guild, String[] arguments) {
+ public void runAction(@NotNull Guild guild, TwitchEvent twitchEvent, String[] arguments) {
if (arguments == null || arguments.length == 0) {
return;
}
if (!Main.getInstance().getMusicWorker().isConnectedMember(guild.getSelfMember())) return;
- String text = String.join(" ", arguments);
-
- RequestUtility.Request request = RequestUtility.Request.builder()
- .url("https://api.streamelements.com/kappa/v2/speech?voice=Brian&text=" + URLEncoder.encode(text, StandardCharsets.UTF_8))
- .GET().build();
- byte[] tts = RequestUtility.requestBytes(request);
-
- Path filePath = Path.of("storage/tmp/", RandomUtils.randomString(16, false) + ".mp3");
-
- try {
- Files.write(filePath, tts);
- Main.getInstance().getMusicWorker().loadAndPlay(guild, null, null, filePath.toAbsolutePath().toString(), null, true, false);
- } catch (Exception ignore) {
- }
+ Main.getInstance().getMusicWorker().loadAndPlay(guild, null, null,
+ "https://api.streamelements.com/kappa/v2/speech?voice=Brian&text=" + URLEncoder.encode(String.join(" ", arguments), StandardCharsets.UTF_8),
+ null, true, false);
}
}
diff --git a/src/main/java/de/presti/ree6/streamtools/action/impl/PlayUrlStreamAction.java b/src/main/java/de/presti/ree6/streamtools/action/impl/PlayUrlStreamAction.java
index 6bbbe733b..016c039b4 100644
--- a/src/main/java/de/presti/ree6/streamtools/action/impl/PlayUrlStreamAction.java
+++ b/src/main/java/de/presti/ree6/streamtools/action/impl/PlayUrlStreamAction.java
@@ -1,5 +1,6 @@
package de.presti.ree6.streamtools.action.impl;
+import com.github.twitch4j.common.events.TwitchEvent;
import de.presti.ree6.main.Main;
import de.presti.ree6.streamtools.action.StreamActionInfo;
import de.presti.ree6.streamtools.action.IStreamAction;
@@ -19,7 +20,7 @@ public class PlayUrlStreamAction implements IStreamAction {
* @param arguments Arguments for the action. (Can be null)
*/
@Override
- public void runAction(@NotNull Guild guild, String[] arguments) {
+ public void runAction(@NotNull Guild guild, TwitchEvent twitchEvent, String[] arguments) {
if (arguments == null || arguments.length == 0) {
return;
}
diff --git a/src/main/java/de/presti/ree6/streamtools/action/impl/SayStreamAction.java b/src/main/java/de/presti/ree6/streamtools/action/impl/SayStreamAction.java
index 898fc75b4..34971caf0 100644
--- a/src/main/java/de/presti/ree6/streamtools/action/impl/SayStreamAction.java
+++ b/src/main/java/de/presti/ree6/streamtools/action/impl/SayStreamAction.java
@@ -1,5 +1,6 @@
package de.presti.ree6.streamtools.action.impl;
+import com.github.twitch4j.common.events.TwitchEvent;
import de.presti.ree6.main.Main;
import de.presti.ree6.streamtools.action.StreamActionInfo;
import de.presti.ree6.streamtools.action.IStreamAction;
@@ -19,7 +20,7 @@ public class SayStreamAction implements IStreamAction {
* @inheritDoc
*/
@Override
- public void runAction(@NotNull Guild guild, String[] arguments) {
+ public void runAction(@NotNull Guild guild, TwitchEvent twitchEvent, String[] arguments) {
if (arguments == null || arguments.length == 0) {
return;
}
diff --git a/src/main/java/de/presti/ree6/streamtools/action/impl/VoiceJoinStreamAction.java b/src/main/java/de/presti/ree6/streamtools/action/impl/VoiceJoinStreamAction.java
index 3d49e1d14..eb20da680 100644
--- a/src/main/java/de/presti/ree6/streamtools/action/impl/VoiceJoinStreamAction.java
+++ b/src/main/java/de/presti/ree6/streamtools/action/impl/VoiceJoinStreamAction.java
@@ -1,5 +1,6 @@
package de.presti.ree6.streamtools.action.impl;
+import com.github.twitch4j.common.events.TwitchEvent;
import de.presti.ree6.main.Main;
import de.presti.ree6.streamtools.action.StreamActionInfo;
import de.presti.ree6.streamtools.action.IStreamAction;
@@ -20,7 +21,7 @@ public class VoiceJoinStreamAction implements IStreamAction {
* @inheritDoc
*/
@Override
- public void runAction(@NotNull Guild guild, String[] arguments) {
+ public void runAction(@NotNull Guild guild, TwitchEvent twitchEvent, String[] arguments) {
if (arguments == null || arguments.length == 0) {
return;
}
diff --git a/src/main/java/de/presti/ree6/streamtools/action/impl/VoiceLeaveStreamAction.java b/src/main/java/de/presti/ree6/streamtools/action/impl/VoiceLeaveStreamAction.java
index 6ab949d83..0e5ed5bb0 100644
--- a/src/main/java/de/presti/ree6/streamtools/action/impl/VoiceLeaveStreamAction.java
+++ b/src/main/java/de/presti/ree6/streamtools/action/impl/VoiceLeaveStreamAction.java
@@ -1,5 +1,6 @@
package de.presti.ree6.streamtools.action.impl;
+import com.github.twitch4j.common.events.TwitchEvent;
import de.presti.ree6.main.Main;
import de.presti.ree6.streamtools.action.StreamActionInfo;
import de.presti.ree6.streamtools.action.IStreamAction;
@@ -18,7 +19,7 @@ public class VoiceLeaveStreamAction implements IStreamAction {
* @inheritDoc
*/
@Override
- public void runAction(@NotNull Guild guild, String[] arguments) {
+ public void runAction(@NotNull Guild guild, TwitchEvent twitchEvent, String[] arguments) {
if (!Main.getInstance().getMusicWorker().isConnectedMember(guild.getSelfMember())) return;
Main.getInstance().getMusicWorker().disconnect(guild);
diff --git a/src/main/java/de/presti/ree6/utils/apis/Notifier.java b/src/main/java/de/presti/ree6/utils/apis/Notifier.java
index e9413e176..1437e483d 100644
--- a/src/main/java/de/presti/ree6/utils/apis/Notifier.java
+++ b/src/main/java/de/presti/ree6/utils/apis/Notifier.java
@@ -180,7 +180,7 @@ public Notifier() {
if (!event.getRedemption().getChannelId().equalsIgnoreCase(container.getTwitchChannelId())) return;
if (container.getExtraArgument() == null || event.getRedemption().getReward().getId().equals(container.getExtraArgument())) {
- container.runActions(event.getRedemption().getUserInput());
+ container.runActions(event, event.getRedemption().getUserInput());
}
});
});
@@ -190,7 +190,7 @@ public Notifier() {
list.forEach(container -> {
if (!event.getChannelId().equalsIgnoreCase(container.getTwitchChannelId())) return;
- container.runActions(event.getData().getUsername());
+ container.runActions(event, event.getData().getUsername());
});
});
@@ -199,7 +199,7 @@ public Notifier() {
list.forEach(container -> {
if (!event.getBroadcasterUserId().equalsIgnoreCase(container.getTwitchChannelId())) return;
- container.runActions(event.getUserName());
+ container.runActions(null, event.getUserName());
});
});
diff --git a/src/main/java/de/presti/ree6/utils/external/RequestUtility.java b/src/main/java/de/presti/ree6/utils/external/RequestUtility.java
index 33f84fb2a..f724fb334 100644
--- a/src/main/java/de/presti/ree6/utils/external/RequestUtility.java
+++ b/src/main/java/de/presti/ree6/utils/external/RequestUtility.java
@@ -15,6 +15,8 @@
import java.net.http.HttpResponse;
import java.util.ArrayList;
import java.util.List;
+import java.util.Scanner;
+import java.util.regex.Pattern;
/**
* Utility used to work with HTTP Requests.
@@ -152,6 +154,38 @@ public static byte[] requestBytes(Request request) {
return new byte[0];
}
+ /**
+ * Send a Request.
+ * @param request the Request.
+ * @return a {@link String}
+ */
+ public static String requestString(Request request) {
+ try (InputStream httpResponse = request(request)) {
+
+ if (httpResponse == null) {
+ return "";
+ }
+
+ try {
+ Scanner scanner = new Scanner(httpResponse);
+ StringBuilder stringBuilder = new StringBuilder();
+
+ while(scanner.hasNext()){
+ stringBuilder.append(scanner.nextLine());
+ }
+
+ return stringBuilder.toString();
+ } catch (Exception ex) {
+ log.error("Couldn't send a Request!", ex);
+ }
+ } catch (IOException e) {
+ log.error("Couldn't send a Request!", e);
+ return "";
+ }
+
+ return "";
+ }
+
/**
* Utility class for Requests.
*/