Merge pull request #15 from Mineplex-LLC/feature/slack-api

Add a Slack API for sending messages through plugins.
This commit is contained in:
William Burns 2016-03-27 10:15:30 +01:00
commit e7245bcc11
5 changed files with 368 additions and 8 deletions

View File

@ -1,27 +1,21 @@
package mineplex.core;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitScheduler;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import mineplex.core.command.CommandCenter;
import mineplex.core.command.ICommand;
import mineplex.core.common.util.F;
import mineplex.core.common.util.NautHashMap;
import mineplex.core.common.util.UtilTime;
import mineplex.core.common.util.UtilTime.TimeUnit;
import mineplex.core.thread.ThreadPool;
public abstract class MiniPlugin implements Listener
{
private static final ExecutorService threadPool = Executors.newCachedThreadPool(
new ThreadFactoryBuilder().setNameFormat("MiniPlugin Async %1$d").build());
protected String _moduleName = "Default";
protected JavaPlugin _plugin;
protected NautHashMap<String, ICommand> _commands;
@ -113,7 +107,7 @@ public abstract class MiniPlugin implements Listener
public void runAsync(Runnable runnable)
{
// Instead of using
threadPool.execute(runnable);
ThreadPool.ASYNC.execute(runnable);
}
public void runAsync(Runnable runnable, long time)

View File

@ -0,0 +1,129 @@
package mineplex.core.slack;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import com.google.gson.JsonObject;
import mineplex.core.thread.ThreadPool;
/**
* An API for sending and handling Slack messages.
*/
public class SlackAPI
{
// Default emoji.
public static final String DEFAULT_ICON = ":mineplex:";
// Singular instance.
private static SlackAPI _instance;
// Don't allow instantiation elsewhere.
private SlackAPI() {}
/**
* Sends a message asynchronously to a Slack channel.
*
* @param team The team which contains the target channel.
* @param channel The target channel for the message.
* @param message The message to be displayed.
* @param customTitle Whether or not to use a custom title for the message.
* If <code>false</code> the default team title is used.
*/
public void sendMessage(SlackTeam team, String channel, SlackMessage message, boolean customTitle)
{
ThreadPool.ASYNC.execute(() ->
{
// Set message title.
if (!customTitle)
{
message.setUsername(team.getTitle());
message.setIcon(DEFAULT_ICON);
}
// Set message channel.
JsonObject msg = message.toJson();
msg.addProperty("channel", channel);
// Run the call.
runWebCall(team, msg);
});
}
/**
* Runs a web call to a specified Slack incoming-hook.
*
* @param team The team to run the call on.
* @param call The call to be run.
*/
private String runWebCall(SlackTeam team, JsonObject call)
{
HttpURLConnection connection = null;
try
{
// Create connection.
URL url = new URL(team.getURL());
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setConnectTimeout(5000);
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
// Setup payload.
String payload = "payload=" + URLEncoder.encode(call.toString(), "UTF-8");
// Send request.
DataOutputStream dos = new DataOutputStream(connection.getOutputStream());
dos.writeBytes(payload);
dos.flush();
dos.close();
// Receive response.
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
String response = "";
while ((line = rd.readLine()) != null)
{
response += line + "\n";
}
rd.close();
return response.toString();
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if (connection != null)
{
// Terminate connection.
connection.disconnect();
}
}
return "500 Error";
}
/**
* Gets the singular instance of the Slack API.
*
* @return The {@link SlackAPI} instance.
*/
public static SlackAPI getInstance()
{
if (_instance == null)
{
_instance = new SlackAPI();
}
return _instance;
}
}

View File

@ -0,0 +1,139 @@
package mineplex.core.slack;
import com.google.gson.JsonObject;
/**
* A message to be sent through the {@link SlackAPI}.
*/
public class SlackMessage
{
private String _username;
private String _icon;
private String _content;
/**
* Class constructor.
*
* @param content The content of the message.
*/
public SlackMessage(String content)
{
_icon = SlackAPI.DEFAULT_ICON;
_content = content;
}
/**
* Class constructor.
*
* @param username The username of the message.
* @param content The content of the message.
*/
public SlackMessage(String username, String content)
{
_username = username;
_icon = SlackAPI.DEFAULT_ICON;
_content = content;
}
/**
* Class constructor.
*
* @param username The username of the message.
* @param icon The icon/emoji of the message.
* @param content The content of the message.
*/
public SlackMessage(String username, String icon, String content)
{
_username = username;
_icon = ":" + icon + ":";
_content = content;
}
/**
* Converts the message to JSON format.
*
* @return The {@link SlackMessage} in the form of a {@link JsonObject}.
*/
public JsonObject toJson()
{
JsonObject msg = new JsonObject();
if (_username != null)
{
msg.addProperty("username", _username);
}
if (_icon != null)
{
msg.addProperty("icon_emoji", _icon);
}
if (_content != null)
{
msg.addProperty("text", _content);
}
return msg;
}
/**
* Gets the username that displays as a title.
*
* @return The username in use.
*/
public String getUsername()
{
return _username;
}
/**
* Sets the username that displays as a title.
*
* @param username The username to use.
*/
public void setUsername(String username)
{
_username = username;
}
/**
* Gets the icon that displays with the title.
*
* @return The icon in use.
*/
public String getIcon()
{
return _icon;
}
/**
* Sets the icon that displays with the title.
*
* @param icon The icon to use.
*/
public void setIcon(String icon)
{
_icon = icon;
}
/**
* Gets the content of the message.
*
* @return The content of the message.
*/
public String getContent()
{
return _content;
}
/**
* Sets the content of the message.
*
* @param content The content of the message.
*/
public void setContent(String content)
{
_content = content;
}
}

View File

@ -0,0 +1,79 @@
package mineplex.core.slack;
/**
* An enumeration of Mineplex Slack teams.
*/
public enum SlackTeam
{
// Dev team - mineplex.slack.com
DEVELOPER("Mineplex Dev", "T045RUM7F", "B0VK6GFKN", "6GxwJsDfEpbVnQl8pYuEyq5T"),
// QA team - mineplexqa.slack.com
QA("Mineplex QA", "todo", "todo", "todo"), // TODO: new details
;
private String _title;
private String _id1;
private String _id2;
private String _token;
SlackTeam(String title, String id1, String id2, String token)
{
_title = title;
_id1 = id1;
_id2 = id2;
_token = token;
}
/**
* Gets the title that will be displayed that the top of each
* {@link SlackMessage}.
*
* @return The title of this team.
*/
public String getTitle()
{
return _title;
}
/**
* Gets the first ID of this Slack team.
*
* @return The individual first ID.
*/
public String getId1()
{
return _id1;
}
/**
* Gets the second ID of this Slack team.
*
* @return The individual second ID.
*/
public String getId2()
{
return _id2;
}
/**
* Gets the token key of this Slack team.
*
* @return The individual and <b>secret</b> token.
*/
public String getToken()
{
return _token;
}
/**
* Gets the web hook in the form of a URL.
*
* @return The URL as a string.
*/
public String getURL()
{
return "https://hooks.slack.com/services/" + getId1() + "/" + getId2() + "/" + getToken();
}
}

View File

@ -0,0 +1,19 @@
package mineplex.core.thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
/**
* A collection of threads for different uses.
*/
public class ThreadPool
{
// Async Thread
public static ExecutorService ASYNC = Executors.newCachedThreadPool(
new ThreadFactoryBuilder().setNameFormat("MiniPlugin Async %1$d").build()
);
}