From 90f83484da18624c7bea7e4f0c052382c5e9cb09 Mon Sep 17 00:00:00 2001 From: Nick K Date: Sun, 14 Jun 2015 20:18:42 -0400 Subject: [PATCH] 2.33 Added: Special Sounds Overhaul (closes #89) Sanity checks to face downloads (closes #91) Fixed: Port switched to 6667 (dedicated IRC) --- src/main/java/face/FaceManager.java | 78 ++++++++++++------- src/main/java/gui/GUIMain.java | 3 +- src/main/java/gui/GUISettings.java | 2 + src/main/java/gui/GUIStreams.java | 5 +- src/main/java/irc/IRCBot.java | 64 +++++++++------ src/main/java/irc/account/AccountManager.java | 5 +- src/main/java/irc/message/MessageQueue.java | 2 +- src/main/java/sound/SoundEngine.java | 57 ++++++++++++-- src/main/java/thread/ThreadEngine.java | 22 ++++++ .../java/thread/heartbeat/DonationCheck.java | 2 +- src/main/java/util/APIRequests.java | 22 +++++- src/main/java/util/Constants.java | 2 +- src/main/java/util/Utils.java | 3 +- src/main/java/util/comm/ConsoleCommand.java | 4 +- src/main/java/util/settings/Settings.java | 45 +++++++---- .../java/util/settings/SubscriberManager.java | 2 +- version.txt | 9 +-- 17 files changed, 232 insertions(+), 95 deletions(-) create mode 100644 src/main/java/thread/ThreadEngine.java diff --git a/src/main/java/face/FaceManager.java b/src/main/java/face/FaceManager.java index 1c65af0..a9fe7a2 100644 --- a/src/main/java/face/FaceManager.java +++ b/src/main/java/face/FaceManager.java @@ -4,19 +4,24 @@ import lib.JSON.JSONArray; import lib.JSON.JSONObject; import lib.scalr.Scalr; +import thread.ThreadEngine; import util.Response; import util.Utils; import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.stream.ImageInputStream; import javax.swing.*; import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; +import java.awt.*; import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.File; import java.io.InputStreamReader; import java.net.URL; import java.util.ArrayList; +import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -178,27 +183,21 @@ public static void buildMap() { * This process is threaded, and will only show the faces when it's done downloading. */ public static void loadDefaultFaces() { - try { - faceCheck.start(); - } catch (Exception e) { - GUIMain.log(e.getMessage()); - } + ThreadEngine.submit(() -> { + buildMap(); + GUIMain.log("Loaded Twitch faces!"); + GUIMain.currentSettings.saveTwitchFaces(); + doneWithTwitchFaces = true; + + //TODO if currentSettings.FFZFacesEnable + handleFFZChannel("global");//this corrects the global emotes and downloads them if we don't have them + GUIMain.channelSet.stream().forEach(s -> handleFFZChannel(s.replaceAll("#", ""))); + doneWithFrankerFaces = true; + GUIMain.log("Loaded FrankerFaceZ faces!"); + // END TODO + }); } - public static Thread faceCheck = new Thread(() -> { - buildMap(); - GUIMain.log("Loaded Twitch faces!"); - GUIMain.currentSettings.saveTwitchFaces(); - doneWithTwitchFaces = true; - - //TODO if currentSettings.FFZFacesEnable - handleFFZChannel("global");//this corrects the global emotes and downloads them if we don't have them - GUIMain.channelSet.stream().forEach(s -> handleFFZChannel(s.replaceAll("#", ""))); - doneWithFrankerFaces = true; - GUIMain.log("Loaded FrankerFaceZ faces!"); - // END TODO - }); - /** * Toggles a twitch face on/off. *

@@ -261,7 +260,7 @@ public static void handleNameFaces(String object, SimpleAttributeSet set) { } public static void handleFFZChannel(String channel) { - new Thread(() -> { + ThreadEngine.submit(() -> { ArrayList faces = ffzFaceMap.get(channel); ArrayList fromOnline = new ArrayList<>(); FrankerFaceZ.FFZParser.parse(channel, fromOnline); @@ -290,7 +289,7 @@ public static void handleFFZChannel(String channel) { } ffzFaceMap.put(channel, faces); } - }).start(); + }); } public static void handleFaces(Map ranges, Map rangeStyles, @@ -523,12 +522,14 @@ private static boolean download(String url, File toSave) { if (URL.getHost().equals("imgur.com")) { URL = new URL(Utils.setExtension("http://i.imgur.com" + URL.getPath(), ".png")); } - image = ImageIO.read(URL);//just incase the file is null/it can't read it - if (image.getHeight() > DOWNLOAD_MAX_FACE_HEIGHT) {//if it's too big, scale it - image = Scalr.resize(image, Scalr.Method.ULTRA_QUALITY, - Scalr.Mode.FIT_TO_HEIGHT, DOWNLOAD_MAX_FACE_HEIGHT); + if (sanityCheck(URL)) { + image = ImageIO.read(URL);//just incase the file is null/it can't read it + if (image.getHeight() > DOWNLOAD_MAX_FACE_HEIGHT) {//if it's too big, scale it + image = Scalr.resize(image, Scalr.Method.ULTRA_QUALITY, + Scalr.Mode.FIT_TO_HEIGHT, DOWNLOAD_MAX_FACE_HEIGHT); + } + return ImageIO.write(image, "PNG", toSave);//save it } - return ImageIO.write(image, "PNG", toSave);//save it } catch (Exception e) { if (!e.getMessage().contains("Unsupported")) GUIMain.log(e.getMessage()); @@ -536,6 +537,31 @@ private static boolean download(String url, File toSave) { return false; } + /** + * Tests to see if an image is within reasonable downloading bounds (5000x5000) + * + * @param url The URL to the image to check. + * @return True if within downloadable bounds else false. + */ + private static boolean sanityCheck(URL url) { + try (ImageInputStream in = ImageIO.createImageInputStream(url.openStream())) { + final Iterator readers = ImageIO.getImageReaders(in); + if (readers.hasNext()) { + ImageReader reader = readers.next(); + try { + reader.setInput(in); + Dimension d = new Dimension(reader.getWidth(0), reader.getHeight(0)); + return d.getHeight() < 5000 && d.getWidth() < 5000; + } finally { + reader.dispose(); + } + } + } catch (Exception e) { + return false; + } + return false; + } + /** * Either adds a face to the image map or changes a face to another variant. diff --git a/src/main/java/gui/GUIMain.java b/src/main/java/gui/GUIMain.java index 612b052..4ebe877 100644 --- a/src/main/java/gui/GUIMain.java +++ b/src/main/java/gui/GUIMain.java @@ -11,6 +11,7 @@ import irc.message.MessageQueue; import sound.SoundEngine; import thread.TabPulse; +import thread.ThreadEngine; import thread.heartbeat.BanQueue; import thread.heartbeat.DonationCheck; import thread.heartbeat.Heartbeat; @@ -77,6 +78,7 @@ public GUIMain() { tabPulses = new HashSet<>(); combinedChatPanes = new HashSet<>(); userResponses = new ArrayList<>(); + ThreadEngine.init(); FaceManager.init(); SoundEngine.init(); StyleConstants.setForeground(norm, Color.white); @@ -224,7 +226,6 @@ public void exitButtonActionPerformed() { SoundEngine.getEngine().close(); currentSettings.save(); heartbeat.interrupt(); - if (FaceManager.faceCheck != null && FaceManager.faceCheck.isAlive()) FaceManager.faceCheck.interrupt(); if (currentSettings.logChat) { String[] keys = chatPanes.keySet().toArray(new String[chatPanes.keySet().size()]); for (String s : keys) { diff --git a/src/main/java/gui/GUISettings.java b/src/main/java/gui/GUISettings.java index decaa76..e96bf2f 100644 --- a/src/main/java/gui/GUISettings.java +++ b/src/main/java/gui/GUISettings.java @@ -1558,6 +1558,8 @@ private void initComponents() { //---- permissionBox ---- permissionBox.setModel(new DefaultComboBoxModel<>(new String[]{ "Everyone", + "Subscribers/Donors/Mods/Broadcaster", + "Donors/Mods/Broadcaster", "Mods/Broadcaster", "Broadcaster Only" })); diff --git a/src/main/java/gui/GUIStreams.java b/src/main/java/gui/GUIStreams.java index 319206c..606cd3b 100644 --- a/src/main/java/gui/GUIStreams.java +++ b/src/main/java/gui/GUIStreams.java @@ -39,8 +39,7 @@ public void addStreamButtonActionPerformed() { //the tab will not be added to the tabbed pane and therefore invisible cp.setTabVisible(false); if (GUIMain.viewer != null) GUIMain.viewer.doConnect(channel); - //TODO check if in the settings GUI they want the bot to follow, per issue #76 - //if (GUIMain.bot != null) GUIMain.bot.doConnect(channel); + if (GUIMain.bot != null) GUIMain.bot.doConnect(channel); GUIMain.channelSet.add(channel); GUIMain.chatPanes.put(cp.getChannel(), cp); panes.add(cp); @@ -54,7 +53,7 @@ public void addStreamButtonActionPerformed() { if (!channel.equals("") && !channel.contains(" ") && !GUIMain.chatPanes.containsKey(channel)) { ChatPane cp = ChatPane.createPane(channel); if (GUIMain.viewer != null) GUIMain.viewer.doConnect(channel); - //if (GUIMain.bot != null) GUIMain.bot.doConnect(channel); TODO as above, issue #76 + if (GUIMain.bot != null) GUIMain.bot.doConnect(channel); GUIMain.chatPanes.put(cp.getChannel(), cp); GUIMain.channelSet.add(channel); GUIMain.channelPane.insertTab(cp.getChannel(), null, cp.getScrollPane(), null, cp.getIndex()); diff --git a/src/main/java/irc/IRCBot.java b/src/main/java/irc/IRCBot.java index 7bc2814..095d1e5 100644 --- a/src/main/java/irc/IRCBot.java +++ b/src/main/java/irc/IRCBot.java @@ -9,6 +9,7 @@ import lib.pircbot.org.jibble.pircbot.User; import sound.Sound; import sound.SoundEngine; +import thread.ThreadEngine; import util.APIRequests; import util.Response; import util.StringArray; @@ -43,16 +44,13 @@ public IRCBot() { @Override public void onConnect() { - //TODO do people want it to follow? See Issue #76 - if (GUIMain.currentSettings.accountManager.getUserAccount() != null) - doConnect(GUIMain.currentSettings.accountManager.getUserAccount().getName()); + GUIMain.channelSet.forEach(this::doConnect); GUIMain.updateTitle(null); } public void doConnect(String channel) { - String channelName = "#" + channel; - GUIMain.currentSettings.accountManager.addTask( - new Task(GUIMain.currentSettings.accountManager.getBot(), Task.Type.JOIN_CHANNEL, channelName)); + if (!channel.startsWith("#")) channel = "#" + channel; + GUIMain.currentSettings.accountManager.addTask(new Task(getBot(), Task.Type.JOIN_CHANNEL, channel)); } /** @@ -63,8 +61,7 @@ public void doConnect(String channel) { */ public void doLeave(String channel) { if (!channel.startsWith("#")) channel = "#" + channel; - GUIMain.currentSettings.accountManager.addTask( - new Task(GUIMain.currentSettings.accountManager.getBot(), Task.Type.LEAVE_CHANNEL, channel)); + GUIMain.currentSettings.accountManager.addTask(new Task(getBot(), Task.Type.LEAVE_CHANNEL, channel)); } /** @@ -77,25 +74,30 @@ public void close(boolean forget) { if (forget) { GUIMain.currentSettings.accountManager.setBotAccount(null); } - GUIMain.currentSettings.accountManager.addTask( - new Task(GUIMain.currentSettings.accountManager.getBot(), Task.Type.DISCONNECT, null)); + GUIMain.currentSettings.accountManager.addTask(new Task(getBot(), Task.Type.DISCONNECT, null)); GUIMain.bot = null; } public void onDisconnect() { - if (!GUIMain.shutDown && GUIMain.currentSettings.accountManager.getBot() != null) { - GUIMain.currentSettings.accountManager.createReconnectThread(GUIMain.currentSettings.accountManager.getBot()); + if (!GUIMain.shutDown && getBot() != null) { + GUIMain.currentSettings.accountManager.createReconnectThread(getBot()); } } @Override public void onMessage(String channel, String sender, String message) { if (message != null && channel != null && sender != null && GUIMain.currentSettings.accountManager.getViewer() != null) { + String botnakUserName = GUIMain.currentSettings.accountManager.getUserAccount().getName(); sender = sender.toLowerCase(); + if (!channel.contains(botnakUserName.toLowerCase())) { + int replyType = GUIMain.currentSettings.botReplyType; + if (replyType == 0) return; + + if (replyType == 1 && !sender.equalsIgnoreCase(botnakUserName)) return; + } boolean senderIsBot = sender.equalsIgnoreCase(getBot().getNick()); - boolean userIsBot = GUIMain.currentSettings.accountManager.getUserAccount().getName() - .equalsIgnoreCase(GUIMain.currentSettings.accountManager.getBotAccount().getName()); + boolean userIsBot = botnakUserName.equalsIgnoreCase(GUIMain.currentSettings.accountManager.getBotAccount().getName()); //if the sender of the message is the bot, but //the user account is NOT the bot, just return, we don't want the bot to trigger anything if (senderIsBot && !userIsBot) return; @@ -133,20 +135,22 @@ public void onMessage(String channel, String sender, String message) { String[] split = message.split(" "); //URL Checking TODO could this be threaded? - for (String part : split) { - if (part.startsWith("http") || part.startsWith("www")) { - if (part.contains("youtu.be") || part.contains("youtube.com/watch") - || part.contains("youtube.com/v") || part.contains("youtube.com/embed/")) { - getBot().sendMessage(channel, APIRequests.YouTube.getVideoData(part).getResponseText()); - } else if (part.contains("bit.ly") || part.contains("tinyurl")) { - getBot().sendMessage(channel, APIRequests.UnshortenIt.getUnshortened(part).getResponseText()); - } else if (part.contains("twitch.tv/")) { - if (part.contains("/v/") || part.contains("/c/") || part.contains("/b/")) { - getBot().sendMessage(channel, APIRequests.Twitch.getTitleOfVOD(part).getResponseText()); + ThreadEngine.submit(() -> { + for (String part : split) { + if (part.startsWith("http") || part.startsWith("www")) { + if (part.contains("youtu.be") || part.contains("youtube.com/watch") + || part.contains("youtube.com/v") || part.contains("youtube.com/embed/")) { + getBot().sendMessage(channel, APIRequests.YouTube.getVideoData(part).getResponseText()); + } else if (part.contains("bit.ly") || part.contains("tinyurl") || part.contains("goo.gl")) { + getBot().sendMessage(channel, APIRequests.UnshortenIt.getUnshortened(part).getResponseText()); + } else if (part.contains("twitch.tv/")) { + if (part.contains("/v/") || part.contains("/c/") || part.contains("/b/")) { + getBot().sendMessage(channel, APIRequests.Twitch.getTitleOfVOD(part).getResponseText()); + } } } } - } + }); String first = ""; if (split.length > 1) first = split[1]; @@ -421,6 +425,16 @@ public void onMessage(String channel, String sender, String message) { case SHOW_UPTIME: commandResponse = APIRequests.Twitch.getUptimeString(channel.substring(1)); break; + case SEE_PREV_SOUND_DON: + //TODO if currentSettings.seePreviousDonEnable + if (!SoundEngine.getEngine().getDonationStack().isEmpty()) + commandResponse = SoundEngine.getEngine().getLastDonationSound(); + break; + case SEE_PREV_SOUND_SUB: + //TODO if currentSettings.seePreviousSubEnable + if (!SoundEngine.getEngine().getSubStack().isEmpty()) + commandResponse = SoundEngine.getEngine().getLastSubSound(); + break; default: break; diff --git a/src/main/java/irc/account/AccountManager.java b/src/main/java/irc/account/AccountManager.java index 88592c9..5174c06 100644 --- a/src/main/java/irc/account/AccountManager.java +++ b/src/main/java/irc/account/AccountManager.java @@ -53,8 +53,9 @@ public synchronized void addTask(Task t) { if (t.doer != null) { ReconnectThread rt = reconnectThreads.get(t.doer.getNick()); if (rt != null) { - if (t.type != Task.Type.CONNECT) //since the reconnect thread already handles this... + if (t.type != Task.Type.CONNECT) {//since the reconnect thread already handles this... rt.addTask(t); + } return; } } @@ -126,7 +127,7 @@ public void run() {//handle connection status } break; case CONNECT: - if (t.doer.connect("irc.twitch.tv", 80)) { + if (t.doer.connect("irc.twitch.tv", 6667)) { GUIMain.log(t.message); } else { if (!t.doer.isConnected()) { diff --git a/src/main/java/irc/message/MessageQueue.java b/src/main/java/irc/message/MessageQueue.java index 5ace1c8..709de0a 100644 --- a/src/main/java/irc/message/MessageQueue.java +++ b/src/main/java/irc/message/MessageQueue.java @@ -73,7 +73,7 @@ public static void addMessage(Message mess) { GUIMain.chatPanes.get(mess.getChannel()).log(wrap, false); } else if (mess.getType() == Message.MessageType.DONATION_NOTIFY) { GUIMain.chatPanes.get(mess.getChannel()).onDonation(wrap); - if (GUIMain.currentSettings.donationSound != null) { + if (GUIMain.currentSettings.loadedDonationSounds) { SoundEngine.getEngine().playSpecialSound(false); } } else if (mess.getType() == Message.MessageType.CLEAR_TEXT) { diff --git a/src/main/java/sound/SoundEngine.java b/src/main/java/sound/SoundEngine.java index eb26e2d..abd1b3d 100644 --- a/src/main/java/sound/SoundEngine.java +++ b/src/main/java/sound/SoundEngine.java @@ -7,10 +7,7 @@ import util.Utils; import java.io.File; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; +import java.util.*; /** * Created by Nick on 12/20/13. @@ -29,6 +26,8 @@ public static SoundEngine getEngine() { private boolean soundToggle = true; private Timer soundTimer = new Timer(delay); private HashMap soundMap; + private Stack subStack, donationStack; + private Sound lastSubSound, lastDonationSound; public static void init() { engine = new SoundEngine(); @@ -37,6 +36,9 @@ public static void init() { public SoundEngine() { soundMap = new HashMap<>(); player = new SoundPlayer(); + subStack = new Stack<>(); + donationStack = new Stack<>(); + lastSubSound = lastDonationSound = null; } public void setDelay(int newDelay) { @@ -48,6 +50,14 @@ public HashMap getSoundMap() { return soundMap; } + public Stack getSubStack() { + return subStack; + } + + public Stack getDonationStack() { + return donationStack; + } + public Timer getSoundTimer() { return soundTimer; } @@ -93,16 +103,49 @@ public void playSound(Sound s) { } /** - * Plays the new subscriber sound, ignoring the current playing ones. + * Plays the new subscriber/donation sound, overrides current ruleset for engine. */ public void playSpecialSound(boolean isSub) { - File f = (isSub ? GUIMain.currentSettings.subSound.getFile() : GUIMain.currentSettings.donationSound.getFile()); + Sound s = getSpecialSound(isSub); try { - player.play(f, SoundPlayer.PlayMode.Force); + player.play(s.getFile(), SoundPlayer.PlayMode.Force); } catch (Exception ignored) { } } + private Sound getSpecialSound(boolean isSub) { + if ((isSub ? subStack : donationStack).isEmpty()) {//refreshes and reshuffles + if (isSub) GUIMain.currentSettings.loadSubSounds(); + else GUIMain.currentSettings.loadDonationSounds(); + } + Sound sound = (isSub ? subStack : donationStack).pop(); + if (isSub) lastSubSound = sound; + else lastDonationSound = sound; + return sound; + } + + public Response getLastDonationSound() { + Response toReturn = new Response(); + if (lastDonationSound != null) { + toReturn.setResponseText("The previous donation notification sound was taken from the song: " + + Utils.removeExt(lastDonationSound.getFile().getName())); + } else { + toReturn.setResponseText("There is no previous donation sound!"); + } + return toReturn; + } + + public Response getLastSubSound() { + Response toReturn = new Response(); + if (lastSubSound != null) { + toReturn.setResponseText("The previous subscriber notification sound was taken from the song: " + + Utils.removeExt(lastSubSound.getFile().getName())); + } else { + toReturn.setResponseText("There is no previous donation sound!"); + } + return toReturn; + } + /** * Gets the first playing sound in the queue. * diff --git a/src/main/java/thread/ThreadEngine.java b/src/main/java/thread/ThreadEngine.java new file mode 100644 index 0000000..b35208f --- /dev/null +++ b/src/main/java/thread/ThreadEngine.java @@ -0,0 +1,22 @@ +package thread; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * Created by Nick on 6/10/2015. + *

+ * Handles tasks that should be Asynchronous. + */ +public class ThreadEngine { + + private static ExecutorService pool; + + public static void init() { + pool = Executors.newCachedThreadPool(); + } + + public static void submit(Runnable r) { + pool.submit(r); + } +} \ No newline at end of file diff --git a/src/main/java/thread/heartbeat/DonationCheck.java b/src/main/java/thread/heartbeat/DonationCheck.java index 7b0ffb7..011aa53 100644 --- a/src/main/java/thread/heartbeat/DonationCheck.java +++ b/src/main/java/thread/heartbeat/DonationCheck.java @@ -36,4 +36,4 @@ public void afterBeat() { beating = false; toCheck.reset(); } -} +} \ No newline at end of file diff --git a/src/main/java/util/APIRequests.java b/src/main/java/util/APIRequests.java index 9242800..eea2a91 100644 --- a/src/main/java/util/APIRequests.java +++ b/src/main/java/util/APIRequests.java @@ -427,17 +427,31 @@ public static Response getUnshortened(String shortenedURL) { Response toReturn = new Response(); toReturn.setResponseText("Failed to un-shorten URL! Click with caution!"); try { - URL request = new URL("http://api.unshorten.it/?shortURL=" + shortenedURL + - "&return=domainonly&apiKey=25Vr95jzxnWek79hpA2PDOFaMMqhdiCk"); + URL request = new URL("https://therealurl.appspot.com/?url=" + shortenedURL); BufferedReader br = new BufferedReader(new InputStreamReader(request.openStream())); String line = br.readLine(); br.close(); - if (line != null && !line.contains("error (")) { - toReturn.setResponseText("Linked Shortened URL directs to: " + line + " !"); + if (line != null) { + if (!line.equals(shortenedURL)) { + line = getHost(line); + toReturn.setResponseText("Linked Shortened URL directs to: " + line + " !"); + } else { + toReturn.setResponseText("Invalid shortened URL!"); + } } } catch (Exception ignored) { } return toReturn; } + + private static String getHost(String webURL) { + String toReturn = webURL; + try { + URL url = new URL(webURL); + toReturn = url.getHost(); + } catch (Exception ignored) { + } + return toReturn; + } } } \ No newline at end of file diff --git a/src/main/java/util/Constants.java b/src/main/java/util/Constants.java index fe2fe9f..f5c317b 100644 --- a/src/main/java/util/Constants.java +++ b/src/main/java/util/Constants.java @@ -12,7 +12,7 @@ public class Constants { - public static final double VERSION = 2.32; + public static final double VERSION = 2.33; /** * All users may do it diff --git a/src/main/java/util/Utils.java b/src/main/java/util/Utils.java index 83948cb..e95dcf6 100644 --- a/src/main/java/util/Utils.java +++ b/src/main/java/util/Utils.java @@ -59,7 +59,8 @@ public static String getExtension(String fileName) { String ext = null; int i = fileName.lastIndexOf('.'); int len = fileName.length(); - if (i > 0 && (i < len - 1) && (i >= len / 2)) {//has to be near the end + int after = len - i; + if (i > 0 && (i < len - 1) && after < 5) {//has to be near the end ext = fileName.substring(i).toLowerCase(); } return ext; diff --git a/src/main/java/util/comm/ConsoleCommand.java b/src/main/java/util/comm/ConsoleCommand.java index 852ee98..cecf2ae 100644 --- a/src/main/java/util/comm/ConsoleCommand.java +++ b/src/main/java/util/comm/ConsoleCommand.java @@ -61,7 +61,9 @@ public enum Action { //one for each CANCEL_POLL, NOW_PLAYING, SEE_SOUND_STATE, - SHOW_UPTIME + SHOW_UPTIME, + SEE_PREV_SOUND_SUB, + SEE_PREV_SOUND_DON } /** diff --git a/src/main/java/util/settings/Settings.java b/src/main/java/util/settings/Settings.java index 1356d1e..626b35a 100644 --- a/src/main/java/util/settings/Settings.java +++ b/src/main/java/util/settings/Settings.java @@ -13,6 +13,7 @@ import lib.pircbot.org.jibble.pircbot.ChannelManager; import sound.Sound; import sound.SoundEngine; +import thread.ThreadEngine; import util.Constants; import util.Utils; import util.comm.Command; @@ -43,19 +44,19 @@ public class Settings { public AccountManager accountManager = null; public ChannelManager channelManager = null; public String lastFMAccount = ""; + public int botReplyType = 0; //TODO set this + //0 = none, 1 = botnak user only, 2 = everyone //donations public DonationManager donationManager = null; + public boolean loadedDonationSounds = false; public SubscriberManager subscriberManager = null; + public boolean loadedSubSounds = false; //custom directories public String defaultSoundDir = ""; public String defaultFaceDir = ""; - //custom sound - public Sound subSound = null; - public Sound donationSound = null; - //icons public URL modIcon; public URL broadIcon; @@ -135,7 +136,7 @@ public Settings() {//default account * This void loads everything Botnak will use, and sets the appropriate settings. */ public void load() { - new Thread(() -> { + ThreadEngine.submit(() -> { loadWindow(); accountManager = new AccountManager(); channelManager = new ChannelManager(); @@ -160,11 +161,11 @@ public void load() { } if (subSoundDir.exists() && subSoundDir.list().length > 0) { GUIMain.log("Loading sub sounds..."); - loadSubSounds(); + doLoadSubSounds(); } if (donationSoundDir.exists() && donationSoundDir.list().length > 0) { GUIMain.log("Loading donation sounds..."); - loadDonationSounds(); + doLoadDonationSounds(); } if (Utils.areFilesGood(userColFile.getAbsolutePath())) { GUIMain.log("Loading user colors..."); @@ -221,7 +222,7 @@ public void load() { loadDefaultTwitchFaces(); } FaceManager.loadDefaultFaces(); - }).start(); + }); } /** @@ -428,18 +429,24 @@ public void saveSounds() { } } + public boolean doLoadSubSounds() { + if (loadSubSounds()) { + GUIMain.log("Loaded sub sounds!"); + loadedSubSounds = true; + return true; + } else return false; + } + public boolean loadSubSounds() { boolean toReturn = false; try { File[] files = subSoundDir.listFiles(); if (files != null && files.length > 0) { - ArrayList temp = new ArrayList<>(); for (File f : files) { - temp.add(f.getAbsolutePath()); + SoundEngine.getEngine().getSubStack().add(new Sound(5, f.getAbsolutePath())); } - subSound = new Sound(5, temp.toArray(new String[temp.size()])); + Collections.shuffle(SoundEngine.getEngine().getSubStack()); toReturn = true; - GUIMain.log("Loaded sub sounds!"); } } catch (Exception e) { GUIMain.log(e.getMessage()); @@ -447,16 +454,20 @@ public boolean loadSubSounds() { return toReturn; } + private void doLoadDonationSounds() { + loadDonationSounds(); + loadedDonationSounds = true; + GUIMain.log("Loaded donation sounds!"); + } + public void loadDonationSounds() { try { File[] files = donationSoundDir.listFiles(); if (files != null && files.length > 0) { - ArrayList temp = new ArrayList<>(); for (File f : files) { - temp.add(f.getAbsolutePath()); + SoundEngine.getEngine().getDonationStack().add(new Sound(5, f.getAbsolutePath())); } - donationSound = new Sound(5, temp.toArray(new String[temp.size()])); - GUIMain.log("Loaded donation sounds!"); + Collections.shuffle(SoundEngine.getEngine().getDonationStack()); } } catch (Exception e) { GUIMain.log(e.getMessage()); @@ -724,6 +735,8 @@ public void loadConsoleCommands() { hardcoded.add(new ConsoleCommand("song", ConsoleCommand.Action.NOW_PLAYING, Constants.PERMISSION_ALL, null)); hardcoded.add(new ConsoleCommand("soundstate", ConsoleCommand.Action.SEE_SOUND_STATE, Constants.PERMISSION_MOD, null)); hardcoded.add(new ConsoleCommand("uptime", ConsoleCommand.Action.SHOW_UPTIME, Constants.PERMISSION_ALL, null)); + hardcoded.add(new ConsoleCommand("lastsubsound", ConsoleCommand.Action.SEE_PREV_SOUND_SUB, Constants.PERMISSION_ALL, null)); + hardcoded.add(new ConsoleCommand("lastdonationsound", ConsoleCommand.Action.SEE_PREV_SOUND_DON, Constants.PERMISSION_ALL, null)); if (Utils.areFilesGood(ccommandsFile.getAbsolutePath())) { try (BufferedReader br = new BufferedReader(new InputStreamReader(ccommandsFile.toURI().toURL().openStream()))) { diff --git a/src/main/java/util/settings/SubscriberManager.java b/src/main/java/util/settings/SubscriberManager.java index 514117d..4f8eacd 100644 --- a/src/main/java/util/settings/SubscriberManager.java +++ b/src/main/java/util/settings/SubscriberManager.java @@ -184,7 +184,7 @@ public boolean addNewSubscriber(String name, String channel) { private void addSubDonation(String who, String content, double amt) { GUIMain.currentSettings.donationManager.addDonation( new Donation("SUBSCRIBER", who, content, amt, Date.from(Instant.now())), true); - if (GUIMain.currentSettings.subSound != null) + if (GUIMain.currentSettings.loadedSubSounds) SoundEngine.getEngine().playSpecialSound(true); } diff --git a/version.txt b/version.txt index ef890d8..76a9054 100644 --- a/version.txt +++ b/version.txt @@ -1,11 +1,10 @@ -2.32 +2.33 Added: -FrankerFaceZ API Support (closes #88) -NOTICE JTV messages support +Special Sounds Overhaul (closes #89) +Sanity checks to face downloads (closes #91) Fixed: -Subscriber streaks are now Twitch-tier in forgiveness (closes #87) -Accidental Shadowbans (hopefully) +Port switched to 6667 (dedicated IRC)