Version 1.4.0 merge from development. #6

Merged
andrewlalis merged 13 commits from development into master 2017-07-03 11:28:00 +00:00
9 changed files with 76 additions and 176 deletions
Showing only changes of commit ca56b5061a - Show all commits

View File

@ -60,7 +60,7 @@
<dependency> <dependency>
<groupId>com.github.austinv11</groupId> <groupId>com.github.austinv11</groupId>
<artifactId>Discord4J</artifactId> <artifactId>Discord4J</artifactId>
<version>2.8.2</version> <version>2.8.3</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sedmelluq</groupId> <groupId>com.sedmelluq</groupId>

View File

@ -5,16 +5,13 @@ import handiebot.command.ReactionHandler;
import handiebot.lavaplayer.MusicPlayer; import handiebot.lavaplayer.MusicPlayer;
import handiebot.view.BotLog; import handiebot.view.BotLog;
import handiebot.view.BotWindow; import handiebot.view.BotWindow;
import handiebot.view.View;
import sx.blah.discord.api.ClientBuilder; import sx.blah.discord.api.ClientBuilder;
import sx.blah.discord.api.IDiscordClient; import sx.blah.discord.api.IDiscordClient;
import sx.blah.discord.api.events.EventSubscriber; import sx.blah.discord.api.events.EventSubscriber;
import sx.blah.discord.handle.impl.events.ReadyEvent; import sx.blah.discord.handle.impl.events.ReadyEvent;
import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent;
import sx.blah.discord.handle.impl.events.guild.channel.message.reaction.ReactionEvent; import sx.blah.discord.handle.impl.events.guild.channel.message.reaction.ReactionEvent;
import sx.blah.discord.handle.obj.IGuild; import sx.blah.discord.handle.obj.IChannel;
import sx.blah.discord.handle.obj.IRole;
import sx.blah.discord.handle.obj.IUser;
import sx.blah.discord.handle.obj.Permissions; import sx.blah.discord.handle.obj.Permissions;
import sx.blah.discord.util.DiscordException; import sx.blah.discord.util.DiscordException;
import sx.blah.discord.util.RateLimitException; import sx.blah.discord.util.RateLimitException;
@ -41,7 +38,6 @@ public class HandieBot {
public static IDiscordClient client; public static IDiscordClient client;
//Display objects. //Display objects.
public static View view;
private static BotWindow window; private static BotWindow window;
public static BotLog log; public static BotLog log;
@ -90,9 +86,8 @@ public class HandieBot {
musicPlayer = new MusicPlayer(); musicPlayer = new MusicPlayer();
view = new View(); window = new BotWindow();
log = new BotLog(view.getOutputArea()); log = new BotLog(window.getOutputArea());
window = new BotWindow(view);
log.log(BotLog.TYPE.INFO, "Logging client in..."); log.log(BotLog.TYPE.INFO, "Logging client in...");
client = new ClientBuilder().withToken(TOKEN).build(); client = new ClientBuilder().withToken(TOKEN).build();
@ -101,27 +96,13 @@ public class HandieBot {
} }
/** /**
* Gets the integer value representing all permission flags. * Returns whether or not the bot has a specific permission.
* @param guild The guild to get permissions for. * @param permission The permission to check.
* @return int representing permissions. * @param channel The channel the bot wants to work in.
* @return True if the bot has permission, false otherwise.
*/ */
private int getClientPermissions(IGuild guild){ public static boolean hasPermission(Permissions permission, IChannel channel){
List<IRole> roles = client.getOurUser().getRolesForGuild(guild); return channel.getModifiedPermissions(client.getOurUser()).contains(permission);
int allPermissions = 0;
for (IRole role : roles) {
allPermissions = allPermissions | Permissions.generatePermissionsNumber(role.getPermissions());
}
return allPermissions;
}
/**
* Returns whether or not the user has a certain permission.
* @param user The user to check for permission.
* @param guild The guild to get the permissions for.
* @return True if the bot has this permission, false if not.
*/
boolean hasPermission(IUser user, IGuild guild){
return Permissions.getAllowedPermissionsForNumber(getClientPermissions(guild)).contains(user.getPermissionsForGuild(guild));
} }
/** /**

View File

@ -47,32 +47,20 @@ public class Commands {
public static void executeCommand(String command, CommandContext context){ public static void executeCommand(String command, CommandContext context){
for (Command cmd : commands) { for (Command cmd : commands) {
if (cmd.getName().equals(command)){ if (cmd.getName().equals(command)){
if (!cmd.canUserExecute(context.getUser(), context.getGuild())){ if (cmd instanceof StaticCommand){
((StaticCommand)cmd).execute();
} else if (!cmd.canUserExecute(context.getUser(), context.getGuild())){
log.log(BotLog.TYPE.ERROR, context.getGuild(), "User "+context.getUser().getName()+" does not have permission to execute "+cmd.getName()); log.log(BotLog.TYPE.ERROR, context.getGuild(), "User "+context.getUser().getName()+" does not have permission to execute "+cmd.getName());
context.getChannel().sendMessage("You do not have permission to use the command `"+command+"`."); context.getChannel().sendMessage("You do not have permission to use the command `"+command+"`.");
} } else if (cmd instanceof ContextCommand){
if (cmd instanceof ContextCommand){
((ContextCommand)cmd).execute(context); ((ContextCommand)cmd).execute(context);
return;
} else if (cmd instanceof StaticCommand){
((StaticCommand)cmd).execute();
return;
} }
} }
} }
log.log(BotLog.TYPE.ERROR, context.getGuild(), "Invalid command: "+command+" issued by "+context.getUser().getName()); if (context == null){
} log.log(BotLog.TYPE.ERROR, "Invalid command issued: "+command);
} else {
/** log.log(BotLog.TYPE.ERROR, context.getGuild(), "Invalid command: " + command + " issued by " + context.getUser().getName());
* Attempts to execute a command.
* @param command The command to execute.
* @param context The command context.
*/
public static void executeCommand(Command command, CommandContext context){
if (command instanceof ContextCommand && context != null){
((ContextCommand)command).execute(context);
} else if (command instanceof StaticCommand){
((StaticCommand)command).execute();
} }
} }

