diff options
author | Cow <cow@volloeko.de> | 2020-04-26 03:43:30 +0200 |
---|---|---|
committer | Cow <cow@volloeko.de> | 2020-04-26 03:43:30 +0200 |
commit | 35553dceb9c683000095ce1a62b4e094234304bc (patch) | |
tree | 8ed09cd69ba877be4defe9583007333c8164f8f0 /src/main/java/eu/olli | |
parent | f0686a8e45528e3dd682a6f7a69dd904730f6fb1 (diff) | |
download | Cowlection-35553dceb9c683000095ce1a62b4e094234304bc.tar.gz Cowlection-35553dceb9c683000095ce1a62b4e094234304bc.tar.bz2 Cowlection-35553dceb9c683000095ce1a62b4e094234304bc.zip |
Improved output of player stalking feature
- offline players now include 'offline for <duration>'
- better handling of special cases (e.g. nicked players)
- also: simplified API requests and config handling
Diffstat (limited to 'src/main/java/eu/olli')
5 files changed, 99 insertions, 39 deletions
diff --git a/src/main/java/eu/olli/cowmoonication/command/MooCommand.java b/src/main/java/eu/olli/cowmoonication/command/MooCommand.java index a38eec7..58d01a5 100644 --- a/src/main/java/eu/olli/cowmoonication/command/MooCommand.java +++ b/src/main/java/eu/olli/cowmoonication/command/MooCommand.java @@ -1,5 +1,6 @@ package eu.olli.cowmoonication.command; +import com.mojang.realmsclient.util.Pair; import eu.olli.cowmoonication.Cowmoonication; import eu.olli.cowmoonication.config.MooConfig; import eu.olli.cowmoonication.config.MooGuiConfig; @@ -15,7 +16,6 @@ import net.minecraft.command.ICommandSender; import net.minecraft.event.ClickEvent; import net.minecraft.event.HoverEvent; import net.minecraft.util.*; -import org.apache.commons.lang3.time.DurationFormatUtils; import java.awt.*; import java.io.IOException; @@ -179,12 +179,24 @@ public class MooCommand extends CommandBase { ApiUtils.fetchPlayerOfflineStatus(stalkedPlayer, slothStalking -> { if (slothStalking == null) { main.getChatHelper().sendMessage(EnumChatFormatting.RED, "Something went wrong contacting the Slothpixel API. Couldn't stalk " + EnumChatFormatting.DARK_RED + stalkedPlayer.getName() + EnumChatFormatting.RED + " but they appear to be offline currently."); - } else if (slothStalking.getLastLogout() < 1) { // last_logout == null in API response + } else if (slothStalking.hasNeverJoinedHypixel()) { + main.getChatHelper().sendMessage(EnumChatFormatting.YELLOW, stalkedPlayer.getName() + EnumChatFormatting.YELLOW + " has " + EnumChatFormatting.GOLD + "never " + EnumChatFormatting.YELLOW + "been on Hypixel (or might be nicked)."); + } else if (slothStalking.isHidingOnlineStatus()) { main.getChatHelper().sendMessage(EnumChatFormatting.YELLOW, slothStalking.getPlayerNameFormatted() + EnumChatFormatting.YELLOW + " is hiding their online status."); + } else if (slothStalking.hasNeverLoggedOut()) { + Pair<String, String> lastOnline = Utils.getLastOnlineWords(slothStalking.getLastLogin()); + + main.getChatHelper().sendMessage(EnumChatFormatting.YELLOW, slothStalking.getPlayerNameFormatted() + EnumChatFormatting.YELLOW + " was last online " + EnumChatFormatting.GOLD + lastOnline.first() + EnumChatFormatting.YELLOW + " ago" + + (lastOnline.second() != null ? " (" + EnumChatFormatting.GOLD + lastOnline.second() + EnumChatFormatting.YELLOW + ")" : "") + "."); } else { - String offlineSince = DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - slothStalking.getLastLogout(), true, true); + Pair<String, String> lastOnline = Utils.getLastOnlineWords(slothStalking.getLastLogout()); - main.getChatHelper().sendMessage(EnumChatFormatting.YELLOW, slothStalking.getPlayerNameFormatted() + EnumChatFormatting.YELLOW + " is " + EnumChatFormatting.GOLD + "offline" + EnumChatFormatting.YELLOW + " since " + EnumChatFormatting.GOLD + offlineSince + EnumChatFormatting.YELLOW + (slothStalking.getLastGame() != null ? " (last played gamemode: " + EnumChatFormatting.GOLD + slothStalking.getLastGame() + EnumChatFormatting.YELLOW + ")" : "") + "."); + main.getChatHelper().sendMessage(EnumChatFormatting.YELLOW, slothStalking.getPlayerNameFormatted() + EnumChatFormatting.YELLOW + " is " + EnumChatFormatting.GOLD + "offline" + EnumChatFormatting.YELLOW + " for " + EnumChatFormatting.GOLD + lastOnline.first() + EnumChatFormatting.YELLOW + + ((lastOnline.second() != null || slothStalking.getLastGame() != null) ? (" (" + + (lastOnline.second() != null ? EnumChatFormatting.GOLD + lastOnline.second() + EnumChatFormatting.YELLOW : "") // = last online date + + (lastOnline.second() != null && slothStalking.getLastGame() != null ? "; " : "") // = delimiter + + (slothStalking.getLastGame() != null ? "last played gamemode: " + EnumChatFormatting.GOLD + slothStalking.getLastGame() + EnumChatFormatting.YELLOW : "") // = last gamemode + + ")") : "") + "."); } }); } diff --git a/src/main/java/eu/olli/cowmoonication/config/MooConfig.java b/src/main/java/eu/olli/cowmoonication/config/MooConfig.java index a401dbb..41cec89 100644 --- a/src/main/java/eu/olli/cowmoonication/config/MooConfig.java +++ b/src/main/java/eu/olli/cowmoonication/config/MooConfig.java @@ -19,6 +19,7 @@ public class MooConfig { public static boolean showGuildNotifications; public static String moo; private static Configuration cfg = null; + private List<String> propOrderGeneral; public MooConfig(Configuration configuration) { cfg = configuration; @@ -68,36 +69,26 @@ public class MooConfig { if (loadConfigFromFile) { cfg.load(); } + propOrderGeneral = new ArrayList<>(); + + Property propDoUpdateCheck = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT, + "doUpdateCheck", true, "Check for mod updates?"), true); + Property propShowBestFriendNotifications = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT, + "showBestFriendNotifications", true, "Set to true to receive best friends' login/logout messages, set to false hide them."), true); + Property propShowFriendNotifications = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT, + "showFriendNotifications", false, "Set to true to receive friends' login/logout messages, set to false hide them."), true); + Property propShowGuildNotifications = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT, + "showGuildNotifications", false, "Set to true to receive guild members' login/logout messages, set to false hide them."), true); + Property propMoo = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT, + "moo", "", "The answer to life the universe and everything. Don't edit this entry manually!", Utils.VALID_UUID_PATTERN), false); - final boolean DO_UPDATE_CHECK = true; - Property propDoUpdateCheck = cfg.get(Configuration.CATEGORY_CLIENT, "doUpdateCheck", DO_UPDATE_CHECK, "Check for mod updates?"); - - final boolean SHOW_BEST_FRIEND_NOTIFICATIONS = true; - Property propShowBestFriendNotifications = cfg.get(Configuration.CATEGORY_CLIENT, "showBestFriendNotifications", SHOW_BEST_FRIEND_NOTIFICATIONS, "Set to true to receive best friends' login/logout messages, set to false hide them."); - - final boolean SHOW_FRIEND_NOTIFICATIONS = false; - Property propShowFriendNotifications = cfg.get(Configuration.CATEGORY_CLIENT, "showFriendNotifications", SHOW_FRIEND_NOTIFICATIONS, "Set to true to receive friends' login/logout messages, set to false hide them."); - - final boolean SHOW_GUILD_NOTIFICATIONS = false; - Property propShowGuildNotifications = cfg.get(Configuration.CATEGORY_CLIENT, "showGuildNotifications", SHOW_GUILD_NOTIFICATIONS, "Set to true to receive guild members' login/logout messages, set to false hide them."); - - final String MOO = ""; - Property propMoo = cfg.get(Configuration.CATEGORY_CLIENT, "moo", MOO, "The answer to life the universe and everything. Don't edit this entry manually!", Utils.VALID_UUID_PATTERN); - propMoo.setShowInGui(false); - - List<String> propOrderGeneral = new ArrayList<>(); - propOrderGeneral.add(propDoUpdateCheck.getName()); - propOrderGeneral.add(propShowBestFriendNotifications.getName()); - propOrderGeneral.add(propShowFriendNotifications.getName()); - propOrderGeneral.add(propShowGuildNotifications.getName()); - propOrderGeneral.add(propMoo.getName()); cfg.setCategoryPropertyOrder(Configuration.CATEGORY_CLIENT, propOrderGeneral); if (readFieldsFromConfig) { - doUpdateCheck = propDoUpdateCheck.getBoolean(DO_UPDATE_CHECK); - showBestFriendNotifications = propShowBestFriendNotifications.getBoolean(SHOW_BEST_FRIEND_NOTIFICATIONS); - showFriendNotifications = propShowFriendNotifications.getBoolean(SHOW_FRIEND_NOTIFICATIONS); - showGuildNotifications = propShowGuildNotifications.getBoolean(SHOW_GUILD_NOTIFICATIONS); + doUpdateCheck = propDoUpdateCheck.getBoolean(); + showBestFriendNotifications = propShowBestFriendNotifications.getBoolean(); + showFriendNotifications = propShowFriendNotifications.getBoolean(); + showGuildNotifications = propShowGuildNotifications.getBoolean(); moo = propMoo.getString(); } @@ -112,6 +103,16 @@ public class MooConfig { } } + private Property addConfigEntry(Property property, boolean showInGui) { + if (showInGui) { + property.setLanguageKey(Cowmoonication.MODID + ".config." + property.getName()); + } else { + property.setShowInGui(false); + } + propOrderGeneral.add(property.getName()); + return property; + } + /** * Should login/logout notifications be modified and thus monitored? * diff --git a/src/main/java/eu/olli/cowmoonication/util/ApiUtils.java b/src/main/java/eu/olli/cowmoonication/util/ApiUtils.java index 2a62153..650c56d 100644 --- a/src/main/java/eu/olli/cowmoonication/util/ApiUtils.java +++ b/src/main/java/eu/olli/cowmoonication/util/ApiUtils.java @@ -37,8 +37,7 @@ public class ApiUtils { } private static Friend getFriend(String name) { - try { - BufferedReader reader = makeApiCall(NAME_TO_UUID_URL + name); + try (BufferedReader reader = makeApiCall(NAME_TO_UUID_URL + name)) { if (reader == null) { return Friend.FRIEND_NOT_FOUND; } else { @@ -55,8 +54,7 @@ public class ApiUtils { } private static String getCurrentName(Friend friend) { - try { - BufferedReader reader = makeApiCall(String.format(UUID_TO_NAME_URL, UUIDTypeAdapter.fromUUID(friend.getUuid()))); + try (BufferedReader reader = makeApiCall(String.format(UUID_TO_NAME_URL, UUIDTypeAdapter.fromUUID(friend.getUuid())))) { if (reader == null) { return UUID_NOT_FOUND; } else { @@ -76,8 +74,7 @@ public class ApiUtils { } private static HyStalking stalkPlayer(Friend friend) { - try { - BufferedReader reader = makeApiCall(String.format(STALKING_URL_OFFICIAL, MooConfig.moo, UUIDTypeAdapter.fromUUID(friend.getUuid()))); + try (BufferedReader reader = makeApiCall(String.format(STALKING_URL_OFFICIAL, MooConfig.moo, UUIDTypeAdapter.fromUUID(friend.getUuid())))) { if (reader != null) { return gson.fromJson(reader, HyStalking.class); } @@ -92,8 +89,7 @@ public class ApiUtils { } private static SlothStalking stalkOfflinePlayer(Friend stalkedPlayer) { - try { - BufferedReader reader = makeApiCall(String.format(STALKING_URL_UNOFFICIAL, UUIDTypeAdapter.fromUUID(stalkedPlayer.getUuid()))); + try (BufferedReader reader = makeApiCall(String.format(STALKING_URL_UNOFFICIAL, UUIDTypeAdapter.fromUUID(stalkedPlayer.getUuid())))) { if (reader != null) { return gson.fromJson(reader, SlothStalking.class); } @@ -105,6 +101,7 @@ public class ApiUtils { private static BufferedReader makeApiCall(String url) throws IOException { HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); + connection.setConnectTimeout(5000); connection.setReadTimeout(5000); connection.addRequestProperty("User-Agent", "Forge Mod " + Cowmoonication.MODNAME + "/" + Cowmoonication.VERSION + " (https://github.com/cow-mc/Cowmoonication/)"); diff --git a/src/main/java/eu/olli/cowmoonication/util/SlothStalking.java b/src/main/java/eu/olli/cowmoonication/util/SlothStalking.java index bcd0e01..1cc7c22 100644 --- a/src/main/java/eu/olli/cowmoonication/util/SlothStalking.java +++ b/src/main/java/eu/olli/cowmoonication/util/SlothStalking.java @@ -2,9 +2,10 @@ package eu.olli.cowmoonication.util; public class SlothStalking { private String username; + private String rank; private String rank_formatted; // private boolean online; - // private long last_login; + private long last_login; private long last_logout; private String last_game; @@ -15,6 +16,10 @@ public class SlothStalking { return rank_formatted.replace('&', 'ยง') + " " + username; } + public long getLastLogin() { + return last_login; + } + public long getLastLogout() { return last_logout; } @@ -22,4 +27,19 @@ public class SlothStalking { public String getLastGame() { return last_game; } + + public boolean hasNeverJoinedHypixel() { + // example player that has never joined Hypixel (as of April 2020): Joe + return rank == null && last_login == 0; + } + + public boolean hasNeverLoggedOut() { + // example player that has no logout value (as of April 2020): Pig (in general accounts that haven't logged in for a few years) + return last_login != 0 && last_logout == 0; + } + + public boolean isHidingOnlineStatus() { + // example players: any higher ranked player (mods, admins, ...) + return last_login == 0 && last_logout == 0; + } } diff --git a/src/main/java/eu/olli/cowmoonication/util/Utils.java b/src/main/java/eu/olli/cowmoonication/util/Utils.java index dd68cc3..0ff4010 100644 --- a/src/main/java/eu/olli/cowmoonication/util/Utils.java +++ b/src/main/java/eu/olli/cowmoonication/util/Utils.java @@ -1,7 +1,11 @@ package eu.olli.cowmoonication.util; +import com.mojang.realmsclient.util.Pair; import org.apache.commons.lang3.text.WordUtils; +import org.apache.commons.lang3.time.DateFormatUtils; +import org.apache.commons.lang3.time.DurationFormatUtils; +import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; public final class Utils { @@ -22,4 +26,30 @@ public final class Utils { public static String fancyCase(String string) { return WordUtils.capitalizeFully(string.replace('_', ' ')); } + + /** + * Turn timestamp into pretty-formatted duration and date details. + * + * @param timestamp last login/logout + * @return 1st: duration between timestamp and now in words; 2nd: formatted date if time differences is >24h, otherwise null + */ + public static Pair<String, String> getLastOnlineWords(long timestamp) { + long duration = System.currentTimeMillis() - timestamp; + long daysPast = TimeUnit.MILLISECONDS.toDays(duration); + + String dateFormatted = null; + if (daysPast > 1) { + dateFormatted = DateFormatUtils.format(timestamp, "dd-MMM-yyyy"); + } + + if (daysPast > 31) { + return Pair.of( + DurationFormatUtils.formatPeriod(timestamp, System.currentTimeMillis(), (daysPast > 365 ? "y 'years' " : "") + "M 'months' d 'days'"), + dateFormatted); + } else { + return Pair.of( + DurationFormatUtils.formatDurationWords(duration, true, true), + dateFormatted); + } + } } |