mirror of
https://github.com/chrisb09/MusicBot.git
synced 2026-11-05 17:02:35 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
474cc1eb3e | ||
|
|
a66af36224 | ||
|
|
4471746842 | ||
|
|
9944514fab | ||
|
|
4dc60784c1 | ||
|
|
2c75c051a7 | ||
|
|
5a5cfa4ca0 | ||
|
|
f96b3251cd |
No files matched your search
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot;
|
||||
|
||||
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 java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import me.jagrosh.jdautilities.commandclient.Command.Category;
|
||||
import me.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import me.jagrosh.jdautilities.waiter.EventWaiter;
|
||||
import me.jagrosh.jmusicbot.audio.AudioHandler;
|
||||
import me.jagrosh.jmusicbot.gui.GUI;
|
||||
import me.jagrosh.jmusicbot.utils.FormatUtil;
|
||||
import net.dv8tion.jda.core.JDA;
|
||||
import net.dv8tion.jda.core.Permission;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
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.hooks.ListenerAdapter;
|
||||
import net.dv8tion.jda.core.utils.PermissionUtil;
|
||||
import net.dv8tion.jda.core.utils.SimpleLog;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class Bot extends ListenerAdapter {
|
||||
|
||||
private final HashMap<String,Settings> settings;
|
||||
private final AudioPlayerManager manager;
|
||||
private final EventWaiter waiter;
|
||||
private final ScheduledExecutorService threadpool;
|
||||
private JDA jda;
|
||||
private GUI gui;
|
||||
//private GuildsPanel panel;
|
||||
public final Category MUSIC = new Category("Music");
|
||||
public final Category DJ = new Category("DJ", event ->
|
||||
{
|
||||
if(event.getGuild()==null)
|
||||
return true;
|
||||
if(PermissionUtil.checkPermission(event.getGuild(), event.getMember(), Permission.MANAGE_SERVER))
|
||||
return true;
|
||||
Role dj = event.getGuild().getRoleById(getSettings(event.getGuild()).getRoleId());
|
||||
return event.getMember().getRoles().contains(dj);
|
||||
});
|
||||
public final Category ADMIN = new Category("Admin", event ->
|
||||
{
|
||||
if(event.getGuild()==null)
|
||||
return true;
|
||||
return PermissionUtil.checkPermission(event.getGuild(), event.getMember(), Permission.MANAGE_SERVER);
|
||||
});
|
||||
public final Category OWNER = new Category("Owner");
|
||||
|
||||
public Bot(EventWaiter waiter)
|
||||
{
|
||||
this.waiter = waiter;
|
||||
this.settings = new HashMap<>();
|
||||
manager = new DefaultAudioPlayerManager();
|
||||
threadpool = Executors.newSingleThreadScheduledExecutor();
|
||||
AudioSourceManagers.registerRemoteSources(manager);
|
||||
try {
|
||||
JSONObject loadedSettings = new JSONObject(new String(Files.readAllBytes(Paths.get("serversettings.json"))));
|
||||
for(String id: loadedSettings.keySet())
|
||||
{
|
||||
JSONObject o = loadedSettings.getJSONObject(id);
|
||||
settings.put(id, new Settings(o.has("text_channel_id")?o.getString("text_channel_id"):null,
|
||||
o.has("voice_channel_id")?o.getString("voice_channel_id"):null,
|
||||
o.has("dj_role_id")?o.getString("dj_role_id"):null));
|
||||
}
|
||||
} catch(IOException | JSONException e) {
|
||||
SimpleLog.getLog("Settings").warn("Failed to load server settings: "+e);
|
||||
}
|
||||
}
|
||||
|
||||
public EventWaiter getWaiter()
|
||||
{
|
||||
return waiter;
|
||||
}
|
||||
|
||||
public AudioPlayerManager getAudioManager()
|
||||
{
|
||||
return manager;
|
||||
}
|
||||
|
||||
public int queueTrack(CommandEvent event, AudioTrack track)
|
||||
{
|
||||
return setUpHandler(event).addTrack(track, event.getAuthor());
|
||||
}
|
||||
|
||||
public AudioHandler setUpHandler(CommandEvent event)
|
||||
{
|
||||
AudioHandler handler;
|
||||
if(event.getGuild().getAudioManager().getSendingHandler()==null)
|
||||
{
|
||||
AudioPlayer player = manager.createPlayer();
|
||||
handler = new AudioHandler(player, event.getGuild());
|
||||
player.addListener(handler);
|
||||
event.getGuild().getAudioManager().setSendingHandler(handler);
|
||||
threadpool.scheduleWithFixedDelay(() -> updateTopic(event.getGuild(),handler), 0, 5, TimeUnit.SECONDS);
|
||||
}
|
||||
else
|
||||
{
|
||||
handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
private void updateTopic(Guild guild, AudioHandler handler)
|
||||
{
|
||||
TextChannel tchan = guild.getTextChannelById(getSettings(guild).getTextId());
|
||||
if(tchan!=null && PermissionUtil.checkPermission(tchan, guild.getSelfMember(), Permission.MANAGE_CHANNEL))
|
||||
{
|
||||
String otherText;
|
||||
if(tchan.getTopic()==null || tchan.getTopic().isEmpty())
|
||||
otherText = "";
|
||||
else if(tchan.getTopic().contains("\u200B"))
|
||||
otherText = tchan.getTopic().substring(tchan.getTopic().indexOf("\u200B")).trim();
|
||||
else
|
||||
otherText = "\n\u200B "+tchan.getTopic();
|
||||
String text = FormatUtil.formattedAudio(handler, guild.getJDA(), true)+otherText;
|
||||
if(!text.equals(tchan.getTopic()))
|
||||
tchan.getManager().setTopic(text).queue();
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown(){
|
||||
manager.shutdown();
|
||||
threadpool.shutdownNow();
|
||||
jda.getGuilds().stream().forEach(g -> {
|
||||
g.getAudioManager().closeAudioConnection();
|
||||
AudioHandler ah = (AudioHandler)g.getAudioManager().getSendingHandler();
|
||||
if(ah!=null)
|
||||
{
|
||||
ah.getQueue().clear();
|
||||
ah.getPlayer().destroy();
|
||||
updateTopic(g, ah);
|
||||
}
|
||||
});
|
||||
jda.shutdown();
|
||||
}
|
||||
|
||||
public void setGUI(GUI gui)
|
||||
{
|
||||
this.gui = gui;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShutdown(ShutdownEvent event) {
|
||||
if(gui!=null)
|
||||
gui.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReady(ReadyEvent event) {
|
||||
this.jda = event.getJDA();
|
||||
//if(panel!=null)
|
||||
// panel.updateList(event.getJDA().getGuilds());
|
||||
}
|
||||
|
||||
|
||||
// settings
|
||||
|
||||
public Settings getSettings(Guild guild)
|
||||
{
|
||||
return settings.getOrDefault(guild.getId(), Settings.DEFAULT_SETTINGS);
|
||||
}
|
||||
|
||||
public void setTextChannel(TextChannel channel)
|
||||
{
|
||||
Settings s = settings.get(channel.getGuild().getId());
|
||||
if(s==null)
|
||||
{
|
||||
settings.put(channel.getGuild().getId(), new Settings(channel.getId(),null,null));
|
||||
}
|
||||
else
|
||||
{
|
||||
s.setTextId(channel.getId());
|
||||
}
|
||||
writeSettings();
|
||||
}
|
||||
|
||||
public void setVoiceChannel(VoiceChannel channel)
|
||||
{
|
||||
Settings s = settings.get(channel.getGuild().getId());
|
||||
if(s==null)
|
||||
{
|
||||
settings.put(channel.getGuild().getId(), new Settings(null,channel.getId(),null));
|
||||
}
|
||||
else
|
||||
{
|
||||
s.setVoiceId(channel.getId());
|
||||
}
|
||||
writeSettings();
|
||||
}
|
||||
|
||||
public void setRole(Role role)
|
||||
{
|
||||
Settings s = settings.get(role.getGuild().getId());
|
||||
if(s==null)
|
||||
{
|
||||
settings.put(role.getGuild().getId(), new Settings(null,null,role.getId()));
|
||||
}
|
||||
else
|
||||
{
|
||||
s.setRoleId(role.getId());
|
||||
}
|
||||
writeSettings();
|
||||
}
|
||||
|
||||
public void clearTextChannel(Guild guild)
|
||||
{
|
||||
Settings s = getSettings(guild);
|
||||
if(s!=null)
|
||||
{
|
||||
if(s.getVoiceId()==null && s.getRoleId()==null)
|
||||
settings.remove(guild.getId());
|
||||
else
|
||||
s.setTextId(null);
|
||||
writeSettings();
|
||||
}
|
||||
}
|
||||
|
||||
public void clearVoiceChannel(Guild guild)
|
||||
{
|
||||
Settings s = getSettings(guild);
|
||||
if(s!=null)
|
||||
{
|
||||
if(s.getTextId()==null && s.getRoleId()==null)
|
||||
settings.remove(guild.getId());
|
||||
else
|
||||
s.setVoiceId(null);
|
||||
writeSettings();
|
||||
}
|
||||
}
|
||||
|
||||
public void clearRole(Guild guild)
|
||||
{
|
||||
Settings s = getSettings(guild);
|
||||
if(s!=null)
|
||||
{
|
||||
if(s.getVoiceId()==null && s.getTextId()==null)
|
||||
settings.remove(guild.getId());
|
||||
else
|
||||
s.setRoleId(null);
|
||||
writeSettings();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeSettings()
|
||||
{
|
||||
JSONObject obj = new JSONObject();
|
||||
settings.keySet().stream().forEach(key -> {
|
||||
JSONObject o = new JSONObject();
|
||||
Settings s = settings.get(key);
|
||||
if(s.getTextId()!=null)
|
||||
o.put("text_channel_id", s.getTextId());
|
||||
if(s.getVoiceId()!=null)
|
||||
o.put("voice_channel_id", s.getVoiceId());
|
||||
if(s.getRoleId()!=null)
|
||||
o.put("dj_role_id", s.getRoleId());
|
||||
obj.put(key, o);
|
||||
});
|
||||
try {
|
||||
Files.write(Paths.get("serversettings.json"), obj.toString(4).getBytes());
|
||||
} catch(IOException ex){
|
||||
SimpleLog.getLog("Settings").warn("Failed to write to file: "+ex);
|
||||
}
|
||||
}
|
||||
|
||||
//gui stuff
|
||||
/*public void registerPanel(GuildsPanel panel)
|
||||
{
|
||||
this.panel = panel;
|
||||
threadpool.scheduleWithFixedDelay(() -> updatePanel(), 0, 5, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public void updatePanel()
|
||||
{
|
||||
System.out.println("updating...");
|
||||
Guild guild = jda.getGuilds().get(panel.getIndex());
|
||||
panel.updatePanel((AudioHandler)guild.getAudioManager().getSendingHandler());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGuildJoin(GuildJoinEvent event) {
|
||||
if(panel!=null)
|
||||
panel.updateList(event.getJDA().getGuilds());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGuildLeave(GuildLeaveEvent event) {
|
||||
if(panel!=null)
|
||||
panel.updateList(event.getJDA().getGuilds());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShutdown(ShutdownEvent event) {
|
||||
((GUI)panel.getTopLevelAncestor()).dispose();
|
||||
}*/
|
||||
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot;
|
||||
|
||||
import java.io.IOException;
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
*/
|
||||
public class Config {
|
||||
private final boolean nogui;
|
||||
private String prefix;
|
||||
private String token;
|
||||
private String owner;
|
||||
private String success;
|
||||
private String warning;
|
||||
private String error;
|
||||
|
||||
public Config(boolean nogui)
|
||||
{
|
||||
this.nogui = nogui;
|
||||
List<String> lines;
|
||||
try {
|
||||
lines = Files.readAllLines(Paths.get("config.txt"));
|
||||
for(String line: lines)
|
||||
{
|
||||
String[] parts = line.split("=",2);
|
||||
String key = parts[0].trim().toLowerCase();
|
||||
String value = parts.length>1 ? parts[1].trim() : null;
|
||||
switch(key)
|
||||
{
|
||||
case "token":
|
||||
token = value;
|
||||
break;
|
||||
case "prefix":
|
||||
prefix = value;
|
||||
break;
|
||||
case "owner":
|
||||
owner = value;
|
||||
break;
|
||||
case "success":
|
||||
success = value;
|
||||
break;
|
||||
case "warning":
|
||||
warning = value;
|
||||
break;
|
||||
case "error":
|
||||
error = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
alert("'config.txt' was not found!");
|
||||
lines = new LinkedList<>();
|
||||
}
|
||||
boolean write = false;
|
||||
if(token==null || token.isEmpty())
|
||||
{
|
||||
token = prompt("Please provide a bot token."
|
||||
+ "\nInstructions for obtaining a token can be found here:"
|
||||
+ "\nhttps://github.com/jagrosh/MusicBot/wiki/Getting-a-Bot-Token."
|
||||
+ "\nBot Token: ");
|
||||
if(token==null)
|
||||
{
|
||||
alert("No token provided! Exiting.");
|
||||
System.exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
lines.add("token="+token);
|
||||
write = true;
|
||||
}
|
||||
}
|
||||
if(owner==null || !owner.matches("\\d{17,20}"))
|
||||
{
|
||||
owner = prompt("Owner ID was missing, or the provided owner ID is not valid."
|
||||
+ "\nPlease provide the User ID of the bot's owner."
|
||||
+ "\nInstructions for obtaining your User ID can be found here:"
|
||||
+ "\nhttps://github.com/jagrosh/MusicBot/wiki/Finding-Your-User-ID"
|
||||
+ "\nOwner User ID: ");
|
||||
if(owner==null || !owner.matches("\\d{17,20}"))
|
||||
{
|
||||
alert("Invalid User ID! Exiting.");
|
||||
System.exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
lines.add("owner="+owner);
|
||||
write = true;
|
||||
}
|
||||
}
|
||||
if(write)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
lines.stream().forEach(s -> builder.append(s).append("\r\n"));
|
||||
try {
|
||||
Files.write(Paths.get("config.txt"), builder.toString().trim().getBytes());
|
||||
} catch(IOException ex) {
|
||||
alert("Failed to write new config options to config.txt: "+ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getPrefix()
|
||||
{
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public String getToken()
|
||||
{
|
||||
return token;
|
||||
}
|
||||
|
||||
public String getOwnerId()
|
||||
{
|
||||
return owner;
|
||||
}
|
||||
|
||||
public String getSuccess()
|
||||
{
|
||||
return success==null ? "\uD83C\uDFB6" : success;
|
||||
}
|
||||
|
||||
public String getWarning()
|
||||
{
|
||||
return warning==null ? "\uD83D\uDCA1" : warning;
|
||||
}
|
||||
|
||||
public String getError()
|
||||
{
|
||||
return error==null ? "\uD83D\uDEAB" : error;
|
||||
}
|
||||
|
||||
private void alert(String message)
|
||||
{
|
||||
if(nogui)
|
||||
System.out.println("[WARNING] "+message);
|
||||
else
|
||||
{
|
||||
JOptionPane.showMessageDialog(null, message, "JMusicBot", JOptionPane.WARNING_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
private String prompt(String content)
|
||||
{
|
||||
if(nogui)
|
||||
{
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
System.out.println(content);
|
||||
return scanner.next();
|
||||
}
|
||||
else
|
||||
{
|
||||
return JOptionPane.showInputDialog(null, content, "JMusicBot", JOptionPane.WARNING_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot;
|
||||
|
||||
import java.awt.Color;
|
||||
import javax.security.auth.login.LoginException;
|
||||
import me.jagrosh.jdautilities.commandclient.CommandClient;
|
||||
import me.jagrosh.jdautilities.commandclient.CommandClientBuilder;
|
||||
import me.jagrosh.jdautilities.commandclient.examples.*;
|
||||
import me.jagrosh.jdautilities.waiter.EventWaiter;
|
||||
import me.jagrosh.jmusicbot.commands.*;
|
||||
import me.jagrosh.jmusicbot.gui.GUI;
|
||||
import net.dv8tion.jda.core.AccountType;
|
||||
import net.dv8tion.jda.core.JDABuilder;
|
||||
import net.dv8tion.jda.core.OnlineStatus;
|
||||
import net.dv8tion.jda.core.entities.Game;
|
||||
import net.dv8tion.jda.core.exceptions.RateLimitedException;
|
||||
import net.dv8tion.jda.core.utils.SimpleLog;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
*/
|
||||
public class JMusicBot {
|
||||
|
||||
/**
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(String[] args){
|
||||
// check run mode(s)
|
||||
boolean nogui = false;
|
||||
for(String arg: args)
|
||||
if("-nogui".equalsIgnoreCase(arg))
|
||||
nogui = true;
|
||||
|
||||
// load config
|
||||
Config config = new Config(nogui);
|
||||
|
||||
// set up the listener
|
||||
EventWaiter waiter = new EventWaiter();
|
||||
Bot bot = new Bot(waiter);
|
||||
|
||||
// set up the command client
|
||||
CommandClient client = new CommandClientBuilder()
|
||||
.setPrefix(config.getPrefix())
|
||||
.setOwnerId(config.getOwnerId())
|
||||
.setEmojis(config.getSuccess(), config.getWarning(), config.getError())
|
||||
.addCommands(
|
||||
new AboutCommand(Color.BLUE.brighter(),
|
||||
"a music bot that is [easy to host yourself!](https://github.com/jagrosh/MusicBot)",
|
||||
"https://github.com/jagrosh/MusicBot",
|
||||
new String[]{"High-quality music playback", "FairQueue™ Technology", "Easy to host yourself"}),
|
||||
new PingCommand(),
|
||||
new SettingsCmd(bot),
|
||||
|
||||
new NowplayingCmd(bot),
|
||||
new PlayCmd(bot),
|
||||
new QueueCmd(bot),
|
||||
new RemoveCmd(bot),
|
||||
new SearchCmd(bot),
|
||||
new SkipCmd(bot),
|
||||
|
||||
new ForceskipCmd(bot),
|
||||
new StopCmd(bot),
|
||||
new VolumeCmd(bot),
|
||||
|
||||
new SetdjCmd(bot),
|
||||
new SettcCmd(bot),
|
||||
new SetvcCmd(bot),
|
||||
|
||||
new SetavatarCmd(bot),
|
||||
new SetnameCmd(bot),
|
||||
new ShutdownCmd(bot)
|
||||
).build();
|
||||
|
||||
|
||||
if(!nogui)
|
||||
{
|
||||
GUI gui = new GUI(bot);
|
||||
bot.setGUI(gui);
|
||||
gui.init();
|
||||
}
|
||||
|
||||
// attempt to log in and start
|
||||
try {
|
||||
new JDABuilder(AccountType.BOT)
|
||||
.setToken(config.getToken())
|
||||
.setAudioEnabled(true)
|
||||
.setGame(Game.of("loading..."))
|
||||
.setStatus(OnlineStatus.DO_NOT_DISTURB)
|
||||
.addListener(client)
|
||||
.addListener(waiter)
|
||||
.addListener(bot)
|
||||
.buildAsync();
|
||||
} catch (LoginException | IllegalArgumentException | RateLimitedException ex) {
|
||||
SimpleLog.getLog("Login").fatal(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class Settings {
|
||||
public final static Settings DEFAULT_SETTINGS = new Settings(null, null, null);
|
||||
|
||||
private String textId;
|
||||
private String voiceId;
|
||||
private String roleId;
|
||||
|
||||
public Settings(String textId, String voiceId, String roleId)
|
||||
{
|
||||
this.textId = textId;
|
||||
this.voiceId = voiceId;
|
||||
this.roleId = roleId;
|
||||
}
|
||||
|
||||
public String getTextId()
|
||||
{
|
||||
return textId;
|
||||
}
|
||||
|
||||
public String getVoiceId()
|
||||
{
|
||||
return voiceId;
|
||||
}
|
||||
|
||||
public String getRoleId()
|
||||
{
|
||||
return roleId;
|
||||
}
|
||||
|
||||
public void setTextId(String id)
|
||||
{
|
||||
this.textId = id;
|
||||
}
|
||||
|
||||
public void setVoiceId(String id)
|
||||
{
|
||||
this.voiceId = id;
|
||||
}
|
||||
|
||||
public void setRoleId(String id)
|
||||
{
|
||||
this.roleId = id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.audio;
|
||||
|
||||
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 com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import me.jagrosh.jmusicbot.queue.FairQueue;
|
||||
import net.dv8tion.jda.core.audio.AudioSendHandler;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.User;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class AudioHandler extends AudioEventAdapter implements AudioSendHandler {
|
||||
private final AudioPlayer audioPlayer;
|
||||
private final Guild guild;
|
||||
private final FairQueue<QueuedTrack> queue;
|
||||
private final Set<String> votes;
|
||||
private AudioFrame lastFrame;
|
||||
private QueuedTrack current;
|
||||
|
||||
public AudioHandler(AudioPlayer audioPlayer, Guild guild) {
|
||||
this.audioPlayer = audioPlayer;
|
||||
this.guild = guild;
|
||||
queue = new FairQueue<>();
|
||||
votes = new HashSet<>();
|
||||
}
|
||||
|
||||
public int addTrack(AudioTrack track, User user)
|
||||
{
|
||||
QueuedTrack qt = new QueuedTrack(track, user.getId());
|
||||
if(current==null)
|
||||
{
|
||||
current = qt;
|
||||
audioPlayer.playTrack(track);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return queue.add(qt);
|
||||
}
|
||||
}
|
||||
|
||||
public QueuedTrack getCurrentTrack()
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
public FairQueue<QueuedTrack> getQueue()
|
||||
{
|
||||
return queue;
|
||||
}
|
||||
|
||||
public Set<String> getVotes()
|
||||
{
|
||||
return votes;
|
||||
}
|
||||
|
||||
public AudioPlayer getPlayer()
|
||||
{
|
||||
return audioPlayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) {
|
||||
if(queue.isEmpty())
|
||||
{
|
||||
current = null;
|
||||
guild.getAudioManager().closeAudioConnection();
|
||||
}
|
||||
else
|
||||
{
|
||||
current = queue.pull();
|
||||
player.playTrack(current.getTrack());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrackStart(AudioPlayer player, AudioTrack track) {
|
||||
votes.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProvide() {
|
||||
lastFrame = audioPlayer.provide();
|
||||
return lastFrame != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] provide20MsAudio() {
|
||||
return lastFrame.data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpus() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +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 me.jagrosh.jmusicbot.audio;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
import me.jagrosh.jmusicbot.queue.Queueable;
|
||||
import me.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+">";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.commands;
|
||||
|
||||
import me.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import me.jagrosh.jmusicbot.Bot;
|
||||
import me.jagrosh.jmusicbot.audio.AudioHandler;
|
||||
import net.dv8tion.jda.core.entities.User;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class ForceskipCmd extends MusicCommand {
|
||||
|
||||
public ForceskipCmd(Bot bot)
|
||||
{
|
||||
super(bot);
|
||||
this.name = "forceskip";
|
||||
this.help = "skips the current song";
|
||||
this.aliases = new String[]{"modskip"};
|
||||
this.bePlaying = true;
|
||||
this.category = bot.DJ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCommand(CommandEvent event) {
|
||||
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
|
||||
User u = event.getJDA().getUserById(handler.getCurrentTrack().getIdentifier());
|
||||
event.reply(event.getClient().getSuccess()+" Skipped **"+handler.getCurrentTrack().getTrack().getInfo().title
|
||||
+"** (requested by "+(u==null ? "someone" : "**"+u.getName()+"**")+")");
|
||||
handler.getPlayer().stopTrack();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.commands;
|
||||
|
||||
import me.jagrosh.jdautilities.commandclient.Command;
|
||||
import me.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import me.jagrosh.jmusicbot.Bot;
|
||||
import me.jagrosh.jmusicbot.Settings;
|
||||
import me.jagrosh.jmusicbot.audio.AudioHandler;
|
||||
import net.dv8tion.jda.core.entities.GuildVoiceState;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||
import net.dv8tion.jda.core.exceptions.PermissionException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public abstract class MusicCommand extends Command {
|
||||
|
||||
protected final Bot bot;
|
||||
protected boolean bePlaying;
|
||||
protected boolean beListening;
|
||||
|
||||
public MusicCommand(Bot bot)
|
||||
{
|
||||
this.bot = bot;
|
||||
this.guildOnly = true;
|
||||
this.category = bot.MUSIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(CommandEvent event) {
|
||||
Settings settings = bot.getSettings(event.getGuild());
|
||||
TextChannel tchannel = event.getGuild().getTextChannelById(settings.getTextId());
|
||||
if(tchannel!=null && !event.getTextChannel().equals(tchannel))
|
||||
{
|
||||
try {
|
||||
event.getMessage().deleteMessage().queue();
|
||||
} catch(PermissionException e){}
|
||||
event.replyInDM(event.getClient().getError()+" You can only use that command in <#"+settings.getTextId()+">!");
|
||||
return;
|
||||
}
|
||||
if(bePlaying
|
||||
&& (event.getGuild().getAudioManager().getSendingHandler()==null
|
||||
|| ((AudioHandler)event.getGuild().getAudioManager().getSendingHandler()).getCurrentTrack()==null))
|
||||
{
|
||||
event.reply(event.getClient().getError()+" There must be music playing to use that!");
|
||||
return;
|
||||
}
|
||||
if(beListening)
|
||||
{
|
||||
VoiceChannel current = event.getGuild().getSelfMember().getVoiceState().getChannel();
|
||||
if(current==null)
|
||||
current = event.getGuild().getVoiceChannelById(settings.getVoiceId());
|
||||
GuildVoiceState userState = event.getMember().getVoiceState();
|
||||
if(!userState.inVoiceChannel() || userState.isDeafened() || (current!=null && !userState.getChannel().equals(current)))
|
||||
{
|
||||
event.reply(event.getClient().getError()
|
||||
+" You must be listening in "+(current==null ? "a voice channel" : "**"+current.getName()+"**")
|
||||
+" to use that!");
|
||||
return;
|
||||
}
|
||||
if(current==null)
|
||||
event.getGuild().getAudioManager().openAudioConnection(userState.getChannel());
|
||||
}
|
||||
doCommand(event);
|
||||
}
|
||||
|
||||
public abstract void doCommand(CommandEvent event);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.commands;
|
||||
|
||||
import me.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import me.jagrosh.jmusicbot.Bot;
|
||||
import me.jagrosh.jmusicbot.audio.AudioHandler;
|
||||
import me.jagrosh.jmusicbot.utils.FormatUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class NowplayingCmd extends MusicCommand {
|
||||
|
||||
public NowplayingCmd(Bot bot)
|
||||
{
|
||||
super(bot);
|
||||
this.name = "nowplaying";
|
||||
this.help = "shows the song that is currently playing";
|
||||
this.aliases = new String[]{"np","current"};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCommand(CommandEvent event) {
|
||||
event.reply(FormatUtil.formattedAudio((AudioHandler)event.getGuild().getAudioManager().getSendingHandler(), event.getJDA(), false));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.commands;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
|
||||
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
|
||||
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException.Severity;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
import me.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import me.jagrosh.jmusicbot.Bot;
|
||||
import me.jagrosh.jmusicbot.utils.FormatUtil;
|
||||
import net.dv8tion.jda.core.entities.Message;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class PlayCmd extends MusicCommand {
|
||||
|
||||
public PlayCmd(Bot bot)
|
||||
{
|
||||
super(bot);
|
||||
this.name = "play";
|
||||
this.arguments = "<title|URL>";
|
||||
this.help = "plays the provided song";
|
||||
this.beListening = true;
|
||||
this.bePlaying = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCommand(CommandEvent event) {
|
||||
if(event.getArgs().isEmpty())
|
||||
{
|
||||
event.reply(event.getClient().getError()+" Please include a url or song title.");
|
||||
return;
|
||||
}
|
||||
String args = event.getArgs().startsWith("<") && event.getArgs().endsWith(">")
|
||||
? event.getArgs().substring(1,event.getArgs().length()-1)
|
||||
: event.getArgs();
|
||||
event.getChannel().sendMessage("\u231A Loading... `["+args+"]`").queue(m -> {
|
||||
bot.getAudioManager().loadItemOrdered(event.getGuild(), args, new ResultHandler(m,event,false));
|
||||
});
|
||||
}
|
||||
|
||||
private class ResultHandler implements AudioLoadResultHandler {
|
||||
final Message m;
|
||||
final CommandEvent event;
|
||||
final boolean ytsearch;
|
||||
private ResultHandler(Message m, CommandEvent event, boolean ytsearch)
|
||||
{
|
||||
this.m = m;
|
||||
this.event = event;
|
||||
this.ytsearch = ytsearch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trackLoaded(AudioTrack track) {
|
||||
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"
|
||||
: " to the queue at position "+pos)).queue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playlistLoaded(AudioPlaylist playlist) {
|
||||
if(playlist.getTracks().size()==1 || playlist.isSearchResult() || playlist.getSelectedTrack()!=null)
|
||||
{
|
||||
AudioTrack single = playlist.getSelectedTrack()==null?playlist.getTracks().get(0):playlist.getSelectedTrack();
|
||||
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"
|
||||
: " to the queue at position "+pos)).queue();
|
||||
}
|
||||
else
|
||||
{
|
||||
m.editMessage(event.getClient().getSuccess()+" Found "
|
||||
+(playlist.getName()==null?"a playlist":"playlist **"+playlist.getName()+"**")+" with `"
|
||||
+playlist.getTracks().size()+"` entries; adding to the queue.").queue();
|
||||
playlist.getTracks().stream().forEach((track) -> {
|
||||
bot.queueTrack(event, track);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void noMatches() {
|
||||
if(ytsearch)
|
||||
m.editMessage(event.getClient().getWarning()+" No results found for `"+event.getArgs()+"`.").queue();
|
||||
else
|
||||
bot.getAudioManager().loadItemOrdered(event.getGuild(), "ytsearch:"+event.getArgs(), new ResultHandler(m,event,true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadFailed(FriendlyException throwable) {
|
||||
if(throwable.severity==Severity.COMMON)
|
||||
m.editMessage(event.getClient().getError()+" Error loading: "+throwable.getMessage()).queue();
|
||||
else
|
||||
m.editMessage(event.getClient().getError()+" Error loading track.").queue();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.commands;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import me.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import me.jagrosh.jdautilities.menu.pagination.PaginatorBuilder;
|
||||
import me.jagrosh.jmusicbot.Bot;
|
||||
import me.jagrosh.jmusicbot.audio.AudioHandler;
|
||||
import me.jagrosh.jmusicbot.audio.QueuedTrack;
|
||||
import me.jagrosh.jmusicbot.utils.FormatUtil;
|
||||
import net.dv8tion.jda.core.Permission;
|
||||
import net.dv8tion.jda.core.exceptions.PermissionException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class QueueCmd extends MusicCommand {
|
||||
|
||||
private final PaginatorBuilder builder;
|
||||
public QueueCmd(Bot bot)
|
||||
{
|
||||
super(bot);
|
||||
this.name = "queue";
|
||||
this.help = "shows the current queue";
|
||||
this.arguments = "[pagenum]";
|
||||
this.aliases = new String[]{"list"};
|
||||
this.bePlaying = true;
|
||||
this.botPermissions = new Permission[]{Permission.MESSAGE_ADD_REACTION,Permission.MESSAGE_EMBED_LINKS};
|
||||
builder = new PaginatorBuilder()
|
||||
.setColumns(1)
|
||||
.setFinalAction(m -> {try{m.clearReactions().queue();}catch(PermissionException e){}})
|
||||
.setItemsPerPage(10)
|
||||
.waitOnSinglePage(false)
|
||||
.useNumberedItems(true)
|
||||
.showPageNumbers(true)
|
||||
.setEventWaiter(bot.getWaiter())
|
||||
.setTimeout(1, TimeUnit.MINUTES)
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCommand(CommandEvent event) {
|
||||
int pagenum = 1;
|
||||
try{
|
||||
pagenum = Integer.parseInt(event.getArgs());
|
||||
}catch(NumberFormatException e){}
|
||||
List<QueuedTrack> list = ((AudioHandler)event.getGuild().getAudioManager().getSendingHandler()).getQueue().getList();
|
||||
if(list.isEmpty())
|
||||
{
|
||||
event.reply(event.getClient().getWarning()+" There is no music in the queue!");
|
||||
return;
|
||||
}
|
||||
String[] songs = new String[list.size()];
|
||||
long total = 0;
|
||||
for(int i=0; i<list.size(); i++)
|
||||
{
|
||||
total += list.get(i).getTrack().getDuration();
|
||||
songs[i] = list.get(i).toString();
|
||||
}
|
||||
builder.setText(event.getClient().getSuccess()+" Current Queue | "+songs.length+" entries | `"+FormatUtil.formatTime(total)+"` ")
|
||||
.setItems(songs)
|
||||
.setUsers(event.getAuthor())
|
||||
.setColor(event.getSelfMember().getColor())
|
||||
;
|
||||
builder.build().paginate(event.getChannel(), pagenum);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.commands;
|
||||
|
||||
import me.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import me.jagrosh.jmusicbot.Bot;
|
||||
import me.jagrosh.jmusicbot.audio.AudioHandler;
|
||||
import me.jagrosh.jmusicbot.audio.QueuedTrack;
|
||||
import net.dv8tion.jda.core.Permission;
|
||||
import net.dv8tion.jda.core.entities.Role;
|
||||
import net.dv8tion.jda.core.entities.User;
|
||||
import net.dv8tion.jda.core.utils.PermissionUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class RemoveCmd extends MusicCommand {
|
||||
|
||||
public RemoveCmd(Bot bot)
|
||||
{
|
||||
super(bot);
|
||||
this.name = "remove";
|
||||
this.help = "removes a song from the queue";
|
||||
this.arguments = "<position>";
|
||||
this.aliases = new String[]{"delete"};
|
||||
this.beListening = true;
|
||||
this.bePlaying = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCommand(CommandEvent event) {
|
||||
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
|
||||
if(handler.getQueue().isEmpty())
|
||||
{
|
||||
event.reply(event.getClient().getError()+" There is nothing in the queue!");
|
||||
return;
|
||||
}
|
||||
int pos;
|
||||
try {
|
||||
pos = Integer.parseInt(event.getArgs());
|
||||
} catch(NumberFormatException e) {
|
||||
pos = 0;
|
||||
}
|
||||
if(pos<1 || pos>handler.getQueue().size())
|
||||
{
|
||||
event.reply(event.getClient().getError()+" Position must be a valid integer between 1 and "+handler.getQueue().size()+"!");
|
||||
return;
|
||||
}
|
||||
boolean isDJ = PermissionUtil.checkPermission(event.getGuild(), event.getMember(), Permission.MANAGE_SERVER);
|
||||
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()))
|
||||
{
|
||||
handler.getQueue().remove(pos-1);
|
||||
event.reply(event.getClient().getSuccess()+" Removed **"+qt.getTrack().getInfo().title+"** from the queue");
|
||||
}
|
||||
else if(isDJ)
|
||||
{
|
||||
handler.getQueue().remove(pos-1);
|
||||
User u = event.getJDA().getUserById(qt.getIdentifier());
|
||||
event.reply(event.getClient().getSuccess()+" Removed **"+qt.getTrack().getInfo().title
|
||||
+"** from the queue (requested by "+(u==null ? "someone" : "**"+u.getName()+"**")+")");
|
||||
}
|
||||
else
|
||||
{
|
||||
event.reply(event.getClient().getError()+" You cannot remove **"+qt.getTrack().getInfo().title+"** because you didn't add it!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.commands;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
|
||||
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
|
||||
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException.Severity;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import me.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import me.jagrosh.jdautilities.menu.orderedmenu.OrderedMenuBuilder;
|
||||
import me.jagrosh.jmusicbot.Bot;
|
||||
import me.jagrosh.jmusicbot.utils.FormatUtil;
|
||||
import net.dv8tion.jda.core.Permission;
|
||||
import net.dv8tion.jda.core.entities.Message;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class SearchCmd extends MusicCommand {
|
||||
|
||||
private final OrderedMenuBuilder builder;
|
||||
public SearchCmd(Bot bot)
|
||||
{
|
||||
super(bot);
|
||||
this.name = "search";
|
||||
this.arguments = "<query>";
|
||||
this.help = "searches Youtube for a provided query";
|
||||
this.beListening = true;
|
||||
this.bePlaying = false;
|
||||
this.botPermissions = new Permission[]{Permission.MESSAGE_EMBED_LINKS};
|
||||
builder = new OrderedMenuBuilder()
|
||||
.allowTextInput(true)
|
||||
.useNumbers()
|
||||
.useCancelButton(true)
|
||||
.setEventWaiter(bot.getWaiter())
|
||||
.setTimeout(1, TimeUnit.MINUTES)
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCommand(CommandEvent event) {
|
||||
if(event.getArgs().isEmpty())
|
||||
{
|
||||
event.reply(event.getClient().getError()+" Please include a query.");
|
||||
return;
|
||||
}
|
||||
event.getChannel().sendMessage("\uD83D\uDD0E Searching... `["+event.getArgs()+"]`").queue(m -> {
|
||||
bot.getAudioManager().loadItemOrdered(event.getGuild(), "ytsearch:"+event.getArgs(), new ResultHandler(m,event));
|
||||
});
|
||||
}
|
||||
|
||||
private class ResultHandler implements AudioLoadResultHandler {
|
||||
final Message m;
|
||||
final CommandEvent event;
|
||||
private ResultHandler(Message m, CommandEvent event)
|
||||
{
|
||||
this.m = m;
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trackLoaded(AudioTrack track) {
|
||||
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"
|
||||
: " to the queue at position "+pos)).queue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playlistLoaded(AudioPlaylist playlist) {
|
||||
builder.setColor(event.getSelfMember().getColor())
|
||||
.setText(event.getClient().getSuccess()+" Search results for `"+event.getArgs()+"`:")
|
||||
.setChoices(new String[0])
|
||||
.setAction(i -> {
|
||||
AudioTrack track = playlist.getTracks().get(i-1);
|
||||
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"
|
||||
: " to the queue at position "+pos)).queue();
|
||||
})
|
||||
.setUsers(event.getAuthor())
|
||||
;
|
||||
for(int i=0; i<4&&i<playlist.getTracks().size(); i++)
|
||||
{
|
||||
AudioTrack track = playlist.getTracks().get(i);
|
||||
builder.addChoices("`["+FormatUtil.formatTime(track.getDuration())+"]` [**"
|
||||
+track.getInfo().title+"**](https://youtu.be/"+track.getIdentifier()+")");
|
||||
}
|
||||
builder.build().display(m);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void noMatches() {
|
||||
m.editMessage(event.getClient().getWarning()+" No results found for `"+event.getArgs()+"`.").queue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadFailed(FriendlyException throwable) {
|
||||
if(throwable.severity==Severity.COMMON)
|
||||
m.editMessage(event.getClient().getError()+" Error loading: "+throwable.getMessage()).queue();
|
||||
else
|
||||
m.editMessage(event.getClient().getError()+" Error loading track.").queue();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.commands;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import me.jagrosh.jdautilities.commandclient.Command;
|
||||
import me.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import me.jagrosh.jmusicbot.Bot;
|
||||
import me.jagrosh.jmusicbot.utils.OtherUtil;
|
||||
import net.dv8tion.jda.core.entities.Icon;
|
||||
import net.dv8tion.jda.core.exceptions.RateLimitedException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class SetavatarCmd extends Command {
|
||||
|
||||
public SetavatarCmd(Bot bot)
|
||||
{
|
||||
this.name = "setavatar";
|
||||
this.help = "sets the name of the bot";
|
||||
this.arguments = "<url>";
|
||||
this.ownerCommand = true;
|
||||
this.category = bot.OWNER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(CommandEvent event) {
|
||||
String url;
|
||||
if(event.getArgs().isEmpty())
|
||||
if(!event.getMessage().getAttachments().isEmpty() && event.getMessage().getAttachments().get(0).isImage())
|
||||
url = event.getMessage().getAttachments().get(0).getUrl();
|
||||
else
|
||||
url = null;
|
||||
else
|
||||
url = event.getArgs();
|
||||
InputStream s = OtherUtil.imageFromUrl(url);
|
||||
if(s==null)
|
||||
{
|
||||
event.reply(event.getClient().getError()+" Invalid or missing URL");
|
||||
}
|
||||
else
|
||||
{
|
||||
try {
|
||||
event.getSelfUser().getManager().setAvatar(Icon.from(s)).queue(
|
||||
v -> event.reply(event.getClient().getSuccess()+" Successfully changed avatar."),
|
||||
t -> event.reply(event.getClient().getError()+" Failed to set avatar."));
|
||||
} catch(IOException e) {
|
||||
event.reply(event.getClient().getError()+" Could not load from provided URL.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.commands;
|
||||
|
||||
import java.util.List;
|
||||
import me.jagrosh.jdautilities.commandclient.Command;
|
||||
import me.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import me.jagrosh.jmusicbot.Bot;
|
||||
import me.jagrosh.jmusicbot.utils.FinderUtil;
|
||||
import me.jagrosh.jmusicbot.utils.FormatUtil;
|
||||
import net.dv8tion.jda.core.entities.Role;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class SetdjCmd extends Command {
|
||||
|
||||
private final Bot bot;
|
||||
public SetdjCmd(Bot bot)
|
||||
{
|
||||
this.bot = bot;
|
||||
this.name = "setdj";
|
||||
this.help = "sets the DJ role for certain music commands";
|
||||
this.arguments = "<rolename|NONE>";
|
||||
this.guildOnly = true;
|
||||
this.category = bot.ADMIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(CommandEvent event) {
|
||||
if(event.getArgs().isEmpty())
|
||||
{
|
||||
event.reply(event.getClient().getError()+" Please include a role name or NONE");
|
||||
}
|
||||
else if(event.getArgs().equalsIgnoreCase("none"))
|
||||
{
|
||||
bot.clearTextChannel(event.getGuild());
|
||||
event.reply(event.getClient().getSuccess()+" DJ role cleared; Only Admins can use the DJ commands.");
|
||||
}
|
||||
else
|
||||
{
|
||||
List<Role> list = FinderUtil.findRole(event.getArgs(), event.getGuild());
|
||||
if(list.isEmpty())
|
||||
event.reply(event.getClient().getWarning()+" No Roles found matching \""+event.getArgs()+"\"");
|
||||
else if (list.size()>1)
|
||||
event.reply(event.getClient().getWarning()+FormatUtil.listOfRoles(list, event.getArgs()));
|
||||
else
|
||||
{
|
||||
bot.setRole(list.get(0));
|
||||
event.reply(event.getClient().getSuccess()+" DJ commands can now be used by users with the **"+list.get(0).getName()+"** role.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.commands;
|
||||
|
||||
import me.jagrosh.jdautilities.commandclient.Command;
|
||||
import me.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import me.jagrosh.jmusicbot.Bot;
|
||||
import net.dv8tion.jda.core.exceptions.RateLimitedException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class SetnameCmd extends Command {
|
||||
|
||||
public SetnameCmd(Bot bot)
|
||||
{
|
||||
this.name = "setname";
|
||||
this.help = "sets the name of the bot";
|
||||
this.arguments = "<name>";
|
||||
this.ownerCommand = true;
|
||||
this.category = bot.OWNER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(CommandEvent event) {
|
||||
try {
|
||||
String oldname = event.getSelfUser().getName();
|
||||
event.getSelfUser().getManager().setName(event.getArgs()).complete(false);
|
||||
event.reply(event.getClient().getSuccess()+" Name changed from `"+oldname+"` to `"+event.getArgs()+"`");
|
||||
} catch(RateLimitedException e) {
|
||||
event.reply(event.getClient().getError()+" Name can only be changed twice per hour!");
|
||||
} catch(Exception e) {
|
||||
event.reply(event.getClient().getError()+" That name is not valid!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.commands;
|
||||
|
||||
import java.util.List;
|
||||
import me.jagrosh.jdautilities.commandclient.Command;
|
||||
import me.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import me.jagrosh.jmusicbot.Bot;
|
||||
import me.jagrosh.jmusicbot.utils.FinderUtil;
|
||||
import me.jagrosh.jmusicbot.utils.FormatUtil;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class SettcCmd extends Command {
|
||||
|
||||
private final Bot bot;
|
||||
public SettcCmd(Bot bot)
|
||||
{
|
||||
this.bot = bot;
|
||||
this.name = "settc";
|
||||
this.help = "sets the text channel for music commands";
|
||||
this.arguments = "<channel|NONE>";
|
||||
this.guildOnly = true;
|
||||
this.category = bot.ADMIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(CommandEvent event) {
|
||||
if(event.getArgs().isEmpty())
|
||||
{
|
||||
event.reply(event.getClient().getError()+" Please include a text channel or NONE");
|
||||
}
|
||||
else if(event.getArgs().equalsIgnoreCase("none"))
|
||||
{
|
||||
bot.clearTextChannel(event.getGuild());
|
||||
event.reply(event.getClient().getSuccess()+" Music commands can now be used in any channel");
|
||||
}
|
||||
else
|
||||
{
|
||||
List<TextChannel> list = FinderUtil.findTextChannel(event.getArgs(), event.getGuild());
|
||||
if(list.isEmpty())
|
||||
event.reply(event.getClient().getWarning()+" No Text Channels found matching \""+event.getArgs()+"\"");
|
||||
else if (list.size()>1)
|
||||
event.reply(event.getClient().getWarning()+FormatUtil.listOfTChannels(list, event.getArgs()));
|
||||
else
|
||||
{
|
||||
bot.setTextChannel(list.get(0));
|
||||
event.reply(event.getClient().getSuccess()+" Music commands can now only be used in <#"+list.get(0).getId()+">");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.commands;
|
||||
|
||||
import me.jagrosh.jdautilities.commandclient.Command;
|
||||
import me.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import me.jagrosh.jmusicbot.Bot;
|
||||
import me.jagrosh.jmusicbot.Settings;
|
||||
import net.dv8tion.jda.core.EmbedBuilder;
|
||||
import net.dv8tion.jda.core.MessageBuilder;
|
||||
import net.dv8tion.jda.core.entities.Role;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class SettingsCmd extends Command {
|
||||
|
||||
private final Bot bot;
|
||||
public SettingsCmd(Bot bot)
|
||||
{
|
||||
this.bot = bot;
|
||||
this.name = "settings";
|
||||
this.help = "shows the bots settings";
|
||||
this.aliases = new String[]{"status"};
|
||||
this.guildOnly = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(CommandEvent event) {
|
||||
Settings s = bot.getSettings(event.getGuild());
|
||||
MessageBuilder builder = new MessageBuilder()
|
||||
.append("\uD83C\uDFA7 **")
|
||||
.append(event.getSelfUser().getName())
|
||||
.append("** settings:");
|
||||
TextChannel tchan = event.getGuild().getTextChannelById(s.getTextId());
|
||||
VoiceChannel vchan = event.getGuild().getVoiceChannelById(s.getVoiceId());
|
||||
Role role = event.getGuild().getRoleById(s.getRoleId());
|
||||
EmbedBuilder ebuilder = new EmbedBuilder()
|
||||
.setColor(event.getSelfMember().getColor())
|
||||
.setDescription("Text Channel: "+(tchan==null ? "Any" : "**#"+tchan.getName()+"**")
|
||||
+ "\nVoice Channel: "+(vchan==null ? "Any" : "**"+vchan.getName()+"**")
|
||||
+ "\nDJ Role: "+(role==null ? "None" : "**"+role.getName()+"**"))
|
||||
.setFooter(event.getJDA().getGuilds().size()+" servers | "
|
||||
+event.getJDA().getGuilds().stream().filter(g -> g.getSelfMember().getVoiceState().inVoiceChannel()).count()
|
||||
+" audio connections", null);
|
||||
event.getChannel().sendMessage(builder.setEmbed(ebuilder.build()).build()).queue();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.commands;
|
||||
|
||||
import java.util.List;
|
||||
import me.jagrosh.jdautilities.commandclient.Command;
|
||||
import me.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import me.jagrosh.jmusicbot.Bot;
|
||||
import me.jagrosh.jmusicbot.utils.FinderUtil;
|
||||
import me.jagrosh.jmusicbot.utils.FormatUtil;
|
||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class SetvcCmd extends Command {
|
||||
|
||||
private final Bot bot;
|
||||
public SetvcCmd(Bot bot)
|
||||
{
|
||||
this.bot = bot;
|
||||
this.name = "setvc";
|
||||
this.help = "sets the voice channel for playing music";
|
||||
this.arguments = "<channel|NONE>";
|
||||
this.guildOnly = true;
|
||||
this.category = bot.ADMIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(CommandEvent event) {
|
||||
if(event.getArgs().isEmpty())
|
||||
{
|
||||
event.reply(event.getClient().getError()+" Please include a voice channel or NONE");
|
||||
}
|
||||
else if(event.getArgs().equalsIgnoreCase("none"))
|
||||
{
|
||||
bot.clearVoiceChannel(event.getGuild());
|
||||
event.reply(event.getClient().getSuccess()+" Music can now be played in any channel");
|
||||
}
|
||||
else
|
||||
{
|
||||
List<VoiceChannel> list = FinderUtil.findVoiceChannel(event.getArgs(), event.getGuild());
|
||||
if(list.isEmpty())
|
||||
event.reply(event.getClient().getWarning()+" No Voice Channels found matching \""+event.getArgs()+"\"");
|
||||
else if (list.size()>1)
|
||||
event.reply(event.getClient().getWarning()+FormatUtil.listOfVChannels(list, event.getArgs()));
|
||||
else
|
||||
{
|
||||
bot.setVoiceChannel(list.get(0));
|
||||
event.reply(event.getClient().getSuccess()+" Music can now only be played in **"+list.get(0).getName()+"**");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.commands;
|
||||
|
||||
import me.jagrosh.jdautilities.commandclient.Command;
|
||||
import me.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import me.jagrosh.jmusicbot.Bot;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class ShutdownCmd extends Command {
|
||||
|
||||
private final Bot bot;
|
||||
public ShutdownCmd(Bot bot)
|
||||
{
|
||||
this.bot = bot;
|
||||
this.name = "shutdown";
|
||||
this.help = "safely shuts down";
|
||||
this.ownerCommand = true;
|
||||
this.category = bot.OWNER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(CommandEvent event) {
|
||||
event.reply(event.getClient().getWarning()+" Shutting down...");
|
||||
bot.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.commands;
|
||||
|
||||
import me.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import me.jagrosh.jmusicbot.Bot;
|
||||
import me.jagrosh.jmusicbot.audio.AudioHandler;
|
||||
import net.dv8tion.jda.core.entities.User;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class SkipCmd extends MusicCommand {
|
||||
|
||||
public SkipCmd(Bot bot)
|
||||
{
|
||||
super(bot);
|
||||
this.name = "skip";
|
||||
this.help = "votes to skip the current song";
|
||||
this.aliases = new String[]{"voteskip"};
|
||||
this.beListening = true;
|
||||
this.bePlaying = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCommand(CommandEvent event) {
|
||||
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
|
||||
if(event.getAuthor().getId().equals(handler.getCurrentTrack().getIdentifier()))
|
||||
{
|
||||
event.reply(event.getClient().getSuccess()+" Skipped **"+handler.getCurrentTrack().getTrack().getInfo().title
|
||||
+"** (requested by **"+event.getAuthor().getName()+"**)");
|
||||
handler.getPlayer().stopTrack();
|
||||
}
|
||||
else
|
||||
{
|
||||
int listeners = (int)event.getSelfMember().getVoiceState().getChannel().getMembers().stream()
|
||||
.filter(m -> !m.getUser().isBot() && !m.getVoiceState().isDeafened()).count();
|
||||
String msg;
|
||||
if(handler.getVotes().contains(event.getAuthor().getId()))
|
||||
msg = event.getClient().getWarning()+" You already voted to skip this song `[";
|
||||
else
|
||||
{
|
||||
msg = event.getClient().getSuccess()+" You voted to skip the song `[";
|
||||
handler.getVotes().add(event.getAuthor().getId());
|
||||
}
|
||||
int skippers = (int)event.getSelfMember().getVoiceState().getChannel().getMembers().stream()
|
||||
.filter(m -> handler.getVotes().contains(m.getUser().getId())).count();
|
||||
int required = (int)Math.ceil(listeners * .55);
|
||||
msg+= skippers+" votes, "+required+"/"+listeners+" needed]`";
|
||||
if(skippers>=required)
|
||||
{
|
||||
User u = event.getJDA().getUserById(handler.getCurrentTrack().getIdentifier());
|
||||
msg+="\n"+event.getClient().getSuccess()+" Skipped **"+handler.getCurrentTrack().getTrack().getInfo().title
|
||||
+"** (requested by "+(u==null ? "someone" : "**"+u.getName()+"**")+")";
|
||||
handler.getPlayer().stopTrack();
|
||||
}
|
||||
event.reply(msg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.commands;
|
||||
|
||||
import me.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import me.jagrosh.jmusicbot.Bot;
|
||||
import me.jagrosh.jmusicbot.audio.AudioHandler;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class StopCmd extends MusicCommand {
|
||||
|
||||
public StopCmd(Bot bot)
|
||||
{
|
||||
super(bot);
|
||||
this.name = "stop";
|
||||
this.help = "stops the current song and clears the queue";
|
||||
this.bePlaying = true;
|
||||
this.category = bot.DJ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCommand(CommandEvent event) {
|
||||
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
|
||||
handler.getQueue().clear();
|
||||
handler.getPlayer().stopTrack();
|
||||
event.getGuild().getAudioManager().closeAudioConnection();
|
||||
event.reply(event.getClient().getSuccess()+" The player has stopped and the queue has been cleared.");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.commands;
|
||||
|
||||
import me.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import me.jagrosh.jmusicbot.Bot;
|
||||
import me.jagrosh.jmusicbot.audio.AudioHandler;
|
||||
import me.jagrosh.jmusicbot.utils.FormatUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class VolumeCmd extends MusicCommand {
|
||||
|
||||
public VolumeCmd(Bot bot)
|
||||
{
|
||||
super(bot);
|
||||
this.name = "volume";
|
||||
this.help = "sets or shows volume";
|
||||
this.arguments = "[0-150]";
|
||||
this.category = bot.DJ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCommand(CommandEvent event) {
|
||||
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
|
||||
int volume = handler==null ? 100 : handler.getPlayer().getVolume();
|
||||
if(event.getArgs().isEmpty())
|
||||
{
|
||||
event.reply(FormatUtil.volumeIcon(volume)+" Current volume is `"+volume+"`");
|
||||
}
|
||||
else
|
||||
{
|
||||
int nvolume;
|
||||
try{
|
||||
nvolume = Integer.parseInt(event.getArgs());
|
||||
}catch(NumberFormatException e){
|
||||
nvolume = -1;
|
||||
}
|
||||
if(nvolume<0 || nvolume>150)
|
||||
event.reply(event.getClient().getError()+" Volume must be a valid integer between 0 and 150!");
|
||||
else
|
||||
{
|
||||
bot.setUpHandler(event).getPlayer().setVolume(nvolume);
|
||||
event.reply(FormatUtil.volumeIcon(nvolume)+" Volume changed from `"+volume+"` to `"+nvolume+"`");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.gui;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridLayout;
|
||||
import java.io.PrintStream;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextArea;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class ConsolePanel extends JPanel {
|
||||
|
||||
public ConsolePanel()
|
||||
{
|
||||
super();
|
||||
JTextArea text = new JTextArea();
|
||||
text.setLineWrap(true);
|
||||
text.setWrapStyleWord(true);
|
||||
text.setEditable(false);
|
||||
PrintStream con=new PrintStream(new TextAreaOutputStream(text));
|
||||
System.setOut(con);
|
||||
System.setErr(con);
|
||||
|
||||
JScrollPane pane = new JScrollPane();
|
||||
pane.setViewportView(text);
|
||||
|
||||
super.setLayout(new GridLayout(1,1));
|
||||
super.add(pane);
|
||||
super.setPreferredSize(new Dimension(400,300));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.gui;
|
||||
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.event.WindowListener;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.WindowConstants;
|
||||
import me.jagrosh.jmusicbot.Bot;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class GUI extends JFrame {
|
||||
|
||||
private final ConsolePanel console;
|
||||
private final GuildsPanel guilds;
|
||||
private final Bot bot;
|
||||
|
||||
public GUI(Bot bot) {
|
||||
super();
|
||||
this.bot = bot;
|
||||
console = new ConsolePanel();
|
||||
guilds = new GuildsPanel(bot);
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
setTitle("JMusicBot");
|
||||
JTabbedPane tabs = new JTabbedPane();
|
||||
//tabs.add("Guilds", guilds);
|
||||
tabs.add("Console", console);
|
||||
getContentPane().add(tabs);
|
||||
pack();
|
||||
setLocationRelativeTo(null);
|
||||
setVisible(true);
|
||||
addWindowListener(new WindowListener() {
|
||||
@Override public void windowOpened(WindowEvent e) {}
|
||||
@Override public void windowClosing(WindowEvent e) {bot.shutdown();}
|
||||
@Override public void windowClosed(WindowEvent e) {}
|
||||
@Override public void windowIconified(WindowEvent e) {}
|
||||
@Override public void windowDeiconified(WindowEvent e) {}
|
||||
@Override public void windowActivated(WindowEvent e) {}
|
||||
@Override public void windowDeactivated(WindowEvent e) {}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +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 me.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 me.jagrosh.jmusicbot.Bot;
|
||||
import me.jagrosh.jmusicbot.audio.AudioHandler;
|
||||
import me.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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.gui;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import javax.swing.*;
|
||||
/**
|
||||
*
|
||||
* @author Lawrence Dol
|
||||
*/
|
||||
public class TextAreaOutputStream extends OutputStream {
|
||||
|
||||
// *************************************************************************************************
|
||||
// INSTANCE MEMBERS
|
||||
// *************************************************************************************************
|
||||
|
||||
private byte[] oneByte; // array for write(int val);
|
||||
private Appender appender; // most recent action
|
||||
|
||||
public TextAreaOutputStream(JTextArea txtara) {
|
||||
this(txtara,1000);
|
||||
}
|
||||
|
||||
public TextAreaOutputStream(JTextArea txtara, int maxlin) {
|
||||
if(maxlin<1) { throw new IllegalArgumentException("TextAreaOutputStream maximum lines must be positive (value="+maxlin+")"); }
|
||||
oneByte=new byte[1];
|
||||
appender=new Appender(txtara,maxlin);
|
||||
}
|
||||
|
||||
/** Clear the current console text area. */
|
||||
public synchronized void clear() {
|
||||
if(appender!=null) { appender.clear(); }
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() {
|
||||
appender=null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void flush() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void write(int val) {
|
||||
oneByte[0]=(byte)val;
|
||||
write(oneByte,0,1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void write(byte[] ba) {
|
||||
write(ba,0,ba.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void write(byte[] ba,int str,int len) {
|
||||
if(appender!=null) { appender.append(bytesToString(ba,str,len)); }
|
||||
}
|
||||
|
||||
//@edu.umd.cs.findbugs.annotations.SuppressWarnings("DM_DEFAULT_ENCODING")
|
||||
static private String bytesToString(byte[] ba, int str, int len) {
|
||||
try { return new String(ba,str,len,"UTF-8"); } catch(UnsupportedEncodingException thr) { return new String(ba,str,len); } // all JVMs are required to support UTF-8
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
// STATIC MEMBERS
|
||||
// *************************************************************************************************
|
||||
|
||||
static class Appender
|
||||
implements Runnable
|
||||
{
|
||||
private final JTextArea textArea;
|
||||
private final int maxLines; // maximum lines allowed in text area
|
||||
private final LinkedList<Integer> lengths; // length of lines within text area
|
||||
private final List<String> values; // values waiting to be appended
|
||||
|
||||
private int curLength; // length of current line
|
||||
private boolean clear;
|
||||
private boolean queue;
|
||||
|
||||
Appender(JTextArea txtara, int maxlin) {
|
||||
textArea =txtara;
|
||||
maxLines =maxlin;
|
||||
lengths =new LinkedList<>();
|
||||
values =new ArrayList<>();
|
||||
|
||||
curLength=0;
|
||||
clear =false;
|
||||
queue =true;
|
||||
}
|
||||
|
||||
synchronized void append(String val) {
|
||||
values.add(val);
|
||||
if(queue) { queue=false; EventQueue.invokeLater(this); }
|
||||
}
|
||||
|
||||
synchronized void clear() {
|
||||
clear=true;
|
||||
curLength=0;
|
||||
lengths.clear();
|
||||
values.clear();
|
||||
if(queue) { queue=false; EventQueue.invokeLater(this); }
|
||||
}
|
||||
|
||||
// MUST BE THE ONLY METHOD THAT TOUCHES textArea!
|
||||
@Override
|
||||
public synchronized void run() {
|
||||
if(clear) { textArea.setText(""); }
|
||||
values.stream().map((val) -> {
|
||||
curLength+=val.length();
|
||||
return val;
|
||||
}).map((val) -> {
|
||||
if(val.endsWith(EOL1) || val.endsWith(EOL2)) {
|
||||
if(lengths.size()>=maxLines) { textArea.replaceRange("",0,lengths.removeFirst()); }
|
||||
lengths.addLast(curLength);
|
||||
curLength=0;
|
||||
}
|
||||
return val;
|
||||
}).forEach((val) -> {
|
||||
textArea.append(val);
|
||||
});
|
||||
values.clear();
|
||||
clear =false;
|
||||
queue =true;
|
||||
}
|
||||
|
||||
static private final String EOL1="\n";
|
||||
static private final String EOL2=System.getProperty("line.separator",EOL1);
|
||||
}
|
||||
|
||||
} /* END PUBLIC CLASS */
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.queue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
*/
|
||||
public class FairQueue<T extends Queueable> {
|
||||
private final List<T> list = new ArrayList<>();
|
||||
private final Set<String> 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()))
|
||||
break;
|
||||
lastIndex++;
|
||||
set.clear();
|
||||
for(; lastIndex<list.size(); lastIndex++)
|
||||
{
|
||||
if(set.contains(list.get(lastIndex).getIdentifier()))
|
||||
break;
|
||||
set.add(list.get(lastIndex).getIdentifier());
|
||||
}
|
||||
list.add(lastIndex, item);
|
||||
return lastIndex;
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
return list.size();
|
||||
}
|
||||
|
||||
public T pull()
|
||||
{
|
||||
return list.remove(0);
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return list.isEmpty();
|
||||
}
|
||||
|
||||
public List<T> getList()
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
public T get(int index)
|
||||
{
|
||||
return list.get(index);
|
||||
}
|
||||
|
||||
public T remove(int index)
|
||||
{
|
||||
return list.remove(index);
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
list.clear();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
|
||||
/*
|
||||
* Copyright 2016 jagrosh.
|
||||
* 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.
|
||||
@@ -14,12 +13,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package spectramusic;
|
||||
package me.jagrosh.jmusicbot.queue;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class GUI {
|
||||
public interface Queueable {
|
||||
|
||||
public String getIdentifier();
|
||||
}
|
||||
+8
-9
@@ -1,6 +1,5 @@
|
||||
|
||||
/*
|
||||
* Copyright 2016 jagrosh.
|
||||
* 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.
|
||||
@@ -14,19 +13,19 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package spectramusic.util;
|
||||
package me.jagrosh.jmusicbot.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import net.dv8tion.jda.entities.Guild;
|
||||
import net.dv8tion.jda.entities.Role;
|
||||
import net.dv8tion.jda.entities.TextChannel;
|
||||
import net.dv8tion.jda.entities.VoiceChannel;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Role;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class FinderUtil {
|
||||
|
||||
@@ -137,5 +136,5 @@ public class FinderUtil {
|
||||
if(!startswith.isEmpty())
|
||||
return startswith;
|
||||
return contains;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.utils;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
import java.util.List;
|
||||
import me.jagrosh.jmusicbot.audio.AudioHandler;
|
||||
import net.dv8tion.jda.core.JDA;
|
||||
import net.dv8tion.jda.core.entities.Role;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
import net.dv8tion.jda.core.entities.User;
|
||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class FormatUtil {
|
||||
|
||||
public static String formatTime(long duration)
|
||||
{
|
||||
long seconds = Math.round(duration/1000.0);
|
||||
long hours = seconds/(60*60);
|
||||
seconds %= 60*60;
|
||||
long minutes = seconds/60;
|
||||
seconds %= 60;
|
||||
return (hours>0 ? hours+":" : "") + (minutes<10 ? "0"+minutes : minutes) + ":" + (seconds<10 ? "0"+seconds : seconds);
|
||||
}
|
||||
|
||||
public static String formattedAudio(AudioHandler handler, JDA jda, boolean inTopic)
|
||||
{
|
||||
if(handler==null || handler.getCurrentTrack()==null)
|
||||
{
|
||||
return "No music playing\n\u23F9 "+progressBar(-1)+" "+volumeIcon(handler.getPlayer().getVolume());
|
||||
}
|
||||
else
|
||||
{
|
||||
String userid = handler.getCurrentTrack().getIdentifier();
|
||||
User user = jda.getUserById(userid);
|
||||
AudioTrack track = handler.getCurrentTrack().getTrack();
|
||||
String title = track.getInfo().title;
|
||||
if(inTopic && title.length()>30)
|
||||
title = title.substring(0,27)+"...";
|
||||
double progress = (double)track.getPosition()/track.getDuration();
|
||||
String str = "**"+title+"** ["+(user==null||inTopic ? "<@"+userid+">" : user.getName())+"]\n\u25B6 "+progressBar(progress)
|
||||
+" "+(inTopic ? "" : "`")+"["+formatTime(track.getPosition()) + "/" + formatTime(track.getDuration())
|
||||
+"]"+(inTopic ? "" : "`")+" " +volumeIcon(handler.getPlayer().getVolume());
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
private static String progressBar(double percent)
|
||||
{
|
||||
String str = "";
|
||||
for(int i=0; i<10; i++)
|
||||
if(i == (int)(percent*10))
|
||||
str+="\uD83D\uDD18";
|
||||
else
|
||||
str+="▬";
|
||||
return str;
|
||||
}
|
||||
|
||||
public static String volumeIcon(int volume)
|
||||
{
|
||||
if(volume == 0)
|
||||
return "\uD83D\uDD07";
|
||||
if(volume < 30)
|
||||
return "\uD83D\uDD08";
|
||||
if(volume < 70)
|
||||
return "\uD83D\uDD09";
|
||||
return "\uD83D\uDD0A";
|
||||
}
|
||||
|
||||
public static String listOfTChannels(List<TextChannel> list, String query)
|
||||
{
|
||||
String out = " Multiple text channels found matching \""+query+"\":";
|
||||
for(int i=0; i<6 && i<list.size(); i++)
|
||||
out+="\n - "+list.get(i).getName()+" (<#"+list.get(i).getId()+">)";
|
||||
if(list.size()>6)
|
||||
out+="\n**And "+(list.size()-6)+" more...**";
|
||||
return out;
|
||||
}
|
||||
public static String listOfVChannels(List<VoiceChannel> list, String query)
|
||||
{
|
||||
String out = " Multiple voice channels found matching \""+query+"\":";
|
||||
for(int i=0; i<6 && i<list.size(); i++)
|
||||
out+="\n - "+list.get(i).getName()+" (ID:"+list.get(i).getId()+")";
|
||||
if(list.size()>6)
|
||||
out+="\n**And "+(list.size()-6)+" more...**";
|
||||
return out;
|
||||
}
|
||||
public static String listOfRoles(List<Role> list, String query)
|
||||
{
|
||||
String out = " Multiple text channels found matching \""+query+"\":";
|
||||
for(int i=0; i<6 && i<list.size(); i++)
|
||||
out+="\n - "+list.get(i).getName()+" (ID:"+list.get(i).getId()+")";
|
||||
if(list.size()>6)
|
||||
out+="\n**And "+(list.size()-6)+" more...**";
|
||||
return out;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 me.jagrosh.jmusicbot.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class OtherUtil {
|
||||
|
||||
public static InputStream imageFromUrl(String url)
|
||||
{
|
||||
if(url==null)
|
||||
return null;
|
||||
try {
|
||||
URL u = new URL(url);
|
||||
URLConnection urlConnection = u.openConnection();
|
||||
urlConnection.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36");
|
||||
return urlConnection.getInputStream();
|
||||
} catch(IOException|IllegalArgumentException e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,434 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright 2016 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 spectramusic;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javafx.util.Pair;
|
||||
import net.dv8tion.jda.Permission;
|
||||
import net.dv8tion.jda.entities.Guild;
|
||||
import net.dv8tion.jda.entities.Message;
|
||||
import net.dv8tion.jda.entities.Role;
|
||||
import net.dv8tion.jda.entities.TextChannel;
|
||||
import net.dv8tion.jda.entities.VoiceChannel;
|
||||
import net.dv8tion.jda.entities.VoiceStatus;
|
||||
import net.dv8tion.jda.events.ReadyEvent;
|
||||
import net.dv8tion.jda.events.ShutdownEvent;
|
||||
import net.dv8tion.jda.events.message.guild.GuildMessageReceivedEvent;
|
||||
import net.dv8tion.jda.hooks.ListenerAdapter;
|
||||
import net.dv8tion.jda.managers.AudioManager;
|
||||
import net.dv8tion.jda.player.Playlist;
|
||||
import net.dv8tion.jda.player.hooks.PlayerListenerAdapter;
|
||||
import net.dv8tion.jda.player.hooks.events.FinishEvent;
|
||||
import net.dv8tion.jda.player.source.AudioInfo;
|
||||
import net.dv8tion.jda.player.source.AudioSource;
|
||||
import net.dv8tion.jda.utils.PermissionUtil;
|
||||
import net.dv8tion.jda.utils.SimpleLog;
|
||||
import org.json.JSONObject;
|
||||
import spectramusic.Command.PermLevel;
|
||||
import spectramusic.commands.NowplayingCmd;
|
||||
import spectramusic.commands.PlayCmd;
|
||||
import spectramusic.commands.QueueCmd;
|
||||
import spectramusic.commands.SearchCmd;
|
||||
import spectramusic.commands.SetDJCmd;
|
||||
import spectramusic.commands.SetTCCmd;
|
||||
import spectramusic.commands.SetVCCmd;
|
||||
import spectramusic.commands.ShutdownCmd;
|
||||
import spectramusic.commands.SkipCmd;
|
||||
import spectramusic.commands.StatusCmd;
|
||||
import spectramusic.commands.StopCmd;
|
||||
import spectramusic.commands.VolumeCmd;
|
||||
import spectramusic.commands.VoteskipCmd;
|
||||
import spectramusic.entities.ClumpedMusicPlayer;
|
||||
import spectramusic.entities.ClumpedQueue;
|
||||
import spectramusic.util.FormatUtil;
|
||||
import spectramusic.web.YoutubeSearcher;
|
||||
import spectramusic.web.YoutubeSearcher.YoutubeInfo;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
*/
|
||||
public class Bot extends ListenerAdapter {
|
||||
|
||||
private final Command[] commands;
|
||||
private final String[] prefixes;
|
||||
private final String ownerId;
|
||||
private final JSONObject serverSettings;
|
||||
private final ArrayList<PlayerEvents> listeners = new ArrayList<>();
|
||||
private final HashMap<String,WaitingSearch> searches = new HashMap<>();
|
||||
private final ExecutorService addSongs = Executors.newFixedThreadPool(20);
|
||||
private final YoutubeSearcher youtubeSearcher;
|
||||
|
||||
public Bot(String ownerId, String[] prefixes, String youtubeApiKey){
|
||||
this.prefixes = prefixes;
|
||||
this.ownerId = ownerId;
|
||||
JSONObject loadedSettings = new JSONObject();
|
||||
try {
|
||||
loadedSettings = new JSONObject(new String(Files.readAllBytes(Paths.get("serversettings.json"))));
|
||||
} catch (IOException ex) {
|
||||
System.out.println("No server settings found; using new settings for all servers.");
|
||||
}
|
||||
serverSettings = loadedSettings;
|
||||
if(youtubeApiKey==null || youtubeApiKey.equals(""))
|
||||
youtubeSearcher = null;
|
||||
else
|
||||
youtubeSearcher = new YoutubeSearcher(youtubeApiKey);
|
||||
commands = new Command[]{
|
||||
new NowplayingCmd(),
|
||||
new PlayCmd(this),
|
||||
new QueueCmd(),
|
||||
new SearchCmd(this,youtubeSearcher),
|
||||
new StatusCmd(serverSettings,ownerId),
|
||||
new VoteskipCmd(),
|
||||
|
||||
new SkipCmd(),
|
||||
new StopCmd(),
|
||||
new VolumeCmd(),
|
||||
|
||||
new SetDJCmd(serverSettings),
|
||||
new SetTCCmd(serverSettings),
|
||||
new SetVCCmd(serverSettings),
|
||||
|
||||
new ShutdownCmd(),
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReady(ReadyEvent event) {
|
||||
event.getJDA().getAccountManager().setGame("Type "+prefixes[0]+"musichelp");
|
||||
if(event.getJDA().getGuilds().isEmpty())
|
||||
System.out.println("Warning: This bot is not connected to any servers. Please use the following link to connect it to your servers:\n"
|
||||
+event.getJDA().getSelfInfo().getAuthUrl(Permission.VOICE_CONNECT,Permission.VOICE_SPEAK,
|
||||
Permission.MANAGE_CHANNEL,Permission.MESSAGE_MANAGE,Permission.MESSAGE_READ,Permission.MESSAGE_WRITE));
|
||||
SimpleLog.getLog("Music").info(event.getJDA().getSelfInfo().getUsername()+" is online and ready to play music!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGuildMessageReceived(GuildMessageReceivedEvent event) {
|
||||
if(event.getAuthor().isBot())
|
||||
return;
|
||||
Object searchresult = pullSearch(event);
|
||||
if(searchresult!=null)
|
||||
{
|
||||
if(searchresult instanceof AudioSource)
|
||||
addToQueue(event, (AudioSource)searchresult);
|
||||
else
|
||||
addToQueue(event, ((YoutubeInfo)searchresult).url);
|
||||
return;
|
||||
}
|
||||
String content = null;
|
||||
for(String prefix : prefixes)
|
||||
if(event.getMessage().getRawContent().toLowerCase().startsWith(prefix))
|
||||
{
|
||||
content = event.getMessage().getRawContent().substring(prefix.length()).trim();
|
||||
break;
|
||||
}
|
||||
if(content==null)
|
||||
return;
|
||||
|
||||
//get levels for users
|
||||
JSONObject settings = serverSettings.has(event.getGuild().getId()) ? serverSettings.getJSONObject(event.getGuild().getId()) : null;
|
||||
Role djRole = settings==null ? null : event.getGuild().getRoleById(settings.getString(SpConst.DJ_JSON));
|
||||
PermLevel userLevel = PermLevel.EVERYONE;
|
||||
if(event.getAuthor().getId().equals(ownerId))
|
||||
userLevel = PermLevel.OWNER;
|
||||
else if (PermissionUtil.checkPermission(event.getGuild(), event.getAuthor(), Permission.MANAGE_SERVER))
|
||||
userLevel = PermLevel.ADMIN;
|
||||
else if (djRole!=null && event.getGuild().getRolesForUser(event.getAuthor()).contains(djRole))
|
||||
userLevel = PermLevel.DJ;
|
||||
|
||||
if(content.equalsIgnoreCase("musichelp") || content.equalsIgnoreCase("music help"))
|
||||
{
|
||||
StringBuilder builder = new StringBuilder("**Spectra Music** commands:");
|
||||
PermLevel current = PermLevel.EVERYONE;
|
||||
for(Command cmd: commands)
|
||||
{
|
||||
if(!current.isAtLeast(cmd.level))
|
||||
{
|
||||
if(userLevel.isAtLeast(cmd.level))
|
||||
{
|
||||
current = cmd.level;
|
||||
builder.append("\n\nCommands for **").append(cmd.level).append("**:");
|
||||
}
|
||||
else break;
|
||||
}
|
||||
builder.append("\n`").append(prefixes[0]).append(cmd.command)
|
||||
.append(cmd.arguments==null ? "" : " "+cmd.arguments).append("` - ").append(cmd.getHelp());
|
||||
}
|
||||
Sender.sendReply(builder.toString(), event);
|
||||
return;
|
||||
}
|
||||
String[] parts = content.split("\\s+",2);
|
||||
Command command = null;
|
||||
for(Command cmd : commands)
|
||||
if(cmd.isCommandFor(parts[0]))
|
||||
command = cmd;
|
||||
if(command==null)
|
||||
return;
|
||||
|
||||
boolean isValidChannel = userLevel.isAtLeast(PermLevel.DJ) || settings==null || settings.getString(SpConst.TC_JSON).equals("") || settings.getString(SpConst.TC_JSON).equals(event.getChannel().getId());
|
||||
|
||||
boolean listeningInVc;
|
||||
VoiceStatus botstatus = event.getGuild().getVoiceStatusOfUser(event.getJDA().getSelfInfo());
|
||||
VoiceStatus userstatus = event.getGuild().getVoiceStatusOfUser(event.getAuthor());
|
||||
VoiceChannel vc = settings==null ? null : event.getJDA().getVoiceChannelById(settings.getString(SpConst.VC_JSON));
|
||||
String vcName = vc==null ? "a voice channel" : "**"+vc.getName()+"**";
|
||||
if(userstatus==null || !userstatus.inVoiceChannel() || userstatus.isDeaf())
|
||||
{
|
||||
listeningInVc = false;
|
||||
}
|
||||
else if (botstatus==null || !botstatus.inVoiceChannel())
|
||||
{
|
||||
listeningInVc = vc==null || userstatus.getChannel().equals(vc);
|
||||
}
|
||||
else
|
||||
{
|
||||
listeningInVc = botstatus.getChannel().equals(userstatus.getChannel());
|
||||
}
|
||||
|
||||
if(isValidChannel)
|
||||
{
|
||||
AudioManager manager = event.getGuild().getAudioManager();
|
||||
ClumpedMusicPlayer player;
|
||||
if (manager.getSendingHandler() == null)
|
||||
{
|
||||
player = new ClumpedMusicPlayer();
|
||||
PlayerEvents events = new PlayerEvents(event.getGuild());
|
||||
player.addEventListener(events);
|
||||
listeners.add(events);
|
||||
player.setVolume(.35f);
|
||||
manager.setSendingHandler(player);
|
||||
}
|
||||
else
|
||||
{
|
||||
player = (ClumpedMusicPlayer) manager.getSendingHandler();
|
||||
}
|
||||
command.run(parts.length<2||parts[1]==null ? "" : parts[1], event, userLevel, player, new Pair<>(listeningInVc,vcName));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShutdown(ShutdownEvent event) {
|
||||
listeners.stream().forEach(e -> e.shutdown());
|
||||
Sender.shutdown();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
public void addToQueue(GuildMessageReceivedEvent event, AudioSource audiosource)
|
||||
{
|
||||
addSongs.submit(() -> {
|
||||
AudioInfo info = audiosource.getInfo();
|
||||
if (info.getError() == null)
|
||||
{
|
||||
if(!joinVoiceChannel(event))
|
||||
return;
|
||||
ClumpedMusicPlayer player = (ClumpedMusicPlayer)event.getGuild().getAudioManager().getSendingHandler();
|
||||
int position = player.getAudioQueue().add(event.getAuthor().getId(),audiosource);
|
||||
if(player.isStopped())
|
||||
player.play();
|
||||
Sender.sendReply(SpConst.SUCCESS+"Added **"+info.getTitle()
|
||||
+"** (`"+(info.isLive() ? "LIVE" : info.getDuration().getTimestamp())+"`) to the queue "
|
||||
+(position==0 ? "and will begin playing" :"at position "+(position+1)), event);
|
||||
}
|
||||
else
|
||||
{
|
||||
Sender.sendReply(SpConst.ERROR+"There was a problem with the provided source:\n"+info.getError(), event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void addToQueue(GuildMessageReceivedEvent event, String url)
|
||||
{
|
||||
if(!joinVoiceChannel(event))
|
||||
return;
|
||||
addSongs.submit(() -> {
|
||||
Sender.sendReply("\u231A Loading... `["+url+"]`", event, () -> {
|
||||
Playlist playlist;
|
||||
try {
|
||||
playlist = Playlist.getPlaylist(url);
|
||||
} catch(NullPointerException e)
|
||||
{
|
||||
try{
|
||||
playlist = Playlist.getPlaylist("ytsearch:"+URLEncoder.encode(url, "UTF-8"));
|
||||
} catch(NullPointerException | UnsupportedEncodingException ex)
|
||||
{
|
||||
SimpleLog.getLog("Queue").warn("Invalid url ["+url+"]: "+ex);
|
||||
return SpConst.ERROR+"The given link or playlist was invalid";
|
||||
}
|
||||
}
|
||||
|
||||
List<AudioSource> sources = new ArrayList<>(playlist.getSources());
|
||||
String id = event.getAuthor().getId();
|
||||
final ClumpedMusicPlayer player = (ClumpedMusicPlayer)event.getGuild().getAudioManager().getSendingHandler();
|
||||
if (sources.size() > 1)
|
||||
{
|
||||
ClumpedQueue<String,AudioSource> queue = player.getAudioQueue();
|
||||
addSongs.submit(() -> {
|
||||
int count = 0;
|
||||
for(AudioSource it : sources)
|
||||
{
|
||||
AudioSource source = it;
|
||||
AudioInfo info = source.getInfo();
|
||||
if (info.getError() == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
queue.add(id,source);
|
||||
} catch(UnsupportedOperationException e)
|
||||
{
|
||||
return;
|
||||
}
|
||||
count++;
|
||||
if (player.isStopped())
|
||||
player.play();
|
||||
}
|
||||
}
|
||||
Sender.sendAlert(SpConst.SUCCESS+"Successfully queued "+count+" (out of "+sources.size()+") sources [<@"+id+">]", event);
|
||||
});
|
||||
return SpConst.SUCCESS+"Found a playlist with `"
|
||||
+sources.size()+"` entries.\n\u231A Queueing sources... (this may take some time)";
|
||||
}
|
||||
else
|
||||
{
|
||||
AudioSource source = sources.get(0);
|
||||
AudioInfo info = source.getInfo();
|
||||
if (info.getError() == null)
|
||||
{
|
||||
int position = player.getAudioQueue().add(id,source);
|
||||
if(player.isStopped())
|
||||
player.play();
|
||||
return SpConst.SUCCESS+"Added **"+info.getTitle()
|
||||
+"** (`"+(info.isLive() ? "LIVE" : info.getDuration().getTimestamp())+"`) to the queue "+(position==0 ? "and will begin playing" :"at position "+(position+1));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return SpConst.ERROR+"There was a problem with the provided source:\n"+info.getError();
|
||||
}
|
||||
}
|
||||
});});
|
||||
}
|
||||
|
||||
public boolean joinVoiceChannel(GuildMessageReceivedEvent event)
|
||||
{
|
||||
if(!event.getGuild().getVoiceStatusOfUser(event.getJDA().getSelfInfo()).inVoiceChannel())
|
||||
{
|
||||
VoiceChannel target = event.getGuild().getVoiceStatusOfUser(event.getAuthor()).getChannel();
|
||||
if(!target.checkPermission(event.getJDA().getSelfInfo(), Permission.VOICE_CONNECT) || !target.checkPermission(event.getJDA().getSelfInfo(), Permission.VOICE_SPEAK))
|
||||
{
|
||||
Sender.sendReply(SpConst.ERROR+"I must be able to connect and speak in **"+target.getName()+"** to join!", event);
|
||||
return false;
|
||||
}
|
||||
event.getGuild().getAudioManager().openAudioConnection(target);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void addSearch(GuildMessageReceivedEvent event, List<AudioSource> list, List<YoutubeInfo> list2, Message botMessage)
|
||||
{
|
||||
searches.put(event.getAuthor().getId()+"|"+event.getChannel().getId(), new WaitingSearch(list, list2, event.getMessage(), botMessage));
|
||||
}
|
||||
|
||||
//returns an AudioSource or a String (url)
|
||||
public Object pullSearch(GuildMessageReceivedEvent event)
|
||||
{
|
||||
WaitingSearch search = searches.remove(event.getAuthor().getId()+"|"+event.getChannel().getId());
|
||||
if(search==null)
|
||||
return null;
|
||||
search.botMessage.deleteMessage();
|
||||
if(event.getChannel().checkPermission(event.getJDA().getSelfInfo(), Permission.MESSAGE_MANAGE))
|
||||
search.userMessage.deleteMessage();
|
||||
try
|
||||
{
|
||||
String input = event.getMessage().getRawContent();
|
||||
if(input.endsWith("."))
|
||||
input = input.substring(0,input.length()-1);
|
||||
return (search.list==null ? search.list2 : search.list).get(Integer.parseInt(input)-1);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private class WaitingSearch {
|
||||
private final List<AudioSource> list;
|
||||
private final List<YoutubeInfo> list2;
|
||||
private final Message userMessage;
|
||||
private final Message botMessage;
|
||||
public WaitingSearch(List<AudioSource> list, List<YoutubeInfo> list2, Message userMessage, Message botMessage)
|
||||
{
|
||||
this.list = list;
|
||||
this.list2 = list2;
|
||||
this.userMessage = userMessage;
|
||||
this.botMessage = botMessage;
|
||||
}
|
||||
}
|
||||
|
||||
private class PlayerEvents extends PlayerListenerAdapter {
|
||||
private final Guild guild;
|
||||
ScheduledExecutorService channelUpdater = Executors.newScheduledThreadPool(1);
|
||||
|
||||
private PlayerEvents(Guild guild)
|
||||
{
|
||||
this.guild = guild;
|
||||
channelUpdater.scheduleWithFixedDelay(() -> {
|
||||
JSONObject settings = serverSettings.has(guild.getId()) ? serverSettings.getJSONObject(guild.getId()) : null;
|
||||
if(settings!=null)
|
||||
{
|
||||
TextChannel channel = guild.getJDA().getTextChannelById(settings.getString("text_channel_id"));
|
||||
if(channel!=null && channel.checkPermission(guild.getJDA().getSelfInfo(), Permission.MANAGE_CHANNEL))
|
||||
{
|
||||
String otherText;
|
||||
if(channel.getTopic()!=null && channel.getTopic().contains("\u200B"))
|
||||
{
|
||||
otherText = channel.getTopic().substring(channel.getTopic().indexOf("\u200B")+1);
|
||||
}
|
||||
else
|
||||
otherText = channel.getTopic()==null ? "" : channel.getTopic();
|
||||
String newTopic = FormatUtil.formattedAudio((ClumpedMusicPlayer)guild.getAudioManager().getSendingHandler(), guild.getJDA(), true)+"\n\u200B"+otherText;
|
||||
if(!newTopic.equals(channel.getTopic()))
|
||||
channel.getManager().setTopic(newTopic).update();
|
||||
}
|
||||
}
|
||||
}, 0, 10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public void shutdown()
|
||||
{
|
||||
channelUpdater.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish(FinishEvent event) {
|
||||
guild.getAudioManager().closeAudioConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright 2016 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 spectramusic;
|
||||
|
||||
import javafx.util.Pair;
|
||||
import net.dv8tion.jda.events.message.guild.GuildMessageReceivedEvent;
|
||||
import spectramusic.entities.ClumpedMusicPlayer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
*/
|
||||
public abstract class Command {
|
||||
protected String command = "null";
|
||||
protected String arguments = null;
|
||||
protected String[] aliases = new String[0];
|
||||
protected PermLevel level = PermLevel.EVERYONE;
|
||||
protected String help = "";
|
||||
protected boolean mustBePlaying = false;
|
||||
protected boolean userMustBeInVC = false;
|
||||
|
||||
protected abstract void execute(String args, GuildMessageReceivedEvent event, PermLevel caller, ClumpedMusicPlayer player);
|
||||
|
||||
public void run(String args, GuildMessageReceivedEvent event, PermLevel caller, ClumpedMusicPlayer player, Pair<Boolean,String> voiceState)
|
||||
{
|
||||
if(!caller.isAtLeast(level))
|
||||
return;
|
||||
if(mustBePlaying && (player==null || !player.isPlaying()))
|
||||
{
|
||||
Sender.sendReply(SpConst.MUST_BE_PLAYING, event);
|
||||
return;
|
||||
}
|
||||
if(userMustBeInVC && !voiceState.getKey())
|
||||
{
|
||||
Sender.sendReply(String.format(SpConst.MUST_BE_IN_VC,voiceState.getValue()), event);
|
||||
return;
|
||||
}
|
||||
execute(args,event,caller,player);
|
||||
}
|
||||
|
||||
public String getHelp()
|
||||
{
|
||||
return help;
|
||||
}
|
||||
|
||||
public boolean isCommandFor(String input)
|
||||
{
|
||||
if(command.equalsIgnoreCase(input))
|
||||
return true;
|
||||
for(String str: aliases)
|
||||
if(str.equalsIgnoreCase(input))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public enum PermLevel {
|
||||
EVERYONE(0), DJ(1), ADMIN(2), OWNER(3);
|
||||
|
||||
private final int value;
|
||||
|
||||
private PermLevel(int value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean isAtLeast(PermLevel level)
|
||||
{
|
||||
return value >= level.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright 2016 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 spectramusic;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import net.dv8tion.jda.Permission;
|
||||
import net.dv8tion.jda.entities.Message;
|
||||
import net.dv8tion.jda.entities.PrivateChannel;
|
||||
import net.dv8tion.jda.events.message.guild.GuildMessageReceivedEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
*/
|
||||
public class Sender {
|
||||
private final static ScheduledExecutorService executor = Executors.newScheduledThreadPool(100);
|
||||
//for replying to commands
|
||||
|
||||
public static void sendReply(String message, GuildMessageReceivedEvent event)
|
||||
{
|
||||
sendReply(message,event,null);
|
||||
}
|
||||
|
||||
public static void sendReply(String message, GuildMessageReceivedEvent event, Supplier<String> edit)
|
||||
{
|
||||
Consumer<Message> cleanup = event.getChannel().checkPermission(event.getJDA().getSelfInfo(), Permission.MESSAGE_MANAGE)
|
||||
? m -> executor.schedule(() -> {
|
||||
event.getMessage().deleteMessage();
|
||||
m.deleteMessage();
|
||||
}, m.getRawContent().split("\n").length*10+5, TimeUnit.SECONDS)
|
||||
: null;
|
||||
if(edit==null)
|
||||
event.getChannel().sendMessageAsync(cleanMessage(message), cleanup);
|
||||
else
|
||||
event.getChannel().sendMessageAsync(cleanMessage(message), m -> {
|
||||
String newmessage = cleanMessage(edit.get());
|
||||
m.updateMessageAsync(newmessage, cleanup);
|
||||
});
|
||||
}
|
||||
|
||||
public static void sendReplyNoDelete(String message, GuildMessageReceivedEvent event, Consumer<Message> callback)
|
||||
{
|
||||
message = cleanMessage(message);
|
||||
event.getChannel().sendMessageAsync(message, callback);
|
||||
}
|
||||
|
||||
public static void sendAlert(String message, GuildMessageReceivedEvent event)
|
||||
{
|
||||
message = cleanMessage(message);
|
||||
event.getChannel().sendMessageAsync(message, m -> {
|
||||
executor.schedule(()-> m.deleteMessage(), m.getRawContent().split("\n").length*30, TimeUnit.SECONDS);
|
||||
});
|
||||
}
|
||||
|
||||
//send help (warn if can't send)
|
||||
public static void sendHelp(String message, PrivateChannel pchan, GuildMessageReceivedEvent event)//dependency for fallback
|
||||
{
|
||||
ArrayList<String> bits = splitMessage(message);
|
||||
for(int i=0; i<bits.size(); i++)
|
||||
{
|
||||
boolean first = (i == 0);
|
||||
pchan.sendMessageAsync(bits.get(i), m ->
|
||||
{
|
||||
if(m==null && first)//failed to send
|
||||
{
|
||||
sendReply(SpConst.CANT_HELP, event);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static String cleanMessage(String message)
|
||||
{
|
||||
message = message.replace("@everyone", "@\u200Beveryone").replace("@here", "@\u200Bhere").trim();
|
||||
if(message.length()>2000)
|
||||
message = message.substring(0,1995)+" (...)";
|
||||
return message;
|
||||
}
|
||||
|
||||
private static ArrayList<String> splitMessage(String stringtoSend)
|
||||
{
|
||||
ArrayList<String> msgs = new ArrayList<>();
|
||||
if(stringtoSend!=null)
|
||||
{
|
||||
stringtoSend = stringtoSend.replace("@everyone", "@\u200Beveryone").replace("@here", "@\u200Bhere").trim();
|
||||
while(stringtoSend.length()>2000)
|
||||
{
|
||||
int leeway = 2000 - (stringtoSend.length()%2000);
|
||||
int index = stringtoSend.lastIndexOf("\n", 2000);
|
||||
if(index<leeway)
|
||||
index = stringtoSend.lastIndexOf(" ", 2000);
|
||||
if(index<leeway)
|
||||
index=2000;
|
||||
String temp = stringtoSend.substring(0,index).trim();
|
||||
if(!temp.equals(""))
|
||||
msgs.add(temp);
|
||||
stringtoSend = stringtoSend.substring(index).trim();
|
||||
}
|
||||
if(!stringtoSend.equals(""))
|
||||
msgs.add(stringtoSend);
|
||||
}
|
||||
return msgs;
|
||||
}
|
||||
|
||||
public static void shutdown()
|
||||
{
|
||||
executor.shutdown();
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright 2016 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 spectramusic;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
*/
|
||||
public class SpConst {
|
||||
final public static String VERSION = "0.2";
|
||||
|
||||
//command responses
|
||||
final public static String SUCCESS = (char)9989+" ";
|
||||
final public static String WARNING = (char)9888+" ";
|
||||
final public static String ERROR = (char)9940+" ";
|
||||
|
||||
final public static String LINESTART = " ➣ ";
|
||||
|
||||
final public static String TC_JSON = "text_channel_id";
|
||||
final public static String VC_JSON = "voice_channel_id";
|
||||
final public static String DJ_JSON = "dj_role_id";
|
||||
|
||||
final public static String MUST_BE_PLAYING = ERROR+"There must be a song playing to use that!";
|
||||
final public static String MUST_BE_IN_VC = ERROR+"You must be listening in %s to use that!";
|
||||
|
||||
|
||||
final public static String MULTIPLE_FOUND = WARNING + "**Multiple %s found matching \"%s\":**";
|
||||
final public static String NONE_FOUND = WARNING + "**No %s found matching \"%s\"**";
|
||||
|
||||
final public static String CANT_HELP = WARNING + "Help could not be sent because you are blocking Direct Messages!";
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright 2016 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 spectramusic;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import javax.security.auth.login.LoginException;
|
||||
import net.dv8tion.jda.JDA;
|
||||
import net.dv8tion.jda.JDABuilder;
|
||||
import net.dv8tion.jda.utils.SimpleLog;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
*/
|
||||
public class SpectraMusic {
|
||||
|
||||
/**
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
||||
try{
|
||||
JSONObject config = new JSONObject(new String(Files.readAllBytes(Paths.get("config.json"))));
|
||||
JSONArray array = config.getJSONArray("prefixes");
|
||||
String[] prefixes = new String[array.length()];
|
||||
for(int i=0; i<prefixes.length; i++)
|
||||
prefixes[i] = array.getString(i).toLowerCase();
|
||||
String token = config.getString("bot_token");
|
||||
String ownerId = config.getString("owner_id");
|
||||
String youtubeApiKey = config.has("youtube_api_key") ? config.getString("youtube_api_key") : null;
|
||||
|
||||
if(token==null || token.equals("INSERT_TOKEN_HERE"))
|
||||
{
|
||||
System.out.println("Looks like you didn't set a token...");
|
||||
}
|
||||
else if(ownerId==null || !ownerId.matches("\\d{10,}"))
|
||||
{
|
||||
System.out.println("That owner ID doesn't look right...");
|
||||
}
|
||||
else if(prefixes.length==0)
|
||||
{
|
||||
System.out.println("Please specify at least 1 prefix");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(youtubeApiKey==null || youtubeApiKey.equals("INSERT_YOUTUBE_API_KEY_HERE_FOR_FASTER_SEARCHES"))
|
||||
{
|
||||
SimpleLog.getLog("Youtube").warn("No Youtube API key found; The search command could be faster if one was provided.");
|
||||
youtubeApiKey = null;
|
||||
}
|
||||
JDA jda = new JDABuilder().setBotToken(token).addListener(new Bot(ownerId, prefixes, youtubeApiKey)).buildAsync();
|
||||
}
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
JSONObject newconfig = new JSONObject();
|
||||
newconfig.put("bot_token", "INSERT_TOKEN_HERE");
|
||||
newconfig.put("owner_id", "INSERT_OWNER'S_DISCORD_ID_HERE");
|
||||
newconfig.put("prefixes", new JSONArray().put("%").put("/"));
|
||||
newconfig.put("youtube_api_key","INSERT_YOUTUBE_API_KEY_HERE_FOR_FASTER_SEARCHES");
|
||||
try
|
||||
{
|
||||
Files.write(Paths.get("config.json"), newconfig.toString(4).getBytes());
|
||||
System.out.println("No config file was found. Config.json has been generated, please populate it!");
|
||||
}
|
||||
catch (IOException e1)
|
||||
{
|
||||
System.out.println("No config file was found and we failed to generate one.");
|
||||
}
|
||||
}
|
||||
catch(JSONException e)
|
||||
{
|
||||
System.out.println("There was an error reading the config file. Please fix this or delete it so a new one can be created.");
|
||||
}
|
||||
catch(LoginException e)
|
||||
{
|
||||
System.out.println("Cannot log in with given token.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright 2016 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 spectramusic.commands;
|
||||
|
||||
import net.dv8tion.jda.events.message.guild.GuildMessageReceivedEvent;
|
||||
import spectramusic.Command;
|
||||
import spectramusic.Sender;
|
||||
import spectramusic.entities.ClumpedMusicPlayer;
|
||||
import spectramusic.util.FormatUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
*/
|
||||
public class NowplayingCmd extends Command {
|
||||
|
||||
public NowplayingCmd()
|
||||
{
|
||||
this.command = "nowplaying";
|
||||
this.aliases = new String[]{"np","current"};
|
||||
this.help = "shows what is currently playing";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(String args, GuildMessageReceivedEvent event, PermLevel caller, ClumpedMusicPlayer player) {
|
||||
Sender.sendReply(FormatUtil.formattedAudio(player, event.getJDA(), false), event);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package spectramusic.commands;
|
||||
|
||||
import net.dv8tion.jda.events.message.guild.GuildMessageReceivedEvent;
|
||||
import spectramusic.Bot;
|
||||
import spectramusic.Command;
|
||||
import spectramusic.Sender;
|
||||
import spectramusic.SpConst;
|
||||
import spectramusic.entities.ClumpedMusicPlayer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author johna
|
||||
*/
|
||||
public class PlayCmd extends Command {
|
||||
|
||||
//public static final String YT_ID = "[a-zA-Z0-9\\-_]+";
|
||||
private final Bot bot;
|
||||
public PlayCmd(Bot bot)
|
||||
{
|
||||
this.bot = bot;
|
||||
this.command = "play";
|
||||
this.arguments = "<URL>";
|
||||
this.help = "plays the song at the specified URL (or youtube video ID)";
|
||||
this.userMustBeInVC = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(String args, GuildMessageReceivedEvent event, PermLevel caller, ClumpedMusicPlayer player) {
|
||||
if(args.startsWith("<") && args.endsWith(">"))
|
||||
args = args.substring(1,args.length()-1);
|
||||
args = args.split("\\s+")[0];
|
||||
if(args.contains("&list="))
|
||||
args = args.split("&list=")[0];
|
||||
if(args.equals(""))
|
||||
{
|
||||
Sender.sendReply(SpConst.ERROR+"Please specify a url", event);
|
||||
return;
|
||||
}
|
||||
bot.addToQueue(event, args);
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright 2016 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 spectramusic.commands;
|
||||
|
||||
import javafx.util.Pair;
|
||||
import net.dv8tion.jda.entities.User;
|
||||
import net.dv8tion.jda.events.message.guild.GuildMessageReceivedEvent;
|
||||
import net.dv8tion.jda.player.source.AudioInfo;
|
||||
import net.dv8tion.jda.player.source.AudioSource;
|
||||
import net.dv8tion.jda.player.source.AudioTimestamp;
|
||||
import spectramusic.Command;
|
||||
import spectramusic.Sender;
|
||||
import spectramusic.SpConst;
|
||||
import spectramusic.entities.ClumpedMusicPlayer;
|
||||
import spectramusic.entities.ClumpedQueue;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
*/
|
||||
public class QueueCmd extends Command {
|
||||
|
||||
public QueueCmd()
|
||||
{
|
||||
this.command = "queue";
|
||||
this.aliases = new String[]{"list"};
|
||||
this.help = "shows the current queue";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(String args, GuildMessageReceivedEvent event, PermLevel caller, ClumpedMusicPlayer player) {
|
||||
ClumpedQueue<String,AudioSource> queue = player.getAudioQueue();
|
||||
if(queue.isEmpty())
|
||||
{
|
||||
Sender.sendReply(SpConst.WARNING+"There is no music in the queue!", event);
|
||||
return;
|
||||
}
|
||||
int size = queue.size();
|
||||
StringBuilder builder = new StringBuilder(SpConst.SUCCESS+"Current Queue ("+size+" entries):");
|
||||
for(int i=0; i<10 && i<size; i++ )
|
||||
{
|
||||
Pair<String,AudioSource> item = queue.get(i);
|
||||
AudioInfo info = item.getValue().getInfo();
|
||||
builder.append("\n**").append(i<9 ? "0" : "").append(i+1).append(".** ");
|
||||
if (info == null)
|
||||
builder.append("*No info found*");
|
||||
else
|
||||
{
|
||||
AudioTimestamp duration = info.getDuration();
|
||||
builder.append("`[");
|
||||
if (duration == null)
|
||||
builder.append("N/A");
|
||||
else
|
||||
builder.append(duration.getTimestamp());
|
||||
builder.append("]` **").append(info.getTitle()).append("**");
|
||||
}
|
||||
User user = event.getJDA().getUserById(item.getKey());
|
||||
builder.append(" - requested by ").append(user==null ? "an unknown user..." : "**"+user.getUsername()+"**");
|
||||
}
|
||||
boolean error = false;
|
||||
int totalSeconds = 0;
|
||||
for (int i=0; i<queue.size(); i++)
|
||||
{
|
||||
AudioInfo info = queue.get(i).getValue().getInfo();
|
||||
if (info == null || info.getDuration() == null)
|
||||
{
|
||||
error = true;
|
||||
continue;
|
||||
}
|
||||
totalSeconds += info.getDuration().getTotalSeconds();
|
||||
}
|
||||
|
||||
builder.append("\nTotal Queue Time Length: `").append(AudioTimestamp.fromSeconds(totalSeconds).getTimestamp()).append("`");
|
||||
if (error)
|
||||
builder.append("\nAn error occured calculating total time. Might not be completely valid.");
|
||||
Sender.sendReply(builder.toString(), event);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package spectramusic.commands;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.dv8tion.jda.events.message.guild.GuildMessageReceivedEvent;
|
||||
import net.dv8tion.jda.player.Playlist;
|
||||
import net.dv8tion.jda.player.source.AudioInfo;
|
||||
import net.dv8tion.jda.player.source.AudioSource;
|
||||
import spectramusic.Bot;
|
||||
import spectramusic.Command;
|
||||
import spectramusic.Sender;
|
||||
import spectramusic.SpConst;
|
||||
import spectramusic.entities.ClumpedMusicPlayer;
|
||||
import spectramusic.web.YoutubeSearcher;
|
||||
import spectramusic.web.YoutubeSearcher.YoutubeInfo;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author johna
|
||||
*/
|
||||
public class SearchCmd extends Command {
|
||||
private final Bot bot;
|
||||
private final YoutubeSearcher searcher;
|
||||
public SearchCmd(Bot bot, YoutubeSearcher searcher)
|
||||
{
|
||||
this.bot = bot;
|
||||
this.searcher = searcher;
|
||||
this.command = "search";
|
||||
this.help = "searches YouTube and offers results to be played";
|
||||
this.arguments = "<query>";
|
||||
this.userMustBeInVC = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(String args, GuildMessageReceivedEvent event, PermLevel caller, ClumpedMusicPlayer player) {
|
||||
if(args==null || args.equals(""))
|
||||
{
|
||||
Sender.sendReply(SpConst.ERROR+"Please include search terms!", event);
|
||||
return;
|
||||
}
|
||||
StringBuilder builder = new StringBuilder(SpConst.SUCCESS+"<@"+event.getAuthor().getId()+"> Results for `"+args+"`:");
|
||||
if(searcher==null)
|
||||
{
|
||||
try
|
||||
{
|
||||
String query = "ytsearch4:"+URLEncoder.encode(args, "UTF-8");
|
||||
Playlist playlist;
|
||||
event.getChannel().sendTyping();
|
||||
playlist = Playlist.getPlaylist(query);
|
||||
List<AudioSource> list = new ArrayList<>();
|
||||
if(playlist.getSources().isEmpty())
|
||||
{
|
||||
Sender.sendReply(SpConst.WARNING+"No results found for `"+args+"`", event);
|
||||
return;
|
||||
}
|
||||
for(int i=0; i<playlist.getSources().size() && i<3; i++)
|
||||
{
|
||||
AudioInfo info = playlist.getSources().get(i).getInfo();
|
||||
if(info.getError()==null)
|
||||
{
|
||||
list.add(playlist.getSources().get(i));
|
||||
builder.append("\n**").append(i+1).append(".** `[")
|
||||
.append(info.getDuration().getTimestamp())
|
||||
.append("]` **").append(info.getTitle()).append("**");
|
||||
}
|
||||
}
|
||||
builder.append("\nType the number of your choice to play (ex: `2`), or any invalid choice to cancel");
|
||||
Sender.sendReplyNoDelete(builder.toString(), event, m -> bot.addSearch(event, list, null, m) );
|
||||
}
|
||||
catch(NullPointerException | UnsupportedEncodingException e)
|
||||
{
|
||||
Sender.sendReply(SpConst.ERROR+"The given query or result was invalid", event);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
event.getChannel().sendTyping();
|
||||
List<YoutubeInfo> list = searcher.getResults(args, 3);
|
||||
if(list==null)
|
||||
{
|
||||
Sender.sendReply(SpConst.ERROR+"The search was unable to be completed", event);
|
||||
return;
|
||||
}
|
||||
if(list.isEmpty())
|
||||
{
|
||||
Sender.sendReply(SpConst.WARNING+"No results found for `"+args+"`", event);
|
||||
return;
|
||||
}
|
||||
for(int i=0; i<list.size(); i++)
|
||||
{
|
||||
builder.append("\n**").append(i+1).append(".** `[")
|
||||
.append(list.get(i).duration)
|
||||
.append("]` **").append(list.get(i).title).append("**");
|
||||
}
|
||||
builder.append("\nType the number of your choice to play (ex: `2`), or any invalid choice to cancel");
|
||||
Sender.sendReplyNoDelete(builder.toString(), event, m -> bot.addSearch(event, null, list, m) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright 2016 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 spectramusic.commands;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import net.dv8tion.jda.entities.Role;
|
||||
import net.dv8tion.jda.events.message.guild.GuildMessageReceivedEvent;
|
||||
import org.json.JSONObject;
|
||||
import spectramusic.Command;
|
||||
import spectramusic.Sender;
|
||||
import spectramusic.SpConst;
|
||||
import spectramusic.entities.ClumpedMusicPlayer;
|
||||
import spectramusic.util.FinderUtil;
|
||||
import spectramusic.util.FormatUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
*/
|
||||
public class SetDJCmd extends Command {
|
||||
private final JSONObject serverSettings;
|
||||
public SetDJCmd(JSONObject serverSettings)
|
||||
{
|
||||
this.serverSettings = serverSettings;
|
||||
this.command = "setdj";
|
||||
this.help = "sets a role to have access to the DJ commands "
|
||||
+ "(1 per server). If set to NONE, only admins can use DJ commands";
|
||||
this.arguments = "<role|NONE>";
|
||||
this.level = PermLevel.ADMIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(String args, GuildMessageReceivedEvent event, PermLevel caller, ClumpedMusicPlayer player) {
|
||||
JSONObject settings = serverSettings.has(event.getGuild().getId()) ? serverSettings.getJSONObject(event.getGuild().getId()) : null;
|
||||
if(args.equalsIgnoreCase("none"))
|
||||
{
|
||||
if(settings!=null)
|
||||
{
|
||||
settings.put(SpConst.DJ_JSON, "");
|
||||
}
|
||||
Sender.sendReply(SpConst.SUCCESS+"Only Admins (users with Manage Server permission) can now use DJ-level commands", event);
|
||||
}
|
||||
else
|
||||
{
|
||||
List<Role> found = FinderUtil.findRole(args, event.getGuild());
|
||||
if(found.isEmpty())
|
||||
{
|
||||
Sender.sendReply(String.format(SpConst.NONE_FOUND, "Roles",args), event);
|
||||
}
|
||||
else if (found.size()>1)
|
||||
{
|
||||
Sender.sendReply(FormatUtil.listOfRoles(found, args), event);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(settings==null)
|
||||
{
|
||||
settings = new JSONObject()
|
||||
.put(SpConst.VC_JSON, "")
|
||||
.put(SpConst.TC_JSON, "")
|
||||
.put(SpConst.DJ_JSON,found.get(0).getId());
|
||||
}
|
||||
else
|
||||
{
|
||||
settings = settings.put(SpConst.DJ_JSON,found.get(0).getId());
|
||||
}
|
||||
serverSettings.put(event.getGuild().getId(), settings);
|
||||
String msg = SpConst.SUCCESS+"DJ commands can now be used by users with the role **"+found.get(0).getName()+"**";
|
||||
try {
|
||||
Files.write(Paths.get("serversettings.json"), serverSettings.toString(4).getBytes());
|
||||
|
||||
} catch (IOException e) {
|
||||
msg+="\n"+SpConst.WARNING+"There was an error saving the settings file.";
|
||||
}
|
||||
Sender.sendReply(msg, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright 2016 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 spectramusic.commands;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import net.dv8tion.jda.entities.TextChannel;
|
||||
import net.dv8tion.jda.events.message.guild.GuildMessageReceivedEvent;
|
||||
import org.json.JSONObject;
|
||||
import spectramusic.Command;
|
||||
import spectramusic.Sender;
|
||||
import spectramusic.SpConst;
|
||||
import spectramusic.entities.ClumpedMusicPlayer;
|
||||
import spectramusic.util.FinderUtil;
|
||||
import spectramusic.util.FormatUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
*/
|
||||
public class SetTCCmd extends Command {
|
||||
private final JSONObject serverSettings;
|
||||
public SetTCCmd(JSONObject serverSettings)
|
||||
{
|
||||
this.serverSettings = serverSettings;
|
||||
this.command = "settc";
|
||||
this.help = "sets a text channel to be the only usable channel by the bot "
|
||||
+ "(1 per server). If set to NONE, the bot can use any channel";
|
||||
this.arguments = "<channel|NONE>";
|
||||
this.level = PermLevel.ADMIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(String args, GuildMessageReceivedEvent event, PermLevel caller, ClumpedMusicPlayer player) {
|
||||
JSONObject settings = serverSettings.has(event.getGuild().getId()) ? serverSettings.getJSONObject(event.getGuild().getId()) : null;
|
||||
if(args.equalsIgnoreCase("none"))
|
||||
{
|
||||
if(settings!=null)
|
||||
{
|
||||
settings.put(SpConst.TC_JSON, "");
|
||||
}
|
||||
Sender.sendReply(SpConst.SUCCESS+event.getJDA().getSelfInfo().getUsername()+" can now use any Text Channel to receive commands", event);
|
||||
}
|
||||
else
|
||||
{
|
||||
List<TextChannel> found = FinderUtil.findTextChannel(args, event.getGuild());
|
||||
if(found.isEmpty())
|
||||
{
|
||||
Sender.sendReply(String.format(SpConst.NONE_FOUND, "Text Channels",args), event);
|
||||
}
|
||||
else if (found.size()>1)
|
||||
{
|
||||
Sender.sendReply(FormatUtil.listOfTChannels(found, args), event);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(settings==null)
|
||||
{
|
||||
settings = new JSONObject()
|
||||
.put(SpConst.VC_JSON, "")
|
||||
.put(SpConst.TC_JSON, found.get(0).getId())
|
||||
.put(SpConst.DJ_JSON,"");
|
||||
}
|
||||
else
|
||||
{
|
||||
settings = settings.put(SpConst.TC_JSON, found.get(0).getId());
|
||||
}
|
||||
serverSettings.put(event.getGuild().getId(), settings);
|
||||
String msg = SpConst.SUCCESS+event.getJDA().getSelfInfo().getUsername()+" will now only receive commands in **"+found.get(0).getName()+"**";
|
||||
try {
|
||||
Files.write(Paths.get("serversettings.json"), serverSettings.toString(4).getBytes());
|
||||
|
||||
} catch (IOException e) {
|
||||
msg+="\n"+SpConst.WARNING+"There was an error saving the settings file.";
|
||||
}
|
||||
Sender.sendReply(msg, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright 2016 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 spectramusic.commands;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import net.dv8tion.jda.entities.VoiceChannel;
|
||||
import net.dv8tion.jda.events.message.guild.GuildMessageReceivedEvent;
|
||||
import org.json.JSONObject;
|
||||
import spectramusic.Command;
|
||||
import spectramusic.Sender;
|
||||
import spectramusic.SpConst;
|
||||
import spectramusic.entities.ClumpedMusicPlayer;
|
||||
import spectramusic.util.FinderUtil;
|
||||
import spectramusic.util.FormatUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
*/
|
||||
public class SetVCCmd extends Command {
|
||||
private final JSONObject serverSettings;
|
||||
public SetVCCmd(JSONObject serverSettings)
|
||||
{
|
||||
this.serverSettings = serverSettings;
|
||||
this.command = "setvc";
|
||||
this.help = "sets a voice channel to be the only usable channel by the bot "
|
||||
+ "(1 per server). If set to NONE, the bot can use any channel";
|
||||
this.arguments = "<channel|NONE>";
|
||||
this.level = PermLevel.ADMIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(String args, GuildMessageReceivedEvent event, PermLevel caller, ClumpedMusicPlayer player) {
|
||||
JSONObject settings = serverSettings.has(event.getGuild().getId()) ? serverSettings.getJSONObject(event.getGuild().getId()) : null;
|
||||
if(args.equalsIgnoreCase("none"))
|
||||
{
|
||||
if(settings!=null)
|
||||
{
|
||||
settings.put(SpConst.VC_JSON, "");
|
||||
}
|
||||
Sender.sendReply(SpConst.SUCCESS+event.getJDA().getSelfInfo().getUsername()+" can now use any Voice Channel for music", event);
|
||||
}
|
||||
else
|
||||
{
|
||||
List<VoiceChannel> found = FinderUtil.findVoiceChannel(args, event.getGuild());
|
||||
if(found.isEmpty())
|
||||
{
|
||||
Sender.sendReply(String.format(SpConst.NONE_FOUND, "Voice Channels",args), event);
|
||||
}
|
||||
else if (found.size()>1)
|
||||
{
|
||||
Sender.sendReply(FormatUtil.listOfVChannels(found, args), event);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(settings==null)
|
||||
{
|
||||
settings = new JSONObject()
|
||||
.put(SpConst.VC_JSON, found.get(0).getId())
|
||||
.put(SpConst.TC_JSON, "")
|
||||
.put(SpConst.DJ_JSON,"");
|
||||
}
|
||||
else
|
||||
{
|
||||
settings = settings.put(SpConst.VC_JSON, found.get(0).getId());
|
||||
}
|
||||
serverSettings.put(event.getGuild().getId(), settings);
|
||||
String msg = SpConst.SUCCESS+event.getJDA().getSelfInfo().getUsername()+" can now only play music in **"+found.get(0).getName()+"**";
|
||||
try {
|
||||
Files.write(Paths.get("serversettings.json"), serverSettings.toString(4).getBytes());
|
||||
|
||||
} catch (IOException e) {
|
||||
msg+="\n"+SpConst.WARNING+"There was an error saving the settings file.";
|
||||
}
|
||||
Sender.sendReply(msg, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package spectramusic.commands;
|
||||
|
||||
import net.dv8tion.jda.events.message.guild.GuildMessageReceivedEvent;
|
||||
import spectramusic.Command;
|
||||
import spectramusic.Sender;
|
||||
import spectramusic.SpConst;
|
||||
import spectramusic.entities.ClumpedMusicPlayer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author johna
|
||||
*/
|
||||
public class ShutdownCmd extends Command {
|
||||
|
||||
public ShutdownCmd()
|
||||
{
|
||||
this.command = "shutdown";
|
||||
this.help = "shuts down the bot safely";
|
||||
this.level = PermLevel.OWNER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(String args, GuildMessageReceivedEvent event, PermLevel caller, ClumpedMusicPlayer player) {
|
||||
event.getChannel().sendMessage(SpConst.WARNING+"Shutting down...");
|
||||
event.getJDA().shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package spectramusic.commands;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import net.dv8tion.jda.entities.User;
|
||||
import net.dv8tion.jda.events.message.guild.GuildMessageReceivedEvent;
|
||||
import spectramusic.Command;
|
||||
import spectramusic.Sender;
|
||||
import spectramusic.SpConst;
|
||||
import spectramusic.entities.ClumpedMusicPlayer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author johna
|
||||
*/
|
||||
public class SkipCmd extends Command {
|
||||
|
||||
public SkipCmd()
|
||||
{
|
||||
this.command = "skip";
|
||||
this.help = "skips the current song in the queue";
|
||||
this.level = PermLevel.DJ;
|
||||
this.mustBePlaying = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(String args, GuildMessageReceivedEvent event, PermLevel caller, ClumpedMusicPlayer player) {
|
||||
if(player.getCurrentTimestamp().getTotalSeconds()<1)
|
||||
{
|
||||
Sender.sendReply(SpConst.WARNING+"Please wait for the song to start before skipping.", event);
|
||||
return;
|
||||
}
|
||||
User user = event.getJDA().getUserById(player.getCurrentRequestor());
|
||||
String title = player.getCurrentAudioSource().getInfo().getTitle();
|
||||
String msg = SpConst.SUCCESS+"Skipped **"+title
|
||||
+"** (requested by "+(user==null ? "an unknown user" : "**"+user.getUsername()+"**)");
|
||||
Sender.sendReply(msg, event);
|
||||
player.skipToNext();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package spectramusic.commands;
|
||||
|
||||
import net.dv8tion.jda.entities.Role;
|
||||
import net.dv8tion.jda.entities.TextChannel;
|
||||
import net.dv8tion.jda.entities.User;
|
||||
import net.dv8tion.jda.entities.VoiceChannel;
|
||||
import net.dv8tion.jda.events.message.guild.GuildMessageReceivedEvent;
|
||||
import org.json.JSONObject;
|
||||
import spectramusic.Command;
|
||||
import spectramusic.Sender;
|
||||
import spectramusic.SpConst;
|
||||
import spectramusic.entities.ClumpedMusicPlayer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
*/
|
||||
public class StatusCmd extends Command {
|
||||
private final JSONObject serverSettings;
|
||||
private final String ownerId;
|
||||
public StatusCmd(JSONObject serverSettings, String ownerId)
|
||||
{
|
||||
this.ownerId = ownerId;
|
||||
this.serverSettings = serverSettings;
|
||||
this.command = "status";
|
||||
this.help = "shows the status and info about the bot";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(String args, GuildMessageReceivedEvent event, PermLevel caller, ClumpedMusicPlayer player) {
|
||||
JSONObject settings = serverSettings.has(event.getGuild().getId()) ? serverSettings.getJSONObject(event.getGuild().getId()) : null;
|
||||
TextChannel tc = settings==null ? null : event.getJDA().getTextChannelById(settings.getString(SpConst.TC_JSON));
|
||||
VoiceChannel vc = settings==null ? null : event.getJDA().getVoiceChannelById(settings.getString(SpConst.VC_JSON));
|
||||
Role dj = settings==null ? null : event.getGuild().getRoleById(settings.getString(SpConst.DJ_JSON));
|
||||
User owner = event.getJDA().getUserById(ownerId);
|
||||
String str = "\uD83C\uDFA7 **"+event.getJDA().getSelfInfo().getUsername()+"** status:\n"
|
||||
+SpConst.LINESTART+"Total Servers: **"+event.getJDA().getGuilds().size()+"**\n"+SpConst.LINESTART+"Audio Connections: **"
|
||||
+event.getJDA().getGuilds().stream().filter(g -> g.getVoiceStatusOfUser(event.getJDA().getSelfInfo()).inVoiceChannel()).count()
|
||||
+"**\n\n\uD83D\uDDA5 Settings on **"+event.getGuild().getName()+"**:\n"
|
||||
+SpConst.LINESTART+"Text Channel: "+(tc==null ? "any" : "**#"+tc.getName()+"**")+"\n"
|
||||
+SpConst.LINESTART+"Voice Channel: "+(vc==null ? "any" : "**"+vc.getName()+"**")+"\n"
|
||||
+SpConst.LINESTART+"DJ Role: "+(dj==null ? "none" : "**"+dj.getName()+"**")+"\n\n"
|
||||
+event.getJDA().getSelfInfo().getUsername()+" is an instance of the **Spectra Music** bot written by jagrosh in Java using the JDA-Player library."
|
||||
+ "\nThe source and instructions are available here: <https://github.com/jagrosh/Spectra-Music>"
|
||||
+ "\nThis bot's owner is "+(owner==null ? "unknown" : "**"+owner.getUsername()+"**#"+owner.getDiscriminator())+" and it is running version **"+SpConst.VERSION+"**.";
|
||||
Sender.sendReply(str, event);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright 2016 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 spectramusic.commands;
|
||||
|
||||
import net.dv8tion.jda.events.message.guild.GuildMessageReceivedEvent;
|
||||
import spectramusic.Command;
|
||||
import spectramusic.Sender;
|
||||
import spectramusic.SpConst;
|
||||
import spectramusic.entities.ClumpedMusicPlayer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
*/
|
||||
public class StopCmd extends Command {
|
||||
|
||||
public StopCmd()
|
||||
{
|
||||
this.command = "stop";
|
||||
this.help = "clears the queue and leaves the voice chat";
|
||||
this.level = PermLevel.DJ;
|
||||
this.mustBePlaying = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(String args, GuildMessageReceivedEvent event, PermLevel caller, ClumpedMusicPlayer player) {
|
||||
player.stop();
|
||||
player.getAudioQueue().clear();
|
||||
event.getGuild().getAudioManager().closeAudioConnection();
|
||||
Sender.sendReply(SpConst.SUCCESS+"The queue has been cleared and the bot has disconnected", event);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright 2016 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 spectramusic.commands;
|
||||
|
||||
import net.dv8tion.jda.events.message.guild.GuildMessageReceivedEvent;
|
||||
import spectramusic.Command;
|
||||
import spectramusic.Sender;
|
||||
import spectramusic.SpConst;
|
||||
import spectramusic.entities.ClumpedMusicPlayer;
|
||||
import spectramusic.util.FormatUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
*/
|
||||
public class VolumeCmd extends Command {
|
||||
|
||||
public VolumeCmd(){
|
||||
this.command = "volume";
|
||||
this.arguments = "<value>";
|
||||
this.aliases = new String[]{"vol"};
|
||||
this.level = PermLevel.DJ;
|
||||
this.help = "sets the volume (must be a value between 0 and 100; default is 35)";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(String args, GuildMessageReceivedEvent event, PermLevel caller, ClumpedMusicPlayer player) {
|
||||
int newVolume;
|
||||
try{
|
||||
newVolume = Integer.parseInt(args);
|
||||
} catch(NumberFormatException e)
|
||||
{
|
||||
Sender.sendReply(SpConst.ERROR+"Volume bust be an integer value between 0 and 100", event);
|
||||
return;
|
||||
}
|
||||
if(newVolume<0 || newVolume>100)
|
||||
{
|
||||
Sender.sendReply(SpConst.ERROR+"Volume bust be an integer value between 0 and 100", event);
|
||||
return;
|
||||
}
|
||||
int oldVolume = (int)(player.getVolume()*100);
|
||||
player.setVolume(newVolume/100f);
|
||||
Sender.sendReply(FormatUtil.volumeIcon(newVolume/100.0)+" Volume changed from `"+oldVolume+"` to `"+newVolume+"`", event);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package spectramusic.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import net.dv8tion.jda.entities.User;
|
||||
import net.dv8tion.jda.events.message.guild.GuildMessageReceivedEvent;
|
||||
import spectramusic.Command;
|
||||
import spectramusic.Sender;
|
||||
import spectramusic.SpConst;
|
||||
import spectramusic.entities.ClumpedMusicPlayer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author johna
|
||||
*/
|
||||
public class VoteskipCmd extends Command {
|
||||
|
||||
public VoteskipCmd()
|
||||
{
|
||||
this.command = "voteskip";
|
||||
this.help = "votes to skip the current song (needs majority vote of listeners)";
|
||||
this.mustBePlaying = true;
|
||||
this.userMustBeInVC = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(String args, GuildMessageReceivedEvent event, PermLevel caller, ClumpedMusicPlayer player) {
|
||||
int listeners = 0;
|
||||
int skippers = 0;
|
||||
ArrayList<String> checked = new ArrayList<>();
|
||||
checked.add(event.getJDA().getSelfInfo().getId());
|
||||
for(User user : event.getGuild().getVoiceStatusOfUser(event.getJDA().getSelfInfo()).getChannel().getUsers())
|
||||
{
|
||||
if(checked.contains(user.getId()) || user.isBot())
|
||||
continue;
|
||||
if(event.getGuild().getVoiceStatusOfUser(user).inVoiceChannel() && !event.getGuild().getVoiceStatusOfUser(user).isDeaf())
|
||||
listeners++;
|
||||
if(player.getCurrentSkips().contains(user.getId()))
|
||||
skippers++;
|
||||
checked.add(user.getId());
|
||||
}
|
||||
int required = (int)Math.ceil(listeners * .6);
|
||||
String msg = "";
|
||||
if(player.getCurrentSkips().contains(event.getAuthor().getId()))
|
||||
msg+=SpConst.WARNING+"You have already voted to skip this song `[";
|
||||
else
|
||||
{
|
||||
skippers++;
|
||||
player.getCurrentSkips().add(event.getAuthor().getId());
|
||||
msg+=SpConst.SUCCESS+"You voted to skip the song `[";
|
||||
}
|
||||
msg+=skippers+" votes, "+required+"/"+listeners+" needed]`";
|
||||
if(skippers>=required)
|
||||
{
|
||||
if(player.getCurrentTimestamp().getTotalSeconds()<1)
|
||||
{
|
||||
Sender.sendReply(msg+"\n"+SpConst.WARNING+"Please wait for the song to start before skipping.", event);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
User user = event.getJDA().getUserById(player.getCurrentRequestor());
|
||||
String title = player.getCurrentAudioSource().getInfo().getTitle();
|
||||
msg+="\n"+SpConst.SUCCESS+"Skipped **"+title
|
||||
+"** (requested by "+(user==null ? "an unknown user" : "**"+user.getUsername()+"**)");
|
||||
player.skipToNext();
|
||||
}
|
||||
}
|
||||
Sender.sendReply(msg, event);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Austin Keener
|
||||
*
|
||||
* 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 spectramusic.entities;
|
||||
|
||||
import net.dv8tion.jda.player.hooks.events.*;
|
||||
import net.dv8tion.jda.player.source.AudioSource;
|
||||
import net.dv8tion.jda.player.source.AudioStream;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import javafx.util.Pair;
|
||||
import net.dv8tion.jda.player.AbstractMusicPlayer;
|
||||
|
||||
public abstract class ClumpedAbstractMusicPlayer extends AbstractMusicPlayer
|
||||
{
|
||||
protected ClumpedQueue<String,AudioSource> audioQueue = new ClumpedQueue<>(2);
|
||||
protected String previousRequestor = null;
|
||||
protected String currentRequestor = null;
|
||||
protected ArrayList<String> votedSkips = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public ClumpedQueue<String,AudioSource> getAudioQueue()
|
||||
{
|
||||
return audioQueue;
|
||||
}
|
||||
|
||||
public void newQueue()
|
||||
{
|
||||
audioQueue.kill();
|
||||
audioQueue = new ClumpedQueue<>(2);
|
||||
}
|
||||
|
||||
public String getCurrentRequestor()
|
||||
{
|
||||
return currentRequestor;
|
||||
}
|
||||
|
||||
public String getPreviousRequestor()
|
||||
{
|
||||
return previousRequestor;
|
||||
}
|
||||
|
||||
public List<String> getCurrentSkips()
|
||||
{
|
||||
return votedSkips;
|
||||
}
|
||||
|
||||
// ========= Internal Functions ==========
|
||||
|
||||
@Override
|
||||
protected void play0(boolean fireEvent)
|
||||
{
|
||||
if (state == State.PLAYING)
|
||||
return;
|
||||
|
||||
if (currentAudioSource != null)
|
||||
{
|
||||
state = State.PLAYING;
|
||||
return;
|
||||
}
|
||||
|
||||
if (audioQueue.isEmpty())
|
||||
throw new IllegalStateException("MusicPlayer: The audio queue is empty! Cannot start playing.");
|
||||
|
||||
loadFromSource(audioQueue.removeFirst());
|
||||
state = State.PLAYING;
|
||||
|
||||
if (fireEvent)
|
||||
eventManager.handle(new PlayEvent(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stop0(boolean fireEvent)
|
||||
{
|
||||
if (state == State.STOPPED)
|
||||
return;
|
||||
|
||||
state = State.STOPPED;
|
||||
try
|
||||
{
|
||||
currentAudioStream.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.log(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
previousAudioSource = currentAudioSource;
|
||||
previousRequestor = currentRequestor;
|
||||
currentAudioSource = null;
|
||||
currentAudioStream = null;
|
||||
votedSkips.clear();
|
||||
}
|
||||
|
||||
if (fireEvent)
|
||||
eventManager.handle(new StopEvent(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reload0(boolean autoPlay, boolean fireEvent)
|
||||
{
|
||||
if (previousAudioSource == null && currentAudioSource == null)
|
||||
throw new IllegalStateException("Cannot restart or reload a player that has never been started!");
|
||||
|
||||
stop0(false);
|
||||
loadFromSource(new Pair<>(previousRequestor,previousAudioSource));
|
||||
|
||||
if (autoPlay)
|
||||
play0(false);
|
||||
if (fireEvent)
|
||||
eventManager.handle(new ReloadEvent(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void playNext(boolean fireEvent)
|
||||
{
|
||||
stop0(false);
|
||||
if (audioQueue.isEmpty())
|
||||
{
|
||||
if (fireEvent)
|
||||
eventManager.handle(new FinishEvent(this));
|
||||
return;
|
||||
}
|
||||
|
||||
Pair<String,AudioSource> source;
|
||||
if (shuffle)
|
||||
{
|
||||
Random rand = new Random();
|
||||
source = audioQueue.remove(rand.nextInt(audioQueue.size()));
|
||||
}
|
||||
else
|
||||
source = audioQueue.removeFirst();
|
||||
loadFromSource(source);
|
||||
|
||||
play0(false);
|
||||
if (fireEvent)
|
||||
eventManager.handle(new NextEvent(this));
|
||||
}
|
||||
|
||||
protected void loadFromSource(Pair<String,AudioSource> source)
|
||||
{
|
||||
AudioStream stream = source.getValue().asStream();
|
||||
currentAudioSource = source.getValue();
|
||||
currentAudioStream = stream;
|
||||
currentRequestor = source.getKey();
|
||||
votedSkips.clear();
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Austin Keener
|
||||
*
|
||||
* 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 spectramusic.entities;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import net.dv8tion.jda.audio.AudioConnection;
|
||||
import net.dv8tion.jda.audio.AudioSendHandler;
|
||||
|
||||
public class ClumpedMusicPlayer extends ClumpedAbstractMusicPlayer implements AudioSendHandler
|
||||
{
|
||||
|
||||
public static final int PCM_FRAME_SIZE = 4;
|
||||
private byte[] buffer = new byte[AudioConnection.OPUS_FRAME_SIZE * PCM_FRAME_SIZE];
|
||||
|
||||
@Override
|
||||
public boolean canProvide()
|
||||
{
|
||||
return state.equals(State.PLAYING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] provide20MsAudio()
|
||||
{
|
||||
// if (currentAudioStream == null || audioFormat == null)
|
||||
// throw new IllegalStateException("The Audio source was never set for this player!\n" +
|
||||
// "Please provide an AudioInputStream using setAudioSource.");
|
||||
try
|
||||
{
|
||||
int amountRead = currentAudioStream.read(buffer, 0, buffer.length);
|
||||
if (amountRead > -1)
|
||||
{
|
||||
if (amountRead < buffer.length) {
|
||||
Arrays.fill(buffer, amountRead, buffer.length - 1, (byte) 0);
|
||||
}
|
||||
if (volume != 1) {
|
||||
short sample;
|
||||
for (int i = 0; i < buffer.length; i+=2) {
|
||||
sample = (short)((buffer[ i+ 1] & 0xff) | (buffer[i] << 8));
|
||||
sample = (short) (sample * volume);
|
||||
buffer[i + 1] = (byte)(sample & 0xff);
|
||||
buffer[i] = (byte)((sample >> 8) & 0xff);
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
sourceFinished();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
if(this.getCurrentTimestamp().getMilliseconds()>0)
|
||||
{
|
||||
LOG.warn("A source closed unexpectantly? Oh well I guess...");
|
||||
sourceFinished();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright 2016 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 spectramusic.entities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import javafx.util.Pair;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
*
|
||||
* The ClumpedQueue holds Objects in an order based on the order of entry and 4
|
||||
* also on the associated "ID" item. Each clump can only contain a predefined
|
||||
* number of objects from a certain ID. When this threshold is reached, all
|
||||
* items from that ID are placed in the next clump.
|
||||
* @param <X> the item used for clump max
|
||||
* @param <Y> the items in the list
|
||||
*/
|
||||
public class ClumpedQueue<X,Y> extends LinkedList {
|
||||
private final int clumpSize;
|
||||
private final ArrayList<Clump> clumps;
|
||||
private boolean alive = true;
|
||||
|
||||
public ClumpedQueue(int clumpSize)
|
||||
{
|
||||
this.clumpSize = clumpSize;
|
||||
clumps = new ArrayList<>();
|
||||
}
|
||||
|
||||
/*
|
||||
Adds an item to the first available clump, creating a new clump
|
||||
if necessary
|
||||
|
||||
@returns the index of the new addition
|
||||
*/
|
||||
public synchronized int add(X key, Y value)
|
||||
{
|
||||
if(!alive)
|
||||
throw new UnsupportedOperationException("The current queue is dead.");
|
||||
int size = 0;
|
||||
for(Clump clump : clumps)
|
||||
{
|
||||
size+=clump.size();
|
||||
if(clump.add(key, value))
|
||||
return size;
|
||||
}
|
||||
Clump newClump = new Clump();
|
||||
newClump.add(key, value);
|
||||
clumps.add(newClump);
|
||||
return size;
|
||||
}
|
||||
|
||||
public void addAll(X key, Collection<Y> values)
|
||||
{
|
||||
values.stream().forEach(value -> add(key, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Pair<X,Y> removeFirst()
|
||||
{
|
||||
if(clumps.isEmpty())
|
||||
return null;
|
||||
Pair<X,Y> toReturn = clumps.get(0).removeFirst();
|
||||
if(clumps.get(0).isEmpty())
|
||||
clumps.remove(0);
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Pair<X,Y> remove(int index)
|
||||
{
|
||||
if(clumps.isEmpty() || index>=size())
|
||||
return null;
|
||||
Pair<X,Y> toReturn = null;
|
||||
Clump foundClump = null;
|
||||
for(Clump clump : clumps)
|
||||
if(clump.size()<=index)
|
||||
index-=clump.size();
|
||||
else
|
||||
{
|
||||
toReturn = clump.remove(index);
|
||||
foundClump = clump;
|
||||
}
|
||||
if(foundClump!=null && foundClump.isEmpty())
|
||||
clumps.remove(foundClump);
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int size()
|
||||
{
|
||||
int sum = 0;
|
||||
return clumps.stream().map((clump) -> clump.size()).reduce(sum, Integer::sum);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isEmpty()
|
||||
{
|
||||
return clumps.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Pair<X,Y> get(int index)
|
||||
{
|
||||
if(index<0 || index>=size())
|
||||
return null;
|
||||
for(Clump clump : clumps)
|
||||
if(clump.size()<=index)
|
||||
index-=clump.size();
|
||||
else
|
||||
return clump.get(index);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void clear()
|
||||
{
|
||||
clumps.clear();
|
||||
}
|
||||
|
||||
public synchronized void kill()
|
||||
{
|
||||
alive = false;
|
||||
}
|
||||
|
||||
private class Clump {
|
||||
ArrayList<Pair<X,Y>> items = new ArrayList<>();
|
||||
HashMap<X,Integer> count = new HashMap<>();
|
||||
|
||||
public boolean add(X key, Y value)
|
||||
{
|
||||
if(count.getOrDefault(key, 0)<clumpSize)
|
||||
{
|
||||
count.put(key, count.getOrDefault(key, 0)+1);
|
||||
items.add(new Pair<>(key,value));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Pair<X,Y> removeFirst()
|
||||
{
|
||||
return items.isEmpty() ? null : items.remove(0);
|
||||
}
|
||||
|
||||
public Pair<X,Y> remove(int index)
|
||||
{
|
||||
return items.remove(index);
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return items.isEmpty();
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
return items.size();
|
||||
}
|
||||
|
||||
public Pair<X,Y> get(int index)
|
||||
{
|
||||
return items.get(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright 2016 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 spectramusic.util;
|
||||
|
||||
import java.util.List;
|
||||
import net.dv8tion.jda.JDA;
|
||||
import net.dv8tion.jda.entities.Role;
|
||||
import net.dv8tion.jda.entities.TextChannel;
|
||||
import net.dv8tion.jda.entities.User;
|
||||
import net.dv8tion.jda.entities.VoiceChannel;
|
||||
import net.dv8tion.jda.player.source.AudioInfo;
|
||||
import net.dv8tion.jda.player.source.AudioTimestamp;
|
||||
import spectramusic.SpConst;
|
||||
import spectramusic.entities.ClumpedMusicPlayer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
*/
|
||||
public class FormatUtil {
|
||||
|
||||
public static String formattedAudio(ClumpedMusicPlayer player, JDA jda, boolean inTopic)
|
||||
{
|
||||
if(player.getCurrentAudioSource()==null)
|
||||
{
|
||||
return "No music playing\n\u23F9 "+progressBar(-1)+" "+volumeIcon(player.getVolume());
|
||||
}
|
||||
else
|
||||
{
|
||||
AudioInfo info = player.getCurrentAudioSource().getInfo();
|
||||
AudioTimestamp currentTime = player.getCurrentTimestamp();
|
||||
User user = jda.getUserById(player.getCurrentRequestor());
|
||||
String title = info.getError()==null ? info.getTitle() : "Error! Source: "+player.getCurrentAudioSource().getSource();
|
||||
if(inTopic && title.length()>40)
|
||||
title = title.substring(0,37)+"...";
|
||||
double progress = info.getError()==null && !info.isLive() ? (double)currentTime.getTotalSeconds() / info.getDuration().getTotalSeconds() : 0;
|
||||
String str = "**"+title+"** {"+(user==null ? "???" : user.getUsername())+"}\n\u25B6 "+progressBar(progress)
|
||||
+" "+(inTopic ? "" : "`")+"["+currentTime.getTimestamp() + "/"
|
||||
+ (info.getError()==null ? info.getDuration().getTimestamp() : "???")+"]"+(inTopic ? "" : "`")+" "
|
||||
+volumeIcon(player.getVolume());
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
private static String progressBar(double percent)
|
||||
{
|
||||
String str = "";
|
||||
for(int i=0; i<10; i++)
|
||||
if(i == (int)(percent*10))
|
||||
str+="\uD83D\uDD18";
|
||||
else
|
||||
str+="▬";
|
||||
return str;
|
||||
}
|
||||
|
||||
public static String volumeIcon(double percent)
|
||||
{
|
||||
if(percent == 0)
|
||||
return "\uD83D\uDD07";
|
||||
if(percent < .25)
|
||||
return "\uD83D\uDD08";
|
||||
if(percent < .5)
|
||||
return "\uD83D\uDD09";
|
||||
return "\uD83D\uDD0A";
|
||||
}
|
||||
|
||||
public static String listOfTChannels(List<TextChannel> list, String query)
|
||||
{
|
||||
String out = String.format(SpConst.MULTIPLE_FOUND, "text channels", query);
|
||||
for(int i=0; i<6 && i<list.size(); i++)
|
||||
out+="\n - "+list.get(i).getName()+" (<#"+list.get(i).getId()+">)";
|
||||
if(list.size()>6)
|
||||
out+="\n**And "+(list.size()-6)+" more...**";
|
||||
return out;
|
||||
}
|
||||
|
||||
public static String listOfVChannels(List<VoiceChannel> list, String query)
|
||||
{
|
||||
String out = String.format(SpConst.MULTIPLE_FOUND, "text channels", query);
|
||||
for(int i=0; i<6 && i<list.size(); i++)
|
||||
out+="\n - "+list.get(i).getName()+" (<#"+list.get(i).getId()+">)";
|
||||
if(list.size()>6)
|
||||
out+="\n**And "+(list.size()-6)+" more...**";
|
||||
return out;
|
||||
}
|
||||
|
||||
public static String listOfRoles(List<Role> list, String query)
|
||||
{
|
||||
String out = String.format(SpConst.MULTIPLE_FOUND, "roles", query);
|
||||
for(int i=0; i<6 && i<list.size(); i++)
|
||||
out+="\n - "+list.get(i).getName()+" (ID:"+list.get(i).getId()+")";
|
||||
if(list.size()>6)
|
||||
out+="\n**And "+(list.size()-6)+" more...**";
|
||||
return out;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright 2016 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 spectramusic.util;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
*/
|
||||
public class OtherUtil {
|
||||
|
||||
public static File writeArchive(String text, String txtname)
|
||||
{
|
||||
File f = new File("WrittenFiles"+File.separatorChar+txtname+".txt");
|
||||
try (BufferedWriter writer = new BufferedWriter(new FileWriter(f)))
|
||||
{
|
||||
String lines[] = text.split("\n");
|
||||
for(String line: lines)
|
||||
{
|
||||
writer.write(line+"\r\n");
|
||||
}
|
||||
writer.flush();
|
||||
}catch(IOException e){System.err.println("ERROR saving file: "+e);}
|
||||
return f;
|
||||
}
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
/*
|
||||
* 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 spectramusic.web;
|
||||
|
||||
import com.google.api.client.http.HttpRequest;
|
||||
import com.google.api.client.http.javanet.NetHttpTransport;
|
||||
import com.google.api.client.json.jackson2.JacksonFactory;
|
||||
import com.google.api.services.youtube.YouTube;
|
||||
import com.google.api.services.youtube.YouTube.Search;
|
||||
import com.google.api.services.youtube.YouTube.Videos;
|
||||
import com.google.api.services.youtube.model.SearchListResponse;
|
||||
import com.google.api.services.youtube.model.SearchResult;
|
||||
import com.google.api.services.youtube.model.Video;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.dv8tion.jda.utils.SimpleLog;
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
*/
|
||||
public class YoutubeSearcher {
|
||||
private final YouTube youtube;
|
||||
private final Search.List search;
|
||||
private final Videos.List videoInfo;
|
||||
public YoutubeSearcher(String apiKey)
|
||||
{
|
||||
youtube = new YouTube.Builder(new NetHttpTransport(), new JacksonFactory(), (HttpRequest request) -> {
|
||||
}).setApplicationName("Spectra Music JDA Java Bot").build();
|
||||
Search.List tmp = null;
|
||||
Videos.List tmp2 = null;
|
||||
try {
|
||||
tmp = youtube.search().list("id,snippet");
|
||||
tmp2 = youtube.videos().list("contentDetails");
|
||||
} catch (IOException ex) {
|
||||
SimpleLog.getLog("Youtube").fatal("Failed to initialize search or videos: "+ex.toString());
|
||||
}
|
||||
videoInfo = tmp2;
|
||||
search = tmp;
|
||||
if(search!=null)
|
||||
{
|
||||
search.setKey(apiKey);
|
||||
search.setType("video");
|
||||
search.setFields("items(id/kind,id/videoId,snippet/title,snippet/thumbnails/default/url)");
|
||||
}
|
||||
if(videoInfo!=null)
|
||||
{
|
||||
videoInfo.setKey(apiKey);
|
||||
}
|
||||
}
|
||||
|
||||
public List<YoutubeInfo> getResults(String query, int numresults)
|
||||
{
|
||||
List<YoutubeInfo> infos = new ArrayList<>();
|
||||
search.setQ(query);
|
||||
search.setMaxResults((long)numresults);
|
||||
|
||||
SearchListResponse searchResponse;
|
||||
try {
|
||||
searchResponse = search.execute();
|
||||
List<SearchResult> searchResultList = searchResponse.getItems();
|
||||
if(searchResultList.isEmpty())
|
||||
return infos;
|
||||
StringBuilder builder = new StringBuilder();
|
||||
searchResultList.stream().forEach(sr -> builder.append(", ").append(sr.getId().getVideoId()));
|
||||
List<Video> videos = videoInfo.setId(builder.toString().substring(2)).execute().getItems();
|
||||
for(int i=0; i<videos.size(); i++)
|
||||
{
|
||||
infos.add(new YoutubeInfo(videos.get(i).getId(),
|
||||
searchResultList.get(i).getSnippet().getTitle(),
|
||||
cleanDuration(Duration.parse(videos.get(i).getContentDetails().getDuration()))
|
||||
));
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
SimpleLog.getLog("Youtube").fatal("Search failure: "+ex.toString());
|
||||
return null;
|
||||
}
|
||||
return infos;
|
||||
}
|
||||
|
||||
public static String cleanDuration(Duration dur)
|
||||
{
|
||||
long seconds = dur.getSeconds();
|
||||
long hours = seconds / 3600;
|
||||
seconds = seconds % 3600;
|
||||
long minutes = seconds / 60;
|
||||
seconds = seconds % 60;
|
||||
return (hours>0 ? hours+":" : "")+(minutes>0 ? (minutes<10 ? "0" : "")+minutes+":" : "")+(seconds<10 ? "0" : "")+seconds;
|
||||
}
|
||||
|
||||
public class YoutubeInfo {
|
||||
public final String url;
|
||||
public final String title;
|
||||
public final String duration;
|
||||
public YoutubeInfo(String url, String title, String duration)
|
||||
{
|
||||
this.url = url;
|
||||
this.title = title;
|
||||
this.duration = duration;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user