code cleanup

This commit is contained in:
John Grosh 2018-12-04 23:37:45 -05:00
parent c88979a6dd
commit c0f0d45138
16 changed files with 212 additions and 324 deletions

View file

@ -1,24 +1,26 @@
[download]: https://github.com/jagrosh/MusicBot/releases/latest
[release]: https://img.shields.io/github/release/jagrosh/MusicBot.svg
[setup]: https://github.com/jagrosh/MusicBot/wiki/Setup
[rpi]: https://github.com/jagrosh/MusicBot/wiki/JMusicBot-on-Raspberry-Pi
[features]: https://github.com/jagrosh/MusicBot/projects/1
## General Troubleshooting
Please check off these steps before suggesting a feature or reporting a bug:
- [ ] I am running the [latest version][download]: [![Release][release]][download]
- [ ] I have followed all instructions on the [setup page][setup] (and if applicable, [Raspberry Pi][rpi])
- [ ] I have read through the [planned and suggested features][features]
- [ ] I am running the [latest version][download]: [![Release][release]][download]
- [ ] I have followed all instructions on the [setup page][setup] (and if applicable, [Raspberry Pi][rpi])
- [ ] I have read through the [planned and suggested features][features]
## Issue
### Issue Type
- [ ] Bug Report
- [ ] Feature Request
- [ ] Bug Report
- [ ] Feature Request
### Description
Replace this with a description of your bug or feature request. Please provide screenshots and logs as applicable.
Replace this with a description of your bug or feature request. Please provide screenshots and logs as applicable.
[download]: https://github.com/jagrosh/MusicBot/releases/latest
[release]: https://img.shields.io/github/release/jagrosh/MusicBot.svg
[setup]: https://github.com/jagrosh/MusicBot/wiki/Setup
[rpi]: https://github.com/jagrosh/MusicBot/wiki/JMusicBot-on-Raspberry-Pi
[features]: https://github.com/jagrosh/MusicBot/projects/1

View file

