Skip to content

Commit

Permalink
Follow channels, resub changes
Browse files Browse the repository at this point in the history
- Add feature to follow/unfollow channels
  - Add context menu entries
  - Add user_follows_edit scope for API calls
  - Add commands /follow and /unfollow
- Make stream offline recheck delay longer
- Add initial support for new resub message via USERNOTICE
- Add date to debug log lines
- Add check to automatically exit application when too many errors occur in a short time
  • Loading branch information
tduva committed Jun 12, 2016
1 parent d3e7b9a commit 6c06605
Show file tree
Hide file tree
Showing 16 changed files with 224 additions and 21 deletions.
7 changes: 7 additions & 0 deletions src/chatty/ErrorHandler.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

package chatty;

import chatty.util.TimedCounter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.Thread.UncaughtExceptionHandler;
Expand All @@ -15,9 +16,15 @@ public class ErrorHandler implements UncaughtExceptionHandler {

private final static Logger LOGGER = Logger.getLogger(ErrorHandler.class.getName());

private final TimedCounter counter = new TimedCounter(60*1000, 0);

@Override
public void uncaughtException(Thread t, Throwable e) {
counter.increase();
if (counter.getCount(false) > 1000) {
LOGGER.warning("Over 1000 errors in a minute, exiting application.");
System.exit(1);
}
if (e == null && t != null) {
LOGGER.severe("Unknown exception in thread "+t.toString());
return;
Expand Down
7 changes: 7 additions & 0 deletions src/chatty/Irc.java
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,11 @@ private void receivedCommand(String prefix, String command,
LOGGER.info("Unknown info message: "+trailing);
}
}
if (command.equals("USERNOTICE")) {
if (parameters.length == 1 && parameters[0].startsWith("#")) {
onUsernotice(parameters[0], trailing, tags);
}
}
if (command.equals("JOIN")) {
if (trailing.isEmpty() && parameters.length > 0) {
onJoin(parameters[0], nick, prefix);
Expand Down Expand Up @@ -687,4 +692,6 @@ void onClearChat(Map<String, String> tags, String channel, String name) { }
void onChannelCommand(Map<String, String> tags, String nick, String channel, String command, String trailing) { }

void onCommand(String nick, String command, String parameter, String text, Map<String, String> tags) { }

void onUsernotice(String channel, String message, Map<String, String> tags) { }
}
4 changes: 2 additions & 2 deletions src/chatty/Logging.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,12 @@ static class TextFormatter extends Formatter {

@Override
public String format(LogRecord record) {
return String.format("[%1$tT %5$s] %2$s [%3$s/%4$s]\n",
return String.format("[%1$tF %1$tT %5$s] %2$s [%3$s/%4$s]\n",
new Date(record.getMillis()),
record.getMessage(),
record.getSourceClassName(),
record.getSourceMethodName(),
record.getLevel().getLocalizedName());
record.getLevel().getName());
}

}
Expand Down
2 changes: 2 additions & 0 deletions src/chatty/SettingsManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ void defineSettings() {
settings.setFile("token_subs", loginFile);
settings.addBoolean("token_chat", false);
settings.setFile("token_chat", loginFile);
settings.addBoolean("token_follow", false);
settings.setFile("token_follow", loginFile);

//=================
// Appearance / GUI
Expand Down
52 changes: 52 additions & 0 deletions src/chatty/TwitchClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -924,6 +924,12 @@ else if (command.equals("clearemotecache")) {
//------
// Other
//------
else if (command.equals("follow")) {
commandFollow(channel, parameter);
}
else if (command.equals("unfollow")) {
commandUnfollow(channel, parameter);
}
else if (command.equals("addstreamhighlight")) {
commandAddStreamHighlight(channel, parameter);
}
Expand Down Expand Up @@ -1339,6 +1345,47 @@ private void commandCustomCompletion(String parameter) {
}
}

/**
* Follows the stream given in the parameter, or the channel if no parameter
* is given.
*
* @param channel
* @param parameter
*/
public void commandFollow(String channel, String parameter) {
String user = settings.getString("username");
String target = Helper.toStream(channel);
if (parameter != null && !parameter.isEmpty()) {
target = Helper.toStream(parameter.trim());
}
if (!Helper.validateStream(target)) {
g.printSystem("No valid channel to follow.");
return;
}
if (!Helper.validateStream(user)) {
g.printSystem("No valid username.");
return;
}
api.followChannel(user, target);
}

public void commandUnfollow(String channel, String parameter) {
String user = settings.getString("username");
String target = Helper.toStream(channel);
if (parameter != null && !parameter.isEmpty()) {
target = Helper.toStream(parameter.trim());
}
if (!Helper.validateStream(target)) {
g.printSystem("No valid channel to unfollow.");
return;
}
if (!Helper.validateStream(user)) {
g.printSystem("No valid username.");
return;
}
api.unfollowChannel(user, target);
}

public void commandAddStreamHighlight(String channel, String parameter) {
g.printLine(channel, streamHighlights.addHighlight(channel, parameter));
}
Expand Down Expand Up @@ -1605,6 +1652,11 @@ public void receivedServer(String channel, String server) {
g.printLine(channel, "An error occured requesting server info.");
}
}

@Override
public void followResult(String message) {
g.printSystem(message);
}
}

private void checkToken() {
Expand Down
17 changes: 17 additions & 0 deletions src/chatty/TwitchConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,23 @@ void onNotice(String channel, String text, Map<String, String> tags) {
listener.onInfo(String.format("[Info/%s] %s", channel, text));
}
}

@Override
void onUsernotice(String channel, String text, Map<String, String> tags) {
if ("resub".equals(tags.get("msg-id"))) {
if (text.isEmpty()) {
listener.onInfo(channel, "[Notification] "+tags.get("system-msg"));
} else {
listener.onInfo(channel, "[Notification] "+tags.get("system-msg")+" ["+text+"]");
}
try {
int months = Integer.parseInt(tags.get("msg-param-months"));
listener.onSubscriberNotification(channel, tags.get("login"), months);
} catch (Exception ex) {
// Do nothing
}
}
}

@Override
void onQueryMessage(String nick, String from, String text) {
Expand Down
13 changes: 12 additions & 1 deletion src/chatty/gui/MainGui.java
Original file line number Diff line number Diff line change
Expand Up @@ -1642,6 +1642,14 @@ private void streamStuff(String cmd, Collection<String> streams) {
} else {
printLine("Can't host more than one channel.");
}
} else if (cmd.equals("follow")) {
for (String stream : streams) {
client.commandFollow(null, stream);
}
} else if (cmd.equals("unfollow")) {
for (String stream : streams) {
client.commandUnfollow(null, stream);
}
} else if (cmd.equals("copy") && !streams.isEmpty()) {
MiscUtil.copyToClipboard(StringUtil.join(streams, ", "));
}
Expand Down Expand Up @@ -3391,6 +3399,7 @@ private void setTokenScopes(TokenInfo info) {
client.settings.setBoolean("token_commercials", info.channel_commercials);
client.settings.setBoolean("token_user", info.user_read);
client.settings.setBoolean("token_subs", info.channel_subscriptions);
client.settings.setBoolean("token_follow", info.user_follows_edit);
}
else {
resetTokenScopes();
Expand All @@ -3407,7 +3416,8 @@ private void updateTokenScopes() {
boolean editor = client.settings.getBoolean("token_editor");
boolean user = client.settings.getBoolean("token_user");
boolean subscriptions = client.settings.getBoolean("token_subs");
tokenDialog.updateAccess(chat, editor, commercials, user, subscriptions);
boolean follow = client.settings.getBoolean("token_follow");
tokenDialog.updateAccess(chat, editor, commercials, user, subscriptions, follow);
adminDialog.updateAccess(editor, commercials);
}

Expand All @@ -3417,6 +3427,7 @@ private void resetTokenScopes() {
client.settings.setBoolean("token_editor", false);
client.settings.setBoolean("token_user", false);
client.settings.setBoolean("token_subs", false);
client.settings.setBoolean("token_follow", false);
}

public void showTokenWarning() {
Expand Down
5 changes: 3 additions & 2 deletions src/chatty/gui/components/TokenDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ public void update(String username, String currentToken) {
* @param subs
*/
public void updateAccess(boolean chat, boolean editor, boolean commercial,
boolean user, boolean subs) {
boolean user, boolean subs, boolean follow) {
boolean empty = currentUsername.isEmpty() || currentToken.isEmpty();
access.setVisible(!empty);
accessLabel.setVisible(!empty);
Expand All @@ -146,7 +146,8 @@ public void updateAccess(boolean chat, boolean editor, boolean commercial,
b.append(accessStatusImage(user)).append("&nbsp;Read user info<br />");
b.append(accessStatusImage(editor)).append("&nbsp;Editor access<br />");
b.append(accessStatusImage(commercial)).append("&nbsp;Run commercials<br />");
b.append(accessStatusImage(subs)).append("&nbsp;Show subscribers");
b.append(accessStatusImage(subs)).append("&nbsp;Show subscribers<br />");
b.append(accessStatusImage(follow)).append("&nbsp;Follow channels");

access.setText(b.toString());
update();
Expand Down
28 changes: 21 additions & 7 deletions src/chatty/gui/components/TokenGetDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ public class TokenGetDialog extends JDialog implements ItemListener, ActionListe
private final JCheckBox includeReadUserAccess = new JCheckBox("Read user info (followed streams)");
private final JCheckBox includeEditorAccess = new JCheckBox("Editor access (edit stream title/game)");
private final JCheckBox includeCommercialAccess = new JCheckBox("Allow running ads");
private final JCheckBox includeShowSubsAccess = new JCheckBox("Show your subscribers");
private final JCheckBox includeShowSubsAccess = new JCheckBox("View your subscribers");
private final JCheckBox includeFollowAccess = new JCheckBox("Follow channels");

private String currentUrl = TwitchClient.REQUEST_TOKEN_URL;

Expand All @@ -64,42 +65,51 @@ public TokenGetDialog(MainGui owner) {
includeEditorAccess.setSelected(true);
includeCommercialAccess.setSelected(true);
includeShowSubsAccess.setSelected(true);
includeFollowAccess.setSelected(true);

// Options
gbc = makeGridBagConstraints(0, 1, 2, 1, GridBagConstraints.WEST);
gbc.insets = new Insets(5,5,0,5);
includeReadUserAccess.setToolTipText("To get notified when streams you "
+ "follow go online.");
add(includeReadUserAccess, gbc);

gbc = makeGridBagConstraints(0, 2, 2, 1, GridBagConstraints.WEST);
gbc.insets = new Insets(0,5,0,5);
includeEditorAccess.setToolTipText("To be able to edit your channel's title and game.");
add(includeEditorAccess,gbc);

gbc = makeGridBagConstraints(0,3,2,1,GridBagConstraints.WEST);
gbc.insets = new Insets(0,5,0,5);
includeCommercialAccess.setToolTipText("To be able to run commercials on your stream.");
add(includeCommercialAccess,gbc);

gbc = makeGridBagConstraints(0,4,2,1,GridBagConstraints.WEST);
gbc.insets = new Insets(0,5,5,5);
gbc.insets = new Insets(0,5,0,5);
includeShowSubsAccess.setToolTipText("To be able to show the list of your subscribers.");
add(includeShowSubsAccess,gbc);

gbc = makeGridBagConstraints(0,5,2,1,GridBagConstraints.WEST);
gbc.insets = new Insets(0,5,5,5);
includeFollowAccess.setToolTipText("To be able to follow channels.");
add(includeFollowAccess,gbc);

// URL Display and Buttons
gbc = makeGridBagConstraints(0,5,2,1,GridBagConstraints.CENTER);
gbc = makeGridBagConstraints(0,6,2,1,GridBagConstraints.CENTER);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1;
urlField.setEditable(false);
add(urlField, gbc);
gbc = makeGridBagConstraints(0,6,1,1,GridBagConstraints.EAST);
gbc = makeGridBagConstraints(0,7,1,1,GridBagConstraints.EAST);
gbc.insets = new Insets(0,5,10,5);
add(copyUrl,gbc);
gbc = makeGridBagConstraints(1,6,1,1,GridBagConstraints.EAST);
gbc = makeGridBagConstraints(1,7,1,1,GridBagConstraints.EAST);
gbc.insets = new Insets(0,0,10,5);
add(openUrl,gbc);

// Status and Close Button
add(status,makeGridBagConstraints(0,7,2,1,GridBagConstraints.CENTER));
add(close,makeGridBagConstraints(1,8,1,1,GridBagConstraints.EAST));
add(status,makeGridBagConstraints(0,8,2,1,GridBagConstraints.CENTER));
add(close,makeGridBagConstraints(1,9,1,1,GridBagConstraints.EAST));

openUrl.addActionListener(this);
copyUrl.addActionListener(this);
Expand All @@ -109,6 +119,7 @@ public TokenGetDialog(MainGui owner) {
includeCommercialAccess.addItemListener(this);
includeReadUserAccess.addItemListener(this);
includeShowSubsAccess.addItemListener(this);
includeFollowAccess.addItemListener(this);

reset();
updateUrl();
Expand Down Expand Up @@ -172,6 +183,9 @@ private void updateUrl() {
if (includeShowSubsAccess.isSelected()) {
url += "+channel_subscriptions";
}
if (includeFollowAccess.isSelected()) {
url += "+user_follows_edit";
}
currentUrl = url;
urlField.setText(url);
urlField.setToolTipText(url);
Expand Down
3 changes: 3 additions & 0 deletions src/chatty/gui/components/menus/ChannelContextMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ public ChannelContextMenu(ContextMenuListener listener) {
addItem("joinHostedChannel", "Join Hosted Channel", MISC_MENU);
addItem("copy", "Copy Stream Name", MISC_MENU);
addSeparator(MISC_MENU);
addItem("follow", "Follow Channel", MISC_MENU);
addItem("unfollow", "Unfollow Channel", MISC_MENU);
addSeparator(MISC_MENU);
addItem("srcOpen", "Open Speedrun.com", MISC_MENU);
addSeparator();
addItem("closeChannel", "Close Channel");
Expand Down
4 changes: 4 additions & 0 deletions src/chatty/gui/components/menus/ContextMenuHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,11 @@ protected static void addStreamsOptions(ContextMenu m, int numStreams, boolean j
m.addItem("join", "Join " + count + "channel" + s);
m.addSeparator();
m.addItem("hostchannel", "Host Channel", miscSubmenu);
m.addSeparator(miscSubmenu);
m.addItem("copy", "Copy Stream Name", miscSubmenu);
m.addSeparator(miscSubmenu);
m.addItem("follow", "Follow Channel", miscSubmenu);
m.addItem("unfollow", "Unfollow Channel", miscSubmenu);
}
}

Expand Down
14 changes: 9 additions & 5 deletions src/chatty/gui/components/menus/UserContextMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class UserContextMenu extends ContextMenu {
private final ContextMenuListener listener;
private final User user;

private static final String MISC = "Miscellaneous";
private static final String MISC_MENU = "Miscellaneous";

public UserContextMenu(User user, ContextMenuListener listener) {
this.listener = listener;
Expand All @@ -30,10 +30,14 @@ public UserContextMenu(User user, ContextMenuListener listener) {
addItem("join","Join #"+user.getNick());
addSeparator();

addItem("copy", "Copy Name", MISC);
addSeparator(MISC);
ContextMenuHelper.addIgnore(this, user.nick, MISC, false);
ContextMenuHelper.addIgnore(this, user.nick, MISC, true);
// Misc Submenu
addItem("copy", "Copy Name", MISC_MENU);
addSeparator(MISC_MENU);
ContextMenuHelper.addIgnore(this, user.nick, MISC_MENU, false);
ContextMenuHelper.addIgnore(this, user.nick, MISC_MENU, true);
addSeparator(MISC_MENU);
addItem("follow", "Follow", MISC_MENU);
addItem("unfollow", "Unfollow", MISC_MENU);

// Get the preset categories from the addressbook, which may be empty
// if not addressbook is set to this user
Expand Down
2 changes: 1 addition & 1 deletion src/chatty/util/api/StreamInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ private enum UpdateResult { UPDATED, CHANGED, SET_OFFLINE };
// How long a stats range can be at most
private static final int VIEWERSTATS_MAX_LENGTH = 35*60*1000;

private static final int RECHECK_OFFLINE_DELAY = 10*1000;
private static final int RECHECK_OFFLINE_DELAY = 20*1000;

/**
* Maximum length in seconds of what should count as a PICNIC (short stream
Expand Down
6 changes: 5 additions & 1 deletion src/chatty/util/api/TokenInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class TokenInfo {
public final boolean chat_access;
public final boolean user_read;
public final boolean channel_subscriptions;
public final boolean user_follows_edit;
public final String name;
public final boolean valid;

Expand All @@ -24,16 +25,19 @@ public TokenInfo() {
user_read = false;
name = null;
channel_subscriptions = false;
user_follows_edit = false;
}

public TokenInfo(String name, boolean chat_access, boolean channel_editor,
boolean channel_commercials, boolean user_read, boolean channel_subscriptions) {
boolean channel_commercials, boolean user_read, boolean channel_subscriptions,
boolean user_follows_edit) {
this.name = name;
this.channel_editor = channel_editor;
this.channel_commercials = channel_commercials;
this.chat_access = chat_access;
this.user_read = user_read;
this.channel_subscriptions = channel_subscriptions;
this.user_follows_edit = user_follows_edit;
valid = true;
}
}
Loading

0 comments on commit 6c06605

Please sign in to comment.