Made LogalBot open source.
This commit is contained in:
141
src/main/java/dev/logal/logalbot/Main.java
Normal file
141
src/main/java/dev/logal/logalbot/Main.java
Normal file
@@ -0,0 +1,141 @@
|
||||
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 javax.security.auth.login.LoginException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import dev.logal.logalbot.commands.administration.*;
|
||||
import dev.logal.logalbot.commands.audio.*;
|
||||
import dev.logal.logalbot.commands.fun.*;
|
||||
import dev.logal.logalbot.commands.general.*;
|
||||
import dev.logal.logalbot.events.*;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.CommandManager;
|
||||
import dev.logal.logalbot.utils.DataManager;
|
||||
import net.dv8tion.jda.core.AccountType;
|
||||
import net.dv8tion.jda.core.JDA;
|
||||
import net.dv8tion.jda.core.JDABuilder;
|
||||
|
||||
public final class Main {
|
||||
private static final Logger logger = LoggerFactory.getLogger(Main.class);
|
||||
|
||||
private static final String token = System.getenv("TOKEN");
|
||||
private static JDA jda;
|
||||
|
||||
private Main() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final void main(final String[] arguments) {
|
||||
logger.info("Beginning setup of LogalBot...");
|
||||
|
||||
logger.info("Verifying connection to Redis...");
|
||||
try {
|
||||
DataManager.verifyConnection();
|
||||
} catch (final Throwable exception) {
|
||||
logger.error("An error occurred while attempting to verify the connection to Redis!", exception);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
logger.info("Running any needed schema migrations...");
|
||||
try {
|
||||
DataManager.runMigrations();
|
||||
} catch (final Throwable exception) {
|
||||
logger.error("An error occurred while attempting to migrate the database!", exception);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
logger.info("Attempting to log into Discord...");
|
||||
try {
|
||||
final JDABuilder builder = new JDABuilder(AccountType.BOT);
|
||||
builder.setAutoReconnect(true);
|
||||
builder.setAudioEnabled(true);
|
||||
builder.setToken(token);
|
||||
builder.addEventListener(new GuildReady());
|
||||
jda = builder.build().awaitReady();
|
||||
} catch (final LoginException exception) {
|
||||
logger.error("The token specified is not valid.");
|
||||
System.exit(1);
|
||||
} catch (final Throwable exception) {
|
||||
logger.error("An error occurred while attempting to set up JDA!", exception);
|
||||
System.exit(1);
|
||||
}
|
||||
logger.info("Successfully logged into Discord as bot user '" + jda.getSelfUser().getName() + "'.");
|
||||
|
||||
logger.info("Initializing...");
|
||||
AudioUtil.initializePlayerManager();
|
||||
|
||||
jda.addEventListener(new GuildVoiceLeave());
|
||||
jda.addEventListener(new GuildVoiceMove());
|
||||
jda.addEventListener(new GuildMessageReactionAdd());
|
||||
|
||||
// General Commands
|
||||
CommandManager.registerCommand("about", new About(), false);
|
||||
CommandManager.registerCommand("help", new Help(), false);
|
||||
|
||||
// Fun Commands
|
||||
CommandManager.registerCommand("8ball", new EightBall(), false);
|
||||
|
||||
// Audio Commands
|
||||
CommandManager.registerCommand("forceskip", new ForceSkip(), true);
|
||||
CommandManager.registerCommandAlias("fs", "forceskip");
|
||||
CommandManager.registerCommandAlias("fskip", "forceskip");
|
||||
CommandManager.registerCommand("lock", new Lock(), true);
|
||||
CommandManager.registerCommandAlias("l", "lock");
|
||||
CommandManager.registerCommand("nowplaying", new NowPlaying(), false);
|
||||
CommandManager.registerCommandAlias("np", "nowplaying");
|
||||
CommandManager.registerCommand("pause", new Pause(), true);
|
||||
CommandManager.registerCommand("play", new Play(), false);
|
||||
CommandManager.registerCommandAlias("p", "play");
|
||||
CommandManager.registerCommandAlias("pl", "play");
|
||||
CommandManager.registerCommandAlias("add", "play");
|
||||
CommandManager.registerCommandAlias("a", "play");
|
||||
CommandManager.registerCommand("queue", new Queue(), false);
|
||||
CommandManager.registerCommandAlias("q", "queue");
|
||||
CommandManager.registerCommand("remove", new Remove(), true);
|
||||
CommandManager.registerCommandAlias("r", "remove");
|
||||
CommandManager.registerCommandAlias("x", "remove");
|
||||
CommandManager.registerCommandAlias("rem", "remove");
|
||||
CommandManager.registerCommandAlias("rm", "remove");
|
||||
CommandManager.registerCommand("reset", new Reset(), true);
|
||||
CommandManager.registerCommandAlias("rst", "reset");
|
||||
CommandManager.registerCommand("skip", new Skip(), false);
|
||||
CommandManager.registerCommandAlias("s", "skip");
|
||||
CommandManager.registerCommand("volume", new Volume(), true);
|
||||
CommandManager.registerCommandAlias("v", "volume");
|
||||
CommandManager.registerCommandAlias("vol", "volume");
|
||||
CommandManager.registerCommand("shuffle", new Shuffle(), true);
|
||||
CommandManager.registerCommandAlias("shuf", "shuffle");
|
||||
CommandManager.registerCommandAlias("shuff", "shuffle");
|
||||
CommandManager.registerCommandAlias("shfl", "shuffle");
|
||||
|
||||
// Administration Commands
|
||||
CommandManager.registerCommand("whitelist", new Whitelist(), true);
|
||||
CommandManager.registerCommandAlias("wl", "whitelist");
|
||||
CommandManager.registerCommand("settings", new Settings(), true);
|
||||
CommandManager.registerCommandAlias("set", "settings");
|
||||
CommandManager.registerCommandAlias("setting", "settings");
|
||||
CommandManager.registerCommandAlias("configure", "settings");
|
||||
CommandManager.registerCommandAlias("config", "settings");
|
||||
CommandManager.registerCommandAlias("conf", "settings");
|
||||
|
||||
logger.info("Everything seems to be ready! Enabling command listener...");
|
||||
jda.addEventListener(new GuildMessageReceived());
|
||||
logger.info("Initialization complete!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package dev.logal.logalbot.audio;
|
||||
|
||||
// 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 com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
|
||||
import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame;
|
||||
|
||||
import net.dv8tion.jda.core.audio.AudioSendHandler;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class AudioPlayerSendHandler implements AudioSendHandler {
|
||||
private final AudioPlayer audioPlayer;
|
||||
private AudioFrame lastFrame;
|
||||
|
||||
public AudioPlayerSendHandler(final AudioPlayer audioPlayer) {
|
||||
Checks.notNull(audioPlayer, "Audio Player");
|
||||
|
||||
this.audioPlayer = audioPlayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean canProvide() {
|
||||
lastFrame = audioPlayer.provide();
|
||||
return lastFrame != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final byte[] provide20MsAudio() {
|
||||
return lastFrame.getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isOpus() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
201
src/main/java/dev/logal/logalbot/audio/TrackLoadHandler.java
Normal file
201
src/main/java/dev/logal/logalbot/audio/TrackLoadHandler.java
Normal file
@@ -0,0 +1,201 @@
|
||||
package dev.logal.logalbot.audio;
|
||||
|
||||
// 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.ArrayList;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
|
||||
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.PermissionManager;
|
||||
import dev.logal.logalbot.utils.TrackUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class TrackLoadHandler implements AudioLoadResultHandler {
|
||||
private final Logger logger = LoggerFactory.getLogger(TrackLoadHandler.class);
|
||||
|
||||
private final Member requester;
|
||||
private final TextChannel channel;
|
||||
|
||||
public TrackLoadHandler(final Member requester, final TextChannel channel) {
|
||||
Checks.notNull(requester, "Requester");
|
||||
Checks.notNull(channel, "Channel");
|
||||
|
||||
this.requester = requester;
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void trackLoaded(final AudioTrack track) {
|
||||
Checks.notNull(track, "Track");
|
||||
|
||||
final CommandResponse response;
|
||||
final TrackScheduler scheduler = AudioUtil.getTrackScheduler(this.channel.getGuild());
|
||||
|
||||
final AudioTrackInfo info = track.getInfo();
|
||||
if (info.isStream) {
|
||||
response = new CommandResponse("no_entry_sign",
|
||||
"Sorry " + this.requester.getAsMention() + ", but streams cannot be added to the queue.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
response.sendResponse(this.channel);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((info.length >= 60000 && info.length <= 900000) || PermissionManager.isWhitelisted(this.requester)) {
|
||||
response = new CommandResponse("no_entry_sign",
|
||||
"Sorry " + this.requester.getAsMention()
|
||||
+ ", but you can only add tracks between 1 and 15 minutes in length.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
response.sendResponse(this.channel);
|
||||
return;
|
||||
}
|
||||
|
||||
if (scheduler.isQueued(track)) {
|
||||
response = new CommandResponse("no_entry_sign",
|
||||
"Sorry " + this.requester.getAsMention() + ", but that track is already queued.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
response.sendResponse(this.channel);
|
||||
return;
|
||||
}
|
||||
|
||||
scheduler.addToQueue(track, requester);
|
||||
response = new CommandResponse("notes",
|
||||
this.requester.getAsMention() + " added the following track to the queue:");
|
||||
response.attachEmbed(TrackUtil.generateTrackInfoEmbed(track));
|
||||
response.sendResponse(this.channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void playlistLoaded(final AudioPlaylist playlist) {
|
||||
Checks.notNull(playlist, "Playlist");
|
||||
|
||||
CommandResponse response;
|
||||
final TrackScheduler scheduler = AudioUtil.getTrackScheduler(this.channel.getGuild());
|
||||
|
||||
final AudioTrack selectedTrack = playlist.getSelectedTrack();
|
||||
AudioTrack track = null;
|
||||
if (!playlist.isSearchResult() && selectedTrack != null) {
|
||||
track = selectedTrack;
|
||||
} else if (playlist.isSearchResult()) {
|
||||
track = playlist.getTracks().get(0);
|
||||
}
|
||||
|
||||
if (track != null) {
|
||||
if (scheduler.isQueued(track)) {
|
||||
response = new CommandResponse("no_entry_sign",
|
||||
"Sorry " + this.requester.getAsMention() + ", but that track is already queued.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
response.sendResponse(this.channel);
|
||||
return;
|
||||
}
|
||||
|
||||
final AudioTrackInfo info = track.getInfo();
|
||||
if (info.isStream) {
|
||||
response = new CommandResponse("no_entry_sign",
|
||||
"Sorry " + this.requester.getAsMention() + ", but streams cannot be added to the queue.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
response.sendResponse(this.channel);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((info.length >= 60000 && info.length <= 900000) || PermissionManager.isWhitelisted(this.requester)) {
|
||||
scheduler.addToQueue(track, this.requester);
|
||||
response = new CommandResponse("notes",
|
||||
this.requester.getAsMention() + " added the following track to the queue:");
|
||||
response.attachEmbed(TrackUtil.generateTrackInfoEmbed(track));
|
||||
response.sendResponse(this.channel);
|
||||
} else {
|
||||
response = new CommandResponse("no_entry_sign", "Sorry " + this.requester.getAsMention()
|
||||
+ ", but you are not allowed to add tracks less than 1 minute or greater than 15 minutes in length.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
response.sendResponse(this.channel);
|
||||
}
|
||||
} else {
|
||||
if (PermissionManager.isWhitelisted(this.requester)) {
|
||||
final ArrayList<AudioTrack> addedTracks = new ArrayList<>();
|
||||
for (final AudioTrack playlistTrack : playlist.getTracks()) {
|
||||
if (!scheduler.isQueueFull()) {
|
||||
if (!scheduler.isQueued(playlistTrack) && !playlistTrack.getInfo().isStream) {
|
||||
scheduler.addToQueue(playlistTrack, this.requester);
|
||||
addedTracks.add(playlistTrack);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (addedTracks.size() == 0) {
|
||||
response = new CommandResponse("no_entry_sign",
|
||||
"Sorry " + this.requester.getAsMention()
|
||||
+ ", but none of the tracks in that playlist could be added.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
response.sendResponse(this.channel);
|
||||
}
|
||||
|
||||
response = new CommandResponse("notes",
|
||||
this.requester.getAsMention() + " added the following tracks to the queue:");
|
||||
response.attachEmbed(TrackUtil.generateTrackListInfoEmbed(addedTracks, false));
|
||||
response.sendResponse(this.channel);
|
||||
} else {
|
||||
response = new CommandResponse("no_entry_sign",
|
||||
"Sorry " + this.requester.getAsMention()
|
||||
+ ", but you are not allowed to add playlists to the queue.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
response.sendResponse(this.channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void noMatches() {
|
||||
final CommandResponse response = new CommandResponse("map",
|
||||
"Sorry " + this.requester.getAsMention() + ", but I was not able to find that track.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
response.sendResponse(this.channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void loadFailed(final FriendlyException exception) {
|
||||
Checks.notNull(exception, "Exception");
|
||||
|
||||
final CommandResponse response;
|
||||
if (exception.getMessage().equals("Unknown file format.")) {
|
||||
response = new CommandResponse("question",
|
||||
"Sorry " + this.requester.getAsMention() + ", but I do not recognize the format of that track.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
} else {
|
||||
final Guild guild = this.channel.getGuild();
|
||||
logger.error("An error occurred for " + guild.getName() + " (" + guild.getId()
|
||||
+ ") while trying to load a track!", exception);
|
||||
response = new CommandResponse("sos",
|
||||
"Sorry " + this.requester.getAsMention()
|
||||
+ ", but an error occurred while trying to get that track!").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
response.sendResponse(this.channel);
|
||||
}
|
||||
}
|
||||
176
src/main/java/dev/logal/logalbot/audio/TrackScheduler.java
Normal file
176
src/main/java/dev/logal/logalbot/audio/TrackScheduler.java
Normal file
@@ -0,0 +1,176 @@
|
||||
package dev.logal.logalbot.audio;
|
||||
|
||||
// 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.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
|
||||
import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
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.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;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.User;
|
||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class TrackScheduler extends AudioEventAdapter {
|
||||
private static final Logger logger = LoggerFactory.getLogger(TrackScheduler.class);
|
||||
|
||||
private final Guild guild;
|
||||
private final ArrayList<AudioTrack> queue = new ArrayList<>(250);
|
||||
private boolean queueLocked = false;
|
||||
private ScheduledFuture<?> idleLogoutTask;
|
||||
|
||||
public TrackScheduler(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
this.guild = guild;
|
||||
}
|
||||
|
||||
public final void addToQueue(final AudioTrack track, final Member requester) {
|
||||
Checks.notNull(track, "Track");
|
||||
Checks.notNull(requester, "Requester");
|
||||
|
||||
if (this.queueLocked && !PermissionManager.isWhitelisted(requester)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isQueueFull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final User user = requester.getUser();
|
||||
logger.info(user.getName() + " (" + user.getId() + ") added '" + track.getInfo().title + "' to the queue in "
|
||||
+ this.guild.getName() + " (" + this.guild.getId() + ").");
|
||||
this.queue.add(track);
|
||||
if (!AudioUtil.isTrackLoaded(this.guild)) {
|
||||
AudioUtil.openAudioConnection(VoiceChannelUtil.getVoiceChannelMemberIsConnectedTo(requester));
|
||||
AudioUtil.playTrack(this.guild, this.queue.remove(0));
|
||||
}
|
||||
}
|
||||
|
||||
public final void removeFromQueue(final int index) {
|
||||
Checks.notNull(index, "Index");
|
||||
|
||||
logger.info("Track '" + queue.remove(index).getInfo().title + "' has been removed from the queue in "
|
||||
+ this.guild.getName() + " (" + this.guild.getId() + ").");
|
||||
}
|
||||
|
||||
public final boolean isQueued(final AudioTrack track) {
|
||||
Checks.notNull(track, "Track");
|
||||
|
||||
for (final AudioTrack queuedTrack : queue) {
|
||||
if (track.getInfo().identifier.equals(queuedTrack.getInfo().identifier)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public final boolean isQueueFull() {
|
||||
return this.queue.size() >= 250;
|
||||
}
|
||||
|
||||
public final boolean isQueueEmpty() {
|
||||
return this.queue.isEmpty();
|
||||
}
|
||||
|
||||
public final boolean isQueueLocked() {
|
||||
return this.queueLocked;
|
||||
}
|
||||
|
||||
public final void setQueueLocked(final boolean locked) {
|
||||
Checks.notNull(locked, "Locked");
|
||||
|
||||
this.queueLocked = locked;
|
||||
}
|
||||
|
||||
public final void clearQueue() {
|
||||
this.queue.clear();
|
||||
}
|
||||
|
||||
public final void shuffleQueue() {
|
||||
Collections.shuffle(this.queue);
|
||||
}
|
||||
|
||||
public final ArrayList<AudioTrack> getQueue() {
|
||||
return this.queue;
|
||||
}
|
||||
|
||||
public final void skipCurrentTrack() {
|
||||
if (AudioUtil.isTrackLoaded(this.guild)) {
|
||||
logger.info("Track '" + AudioUtil.getLoadedTrack(this.guild).getInfo().title + "' in "
|
||||
+ this.guild.getName() + " (" + this.guild.getId() + ") been skipped.");
|
||||
AudioUtil.stopTrack(this.guild);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onTrackStart(final AudioPlayer player, final AudioTrack track) {
|
||||
Checks.notNull(player, "Player");
|
||||
Checks.notNull(track, "Track");
|
||||
|
||||
logger.info("Track '" + track.getInfo().title + "' in " + this.guild.getName() + " (" + this.guild.getId()
|
||||
+ ") has started.");
|
||||
if (this.idleLogoutTask != null && !this.idleLogoutTask.isDone()) {
|
||||
logger.info("A track has started in " + this.guild.getName() + " (" + this.guild.getId()
|
||||
+ "). Cancelling scheduled disconnect.");
|
||||
this.idleLogoutTask.cancel(true);
|
||||
}
|
||||
SkipTracker.resetVotes(this.guild);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onTrackEnd(final AudioPlayer player, final AudioTrack track,
|
||||
final AudioTrackEndReason endReason) {
|
||||
Checks.notNull(player, "Player");
|
||||
Checks.notNull(track, "Track");
|
||||
Checks.notNull(endReason, "End reason");
|
||||
|
||||
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));
|
||||
} else {
|
||||
try {
|
||||
AudioUtil.setVolume(this.guild, Integer.parseInt(DataManager.getGuildValue(guild, "defaultVolume")));
|
||||
} catch (final NumberFormatException exception) {
|
||||
AudioUtil.setVolume(this.guild, 10);
|
||||
}
|
||||
this.queueLocked = false;
|
||||
AudioUtil.setPausedState(this.guild, false);
|
||||
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);
|
||||
}
|
||||
SkipTracker.resetVotes(this.guild);
|
||||
}
|
||||
}
|
||||
22
src/main/java/dev/logal/logalbot/commands/Command.java
Normal file
22
src/main/java/dev/logal/logalbot/commands/Command.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package dev.logal.logalbot.commands;
|
||||
|
||||
// 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 net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public interface Command {
|
||||
CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel);
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package dev.logal.logalbot.commands;
|
||||
|
||||
// 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.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.vdurmont.emoji.Emoji;
|
||||
import com.vdurmont.emoji.EmojiManager;
|
||||
|
||||
import dev.logal.logalbot.tasks.MessageDeleteTask;
|
||||
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;
|
||||
import net.dv8tion.jda.core.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
import net.dv8tion.jda.core.entities.User;
|
||||
|
||||
public final class CommandResponse {
|
||||
private final Emoji emoji;
|
||||
private final String response;
|
||||
private final LinkedHashMap<Emoji, ReactionCallback> callbacks = new LinkedHashMap<>();
|
||||
private MessageEmbed responseEmbed;
|
||||
private User callbacksTarget;
|
||||
|
||||
private long deletionDelay = 0;
|
||||
private TimeUnit deletionDelayUnit;
|
||||
|
||||
public CommandResponse(final String emoji, final String response) {
|
||||
this.emoji = EmojiManager.getForAlias(emoji);
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
public final CommandResponse attachEmbed(final MessageEmbed embed) {
|
||||
this.responseEmbed = embed;
|
||||
return this;
|
||||
}
|
||||
|
||||
public final CommandResponse setDeletionDelay(final long delay, final TimeUnit unit) {
|
||||
this.deletionDelay = delay;
|
||||
this.deletionDelayUnit = unit;
|
||||
return this;
|
||||
}
|
||||
|
||||
public final CommandResponse addReactionCallback(final Emoji emoji, final ReactionCallback callback) {
|
||||
this.callbacks.put(emoji, callback);
|
||||
return this;
|
||||
}
|
||||
|
||||
public final CommandResponse setReactionCallbackTarget(final Member member) {
|
||||
this.callbacksTarget = member.getUser();
|
||||
return this;
|
||||
}
|
||||
|
||||
public final void sendResponse(final TextChannel channel) {
|
||||
final MessageBuilder builder = new MessageBuilder();
|
||||
builder.setContent(this.emoji.getUnicode() + " " + this.response);
|
||||
|
||||
if (this.responseEmbed != null) {
|
||||
builder.setEmbed(this.responseEmbed);
|
||||
}
|
||||
|
||||
channel.sendMessage(builder.build()).queue(this::handleResponseCreation);
|
||||
}
|
||||
|
||||
private final void handleResponseCreation(final Message message) {
|
||||
if ((this.deletionDelay != 0) && (this.deletionDelayUnit != null)) {
|
||||
Scheduler.schedule(new MessageDeleteTask(message), this.deletionDelay, this.deletionDelayUnit);
|
||||
}
|
||||
|
||||
for (final Map.Entry<Emoji, ReactionCallback> callback : callbacks.entrySet()) {
|
||||
ReactionCallbackManager.registerCallback(message, callback.getKey(), callback.getValue());
|
||||
ReactionCallbackManager.setCallbackTarget(this.callbacksTarget, message);
|
||||
message.addReaction(callback.getKey().getUnicode()).queue();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.logal.logalbot.commands;
|
||||
|
||||
// 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 net.dv8tion.jda.core.entities.Member;
|
||||
|
||||
public interface ReactionCallback {
|
||||
void run(final Member reactor, final long messageID);
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package dev.logal.logalbot.commands.administration;
|
||||
|
||||
// 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.TimeUnit;
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.DataManager;
|
||||
import dev.logal.logalbot.utils.StringUtil;
|
||||
import net.dv8tion.jda.core.EmbedBuilder;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Settings implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = executor.getGuild();
|
||||
|
||||
if (arguments.length == 0) {
|
||||
final CommandResponse response = new CommandResponse("tools",
|
||||
executor.getAsMention() + ", these are the current settings for this guild:");
|
||||
final EmbedBuilder builder = new EmbedBuilder();
|
||||
builder.setTitle("**Current Settings for " + StringUtil.sanitize(guild.getName()) + "**");
|
||||
|
||||
final String commandCharacter = DataManager.getGuildValue(guild, "commandCharacter");
|
||||
if (commandCharacter == null) {
|
||||
builder.addField("Command Character", "Not Set", true);
|
||||
} else {
|
||||
builder.addField("Command Character", commandCharacter, true);
|
||||
}
|
||||
|
||||
final String defaultVolume = DataManager.getGuildValue(guild, "defaultVolume");
|
||||
if (defaultVolume == null) {
|
||||
builder.addField("Default Volume", "10%", true);
|
||||
} else {
|
||||
builder.addField("Default Volume", defaultVolume + "%", true);
|
||||
}
|
||||
response.attachEmbed(builder.build());
|
||||
return response;
|
||||
}
|
||||
|
||||
if (arguments[0].equalsIgnoreCase("commandcharacter") || arguments[0].equalsIgnoreCase("cmdchar")) {
|
||||
if (arguments.length == 1) {
|
||||
DataManager.deleteGuildKey(guild, "commandCharacter");
|
||||
return new CommandResponse("white_check_mark",
|
||||
executor.getAsMention() + ", the command character has been disabled.");
|
||||
} else {
|
||||
final char[] input = arguments[1].replaceAll("\n", "").toCharArray();
|
||||
if (input.length > 1) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but the command character must be a single character.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
} else if (input.length == 0) {
|
||||
DataManager.deleteGuildKey(guild, "commandCharacter");
|
||||
return new CommandResponse("white_check_mark",
|
||||
executor.getAsMention() + ", the command character has been disabled.");
|
||||
} else {
|
||||
DataManager.setGuildValue(guild, "commandCharacter", "" + input[0]);
|
||||
return new CommandResponse("white_check_mark",
|
||||
executor.getAsMention() + ", the command character has been set to `" + input[0] + "`.");
|
||||
}
|
||||
}
|
||||
} else if (arguments[0].equalsIgnoreCase("defaultvolume") || arguments[0].equalsIgnoreCase("volume")) {
|
||||
if (arguments.length == 1) {
|
||||
DataManager.deleteGuildKey(guild, "defaultVolume");
|
||||
if (!AudioUtil.isTrackLoaded(guild)) {
|
||||
AudioUtil.setVolume(guild, 10);
|
||||
}
|
||||
return new CommandResponse("white_check_mark",
|
||||
executor.getAsMention() + ", the default volume has been reset to `10%`.");
|
||||
} else {
|
||||
final int volume;
|
||||
try {
|
||||
volume = Integer.parseInt(arguments[1]);
|
||||
} catch (final NumberFormatException exception) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but the default volume must be an integer.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (volume == 10) {
|
||||
DataManager.deleteGuildKey(guild, "defaultVolume");
|
||||
return new CommandResponse("white_check_mark",
|
||||
executor.getAsMention() + ", the default volume has been reset to `10%`.");
|
||||
}
|
||||
|
||||
if (volume <= 150 && volume >= 1) {
|
||||
if (!AudioUtil.isTrackLoaded(guild)) {
|
||||
AudioUtil.setVolume(guild, volume);
|
||||
}
|
||||
DataManager.setGuildValue(guild, "defaultVolume", "" + volume);
|
||||
return new CommandResponse("white_check_mark",
|
||||
executor.getAsMention() + ", the default volume has been set to `" + volume + "%`.");
|
||||
} else {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but the default volume must be between 1% and 150%.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but I do not know what that setting is.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package dev.logal.logalbot.commands.administration;
|
||||
|
||||
// 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.TimeUnit;
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.PermissionManager;
|
||||
import net.dv8tion.jda.core.Permission;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Whitelist implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
if (!executor.hasPermission(Permission.ADMINISTRATOR)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you are not allowed to use this command.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (arguments.length == 0) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but you need to specify a user to add or remove from the whitelist.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
final String userID = arguments[0].replaceFirst("<@[!]?([0-9]*)>", "$1");
|
||||
final Member member;
|
||||
try {
|
||||
member = guild.getMemberById(userID);
|
||||
} catch (final Throwable exception) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but that doesn't appear to be a valid user.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (member == null) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but that doesn't appear to be a valid user.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (member.hasPermission(Permission.ADMINISTRATOR)) {
|
||||
return new CommandResponse("no_entry_sign", "Sorry " + executor.getAsMention()
|
||||
+ ", but you cannot remove that user from the whitelist due to them being a guild administrator.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (member.getUser().isBot()) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you cannot whitelist bots.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (PermissionManager.isWhitelisted(member)) {
|
||||
PermissionManager.removeFromWhitelist(member);
|
||||
return new CommandResponse("heavy_multiplication_x",
|
||||
executor.getAsMention() + " has removed " + member.getAsMention() + " from the whitelist.");
|
||||
} else {
|
||||
PermissionManager.addToWhitelist(member);
|
||||
return new CommandResponse("heavy_check_mark",
|
||||
executor.getAsMention() + " has added " + member.getAsMention() + " to the whitelist.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// 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.TimeUnit;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.TrackUtil;
|
||||
import dev.logal.logalbot.utils.VoiceChannelUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class ForceSkip implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
if (!AudioUtil.isTrackLoaded(guild)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but there must be a track playing in order to force skip it.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (!VoiceChannelUtil.isInCurrentVoiceChannel(executor)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you must be in voice channel `"
|
||||
+ AudioUtil.getVoiceChannelConnectedTo(guild).getName()
|
||||
+ "` in order to force skip tracks.").setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
final AudioTrack skippedTrack = AudioUtil.getLoadedTrack(guild);
|
||||
|
||||
AudioUtil.getTrackScheduler(guild).skipCurrentTrack();
|
||||
final CommandResponse response = new CommandResponse("gun",
|
||||
executor.getAsMention() + " force skipped the following track:");
|
||||
response.attachEmbed(TrackUtil.generateTrackInfoEmbed(skippedTrack));
|
||||
return response;
|
||||
}
|
||||
}
|
||||
55
src/main/java/dev/logal/logalbot/commands/audio/Lock.java
Normal file
55
src/main/java/dev/logal/logalbot/commands/audio/Lock.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// 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.TimeUnit;
|
||||
|
||||
import dev.logal.logalbot.audio.TrackScheduler;
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.VoiceChannelUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Lock implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
if (!AudioUtil.isTrackLoaded(guild)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but there must be a track playing in order to lock or unlock the queue.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (!VoiceChannelUtil.isInCurrentVoiceChannel(executor)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you must be in voice channel `"
|
||||
+ AudioUtil.getVoiceChannelConnectedTo(guild).getName()
|
||||
+ "` in order to lock or unlock the queue.").setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
final TrackScheduler scheduler = AudioUtil.getTrackScheduler(guild);
|
||||
if (scheduler.isQueueLocked()) {
|
||||
scheduler.setQueueLocked(false);
|
||||
return new CommandResponse("unlock", executor.getAsMention() + " unlocked the queue.");
|
||||
} else {
|
||||
scheduler.setQueueLocked(true);
|
||||
return new CommandResponse("lock", executor.getAsMention() + " locked the queue.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// 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.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.TrackUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class NowPlaying implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
if (!AudioUtil.isTrackLoaded(guild)) {
|
||||
return new CommandResponse("mute", executor.getAsMention() + ", there is nothing currently playing.");
|
||||
}
|
||||
|
||||
final CommandResponse response = new CommandResponse("dancer",
|
||||
executor.getAsMention() + ", this is the track currently playing:");
|
||||
response.attachEmbed(TrackUtil.generateCurrentTrackInfoEmbed(guild));
|
||||
return response;
|
||||
}
|
||||
}
|
||||
53
src/main/java/dev/logal/logalbot/commands/audio/Pause.java
Normal file
53
src/main/java/dev/logal/logalbot/commands/audio/Pause.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// 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.TimeUnit;
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.VoiceChannelUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Pause implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
if (!AudioUtil.isTrackLoaded(guild)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but there must be a track playing in order to pause or resume the track player.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (!VoiceChannelUtil.isInCurrentVoiceChannel(executor)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you must be in voice channel `"
|
||||
+ AudioUtil.getVoiceChannelConnectedTo(guild).getName()
|
||||
+ "` in order to pause or resume the track player.").setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (AudioUtil.isPlayerPaused(guild)) {
|
||||
AudioUtil.setPausedState(guild, false);
|
||||
return new CommandResponse("arrow_forward", executor.getAsMention() + " resumed the track player.");
|
||||
} else {
|
||||
AudioUtil.setPausedState(guild, true);
|
||||
return new CommandResponse("pause_button", executor.getAsMention() + " paused the track player.");
|
||||
}
|
||||
}
|
||||
}
|
||||
100
src/main/java/dev/logal/logalbot/commands/audio/Play.java
Normal file
100
src/main/java/dev/logal/logalbot/commands/audio/Play.java
Normal file
@@ -0,0 +1,100 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// 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.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import dev.logal.logalbot.audio.TrackScheduler;
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.PermissionManager;
|
||||
import dev.logal.logalbot.utils.VoiceChannelUtil;
|
||||
import net.dv8tion.jda.core.Permission;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||
|
||||
public final class Play implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
if (AudioUtil.isTrackLoaded(guild) && !VoiceChannelUtil.isInCurrentVoiceChannel(executor)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you need to be in voice channel `"
|
||||
+ AudioUtil.getVoiceChannelConnectedTo(guild).getName()
|
||||
+ "` in order to add songs to the queue.").setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
final VoiceChannel targetChannel = VoiceChannelUtil.getVoiceChannelMemberIsConnectedTo(executor);
|
||||
if (targetChannel == null) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but you need to be in a voice channel in order to add songs to the queue.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
final Member selfMember = guild.getSelfMember();
|
||||
if (!selfMember.hasPermission(targetChannel, Permission.VOICE_CONNECT)
|
||||
|| !selfMember.hasPermission(targetChannel, Permission.VOICE_SPEAK)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but I do not have the required permissions to use your current voice channel.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (arguments.length == 0) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but you need to provide a search query or a link to a specific track or playlist.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
final TrackScheduler scheduler = AudioUtil.getTrackScheduler(guild);
|
||||
if (scheduler.isQueueLocked() && !PermissionManager.isWhitelisted(executor)) {
|
||||
return new CommandResponse("lock", "Sorry " + executor.getAsMention() + ", but the queue is locked.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (scheduler.isQueueFull()) {
|
||||
return new CommandResponse("card_box", "Sorry " + executor.getAsMention() + ", but the queue is full.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
boolean isLink;
|
||||
try {
|
||||
new URL(arguments[0]);
|
||||
isLink = true;
|
||||
} catch (final MalformedURLException exception) {
|
||||
isLink = false;
|
||||
}
|
||||
|
||||
final StringBuilder query;
|
||||
if (isLink) {
|
||||
query = new StringBuilder(arguments[0]);
|
||||
} else {
|
||||
query = new StringBuilder("ytsearch:");
|
||||
for (final String part : arguments) {
|
||||
query.append(part).append(" ");
|
||||
}
|
||||
}
|
||||
|
||||
AudioUtil.findTrack(query.toString(), executor, channel);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
55
src/main/java/dev/logal/logalbot/commands/audio/Queue.java
Normal file
55
src/main/java/dev/logal/logalbot/commands/audio/Queue.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// 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.TimeUnit;
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.TrackUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Queue implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
if (AudioUtil.getTrackScheduler(guild).isQueueEmpty()) {
|
||||
return new CommandResponse("information_source", executor.getAsMention() + ", the queue is empty.");
|
||||
}
|
||||
|
||||
final CommandResponse response = new CommandResponse("bookmark_tabs",
|
||||
executor.getAsMention() + ", the following tracks are in the queue:");
|
||||
|
||||
final int page;
|
||||
if (arguments.length == 0) {
|
||||
page = 1;
|
||||
} else {
|
||||
try {
|
||||
page = Integer.parseInt(arguments[0]);
|
||||
} catch (final NumberFormatException exception) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but the page number must be an integer.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
response.attachEmbed(
|
||||
TrackUtil.generatePaginatedTrackListInfoEmbed(AudioUtil.getTrackScheduler(guild).getQueue(), page));
|
||||
return response;
|
||||
}
|
||||
}
|
||||
114
src/main/java/dev/logal/logalbot/commands/audio/Remove.java
Normal file
114
src/main/java/dev/logal/logalbot/commands/audio/Remove.java
Normal file
@@ -0,0 +1,114 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// 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.TimeUnit;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
import com.vdurmont.emoji.EmojiManager;
|
||||
|
||||
import dev.logal.logalbot.audio.TrackScheduler;
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.commands.ReactionCallback;
|
||||
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 dev.logal.logalbot.utils.VoiceChannelUtil;
|
||||
import net.dv8tion.jda.core.Permission;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.Message;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Remove implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final TrackScheduler scheduler = AudioUtil.getTrackScheduler(channel.getGuild());
|
||||
if (scheduler.isQueueEmpty()) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but there are no tracks in the queue.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
final Guild guild = channel.getGuild();
|
||||
if (AudioUtil.isTrackLoaded(guild) && !VoiceChannelUtil.isInCurrentVoiceChannel(executor)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you need to be in voice channel `"
|
||||
+ AudioUtil.getVoiceChannelConnectedTo(guild).getName()
|
||||
+ "` in order to remove tracks from the queue.").setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (arguments.length == 0) {
|
||||
if (!guild.getSelfMember().hasPermission(channel, Permission.MESSAGE_ADD_REACTION)) {
|
||||
return new CommandResponse("no_entry_sign", "Sorry " + executor.getAsMention()
|
||||
+ ", but I do not have the required permissions to create a reaction selection dialog in this text channel.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
final CommandResponse response = new CommandResponse("question",
|
||||
executor.getAsMention() + ", which track would you like to remove from the top of the queue?");
|
||||
response.attachEmbed(TrackUtil.generateTrackListInfoEmbed(scheduler.getQueue(), true));
|
||||
|
||||
for (int i = 0; i < scheduler.getQueue().size(); i++) {
|
||||
final int trackNumber = i + 1;
|
||||
if (trackNumber == 11) {
|
||||
break;
|
||||
}
|
||||
|
||||
response.addReactionCallback(EmojiManager.getForAlias("" + trackNumber), new ReactionCallback() {
|
||||
@Override
|
||||
public final void run(final Member reactor, final long messageID) {
|
||||
ReactionCallbackManager.unregisterMessage(messageID);
|
||||
channel.getMessageById(messageID).queue(this::deleteMessage);
|
||||
CommandManager.executeCommand(("remove " + trackNumber).split(" "), reactor, channel);
|
||||
}
|
||||
|
||||
private void deleteMessage(final Message message) {
|
||||
message.delete().queue();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
response.setReactionCallbackTarget(executor);
|
||||
response.setDeletionDelay(30, TimeUnit.SECONDS);
|
||||
return response;
|
||||
}
|
||||
|
||||
final int index;
|
||||
try {
|
||||
index = Integer.parseInt(arguments[0]);
|
||||
} catch (final NumberFormatException exception) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but the index must be an integer.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
try {
|
||||
final AudioTrack removedTrack = scheduler.getQueue().get(index - 1);
|
||||
|
||||
scheduler.removeFromQueue(index - 1);
|
||||
final CommandResponse response = new CommandResponse("scissors",
|
||||
executor.getAsMention() + " removed the following track from the queue:");
|
||||
response.attachEmbed(TrackUtil.generateTrackInfoEmbed(removedTrack));
|
||||
return response;
|
||||
} catch (final IndexOutOfBoundsException exception) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but that index is outside the bounds of the queue.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
46
src/main/java/dev/logal/logalbot/commands/audio/Reset.java
Normal file
46
src/main/java/dev/logal/logalbot/commands/audio/Reset.java
Normal file
@@ -0,0 +1,46 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// 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.TimeUnit;
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.VoiceChannelUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Reset implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
if (AudioUtil.isTrackLoaded(guild) && !VoiceChannelUtil.isInCurrentVoiceChannel(executor)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you need to be in voice channel `"
|
||||
+ AudioUtil.getVoiceChannelConnectedTo(guild).getName()
|
||||
+ "` in order to reset the audio player.").setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
AudioUtil.getTrackScheduler(guild).clearQueue();
|
||||
if (AudioUtil.isTrackLoaded(guild)) {
|
||||
AudioUtil.stopTrack(guild);
|
||||
}
|
||||
|
||||
return new CommandResponse("recycle",
|
||||
executor.getAsMention() + " has stopped the current track and reset the queue.");
|
||||
}
|
||||
}
|
||||
49
src/main/java/dev/logal/logalbot/commands/audio/Shuffle.java
Normal file
49
src/main/java/dev/logal/logalbot/commands/audio/Shuffle.java
Normal file
@@ -0,0 +1,49 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// 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.TimeUnit;
|
||||
|
||||
import dev.logal.logalbot.audio.TrackScheduler;
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.VoiceChannelUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Shuffle implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
final TrackScheduler scheduler = AudioUtil.getTrackScheduler(guild);
|
||||
if (scheduler.isQueueEmpty()) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but there are no tracks in the queue.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (AudioUtil.isTrackLoaded(guild) && !VoiceChannelUtil.isInCurrentVoiceChannel(executor)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you need to be in voice channel `"
|
||||
+ AudioUtil.getVoiceChannelConnectedTo(guild).getName()
|
||||
+ "` in order to shuffle the queue.").setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
scheduler.shuffleQueue();
|
||||
return new CommandResponse("salad", executor.getAsMention() + " shuffled the queue.");
|
||||
}
|
||||
}
|
||||
73
src/main/java/dev/logal/logalbot/commands/audio/Skip.java
Normal file
73
src/main/java/dev/logal/logalbot/commands/audio/Skip.java
Normal file
@@ -0,0 +1,73 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// 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.TimeUnit;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.SkipTracker;
|
||||
import dev.logal.logalbot.utils.TrackUtil;
|
||||
import dev.logal.logalbot.utils.VoiceChannelUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Skip implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
if (!AudioUtil.isTrackLoaded(guild)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but there must be a track playing in order to vote to skip it.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (!VoiceChannelUtil.isInCurrentVoiceChannel(executor)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you must be in voice channel `"
|
||||
+ AudioUtil.getVoiceChannelConnectedTo(channel.getGuild()).getName()
|
||||
+ "` in order to vote to skip the current track.").setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (SkipTracker.hasVoted(executor)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"You have already voted to skip the current track " + executor.getAsMention() + ".")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
SkipTracker.registerVote(executor);
|
||||
if (SkipTracker.shouldSkip(guild)) {
|
||||
final AudioTrack skippedTrack = AudioUtil.getLoadedTrack(guild);
|
||||
AudioUtil.getTrackScheduler(guild).skipCurrentTrack();
|
||||
final CommandResponse response = new CommandResponse("gun",
|
||||
executor.getAsMention() + " was the last required vote. The following track has been skipped:");
|
||||
response.attachEmbed(TrackUtil.generateTrackInfoEmbed(skippedTrack));
|
||||
return response;
|
||||
} else {
|
||||
if (SkipTracker.getRemainingRequired(guild) == 1) {
|
||||
return new CommandResponse("x", executor.getAsMention() + " has voted to skip the current track. "
|
||||
+ SkipTracker.getRemainingRequired(guild) + " more vote is needed.");
|
||||
} else {
|
||||
return new CommandResponse("x", executor.getAsMention() + " has voted to skip the current track. "
|
||||
+ SkipTracker.getRemainingRequired(guild) + " more votes are needed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
81
src/main/java/dev/logal/logalbot/commands/audio/Volume.java
Normal file
81
src/main/java/dev/logal/logalbot/commands/audio/Volume.java
Normal file
@@ -0,0 +1,81 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// 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.TimeUnit;
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.VoiceChannelUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Volume implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
if (!AudioUtil.isTrackLoaded(guild)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but there must be a track playing in order to change the volume of the track player.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (!VoiceChannelUtil.isInCurrentVoiceChannel(executor)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you must be in voice channel `"
|
||||
+ AudioUtil.getVoiceChannelConnectedTo(guild).getName()
|
||||
+ "` in order to change the volume of the track player.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (arguments.length == 0) {
|
||||
if (AudioUtil.getVolume(guild) >= 75) {
|
||||
return new CommandResponse("loud_sound", executor.getAsMention() + ", the volume is currently set to `"
|
||||
+ AudioUtil.getVolume(guild) + "%`.");
|
||||
} else {
|
||||
return new CommandResponse("sound", executor.getAsMention() + ", the volume is currently set to `"
|
||||
+ AudioUtil.getVolume(guild) + "%`.");
|
||||
}
|
||||
}
|
||||
|
||||
final int volume;
|
||||
try {
|
||||
volume = Integer.parseInt(arguments[0]);
|
||||
} catch (final NumberFormatException exception) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but the volume must be an integer.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (volume <= 150 && volume >= 1) {
|
||||
final int oldVolume = AudioUtil.getVolume(guild);
|
||||
AudioUtil.setVolume(guild, volume);
|
||||
if (volume >= 75) {
|
||||
return new CommandResponse("loud_sound",
|
||||
executor.getAsMention() + " set the volume from `" + oldVolume + "%` to `" + volume + "%`.");
|
||||
} else {
|
||||
return new CommandResponse("sound",
|
||||
executor.getAsMention() + " set the volume from `" + oldVolume + "%` to `" + volume + "%`.");
|
||||
}
|
||||
} else {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but the volume must be between 1% and 150%.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
73
src/main/java/dev/logal/logalbot/commands/fun/EightBall.java
Normal file
73
src/main/java/dev/logal/logalbot/commands/fun/EightBall.java
Normal file
@@ -0,0 +1,73 @@
|
||||
package dev.logal.logalbot.commands.fun;
|
||||
|
||||
// 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.ArrayList;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.vdurmont.emoji.EmojiManager;
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.StringUtil;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class EightBall implements Command {
|
||||
private final ArrayList<String> responses = new ArrayList<>(20);
|
||||
private final Random rng = new Random();
|
||||
|
||||
public EightBall() {
|
||||
responses.add("It is certain");
|
||||
responses.add("It is decidedly so");
|
||||
responses.add("Without a doubt");
|
||||
responses.add("Yes - definitely");
|
||||
responses.add("You may rely on it");
|
||||
responses.add("As I see it, yes");
|
||||
responses.add("Most likely");
|
||||
responses.add("Outlook good");
|
||||
responses.add("Yes");
|
||||
responses.add("Signs point to yes");
|
||||
|
||||
responses.add("Reply hazy, try again");
|
||||
responses.add("Ask again later");
|
||||
responses.add("Better not tell you now");
|
||||
responses.add("Cannot predict now");
|
||||
responses.add("Concentrate and ask again");
|
||||
|
||||
responses.add("Don't count on it");
|
||||
responses.add("My reply is no");
|
||||
responses.add("My sources say no");
|
||||
responses.add("Outlook not so good");
|
||||
responses.add("Very doubtful");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
if (arguments.length == 0) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry, " + executor.getAsMention() + ", but you need to supply a question for the Magic 8 Ball.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
final String question = StringUtil.sanitizeCodeBlock(String.join(" ", arguments));
|
||||
|
||||
return new CommandResponse("question",
|
||||
executor.getAsMention() + " asked the Magic 8 Ball: `" + question + "`\n"
|
||||
+ EmojiManager.getForAlias("8ball").getUnicode() + " The Magic 8 Ball responds: *"
|
||||
+ responses.get(rng.nextInt(responses.size())) + "*.");
|
||||
}
|
||||
}
|
||||
28
src/main/java/dev/logal/logalbot/commands/general/About.java
Normal file
28
src/main/java/dev/logal/logalbot/commands/general/About.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package dev.logal.logalbot.commands.general;
|
||||
|
||||
// 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.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class About implements Command {
|
||||
@Override
|
||||
public CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
return new CommandResponse("wave", "Hello " + executor.getAsMention()
|
||||
+ "! I'm LogalBot, a bot created by LogalDeveloper. https://logal.dev/");
|
||||
}
|
||||
}
|
||||
34
src/main/java/dev/logal/logalbot/commands/general/Help.java
Normal file
34
src/main/java/dev/logal/logalbot/commands/general/Help.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package dev.logal.logalbot.commands.general;
|
||||
|
||||
// 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.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import net.dv8tion.jda.core.EmbedBuilder;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Help implements Command {
|
||||
@Override
|
||||
public CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final CommandResponse response = new CommandResponse("directory",
|
||||
executor.getAsMention() + ", here are some helpful links:");
|
||||
final EmbedBuilder builder = new EmbedBuilder();
|
||||
builder.addField("Command Reference", "https://logal.dev/projects/logalbot/command-reference/", false);
|
||||
builder.addField("Git Repository", "https://git.logal.dev/LogalDeveloper/LogalBot", false);
|
||||
response.attachEmbed(builder.build());
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package dev.logal.logalbot.events;
|
||||
|
||||
// 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.events.message.guild.react.GuildMessageReactionAddEvent;
|
||||
import net.dv8tion.jda.core.hooks.ListenerAdapter;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class GuildMessageReactionAdd extends ListenerAdapter {
|
||||
@Override
|
||||
public final void onGuildMessageReactionAdd(final GuildMessageReactionAddEvent event) {
|
||||
Checks.notNull(event, "Event");
|
||||
|
||||
if (!event.getUser().equals(event.getJDA().getSelfUser())) {
|
||||
ReactionCallbackManager.executeCallback(event.getMessageIdLong(), event.getMember(),
|
||||
event.getReactionEmote().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package dev.logal.logalbot.events;
|
||||
|
||||
// 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.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import dev.logal.logalbot.utils.CommandManager;
|
||||
import dev.logal.logalbot.utils.DataManager;
|
||||
import net.dv8tion.jda.core.Permission;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.Message;
|
||||
import net.dv8tion.jda.core.entities.SelfUser;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent;
|
||||
import net.dv8tion.jda.core.hooks.ListenerAdapter;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class GuildMessageReceived extends ListenerAdapter {
|
||||
@Override
|
||||
public final void onGuildMessageReceived(final GuildMessageReceivedEvent event) {
|
||||
Checks.notNull(event, "Event");
|
||||
|
||||
final Guild guild = event.getGuild();
|
||||
final Member self = guild.getSelfMember();
|
||||
final TextChannel channel = event.getChannel();
|
||||
final Message message = event.getMessage();
|
||||
if (event.getAuthor().isBot() || message.isTTS() || !self.hasPermission(channel, Permission.MESSAGE_WRITE)
|
||||
|| !self.hasPermission(channel, Permission.MESSAGE_EMBED_LINKS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String content = message.getContentRaw();
|
||||
final SelfUser selfUser = event.getJDA().getSelfUser();
|
||||
final List<Member> mentionedMembers = message.getMentionedMembers();
|
||||
final Member author = event.getMember();
|
||||
if (mentionedMembers.size() >= 1 && mentionedMembers.get(0).getUser().getIdLong() == selfUser.getIdLong()
|
||||
&& (content.startsWith(self.getAsMention()) || content.startsWith(selfUser.getAsMention()))) {
|
||||
final String[] rawCommand = content.split(" ");
|
||||
final String[] command = Arrays.copyOfRange(rawCommand, 1, rawCommand.length);
|
||||
if (command.length >= 1) {
|
||||
if (self.hasPermission(channel, Permission.MESSAGE_MANAGE)) {
|
||||
message.delete().reason("LogalBot Command Execution").queue();
|
||||
}
|
||||
CommandManager.executeCommand(command, author, channel);
|
||||
}
|
||||
} else {
|
||||
final String commandCharacter = DataManager.getGuildValue(guild, "commandCharacter");
|
||||
if (commandCharacter == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final char commandChar = commandCharacter.toCharArray()[0];
|
||||
|
||||
if (content.length() > 1 && content.charAt(0) == commandChar) {
|
||||
final String[] command = content.substring(1).split(" ");
|
||||
if (self.hasPermission(channel, Permission.MESSAGE_MANAGE)) {
|
||||
message.delete().reason("LogalBot Command Execution").queue();
|
||||
}
|
||||
CommandManager.executeCommand(command, author, channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
29
src/main/java/dev/logal/logalbot/events/GuildReady.java
Normal file
29
src/main/java/dev/logal/logalbot/events/GuildReady.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package dev.logal.logalbot.events;
|
||||
|
||||
// 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.events.guild.GuildReadyEvent;
|
||||
import net.dv8tion.jda.core.hooks.ListenerAdapter;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class GuildReady extends ListenerAdapter {
|
||||
@Override
|
||||
public final void onGuildReady(final GuildReadyEvent event) {
|
||||
Checks.notNull(event, "Event");
|
||||
|
||||
AudioUtil.initialize(event.getGuild());
|
||||
}
|
||||
}
|
||||
65
src/main/java/dev/logal/logalbot/events/GuildVoiceLeave.java
Normal file
65
src/main/java/dev/logal/logalbot/events/GuildVoiceLeave.java
Normal file
@@ -0,0 +1,65 @@
|
||||
package dev.logal.logalbot.events;
|
||||
|
||||
// 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.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||
import net.dv8tion.jda.core.events.guild.voice.GuildVoiceLeaveEvent;
|
||||
import net.dv8tion.jda.core.hooks.ListenerAdapter;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class GuildVoiceLeave extends ListenerAdapter {
|
||||
private static final Logger logger = LoggerFactory.getLogger(GuildVoiceLeave.class);
|
||||
|
||||
@Override
|
||||
public final void onGuildVoiceLeave(final GuildVoiceLeaveEvent event) {
|
||||
Checks.notNull(event, "Event");
|
||||
|
||||
final Guild guild = event.getGuild();
|
||||
if (!AudioUtil.isAudioConnectionOpen(guild)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AudioUtil.isTrackLoaded(guild)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Member member = event.getMember();
|
||||
|
||||
if (member.getUser().equals(event.getJDA().getSelfUser())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final VoiceChannel leftChannel = event.getChannelLeft();
|
||||
if (leftChannel.equals(AudioUtil.getVoiceChannelConnectedTo(guild))) {
|
||||
final List<Member> members = leftChannel.getMembers();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
65
src/main/java/dev/logal/logalbot/events/GuildVoiceMove.java
Normal file
65
src/main/java/dev/logal/logalbot/events/GuildVoiceMove.java
Normal file
@@ -0,0 +1,65 @@
|
||||
package dev.logal.logalbot.events;
|
||||
|
||||
// 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.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||
import net.dv8tion.jda.core.events.guild.voice.GuildVoiceMoveEvent;
|
||||
import net.dv8tion.jda.core.hooks.ListenerAdapter;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class GuildVoiceMove extends ListenerAdapter {
|
||||
private static final Logger logger = LoggerFactory.getLogger(GuildVoiceMove.class);
|
||||
|
||||
@Override
|
||||
public final void onGuildVoiceMove(final GuildVoiceMoveEvent event) {
|
||||
Checks.notNull(event, "Event");
|
||||
|
||||
final Guild guild = event.getGuild();
|
||||
if (!AudioUtil.isAudioConnectionOpen(guild)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AudioUtil.isTrackLoaded(guild)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Member member = event.getMember();
|
||||
|
||||
if (member.getUser().equals(event.getJDA().getSelfUser())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final VoiceChannel leftChannel = event.getChannelLeft();
|
||||
if (leftChannel.equals(AudioUtil.getVoiceChannelConnectedTo(guild))) {
|
||||
final List<Member> members = leftChannel.getMembers();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 IdleDisconnectTask implements Runnable {
|
||||
private final Guild guild;
|
||||
|
||||
public IdleDisconnectTask(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
this.guild = guild;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run() {
|
||||
AudioUtil.closeAudioConnection(guild);
|
||||
}
|
||||
}
|
||||
@@ -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.ReactionCallbackManager;
|
||||
import net.dv8tion.jda.core.entities.Message;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class MessageDeleteTask implements Runnable {
|
||||
private final Message messageToDelete;
|
||||
|
||||
public MessageDeleteTask(final Message message) {
|
||||
Checks.notNull(message, "Message");
|
||||
|
||||
this.messageToDelete = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run() {
|
||||
ReactionCallbackManager.unregisterMessage(messageToDelete.getIdLong());
|
||||
messageToDelete.delete().queue();
|
||||
}
|
||||
}
|
||||
173
src/main/java/dev/logal/logalbot/utils/AudioUtil.java
Normal file
173
src/main/java/dev/logal/logalbot/utils/AudioUtil.java
Normal file
@@ -0,0 +1,173 @@
|
||||
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.HashMap;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
|
||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
|
||||
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
|
||||
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import dev.logal.logalbot.audio.AudioPlayerSendHandler;
|
||||
import dev.logal.logalbot.audio.TrackLoadHandler;
|
||||
import dev.logal.logalbot.audio.TrackScheduler;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||
import net.dv8tion.jda.core.managers.AudioManager;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class AudioUtil {
|
||||
private static final Logger logger = LoggerFactory.getLogger(AudioUtil.class);
|
||||
|
||||
private static final AudioPlayerManager playerManager = new DefaultAudioPlayerManager();
|
||||
private static final HashMap<String, AudioPlayer> players = new HashMap<>();
|
||||
private static final HashMap<String, TrackScheduler> schedulers = new HashMap<>();
|
||||
|
||||
private AudioUtil() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final void initializePlayerManager() {
|
||||
AudioSourceManagers.registerRemoteSources(playerManager);
|
||||
}
|
||||
|
||||
public static final void initialize(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
players.put(guild.getId(), playerManager.createPlayer());
|
||||
schedulers.put(guild.getId(), new TrackScheduler(guild));
|
||||
players.get(guild.getId()).addListener(schedulers.get(guild.getId()));
|
||||
|
||||
try {
|
||||
setVolume(guild, Integer.parseInt(DataManager.getGuildValue(guild, "defaultVolume")));
|
||||
} catch (final NumberFormatException exception) {
|
||||
setVolume(guild, 10);
|
||||
}
|
||||
|
||||
getTrackScheduler(guild).setQueueLocked(false);
|
||||
setPausedState(guild, false);
|
||||
|
||||
logger.info("Audio environment initialized for " + guild.getName() + " (" + guild.getId() + ").");
|
||||
}
|
||||
|
||||
public static final void openAudioConnection(final VoiceChannel channel) {
|
||||
Checks.notNull(channel, "Channel");
|
||||
|
||||
final Guild guild = channel.getGuild();
|
||||
final AudioManager audioManager = guild.getAudioManager();
|
||||
|
||||
audioManager.setSendingHandler(new AudioPlayerSendHandler(players.get(guild.getId())));
|
||||
audioManager.openAudioConnection(channel);
|
||||
}
|
||||
|
||||
public static final void closeAudioConnection(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
guild.getAudioManager().closeAudioConnection();
|
||||
}
|
||||
|
||||
public static final VoiceChannel getVoiceChannelConnectedTo(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
return guild.getAudioManager().getConnectedChannel();
|
||||
}
|
||||
|
||||
public static final boolean isAudioConnectionOpen(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
return guild.getAudioManager().isConnected();
|
||||
}
|
||||
|
||||
public static final void playTrack(final Guild guild, final AudioTrack track) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
Checks.notNull(track, "Track");
|
||||
|
||||
players.get(guild.getId()).playTrack(track);
|
||||
}
|
||||
|
||||
public static final void stopTrack(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
players.get(guild.getId()).stopTrack();
|
||||
}
|
||||
|
||||
public static final boolean isTrackLoaded(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
return !(getLoadedTrack(guild) == null);
|
||||
}
|
||||
|
||||
public static final AudioTrack getLoadedTrack(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
return players.get(guild.getId()).getPlayingTrack();
|
||||
}
|
||||
|
||||
public static final void setPausedState(final Guild guild, final boolean pausedState) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
Checks.notNull(pausedState, "Paused state");
|
||||
|
||||
guild.getAudioManager().setSelfMuted(pausedState);
|
||||
players.get(guild.getId()).setPaused(pausedState);
|
||||
|
||||
if (pausedState) {
|
||||
logger.info("The audio player was paused in " + guild.getName() + " (" + guild.getId() + ").");
|
||||
} else {
|
||||
logger.info("The audio player was resumed in " + guild.getName() + " (" + guild.getId() + ").");
|
||||
}
|
||||
}
|
||||
|
||||
public static final boolean isPlayerPaused(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
return players.get(guild.getId()).isPaused();
|
||||
}
|
||||
|
||||
public static final void setVolume(final Guild guild, final int volume) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
Checks.positive(volume, "Volume");
|
||||
|
||||
players.get(guild.getId()).setVolume(volume);
|
||||
logger.info("The audio player's volume was set to " + getVolume(guild) + "% in " + guild.getName() + " ("
|
||||
+ guild.getId() + ").");
|
||||
}
|
||||
|
||||
public static final int getVolume(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
return players.get(guild.getId()).getVolume();
|
||||
}
|
||||
|
||||
public static final void findTrack(final String query, final Member requester, final TextChannel channel) {
|
||||
Checks.notNull(query, "Query");
|
||||
Checks.notNull(requester, "Requester");
|
||||
Checks.notNull(channel, "Channel");
|
||||
|
||||
playerManager.loadItem(query, new TrackLoadHandler(requester, channel));
|
||||
}
|
||||
|
||||
public static final TrackScheduler getTrackScheduler(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
return schedulers.get(guild.getId());
|
||||
}
|
||||
}
|
||||
127
src/main/java/dev/logal/logalbot/utils/CommandManager.java
Normal file
127
src/main/java/dev/logal/logalbot/utils/CommandManager.java
Normal file
@@ -0,0 +1,127 @@
|
||||
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.Arrays;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class CommandManager {
|
||||
private static final Logger logger = LoggerFactory.getLogger(CommandManager.class);
|
||||
|
||||
private static final HashMap<String, Command> commandMap = new HashMap<>();
|
||||
private static final HashMap<String, Boolean> permissionMap = new HashMap<>();
|
||||
private static final HashMap<String, String> aliasMap = new HashMap<>();
|
||||
|
||||
private CommandManager() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final void executeCommand(final String[] command, final Member executor, final TextChannel channel) {
|
||||
Checks.notEmpty(command, "Command");
|
||||
Checks.notNull(executor, "Executor");
|
||||
Checks.notNull(channel, "Channel");
|
||||
|
||||
String commandName = command[0].toLowerCase();
|
||||
final String[] arguments = Arrays.copyOfRange(command, 1, command.length);
|
||||
final Guild guild = channel.getGuild();
|
||||
CommandResponse response;
|
||||
|
||||
if (aliasMap.containsKey(commandName)) {
|
||||
commandName = aliasMap.get(commandName);
|
||||
}
|
||||
|
||||
logger.info(executor.getEffectiveName() + " (" + executor.getUser().getId() + ") executed command '"
|
||||
+ commandName + "' with arguments '" + String.join(" ", arguments) + "' in " + guild.getName() + " ("
|
||||
+ guild.getId() + ").");
|
||||
if (!commandMap.containsKey(commandName)) {
|
||||
response = new CommandResponse("question",
|
||||
"Sorry " + executor.getAsMention() + ", but I do not know what that command is.");
|
||||
response.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
response.sendResponse(channel);
|
||||
return;
|
||||
}
|
||||
|
||||
if (permissionMap.get(commandName) && !PermissionManager.isWhitelisted(executor)) {
|
||||
logger.info(executor.getEffectiveName() + " (" + executor.getUser().getId()
|
||||
+ ") was denied access to a command due to not being whitelisted in " + guild.getName() + " ("
|
||||
+ guild.getId() + ").");
|
||||
response = new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you are not allowed to use this command.");
|
||||
response.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
response.sendResponse(channel);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
response = commandMap.get(commandName).execute(arguments, executor, channel);
|
||||
} catch (final Throwable exception) {
|
||||
logger.error(
|
||||
"An error occurred while executing a command for " + executor.getEffectiveName() + " ("
|
||||
+ executor.getUser().getId() + ") in " + guild.getName() + " (" + guild.getId() + ").",
|
||||
exception);
|
||||
response = new CommandResponse("sos",
|
||||
"Sorry " + executor.getAsMention() + ", but an error occurred while executing your command!!");
|
||||
response.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
response.sendResponse(channel);
|
||||
return;
|
||||
}
|
||||
|
||||
if (response != null) {
|
||||
response.sendResponse(channel);
|
||||
}
|
||||
}
|
||||
|
||||
public static final void registerCommand(final String command, final Command commandObject,
|
||||
final boolean mustBeWhitelisted) {
|
||||
Checks.notEmpty(command, "Command");
|
||||
Checks.notNull(commandObject, "Command object");
|
||||
Checks.notNull(mustBeWhitelisted, "Whitelist requirement");
|
||||
|
||||
commandMap.put(command, commandObject);
|
||||
permissionMap.put(command, mustBeWhitelisted);
|
||||
}
|
||||
|
||||
public static final void registerCommandAlias(final String alias, final String command) {
|
||||
Checks.notEmpty(alias, "Alias");
|
||||
Checks.notEmpty(command, "Command");
|
||||
|
||||
aliasMap.put(alias, command);
|
||||
}
|
||||
|
||||
public static final void unregisterCommand(final String command) {
|
||||
Checks.notEmpty(command, "Command");
|
||||
|
||||
commandMap.remove(command);
|
||||
permissionMap.remove(command);
|
||||
}
|
||||
|
||||
public static final void unregisterCommandAlias(final String command) {
|
||||
Checks.notEmpty(command, "Command");
|
||||
|
||||
aliasMap.remove(command);
|
||||
}
|
||||
}
|
||||
126
src/main/java/dev/logal/logalbot/utils/DataManager.java
Normal file
126
src/main/java/dev/logal/logalbot/utils/DataManager.java
Normal file
@@ -0,0 +1,126 @@
|
||||
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 org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.User;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
import redis.clients.jedis.Jedis;
|
||||
|
||||
public final class DataManager {
|
||||
private static final Logger logger = LoggerFactory.getLogger(DataManager.class);
|
||||
|
||||
private static final String host = System.getenv("REDIS_HOST");
|
||||
private static final String password = System.getenv("REDIS_PASSWORD");
|
||||
private static final String databaseNumber = System.getenv("REDIS_DATABASE");
|
||||
private static Jedis jedis = new Jedis();
|
||||
|
||||
private DataManager() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final void verifyConnection() {
|
||||
if (!jedis.isConnected()) {
|
||||
jedis = new Jedis(host);
|
||||
|
||||
if (password != null) {
|
||||
jedis.auth(password);
|
||||
}
|
||||
|
||||
if (databaseNumber != null) {
|
||||
final int num = Integer.parseInt(databaseNumber);
|
||||
jedis.select(num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final void runMigrations() {
|
||||
if (jedis.get("schemaVersion") == null) {
|
||||
logger.info("Migrating schema to version 1...");
|
||||
jedis.set("schemaVersion", "1");
|
||||
logger.info("Migration to schema version 1 complete.");
|
||||
}
|
||||
}
|
||||
|
||||
public static final String getUserValue(final Member member, final String key) {
|
||||
Checks.notNull(member, "Member");
|
||||
Checks.notEmpty(key, "Key");
|
||||
|
||||
return jedis.get("g" + member.getGuild().getId() + ":u" + member.getUser().getId() + ":" + key);
|
||||
}
|
||||
|
||||
public static final void setUserValue(final Member member, final String key, final String value) {
|
||||
Checks.notNull(member, "Member");
|
||||
Checks.notEmpty(key, "Key");
|
||||
Checks.notEmpty(value, "Value");
|
||||
|
||||
jedis.set("g" + member.getGuild().getId() + ":u" + member.getUser().getId() + ":" + key, value);
|
||||
}
|
||||
|
||||
public static final void deleteUserKey(final Member member, final String key) {
|
||||
Checks.notNull(member, "Member");
|
||||
Checks.notEmpty(key, "Key");
|
||||
|
||||
jedis.del("g" + member.getGuild().getId() + ":u" + member.getUser().getId() + ":" + key);
|
||||
}
|
||||
|
||||
public static final String getGlobalUserValue(final User user, final String key) {
|
||||
Checks.notNull(user, "User");
|
||||
Checks.notEmpty(key, "Key");
|
||||
|
||||
return jedis.get("u" + user.getId() + ":" + key);
|
||||
}
|
||||
|
||||
public static final void setGlobalUserValue(final User user, final String key, final String value) {
|
||||
Checks.notNull(user, "User");
|
||||
Checks.notEmpty(key, "Key");
|
||||
Checks.notEmpty(value, "Value");
|
||||
|
||||
jedis.set("u" + user.getId() + ":" + key, value);
|
||||
}
|
||||
|
||||
public static final void deleteGlobalUserKey(final User user, final String key) {
|
||||
Checks.notNull(user, "User");
|
||||
Checks.notEmpty(key, "Key");
|
||||
|
||||
jedis.del("u" + user.getId() + ":" + key);
|
||||
}
|
||||
|
||||
public static final String getGuildValue(final Guild guild, final String key) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
Checks.notEmpty(key, "Key");
|
||||
|
||||
return jedis.get("g" + guild.getId() + ":" + key);
|
||||
}
|
||||
|
||||
public static final void setGuildValue(final Guild guild, final String key, final String value) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
Checks.notEmpty(key, "Key");
|
||||
Checks.notEmpty(value, "Value");
|
||||
|
||||
jedis.set("g" + guild.getId() + ":" + key, value);
|
||||
}
|
||||
|
||||
public static final void deleteGuildKey(final Guild guild, final String key) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
Checks.notEmpty(key, "Key");
|
||||
|
||||
jedis.del("g" + guild.getId() + ":" + key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
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 org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.dv8tion.jda.core.Permission;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class PermissionManager {
|
||||
private static final Logger logger = LoggerFactory.getLogger(PermissionManager.class);
|
||||
|
||||
private PermissionManager() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final boolean isWhitelisted(final Member member) {
|
||||
Checks.notNull(member, "Member");
|
||||
|
||||
if (member.hasPermission(Permission.ADMINISTRATOR)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (DataManager.getUserValue(member, "whitelisted") == null) {
|
||||
DataManager.setUserValue(member, "whitelisted", "false");
|
||||
}
|
||||
|
||||
return DataManager.getUserValue(member, "whitelisted").equals("true");
|
||||
}
|
||||
|
||||
public static final void addToWhitelist(final Member member) {
|
||||
Checks.notNull(member, "Member");
|
||||
|
||||
DataManager.setUserValue(member, "whitelisted", "true");
|
||||
logger.info(member.getEffectiveName() + " (" + member.getUser().getId() + ") was added to the whitelist in "
|
||||
+ member.getGuild().getName() + " (" + member.getGuild().getId() + ").");
|
||||
}
|
||||
|
||||
public static final void removeFromWhitelist(final Member member) {
|
||||
Checks.notNull(member, "Member");
|
||||
|
||||
DataManager.setUserValue(member, "whitelisted", "false");
|
||||
logger.info(member.getEffectiveName() + " (" + member.getUser().getId() + ") was removed from the whitelist in "
|
||||
+ member.getGuild().getName() + " (" + member.getGuild().getId() + ").");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
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.HashMap;
|
||||
|
||||
import com.vdurmont.emoji.Emoji;
|
||||
import com.vdurmont.emoji.EmojiManager;
|
||||
|
||||
import dev.logal.logalbot.commands.ReactionCallback;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.Message;
|
||||
import net.dv8tion.jda.core.entities.User;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class ReactionCallbackManager {
|
||||
private static final HashMap<Long, HashMap<Emoji, ReactionCallback>> callbackDictionary = new HashMap<>();
|
||||
private static final HashMap<Long, Long> targetDictionary = new HashMap<>();
|
||||
|
||||
private ReactionCallbackManager() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final void registerCallback(final Message message, final Emoji emoji,
|
||||
final ReactionCallback callback) {
|
||||
Checks.notNull(message, "Message");
|
||||
Checks.notNull(emoji, "Emoji");
|
||||
Checks.notNull(callback, "Callback");
|
||||
|
||||
if (!callbackDictionary.containsKey(message.getIdLong())) {
|
||||
callbackDictionary.put(message.getIdLong(), new HashMap<>());
|
||||
}
|
||||
|
||||
callbackDictionary.get(message.getIdLong()).put(emoji, callback);
|
||||
}
|
||||
|
||||
public static final void setCallbackTarget(final User user, final Message message) {
|
||||
Checks.notNull(user, "User");
|
||||
Checks.notNull(message, "Messsage");
|
||||
|
||||
targetDictionary.put(message.getIdLong(), user.getIdLong());
|
||||
}
|
||||
|
||||
public static final void unregisterMessage(final long messageID) {
|
||||
Checks.notNull(messageID, "Message ID");
|
||||
|
||||
callbackDictionary.remove(messageID);
|
||||
targetDictionary.remove(messageID);
|
||||
}
|
||||
|
||||
public static final void executeCallback(final long messageID, final Member reactor, final String emoji) {
|
||||
Checks.notNull(messageID, "Message ID");
|
||||
Checks.notNull(reactor, "Reactor");
|
||||
Checks.notEmpty(emoji, "Emoji");
|
||||
|
||||
if (callbackDictionary.containsKey(messageID)) {
|
||||
if (targetDictionary.containsKey(messageID)
|
||||
&& !targetDictionary.get(messageID).equals(reactor.getUser().getIdLong())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Emoji parsedEmoji = EmojiManager.getByUnicode(emoji);
|
||||
if (callbackDictionary.get(messageID).containsKey(parsedEmoji)) {
|
||||
callbackDictionary.get(messageID).get(parsedEmoji).run(reactor, messageID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
48
src/main/java/dev/logal/logalbot/utils/Scheduler.java
Normal file
48
src/main/java/dev/logal/logalbot/utils/Scheduler.java
Normal file
@@ -0,0 +1,48 @@
|
||||
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.notNull(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.notNull(initialDelay, "Initial delay");
|
||||
Checks.notNull(period, "Period");
|
||||
Checks.notNull(unit, "Unit");
|
||||
|
||||
return pool.scheduleAtFixedRate(runnable, initialDelay, period, unit);
|
||||
}
|
||||
}
|
||||
77
src/main/java/dev/logal/logalbot/utils/SkipTracker.java
Normal file
77
src/main/java/dev/logal/logalbot/utils/SkipTracker.java
Normal file
@@ -0,0 +1,77 @@
|
||||
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.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class SkipTracker {
|
||||
private static final HashMap<Long, ArrayList<Long>> skipVotesDictionary = new HashMap<>();
|
||||
|
||||
private SkipTracker() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final void registerVote(final Member member) {
|
||||
Checks.notNull(member, "Member");
|
||||
|
||||
final Guild guild = member.getGuild();
|
||||
if (!skipVotesDictionary.containsKey(guild.getIdLong())) {
|
||||
resetVotes(guild);
|
||||
}
|
||||
|
||||
final ArrayList<Long> registeredVotes = skipVotesDictionary.get(guild.getIdLong());
|
||||
if (!registeredVotes.contains(member.getUser().getIdLong())) {
|
||||
registeredVotes.add(member.getUser().getIdLong());
|
||||
}
|
||||
}
|
||||
|
||||
public static final boolean hasVoted(final Member member) {
|
||||
Checks.notNull(member, "Member");
|
||||
|
||||
return skipVotesDictionary.get(member.getGuild().getIdLong()).contains(member.getUser().getIdLong());
|
||||
}
|
||||
|
||||
public static final void resetVotes(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
final long guildID = guild.getIdLong();
|
||||
if (skipVotesDictionary.containsKey(guildID)) {
|
||||
skipVotesDictionary.get(guildID).clear();
|
||||
} else {
|
||||
skipVotesDictionary.put(guildID, new ArrayList<>());
|
||||
}
|
||||
}
|
||||
|
||||
public static final int getRemainingRequired(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
final int listeners = (int) AudioUtil.getVoiceChannelConnectedTo(guild).getMembers().stream()
|
||||
.filter(member -> !member.getUser().isBot()).count();
|
||||
final int required = (int) Math.ceil(listeners * .55);
|
||||
|
||||
return (required - skipVotesDictionary.get(guild.getIdLong()).size());
|
||||
}
|
||||
|
||||
public static final boolean shouldSkip(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
return getRemainingRequired(guild) <= 0;
|
||||
}
|
||||
}
|
||||
45
src/main/java/dev/logal/logalbot/utils/StringUtil.java
Normal file
45
src/main/java/dev/logal/logalbot/utils/StringUtil.java
Normal file
@@ -0,0 +1,45 @@
|
||||
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 net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class StringUtil {
|
||||
private StringUtil() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final String sanitize(final String string) {
|
||||
Checks.notNull(string, "String");
|
||||
|
||||
return string.replaceAll("([_*`<@>~|])", "\\\\$1").replaceAll("[\r\n]", "");
|
||||
}
|
||||
|
||||
public static final String sanitizeCodeBlock(final String string) {
|
||||
Checks.notNull(string, "String");
|
||||
|
||||
return string.replaceAll("[`]", "'").replaceAll("[\r\n]", "");
|
||||
}
|
||||
|
||||
public static final String formatTime(final long milliseconds) {
|
||||
Checks.notNull(milliseconds, "Milliseconds");
|
||||
|
||||
final long second = (milliseconds / 1000) % 60;
|
||||
final long minute = (milliseconds / (1000 * 60)) % 60;
|
||||
final long hour = (milliseconds / (1000 * 60 * 60)) % 24;
|
||||
|
||||
return String.format("%02d:%02d:%02d", hour, minute, second);
|
||||
}
|
||||
}
|
||||
110
src/main/java/dev/logal/logalbot/utils/TrackUtil.java
Normal file
110
src/main/java/dev/logal/logalbot/utils/TrackUtil.java
Normal file
@@ -0,0 +1,110 @@
|
||||
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.List;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
|
||||
import net.dv8tion.jda.core.EmbedBuilder;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class TrackUtil {
|
||||
private TrackUtil() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final MessageEmbed generateTrackInfoEmbed(final AudioTrack track) {
|
||||
Checks.notNull(track, "Track");
|
||||
|
||||
final EmbedBuilder builder = new EmbedBuilder();
|
||||
builder.addField(StringUtil.sanitize(track.getInfo().title),
|
||||
StringUtil.sanitize(track.getInfo().author) + " - " + StringUtil.formatTime(track.getDuration()),
|
||||
false);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static final MessageEmbed generateCurrentTrackInfoEmbed(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
final EmbedBuilder builder = new EmbedBuilder();
|
||||
final AudioTrack track = AudioUtil.getLoadedTrack(guild);
|
||||
builder.addField(
|
||||
StringUtil.sanitize(track.getInfo().title), StringUtil.sanitize(track.getInfo().author) + " - "
|
||||
+ StringUtil.formatTime(track.getPosition()) + "/" + StringUtil.formatTime(track.getDuration()),
|
||||
false);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static final MessageEmbed generateTrackListInfoEmbed(final List<AudioTrack> tracks, final boolean numbered) {
|
||||
Checks.notNull(tracks, "Tracks");
|
||||
Checks.notNull(numbered, "Numbered");
|
||||
|
||||
final EmbedBuilder builder = new EmbedBuilder();
|
||||
for (int i = 0; i < tracks.size(); i++) {
|
||||
if (i == 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
final AudioTrack track = tracks.get(i);
|
||||
if (numbered) {
|
||||
builder.addField("**" + (i + 1) + ":** " + StringUtil.sanitize(track.getInfo().title),
|
||||
StringUtil.sanitize(track.getInfo().author) + " - "
|
||||
+ StringUtil.formatTime(track.getDuration()),
|
||||
false);
|
||||
} else {
|
||||
builder.addField(StringUtil.sanitize(track.getInfo().title), StringUtil.sanitize(track.getInfo().author)
|
||||
+ " - " + StringUtil.formatTime(track.getDuration()), false);
|
||||
}
|
||||
}
|
||||
|
||||
if (tracks.size() > 10) {
|
||||
builder.setTitle("**Top 10 Tracks - " + (tracks.size() - 10) + " Not Shown**");
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static final MessageEmbed generatePaginatedTrackListInfoEmbed(final List<AudioTrack> tracks, int page) {
|
||||
Checks.notNull(tracks, "Tracks");
|
||||
Checks.notNull(page, "Page");
|
||||
|
||||
final EmbedBuilder builder = new EmbedBuilder();
|
||||
if (page < 1) {
|
||||
page = 1;
|
||||
}
|
||||
|
||||
final int pages = (int) Math.ceil(tracks.size() / 10d);
|
||||
|
||||
if (page > pages) {
|
||||
page = pages;
|
||||
}
|
||||
|
||||
page = page - 1;
|
||||
final int start = page * 10;
|
||||
final int end = start + 10;
|
||||
|
||||
for (int i = start; i < end && i < tracks.size(); i++) {
|
||||
final AudioTrack track = tracks.get(i);
|
||||
builder.addField("**" + (i + 1) + ":** " + StringUtil.sanitize(track.getInfo().title),
|
||||
StringUtil.sanitize(track.getInfo().author) + " - " + StringUtil.formatTime(track.getDuration()),
|
||||
false);
|
||||
}
|
||||
|
||||
builder.setTitle("**" + tracks.size() + " Total Tracks - Page " + (page + 1) + "/" + pages + "**");
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
42
src/main/java/dev/logal/logalbot/utils/VoiceChannelUtil.java
Normal file
42
src/main/java/dev/logal/logalbot/utils/VoiceChannelUtil.java
Normal file
@@ -0,0 +1,42 @@
|
||||
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 net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class VoiceChannelUtil {
|
||||
private VoiceChannelUtil() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final VoiceChannel getVoiceChannelMemberIsConnectedTo(final Member member) {
|
||||
Checks.notNull(member, "Member");
|
||||
|
||||
for (final VoiceChannel channel : member.getGuild().getVoiceChannels()) {
|
||||
if (channel.getMembers().contains(member)) {
|
||||
return channel;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static final boolean isInCurrentVoiceChannel(final Member member) {
|
||||
Checks.notNull(member, "Member");
|
||||
|
||||
return AudioUtil.getVoiceChannelConnectedTo(member.getGuild()).getMembers().contains(member);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user