package com.alecgorge.minecraft.jsonapi.adminium;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import org.bukkit.command.CommandSender;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import com.alecgorge.java.http.MutableHttpRequest;
import com.alecgorge.minecraft.jsonapi.JSONAPI;
import com.alecgorge.minecraft.jsonapi.api.JSONAPIStream;
import com.alecgorge.minecraft.jsonapi.api.JSONAPIStreamListener;
import com.alecgorge.minecraft.jsonapi.api.JSONAPIStreamMessage;
import com.alecgorge.minecraft.jsonapi.streams.ConnectionMessage;
import com.alecgorge.minecraft.jsonapi.util.FixedSizeArrayList;
public class Adminium3 implements JSONAPIStreamListener {
public static List<String> pushTypes = Arrays.asList(new String[] { "calladmin","player_join","player_quit","severe","taboo" });
public static List<String> pushTypeDescriptions = Arrays.asList(new String[] { "On /calladmin","On player join","On player quit","On SEVERE logs","Chat notifications" });
public Adminium3(JSONAPI jsonapi) {
api = jsonapi;
config = Adminium3Config.config();
api.getServer().getPluginManager().registerEvents(new AdminiumChatListener(this), api);
mcLog.addHandler(new ConsoleHandler(this));
api.registerMethods(new Adminium3Methods(this));
api.getStreamManager().getStream("connections").registerListener(this, false);
}
List<AdminiumPushNotification> notifications = Collections.synchronizedList(new FixedSizeArrayList<AdminiumPushNotification>(200));
final String APNS_PUSH_ENDPOINT = "http://push.adminiumapp.com/push-message";
JSONAPI api;
Adminium3Config config;
public final boolean doTrace = false;
Logger mcLog = Logger.getLogger("Minecraft");
public void pushNotification(String message, String push_type) {
List<String> devices = new ArrayList<String>();
for (String device : config.devices.keySet()) {
Boolean should_recieve = config.devices.get(device).get(push_type);
if (should_recieve != null && should_recieve) {
devices.add(device);
}
}
AdminiumPushNotification not = new AdminiumPushNotification(new Date(), message);
sendNotification(devices, not);
}
public boolean shouldSendNotifications() {
return JSONAPI.instance.adminiumEnabled && config.devices.keySet().size() > 0;
}
@Override
public void onMessage(JSONAPIStreamMessage message, JSONAPIStream sender) {
if (message instanceof ConnectionMessage) {
ConnectionMessage c = (ConnectionMessage) message;
if (c.TrueIsConnectedFalseIsDisconnected) {
pushNotification(c.player + " joined!", "player_join");
}
else {
pushNotification(c.player + " quit!", "player_quit");
}
}
}
public boolean calladmin(CommandSender from, String message) {
if (api.anyoneCanUseCallAdmin || from.hasPermission("jsonapi.calladmin")) {
String push = "Admin request from " + from.getName() + ": " + message;
pushNotification(push, "calladmin");
from.sendMessage("A message was sent to the admin(s).");
}
else if (!from.hasPermission("jsonapi.calladmin")) {
from.sendMessage("You don't have the jsonapi.calladmin permission to call for an admin.");
}
return true;
}
protected void sendNotification(final List<String> devices, final AdminiumPushNotification not) {
notifications.add(not);
if(!shouldSendNotifications()) {
return;
}
api.getServer().getScheduler().runTaskAsynchronously(api, new Runnable() {
@Override
public void run() {
String msg = not.getPushNotification();
MutableHttpRequest r = null;
try {
r = new MutableHttpRequest(new URL(APNS_PUSH_ENDPOINT));
for (String d : devices) {
r.addPostValue("devices[]", d);
}
r.addPostValue("message", msg);
r.post();
JSONAPI.dbug("Sending to " + APNS_PUSH_ENDPOINT + ": " + r.getPostKeys() + " -- " + r.getPostValues());
// System.out.println(String.format("Sending %s to %d (%s) devices.",
// msg, devices.size(), devices.get(0)));
}
catch (Exception e) {
mcLog.warning("The Adminium push notification server seems to be down...push notifications will not go through at this time.");
}
finally {
if (r != null)
r.close();
}
}
});
}
public class AdminiumChatListener implements Listener {
Adminium3 adminium;
Adminium3Config config = Adminium3Config.config();
public AdminiumChatListener(Adminium3 ad) {
adminium = ad;
}
@EventHandler
public void onPlayerChat(AsyncPlayerChatEvent event) {
String player = event.getPlayer().getName();
String message = event.getMessage();
String lowerMessage = message.toLowerCase();
for (String device : config.devices.keySet()) {
if (config.taboo.containsKey(device)) {
for (String taboo : config.taboo.get(device)) {
if (lowerMessage.indexOf(taboo.toLowerCase()) > -1) {
String pmessage = String.format("%s mentioned %s: %s", player, taboo, message);
AdminiumPushNotification not = new AdminiumPushNotification(new Date(), pmessage);
List<String> devices = new ArrayList<String>();
devices.add(device);
adminium.sendNotification(devices, not);
}
}
}
}
}
}
public class ConsoleHandler extends Handler {
Adminium3 adminium;
long lastNotification;
public ConsoleHandler(Adminium3 d) {
adminium = d;
lastNotification = 0;
}
@Override
public void close() throws SecurityException {
}
@Override
public void flush() {
}
@Override
public void publish(LogRecord arg0) {
if (arg0 != null && arg0.getLevel().equals(Level.SEVERE)) {
String message = "SEVERE message: " + arg0.getMessage();
long time = (new Date()).getTime();
if (time - lastNotification > 60 * 1000) {
lastNotification = time;
adminium.pushNotification(message, "severe_log");
}
}
}
}
public class AdminiumPushNotification {
Date dateSent;
String notification;
public AdminiumPushNotification(Date d, String message) {
dateSent = d;
notification = message;
}
public Date getDateSent() {
return dateSent;
}
public void setDateSent(Date dateSent) {
this.dateSent = dateSent;
}
public String getMessage() {
return notification;
}
public void setMessage(String notification) {
this.notification = notification;
}
public String getPushNotification() {
JSONAPI api = JSONAPI.instance;
String messager = getMessage();
if (api.serverName != null && !api.serverName.isEmpty()) {
messager = (api.serverName.equals("default") ? api.getServer().getServerName() : api.serverName) + ": " + messager;
}
return messager.length() > 210 ? messager.substring(0, 208) + "\u2026" : messager;
}
}
}