0

Moved many operations to single main thread.

This commit is contained in:
Logan Fick
2019-06-25 10:20:55 -04:00
parent 079c7ecc81
commit fdb1c0b093
22 changed files with 417 additions and 96 deletions

View File

@@ -31,7 +31,7 @@ import net.dv8tion.jda.core.AccountType;
import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.JDABuilder;
public final class Main {
public final class Main implements Runnable {
private static final Logger logger = LoggerFactory.getLogger(Main.class);
private static final String token = System.getenv("TOKEN");
@@ -42,6 +42,11 @@ public final class Main {
}
public static final void main(final String[] arguments) {
MainThread.scheduleImmediately(new Main());
}
@Override
public final void run() {
logger.info("Beginning setup of LogalBot...");
logger.info("Verifying connection to Redis...");
@@ -93,6 +98,7 @@ public final class Main {
CommandManager.registerCommandAlias("die", "dice");
CommandManager.registerCommandAlias("random", "dice");
CommandManager.registerCommandAlias("rng", "dice");
CommandManager.registerCommandAlias("roll", "dice");
CommandManager.registerCommand("8ball", new EightBall(), false);
// Audio Commands

View File

@@ -0,0 +1,61 @@
package dev.logal.logalbot;
// Copyright 2019 Logan Fick
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import net.dv8tion.jda.core.utils.Checks;
public final class MainThread {
private static final ScheduledExecutorService mainThread = Executors
.newSingleThreadScheduledExecutor(new MainThreadFactory());
public static final void scheduleImmediately(final Runnable task) {
Checks.notNull(task, "Task");
mainThread.schedule(task, 0, TimeUnit.MICROSECONDS);
}
public static final ScheduledFuture<?> scheduleLater(final Runnable task, final long delay, final TimeUnit unit) {
Checks.notNull(task, "Task");
Checks.notNegative(delay, "Delay");
Checks.notNull(unit, "Unit");
return mainThread.schedule(task, delay, unit);
}
public static final ScheduledFuture<?> scheduleRepeatedlyAtFixedRate(final Runnable task, final long initialDelay,
final long period, final TimeUnit unit) {
Checks.notNull(task, "Task");
Checks.notNegative(initialDelay, "Initial Delay");
Checks.notNegative(period, "Period");
Checks.notNull(unit, "Unit");
return mainThread.scheduleAtFixedRate(task, initialDelay, period, unit);
}
public static final ScheduledFuture<?> scheduleRepeatedlyWithFixedDelay(final Runnable task,
final long initialDelay, final long period, final TimeUnit unit) {
Checks.notNull(task, "Task");
Checks.notNegative(initialDelay, "Initial Delay");
Checks.notNegative(period, "Period");
Checks.notNull(unit, "Unit");
return mainThread.scheduleWithFixedDelay(task, initialDelay, period, unit);
}
}

View File

@@ -0,0 +1,30 @@
package dev.logal.logalbot;
// Copyright 2019 Logan Fick
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import java.util.concurrent.ThreadFactory;
import net.dv8tion.jda.core.utils.Checks;
public final class MainThreadFactory implements ThreadFactory {
@Override
public final Thread newThread(final Runnable runnable) {
Checks.notNull(runnable, "Runnable");
final Thread newThread = new Thread(runnable);
newThread.setName("Main Thread");
return newThread;
}
}

View File

@@ -26,7 +26,9 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import dev.logal.logalbot.MainThread;
import dev.logal.logalbot.commands.CommandResponse;
import dev.logal.logalbot.tasks.TrackAdditionTask;
import dev.logal.logalbot.utils.AudioUtil;
import dev.logal.logalbot.utils.PermissionManager;
import dev.logal.logalbot.utils.TrackUtil;
@@ -54,7 +56,8 @@ public final class TrackLoadHandler implements AudioLoadResultHandler {
Checks.notNull(track, "Track");
final CommandResponse response;
final TrackScheduler scheduler = AudioUtil.getTrackScheduler(this.channel.getGuild());
final Guild guild = this.channel.getGuild();
final TrackScheduler scheduler = AudioUtil.getTrackScheduler(guild);
final AudioTrackInfo info = track.getInfo();
if (info.isStream) {
@@ -83,7 +86,7 @@ public final class TrackLoadHandler implements AudioLoadResultHandler {
}
final RequestedTrack requestedTrack = new RequestedTrack(track, requester);
scheduler.addToQueue(requestedTrack);
MainThread.scheduleImmediately(new TrackAdditionTask(guild, requestedTrack));
response = new CommandResponse("notes",
this.requester.getAsMention() + " added the following track to the queue:");
response.attachEmbed(TrackUtil.trackInfoEmbed(requestedTrack));
@@ -95,7 +98,8 @@ public final class TrackLoadHandler implements AudioLoadResultHandler {
Checks.notNull(playlist, "Playlist");
CommandResponse response;
final TrackScheduler scheduler = AudioUtil.getTrackScheduler(this.channel.getGuild());
final Guild guild = this.channel.getGuild();
final TrackScheduler scheduler = AudioUtil.getTrackScheduler(guild);
final AudioTrack selectedTrack = playlist.getSelectedTrack();
final AudioTrack track;
@@ -141,20 +145,19 @@ public final class TrackLoadHandler implements AudioLoadResultHandler {
}
} else {
if (PermissionManager.isWhitelisted(this.requester)) {
final LinkedList<RequestedTrack> addedTracks = new LinkedList<>();
final LinkedList<RequestedTrack> tracksToAdd = new LinkedList<>();
int count = 0;
for (final AudioTrack playlistTrack : playlist.getTracks()) {
if (!scheduler.isQueueFull()) {
if (count++ != 250) {
if (!scheduler.isQueued(playlistTrack) && !playlistTrack.getInfo().isStream) {
final RequestedTrack requestedTrack = new RequestedTrack(playlistTrack, requester);
scheduler.addToQueue(requestedTrack);
addedTracks.add(requestedTrack);
tracksToAdd.add(new RequestedTrack(playlistTrack, requester));
}
} else {
break;
}
}
if (addedTracks.size() == 0) {
if (tracksToAdd.size() == 0) {
response = new CommandResponse("x",
"Sorry " + this.requester.getAsMention()
+ ", but none of the tracks in that playlist could be added to the queue.")
@@ -162,9 +165,10 @@ public final class TrackLoadHandler implements AudioLoadResultHandler {
response.sendResponse(this.channel);
}
MainThread.scheduleImmediately(new TrackAdditionTask(guild, tracksToAdd));
response = new CommandResponse("notes",
this.requester.getAsMention() + " added the following tracks from a playlist to the queue:");
response.attachEmbed(TrackUtil.trackListInfoEmbed(addedTracks, false));
response.attachEmbed(TrackUtil.trackListInfoEmbed(tracksToAdd, false));
response.sendResponse(this.channel);
} else {
response = new CommandResponse("x",

View File

@@ -27,11 +27,13 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import dev.logal.logalbot.tasks.IdleDisconnectTask;
import dev.logal.logalbot.MainThread;
import dev.logal.logalbot.tasks.CloseAudioConnectionTask;
import dev.logal.logalbot.tasks.OpenAudioConnectionTask;
import dev.logal.logalbot.tasks.PlayNextTrackTask;
import dev.logal.logalbot.utils.AudioUtil;
import dev.logal.logalbot.utils.DataManager;
import dev.logal.logalbot.utils.PermissionManager;
import dev.logal.logalbot.utils.Scheduler;
import dev.logal.logalbot.utils.SkipTracker;
import dev.logal.logalbot.utils.VoiceChannelUtil;
import net.dv8tion.jda.core.entities.Guild;
@@ -46,7 +48,7 @@ public final class TrackScheduler extends AudioEventAdapter {
private final Guild guild;
private final LinkedList<RequestedTrack> queue = new LinkedList<>();
private boolean queueLocked = false;
private ScheduledFuture<?> idleLogoutTask;
private ScheduledFuture<?> closeAudioConnectionTask;
public TrackScheduler(final Guild guild) {
Checks.notNull(guild, "Guild");
@@ -71,12 +73,17 @@ public final class TrackScheduler extends AudioEventAdapter {
logger.info(user.getName() + " (" + user.getId() + ") added '" + track.getInfo().title + "' to the queue in "
+ this.guild.getName() + " (" + this.guild.getId() + ").");
if (!AudioUtil.isTrackLoaded(this.guild)) {
AudioUtil.openAudioConnection(VoiceChannelUtil.getVoiceChannelMemberIsConnectedTo(requester));
AudioUtil.playTrack(this.guild, requestedTrack);
} else {
this.queue.add(requestedTrack);
final VoiceChannel targetChannel = VoiceChannelUtil.getVoiceChannelMemberIsConnectedTo(requester);
if (!AudioUtil.isAudioConnectionOpen(this.guild)
|| targetChannel != AudioUtil.getVoiceChannelConnectedTo(this.guild)) {
MainThread.scheduleImmediately(
new OpenAudioConnectionTask(VoiceChannelUtil.getVoiceChannelMemberIsConnectedTo(requester)));
}
if (!AudioUtil.isTrackLoaded(this.guild) && this.queue.size() == 0) {
MainThread.scheduleImmediately(new PlayNextTrackTask(this.guild));
}
this.queue.add(requestedTrack);
}
public final void removeFromQueue(final int index) {
@@ -121,6 +128,10 @@ public final class TrackScheduler extends AudioEventAdapter {
Collections.shuffle(this.queue);
}
public final RequestedTrack popFromQueue() {
return this.queue.remove(0);
}
public final int occupiedSlotCount(Member member) {
Checks.notNull(member, "Member");
@@ -152,10 +163,10 @@ public final class TrackScheduler extends AudioEventAdapter {
logger.info("Track '" + track.getInfo().title + "' in " + this.guild.getName() + " (" + this.guild.getId()
+ ") has started.");
if (this.idleLogoutTask != null && !this.idleLogoutTask.isDone()) {
if (this.closeAudioConnectionTask != null && !this.closeAudioConnectionTask.isDone()) {
logger.info("A track has started in " + this.guild.getName() + " (" + this.guild.getId()
+ "). Cancelling scheduled disconnect.");
this.idleLogoutTask.cancel(true);
this.closeAudioConnectionTask.cancel(true);
}
SkipTracker.resetVotes(this.guild);
}
@@ -170,7 +181,7 @@ public final class TrackScheduler extends AudioEventAdapter {
logger.info("Track '" + track.getInfo().title + "' in " + this.guild.getName() + " (" + this.guild.getId()
+ ") has stopped.");
if ((endReason.mayStartNext || endReason == AudioTrackEndReason.STOPPED) && this.queue.size() >= 1) {
AudioUtil.playTrack(this.guild, this.queue.remove(0));
MainThread.scheduleImmediately(new PlayNextTrackTask(this.guild));
} else {
try {
AudioUtil.setVolume(this.guild, Integer.parseInt(DataManager.getGuildValue(guild, "defaultVolume")));
@@ -182,7 +193,8 @@ public final class TrackScheduler extends AudioEventAdapter {
final VoiceChannel currentChannel = AudioUtil.getVoiceChannelConnectedTo(this.guild);
logger.info("Disconnecting from " + currentChannel.getName() + " (" + currentChannel.getId() + ") in "
+ this.guild.getName() + " (" + this.guild.getId() + ") in 1 minute...");
this.idleLogoutTask = Scheduler.schedule(new IdleDisconnectTask(this.guild), 1, TimeUnit.MINUTES);
this.closeAudioConnectionTask = MainThread.scheduleLater(new CloseAudioConnectionTask(this.guild), 1,
TimeUnit.MINUTES);
}
SkipTracker.resetVotes(this.guild);
}

View File

@@ -21,10 +21,10 @@ import java.util.concurrent.TimeUnit;
import com.vdurmont.emoji.Emoji;
import com.vdurmont.emoji.EmojiManager;
import dev.logal.logalbot.MainThread;
import dev.logal.logalbot.tasks.MessageDeleteTask;
import dev.logal.logalbot.tasks.ReactionCallbackExpireTask;
import dev.logal.logalbot.utils.ReactionCallbackManager;
import dev.logal.logalbot.utils.Scheduler;
import net.dv8tion.jda.core.MessageBuilder;
import net.dv8tion.jda.core.entities.Member;
import net.dv8tion.jda.core.entities.Message;
@@ -106,9 +106,9 @@ public final class CommandResponse {
private final void handleResponseCreation(final Message message) {
if ((this.deletionDelay != 0) && (this.deletionDelayUnit != null)) {
Scheduler.schedule(new MessageDeleteTask(message), this.deletionDelay, this.deletionDelayUnit);
MainThread.scheduleLater(new MessageDeleteTask(message), this.deletionDelay, this.deletionDelayUnit);
} else if ((this.expireDelay != 0) && (this.expireDelayUnit != null)) {
Scheduler.schedule(new ReactionCallbackExpireTask(message), this.expireDelay, this.expireDelayUnit);
MainThread.scheduleLater(new ReactionCallbackExpireTask(message), this.expireDelay, this.expireDelayUnit);
}
for (final Map.Entry<Emoji, ReactionCallback> callback : callbacks.entrySet()) {

View File

@@ -17,11 +17,12 @@ package dev.logal.logalbot.commands.audio;
import java.util.List;
import java.util.concurrent.TimeUnit;
import dev.logal.logalbot.MainThread;
import dev.logal.logalbot.audio.RequestedTrack;
import dev.logal.logalbot.commands.Command;
import dev.logal.logalbot.commands.CommandResponse;
import dev.logal.logalbot.tasks.CommandExecutionTask;
import dev.logal.logalbot.utils.AudioUtil;
import dev.logal.logalbot.utils.CommandManager;
import dev.logal.logalbot.utils.ReactionCallbackManager;
import dev.logal.logalbot.utils.TrackUtil;
import net.dv8tion.jda.core.entities.Guild;
@@ -56,14 +57,16 @@ public final class Queue implements Command {
if (page != 1) {
response.addReactionCallback("arrow_left", (reactor, message) -> {
ReactionCallbackManager.unregisterMessage(message, true);
CommandManager.executeCommand(("queue " + (page - 1)).split(" "), reactor, channel);
MainThread.scheduleImmediately(
new CommandExecutionTask(("queue " + (page - 1)).split(" "), reactor, channel));
});
}
if (TrackUtil.doesGreaterPageExist(queue, page)) {
response.addReactionCallback("arrow_right", (reactor, message) -> {
ReactionCallbackManager.unregisterMessage(message, true);
CommandManager.executeCommand(("queue " + (page + 1)).split(" "), reactor, channel);
MainThread.scheduleImmediately(
new CommandExecutionTask(("queue " + (page + 1)).split(" "), reactor, channel));
});
}

View File

@@ -16,12 +16,13 @@ package dev.logal.logalbot.commands.audio;
import java.util.concurrent.TimeUnit;
import dev.logal.logalbot.MainThread;
import dev.logal.logalbot.audio.RequestedTrack;
import dev.logal.logalbot.audio.TrackScheduler;
import dev.logal.logalbot.commands.Command;
import dev.logal.logalbot.commands.CommandResponse;
import dev.logal.logalbot.tasks.CommandExecutionTask;
import dev.logal.logalbot.utils.AudioUtil;
import dev.logal.logalbot.utils.CommandManager;
import dev.logal.logalbot.utils.ReactionCallbackManager;
import dev.logal.logalbot.utils.StringUtil;
import dev.logal.logalbot.utils.TrackUtil;
@@ -69,7 +70,8 @@ public final class Remove implements Command {
response.addReactionCallback(StringUtil.intToKeycapEmoji(trackNumber).getAliases().get(0),
(reactor, message) -> {
ReactionCallbackManager.unregisterMessage(message, true);
CommandManager.executeCommand(("remove " + trackNumber).split(" "), reactor, channel);
MainThread.scheduleImmediately(
new CommandExecutionTask(("remove " + trackNumber).split(" "), reactor, channel));
});
}

View File

@@ -14,7 +14,8 @@ package dev.logal.logalbot.events;
// See the License for the specific language governing permissions and
// limitations under the License.
import dev.logal.logalbot.utils.ReactionCallbackManager;
import dev.logal.logalbot.MainThread;
import dev.logal.logalbot.tasks.ReactionCallbackExecutionTask;
import net.dv8tion.jda.core.events.message.guild.react.GuildMessageReactionAddEvent;
import net.dv8tion.jda.core.hooks.ListenerAdapter;
import net.dv8tion.jda.core.utils.Checks;
@@ -25,8 +26,8 @@ public final class GuildMessageReactionAdd extends ListenerAdapter {
Checks.notNull(event, "Event");
if (!event.getUser().equals(event.getJDA().getSelfUser())) {
ReactionCallbackManager.executeCallback(event.getMessageIdLong(), event.getChannel(), event.getMember(),
event.getReactionEmote().getName());
MainThread.scheduleImmediately(new ReactionCallbackExecutionTask(event.getMessageIdLong(),
event.getChannel(), event.getMember(), event.getReactionEmote().getName()));
}
}
}

View File

@@ -17,7 +17,8 @@ package dev.logal.logalbot.events;
import java.util.Arrays;
import java.util.List;
import dev.logal.logalbot.utils.CommandManager;
import dev.logal.logalbot.MainThread;
import dev.logal.logalbot.tasks.CommandExecutionTask;
import dev.logal.logalbot.utils.DataManager;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.Guild;
@@ -55,7 +56,7 @@ public final class GuildMessageReceived extends ListenerAdapter {
if (self.hasPermission(channel, Permission.MESSAGE_MANAGE)) {
message.delete().reason("LogalBot Command Execution").queue();
}
CommandManager.executeCommand(command, author, channel);
MainThread.scheduleImmediately(new CommandExecutionTask(command, author, channel));
}
} else {
final String commandCharacter = DataManager.getGuildValue(guild, "commandCharacter");
@@ -70,7 +71,7 @@ public final class GuildMessageReceived extends ListenerAdapter {
if (self.hasPermission(channel, Permission.MESSAGE_MANAGE)) {
message.delete().reason("LogalBot Command Execution").queue();
}
CommandManager.executeCommand(command, author, channel);
MainThread.scheduleImmediately(new CommandExecutionTask(command, author, channel));
}
}
}

View File

@@ -19,6 +19,8 @@ import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import dev.logal.logalbot.MainThread;
import dev.logal.logalbot.tasks.ResetAudioPlayerTask;
import dev.logal.logalbot.utils.AudioUtil;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.entities.Member;
@@ -55,10 +57,7 @@ public final class GuildVoiceLeave extends ListenerAdapter {
if (members.size() == 1 && members.get(0).getUser().equals(event.getJDA().getSelfUser())) {
logger.info("All listeners left " + leftChannel.getName() + " (" + leftChannel.getId() + ") in "
+ guild.getName() + " (" + guild.getId() + ").");
AudioUtil.getTrackScheduler(guild).clearQueue();
if (AudioUtil.isTrackLoaded(guild)) {
AudioUtil.stopTrack(guild);
}
MainThread.scheduleImmediately(new ResetAudioPlayerTask(guild));
}
}
}

View File

@@ -19,6 +19,8 @@ import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import dev.logal.logalbot.MainThread;
import dev.logal.logalbot.tasks.ResetAudioPlayerTask;
import dev.logal.logalbot.utils.AudioUtil;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.entities.Member;
@@ -55,10 +57,7 @@ public final class GuildVoiceMove extends ListenerAdapter {
if (members.size() == 1 && members.get(0).getUser().equals(event.getJDA().getSelfUser())) {
logger.info("All listeners left " + leftChannel.getName() + " (" + leftChannel.getId() + ") in "
+ guild.getName() + " (" + guild.getId() + ").");
AudioUtil.getTrackScheduler(guild).clearQueue();
if (AudioUtil.isTrackLoaded(guild)) {
AudioUtil.stopTrack(guild);
}
MainThread.scheduleImmediately(new ResetAudioPlayerTask(guild));
}
}
}

View File

@@ -18,10 +18,10 @@ import dev.logal.logalbot.utils.AudioUtil;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.utils.Checks;
public final class IdleDisconnectTask implements Runnable {
public final class CloseAudioConnectionTask implements Runnable {
private final Guild guild;
public IdleDisconnectTask(final Guild guild) {
public CloseAudioConnectionTask(final Guild guild) {
Checks.notNull(guild, "Guild");
this.guild = guild;

View File

@@ -0,0 +1,41 @@
package dev.logal.logalbot.tasks;
// Copyright 2019 Logan Fick
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import dev.logal.logalbot.utils.CommandManager;
import net.dv8tion.jda.core.entities.Member;
import net.dv8tion.jda.core.entities.TextChannel;
import net.dv8tion.jda.core.utils.Checks;
public final class CommandExecutionTask implements Runnable {
private final String[] command;
private final Member executor;
private final TextChannel channel;
public CommandExecutionTask(final String[] command, final Member executor, final TextChannel channel) {
Checks.noneNull(command, "Command");
Checks.notNull(executor, "Executor");
Checks.notNull(channel, "Channel");
this.command = command;
this.executor = executor;
this.channel = channel;
}
@Override
public final void run() {
CommandManager.executeCommand(this.command, this.executor, this.channel);
}
}

View File

@@ -30,6 +30,5 @@ public final class MessageDeleteTask implements Runnable {
@Override
public final void run() {
ReactionCallbackManager.unregisterMessage(messageToDelete, true);
messageToDelete.delete().queue();
}
}

View File

@@ -0,0 +1,34 @@
package dev.logal.logalbot.tasks;
// Copyright 2019 Logan Fick
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import dev.logal.logalbot.utils.AudioUtil;
import net.dv8tion.jda.core.entities.VoiceChannel;
import net.dv8tion.jda.core.utils.Checks;
public final class OpenAudioConnectionTask implements Runnable {
private final VoiceChannel channel;
public OpenAudioConnectionTask(final VoiceChannel channel) {
Checks.notNull(channel, "Channel");
this.channel = channel;
}
@Override
public void run() {
AudioUtil.openAudioConnection(channel);
}
}

View File

@@ -0,0 +1,34 @@
package dev.logal.logalbot.tasks;
// Copyright 2019 Logan Fick
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import dev.logal.logalbot.utils.AudioUtil;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.utils.Checks;
public final class PlayNextTrackTask implements Runnable {
private final Guild guild;
public PlayNextTrackTask(final Guild guild) {
Checks.notNull(guild, "Guild");
this.guild = guild;
}
@Override
public void run() {
AudioUtil.playNextTrack(this.guild);
}
}

View File

@@ -0,0 +1,45 @@
package dev.logal.logalbot.tasks;
// Copyright 2019 Logan Fick
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import dev.logal.logalbot.utils.ReactionCallbackManager;
import net.dv8tion.jda.core.entities.Member;
import net.dv8tion.jda.core.entities.TextChannel;
import net.dv8tion.jda.core.utils.Checks;
public final class ReactionCallbackExecutionTask implements Runnable {
private final long messageID;
private final TextChannel channel;
private final Member executor;
private final String emoji;
public ReactionCallbackExecutionTask(final long messageID, final TextChannel channel, final Member executor,
final String emoji) {
Checks.notNegative(messageID, "Message ID");
Checks.notNull(channel, "Channel");
Checks.notNull(executor, "Executor");
Checks.notEmpty(emoji, "Emoji");
this.messageID = messageID;
this.channel = channel;
this.executor = executor;
this.emoji = emoji;
}
@Override
public void run() {
ReactionCallbackManager.executeCallback(this.messageID, this.channel, this.executor, this.emoji);
}
}

View File

@@ -0,0 +1,35 @@
package dev.logal.logalbot.tasks;
// Copyright 2019 Logan Fick
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import dev.logal.logalbot.utils.AudioUtil;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.utils.Checks;
public final class ResetAudioPlayerTask implements Runnable {
private final Guild guild;
public ResetAudioPlayerTask(final Guild guild) {
Checks.notNull(guild, "Guild");
this.guild = guild;
}
@Override
public void run() {
AudioUtil.getTrackScheduler(guild).clearQueue();
AudioUtil.stopTrack(guild);
}
}

View File

@@ -0,0 +1,54 @@
package dev.logal.logalbot.tasks;
// Copyright 2019 Logan Fick
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import java.util.LinkedList;
import java.util.List;
import dev.logal.logalbot.audio.RequestedTrack;
import dev.logal.logalbot.audio.TrackScheduler;
import dev.logal.logalbot.utils.AudioUtil;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.utils.Checks;
public final class TrackAdditionTask implements Runnable {
private final Guild guild;
private final LinkedList<RequestedTrack> tracks;
public TrackAdditionTask(final Guild guild, final RequestedTrack track) {
Checks.notNull(guild, "Guild");
Checks.notNull(track, "Track");
this.guild = guild;
tracks = new LinkedList<RequestedTrack>();
tracks.add(track);
}
public TrackAdditionTask(final Guild guild, final List<RequestedTrack> tracks) {
Checks.notNull(guild, "Guild");
Checks.noneNull(tracks, "Tracks");
this.guild = guild;
this.tracks = (LinkedList<RequestedTrack>) tracks;
}
@Override
public final void run() {
final TrackScheduler scheduler = AudioUtil.getTrackScheduler(this.guild);
for (final RequestedTrack track : this.tracks) {
scheduler.addToQueue(track);
}
}
}

View File

@@ -106,6 +106,15 @@ public final class AudioUtil {
loadedTracks.put(guild.getIdLong(), track);
}
public static final void playNextTrack(final Guild guild) {
Checks.notNull(guild, "Guild");
final RequestedTrack track = schedulers.get(guild.getIdLong()).popFromQueue();
if (track != null) {
playTrack(guild, track);
}
}
public static final void stopTrack(final Guild guild) {
Checks.notNull(guild, "Guild");

View File

@@ -1,48 +0,0 @@
package dev.logal.logalbot.utils;
// Copyright 2019 Logan Fick
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import net.dv8tion.jda.core.utils.Checks;
public final class Scheduler {
private static final ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);
private Scheduler() {
// Static access only.
}
public static final ScheduledFuture<?> schedule(final Runnable runnable, final long delay, final TimeUnit unit) {
Checks.notNull(runnable, "Runnable");
Checks.notNegative(delay, "Delay");
Checks.notNull(unit, "Unit");
return pool.schedule(runnable, delay, unit);
}
public static final ScheduledFuture<?> scheduleRepeating(final Runnable runnable, final long initialDelay,
final long period, final TimeUnit unit) {
Checks.notNull(runnable, "Runnable");
Checks.notNegative(initialDelay, "Initial delay");
Checks.notNegative(period, "Period");
Checks.notNull(unit, "Unit");
return pool.scheduleAtFixedRate(runnable, initialDelay, period, unit);
}
}