Compare commits

...
7 Commits
Author SHA1 Message Date
John Grosh 5deb41c651 updated libs
fixed internal bugs
lots of other things (see 0.0.9 release)
2017-09-02 16:39:08 -04:00
John Grosh 6b454c299d fixed NONE for game 2017-08-18 16:42:32 -04:00
John Grosh dddf4c8e38 added altprefix, songinstatus, and setstatus features
slight change to internals to reduce some bugs
2017-08-18 15:43:20 -04:00
John Grosh 0912de74e9 Merge origin/master 2017-07-04 02:58:24 -04:00
John Grosh 3752e5b9e0 update pom 2017-07-04 02:57:56 -04:00
John Grosh ae62d5771f Update README.md 2017-07-04 02:32:26 -04:00
John Grosh 434749a250 fixed playlist shuffling 2017-07-04 02:19:08 -04:00
26 changed files with 889 additions and 452 deletions

No files matched your search

+3
View File
@@ -22,5 +22,8 @@ Please see the [Setup Page](https://github.com/jagrosh/MusicBot/wiki/Setup) in t
# Questions/Suggestions/Bug Reports
If you'd like to suggest changes to how the bot functions, recommend more customization options, or report bugs, feel free to either open an [Issue](https://github.com/jagrosh/MusicBot/issues) on this repository, or join [my Discord server](https://discord.gg/0p9LSGoRLu6Pet0k). If you like this bot, be sure to add a star to the libraries that make this possible: [**JDA**](https://github.com/DV8FromTheWorld/JDA) and [**lavaplayer**](https://github.com/sedmelluq/lavaplayer)
# Editing
This bot (and the source code here) is not meant to be edited. The main purpose of having the source public is to show the capabilities of the libraries, and to allow others to understand how the bot works. There are many requirements and dependencies required to edit and compile it, and there will not be support provided for people looking to make changes on their own. Instead, consider making a feature request (see the above section). If you still choose to make edits, please do so in accordance with the Apache 2.0 License.
# Example
![Example](http://i.imgur.com/gxDdlRL.png)
+4 -4
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.jagrosh</groupId>
<artifactId>JMusicBot</artifactId>
<version>0.0.4</version>
<version>0.0.9</version>
<packaging>jar</packaging>
<repositories>
@@ -23,17 +23,17 @@
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>3.0.0_168</version>
<version>3.2.0_258</version>
</dependency>
<dependency>
<groupId>com.sedmelluq</groupId>
<artifactId>lavaplayer</artifactId>
<version>1.2.36</version>
<version>1.2.43</version>
</dependency>
<dependency>
<groupId>com.jagrosh</groupId>
<artifactId>JDA-Utilities</artifactId>
<version>1.1</version>
<version>1.6</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
+70 -6
View File
@@ -33,15 +33,21 @@ import com.jagrosh.jdautilities.waiter.EventWaiter;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import com.jagrosh.jmusicbot.gui.GUI;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import java.util.Objects;
import javafx.util.Pair;
import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.Game;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.entities.Message;
import net.dv8tion.jda.core.entities.Role;
import net.dv8tion.jda.core.entities.TextChannel;
import net.dv8tion.jda.core.entities.VoiceChannel;
import net.dv8tion.jda.core.events.ReadyEvent;
import net.dv8tion.jda.core.events.ShutdownEvent;
import net.dv8tion.jda.core.events.guild.GuildJoinEvent;
import net.dv8tion.jda.core.events.message.MessageDeleteEvent;
import net.dv8tion.jda.core.exceptions.PermissionException;
import net.dv8tion.jda.core.hooks.ListenerAdapter;
import net.dv8tion.jda.core.utils.SimpleLog;
import org.json.JSONException;
@@ -54,6 +60,7 @@ import org.json.JSONObject;
public class Bot extends ListenerAdapter {
private final HashMap<String,Settings> settings;
private final HashMap<Long,Pair<Long,Long>> lastNP; // guild -> channel,message
private final AudioPlayerManager manager;
private final EventWaiter waiter;
private final ScheduledExecutorService threadpool;
@@ -90,6 +97,7 @@ public class Bot extends ListenerAdapter {
this.config = config;
this.waiter = waiter;
this.settings = new HashMap<>();
this.lastNP = new HashMap<>();
manager = new DefaultAudioPlayerManager();
threadpool = Executors.newSingleThreadScheduledExecutor();
AudioSourceManagers.registerRemoteSources(manager);
@@ -111,6 +119,11 @@ public class Bot extends ListenerAdapter {
}
}
public JDA getJDA()
{
return jda;
}
public EventWaiter getWaiter()
{
return waiter;
@@ -142,15 +155,64 @@ public class Bot extends ListenerAdapter {
handler = new AudioHandler(player, guild, this);
player.addListener(handler);
guild.getAudioManager().setSendingHandler(handler);
threadpool.scheduleWithFixedDelay(() -> updateTopic(guild,handler), 0, 5, TimeUnit.SECONDS);
if(AudioHandler.USE_NP_REFRESH)
threadpool.scheduleWithFixedDelay(() -> updateLastNP(guild.getIdLong()), 0, 5, TimeUnit.SECONDS);
}
else
handler = (AudioHandler)guild.getAudioManager().getSendingHandler();
return handler;
}
private void updateTopic(Guild guild, AudioHandler handler)
public void resetGame()
{
Game game = config.getGame()==null || config.getGame().equalsIgnoreCase("none") ? null : Game.of(config.getGame());
if(!Objects.equals(jda.getPresence().getGame(), game))
jda.getPresence().setGame(game);
}
public void setLastNP(Message m)
{
lastNP.put(m.getGuild().getIdLong(), new Pair<>(m.getTextChannel().getIdLong(), m.getIdLong()));
}
@Override
public void onMessageDelete(MessageDeleteEvent event) {
if(lastNP.containsKey(event.getGuild().getIdLong()))
{
Pair<Long,Long> pair = lastNP.get(event.getGuild().getIdLong());
if(pair.getValue()==event.getMessageIdLong())
lastNP.remove(event.getGuild().getIdLong());
}
}
private void updateLastNP(long guildId)
{
Guild guild = jda.getGuildById(guildId);
if(guild==null)
return;
if(!lastNP.containsKey(guildId))
return;
Pair<Long,Long> pair = lastNP.get(guildId);
if(pair==null)
return;
TextChannel tc = guild.getTextChannelById(pair.getKey());
if(tc==null)
{
lastNP.remove(guildId);
return;
}
try {
tc.editMessageById(pair.getValue(), FormatUtil.nowPlayingMessage(guild, config.getSuccess())).queue(m->{}, t -> lastNP.remove(guildId));
} catch(Exception e) {
lastNP.remove(guildId);
}
}
public void updateTopic(long guildId, AudioHandler handler)
{
Guild guild = jda.getGuildById(guildId);
if(guild==null)
return;
TextChannel tchan = guild.getTextChannelById(getSettings(guild).getTextId());
if(tchan!=null && guild.getSelfMember().hasPermission(tchan, Permission.MANAGE_CHANNEL))
{
@@ -158,12 +220,14 @@ public class Bot extends ListenerAdapter {
if(tchan.getTopic()==null || tchan.getTopic().isEmpty())
otherText = "\u200B";
else if(tchan.getTopic().contains("\u200B"))
otherText = tchan.getTopic().substring(tchan.getTopic().indexOf("\u200B"));
otherText = tchan.getTopic().substring(tchan.getTopic().lastIndexOf("\u200B"));
else
otherText = "\u200B\n "+tchan.getTopic();
String text = FormatUtil.formattedAudio(handler, guild.getJDA())+otherText;
String text = FormatUtil.topicFormat(handler, guild.getJDA())+otherText;
if(!text.equals(tchan.getTopic()))
tchan.getManager().setTopic(text).queue();
try {
tchan.getManager().setTopic(text).queue();
} catch(PermissionException e){}
}
}
@@ -177,7 +241,7 @@ public class Bot extends ListenerAdapter {
{
ah.getQueue().clear();
ah.getPlayer().destroy();
updateTopic(g, ah);
updateTopic(g.getIdLong(), ah);
}
});
jda.shutdown();
@@ -15,14 +15,15 @@
*/
package com.jagrosh.jmusicbot;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import javax.swing.JOptionPane;
import net.dv8tion.jda.core.OnlineStatus;
/**
*
@@ -31,6 +32,7 @@ import javax.swing.JOptionPane;
public class Config {
private boolean nogui;
private String prefix;
private String altprefix;
private String token;
private String owner;
private String success;
@@ -40,13 +42,18 @@ public class Config {
private String help;
private boolean stay;
private boolean dbots;
private boolean songingame;
private boolean useEval;
private boolean npimages;
private long maxSeconds;
private OnlineStatus status = OnlineStatus.UNKNOWN;
public Config(boolean nogui)
{
this.nogui = nogui;
List<String> lines;
try {
lines = Files.readAllLines(Paths.get("config.txt"));
lines = Files.readAllLines(Paths.get("config.txt"), Charset.forName("ISO-8859-1"));
System.out.println("[INFO] Loading config: "+Paths.get("config.txt").toFile().getAbsolutePath());
for(String line: lines)
{
@@ -61,6 +68,9 @@ public class Config {
case "prefix":
prefix = value;
break;
case "altprefix":
altprefix = value;
break;
case "owner":
owner = value;
break;
@@ -79,15 +89,29 @@ public class Config {
case "help":
help = value;
break;
case "noprogressintopic":
FormatUtil.NO_PROGRESS_BAR_IN_TOPIC = "true".equalsIgnoreCase(value);
case "songinstatus":
songingame = "true".equalsIgnoreCase(value);
break;
case "stayinchannel":
stay = "true".equalsIgnoreCase(value);
break;
case "eval":
useEval = "true".equalsIgnoreCase(value);
break;
case "dbots":
dbots = "110373943822540800".equals(value);
break;
case "npimages":
npimages = "true".equalsIgnoreCase(value);
break;
case "maxtime":
try{
maxSeconds = Long.parseLong(value);
}catch(NumberFormatException e){}
break;
case "status":
status = OnlineStatus.fromKey(value);
break;
}
}
} catch (IOException ex) {
@@ -148,6 +172,11 @@ public class Config {
return prefix;
}
public String getAltPrefix()
{
return altprefix;
}
public String getToken()
{
return token;
@@ -193,11 +222,36 @@ public class Config {
return stay;
}
public boolean getSongInStatus()
{
return songingame;
}
public boolean getDBots()
{
return dbots;
}
public boolean useEval()
{
return useEval;
}
public boolean useNPImages()
{
return npimages;
}
public long getMaxSeconds()
{
return maxSeconds;
}
public OnlineStatus getStatus()
{
return status;
}
private void alert(String message)
{
if(nogui)
@@ -58,21 +58,27 @@ public class JMusicBot {
EventWaiter waiter = new EventWaiter();
Bot bot = new Bot(waiter, config);
AboutCommand.IS_AUTHOR = false;
AboutCommand ab = new AboutCommand(Color.BLUE.brighter(),
"a music bot that is [easy to host yourself!](https://github.com/jagrosh/MusicBot) (v0.0.9)",
new String[]{"High-quality music playback", "FairQueue™ Technology", "Easy to host yourself"},
RECOMMENDED_PERMS);
ab.setIsAuthor(false);
ab.setReplacementCharacter("\uD83C\uDFB6");
AudioHandler.STAY_IN_CHANNEL = config.getStay();
AudioHandler.SONG_IN_STATUS = config.getSongInStatus();
AudioHandler.MAX_SECONDS = config.getMaxSeconds();
AudioHandler.USE_NP_REFRESH = !config.useNPImages();
// set up the command client
CommandClientBuilder cb = new CommandClientBuilder()
.setPrefix(config.getPrefix())
.setAlternativePrefix(config.getAltPrefix())
.setOwnerId(config.getOwnerId())
.setEmojis(config.getSuccess(), config.getWarning(), config.getError())
.setHelpWord(config.getHelp())
.addCommands(
new AboutCommand(Color.BLUE.brighter(),
"a music bot that is [easy to host yourself!](https://github.com/jagrosh/MusicBot) (v0.0.7)",
new String[]{"High-quality music playback", "FairQueue™ Technology", "Easy to host yourself"},
RECOMMENDED_PERMS),
ab,
new PingCommand(),
new SettingsCmd(bot),
@@ -97,14 +103,26 @@ public class JMusicBot {
new SetvcCmd(bot),
//new GuildlistCommand(waiter),
new AutoplaylistCmd(bot),
new PlaylistCmd(bot),
new SetavatarCmd(bot),
new SetgameCmd(bot),
new SetnameCmd(bot),
new SetstatusCmd(bot),
new ShutdownCmd(bot)
);
if(config.useEval())
cb.addCommand(new EvalCmd(bot));
boolean nogame = false;
if(config.getStatus()!=OnlineStatus.UNKNOWN)
cb.setStatus(config.getStatus());
if(config.getGame()==null)
cb.useDefaultGame();
else if(config.getGame().equalsIgnoreCase("none"))
{
cb.setGame(null);
nogame = true;
}
else
cb.setGame(Game.of(config.getGame()));
CommandClient client = cb.build();
@@ -127,8 +145,8 @@ public class JMusicBot {
new JDABuilder(AccountType.BOT)
.setToken(config.getToken())
.setAudioEnabled(true)
.setGame(Game.of("loading..."))
.setStatus(OnlineStatus.DO_NOT_DISTURB)
.setGame(nogame ? null : Game.of("loading..."))
.setStatus(config.getStatus()==OnlineStatus.INVISIBLE||config.getStatus()==OnlineStatus.OFFLINE ? OnlineStatus.INVISIBLE : OnlineStatus.DO_NOT_DISTURB)
.addEventListener(client)
.addEventListener(waiter)
.addEventListener(bot)
@@ -28,6 +28,7 @@ import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.playlist.Playlist;
import com.jagrosh.jmusicbot.queue.FairQueue;
import net.dv8tion.jda.core.audio.AudioSendHandler;
import net.dv8tion.jda.core.entities.Game;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.entities.User;
@@ -37,18 +38,21 @@ import net.dv8tion.jda.core.entities.User;
*/
public class AudioHandler extends AudioEventAdapter implements AudioSendHandler {
private final AudioPlayer audioPlayer;
private final Guild guild;
private final long guildId;
private final FairQueue<QueuedTrack> queue;
private final Set<String> votes;
private final List<AudioTrack> defaultQueue;
private final Bot bot;
private AudioFrame lastFrame;
private QueuedTrack current;
private long requester;
public static boolean STAY_IN_CHANNEL;
public static boolean SONG_IN_STATUS;
public static long MAX_SECONDS = -1;
public static boolean USE_NP_REFRESH;
public AudioHandler(AudioPlayer audioPlayer, Guild guild, Bot bot) {
this.audioPlayer = audioPlayer;
this.guild = guild;
this.guildId = guild.getIdLong();
this.bot = bot;
queue = new FairQueue<>();
votes = new HashSet<>();
@@ -57,22 +61,14 @@ public class AudioHandler extends AudioEventAdapter implements AudioSendHandler
public int addTrack(AudioTrack track, User user)
{
QueuedTrack qt = new QueuedTrack(track, user.getId());
if(current==null)
if(audioPlayer.getPlayingTrack()==null)
{
current = qt;
requester = user.getIdLong();
audioPlayer.playTrack(track);
return -1;
}
else
{
return queue.add(qt);
}
}
public QueuedTrack getCurrentTrack()
{
return current;
return queue.add(new QueuedTrack(track, user.getIdLong()));
}
public FairQueue<QueuedTrack> getQueue()
@@ -90,7 +86,7 @@ public class AudioHandler extends AudioEventAdapter implements AudioSendHandler
public boolean isMusicPlaying()
{
return guild.getSelfMember().getVoiceState().inVoiceChannel() && current!=null;
return bot.getJDA().getGuildById(guildId).getSelfMember().getVoiceState().inVoiceChannel() && audioPlayer.getPlayingTrack()!=null;
}
public Set<String> getVotes()
@@ -103,60 +99,69 @@ public class AudioHandler extends AudioEventAdapter implements AudioSendHandler
return audioPlayer;
}
public long getRequester()
{
return requester;
}
public boolean playFromDefault()
{
if(!defaultQueue.isEmpty())
{
current = new QueuedTrack(defaultQueue.remove(0), null);
audioPlayer.playTrack(current.getTrack());
audioPlayer.playTrack(defaultQueue.remove(0));
return true;
}
Guild guild = bot.getJDA().getGuildById(guildId);
if(bot.getSettings(guild)==null || bot.getSettings(guild).getDefaultPlaylist()==null)
return false;
Playlist pl = Playlist.loadPlaylist(bot.getSettings(guild).getDefaultPlaylist());
if(pl==null || pl.getItems().isEmpty())
return false;
pl.loadTracks(bot.getAudioManager(), (at) -> {
if(current==null)
{
current = new QueuedTrack(at, null);
if(audioPlayer.getPlayingTrack()==null)
audioPlayer.playTrack(at);
}
else
defaultQueue.add(at);
}, () -> {
if(pl.getTracks().isEmpty())
{
current = null;
if(!STAY_IN_CHANNEL)
guild.getAudioManager().closeAudioConnection();
}
if(pl.getTracks().isEmpty() && !STAY_IN_CHANNEL)
guild.getAudioManager().closeAudioConnection();
});
return true;
}
@Override
public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) {
requester = 0;
if(queue.isEmpty())
{
current = null;
if(!playFromDefault())
{
current = null;
if(SONG_IN_STATUS)
bot.resetGame();
if(!STAY_IN_CHANNEL)
guild.getAudioManager().closeAudioConnection();
bot.getJDA().getGuildById(guildId).getAudioManager().closeAudioConnection();
bot.updateTopic(guildId, this);
}
}
else
{
current = queue.pull();
player.playTrack(current.getTrack());
QueuedTrack qt = queue.pull();
requester = qt.getIdentifier();
player.playTrack(qt.getTrack());
}
}
@Override
public void onTrackStart(AudioPlayer player, AudioTrack track) {
votes.clear();
if(SONG_IN_STATUS)
{
if(bot.getJDA().getGuilds().stream().filter(g -> g.getSelfMember().getVoiceState().inVoiceChannel()).count()<=1)
bot.getJDA().getPresence().setGame(Game.of(track.getInfo().title));
else
bot.resetGame();
}
bot.updateTopic(guildId, this);
}
@Override
@@ -174,4 +179,11 @@ public class AudioHandler extends AudioEventAdapter implements AudioSendHandler
public boolean isOpus() {
return true;
}
public static boolean isTooLong(AudioTrack track)
{
if(MAX_SECONDS<=0)
return false;
return Math.round(track.getDuration()/1000.0) > MAX_SECONDS;
}
}
@@ -1,52 +1,52 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* 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
*
* http://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.
*/
package com.jagrosh.jmusicbot.audio;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import com.jagrosh.jmusicbot.queue.Queueable;
import com.jagrosh.jmusicbot.utils.FormatUtil;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class QueuedTrack implements Queueable {
private final AudioTrack track;
private final String owner;
public QueuedTrack(AudioTrack track, String owner)
{
this.track = track;
this.owner = owner;
}
@Override
public String getIdentifier() {
return owner;
}
public AudioTrack getTrack()
{
return track;
}
@Override
public String toString() {
return "`["+FormatUtil.formatTime(track.getDuration())+"]` **" + track.getInfo().title +"** - <@"+owner+">";
}
}
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* 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
*
* http://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.
*/
package com.jagrosh.jmusicbot.audio;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import com.jagrosh.jmusicbot.queue.Queueable;
import com.jagrosh.jmusicbot.utils.FormatUtil;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class QueuedTrack implements Queueable {
private final AudioTrack track;
private final long owner;
public QueuedTrack(AudioTrack track, long owner)
{
this.track = track;
this.owner = owner;
}
@Override
public long getIdentifier() {
return owner;
}
public AudioTrack getTrack()
{
return track;
}
@Override
public String toString() {
return "`["+FormatUtil.formatTime(track.getDuration())+"]` **" + track.getInfo().title +"** - <@"+owner+">";
}
}
@@ -0,0 +1,70 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* 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
*
* http://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.
*/
package com.jagrosh.jmusicbot.commands;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import com.jagrosh.jdautilities.commandclient.Command;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.playlist.Playlist;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class AutoplaylistCmd extends Command {
private final Bot bot;
public AutoplaylistCmd(Bot bot)
{
this.bot = bot;
this.category = bot.OWNER;
this.ownerCommand = true;
this.guildOnly = true;
this.name = "autoplaylist";
this.arguments = "<name|NONE>";
this.help = "sets the default playlist for the server";
}
@Override
public void execute(CommandEvent event) {
if(event.getArgs().isEmpty())
{
event.reply(event.getClient().getError()+" Please include a playlist name or NONE");
return;
}
if(event.getArgs().equalsIgnoreCase("none"))
{
bot.setDefaultPlaylist(event.getGuild(), null);
event.reply(event.getClient().getSuccess()+" Cleared the default playlist for **"+event.getGuild().getName()+"**");
return;
}
String pname = event.getArgs().replaceAll("\\s+", "_");
if(Playlist.loadPlaylist(pname)==null)
{
event.reply(event.getClient().getError()+" Could not find `"+pname+".txt`!");
}
else
{
bot.setDefaultPlaylist(event.getGuild(), pname);
event.reply(event.getClient().getSuccess()+" The default playlist for **"+event.getGuild().getName()+"** is now `"+pname+"`");
}
}
}
@@ -0,0 +1,56 @@
/*
* Copyright 2016 John Grosh (jagrosh).
*
* 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
*
* http://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.
*/
package com.jagrosh.jmusicbot.commands;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import com.jagrosh.jdautilities.commandclient.Command;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
/**
*
* @author John Grosh (jagrosh)
*/
public class EvalCmd extends Command {
public EvalCmd(Bot bot)
{
this.name = "eval";
this.help = "evaluates nashorn code";
this.ownerCommand = true;
this.guildOnly = false;
this.category = bot.OWNER;
}
@Override
protected void execute(CommandEvent event) {
ScriptEngine se = new ScriptEngineManager().getEngineByName("Nashorn");
se.put("event", event);
se.put("jda", event.getJDA());
se.put("guild", event.getGuild());
se.put("channel", event.getChannel());
try
{
event.reply(event.getClient().getSuccess()+" Evaluated Successfully:\n```\n"+se.eval(event.getArgs())+" ```");
}
catch(Exception e)
{
event.reply(event.getClient().getError()+" An exception was thrown:\n```\n"+e+" ```");
}
}
}
@@ -39,13 +39,8 @@ public class ForceskipCmd extends MusicCommand {
@Override
public void doCommand(CommandEvent event) {
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
User u;
try {
u = event.getJDA().getUserById(handler.getCurrentTrack().getIdentifier());
} catch(Exception e) {
u = null;
}
event.reply(event.getClient().getSuccess()+" Skipped **"+handler.getCurrentTrack().getTrack().getInfo().title
User u = event.getJDA().getUserById(handler.getRequester());
event.reply(event.getClient().getSuccess()+" Skipped **"+handler.getPlayer().getPlayingTrack().getInfo().title
+"** (requested by "+(u==null ? "someone" : "**"+u.getName()+"**")+")");
handler.getPlayer().stopTrack();
}
@@ -17,13 +17,8 @@ package com.jagrosh.jmusicbot.commands;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import com.sedmelluq.discord.lavaplayer.source.soundcloud.SoundCloudAudioTrack;
import com.sedmelluq.discord.lavaplayer.source.youtube.YoutubeAudioTrack;
import net.dv8tion.jda.core.EmbedBuilder;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.User;
/**
*
@@ -42,44 +37,7 @@ public class NowplayingCmd extends MusicCommand {
@Override
public void doCommand(CommandEvent event) {
EmbedBuilder eb = new EmbedBuilder();
eb.setColor(event.getSelfMember().getColor());
AudioHandler ah = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
if(ah==null || !ah.isMusicPlaying())
{
eb.setTitle("No music playing");
eb.setDescription("\u23F9 "+FormatUtil.progressBar(-1)+" "+FormatUtil.volumeIcon(ah==null?100:ah.getPlayer().getVolume()));
event.reply(eb.build());
return;
}
if(ah.getCurrentTrack().getIdentifier()!=null)
{
User u;
try {
u = event.getJDA().getUserById(ah.getCurrentTrack().getIdentifier());
} catch(Exception e) {
u = null;
}
if(u==null)
eb.setAuthor("Unknown (ID:"+ah.getCurrentTrack().getIdentifier()+")", null, null);
else
eb.setAuthor(u.getName()+"#"+u.getDiscriminator(), null, u.getEffectiveAvatarUrl());
}
try {
eb.setTitle(ah.getCurrentTrack().getTrack().getInfo().title, ah.getCurrentTrack().getTrack().getInfo().uri);
} catch(Exception e) {
eb.setTitle(ah.getCurrentTrack().getTrack().getInfo().title);
}
if(ah.getCurrentTrack().getTrack() instanceof YoutubeAudioTrack)
eb.setThumbnail("https://img.youtube.com/vi/"+ah.getCurrentTrack().getTrack().getIdentifier()+"/maxresdefault.jpg");
eb.setDescription(FormatUtil.embedformattedAudio(ah));
event.reply(eb.build());
event.reply(FormatUtil.nowPlayingMessage(event.getGuild(), event.getClient().getSuccess()), m->bot.setLastNP(m));
}
}
@@ -44,7 +44,7 @@ public class PauseCmd extends MusicCommand {
return;
}
handler.getPlayer().setPaused(true);
event.replySuccess("Paused **"+handler.getCurrentTrack().getTrack().getInfo().title+"**. Type `"+event.getClient().getPrefix()+"play` to unpause!");
event.replySuccess("Paused **"+handler.getPlayer().getPlayingTrack().getInfo().title+"**. Type `"+event.getClient().getPrefix()+"play` to unpause!");
}
}
@@ -51,9 +51,11 @@ public class PlayCmd extends MusicCommand {
if(event.getArgs().isEmpty())
{
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
if(handler!=null && handler.getCurrentTrack()!=null && handler.getPlayer().isPaused())
if(handler!=null && handler.getPlayer().getPlayingTrack()!=null && handler.getPlayer().isPaused())
{
boolean isDJ = event.getMember().hasPermission(Permission.MANAGE_SERVER);
if(!isDJ)
isDJ = event.isOwner() || event.isCoOwner();
if(!isDJ)
isDJ = event.getMember().getRoles().contains(event.getGuild().getRoleById(bot.getSettings(event.getGuild()).getRoleId()));
if(!isDJ)
@@ -61,7 +63,7 @@ public class PlayCmd extends MusicCommand {
else
{
handler.getPlayer().setPaused(false);
event.replySuccess("Resumed **"+handler.getCurrentTrack().getTrack().getInfo().title+"**.");
event.replySuccess("Resumed **"+handler.getPlayer().getPlayingTrack().getInfo().title+"**.");
}
return;
}
@@ -94,6 +96,12 @@ public class PlayCmd extends MusicCommand {
@Override
public void trackLoaded(AudioTrack track) {
if(AudioHandler.isTooLong(track))
{
m.editMessage(event.getClient().getWarning()+" This track (**"+track.getInfo().title+"**) is longer than the allowed maximum: `"
+FormatUtil.formatTime(track.getDuration())+"` > `"+FormatUtil.formatTime(AudioHandler.MAX_SECONDS*1000)+"`").queue();
return;
}
int pos = bot.queueTrack(event, track)+1;
m.editMessage(event.getClient().getSuccess()+" Added **"+track.getInfo().title
+"** (`"+FormatUtil.formatTime(track.getDuration())+"`) "+(pos==0 ? "to begin playing"
@@ -105,6 +113,12 @@ public class PlayCmd extends MusicCommand {
if(playlist.getTracks().size()==1 || playlist.isSearchResult() || playlist.getSelectedTrack()!=null)
{
AudioTrack single = playlist.getSelectedTrack()==null?playlist.getTracks().get(0):playlist.getSelectedTrack();
if(AudioHandler.isTooLong(single))
{
m.editMessage(event.getClient().getWarning()+" This track (**"+single.getInfo().title+"**) is longer than the allowed maximum: `"
+FormatUtil.formatTime(single.getDuration())+"` > `"+FormatUtil.formatTime(AudioHandler.MAX_SECONDS*1000)+"`").queue();
return;
}
int pos = bot.queueTrack(event, single)+1;
m.editMessage(event.getClient().getSuccess()+" Added **"+single.getInfo().title
+"** (`"+FormatUtil.formatTime(single.getDuration())+"`) "+(pos==0 ? "to begin playing"
@@ -112,12 +126,27 @@ public class PlayCmd extends MusicCommand {
}
else
{
m.editMessage(event.getClient().getSuccess()+" Found "
+(playlist.getName()==null?"a playlist":"playlist **"+playlist.getName()+"**")+" with `"
+playlist.getTracks().size()+"` entries; added to the queue!").queue();
int[] count = {0};
playlist.getTracks().stream().forEach((track) -> {
bot.queueTrack(event, track);
if(!AudioHandler.isTooLong(track))
{
bot.queueTrack(event, track);
count[0]++;
}
});
if(count[0]==0)
{
m.editMessage(event.getClient().getWarning()+" All entries in this playlist "+(playlist.getName()==null ? "" : "(**"+playlist.getName()
+"**) ")+"were longer than the allowed maximum (`"+FormatUtil.formatTime(AudioHandler.MAX_SECONDS*1000)+"`)").queue();
}
else
{
m.editMessage(event.getClient().getSuccess()+" Found "
+(playlist.getName()==null?"a playlist":"playlist **"+playlist.getName()+"**")+" with `"
+ playlist.getTracks().size()+"` entries; added to the queue!"
+ (count[0]<playlist.getTracks().size() ? "\n"+event.getClient().getWarning()+" Tracks longer than the allowed maximum (`"
+ FormatUtil.formatTime(AudioHandler.MAX_SECONDS*1000)+"`) have been omitted." : "")).queue();
}
}
}
@@ -65,7 +65,7 @@ public class QueueCmd extends MusicCommand {
if(list.isEmpty())
{
event.replyWarning("There is no music in the queue!"
+(!ah.isMusicPlaying() ? "" : " Now playing:\n\n**"+ah.getCurrentTrack().getTrack().getInfo().title+"**\n"+FormatUtil.embedformattedAudio(ah)));
+(!ah.isMusicPlaying() ? "" : " Now playing:\n\n**"+ah.getPlayer().getPlayingTrack().getInfo().title+"**\n"+FormatUtil.embedFormat(ah)));
return;
}
String[] songs = new String[list.size()];
@@ -87,8 +87,8 @@ public class QueueCmd extends MusicCommand {
private String getQueueTitle(AudioHandler ah, String success, int songslength, long total)
{
StringBuilder sb = new StringBuilder();
if(ah.getCurrentTrack()!=null)
sb.append("**").append(ah.getCurrentTrack().getTrack().getInfo().title).append("**\n").append(FormatUtil.embedformattedAudio(ah)).append("\n\n");
if(ah.getPlayer().getPlayingTrack()!=null)
sb.append("**").append(ah.getPlayer().getPlayingTrack().getInfo().title).append("**\n").append(FormatUtil.embedFormat(ah)).append("\n\n");
return sb.append(success).append(" Current Queue | ").append(songslength).append(" entries | `").append(FormatUtil.formatTime(total)).append("` ").toString();
}
}
@@ -21,7 +21,6 @@ import com.jagrosh.jmusicbot.audio.AudioHandler;
import com.jagrosh.jmusicbot.audio.QueuedTrack;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.User;
import net.dv8tion.jda.core.utils.PermissionUtil;
/**
*
@@ -50,7 +49,7 @@ public class RemoveCmd extends MusicCommand {
}
if(event.getArgs().equalsIgnoreCase("all"))
{
int count = handler.getQueue().removeAll(event.getAuthor().getId());
int count = handler.getQueue().removeAll(event.getAuthor().getIdLong());
if(count==0)
event.reply(event.getClient().getWarning()+" You don't have any songs in the queue!");
else
@@ -72,7 +71,7 @@ public class RemoveCmd extends MusicCommand {
if(!isDJ)
isDJ = event.getMember().getRoles().contains(event.getGuild().getRoleById(bot.getSettings(event.getGuild()).getRoleId()));
QueuedTrack qt = handler.getQueue().get(pos-1);
if(qt.getIdentifier().equals(event.getAuthor().getId()))
if(qt.getIdentifier()==event.getAuthor().getIdLong())
{
handler.getQueue().remove(pos-1);
event.reply(event.getClient().getSuccess()+" Removed **"+qt.getTrack().getInfo().title+"** from the queue");
@@ -24,6 +24,7 @@ import java.util.concurrent.TimeUnit;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jdautilities.menu.orderedmenu.OrderedMenuBuilder;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.Message;
@@ -75,6 +76,12 @@ public class SCSearchCmd extends MusicCommand {
@Override
public void trackLoaded(AudioTrack track) {
if(AudioHandler.isTooLong(track))
{
m.editMessage(event.getClient().getWarning()+" This track (**"+track.getInfo().title+"**) is longer than the allowed maximum: `"
+FormatUtil.formatTime(track.getDuration())+"` > `"+FormatUtil.formatTime(AudioHandler.MAX_SECONDS*1000)+"`").queue();
return;
}
int pos = bot.queueTrack(event, track)+1;
m.editMessage(event.getClient().getSuccess()+" Added **"+track.getInfo().title
+"** (`"+FormatUtil.formatTime(track.getDuration())+"`) "+(pos==0 ? "to begin playing"
@@ -88,6 +95,12 @@ public class SCSearchCmd extends MusicCommand {
.setChoices(new String[0])
.setAction(i -> {
AudioTrack track = playlist.getTracks().get(i-1);
if(AudioHandler.isTooLong(track))
{
event.getChannel().sendMessage(event.getClient().getWarning()+" This track (**"+track.getInfo().title+"**) is longer than the allowed maximum: `"
+FormatUtil.formatTime(track.getDuration())+"` > `"+FormatUtil.formatTime(AudioHandler.MAX_SECONDS*1000)+"`").queue();
return;
}
int pos = bot.queueTrack(event, track)+1;
event.getChannel().sendMessage(event.getClient().getSuccess()+" Added **"+track.getInfo().title
+"** (`"+FormatUtil.formatTime(track.getDuration())+"`) "+(pos==0 ? "to begin playing"
@@ -24,6 +24,7 @@ import java.util.concurrent.TimeUnit;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jdautilities.menu.orderedmenu.OrderedMenuBuilder;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.Message;
@@ -76,6 +77,12 @@ public class SearchCmd extends MusicCommand {
@Override
public void trackLoaded(AudioTrack track) {
if(AudioHandler.isTooLong(track))
{
m.editMessage(event.getClient().getWarning()+" This track (**"+track.getInfo().title+"**) is longer than the allowed maximum: `"
+FormatUtil.formatTime(track.getDuration())+"` > `"+FormatUtil.formatTime(AudioHandler.MAX_SECONDS*1000)+"`").queue();
return;
}
int pos = bot.queueTrack(event, track)+1;
m.editMessage(event.getClient().getSuccess()+" Added **"+track.getInfo().title
+"** (`"+FormatUtil.formatTime(track.getDuration())+"`) "+(pos==0 ? "to begin playing"
@@ -89,6 +96,12 @@ public class SearchCmd extends MusicCommand {
.setChoices(new String[0])
.setAction(i -> {
AudioTrack track = playlist.getTracks().get(i-1);
if(AudioHandler.isTooLong(track))
{
event.getChannel().sendMessage(event.getClient().getWarning()+" This track (**"+track.getInfo().title+"**) is longer than the allowed maximum: `"
+FormatUtil.formatTime(track.getDuration())+"` > `"+FormatUtil.formatTime(AudioHandler.MAX_SECONDS*1000)+"`").queue();
return;
}
int pos = bot.queueTrack(event, track)+1;
event.getChannel().sendMessage(event.getClient().getSuccess()+" Added **"+track.getInfo().title
+"** (`"+FormatUtil.formatTime(track.getDuration())+"`) "+(pos==0 ? "to begin playing"
@@ -1,49 +1,79 @@
/*
* Copyright 2017 John Grosh <john.a.grosh@gmail.com>.
*
* 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
*
* http://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.
*/
package com.jagrosh.jmusicbot.commands;
import com.jagrosh.jdautilities.commandclient.Command;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import net.dv8tion.jda.core.entities.Game;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class SetgameCmd extends Command {
public SetgameCmd(Bot bot)
{
this.name = "setgame";
this.help = "sets the game the bot is playing";
this.arguments = "[game]";
this.ownerCommand = true;
this.category = bot.OWNER;
}
@Override
protected void execute(CommandEvent event) {
try {
event.getJDA().getPresence().setGame(event.getArgs().isEmpty() ? null : Game.of(event.getArgs()));
event.reply(event.getClient().getSuccess()+" **"+event.getSelfUser().getName()
+"** is "+(event.getArgs().isEmpty() ? "no longer playing anything." : "now playing `"+event.getArgs()+"`"));
} catch(Exception e) {
event.reply(event.getClient().getError()+" The game could not be set!");
}
}
}
/*
* Copyright 2017 John Grosh <john.a.grosh@gmail.com>.
*
* 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
*
* http://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.
*/
package com.jagrosh.jmusicbot.commands;
import com.jagrosh.jdautilities.commandclient.Command;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import net.dv8tion.jda.core.entities.Game;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class SetgameCmd extends Command {
public SetgameCmd(Bot bot)
{
this.name = "setgame";
this.help = "sets the game the bot is playing";
this.arguments = "[game] OR stream <username> <game>";
this.ownerCommand = true;
this.category = bot.OWNER;
this.children = new Command[]{new SetstreamCmd(bot)};
}
@Override
protected void execute(CommandEvent event) {
try {
event.getJDA().getPresence().setGame(event.getArgs().isEmpty() ? null : Game.of(event.getArgs()));
event.reply(event.getClient().getSuccess()+" **"+event.getSelfUser().getName()
+"** is "+(event.getArgs().isEmpty() ? "no longer playing anything." : "now playing `"+event.getArgs()+"`"));
} catch(Exception e) {
event.reply(event.getClient().getError()+" The game could not be set!");
}
}
private class SetstreamCmd extends Command {
private SetstreamCmd(Bot bot)
{
this.name = "stream";
this.aliases = new String[]{"twitch","streaming"};
this.help = "sets the game the bot is playing to a stream";
this.arguments = "<username> <game>";
this.ownerCommand = true;
this.category = bot.OWNER;
}
@Override
protected void execute(CommandEvent event) {
String[] parts = event.getArgs().split("\\s+", 2);
if(parts.length<2)
{
event.replyError("Please include a twitch username and the name of the game to 'stream'");
return;
}
try {
event.getJDA().getPresence().setGame(Game.of(parts[1], "https://twitch.tv/"+parts[0]));
event.replySuccess("**"+event.getSelfUser().getName()
+"** is now streaming `"+parts[1]+"`");
} catch(Exception e) {
event.reply(event.getClient().getError()+" The game could not be set!");
}
}
}
}
@@ -0,0 +1,56 @@
/*
* Copyright 2017 John Grosh <john.a.grosh@gmail.com>.
*
* 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
*
* http://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.
*/
package com.jagrosh.jmusicbot.commands;
import com.jagrosh.jdautilities.commandclient.Command;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import net.dv8tion.jda.core.OnlineStatus;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class SetstatusCmd extends Command {
public SetstatusCmd(Bot bot)
{
this.name = "setstatus";
this.help = "sets the status the bot displays";
this.arguments = "<status>";
this.ownerCommand = true;
this.category = bot.OWNER;
}
@Override
protected void execute(CommandEvent event) {
try {
OnlineStatus status = OnlineStatus.fromKey(event.getArgs());
if(status==OnlineStatus.UNKNOWN)
{
event.replyError("Please include one of the following statuses: `ONLINE`, `IDLE`, `DND`, `INVISIBLE`");
}
else
{
event.getJDA().getPresence().setStatus(status);
event.replySuccess("Set the status to `"+status.getKey().toUpperCase()+"`");
}
} catch(Exception e) {
event.reply(event.getClient().getError()+" The status could not be set!");
}
}
}
@@ -1,54 +1,54 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* 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
*
* http://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.
*/
package com.jagrosh.jmusicbot.commands;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class ShuffleCmd extends MusicCommand {
public ShuffleCmd(Bot bot)
{
super(bot);
this.name = "shuffle";
this.help = "shuffles songs you have added";
this.beListening = true;
this.bePlaying = true;
}
@Override
public void doCommand(CommandEvent event) {
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
int s = handler.getQueue().shuffle(event.getAuthor().getId());
switch (s) {
case 0:
event.reply(event.getClient().getError()+" You don't have any music in the queue to shuffle!");
break;
case 1:
event.reply(event.getClient().getWarning()+" You only have one song in the queue!");
break;
default:
event.reply(event.getClient().getSuccess()+" You successfully shuffled your "+s+" entries.");
break;
}
}
}
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* 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
*
* http://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.
*/
package com.jagrosh.jmusicbot.commands;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class ShuffleCmd extends MusicCommand {
public ShuffleCmd(Bot bot)
{
super(bot);
this.name = "shuffle";
this.help = "shuffles songs you have added";
this.beListening = true;
this.bePlaying = true;
}
@Override
public void doCommand(CommandEvent event) {
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
int s = handler.getQueue().shuffle(event.getAuthor().getIdLong());
switch (s) {
case 0:
event.reply(event.getClient().getError()+" You don't have any music in the queue to shuffle!");
break;
case 1:
event.reply(event.getClient().getWarning()+" You only have one song in the queue!");
break;
default:
event.reply(event.getClient().getSuccess()+" You successfully shuffled your "+s+" entries.");
break;
}
}
}
@@ -39,10 +39,9 @@ public class SkipCmd extends MusicCommand {
@Override
public void doCommand(CommandEvent event) {
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
if(event.getAuthor().getId().equals(handler.getCurrentTrack().getIdentifier()))
if(event.getAuthor().getIdLong()==handler.getRequester())
{
event.reply(event.getClient().getSuccess()+" Skipped **"+handler.getCurrentTrack().getTrack().getInfo().title
+"**");
event.reply(event.getClient().getSuccess()+" Skipped **"+handler.getPlayer().getPlayingTrack().getInfo().title+"**");
handler.getPlayer().stopTrack();
}
else
@@ -63,14 +62,9 @@ public class SkipCmd extends MusicCommand {
msg+= skippers+" votes, "+required+"/"+listeners+" needed]`";
if(skippers>=required)
{
User u;
try {
u = event.getJDA().getUserById(handler.getCurrentTrack().getIdentifier());
} catch(Exception e) {
u = null;
}
msg+="\n"+event.getClient().getSuccess()+" Skipped **"+handler.getCurrentTrack().getTrack().getInfo().title
+"**"+(handler.getCurrentTrack().getIdentifier()==null ? "" : " (requested by "+(u==null ? "someone" : "**"+u.getName()+"**")+")");
User u = event.getJDA().getUserById(handler.getRequester());
msg+="\n"+event.getClient().getSuccess()+" Skipped **"+handler.getPlayer().getPlayingTrack().getInfo().title
+"**"+(handler.getRequester()==0 ? "" : " (requested by "+(u==null ? "someone" : "**"+u.getName()+"**")+")");
handler.getPlayer().stopTrack();
}
event.reply(msg);
@@ -1,111 +1,111 @@
/*
* Copyright 2017 John Grosh <john.a.grosh@gmail.com>.
*
* 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
*
* http://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.
*/
package com.jagrosh.jmusicbot.gui;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.List;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import net.dv8tion.jda.core.entities.Guild;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class GuildsPanel extends JPanel {
private final Bot bot;
private final JList guildList;
private final JTextArea guildQueue;
private int index = -1;
public GuildsPanel(Bot bot)
{
super();
super.setLayout(new GridBagLayout());
this.bot = bot;
guildList = new JList();
guildQueue = new JTextArea();
guildList.setModel(new DefaultListModel());
guildList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
guildList.setFixedCellHeight(20);
guildList.setPreferredSize(new Dimension(100,300));
guildQueue.setPreferredSize(new Dimension(300,300));
guildQueue.setEditable(false);
JScrollPane pane = new JScrollPane();
JScrollPane pane2 = new JScrollPane();
pane.setViewportView(guildList);
pane2.setViewportView(guildQueue);
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.LINE_START;
c.gridx = 0;
c.gridwidth = 1;
super.add(pane, c);
c.gridx = 1;
c.gridwidth = 3;
super.add(pane2, c);
//bot.registerPanel(this);
guildList.addListSelectionListener((ListSelectionEvent e) -> {
index = guildList.getSelectedIndex();
//bot.updatePanel();
});
}
public void updateList(List<Guild> guilds)
{
String[] strs = new String[guilds.size()];
for(int i=0; i<guilds.size(); i++)
strs[i] = guilds.get(i).getName();
guildList.setListData(strs);
}
public int getIndex()
{
return guildList.getSelectedIndex();
}
public void updatePanel(AudioHandler handler) {
StringBuilder builder = new StringBuilder("Now Playing: ");
if(handler==null || handler.getCurrentTrack()==null)
{
builder.append("nothing");
}
else
{
builder.append(handler.getCurrentTrack().getTrack().getInfo().title)
.append(" [")
.append(FormatUtil.formatTime(handler.getCurrentTrack().getTrack().getDuration()))
.append("]\n");
for(int i=0; i<handler.getQueue().size(); i++)
builder.append("\n").append(i+1).append(". ").append(handler.getQueue().get(i).getTrack().getInfo().title);
}
guildQueue.setText(builder.toString());
guildQueue.updateUI();
}
}
/*
* Copyright 2017 John Grosh <john.a.grosh@gmail.com>.
*
* 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
*
* http://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.
*/
package com.jagrosh.jmusicbot.gui;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.List;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import net.dv8tion.jda.core.entities.Guild;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class GuildsPanel extends JPanel {
private final Bot bot;
private final JList guildList;
private final JTextArea guildQueue;
private int index = -1;
public GuildsPanel(Bot bot)
{
super();
super.setLayout(new GridBagLayout());
this.bot = bot;
guildList = new JList();
guildQueue = new JTextArea();
guildList.setModel(new DefaultListModel());
guildList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
guildList.setFixedCellHeight(20);
guildList.setPreferredSize(new Dimension(100,300));
guildQueue.setPreferredSize(new Dimension(300,300));
guildQueue.setEditable(false);
JScrollPane pane = new JScrollPane();
JScrollPane pane2 = new JScrollPane();
pane.setViewportView(guildList);
pane2.setViewportView(guildQueue);
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.LINE_START;
c.gridx = 0;
c.gridwidth = 1;
super.add(pane, c);
c.gridx = 1;
c.gridwidth = 3;
super.add(pane2, c);
//bot.registerPanel(this);
guildList.addListSelectionListener((ListSelectionEvent e) -> {
index = guildList.getSelectedIndex();
//bot.updatePanel();
});
}
public void updateList(List<Guild> guilds)
{
String[] strs = new String[guilds.size()];
for(int i=0; i<guilds.size(); i++)
strs[i] = guilds.get(i).getName();
guildList.setListData(strs);
}
public int getIndex()
{
return guildList.getSelectedIndex();
}
/*public void updatePanel(AudioHandler handler) {
StringBuilder builder = new StringBuilder("Now Playing: ");
if(handler==null || handler.getCurrentTrack()==null)
{
builder.append("nothing");
}
else
{
builder.append(handler.getCurrentTrack().getTrack().getInfo().title)
.append(" [")
.append(FormatUtil.formatTime(handler.getCurrentTrack().getTrack().getDuration()))
.append("]\n");
for(int i=0; i<handler.getQueue().size(); i++)
builder.append("\n").append(i+1).append(". ").append(handler.getQueue().get(i).getTrack().getInfo().title);
}
guildQueue.setText(builder.toString());
guildQueue.updateUI();
}*/
}
@@ -6,6 +6,7 @@
package com.jagrosh.jmusicbot.playlist;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
@@ -32,11 +33,13 @@ public class Playlist {
private final List<String> items;
private List<AudioTrack> tracks;
private List<PlaylistLoadError> errors;
private final boolean shuffle;
private Playlist(String name, List<String> items)
private Playlist(String name, List<String> items, boolean shuffle)
{
this.name = name;
this.items = items;
this.shuffle = shuffle;
}
public void loadTracks(AudioPlayerManager manager, Consumer<AudioTrack> consumer, Runnable callback)
@@ -52,8 +55,13 @@ public class Playlist {
manager.loadItemOrdered(name, items.get(i), new AudioLoadResultHandler() {
@Override
public void trackLoaded(AudioTrack at) {
tracks.add(at);
consumer.accept(at);
if(AudioHandler.isTooLong(at))
errors.add(new PlaylistLoadError(index, items.get(index), "This track is longer than the allowed maximum"));
else
{
tracks.add(at);
consumer.accept(at);
}
if(last)
{
if(callback!=null)
@@ -64,18 +72,38 @@ public class Playlist {
public void playlistLoaded(AudioPlaylist ap) {
if(ap.isSearchResult())
{
tracks.add(ap.getTracks().get(0));
consumer.accept(ap.getTracks().get(0));
if(AudioHandler.isTooLong(ap.getTracks().get(0)))
errors.add(new PlaylistLoadError(index, items.get(index), "This track is longer than the allowed maximum"));
else
{
tracks.add(ap.getTracks().get(0));
consumer.accept(ap.getTracks().get(0));
}
}
else if(ap.getSelectedTrack()!=null)
{
tracks.add(ap.getSelectedTrack());
consumer.accept(ap.getSelectedTrack());
if(AudioHandler.isTooLong(ap.getSelectedTrack()))
errors.add(new PlaylistLoadError(index, items.get(index), "This track is longer than the allowed maximum"));
else
{
tracks.add(ap.getSelectedTrack());
consumer.accept(ap.getSelectedTrack());
}
}
else
{
tracks.addAll(ap.getTracks());
ap.getTracks().forEach(at -> consumer.accept(at));
List<AudioTrack> loaded = new ArrayList<>(ap.getTracks());
if(shuffle)
for(int first =0; first<loaded.size(); first++)
{
int second = (int)(Math.random()*loaded.size());
AudioTrack tmp = loaded.get(first);
loaded.set(first, loaded.get(second));
loaded.set(second, tmp);
}
loaded.removeIf(track -> AudioHandler.isTooLong(track));
tracks.addAll(loaded);
loaded.forEach(at -> consumer.accept(at));
}
if(last)
{
@@ -202,7 +230,7 @@ public class Playlist {
list.set(second, tmp);
}
}
return new Playlist(name, list);
return new Playlist(name, list, shuffle[0]);
}
else
{
@@ -27,13 +27,13 @@ import java.util.Set;
*/
public class FairQueue<T extends Queueable> {
private final List<T> list = new ArrayList<>();
private final Set<String> set = new HashSet<>();
private final Set<Long> set = new HashSet<>();
public int add(T item)
{
int lastIndex;
for(lastIndex=list.size()-1; lastIndex>-1; lastIndex--)
if(list.get(lastIndex).getIdentifier().equals(item.getIdentifier()))
if(list.get(lastIndex).getIdentifier()==item.getIdentifier())
break;
lastIndex++;
set.clear();
@@ -77,12 +77,12 @@ public class FairQueue<T extends Queueable> {
return list.remove(index);
}
public int removeAll(String identifier)
public int removeAll(long identifier)
{
int count = 0;
for(int i=list.size()-1; i>=0; i--)
{
if(list.get(i).getIdentifier().equals(identifier))
if(list.get(i).getIdentifier()==identifier)
{
list.remove(i);
count++;
@@ -96,12 +96,12 @@ public class FairQueue<T extends Queueable> {
list.clear();
}
public int shuffle(String identifier)
public int shuffle(long identifier)
{
List<Integer> iset = new ArrayList<>();
for(int i=0; i<list.size(); i++)
{
if(list.get(i).getIdentifier().equals(identifier))
if(list.get(i).getIdentifier()==identifier)
iset.add(i);
}
for(int j=0; j<iset.size(); j++)
@@ -1,25 +1,25 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* 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
*
* http://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.
*/
package com.jagrosh.jmusicbot.queue;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public interface Queueable {
public String getIdentifier();
}
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* 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
*
* http://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.
*/
package com.jagrosh.jmusicbot.queue;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public interface Queueable {
public long getIdentifier();
}
@@ -18,7 +18,12 @@ package com.jagrosh.jmusicbot.utils;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import java.util.List;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import com.sedmelluq.discord.lavaplayer.source.youtube.YoutubeAudioTrack;
import net.dv8tion.jda.core.EmbedBuilder;
import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.MessageBuilder;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.entities.Message;
import net.dv8tion.jda.core.entities.Role;
import net.dv8tion.jda.core.entities.TextChannel;
import net.dv8tion.jda.core.entities.User;
@@ -30,8 +35,6 @@ import net.dv8tion.jda.core.entities.VoiceChannel;
*/
public class FormatUtil {
public static boolean NO_PROGRESS_BAR_IN_TOPIC = false;
public static String formatTime(long duration)
{
if(duration == Long.MAX_VALUE)
@@ -44,7 +47,44 @@ public class FormatUtil {
return (hours>0 ? hours+":" : "") + (minutes<10 ? "0"+minutes : minutes) + ":" + (seconds<10 ? "0"+seconds : seconds);
}
public static String formattedAudio(AudioHandler handler, JDA jda)
public static Message nowPlayingMessage(Guild guild, String successEmoji)
{
MessageBuilder mb = new MessageBuilder();
mb.append(successEmoji+" **Now Playing...**");
EmbedBuilder eb = new EmbedBuilder();
AudioHandler ah = (AudioHandler)guild.getAudioManager().getSendingHandler();
eb.setColor(guild.getSelfMember().getColor());
if(ah==null || !ah.isMusicPlaying())
{
eb.setTitle("No music playing");
eb.setDescription("\u23F9 "+FormatUtil.progressBar(-1)+" "+FormatUtil.volumeIcon(ah==null?100:ah.getPlayer().getVolume()));
}
else
{
if(ah.getRequester()!=0)
{
User u = guild.getJDA().getUserById(ah.getRequester());
if(u==null)
eb.setAuthor("Unknown (ID:"+ah.getRequester()+")", null, null);
else
eb.setAuthor(u.getName()+"#"+u.getDiscriminator(), null, u.getEffectiveAvatarUrl());
}
try {
eb.setTitle(ah.getPlayer().getPlayingTrack().getInfo().title, ah.getPlayer().getPlayingTrack().getInfo().uri);
} catch(Exception e) {
eb.setTitle(ah.getPlayer().getPlayingTrack().getInfo().title);
}
if(!AudioHandler.USE_NP_REFRESH && ah.getPlayer().getPlayingTrack() instanceof YoutubeAudioTrack)
eb.setThumbnail("https://img.youtube.com/vi/"+ah.getPlayer().getPlayingTrack().getIdentifier()+"/mqdefault.jpg");
eb.setDescription(FormatUtil.embedFormat(ah));
}
return mb.setEmbed(eb.build()).build();
}
public static String topicFormat(AudioHandler handler, JDA jda)
{
if(handler==null)
return "No music playing\n\u23F9 "+progressBar(-1)+" "+volumeIcon(100);
@@ -52,28 +92,33 @@ public class FormatUtil {
return "No music playing\n\u23F9 "+progressBar(-1)+" "+volumeIcon(handler.getPlayer().getVolume());
else
{
String userid = handler.getCurrentTrack().getIdentifier();
AudioTrack track = handler.getCurrentTrack().getTrack();
long userid = handler.getRequester();
AudioTrack track = handler.getPlayer().getPlayingTrack();
String title = track.getInfo().title;
if(!NO_PROGRESS_BAR_IN_TOPIC && title.length()>30)
title = title.substring(0,27)+"...";
double progress = (double)track.getPosition()/track.getDuration();
String str = "**"+title+"** ["+(userid==null ? "autoplay" : "<@"+userid+">")+"]";
String str2 = "\n"+(handler.getPlayer().isPaused()?"\u23F8":"\u25B6")+" "
+(NO_PROGRESS_BAR_IN_TOPIC ? "["+formatTime(track.getDuration())+"] " :
progressBar(progress)+" ["+formatTime(track.getPosition()) + "/" + formatTime(track.getDuration())+"] ")
return "**"+title+"** ["+(userid==0 ? "autoplay" : "<@"+userid+">")+"]"
+ "\n"+(handler.getPlayer().isPaused()?"\u23F8":"\u25B6")+" "
+"["+formatTime(track.getDuration())+"] "
+volumeIcon(handler.getPlayer().getVolume());
return str+str2;
}
}
public static String embedformattedAudio(AudioHandler ah)
public static String embedFormat(AudioHandler handler)
{
return (ah.getPlayer().isPaused()?"\u23F8":"\u25B6")+" "+progressBar((double)ah.getCurrentTrack().getTrack().getPosition()/ah.getCurrentTrack().getTrack().getDuration())
+" `["+formatTime(ah.getCurrentTrack().getTrack().getPosition()) + "/" + formatTime(ah.getCurrentTrack().getTrack().getDuration()) +"]` "
+volumeIcon(ah.getPlayer().getVolume());
if(handler==null)
return "No music playing\n\u23F9 "+progressBar(-1)+" "+volumeIcon(100);
else if (!handler.isMusicPlaying())
return "No music playing\n\u23F9 "+progressBar(-1)+" "+volumeIcon(handler.getPlayer().getVolume());
else
{
AudioTrack track = handler.getPlayer().getPlayingTrack();
double progress = (double)track.getPosition()/track.getDuration();
return (handler.getPlayer().isPaused()?"\u23F8":"\u25B6")
+" "+progressBar(progress)
+" `["+formatTime(track.getPosition()) + "/" + formatTime(track.getDuration()) +"]` "
+volumeIcon(handler.getPlayer().getVolume());
}
}
public static String progressBar(double percent)
{
String str = "";