diff --git a/build.gradle b/build.gradle index 7e4ce38e3..c77edd787 100644 --- a/build.gradle +++ b/build.gradle @@ -2,6 +2,7 @@ import java.util.regex.Matcher plugins { id "com.github.johnrengelman.shadow" version "6.0.0" + id "org.gradle.crypto.checksum" version "1.1.0" id "java" } @@ -242,3 +243,18 @@ task innosetupStandalone(type: Exec, group: 'build') { task releaseWinSetups(group: 'build') { dependsOn releaseWindows, innosetup, innosetupStandalone, build } + +//--------- +// Checksum +//--------- + +import org.gradle.crypto.checksum.Checksum + +task createChecksums(type: Checksum) { + files = layout.files { releasesDir.listFiles() }.filter { File f -> + f.name.endsWith(".exe") || f.name.endsWith(".zip") + } + outputDir = new File(releasesDir, "v"+version) + algorithm = Checksum.Algorithm.SHA256 +} + diff --git a/src/chatty/SettingsManager.java b/src/chatty/SettingsManager.java index 227bd2861..cb60d641b 100644 --- a/src/chatty/SettingsManager.java +++ b/src/chatty/SettingsManager.java @@ -240,6 +240,7 @@ public void defineSettings() { settings.addLong("emoteMaxHeight", 0); settings.addLong("emoteScale", 100); settings.addLong("emoteScaleDialog", 100); + settings.addList("emoteHiddenSets", new ArrayList<>(), Setting.STRING); settings.addBoolean("closeEmoteDialogOnDoubleClick", false); settings.addBoolean("ffz", true); settings.addBoolean("ffzEvent", true); diff --git a/src/chatty/TwitchClient.java b/src/chatty/TwitchClient.java index 17af02d22..4eaed701f 100644 --- a/src/chatty/TwitchClient.java +++ b/src/chatty/TwitchClient.java @@ -2917,7 +2917,7 @@ public void onChannelJoined(User user) { @Override public void onChannelLeft(Room room, boolean closeChannel) { - chatLog.info(room.getFilename(), "You have left "+room.getDisplayName()); + chatLog.info(room.getFilename(), "You have left "+room.getDisplayName(), null); if (closeChannel) { closeChannel(room.getChannel()); } diff --git a/src/chatty/TwitchConnection.java b/src/chatty/TwitchConnection.java index b91f2bc1c..cba9c8e77 100644 --- a/src/chatty/TwitchConnection.java +++ b/src/chatty/TwitchConnection.java @@ -1135,14 +1135,29 @@ void onUsernotice(String channel, String message, MsgTags tags) { if (months == -1) { months = tags.getInteger("msg-param-months", -1); } + int giftMonths = tags.getInteger("msg-param-gift-months", -1); + if (StringUtil.isNullOrEmpty(login, text)) { return; } User user = userJoined(channel, login); updateUserFromTags(user, tags); if (tags.isValueOf("msg-id", "resub", "sub", "subgift", "anonsubgift")) { + text = text.trim(); + if (giftMonths > 1 && !text.matches(".* gifted "+giftMonths+" .*")) { + text += " They gifted "+giftMonths+" months!"; + } + // There are still some types of notifications that don't have + // this info, and it might be useful if (months > 1 && !text.matches(".*\\b"+months+"\\b.*")) { - text += " They've subscribed for "+months+" months!"; + String recipient = tags.get("msg-param-recipient-display-name"); + if (StringUtil.isNullOrEmpty(recipient)) { + recipient = "They've"; + } + else { + recipient += " has"; + } + text += " "+recipient+" subscribed for "+months+" months!"; } listener.onSubscriberNotification(user, text, message, months, tags); } else if (tags.isValue("msg-id", "charity") && login.equals("twitch")) { diff --git a/src/chatty/gui/MainGui.java b/src/chatty/gui/MainGui.java index 30e5715f3..460eaf940 100644 --- a/src/chatty/gui/MainGui.java +++ b/src/chatty/gui/MainGui.java @@ -979,6 +979,7 @@ private void loadSettingsInternal() { streamChat.setMessageTimeout((int)client.settings.getLong("streamChatMessageTimeout")); emotesDialog.setEmoteScale((int)client.settings.getLong("emoteScaleDialog")); + emotesDialog.setHiddenEmotesets(client.settings.getList("emoteHiddenSets")); emotesDialog.setCloseOnDoubleClick(client.settings.getBoolean("closeEmoteDialogOnDoubleClick")); adminDialog.setStatusHistorySorting(client.settings.getString("statusHistorySorting")); @@ -3004,7 +3005,7 @@ public void run() { if (!ignored || client.settings.getBoolean("logIgnored")) { client.chatLog.bits(chan.getFilename(), user, bitsAmount); - client.chatLog.message(chan.getFilename(), user, text, action); + client.chatLog.message(chan.getFilename(), user, text, action, null); } boolean highlighted = false; @@ -3051,7 +3052,7 @@ public void run() { ignoredMessages.addMessage(channel, user, text, action, tagEmotes, bitsForEmotes, whisper, ignoreMatches, tags); - client.chatLog.message("_ignored", user, "["+channel+"] "+text, action); + client.chatLog.message("ignored", user, text, action, channel); ignoredMessagesHelper.ignoredMessage(channel); } long ignoreMode = client.settings.getLong("ignoreMode"); @@ -3101,7 +3102,7 @@ public void run() { chan.printMessage(message, timestamp); if (highlighted) { highlightedMessages.addMessage(channel, message); - client.chatLog.message("_highlighted", user, "["+channel+"] "+text, action); + client.chatLog.message("highlighted", user, text, action, channel); } if (client.settings.listContains("streamChatChannels", channel)) { streamChat.printMessage(message); @@ -3406,7 +3407,7 @@ private boolean printInfo(Channel channel, InfoMessage message) { // After colors and everything is set if (highlighted) { highlightedMessages.addInfoMessage(channel.getChannel(), message); - client.chatLog.info("_highlighted", "["+channel.getChannel()+"] "+message); + client.chatLog.info("highlighted", message.text, channel.getChannel()); } } channel.printInfoMessage(message); @@ -3415,7 +3416,7 @@ private boolean printInfo(Channel channel, InfoMessage message) { } } else if (!message.isHidden()) { ignoredMessages.addInfoMessage(channel.getRoom().getDisplayName(), message.text); - client.chatLog.info("_ignored", "["+channel.getChannel()+"] "+message); + client.chatLog.info("ignored", message.text, channel.getChannel()); } //---------- @@ -3427,7 +3428,7 @@ private boolean printInfo(Channel channel, InfoMessage message) { // ModLog message could be ModLogInfo or generic ModInfo (e.g. for // abandoned messages), so just checking the text instead of type or // something (ModActions are logged separately) - client.chatLog.info(channel.getFilename(), message.text); + client.chatLog.info(channel.getFilename(), message.text, null); } return !ignored; } @@ -4811,12 +4812,13 @@ private class MySettingsListener implements SettingsListener { @Override public void aboutToSaveSettings(Settings settings) { - if (SwingUtilities.isEventDispatchThread()) { + GuiUtil.edtAndWait(() -> { System.out.println("Saving GUI settings."); client.settings.setLong("favoritesSorting", favoritesDialog.getSorting()); emoticons.saveFavoritesToSettings(settings); client.settings.setString("statusHistorySorting", adminDialog.getStatusHistorySorting()); - } + client.settings.putList("emoteHiddenSets", emotesDialog.getHiddenEmotesets()); + }, "Save GUI settings"); } } diff --git a/src/chatty/gui/components/EmotesDialog.java b/src/chatty/gui/components/EmotesDialog.java index f4bca88af..e7fb63ba2 100644 --- a/src/chatty/gui/components/EmotesDialog.java +++ b/src/chatty/gui/components/EmotesDialog.java @@ -4,7 +4,6 @@ import chatty.Chatty; import chatty.util.ForkUtil; import chatty.gui.GuiUtil; -import chatty.gui.LaF; import chatty.gui.MainGui; import chatty.gui.components.menus.ContextMenuListener; import chatty.gui.components.menus.EmoteContextMenu; @@ -18,6 +17,9 @@ import chatty.util.api.Emoticon.EmoticonImage; import chatty.util.api.Emoticon.EmoticonUser; import chatty.util.api.Emoticons; +import chatty.util.colors.ColorCorrection; +import chatty.util.colors.ColorCorrectionNew; +import chatty.util.colors.HtmlColors; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Color; @@ -34,15 +36,19 @@ import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.ImageIcon; @@ -54,7 +60,6 @@ import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JSeparator; -import javax.swing.JTextArea; import javax.swing.JToggleButton; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; @@ -105,6 +110,7 @@ public class EmotesDialog extends JDialog { private final ButtonGroup buttonGroup; private final EmotesPanel defaultPanel; private final Color emotesBackground; + private final Color emotesForeground; private final JButton refreshButton = new JButton(new ImageIcon(EmotesDialog.class.getResource("view-refresh.png"))); /** @@ -131,7 +137,7 @@ public class EmotesDialog extends JDialog { private float scale; private boolean closeOnDoubleClick = true; private boolean userEmotesAccess; - + private final Set hiddenEmotesets = new HashSet<>(); public EmotesDialog(Window owner, Emoticons emotes, final MainGui main, ContextMenuListener contextMenuListener) { super(owner); @@ -150,16 +156,17 @@ public void iconLoaded(Image oldImage, Image newImage, boolean sizeChanged) { this.setFocusableWindowState(false); this.contextMenuListener = contextMenuListener; this.emoteManager = emotes; - Color bg = new JTextArea().getBackground(); - if (bg.equals(Color.WHITE)) { - emotesBackground = new Color(250, 250, 250); + Color bg = HtmlColors.decode(main.getSettings().getString("backgroundColor")); + // Offset the color a bit so it doesn't merge with the background of + // chat as much + if (ColorCorrection.isLightColor(bg)) { + emotesBackground = ColorCorrectionNew.makeDarker(bg, 0.982f); } else { - emotesBackground = bg; + // Dark background seemed to require a larger difference + emotesBackground = ColorCorrectionNew.makeDarker(bg, 0.96f); } - //emotesBackground = new JPanel().getBackground().brighter(); - //emotesBackground = brighter(new JPanel().getBackground(), 0.8); - //emotesBackground = HtmlColors.decode(main.getSettings().getString("backgroundColor")); + emotesForeground = HtmlColors.decode(main.getSettings().getString("foregroundColor")); setResizable(true); //------------------ @@ -457,6 +464,25 @@ public void setEmoteScale(int percentage) { } } + /** + * Set emotesets for hidden sections. Does not update already loaded pages. + * + * @param sets + */ + public void setHiddenEmotesets(Collection sets) { + this.hiddenEmotesets.clear(); + this.hiddenEmotesets.addAll(sets); + } + + /** + * Get the current emotesets for hidden sections. + * + * @return + */ + public Collection getHiddenEmotesets() { + return hiddenEmotesets; + } + public void setUserEmotes(boolean access) { userEmotesAccess = access; // Not ideal, but better than nothing @@ -680,14 +706,35 @@ void reset() { //panel.revalidate(); gbc.gridy = 0; } - + + /** + * Section should show the title only if at least one of the given sets + * is hidden. + * + * @param emotesets + * @return + */ + private boolean isHidden(Collection emotesets) { + for (String set : emotesets) { + if (hiddenEmotesets.contains(set)) { + return true; + } + } + return false; + } + + private boolean isHidden(String emoteset) { + return hiddenEmotesets.contains(emoteset); + } + /** * Adds the emotes of the given emoteset. Includes the name of the * stream if available. * * @param emoteset The emoteset + * @param allowHide Enable hide feature */ - void addEmotes(String emoteset) { + void addEmotes(String emoteset, boolean allowHide) { String stream = emoteManager.getLabelByEmoteset(emoteset); if (stream == null) { stream = "-"; @@ -695,8 +742,11 @@ void addEmotes(String emoteset) { Set emotes = emoteManager.getEmoticonsBySet(emoteset); List sorted = new ArrayList<>(emotes); Collections.sort(sorted, new SortEmotesByTypeAndName()); - addTitle(stream + " [" + emoteset + "] (" + emotes.size() + " emotes)"); - addEmotesPanel(sorted); + addTitle(stream + " [" + emoteset + "] (" + emotes.size() + " emotes)", + Arrays.asList(new String[]{emoteset})); + if (!allowHide || !isHidden(emoteset)) { + addEmotesPanel(sorted); + } } /** @@ -705,9 +755,10 @@ void addEmotes(String emoteset) { * @param titlePrefix Title prefix (emotesets and emotecount added * automatically) * @param emotesets The emotesets to display + * @param allowHide Enable hide feature * @return true if any emotes have been added, false otherwise */ - boolean addEmotes(String titlePrefix, Set emotesets) { + boolean addEmotes(String titlePrefix, Set emotesets, boolean allowHide) { List sets = new ArrayList<>(); for (EmotesetInfo set : emotesets) { sets.add(set.emoteset_id); @@ -721,18 +772,28 @@ boolean addEmotes(String titlePrefix, Set emotesets) { addTitle(String.format("%s %s (%d emotes)", titlePrefix, sets, - sorted.size())); - addEmotesPanel(sorted); - return !sorted.isEmpty(); + sorted.size()), sets); + boolean show = !allowHide || !isHidden(sets); + if (show) { + addEmotesPanel(sorted); + } + return show && !sorted.isEmpty(); + } + + void addTitle(String title) { + addTitle(title, null); } /** * Adds a title (label with seperating line). * * @param title The text of the title + * @param sets Emotesets that will be added under this title (for hide + * feature) */ - void addTitle(String title) { + void addTitle(String title, Collection sets) { JLabel titleLabel = new JLabel(StringUtil.shortenTo(title, 48, 34)); + titleLabel.setForeground(emotesForeground); titleLabel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, titleLabel.getForeground())); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.insets = TITLE_INSETS; @@ -742,6 +803,24 @@ void addTitle(String title) { add(titleLabel, gbc); gbc.gridx = 0; gbc.gridy++; + if (sets != null) { + // If sets are given, allow clicking on title to hide/unhide + titleLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (SwingUtilities.isLeftMouseButton(e)) { + if (isHidden(sets)) { + hiddenEmotesets.removeAll(sets); + } + else { + hiddenEmotesets.addAll(sets); + } + updateEmotes(); + } + } + }); + titleLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + } } /** @@ -754,7 +833,8 @@ void addTitle(String title) { */ void addSubtitle(String title, boolean smallMargin) { JLabel titleLabel = new JLabel(title); - titleLabel.setForeground(Color.GRAY); + // Usually gray should be readable, but just in case + titleLabel.setForeground(ColorCorrection.correctReadability(Color.GRAY, emotesBackground)); gbc.fill = GridBagConstraints.NONE; gbc.weightx = 0; gbc.insets = smallMargin ? SUBTITLE_INSETS_SMALLER_MARGIN : SUBTITLE_INSETS; @@ -923,6 +1003,7 @@ private void updateEmotes2(Map emotesetInfo) { Set turboEmotes = new HashSet<>(); Map> perStream = new HashMap<>(); Map> perInfo = new HashMap<>(); + Map> perPrefix = new HashMap<>(); List unknownEmotesets = new ArrayList<>(); Set unknownEmotesetsSingle = new HashSet<>(); for (String emoteset : localUserEmotesets) { @@ -955,11 +1036,51 @@ private void updateEmotes2(Map emotesetInfo) { } } else { // Unknown emoteset - if (emoteManager.getEmoticonsBySet(emoteset).size() == 1) { - unknownEmotesetsSingle.add(emoteset); - } else { - unknownEmotesets.add(emoteset); + Set emotes = emoteManager.getEmoticonsBySet(emoteset); + String emotePrefix = getPrefix(emotes); + if (emotePrefix == null) { + if (emotes.size() == 1) { + unknownEmotesetsSingle.add(emoteset); + } + else { + unknownEmotesets.add(emoteset); + } } + else { + // Fallback based on emote codes prefix + String key = emotePrefix+" Emotes"; + if (!perPrefix.containsKey(key)) { + perPrefix.put(key, new HashSet<>()); + } + perPrefix.get(key).add(new EmotesetInfo(emoteset, null, null, null)); + } + } + } + } + + //-------------------------- + // Unknown Emotesets + //-------------------------- + /** + * After collecting all perPrefix sets, sort ones that ended up with + * only one emote into "Other" and add others to perInfo emotes, so + * they are sorted the same + */ + Iterator>> it = perPrefix.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry> entry = it.next(); + String key = entry.getKey(); + Set sets = entry.getValue(); + String emoteset = sets.iterator().next().emoteset_id; + if (sets.size() == 1 && emoteManager.getEmoticonsBySet(emoteset).size() == 1) { + unknownEmotesetsSingle.add(emoteset); + } + else { + if (perInfo.containsKey(key)) { + perInfo.get(key).addAll(sets); + } + else { + perInfo.put(key, sets); } } } @@ -970,16 +1091,18 @@ private void updateEmotes2(Map emotesetInfo) { List sortedStreams = new ArrayList<>(perStream.keySet()); Collections.sort(sortedStreams, String.CASE_INSENSITIVE_ORDER); for (String stream : sortedStreams) { - addEmotes(stream, perStream.get(stream)); + addEmotes(stream, perStream.get(stream), true); } - for (String info : perInfo.keySet()) { - addEmotes(info, perInfo.get(info)); + List sortedInfos = new ArrayList<>(perInfo.keySet()); + Collections.sort(sortedInfos, String.CASE_INSENSITIVE_ORDER); + for (String info : sortedInfos) { + addEmotes(info, perInfo.get(info), true); } Collections.sort(unknownEmotesets, SORT_EMOTESETS); for (String emoteset : unknownEmotesets) { - addEmotes(emoteset); + addEmotes(emoteset, true); } // Unknown emotesets that only contain a single emote should be @@ -999,8 +1122,14 @@ private void updateEmotes2(Map emotesetInfo) { // other set as well, and the emotes are equal continue; } - addEmotes(emoteset); + addEmotes(emoteset, true); + } + + // Don't show if there is very little (or nothing) to show/hide + if (sortedStreams.size() + sortedInfos.size() > 2) { + addSubtitle("(Tip: Click headings to show/hide emotes)", false); } + relayout(); } @@ -1086,10 +1215,10 @@ private void addSubemotes(String stream, Set sets) { } } if (!withAccess.isEmpty()) { - addEmotes(Language.getString("emotesDialog.subemotes", stream), withAccess); + addEmotes(Language.getString("emotesDialog.subemotes", stream), withAccess, false); } if (!noAccess.isEmpty()) { - if (addEmotes(Language.getString("emotesDialog.subemotes", stream), noAccess)) { + if (addEmotes(Language.getString("emotesDialog.subemotes", stream), noAccess, false)) { if (withAccess.isEmpty()) { // No subscription active addSubtitle(Language.getString("emotesDialog.subscriptionRequired2"), true); @@ -1381,7 +1510,9 @@ private void addScaledEmote(Emoticon emote, JPanel panel, float scale, panel.add(new EmoteLabel(emote, mouseListener, scale, emoteUser), lgbc); lgbc.gridy = 1; - panel.add(new JLabel(label), lgbc); + JLabel title = new JLabel(label); + title.setForeground(emotesForeground); + panel.add(title, lgbc); lgbc.gridx++; } @@ -1425,4 +1556,60 @@ private void addInfo(JPanel panel, String value) { } + private static final Pattern PREFIX_PATTERN = Pattern.compile("^([A-Za-z][a-z0-9]+)"); + + private static String getPrefix(String code) { + Matcher m = PREFIX_PATTERN.matcher(code); + if (m.find()) { + return m.group(); + } + return null; + } + + /** + * The the emote prefix. Since it can be a bit ambigious what is part of the + * prefix (especially with numbers or sets that don't really have a prefix) + * this may not be entirely correct. + * + * It assumes that everything lowercase or number (first character can be + * uppercase) belongs to the prefix, however it would be an issue when the + * code after the prefix starts with a number, so there is some leniancy for + * not all emotes having the same prefix (the shortest will be used most of + * them have it). + * + * @param emotes + * @return + */ + private static String getPrefix(Collection emotes) { + String commonPrefix = null; + int count = 0; + for (Emoticon emote : emotes) { + String prefix = getPrefix(emote.code); + if (prefix == null) { + return null; + } + if (commonPrefix == null) { + commonPrefix = prefix; + count = 1; + } + else if (prefix.equals(commonPrefix)) { + count++; + } + else if (prefix.length() < commonPrefix.length() + && commonPrefix.startsWith(prefix)) { + // Always prefer shorter prefix, if it still fits + commonPrefix = prefix; + count = 1; + } + + if (!prefix.startsWith(commonPrefix)) { + return null; + } + } + if (count >= emotes.size() * 0.8) { + return commonPrefix; + } + return null; + } + } diff --git a/src/chatty/gui/components/help/help.html b/src/chatty/gui/components/help/help.html index 6bd010ccb..9973e4ede 100644 --- a/src/chatty/gui/components/help/help.html +++ b/src/chatty/gui/components/help/help.html @@ -5,7 +5,7 @@ -

Chatty (Version: 0.13-b4)

+

Chatty (Version: 0.13-b5)

diff --git a/src/chatty/util/RawMessageTest.java b/src/chatty/util/RawMessageTest.java index a86dc7c6e..f87e8998b 100644 --- a/src/chatty/util/RawMessageTest.java +++ b/src/chatty/util/RawMessageTest.java @@ -35,9 +35,23 @@ public static String simulateIRC(String channel, String parameters, String local if (type.equals("subgift")) { return "@badges=;color=;display-name=user1;emotes=;id=123;login=user1;mod=0;msg-id=subgift;msg-param-months=1;msg-param-recipient-display-name=user2;msg-param-recipient-id=44452165;msg-param-recipient-user-name=user2;msg-param-sub-plan-name=Channel\\sSubscription\\s(LIRIK);msg-param-sub-plan=1000;room-id=123;subscriber=0;system-msg=user1\\sgifted\\sa\\s$4.99\\ssub\\sto\\suser2!;tmi-sent-ts=123;turbo=0;user-id=123;user-type= :tmi.twitch.tv USERNOTICE "+channel; } + if (type.equals("subgift3m")) { + // Gifted 3 months, not included in system-msg (just added msg-param-gift-months tag) + return "@badges=;color=;display-name=user1;emotes=;id=123;login=user1;mod=0;msg-id=subgift;msg-param-months=1;msg-param-recipient-display-name=user2;msg-param-recipient-id=44452165;msg-param-recipient-user-name=user2;msg-param-sub-plan-name=Channel\\sSubscription\\s(LIRIK);msg-param-sub-plan=1000;msg-param-gift-months=3;room-id=123;subscriber=0;system-msg=user1\\sgifted\\sa\\s$4.99\\ssub\\sto\\suser2!;tmi-sent-ts=123;turbo=0;user-id=123;user-type= :tmi.twitch.tv USERNOTICE "+channel; + } + if (type.equals("subgift3m2")) { + // Gifted 3 months, included in system-msg (based on older message, but close enough) + return "@badges=;color=;display-name=user1;emotes=;id=123;login=user1;mod=0;msg-id=subgift;msg-param-months=1;msg-param-recipient-display-name=user2;msg-param-recipient-id=44452165;msg-param-recipient-user-name=user2;msg-param-sub-plan-name=Channel\\sSubscription\\s(LIRIK);msg-param-sub-plan=1000;msg-param-gift-months=3;room-id=123;subscriber=0;system-msg=user1\\sgifted\\s3\\smonths\\sof\\s$4.99\\ssub\\sto\\suser2!;tmi-sent-ts=123;turbo=0;user-id=123;user-type= :tmi.twitch.tv USERNOTICE "+channel; + } if (type.equals("anonsubgift")) { return "@badges=;color=;emotes=;id=123;login=channame;mod=0;msg-id=subgift;msg-param-months=1;msg-param-recipient-display-name=user2;msg-param-recipient-id=44452165;msg-param-recipient-user-name=user2;msg-param-sub-plan-name=Channel\\sSubscription\\s(LIRIK);msg-param-sub-plan=1000;room-id=123;subscriber=0;system-msg=An\\sanonymous\\suser\\sgifted\\sa\\sTier\\s1\\ssub\\sto\\sabc!\\s;tmi-sent-ts=123;turbo=0;user-id=123;user-type= :tmi.twitch.tv USERNOTICE "+channel; } + if (type.equals("anonsubgift3m")) { + return "@badge-info=;badges=;color=;display-name=AnAnonymousGifter;emotes=;flags=;id=1234;login=ananonymousgifter;mod=0;msg-id=subgift;msg-param-fun-string=FunStringTwo;msg-param-gift-months=3;msg-param-months=22;msg-param-origin-id=da\\s39\\sa3\\see\\s5e\\s6b\\s4b\\s0d\\s32\\s55\\sbf\\sef\\s95\\s60\\s18\\s90\\saf\\sd8\\s07\\s09;msg-param-recipient-display-name=USERNAME;msg-param-recipient-id=1234;msg-param-recipient-user-name=username;msg-param-sub-plan-name=StreamName\\sSub;msg-param-sub-plan=1000;room-id=1234;subscriber=0;system-msg=An\\sanonymous\\suser\\sgifted\\sa\\sTier\\s1\\ssub\\sto\\sUSERNAME!\\s;tmi-sent-ts=1234;user-id=1234;user-type= :tmi.twitch.tv USERNOTICE "+channel; + } + if (type.equals("primesub")) { + return "@badge-info=subscriber/14;badges=subscriber/12;color=#00FF7F;display-name=USERNAME;emotes=;flags=;id=1234;login=username;mod=0;msg-id=resub;msg-param-cumulative-months=14;msg-param-months=0;msg-param-multimonth-duration=0;msg-param-multimonth-tenure=0;msg-param-should-share-streak=0;msg-param-sub-plan-name=StreamName\\sSub;msg-param-sub-plan=Prime;msg-param-was-gifted=false;room-id=1234;subscriber=1;system-msg=USERNAME\\ssubscribed\\swith\\sTwitch\\sPrime.\\sThey've\\ssubscribed\\sfor\\s14\\smonths!;tmi-sent-ts=1234;user-id=1234;user-type= :tmi.twitch.tv USERNOTICE "+channel+" :F1 subscription fee"; + } if (type.equals("newresub")) { // Without months in system-msg (even though it should have) return "@badges=moderator/1,subscriber/36,turbo/1;color=#0000FF;display-name=USER;emotes=;flags=;id=1234;login=user;mod=1;msg-id=resub;msg-param-cumulative-months=45;msg-param-cumulative-tenure-months=45;msg-param-months=0;msg-param-should-share-streak-tenure=false;msg-param-should-share-streak=0;msg-param-sub-plan-name=CHANNEL\\sSub;msg-param-sub-plan=Prime;room-id=123;subscriber=1;system-msg=USER\\sSubscribed\\swith\\sTwitch\\sPrime.;turbo=1;user-id=123;user-type=mod :tmi.twitch.tv USERNOTICE "+channel+" :Abc"; diff --git a/src/chatty/util/chatlog/ChatLog.java b/src/chatty/util/chatlog/ChatLog.java index c62f3b057..2d1022da6 100644 --- a/src/chatty/util/chatlog/ChatLog.java +++ b/src/chatty/util/chatlog/ChatLog.java @@ -122,14 +122,25 @@ public void bits(String channel, User user, int amount) { } } - public void message(String channel, User user, String message, boolean action) { + /** + * Log a regular chat message. + * + * @param channel The channel to log to (normally the channel received in, + * highlighted/ignore messages could be different) + * @param user The user that sent the message + * @param message The message text + * @param action Whether the message is an action message + * @param includedChannel Channel name to include in the log line (probably + * due to it being logged into another file, like highlighted), can be null + */ + public void message(String channel, User user, String message, boolean action, String includedChannel) { if (isSettingEnabled("logMessage") && isChanEnabled(channel)) { Parameters param = messageParam( user, message, action, settings, - sdf != null ? DateTime.currentTime(sdf) : ""); + timestamp(includedChannel, false)); String line = messageTemplate.replace(param); if (line != null && !line.isEmpty()) { writeLine(channel, line); @@ -149,9 +160,9 @@ public static Parameters messageParam(User user, String message, boolean action, return p; } - public void info(String channel, String message) { + public void info(String channel, String message, String includedChannel) { if (isSettingEnabled("logInfo") && isChanEnabled(channel)) { - writeLine(channel, timestamp()+message); + writeLine(channel, timestamp(includedChannel, true)+message); } } @@ -257,10 +268,23 @@ private Compact getCompact(String channel) { } private String timestamp() { - if (sdf == null) { + return timestamp(null, true); + } + + private String timestamp(String includedChannel, boolean appendSpace) { + String space = appendSpace ? " " : ""; + if (includedChannel != null) { + if (sdf != null) { + return DateTime.currentTime(sdf)+"["+includedChannel+"]"+space; + } + return "["+includedChannel+"]"+space; + } + else { + if (sdf != null) { + return DateTime.currentTime(sdf)+space; + } return ""; } - return DateTime.currentTime(sdf)+" "; } /** @@ -292,10 +316,10 @@ private boolean isChanEnabled(String channel) { // Check non-channel files (not affected by logMode, seems already // separate enough to handle it separately from channels) - if (channel.equals("_highlighted")) { + if (channel.equals("highlighted")) { return settings.getBoolean("logHighlighted2"); } - if (channel.equals("_ignored")) { + if (channel.equals("ignored")) { return settings.getBoolean("logIgnored2"); }