@ -5,32 +5,32 @@
[![License](https://img.shields.io/github/license/jagrosh/MusicBot.svg)](https://github.com/jagrosh/MusicBot/blob/master/LICENSE)
[![Discord](https://discordapp.com/api/guilds/147698382092238848/widget.png)](https://discord.gg/0p9LSGoRLu6Pet0k)
# JMusicBot
## JMusicBot
A Discord music bot with a clean interface, and that is easy to set up and run yourself
[![Setup](http://i.imgur.com/VvXYp5j.png)](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
* Supports many online radio/streams
* Supports local files
* Playlist support (both web/youtube, and local)
## 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
* Supports many online radio/streams
* Supports local files
* Playlist support (both web/youtube, and local)
# Setup
## 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
## Questions/Suggestions/Bug Reports
**Please read the [Suggested/Planned Features List](https://github.com/jagrosh/MusicBot/projects/1) before suggesting a feature**. 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). (Note: I will not accept any feature requests that will require additional API keys, nor any non-music features). 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
## Example
![Example](https://i.imgur.com/tevrtKt.png)
# Editing
## Editing
This bot (and the source code here) is not meant to be edited. The main purpose of having the source public is to show the capabilities of the libraries, and to allow others to understand how the bot works. There are many requirements and dependencies required to edit and compile it, and there will not be support provided for people looking to make changes on their own. Instead, consider making a feature request (see the above section). If you still choose to make edits, please do so in accordance with the Apache 2.0 License.

View file

@ -128,7 +128,7 @@ public class JMusicBot
new PlaylistCmd(bot),
new SetavatarCmd(),
new SetgameCmd(),
new SetnameCmd(bot),
new SetnameCmd(),
new SetstatusCmd(),
new ShutdownCmd(bot)
);

View file

@ -58,10 +58,9 @@ public class Listener extends ListenerAdapter
{
String defpl = bot.getSettingsManager().getSettings(guild).getDefaultPlaylist();
VoiceChannel vc = bot.getSettingsManager().getSettings(guild).getVoiceChannel(guild);
if(defpl!=null && vc!=null)
if(defpl!=null && vc!=null && bot.getPlayerManager().setUpHandler(guild).playFromDefault())
{
if(bot.getPlayerManager().setUpHandler(guild).playFromDefault())
guild.getAudioManager().openAudioConnection(vc);
guild.getAudioManager().openAudioConnection(vc);
}
}
catch(Exception ex) {}

View file

@ -29,8 +29,6 @@ import java.util.Set;
import com.jagrosh.jmusicbot.queue.FairQueue;
import com.jagrosh.jmusicbot.settings.Settings;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import static com.jagrosh.jmusicbot.utils.FormatUtil.formatTime;
import static com.jagrosh.jmusicbot.utils.FormatUtil.volumeIcon;
import com.sedmelluq.discord.lavaplayer.source.youtube.YoutubeAudioTrack;
import net.dv8tion.jda.core.EmbedBuilder;
import net.dv8tion.jda.core.JDA;
@ -256,10 +254,10 @@ public class AudioHandler extends AudioEventAdapter implements AudioSendHandler
title = track.getInfo().uri;
return "**"+title+"** ["+(userid==0 ? "autoplay" : "<@"+userid+">")+"]"
+ "\n"+(audioPlayer.isPaused()?"\u23F8":"\u25B6")+" "
+"["+formatTime(track.getDuration())+"] "
+volumeIcon(audioPlayer.getVolume());
+"["+FormatUtil.formatTime(track.getDuration())+"] "
+FormatUtil.volumeIcon(audioPlayer.getVolume());
}
else return "No music playing \u23F9 " + volumeIcon(audioPlayer.getVolume());
else return "No music playing \u23F9 " + FormatUtil.volumeIcon(audioPlayer.getVolume());
}
// Audio Send Handler methods

View file

@ -18,13 +18,11 @@ package com.jagrosh.jmusicbot.audio;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.entities.Pair;
import com.jagrosh.jmusicbot.settings.Settings;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import net.dv8tion.jda.core.MessageBuilder;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.Game;
import net.dv8tion.jda.core.entities.Guild;

View file

@ -16,23 +16,16 @@
package com.jagrosh.jmusicbot.commands.dj;
import com.jagrosh.jdautilities.command.CommandEvent;
import com.jagrosh.jdautilities.menu.ButtonMenu;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import com.jagrosh.jmusicbot.audio.QueuedTrack;
import com.jagrosh.jmusicbot.commands.DJCommand;
import com.jagrosh.jmusicbot.commands.music.PlayCmd;
import static com.jagrosh.jmusicbot.commands.music.PlayCmd.CANCEL;
import static com.jagrosh.jmusicbot.commands.music.PlayCmd.LOAD;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import java.util.concurrent.TimeUnit;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.Message;
import net.dv8tion.jda.core.exceptions.PermissionException;
/**
*
@ -69,9 +62,9 @@ public class PlaynextCmd extends DJCommand
private class ResultHandler implements AudioLoadResultHandler
{
final Message m;
final CommandEvent event;
final boolean ytsearch;
private final Message m;
private final CommandEvent event;
private final boolean ytsearch;
private ResultHandler(Message m, CommandEvent event, boolean ytsearch)
{

View file

@ -63,5 +63,5 @@ public class RepeatCmd extends DJCommand
}
@Override
public void doCommand(CommandEvent event) {}
public void doCommand(CommandEvent event) { /* Intentionally Empty */ }
}

View file

@ -17,7 +17,6 @@ package com.jagrosh.jmusicbot.commands.general;
import com.jagrosh.jdautilities.command.Command;
import com.jagrosh.jdautilities.command.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.settings.Settings;
import net.dv8tion.jda.core.EmbedBuilder;
import net.dv8tion.jda.core.MessageBuilder;

View file

@ -99,9 +99,9 @@ public class PlayCmd extends MusicCommand
private class ResultHandler implements AudioLoadResultHandler
{
final Message m;
final CommandEvent event;
final boolean ytsearch;
private final Message m;
private final CommandEvent event;
private final boolean ytsearch;
private ResultHandler(Message m, CommandEvent event, boolean ytsearch)
{

View file

@ -73,8 +73,9 @@ public class SearchCmd extends MusicCommand
private class ResultHandler implements AudioLoadResultHandler
{
final Message m;
final CommandEvent event;
private final Message m;
private final CommandEvent event;
private ResultHandler(Message m, CommandEvent event)
{
this.m = m;

View file

@ -27,8 +27,11 @@ import com.jagrosh.jmusicbot.commands.OwnerCommand;
*/
public class EvalCmd extends OwnerCommand
{
private final Bot bot;
public EvalCmd(Bot bot)
{
this.bot = bot;
this.name = "eval";
this.help = "evaluates nashorn code";
this.guildOnly = false;
@ -38,6 +41,7 @@ public class EvalCmd extends OwnerCommand
protected void execute(CommandEvent event)
{
ScriptEngine se = new ScriptEngineManager().getEngineByName("Nashorn");
se.put("bot", bot);
se.put("event", event);
se.put("jda", event.getJDA());
se.put("guild", event.getGuild());

View file

@ -26,7 +26,7 @@ import net.dv8tion.jda.core.exceptions.RateLimitedException;
*/
public class SetnameCmd extends OwnerCommand
{
public SetnameCmd(Bot bot)
public SetnameCmd()
{
this.name = "setname";
this.help = "sets the name of the bot";
@ -37,13 +37,18 @@ public class SetnameCmd extends OwnerCommand
@Override
protected void execute(CommandEvent event)
{
try {
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) {
}
catch(RateLimitedException e)
{
event.reply(event.getClient().getError()+" Name can only be changed twice per hour!");
} catch(Exception e) {
}
catch(Exception e)
{
event.reply(event.getClient().getError()+" That name is not valid!");
}
}

View file

@ -51,7 +51,7 @@ public class GUI extends JFrame
setVisible(true);
addWindowListener(new WindowListener()
{
@Override public void windowOpened(WindowEvent e) {}
@Override public void windowOpened(WindowEvent e) { /* unused */ }
@Override public void windowClosing(WindowEvent e)
{
try
@ -63,11 +63,11 @@ public class GUI extends JFrame
System.exit(0);
}
}
@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) {}
@Override public void windowClosed(WindowEvent e) { /* unused */ }
@Override public void windowIconified(WindowEvent e) { /* unused */ }
@Override public void windowDeiconified(WindowEvent e) { /* unused */ }
@Override public void windowActivated(WindowEvent e) { /* unused */ }
@Override public void windowDeactivated(WindowEvent e) { /* unused */ }
});
}
}

View file

@ -1,111 +0,0 @@
/*
* 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();
}*/
}

View file

@ -1,147 +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);
}
/*
* 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() {
/* empty */
}
@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
{
static private final String EOL1="\n";
static private final String EOL2=System.getProperty("line.separator",EOL1);
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;
}
private synchronized void append(String val) {
values.add(val);
if(queue) { queue=false; EventQueue.invokeLater(this); }
}
private 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;
}
}
} /* END PUBLIC CLASS */