mirror of
https://github.com/chrisb09/MusicBot.git
synced 2026-11-05 17:02:35 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7f690bd9a | ||
|
|
0f52bbd170 | ||
|
|
61c62032f2 | ||
|
|
eb6be6b589 | ||
|
|
25f262c6e4 | ||
|
|
f1cca0b305 | ||
|
|
6c9a497725 | ||
|
|
d87b6aa505 | ||
|
|
269dd7e0a7 | ||
|
|
f9c55ee567 | ||
|
|
8192f7a0bb | ||
|
|
5b5afe7aa8 | ||
|
|
c0dfabf0f8 | ||
|
|
2491fba863 | ||
|
|
f3d16556ff | ||
|
|
474cc1eb3e | ||
|
|
a66af36224 | ||
|
|
4471746842 | ||
|
|
9944514fab | ||
|
|
4dc60784c1 | ||
|
|
2c75c051a7 | ||
|
|
5a5cfa4ca0 | ||
|
|
f96b3251cd |
No files matched your search
@@ -1,5 +1,24 @@
|
||||
# Spectra-Music
|
||||
# JMusicBot
|
||||
A Discord music bot with a clean interface, and that is easy to set up and run yourself
|
||||
|
||||
## Note:
|
||||
This project is currently in early stages of development. If you are having trouble setting it up, or feel that it isn't complete, that's because it is not fully supported yet.
|
||||
[](https://github.com/jagrosh/MusicBot/wiki/Setup)
|
||||
|
||||
# Features
|
||||
* Easy to run (just make sure Java is installed, and run!)
|
||||
* Fast loading of songs
|
||||
* No external keys needed (besides a Discord Bot token)
|
||||
* Smooth playback
|
||||
* Server-specific setup for the "DJ" role that can moderate the music
|
||||
* Clean and beautiful menus
|
||||
* Channel-topic playback bar
|
||||
* Supports many sites, including Youtube, Soundcloud, and more
|
||||
* Playlist support (both web/youtube, and local)
|
||||
|
||||
# Setup
|
||||
Please see the [Setup Page](https://github.com/jagrosh/MusicBot/wiki/Setup) in the wiki to run this bot yourself!
|
||||
|
||||
# Questions/Suggestions/Bug Reports
|
||||
If you'd like to suggest changes to how the bot functions, recommend more customization options, or report bugs, feel free to either open an [Issue](https://github.com/jagrosh/MusicBot/issues) on this repository, or join [my Discord server](https://discord.gg/0p9LSGoRLu6Pet0k). If you like this bot, be sure to add a star to the libraries that make this possible: [**JDA**](https://github.com/DV8FromTheWorld/JDA) and [**lavaplayer**](https://github.com/sedmelluq/lavaplayer)
|
||||
|
||||
# Example
|
||||

|
||||
@@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.jagrosh</groupId>
|
||||
<artifactId>JMusicBot</artifactId>
|
||||
<version>0.0.4</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>central</id>
|
||||
<name>bintray</name>
|
||||
<url>http://jcenter.bintray.com</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-nop</artifactId>
|
||||
<version>1.7.22</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.dv8tion</groupId>
|
||||
<artifactId>JDA</artifactId>
|
||||
<version>3.0.0_168</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sedmelluq</groupId>
|
||||
<artifactId>lavaplayer</artifactId>
|
||||
<version>1.2.36</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jagrosh</groupId>
|
||||
<artifactId>JDA-Utilities</artifactId>
|
||||
<version>1.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
<version>20160810</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addClasspath>true</addClasspath>
|
||||
<mainClass>com.jagrosh.jmusicbot.JMusicBot</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.4.3</version>
|
||||
<configuration>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
</project>
|
||||
@@ -0,0 +1,388 @@
|
||||
/*
|
||||
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jagrosh.jmusicbot;
|
||||
|
||||
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 com.jagrosh.jdautilities.commandclient.Command.Category;
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jdautilities.waiter.EventWaiter;
|
||||
import com.jagrosh.jmusicbot.audio.AudioHandler;
|
||||
import com.jagrosh.jmusicbot.gui.GUI;
|
||||
import com.jagrosh.jmusicbot.utils.FormatUtil;
|
||||
import 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.getAuthor().getId().equals(event.getClient().getOwnerId()))
|
||||
return true;
|
||||
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.getAuthor().getId().equals(event.getClient().getOwnerId()))
|
||||
return true;
|
||||
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"))));
|
||||
loadedSettings.keySet().forEach((id) -> {
|
||||
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,
|
||||
o.has("volume") ? o.getInt("volume") : 100,
|
||||
o.has("default_playlist")? o.getString("default_playlist"): 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)
|
||||
{
|
||||
return setUpHandler(event.getGuild());
|
||||
}
|
||||
|
||||
public AudioHandler setUpHandler(Guild guild)
|
||||
{
|
||||
AudioHandler handler;
|
||||
if(guild.getAudioManager().getSendingHandler()==null)
|
||||
{
|
||||
AudioPlayer player = manager.createPlayer();
|
||||
if(settings.containsKey(guild.getId()))
|
||||
player.setVolume(settings.get(guild.getId()).getVolume());
|
||||
handler = new AudioHandler(player, guild, this);
|
||||
player.addListener(handler);
|
||||
guild.getAudioManager().setSendingHandler(handler);
|
||||
threadpool.scheduleWithFixedDelay(() -> updateTopic(guild,handler), 0, 5, TimeUnit.SECONDS);
|
||||
}
|
||||
else
|
||||
handler = (AudioHandler)guild.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 = "\u200B";
|
||||
else if(tchan.getTopic().contains("\u200B"))
|
||||
otherText = tchan.getTopic().substring(tchan.getTopic().indexOf("\u200B"));
|
||||
else
|
||||
otherText = "\u200B\n "+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(jda.getGuilds().isEmpty())
|
||||
{
|
||||
SimpleLog.getLog("MusicBot").warn("This bot is not on any guilds! Use the following link to add the bot to your guilds!");
|
||||
SimpleLog.getLog("MusicBot").warn(event.getJDA().asBot().getInviteUrl(JMusicBot.RECOMMENDED_PERMS));
|
||||
}
|
||||
jda.getGuilds().forEach((guild) -> {
|
||||
try
|
||||
{
|
||||
String defpl = getSettings(guild).getDefaultPlaylist();
|
||||
if(defpl!=null)
|
||||
{
|
||||
if(setUpHandler(guild).playFromDefault())
|
||||
guild.getAudioManager().openAudioConnection(guild.getVoiceChannelById(getSettings(guild).getVoiceId()));
|
||||
}
|
||||
}
|
||||
catch(Exception ex) {System.err.println(ex);}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 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,100,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,100,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(),100,null));
|
||||
}
|
||||
else
|
||||
{
|
||||
s.setRoleId(role.getId());
|
||||
}
|
||||
writeSettings();
|
||||
}
|
||||
|
||||
public void setDefaultPlaylist(Guild guild, String playlist)
|
||||
{
|
||||
Settings s = settings.get(guild.getId());
|
||||
if(s==null)
|
||||
{
|
||||
settings.put(guild.getId(), new Settings(null,null,null,100,playlist));
|
||||
}
|
||||
else
|
||||
{
|
||||
s.setDefaultPlaylist(playlist);
|
||||
}
|
||||
writeSettings();
|
||||
}
|
||||
|
||||
public void setVolume(Guild guild, int volume)
|
||||
{
|
||||
Settings s = settings.get(guild.getId());
|
||||
if(s==null)
|
||||
{
|
||||
settings.put(guild.getId(), new Settings(null,null,null,volume,null));
|
||||
}
|
||||
else
|
||||
{
|
||||
s.setVolume(volume);
|
||||
}
|
||||
writeSettings();
|
||||
}
|
||||
|
||||
public void clearTextChannel(Guild guild)
|
||||
{
|
||||
Settings s = getSettings(guild);
|
||||
if(s!=Settings.DEFAULT_SETTINGS)
|
||||
{
|
||||
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!=Settings.DEFAULT_SETTINGS)
|
||||
{
|
||||
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!=Settings.DEFAULT_SETTINGS)
|
||||
{
|
||||
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());
|
||||
if(s.getVolume()!=100)
|
||||
o.put("volume",s.getVolume());
|
||||
if(s.getDefaultPlaylist()!=null)
|
||||
o.put("default_playlist", s.getDefaultPlaylist());
|
||||
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,213 @@
|
||||
/*
|
||||
* Copyright 2016 John Grosh (jagrosh)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jagrosh.jmusicbot;
|
||||
|
||||
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 boolean nogui;
|
||||
private String prefix;
|
||||
private String token;
|
||||
private String owner;
|
||||
private String success;
|
||||
private String warning;
|
||||
private String error;
|
||||
private String game;
|
||||
private String help;
|
||||
|
||||
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;
|
||||
case "game":
|
||||
game = value;
|
||||
break;
|
||||
case "help":
|
||||
help = 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
|
||||
+ "\nPlease make sure that the files are not on your desktop or some other restricted area.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public String getGame()
|
||||
{
|
||||
return game;
|
||||
}
|
||||
|
||||
public String getHelp()
|
||||
{
|
||||
return help==null ? "help" : help;
|
||||
}
|
||||
|
||||
public boolean getNoGui()
|
||||
{
|
||||
return nogui;
|
||||
}
|
||||
|
||||
private void alert(String message)
|
||||
{
|
||||
if(nogui)
|
||||
System.out.println("[WARNING] "+message);
|
||||
else
|
||||
{
|
||||
try {
|
||||
JOptionPane.showMessageDialog(null, message, "JMusicBot", JOptionPane.WARNING_MESSAGE);
|
||||
} catch(Exception e) {
|
||||
nogui = true;
|
||||
alert("Switching to nogui mode. You can manually start in nogui mode by including the -nogui flag.");
|
||||
alert(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String prompt(String content)
|
||||
{
|
||||
if(nogui)
|
||||
{
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
System.out.println(content);
|
||||
return scanner.next();
|
||||
}
|
||||
else
|
||||
{
|
||||
try {
|
||||
return JOptionPane.showInputDialog(null, content, "JMusicBot", JOptionPane.WARNING_MESSAGE);
|
||||
} catch(Exception e) {
|
||||
nogui = true;
|
||||
alert("Switching to nogui mode. You can manually start in nogui mode by including the -nogui flag.");
|
||||
return prompt(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2016 John Grosh (jagrosh).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jagrosh.jmusicbot;
|
||||
|
||||
import java.awt.Color;
|
||||
import javax.security.auth.login.LoginException;
|
||||
import com.jagrosh.jdautilities.commandclient.CommandClient;
|
||||
import com.jagrosh.jdautilities.commandclient.CommandClientBuilder;
|
||||
import com.jagrosh.jdautilities.commandclient.examples.*;
|
||||
import com.jagrosh.jdautilities.waiter.EventWaiter;
|
||||
import com.jagrosh.jmusicbot.commands.*;
|
||||
import com.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.Permission;
|
||||
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 {
|
||||
|
||||
public static Permission[] RECOMMENDED_PERMS = new Permission[]{Permission.MESSAGE_READ, Permission.MESSAGE_WRITE, Permission.MESSAGE_HISTORY, Permission.MESSAGE_ADD_REACTION,
|
||||
Permission.MESSAGE_EMBED_LINKS, Permission.MESSAGE_ATTACH_FILES, Permission.MESSAGE_MANAGE, Permission.MESSAGE_EXT_EMOJI,
|
||||
Permission.MANAGE_CHANNEL, Permission.VOICE_CONNECT, Permission.VOICE_SPEAK, Permission.NICKNAME_CHANGE};
|
||||
/**
|
||||
* @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);
|
||||
|
||||
AboutCommand.IS_AUTHOR = false;
|
||||
|
||||
// set up the command client
|
||||
|
||||
CommandClientBuilder cb = new CommandClientBuilder()
|
||||
.setPrefix(config.getPrefix())
|
||||
.setOwnerId(config.getOwnerId())
|
||||
.setEmojis(config.getSuccess(), config.getWarning(), config.getError())
|
||||
.setHelpWord(config.getHelp())
|
||||
.addCommands(
|
||||
new AboutCommand(Color.BLUE.brighter(),
|
||||
"a music bot that is [easy to host yourself!](https://github.com/jagrosh/MusicBot)",
|
||||
new String[]{"High-quality music playback", "FairQueue™ Technology", "Easy to host yourself"},
|
||||
RECOMMENDED_PERMS),
|
||||
new PingCommand(),
|
||||
new SettingsCmd(bot),
|
||||
|
||||
new NowplayingCmd(bot),
|
||||
new PlayCmd(bot),
|
||||
new PlaylistsCmd(bot),
|
||||
new QueueCmd(bot),
|
||||
new RemoveCmd(bot),
|
||||
new SearchCmd(bot),
|
||||
new SCSearchCmd(bot),
|
||||
new ShuffleCmd(bot),
|
||||
new SkipCmd(bot),
|
||||
|
||||
new ForceskipCmd(bot),
|
||||
new SkiptoCmd(bot),
|
||||
new StopCmd(bot),
|
||||
new VolumeCmd(bot),
|
||||
|
||||
new SetdjCmd(bot),
|
||||
new SettcCmd(bot),
|
||||
new SetvcCmd(bot),
|
||||
|
||||
//new GuildlistCommand(waiter),
|
||||
new PlaylistCmd(bot),
|
||||
new SetavatarCmd(bot),
|
||||
new SetgameCmd(bot),
|
||||
new SetnameCmd(bot),
|
||||
new ShutdownCmd(bot)
|
||||
);
|
||||
if(config.getGame()==null)
|
||||
cb.useDefaultGame();
|
||||
else
|
||||
cb.setGame(Game.of(config.getGame()));
|
||||
CommandClient client = cb.build();
|
||||
|
||||
if(!config.getNoGui())
|
||||
{
|
||||
try {
|
||||
GUI gui = new GUI(bot);
|
||||
bot.setGUI(gui);
|
||||
gui.init();
|
||||
} catch(Exception e) {
|
||||
SimpleLog.getLog("Startup").fatal("Could not start GUI. If you are "
|
||||
+ "running on a server or in a location where you cannot display a "
|
||||
+ "window, please run in nogui mode using the -nogui flag.");
|
||||
}
|
||||
}
|
||||
|
||||
// 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,91 @@
|
||||
/*
|
||||
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jagrosh.jmusicbot;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class Settings {
|
||||
public final static Settings DEFAULT_SETTINGS = new Settings(null, null, null, 100, null);
|
||||
|
||||
private String textId;
|
||||
private String voiceId;
|
||||
private String roleId;
|
||||
private int volume;
|
||||
private String defaultPlaylist;
|
||||
|
||||
public Settings(String textId, String voiceId, String roleId, int volume, String defaultPlaylist)
|
||||
{
|
||||
this.textId = textId;
|
||||
this.voiceId = voiceId;
|
||||
this.roleId = roleId;
|
||||
this.volume = volume;
|
||||
this.defaultPlaylist = defaultPlaylist;
|
||||
}
|
||||
|
||||
public String getTextId()
|
||||
{
|
||||
return textId;
|
||||
}
|
||||
|
||||
public String getVoiceId()
|
||||
{
|
||||
return voiceId;
|
||||
}
|
||||
|
||||
public String getRoleId()
|
||||
{
|
||||
return roleId;
|
||||
}
|
||||
|
||||
public int getVolume()
|
||||
{
|
||||
return volume;
|
||||
}
|
||||
|
||||
public String getDefaultPlaylist()
|
||||
{
|
||||
return defaultPlaylist;
|
||||
}
|
||||
|
||||
public void setTextId(String id)
|
||||
{
|
||||
this.textId = id;
|
||||
}
|
||||
|
||||
public void setVoiceId(String id)
|
||||
{
|
||||
this.voiceId = id;
|
||||
}
|
||||
|
||||
public void setRoleId(String id)
|
||||
{
|
||||
this.roleId = id;
|
||||
}
|
||||
|
||||
public void setVolume(int volume)
|
||||
{
|
||||
this.volume = volume;
|
||||
}
|
||||
|
||||
public void setDefaultPlaylist(String defaultPlaylist)
|
||||
{
|
||||
this.defaultPlaylist = defaultPlaylist;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jagrosh.jmusicbot.audio;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.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.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.jagrosh.jmusicbot.playlist.Playlist;
|
||||
import com.jagrosh.jmusicbot.queue.FairQueue;
|
||||
import net.dv8tion.jda.core.audio.AudioSendHandler;
|
||||
import net.dv8tion.jda.core.entities.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 final List<AudioTrack> defaultQueue;
|
||||
private final Bot bot;
|
||||
private AudioFrame lastFrame;
|
||||
private QueuedTrack current;
|
||||
|
||||
public AudioHandler(AudioPlayer audioPlayer, Guild guild, Bot bot) {
|
||||
this.audioPlayer = audioPlayer;
|
||||
this.guild = guild;
|
||||
this.bot = bot;
|
||||
queue = new FairQueue<>();
|
||||
votes = new HashSet<>();
|
||||
defaultQueue = new LinkedList<>();
|
||||
}
|
||||
|
||||
public int addTrack(AudioTrack track, User user)
|
||||
{
|
||||
QueuedTrack qt = new QueuedTrack(track, user.getId());
|
||||
if(current==null)
|
||||
{
|
||||
current = qt;
|
||||
audioPlayer.playTrack(track);
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
public boolean playFromDefault()
|
||||
{
|
||||
if(!defaultQueue.isEmpty())
|
||||
{
|
||||
current = new QueuedTrack(defaultQueue.remove(0), null);
|
||||
audioPlayer.playTrack(current.getTrack());
|
||||
return true;
|
||||
}
|
||||
if(bot.getSettings(guild)==null || bot.getSettings(guild).getDefaultPlaylist()==null)
|
||||
return false;
|
||||
Playlist pl = Playlist.loadPlaylist(bot.getSettings(guild).getDefaultPlaylist());
|
||||
if(pl==null || pl.getItems().isEmpty())
|
||||
return false;
|
||||
pl.loadTracks(bot.getAudioManager(), () -> {
|
||||
if(pl.getTracks().isEmpty())
|
||||
{
|
||||
current = null;
|
||||
guild.getAudioManager().closeAudioConnection();
|
||||
}
|
||||
else
|
||||
{
|
||||
defaultQueue.addAll(pl.getTracks());
|
||||
playFromDefault();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) {
|
||||
if(queue.isEmpty())
|
||||
{
|
||||
if(!playFromDefault())
|
||||
{
|
||||
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 com.jagrosh.jmusicbot.audio;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
import com.jagrosh.jmusicbot.queue.Queueable;
|
||||
import com.jagrosh.jmusicbot.utils.FormatUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class QueuedTrack implements Queueable {
|
||||
|
||||
private final AudioTrack track;
|
||||
private final String owner;
|
||||
|
||||
public QueuedTrack(AudioTrack track, String owner)
|
||||
{
|
||||
this.track = track;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public AudioTrack getTrack()
|
||||
{
|
||||
return track;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "`["+FormatUtil.formatTime(track.getDuration())+"]` **" + track.getInfo().title +"** - <@"+owner+">";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.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,89 @@
|
||||
/*
|
||||
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import com.jagrosh.jdautilities.commandclient.Command;
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.jagrosh.jmusicbot.Settings;
|
||||
import com.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().delete().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(!event.getGuild().getSelfMember().getVoiceState().inVoiceChannel())
|
||||
try {
|
||||
event.getGuild().getAudioManager().openAudioConnection(userState.getChannel());
|
||||
}catch(PermissionException ex) {
|
||||
event.reply(event.getClient().getError()+" I am unable to connect to **"+userState.getChannel().getName()+"**!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
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 com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.jagrosh.jmusicbot.audio.AudioHandler;
|
||||
import com.jagrosh.jmusicbot.utils.FormatUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @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,167 @@
|
||||
/*
|
||||
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import com.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 com.jagrosh.jdautilities.commandclient.Command;
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.jagrosh.jmusicbot.playlist.Playlist;
|
||||
import com.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|subcommand>";
|
||||
this.help = "plays the provided song";
|
||||
this.beListening = true;
|
||||
this.bePlaying = false;
|
||||
this.children = new Command[]{new PlaylistCmd(bot)};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCommand(CommandEvent event) {
|
||||
if(event.getArgs().isEmpty())
|
||||
{
|
||||
StringBuilder builder = new StringBuilder(event.getClient().getWarning()+" Play Commands:\n");
|
||||
builder.append("\n`").append(event.getClient().getPrefix()).append(name).append(" <song title>` - plays the first result from Youtube");
|
||||
builder.append("\n`").append(event.getClient().getPrefix()).append(name).append(" <URL>` - plays the provided song, playlist, or stream");
|
||||
for(Command cmd: children)
|
||||
builder.append("\n`").append(event.getClient().getPrefix()).append(name).append(" ").append(cmd.getName()).append(" ").append(cmd.getArguments()).append("` - ").append(cmd.getHelp());
|
||||
event.reply(builder.toString());
|
||||
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; added 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();
|
||||
}
|
||||
}
|
||||
|
||||
public class PlaylistCmd extends MusicCommand {
|
||||
|
||||
public PlaylistCmd(Bot bot)
|
||||
{
|
||||
super(bot);
|
||||
this.name = "playlist";
|
||||
this.aliases = new String[]{"pl"};
|
||||
this.arguments = "<name>";
|
||||
this.help = "plays the provided playlist";
|
||||
this.beListening = true;
|
||||
this.bePlaying = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCommand(CommandEvent event) {
|
||||
if(event.getArgs().isEmpty())
|
||||
{
|
||||
event.reply(event.getClient().getError()+" Please include a playlist name.");
|
||||
return;
|
||||
}
|
||||
Playlist playlist = Playlist.loadPlaylist(event.getArgs());
|
||||
if(playlist==null)
|
||||
{
|
||||
event.reply(event.getClient().getError()+" I could not find `"+event.getArgs()+".txt` in the Playlists folder.");
|
||||
return;
|
||||
}
|
||||
event.getChannel().sendMessage("\u231A Loading playlist **"+event.getArgs()+"**...").queue(m -> {
|
||||
playlist.loadTracks(bot.getAudioManager(), () -> {
|
||||
StringBuilder builder = new StringBuilder(playlist.getTracks().isEmpty()
|
||||
? event.getClient().getWarning()+" No tracks were loaded!"
|
||||
: event.getClient().getSuccess()+" Loaded **"+playlist.getTracks().size()+"** tracks!");
|
||||
if(!playlist.getErrors().isEmpty())
|
||||
builder.append("\nThe following tracks failed to load:");
|
||||
playlist.getErrors().forEach(err -> builder.append("\n`[").append(err.getIndex()+1).append("]` **").append(err.getItem()).append("**: ").append(err.getReason()));
|
||||
String str = builder.toString();
|
||||
if(str.length()>2000)
|
||||
str = str.substring(0,1994)+" (...)";
|
||||
m.editMessage(str).queue();
|
||||
playlist.getTracks().forEach(track -> bot.queueTrack(event, track));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import com.jagrosh.jdautilities.commandclient.Command;
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.jagrosh.jmusicbot.playlist.Playlist;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class PlaylistCmd extends Command {
|
||||
|
||||
private final Bot bot;
|
||||
public PlaylistCmd(Bot bot)
|
||||
{
|
||||
this.bot = bot;
|
||||
this.category = bot.OWNER;
|
||||
this.ownerCommand = true;
|
||||
this.guildOnly = false;
|
||||
this.name = "playlist";
|
||||
this.arguments = "<append|delete|make|setdefault>";
|
||||
this.help = "playlist management";
|
||||
this.children = new Command[]{
|
||||
new ListCmd(),
|
||||
new AppendlistCmd(),
|
||||
new DeletelistCmd(),
|
||||
new MakelistCmd(),
|
||||
new DefaultlistCmd()
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandEvent event) {
|
||||
StringBuilder builder = new StringBuilder(event.getClient().getWarning()+" Playlist Management Commands:\n");
|
||||
for(Command cmd: this.children)
|
||||
builder.append("\n`").append(event.getClient().getPrefix()).append(name).append(" ").append(cmd.getName())
|
||||
.append(" ").append(cmd.getArguments()==null ? "" : cmd.getArguments()).append("` - ").append(cmd.getHelp());
|
||||
event.reply(builder.toString());
|
||||
}
|
||||
|
||||
public class MakelistCmd extends Command {
|
||||
|
||||
public MakelistCmd()
|
||||
{
|
||||
this.name = "make";
|
||||
this.aliases = new String[]{"create"};
|
||||
this.help = "makes a new playlist";
|
||||
this.arguments = "<name>";
|
||||
this.category = bot.OWNER;
|
||||
this.ownerCommand = true;
|
||||
this.guildOnly = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(CommandEvent event) {
|
||||
String pname = event.getArgs().replaceAll("\\s+", "_");
|
||||
if(Playlist.loadPlaylist(pname)==null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Files.createFile(Paths.get("Playlists"+File.separator+pname+".txt"));
|
||||
event.reply(event.getClient().getSuccess()+" Successfully created playlist `"+pname+"`!");
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
event.reply(event.getClient().getError()+" I was unable to create the playlist: "+e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
else
|
||||
event.reply(event.getClient().getError()+" Playlist `"+pname+"` already exists!");
|
||||
}
|
||||
}
|
||||
|
||||
public class DeletelistCmd extends Command {
|
||||
|
||||
public DeletelistCmd()
|
||||
{
|
||||
this.name = "delete";
|
||||
this.aliases = new String[]{"remove"};
|
||||
this.help = "deletes an existing playlist";
|
||||
this.arguments = "<name>";
|
||||
this.guildOnly = false;
|
||||
this.ownerCommand = true;
|
||||
this.category = bot.OWNER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(CommandEvent event) {
|
||||
String pname = event.getArgs().replaceAll("\\s+", "_");
|
||||
if(Playlist.loadPlaylist(pname)==null)
|
||||
event.reply(event.getClient().getError()+" Playlist `"+pname+"` doesn't exist!");
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
Files.delete(Paths.get("Playlists"+File.separator+pname+".txt"));
|
||||
event.reply(event.getClient().getSuccess()+" Successfully deleted playlist `"+pname+"`!");
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
event.reply(event.getClient().getError()+" I was unable to delete the playlist: "+e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class AppendlistCmd extends Command {
|
||||
|
||||
public AppendlistCmd()
|
||||
{
|
||||
this.name = "append";
|
||||
this.aliases = new String[]{"add"};
|
||||
this.help = "appends songs to an existing playlist";
|
||||
this.arguments = "<name> <URL> | <URL> | ...";
|
||||
this.guildOnly = false;
|
||||
this.ownerCommand = true;
|
||||
this.category = bot.OWNER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(CommandEvent event) {
|
||||
String[] parts = event.getArgs().split("\\s+", 2);
|
||||
if(parts.length<2)
|
||||
{
|
||||
event.reply(event.getClient().getError()+" Please include a playlist name and URLs to add!");
|
||||
return;
|
||||
}
|
||||
String pname = parts[0];
|
||||
Playlist playlist = Playlist.loadPlaylist(pname);
|
||||
if(playlist==null)
|
||||
event.reply(event.getClient().getError()+" Playlist `"+pname+"` doesn't exist!");
|
||||
else
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
playlist.getItems().forEach(item -> builder.append("\r\n").append(item));
|
||||
String[] urls = parts[1].split("\\|");
|
||||
for(String url: urls)
|
||||
{
|
||||
String u = url.trim();
|
||||
if(u.startsWith("<") && u.endsWith(">"))
|
||||
u = u.substring(1, u.length()-1);
|
||||
builder.append("\r\n").append(u);
|
||||
}
|
||||
try
|
||||
{
|
||||
Files.write(Paths.get("Playlists"+File.separator+pname+".txt"), builder.toString().trim().getBytes());
|
||||
event.reply(event.getClient().getSuccess()+" Successfully added "+urls.length+" songs to playlist `"+pname+"`!");
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
event.reply(event.getClient().getError()+" I was unable to append to the playlist: "+e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DefaultlistCmd extends Command {
|
||||
|
||||
public DefaultlistCmd()
|
||||
{
|
||||
this.name = "setdefault";
|
||||
this.aliases = new String[]{"default"};
|
||||
this.help = "sets the default playlist for the server";
|
||||
this.arguments = "<playlistname|NONE>";
|
||||
this.guildOnly = true;
|
||||
this.ownerCommand = true;
|
||||
this.category = bot.OWNER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(CommandEvent event) {
|
||||
if(event.getArgs().isEmpty())
|
||||
{
|
||||
event.reply(event.getClient().getError()+" Please include a playlist name or NONE");
|
||||
}
|
||||
if(event.getArgs().equalsIgnoreCase("none"))
|
||||
{
|
||||
bot.setDefaultPlaylist(event.getGuild(), null);
|
||||
event.reply(event.getClient().getSuccess()+" Cleared the default playlist for **"+event.getGuild().getName()+"**");
|
||||
return;
|
||||
}
|
||||
String pname = event.getArgs().replaceAll("\\s+", "_");
|
||||
if(Playlist.loadPlaylist(pname)==null)
|
||||
{
|
||||
event.reply(event.getClient().getError()+" Could not find `"+pname+".txt`!");
|
||||
}
|
||||
else
|
||||
{
|
||||
bot.setDefaultPlaylist(event.getGuild(), pname);
|
||||
event.reply(event.getClient().getSuccess()+" The default playlist for **"+event.getGuild().getName()+"** is now `"+pname+"`");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ListCmd extends Command {
|
||||
|
||||
public ListCmd()
|
||||
{
|
||||
this.name = "all";
|
||||
this.aliases = new String[]{"available","list"};
|
||||
this.help = "lists all available playlists";
|
||||
this.guildOnly = true;
|
||||
this.ownerCommand = true;
|
||||
this.category = bot.OWNER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(CommandEvent event) {
|
||||
if(!Playlist.folderExists())
|
||||
Playlist.createFolder();
|
||||
if(!Playlist.folderExists())
|
||||
{
|
||||
event.reply(event.getClient().getWarning()+" Playlists folder does not exist and could not be created!");
|
||||
return;
|
||||
}
|
||||
List<String> list = Playlist.getPlaylists();
|
||||
if(list==null)
|
||||
event.reply(event.getClient().getError()+" Failed to load available playlists!");
|
||||
else if(list.isEmpty())
|
||||
event.reply(event.getClient().getWarning()+" There are no playlists in the Playlists folder!");
|
||||
else
|
||||
{
|
||||
StringBuilder builder = new StringBuilder(event.getClient().getSuccess()+" Available playlists:\n");
|
||||
list.forEach(str -> builder.append("`").append(str).append("` "));
|
||||
event.reply(builder.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2017 John Grosh <john.a.grosh@gmail.com>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import java.util.List;
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.jagrosh.jmusicbot.playlist.Playlist;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class PlaylistsCmd extends MusicCommand {
|
||||
|
||||
public PlaylistsCmd(Bot bot)
|
||||
{
|
||||
super(bot);
|
||||
this.name = "playlists";
|
||||
this.help = "shows the available playlists";
|
||||
this.aliases = new String[]{"pls"};
|
||||
this.guildOnly = true;
|
||||
this.beListening = false;
|
||||
this.beListening = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCommand(CommandEvent event) {
|
||||
if(!Playlist.folderExists())
|
||||
Playlist.createFolder();
|
||||
if(!Playlist.folderExists())
|
||||
{
|
||||
event.reply(event.getClient().getWarning()+" Playlists folder does not exist and could not be created!");
|
||||
return;
|
||||
}
|
||||
List<String> list = Playlist.getPlaylists();
|
||||
if(list==null)
|
||||
event.reply(event.getClient().getError()+" Failed to load available playlists!");
|
||||
else if(list.isEmpty())
|
||||
event.reply(event.getClient().getWarning()+" There are no playlists in the Playlists folder!");
|
||||
else
|
||||
{
|
||||
StringBuilder builder = new StringBuilder(event.getClient().getSuccess()+" Available playlists:\n");
|
||||
list.forEach(str -> builder.append("`").append(str).append("` "));
|
||||
builder.append("\nType `").append(event.getClient().getTextualPrefix()).append("play playlist <name>` to play a playlist");
|
||||
event.reply(builder.toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jdautilities.menu.pagination.PaginatorBuilder;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.jagrosh.jmusicbot.audio.AudioHandler;
|
||||
import com.jagrosh.jmusicbot.audio.QueuedTrack;
|
||||
import com.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,93 @@
|
||||
/*
|
||||
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.jagrosh.jmusicbot.audio.AudioHandler;
|
||||
import com.jagrosh.jmusicbot.audio.QueuedTrack;
|
||||
import net.dv8tion.jda.core.Permission;
|
||||
import net.dv8tion.jda.core.entities.User;
|
||||
import net.dv8tion.jda.core.utils.PermissionUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @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|ALL>";
|
||||
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;
|
||||
}
|
||||
if(event.getArgs().equalsIgnoreCase("all"))
|
||||
{
|
||||
int count = handler.getQueue().removeAll(event.getAuthor().getId());
|
||||
if(count==0)
|
||||
event.reply(event.getClient().getWarning()+" You don't have any songs in the queue!");
|
||||
else
|
||||
event.reply(event.getClient().getSuccess()+" Successfully removed your "+count+" entries.");
|
||||
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 com.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 com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jdautilities.menu.orderedmenu.OrderedMenuBuilder;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.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 SCSearchCmd extends MusicCommand {
|
||||
|
||||
private final OrderedMenuBuilder builder;
|
||||
public SCSearchCmd(Bot bot)
|
||||
{
|
||||
super(bot);
|
||||
this.name = "scsearch";
|
||||
this.arguments = "<query>";
|
||||
this.help = "searches Soundcloud 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(), "scsearch:"+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();
|
||||
})
|
||||
.setCancel(() -> m.delete().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+"**]("+track.getInfo().uri+")");
|
||||
}
|
||||
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,122 @@
|
||||
/*
|
||||
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import com.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 com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jdautilities.menu.orderedmenu.OrderedMenuBuilder;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.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.aliases = new String[]{"ytsearch"};
|
||||
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();
|
||||
})
|
||||
.setCancel(() -> m.delete().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,69 @@
|
||||
/*
|
||||
* Copyright 2017 John Grosh <john.a.grosh@gmail.com>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import com.jagrosh.jdautilities.commandclient.Command;
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.jagrosh.jmusicbot.utils.OtherUtil;
|
||||
import net.dv8tion.jda.core.entities.Icon;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class SetavatarCmd extends Command {
|
||||
|
||||
public SetavatarCmd(Bot bot)
|
||||
{
|
||||
this.name = "setavatar";
|
||||
this.help = "sets the avatar 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 com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import java.util.List;
|
||||
import com.jagrosh.jdautilities.commandclient.Command;
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.jagrosh.jmusicbot.utils.FinderUtil;
|
||||
import com.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,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 com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import com.jagrosh.jdautilities.commandclient.Command;
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import net.dv8tion.jda.core.entities.Game;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class SetgameCmd extends Command {
|
||||
|
||||
public SetgameCmd(Bot bot)
|
||||
{
|
||||
this.name = "setgame";
|
||||
this.help = "sets the game the bot is playing";
|
||||
this.arguments = "[game]";
|
||||
this.ownerCommand = true;
|
||||
this.category = bot.OWNER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(CommandEvent event) {
|
||||
try {
|
||||
event.getJDA().getPresence().setGame(event.getArgs().isEmpty() ? null : Game.of(event.getArgs()));
|
||||
event.reply(event.getClient().getSuccess()+" **"+event.getSelfUser().getName()
|
||||
+"** is "+(event.getArgs().isEmpty() ? "no longer playing anything." : "now playing `"+event.getArgs()+"`"));
|
||||
} catch(Exception e) {
|
||||
event.reply(event.getClient().getError()+" The game could not be set!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import com.jagrosh.jdautilities.commandclient.Command;
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import net.dv8tion.jda.core.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 com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import java.util.List;
|
||||
import com.jagrosh.jdautilities.commandclient.Command;
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.jagrosh.jmusicbot.utils.FinderUtil;
|
||||
import com.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,67 @@
|
||||
/*
|
||||
* Copyright 2017 John Grosh <john.a.grosh@gmail.com>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import com.jagrosh.jdautilities.commandclient.Command;
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.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()+"**")
|
||||
+ "\nDefault Playlist: "+(s.getDefaultPlaylist()==null ? "None" : "**"+s.getDefaultPlaylist()+"**")
|
||||
)
|
||||
.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 com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import java.util.List;
|
||||
import com.jagrosh.jdautilities.commandclient.Command;
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.jagrosh.jmusicbot.utils.FinderUtil;
|
||||
import com.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,54 @@
|
||||
/*
|
||||
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.jagrosh.jmusicbot.audio.AudioHandler;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class ShuffleCmd extends MusicCommand {
|
||||
|
||||
public ShuffleCmd(Bot bot)
|
||||
{
|
||||
super(bot);
|
||||
this.name = "shuffle";
|
||||
this.help = "shuffles songs you have added";
|
||||
this.beListening = true;
|
||||
this.bePlaying = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCommand(CommandEvent event) {
|
||||
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
|
||||
int s = handler.getQueue().shuffle(event.getAuthor().getId());
|
||||
switch (s) {
|
||||
case 0:
|
||||
event.reply(event.getClient().getError()+" You don't have any music in the queue to shuffle!");
|
||||
break;
|
||||
case 1:
|
||||
event.reply(event.getClient().getWarning()+" You only have one song in the queue!");
|
||||
break;
|
||||
default:
|
||||
event.reply(event.getClient().getSuccess()+" You successfully shuffled your "+s+" entries.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import com.jagrosh.jdautilities.commandclient.Command;
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.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 com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.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
|
||||
+"**");
|
||||
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
|
||||
+"**"+(handler.getCurrentTrack().getIdentifier()==null ? "" : " (requested by "+(u==null ? "someone" : "**"+u.getName()+"**")+")");
|
||||
handler.getPlayer().stopTrack();
|
||||
}
|
||||
event.reply(msg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.jagrosh.jmusicbot.audio.AudioHandler;
|
||||
import net.dv8tion.jda.core.entities.User;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class SkiptoCmd extends MusicCommand {
|
||||
|
||||
public SkiptoCmd(Bot bot)
|
||||
{
|
||||
super(bot);
|
||||
this.name = "skipto";
|
||||
this.help = "skips to the specified song";
|
||||
this.arguments = "<position>";
|
||||
this.aliases = new String[]{"jumpto"};
|
||||
this.bePlaying = true;
|
||||
this.category = bot.DJ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCommand(CommandEvent event) {
|
||||
int index = 0;
|
||||
try
|
||||
{
|
||||
index = Integer.parseInt(event.getArgs());
|
||||
}
|
||||
catch(NumberFormatException e)
|
||||
{
|
||||
event.reply(event.getClient().getError()+" `"+event.getArgs()+"` is not a valid integer!");
|
||||
return;
|
||||
}
|
||||
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
|
||||
if(index<1 || index>handler.getQueue().size())
|
||||
{
|
||||
event.reply(event.getClient().getError()+" Position must be a valid integer between 1 and "+handler.getQueue().size()+"!");
|
||||
return;
|
||||
}
|
||||
handler.getQueue().skip(index-1);
|
||||
event.reply(event.getClient().getSuccess()+" Skipped to **"+handler.getQueue().get(0).getTrack().getInfo().title+"**");
|
||||
handler.getPlayer().stopTrack();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.jagrosh.jmusicbot.audio.AudioHandler;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class 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,66 @@
|
||||
/*
|
||||
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jagrosh.jmusicbot.commands;
|
||||
|
||||
import com.jagrosh.jdautilities.commandclient.CommandEvent;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.jagrosh.jmusicbot.audio.AudioHandler;
|
||||
import com.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.aliases = new String[]{"vol"};
|
||||
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 && bot.getSettings(event.getGuild())==null ? 100 : (handler==null ? bot.getSettings(event.getGuild()).getVolume() : 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);
|
||||
bot.setVolume(event.getGuild(), 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 com.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 com.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 com.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 com.jagrosh.jmusicbot.gui;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.util.List;
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import com.jagrosh.jmusicbot.Bot;
|
||||
import com.jagrosh.jmusicbot.audio.AudioHandler;
|
||||
import com.jagrosh.jmusicbot.utils.FormatUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh <john.a.grosh@gmail.com>
|
||||
*/
|
||||
public class GuildsPanel extends JPanel {
|
||||
|
||||
private final Bot bot;
|
||||
private final JList guildList;
|
||||
private final JTextArea guildQueue;
|
||||
private int index = -1;
|
||||
|
||||
public GuildsPanel(Bot bot)
|
||||
{
|
||||
super();
|
||||
super.setLayout(new GridBagLayout());
|
||||
this.bot = bot;
|
||||
|
||||
guildList = new JList();
|
||||
guildQueue = new JTextArea();
|
||||
guildList.setModel(new DefaultListModel());
|
||||
guildList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
guildList.setFixedCellHeight(20);
|
||||
guildList.setPreferredSize(new Dimension(100,300));
|
||||
guildQueue.setPreferredSize(new Dimension(300,300));
|
||||
guildQueue.setEditable(false);
|
||||
JScrollPane pane = new JScrollPane();
|
||||
JScrollPane pane2 = new JScrollPane();
|
||||
pane.setViewportView(guildList);
|
||||
pane2.setViewportView(guildQueue);
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
c.anchor = GridBagConstraints.LINE_START;
|
||||
c.gridx = 0;
|
||||
c.gridwidth = 1;
|
||||
super.add(pane, c);
|
||||
c.gridx = 1;
|
||||
c.gridwidth = 3;
|
||||
super.add(pane2, c);
|
||||
//bot.registerPanel(this);
|
||||
guildList.addListSelectionListener((ListSelectionEvent e) -> {
|
||||
index = guildList.getSelectedIndex();
|
||||
//bot.updatePanel();
|
||||
});
|
||||
}
|
||||
|
||||
public void updateList(List<Guild> guilds)
|
||||
{
|
||||
String[] strs = new String[guilds.size()];
|
||||
for(int i=0; i<guilds.size(); i++)
|
||||
strs[i] = guilds.get(i).getName();
|
||||
guildList.setListData(strs);
|
||||
}
|
||||
|
||||
public int getIndex()
|
||||
{
|
||||
return guildList.getSelectedIndex();
|
||||
}
|
||||
|
||||
public void updatePanel(AudioHandler handler) {
|
||||
StringBuilder builder = new StringBuilder("Now Playing: ");
|
||||
if(handler==null || handler.getCurrentTrack()==null)
|
||||
{
|
||||
builder.append("nothing");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.append(handler.getCurrentTrack().getTrack().getInfo().title)
|
||||
.append(" [")
|
||||
.append(FormatUtil.formatTime(handler.getCurrentTrack().getTrack().getDuration()))
|
||||
.append("]\n");
|
||||
for(int i=0; i<handler.getQueue().size(); i++)
|
||||
builder.append("\n").append(i+1).append(". ").append(handler.getQueue().get(i).getTrack().getInfo().title);
|
||||
}
|
||||
guildQueue.setText(builder.toString());
|
||||
guildQueue.updateUI();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 com.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,186 @@
|
||||
/*
|
||||
* 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 com.jagrosh.jmusicbot.playlist;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
|
||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
|
||||
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (john.a.grosh@gmail.com)
|
||||
*/
|
||||
public class Playlist {
|
||||
|
||||
private final String name;
|
||||
private final List<String> items;
|
||||
private List<AudioTrack> tracks;
|
||||
private List<PlaylistLoadError> errors;
|
||||
|
||||
private Playlist(String name, List<String> items)
|
||||
{
|
||||
this.name = name;
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
public void loadTracks(AudioPlayerManager manager, Runnable callback)
|
||||
{
|
||||
if(tracks==null)
|
||||
{
|
||||
tracks = new LinkedList<>();
|
||||
errors = new LinkedList<>();
|
||||
for(int i=0; i<items.size(); i++)
|
||||
{
|
||||
boolean last = i+1==items.size();
|
||||
int index = i;
|
||||
manager.loadItemOrdered(name, items.get(i), new AudioLoadResultHandler() {
|
||||
@Override
|
||||
public void trackLoaded(AudioTrack at) {
|
||||
tracks.add(at);
|
||||
if(last && callback!=null)
|
||||
callback.run();
|
||||
}
|
||||
@Override
|
||||
public void playlistLoaded(AudioPlaylist ap) {
|
||||
if(ap.isSearchResult())
|
||||
tracks.add(ap.getTracks().get(0));
|
||||
else if(ap.getSelectedTrack()!=null)
|
||||
tracks.add(ap.getSelectedTrack());
|
||||
else
|
||||
tracks.addAll(ap.getTracks());
|
||||
if(last && callback!=null)
|
||||
callback.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void noMatches() {
|
||||
errors.add(new PlaylistLoadError(index, items.get(index), "No matches found."));
|
||||
if(last && callback!=null)
|
||||
callback.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadFailed(FriendlyException fe) {
|
||||
errors.add(new PlaylistLoadError(index, items.get(index), "Failed to load track: "+fe.getLocalizedMessage()));
|
||||
if(last && callback!=null)
|
||||
callback.run();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<String> getItems()
|
||||
{
|
||||
return items;
|
||||
}
|
||||
|
||||
public List<AudioTrack> getTracks()
|
||||
{
|
||||
return tracks;
|
||||
}
|
||||
|
||||
public List<PlaylistLoadError> getErrors()
|
||||
{
|
||||
return errors;
|
||||
}
|
||||
|
||||
public static void createFolder()
|
||||
{
|
||||
try
|
||||
{
|
||||
Files.createDirectory(Paths.get("Playlists"));
|
||||
} catch (IOException ex)
|
||||
{}
|
||||
}
|
||||
|
||||
public static boolean folderExists()
|
||||
{
|
||||
return Files.exists(Paths.get("Playlists"));
|
||||
}
|
||||
|
||||
public static List<String> getPlaylists()
|
||||
{
|
||||
if(folderExists())
|
||||
{
|
||||
File folder = new File("Playlists");
|
||||
return Arrays.asList(folder.listFiles((pathname) -> pathname.getName().endsWith(".txt")))
|
||||
.stream().map(f -> f.getName().substring(0,f.getName().length()-4)).collect(Collectors.toList());
|
||||
}
|
||||
else
|
||||
{
|
||||
createFolder();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Playlist loadPlaylist(String name)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(folderExists())
|
||||
{
|
||||
return new Playlist(name, Files.readAllLines(Paths.get("Playlists"+File.separator+name+".txt"))
|
||||
.stream()
|
||||
.map((str) -> str.trim())
|
||||
.filter((s) -> (!s.isEmpty() && !s.startsWith("#") && !s.startsWith("//")))
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
else
|
||||
{
|
||||
createFolder();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class PlaylistLoadError {
|
||||
private final int number;
|
||||
private final String item;
|
||||
private final String reason;
|
||||
|
||||
private PlaylistLoadError(int number, String item, String reason)
|
||||
{
|
||||
this.number = number;
|
||||
this.item = item;
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public int getIndex()
|
||||
{
|
||||
return number;
|
||||
}
|
||||
|
||||
public String getItem()
|
||||
{
|
||||
return item;
|
||||
}
|
||||
|
||||
public String getReason()
|
||||
{
|
||||
return reason;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 2016 John Grosh (jagrosh).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jagrosh.jmusicbot.queue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author John Grosh (jagrosh)
|
||||
* @param <T>
|
||||
*/
|
||||
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 int removeAll(String identifier)
|
||||
{
|
||||
int count = 0;
|
||||
for(int i=list.size()-1; i>=0; i--)
|
||||
{
|
||||
if(list.get(i).getIdentifier().equals(identifier))
|
||||
{
|
||||
list.remove(i);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
list.clear();
|
||||
}
|
||||
|
||||
public int shuffle(String identifier)
|
||||
{
|
||||
List<Integer> iset = new ArrayList<>();
|
||||
for(int i=0; i<list.size(); i++)
|
||||
{
|
||||
if(list.get(i).getIdentifier().equals(identifier))
|
||||
iset.add(i);
|
||||
}
|
||||
for(int j=0; j<iset.size(); j++)
|
||||
{
|
||||
int first = iset.get(j);
|
||||
int second = iset.get((int)(Math.random()*iset.size()));
|
||||
T temp = list.get(first);
|
||||
list.set(first, list.get(second));
|
||||
list.set(second, temp);
|
||||
}
|
||||
return iset.size();
|
||||
}
|
||||
|
||||
public void skip(int number)
|
||||
{
|
||||
for(int i=0; i<number; i++)
|
||||
list.remove(0);
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -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 com.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 com.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,117 @@
|
||||
/*
|
||||
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jagrosh.jmusicbot.utils;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
import java.util.List;
|
||||
import com.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)
|
||||
{
|
||||
if(duration == Long.MAX_VALUE)
|
||||
return "LIVE";
|
||||
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)
|
||||
return "No music playing\n\u23F9 "+progressBar(-1)+" "+volumeIcon(100);
|
||||
else if (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==null ? "autoplay" : "<@"+userid+">") : user.getName())+"]\n\u25B6 "+progressBar(progress)
|
||||
+" "+(inTopic ? "" : "`")+"["+formatTime(track.getPosition()) + "/" + formatTime(track.getDuration())
|
||||
+"]"+(inTopic ? "" : "`")+" " +volumeIcon(handler.getPlayer().getVolume())
|
||||
+(inTopic ? "" : "\n**<"+track.getInfo().uri+">**");
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
private static String progressBar(double percent)
|
||||
{
|
||||
String str = "";
|
||||
for(int i=0; i<8; i++)
|
||||
if(i == (int)(percent*8))
|
||||
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 com.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