diff --git a/MelooonCensor.iml b/MelooonCensor.iml
index 05b723a..06a8ede 100644
--- a/MelooonCensor.iml
+++ b/MelooonCensor.iml
@@ -24,5 +24,7 @@
+
+
\ No newline at end of file
diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml
index cdff835..0d7a09b 100644
--- a/dependency-reduced-pom.xml
+++ b/dependency-reduced-pom.xml
@@ -2,7 +2,7 @@
4.0.0
io.github.jacobmarshall.meloooncensor
- MelooonCensor
+ meloooncensor
3.0.0-SNAPSHOT
@@ -34,12 +34,22 @@
org.mcstats.*:*
+ com.bugsnag:*
+ org.json:*
org.mcstats
- io.github.jacobmarshall.meloooncensor.metrics
+ io.github.jacobmarshall.meloooncensor.lib.org.mcstats
+
+
+ com.bugsnag
+ io.github.jacobmarshall.meloooncensor.lib.com.bugsnag
+
+
+ org.json
+ io.github.jacobmarshall.meloooncensor.lib.org.json
diff --git a/pom.xml b/pom.xml
index 54ad322..121615b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
4.0.0
io.github.jacobmarshall.meloooncensor
- MelooonCensor
+ meloooncensor
3.0.0-SNAPSHOT
@@ -32,12 +32,22 @@
org.mcstats.*:*
+ com.bugsnag:*
+ org.json:*
org.mcstats
- io.github.jacobmarshall.meloooncensor.metrics
+ io.github.jacobmarshall.meloooncensor.lib.org.mcstats
+
+
+ com.bugsnag
+ io.github.jacobmarshall.meloooncensor.lib.com.bugsnag
+
+
+ org.json
+ io.github.jacobmarshall.meloooncensor.lib.org.json
@@ -91,6 +101,16 @@
R8-SNAPSHOT
compile
+
+ com.bugsnag
+ bugsnag
+ 1.3.0
+
+
+ org.json
+ json
+ 20151123
+
\ No newline at end of file
diff --git a/src/main/java/io/github/jacobmarshall/meloooncensor/MelooonCensor.java b/src/main/java/io/github/jacobmarshall/meloooncensor/MelooonCensor.java
index 7bac700..f91ed92 100644
--- a/src/main/java/io/github/jacobmarshall/meloooncensor/MelooonCensor.java
+++ b/src/main/java/io/github/jacobmarshall/meloooncensor/MelooonCensor.java
@@ -1,9 +1,13 @@
package io.github.jacobmarshall.meloooncensor;
+import com.bugsnag.Client;
import io.github.jacobmarshall.meloooncensor.config.Configuration;
import io.github.jacobmarshall.meloooncensor.listener.ChatEventListener;
import io.github.jacobmarshall.meloooncensor.command.CensorCommandExecutor;
+import io.github.jacobmarshall.meloooncensor.listener.PlayerJoinEventListener;
+import io.github.jacobmarshall.meloooncensor.updater.CheckForUpdatesTask;
import org.bukkit.plugin.java.JavaPlugin;
+import org.bukkit.scheduler.BukkitScheduler;
import org.mcstats.Metrics;
import java.io.IOException;
@@ -11,6 +15,13 @@
public class MelooonCensor extends JavaPlugin {
private Configuration config;
+ private CheckForUpdatesTask updater;
+ private Client bugsnag;
+
+ protected void startBugsnag () {
+ bugsnag = new Client("b5347687fe92ee7494d20cdf5a725fad");
+ bugsnag.setProjectPackages("io.github.jacobmarshall.meloooncensor");
+ }
protected void startMetrics () {
try {
@@ -22,10 +33,18 @@ protected void startMetrics () {
}
protected void registerEvents () {
+ getServer().getScheduler().runTaskTimerAsynchronously(
+ this, updater = new CheckForUpdatesTask(this, bugsnag), 0L, 36000L
+ );
+
getServer().getPluginManager().registerEvents(
new ChatEventListener(this.config), this
);
+ getServer().getPluginManager().registerEvents(
+ new PlayerJoinEventListener(this.updater), this
+ );
+
getCommand("censor").setExecutor(
new CensorCommandExecutor(this.config)
);
@@ -37,6 +56,7 @@ protected void setupConfig () {
@Override
public void onEnable () {
+ startBugsnag();
setupConfig();
startMetrics();
registerEvents();
diff --git a/src/main/java/io/github/jacobmarshall/meloooncensor/listener/PlayerJoinEventListener.java b/src/main/java/io/github/jacobmarshall/meloooncensor/listener/PlayerJoinEventListener.java
index c93a9a3..797bdbf 100644
--- a/src/main/java/io/github/jacobmarshall/meloooncensor/listener/PlayerJoinEventListener.java
+++ b/src/main/java/io/github/jacobmarshall/meloooncensor/listener/PlayerJoinEventListener.java
@@ -1,7 +1,30 @@
package io.github.jacobmarshall.meloooncensor.listener;
+import io.github.jacobmarshall.meloooncensor.config.Configuration;
+import io.github.jacobmarshall.meloooncensor.updater.CheckForUpdatesTask;
+import io.github.jacobmarshall.meloooncensor.updater.Release;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerJoinEvent;
public class PlayerJoinEventListener implements Listener {
+ CheckForUpdatesTask updater;
+
+ public PlayerJoinEventListener (CheckForUpdatesTask updater) {
+ this.updater = updater;
+ }
+
+ @EventHandler
+ public void onPlayerJoin (PlayerJoinEvent event) {
+ Player player = event.getPlayer();
+
+ if (player.isOp() && updater.isUpdateAvailable()) {
+ Release latestRelease = updater.getLatestRelease();
+ player.sendMessage(ChatColor.AQUA + "A new version of MelooonCensor is available, please visit " + latestRelease.getReleaseUrl() + ".");
+ }
+ }
+
}
diff --git a/src/main/java/io/github/jacobmarshall/meloooncensor/updater/CheckForUpdatesTask.java b/src/main/java/io/github/jacobmarshall/meloooncensor/updater/CheckForUpdatesTask.java
new file mode 100644
index 0000000..cb1d494
--- /dev/null
+++ b/src/main/java/io/github/jacobmarshall/meloooncensor/updater/CheckForUpdatesTask.java
@@ -0,0 +1,120 @@
+package io.github.jacobmarshall.meloooncensor.updater;
+
+import com.bugsnag.Client;
+import io.github.jacobmarshall.meloooncensor.MelooonCensor;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Iterator;
+
+public class CheckForUpdatesTask implements Runnable {
+
+ public static final String API_URL = "https://api.github.com";
+ public static final String API_ACCEPT = "application/vnd.github.v3+json";
+ public static final String REPO = "jacobmarshall/meloooncensor";
+
+ private MelooonCensor plugin;
+ private Version version;
+ private Client bugsnag;
+
+ private boolean isOutdated;
+ private Release latestRelease;
+
+ public CheckForUpdatesTask (MelooonCensor plugin, Client bugsnag) {
+ this.plugin = plugin;
+ this.bugsnag = bugsnag;
+ this.version = new Version(plugin.getDescription().getVersion());
+ }
+
+ @Override
+ public void run () {
+ boolean isOutdated = false;
+ Release latestRelease = null;
+
+ try {
+ String releasesText = sendRequest("/repos/" + REPO + "/releases");
+ if (releasesText != null) {
+ JSONArray releases = new JSONArray(releasesText);
+
+ if (releases.length() > 0) {
+ for (int index = 0; index < releases.length(); index++) {
+ Release release = Release.from(releases.getJSONObject(index));
+
+ if ( ! release.isPreRelease()) {
+ Version releaseVersion = new Version(release.getVersion());
+
+ if (releaseVersion.compareTo(version) > 0) {
+ isOutdated = true;
+ latestRelease = release;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ } catch (Exception err) {
+ bugsnag.notify(err);
+ } finally {
+ this.isOutdated = isOutdated;
+ this.latestRelease = latestRelease;
+ }
+ }
+
+ private String sendRequest (String api) {
+ HttpURLConnection connection = null;
+
+ try {
+ URL url = new URL(API_URL + "/" + api);
+ connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.setRequestProperty("Accept", API_ACCEPT);
+
+ int statusCode = connection.getResponseCode();
+
+ if (statusCode == HttpURLConnection.HTTP_OK) {
+ BufferedReader reader = null;
+
+ try {
+ reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+
+ String line;
+ StringBuilder response = new StringBuilder();
+
+ while ((line = reader.readLine()) != null) {
+ response.append(line);
+ }
+
+ return response.toString();
+ } catch (IOException err) {
+ bugsnag.notify(err);
+ } finally {
+ if (reader != null) {
+ reader.close();
+ }
+ }
+ }
+ } catch (Exception err) {
+ bugsnag.notify(err);
+ } finally {
+ if (connection != null) {
+ connection.disconnect();
+ }
+ }
+ return null;
+ }
+
+ public boolean isUpdateAvailable () {
+ return isOutdated;
+ }
+
+ public Release getLatestRelease () {
+ return latestRelease;
+ }
+
+}
diff --git a/src/main/java/io/github/jacobmarshall/meloooncensor/updater/Release.java b/src/main/java/io/github/jacobmarshall/meloooncensor/updater/Release.java
new file mode 100644
index 0000000..1f7c296
--- /dev/null
+++ b/src/main/java/io/github/jacobmarshall/meloooncensor/updater/Release.java
@@ -0,0 +1,50 @@
+package io.github.jacobmarshall.meloooncensor.updater;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+public class Release {
+
+ String version;
+ String description;
+ String downloadUrl;
+ String releaseUrl;
+ boolean isPreRelease;
+
+ private Release () {}
+
+ public String getVersion () {
+ return version;
+ }
+
+ public String getDescription () {
+ return description;
+ }
+
+ public String getDownloadUrl () {
+ return downloadUrl;
+ }
+
+ public String getReleaseUrl () {
+ return releaseUrl;
+ }
+
+ public boolean isPreRelease () {
+ return isPreRelease;
+ }
+
+ public static Release from (JSONObject json) {
+ Release release = new Release();
+ release.version = json.getString("tag_name");
+ release.description = json.getString("body");
+ {
+ JSONArray assets = json.getJSONArray("assets");
+ JSONObject jar = assets.getJSONObject(0);
+ release.downloadUrl = jar.getString("browser_download_url");
+ }
+ release.releaseUrl = json.getString("html_url");
+ release.isPreRelease = json.getBoolean("prerelease");
+ return release;
+ }
+
+}
diff --git a/src/main/java/io/github/jacobmarshall/meloooncensor/updater/Version.java b/src/main/java/io/github/jacobmarshall/meloooncensor/updater/Version.java
new file mode 100644
index 0000000..6782a2a
--- /dev/null
+++ b/src/main/java/io/github/jacobmarshall/meloooncensor/updater/Version.java
@@ -0,0 +1,61 @@
+package io.github.jacobmarshall.meloooncensor.updater;
+
+/**
+ * http://stackoverflow.com/a/11024200
+ */
+public class Version implements Comparable {
+
+ private String version;
+
+ public final String get () {
+ return this.version;
+ }
+
+ public Version (String version) {
+ if (version == null) {
+ throw new IllegalArgumentException("Version can not be null");
+ }
+ if ( ! version.matches("[0-9]+(\\.[0-9]+)*")) {
+ throw new IllegalArgumentException("Invalid version format");
+ }
+ this.version = version;
+ }
+
+ @Override
+ public int compareTo (Version that) {
+ if (that == null) {
+ return 1;
+ }
+ String[] thisParts = this.get().split("\\.");
+ String[] thatParts = that.get().split("\\.");
+ int length = Math.max(thisParts.length, thatParts.length);
+ for (int i = 0; i < length; i++) {
+ int thisPart = i < thisParts.length ?
+ Integer.parseInt(thisParts[i]) : 0;
+ int thatPart = i < thatParts.length ?
+ Integer.parseInt(thatParts[i]) : 0;
+ if (thisPart < thatPart) {
+ return -1;
+ }
+ if (thisPart > thatPart) {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean equals (Object that) {
+ if (this == that) {
+ return true;
+ }
+ if (that == null) {
+ return false;
+ }
+ if (this.getClass() != that.getClass()) {
+ return false;
+ }
+ return this.compareTo((Version) that) == 0;
+ }
+
+}
\ No newline at end of file