View File

@ -71,6 +71,9 @@ public class Playlist {
} }
} }
/**
* Clears the list of tracks.
*/
public void clear(){ public void clear(){
this.tracks.clear(); this.tracks.clear();
} }
@ -117,7 +120,8 @@ public class Playlist {
*/ */
public static int getShuffledIndex(int listLength){ public static int getShuffledIndex(int listLength){
float threshold = 0.2f; float threshold = 0.2f;
int trueLength = listLength - (int)threshold*listLength; int trueLength = listLength - (int)(threshold*(float)listLength);
log.log(BotLog.TYPE.INFO, "Shuffle results: Actual size: "+listLength+", Last Usable Index: "+trueLength);
Random rand = new Random(); Random rand = new Random();
//TODO Add in a small gradient in chance for a song to be picked. //TODO Add in a small gradient in chance for a song to be picked.
return rand.nextInt(trueLength); return rand.nextInt(trueLength);

View File

@ -1,14 +1,19 @@
package handiebot.utils; package handiebot.utils;
import handiebot.HandieBot;
import handiebot.view.BotLog;
import sx.blah.discord.handle.obj.IChannel; import sx.blah.discord.handle.obj.IChannel;
import sx.blah.discord.handle.obj.IMessage; import sx.blah.discord.handle.obj.IMessage;
import sx.blah.discord.handle.obj.Permissions;
import static handiebot.HandieBot.log;
/** /**
* @author Andrew Lalis * @author Andrew Lalis
* Creates a message on a channel that will disappear after some time. * Creates a message on a channel that will disappear after some time.
*/ */
public class DisappearingMessage extends Thread implements Runnable { public class DisappearingMessage extends Thread implements Runnable {
/** /**
* Creates a new disappearing message that times out after some time. * Creates a new disappearing message that times out after some time.
* @param channel The channel to write the message in. * @param channel The channel to write the message in.
@ -22,7 +27,8 @@ public class DisappearingMessage extends Thread implements Runnable {
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }
sentMessage.delete(); if (canDelete(sentMessage))
sentMessage.delete();
} }
/** /**
@ -34,11 +40,26 @@ public class DisappearingMessage extends Thread implements Runnable {
new Thread(() -> { new Thread(() -> {
try { try {
sleep(timeout); sleep(timeout);
message.delete();
} catch (InterruptedException e){ } catch (InterruptedException e){
e.printStackTrace(); e.printStackTrace();
} }
if (canDelete(message))
message.delete();
}).start(); }).start();
} }
/**
* Check to see if it is possible to delete a message before doing so.
* @param message The message that may be deleted.
* @return True if it is safe to delete, false otherwise.
*/
private static boolean canDelete(IMessage message){
if (HandieBot.hasPermission(Permissions.MANAGE_MESSAGES, message.getChannel())){
return true;
} else {
log.log(BotLog.TYPE.ERROR, message.getGuild(), "Unable to delete message. Please ensure that the bot has MANAGE_MESSAGES enabled, especially for this channel.");
return false;
}
}
} }

View File

@ -70,6 +70,7 @@ public class BotLog {
Date date = new Date(System.currentTimeMillis()); Date date = new Date(System.currentTimeMillis());
DateFormat formatter = new SimpleDateFormat("HH:mm:ss:SSS"); DateFormat formatter = new SimpleDateFormat("HH:mm:ss:SSS");
String dateFormatted = formatter.format(date); String dateFormatted = formatter.format(date);
System.out.println(dateFormatted+'['+type.name()+"] "+message);
try { try {
this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), dateFormatted, this.defaultStyle); this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), dateFormatted, this.defaultStyle);
this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), '['+type.name()+"] ", this.logStyles.get(type)); this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), '['+type.name()+"] ", this.logStyles.get(type));
@ -86,9 +87,13 @@ public class BotLog {
* @param message The content of the message. * @param message The content of the message.
*/ */
public void log(TYPE type, IGuild guild, String message){ public void log(TYPE type, IGuild guild, String message){
if (guild == null){
log(type, message);
}
Date date = new Date(System.currentTimeMillis()); Date date = new Date(System.currentTimeMillis());
DateFormat formatter = new SimpleDateFormat("HH:mm:ss:SSS"); DateFormat formatter = new SimpleDateFormat("HH:mm:ss:SSS");
String dateFormatted = formatter.format(date); String dateFormatted = formatter.format(date);
System.out.println(dateFormatted+'['+type.name()+"]["+guild.getName()+"] "+message);
try { try {
this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), dateFormatted, this.defaultStyle); this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), dateFormatted, this.defaultStyle);
this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), '['+type.name()+']', this.logStyles.get(type)); this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), '['+type.name()+']', this.logStyles.get(type));

View File

@ -15,9 +15,28 @@ import java.io.IOException;
*/ */
public class BotWindow extends JFrame { public class BotWindow extends JFrame {
public BotWindow(View view){ private JTextPane outputArea;
public BotWindow(){
super(HandieBot.APPLICATION_NAME); super(HandieBot.APPLICATION_NAME);
//Setup GUI
//Output area.
outputArea = new JTextPane();
outputArea.setBackground(Color.white);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setViewportView(outputArea);
scrollPane.setAutoscrolls(true);
getContentPane().add(scrollPane, BorderLayout.CENTER);
//Command field.
JTextField commandField = new JTextField();
commandField.setFont(new Font("Courier New", Font.PLAIN, 16));
commandField.addKeyListener(new CommandLineListener());
getContentPane().add(commandField, BorderLayout.PAGE_END);
//Standard JFrame setup code.
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
//Add a listener to override the user attempting to close the program.
addWindowListener(new WindowAdapter() { addWindowListener(new WindowAdapter() {
@Override @Override
public void windowClosing(WindowEvent e) { public void windowClosing(WindowEvent e) {
@ -34,11 +53,14 @@ public class BotWindow extends JFrame {
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
setContentPane(view.mainPanel);
setJMenuBar(new MenuBar()); setJMenuBar(new MenuBar());
setPreferredSize(new Dimension(800, 600)); setPreferredSize(new Dimension(800, 600));
pack(); pack();
setVisible(true); setVisible(true);
} }
public JTextPane getOutputArea(){
return this.outputArea;
}
} }

View File

@ -1,56 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="handiebot.view.View">
<grid id="27dc6" binding="mainPanel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<scrollpane id="d0969">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<font name="Consolas" size="12"/>
</properties>
<border type="none"/>
<children>
<component id="186aa" class="javax.swing.JTextPane" binding="outputArea">
<constraints/>
<properties>
<editable value="false"/>
<font name="Consolas" size="12"/>
<selectedTextColor color="-1"/>
<selectionColor color="-9843846"/>
<text value=""/>
</properties>
</component>
</children>
</scrollpane>
<grid id="b8806" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="f978" class="javax.swing.JTextField" binding="commandField">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties>
<font name="DialogInput" size="16"/>
<foreground color="-16118999"/>
<margin top="0" left="0" bottom="0" right="0"/>
</properties>
</component>
</children>
</grid>
</children>
</grid>
</form>

View File

@ -1,65 +0,0 @@
package handiebot.view;
import javax.swing.*;
import java.awt.*;
/**
* @author Andrew Lalis
*/
public class View {
public JPanel mainPanel;
private JTextPane outputArea;
private JTextField commandField;
public View() {
this.commandField.addKeyListener(new CommandLineListener());
}
public JTextPane getOutputArea() {
return this.outputArea;
}
{
// GUI initializer generated by IntelliJ IDEA GUI Designer
// >>> IMPORTANT!! <<<
// DO NOT EDIT OR ADD ANY CODE HERE!
$$$setupUI$$$();
}
/**
* Method generated by IntelliJ IDEA GUI Designer
* >>> IMPORTANT!! <<<
* DO NOT edit this method OR call it in your code!
*
* @noinspection ALL
*/
private void $$$setupUI$$$() {
mainPanel = new JPanel();
mainPanel.setLayout(new com.intellij.uiDesigner.core.GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1));
final JScrollPane scrollPane1 = new JScrollPane();
scrollPane1.setFont(new Font("Consolas", scrollPane1.getFont().getStyle(), 12));
mainPanel.add(scrollPane1, new com.intellij.uiDesigner.core.GridConstraints(0, 0, 1, 1, com.intellij.uiDesigner.core.GridConstraints.ANCHOR_CENTER, com.intellij.uiDesigner.core.GridConstraints.FILL_BOTH, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_SHRINK | com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_WANT_GROW, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_SHRINK | com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
outputArea = new JTextPane();
outputArea.setEditable(false);
outputArea.setFont(new Font("Consolas", outputArea.getFont().getStyle(), 12));
outputArea.setSelectedTextColor(new Color(-1));
outputArea.setSelectionColor(new Color(-9843846));
outputArea.setText("");
scrollPane1.setViewportView(outputArea);
final JPanel panel1 = new JPanel();
panel1.setLayout(new com.intellij.uiDesigner.core.GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
mainPanel.add(panel1, new com.intellij.uiDesigner.core.GridConstraints(1, 0, 1, 1, com.intellij.uiDesigner.core.GridConstraints.ANCHOR_CENTER, com.intellij.uiDesigner.core.GridConstraints.FILL_BOTH, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_SHRINK | com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_GROW, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_SHRINK | com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
commandField = new JTextField();
commandField.setFont(new Font("DialogInput", commandField.getFont().getStyle(), 16));
commandField.setForeground(new Color(-16118999));
commandField.setMargin(new Insets(0, 0, 0, 0));
panel1.add(commandField, new com.intellij.uiDesigner.core.GridConstraints(0, 0, 1, 1, com.intellij.uiDesigner.core.GridConstraints.ANCHOR_WEST, com.intellij.uiDesigner.core.GridConstraints.FILL_HORIZONTAL, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_WANT_GROW, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false));
}
/**
* @noinspection ALL
*/
public JComponent $$$getRootComponent$$$() {
return mainPanel;
}
}