Added Twitch API framework for followers. Included retrieval and

detection of user profiles. Also included detecting if a stream is
online. Planned Twitch Follower Features:

Follower Notification System:
 - Provide a Unique Follower Notification first time user Follows.
 - User ID is added to Database to prevent Duplicate Follow entries.
 - Display Logo + Current Display Name of User
 - Display scrolling Bio.
 - Play Sound (Probably Glaceon)
 - "Thanks for Follow"
 - Detect users that follow while offline. Announce them next time
stream is online. (Store 'last announced user' ID, try to find next
stream.)
 
 
Get User-Specific Emotes, Download specific sub emotes.
dev
sigonasr2 7 years ago
parent 9251d09aa7
commit 8488c798c6
  1. 5
      .classpath
  2. 6
      .externalToolBuilders/Makejar.launch
  3. 6
      .settings/org.eclipse.jdt.core.prefs
  4. 4
      README.md
  5. 2
      lib/.gitignore
  6. 1
      projectBuilder.xml
  7. BIN
      sigIRCv2.jar
  8. 21
      src/sig/Module.java
  9. 1
      src/sig/UpdateEvent.java
  10. 212
      src/sig/modules/TwitchModule.java
  11. 13
      src/sig/sigIRC.java
  12. 4
      src/sig/utils/TextUtils.java

@ -1,11 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<classpath> <classpath>
<classpathentry kind="src" path="src"/> <classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="lib" path="D:/Downloads/commons-io-2.5.jar"> <classpathentry exported="true" kind="lib" path="D:/Downloads/commons-io-2.5.jar">
<attributes> <attributes>
<attribute name="javadoc_location" value="jar:file:/D:/Data/commons-io-2.5-javadoc.jar!/"/> <attribute name="javadoc_location" value="jar:file:/D:/Data/commons-io-2.5-javadoc.jar!/"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry exported="true" kind="lib" path="D:/Downloads/twitch-api-wrapper-0.3-jar-with-dependencies.jar"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>
</classpath> </classpath>

@ -3,6 +3,12 @@
<booleanAttribute key="org.eclipse.ant.ui.ATTR_TARGETS_UPDATED" value="true"/> <booleanAttribute key="org.eclipse.ant.ui.ATTR_TARGETS_UPDATED" value="true"/>
<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/> <booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/>
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${resource}"/> <stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${resource}"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/sigIRCv2"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>
</listAttribute>
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/> <booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/> <stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="true"/> <booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="true"/>

@ -1,11 +1,11 @@
eclipse.preferences.version=1 eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.7 org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7 org.eclipse.jdt.core.compiler.source=1.8

@ -2,4 +2,6 @@
You will need to download the commons-io library from the Apache Commons Library website. Download page found here: https://commons.apache.org/proper/commons-io/ You will need to download the commons-io library from the Apache Commons Library website. Download page found here: https://commons.apache.org/proper/commons-io/
Include it as an External Jar and you should be good to go. You will also need the Java Twitch API Wrapper library if you are planning to use the Twitch module functionality. Download page found here: https://github.com/urgrue/Java-Twitch-Api-Wrapper/releases/tag/0.3
Include both as an External Jar and you should be good to go.

2
lib/.gitignore vendored

@ -0,0 +1,2 @@
/commons-io-2.5.jar
/twitch-api-wrapper-0.3-jar-with-dependencies.jar

@ -14,6 +14,7 @@
</manifest> </manifest>
<fileset dir="${dir.jarfile}/bin"/> <fileset dir="${dir.jarfile}/bin"/>
<zipfileset excludes="META-INF/*.SF" src="D:/Downloads/commons-io-2.5.jar"/> <zipfileset excludes="META-INF/*.SF" src="D:/Downloads/commons-io-2.5.jar"/>
<zipfileset excludes="META-INF/*.SF" src="D:/Downloads/twitch-api-wrapper-0.3-jar-with-dependencies.jar"/>
</jar> </jar>
</target> </target>
</project> </project>

Binary file not shown.

@ -21,6 +21,7 @@ public class Module {
protected boolean enabled; protected boolean enabled;
protected String name; protected String name;
public static BufferedImage IMG_DRAGBAR; public static BufferedImage IMG_DRAGBAR;
public static boolean inDragZone=false;
final protected int titleHeight; final protected int titleHeight;
@ -73,9 +74,21 @@ public class Module {
protected void moduleRun() { protected void moduleRun() {
dragWindow(); dragWindow();
modifyCursor();
run(); run();
} }
private void modifyCursor() {
int cursortype = sigIRC.panel.getCursor().getType();
if (inDragZone &&
cursortype!=Cursor.MOVE_CURSOR) {
sigIRC.panel.setCursor(new Cursor(Cursor.MOVE_CURSOR));
} else
if (!inDragZone && cursortype!=Cursor.DEFAULT_CURSOR) {
sigIRC.panel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
}
private void dragWindow() { private void dragWindow() {
if (dragging) { if (dragging) {
sigIRC.panel.repaint(getDrawBounds().getBounds()); sigIRC.panel.repaint(getDrawBounds().getBounds());
@ -88,11 +101,13 @@ public class Module {
ModuleDragEvent(oldX,oldY,mouseX,mouseY); ModuleDragEvent(oldX,oldY,mouseX,mouseY);
} }
if (inDragBounds(sigIRC.panel.lastMouseX,sigIRC.panel.lastMouseY)) { if (inDragBounds(sigIRC.panel.lastMouseX,sigIRC.panel.lastMouseY)) {
sigIRC.panel.setCursor(new Cursor(Cursor.MOVE_CURSOR)); inDragZone=true;
} else //System.out.println("In Drag Zone for Module "+name);
//sigIRC.panel.setCursor(new Cursor(Cursor.MOVE_CURSOR));
} /*else
if (sigIRC.panel.getCursor().getType()==Cursor.MOVE_CURSOR) { if (sigIRC.panel.getCursor().getType()==Cursor.MOVE_CURSOR) {
sigIRC.panel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); sigIRC.panel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
} }*/
} }
public void run() { public void run() {

@ -91,6 +91,7 @@ public class UpdateEvent implements ActionListener{
cs.decreaseCooldown(1); cs.decreaseCooldown(1);
} }
} }
Module.inDragZone=false;
for (Module m : sigIRC.modules) { for (Module m : sigIRC.modules) {
m.moduleRun(); m.moduleRun();
} }

@ -0,0 +1,212 @@
package sig.modules;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import com.mb3364.twitch.api.Twitch;
import com.mb3364.twitch.api.handlers.ChannelFollowsResponseHandler;
import com.mb3364.twitch.api.handlers.StreamResponseHandler;
import com.mb3364.twitch.api.models.ChannelFollow;
import com.mb3364.twitch.api.models.Stream;
import sig.Module;
import sig.sigIRC;
import sig.utils.DrawUtils;
import sig.utils.FileUtils;
import sig.utils.TextUtils;
public class TwitchModule extends Module{
public String console="Twitch module goes here.";
Twitch manager = new Twitch();
final static String USERDIR = sigIRC.BASEDIR+"sigIRC/users/";
final static String FOLLOWERQUEUEFILE = USERDIR+"followers.txt";
public static boolean streamOnline = false;
public TwitchModule(Rectangle2D bounds, String moduleName) {
this(bounds,moduleName,true);
}
public TwitchModule(Rectangle2D bounds, String moduleName, boolean enabled) {
super(bounds, moduleName, enabled);
Initialize();
}
private void Initialize() {
boolean firstTime = false;
firstTime = CreateUserFolder();
if (firstTime) {
CreateFollowerQueueLog();
}
manager.setClientId("o4c2x0l3e82scgar4hpxg6m5dfjbem");
getFollowers(firstTime);
/*manager.streams().get("theduckishot", new StreamResponseHandler() {
@Override
public void onFailure(Throwable arg0) {
}
@Override
public void onFailure(int arg0, String arg1, String arg2) {
System.out.println(arg0+","+arg1+","+arg2);
}
@Override
public void onSuccess(Stream arg0) {
//System.out.println("Stream data is available! "+arg0);
if (arg0==null) {
System.out.println("Stream is offline.");
} else {
System.out.println("Stream is online.");
}
}
});*/
/*manager.channels().getFollows(TextUtils.getActualChannelName(), new ChannelFollowsResponseHandler() {
@Override
public void onSuccess(int total, java.util.List<ChannelFollow> follows) {
//System.out.println("Successfully found followers for channel "+sigIRC.channel+". Total: "+total);
//console = "Last Follower: "+follows.get(0).getUser().getDisplayName();
follows.get(0).
}
@Override
public void onFailure(Throwable arg0) {
}
@Override
public void onFailure(int arg0, String arg1, String arg2) {
System.out.println(arg0+","+arg1+","+arg2);
}
}
);*/
}
private void CreateFollowerQueueLog() {
String dir = FOLLOWERQUEUEFILE;
File filer = new File(dir);
if (!filer.exists()) {
try {
filer.createNewFile();
System.out.println("Follower Queue Log does not exist. Creating in "+USERDIR+".");
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void getFollowers(boolean firstTime) {
//isStreamOnline();
manager.channels().getFollows(TextUtils.getActualChannelName(), new ChannelFollowsResponseHandler() {
@Override
public void onSuccess(int total, java.util.List<ChannelFollow> follows) {
//System.out.println("Successfully found followers for channel "+sigIRC.channel+". Total: "+total);
//console = "Last Follower: "+follows.get(0).getUser().getDisplayName();
for (ChannelFollow f : follows) {
addFollower(f,isStreamOnline(),firstTime);
}
}
@Override
public void onFailure(Throwable arg0) {
}
@Override
public void onFailure(int arg0, String arg1, String arg2) {
System.out.println(arg0+","+arg1+","+arg2);
}
}
);
if (isStreamOnline()) {ClearFollowerAnnouncerQueue();}
}
private void ClearFollowerAnnouncerQueue() {
// TODO Read the file and announce everybody in that queue.
}
private boolean isStreamOnline() {
manager.streams().get(TextUtils.getActualChannelName(), new StreamResponseHandler() {
@Override
public void onFailure(Throwable arg0) {
TwitchModule.streamOnline=false;
}
@Override
public void onFailure(int arg0, String arg1, String arg2) {
System.out.println(arg0+","+arg1+","+arg2);
TwitchModule.streamOnline=false;
}
@Override
public void onSuccess(Stream arg0) {
//System.out.println("Stream data is available! "+arg0);
if (arg0==null) {
//System.out.println("Stream is offline.");
TwitchModule.streamOnline=false;
} else {
TwitchModule.streamOnline=true;
}
}
});
//return TwitchModule.streamOnline;
return false;
}
protected void addFollower(ChannelFollow f, boolean streamOnline, boolean silent) {
String filename = USERDIR+f.getUser().getId();
File userProfile = new File(filename);
if (!silent) { //If we got in here, this isn't the initial follower setup, so we are good to go with announcing these followers.
if (!streamOnline) {
//Save their ID to a queue.
FileUtils.logToFile(Long.toString(f.getUser().getId()), FOLLOWERQUEUEFILE);
} else {
//Announce it now.
AnnounceFollower(f);
}
}
CreateUserProfile(f, filename, userProfile);
}
private void CreateUserProfile(ChannelFollow f, String filename, File userProfile) {
if (!userProfile.exists()) {
try {
userProfile.createNewFile();
FileUtils.logToFile(DateFormat.getDateInstance().format(f.getCreatedAt()), filename);
FileUtils.logToFile(f.getUser().getBio(), filename);
FileUtils.logToFile(f.getUser().getDisplayName(), filename);
FileUtils.logToFile(f.getUser().getLogo(), filename);
FileUtils.logToFile(f.getUser().getName(), filename);
FileUtils.logToFile(f.getUser().getType(), filename);
FileUtils.logToFile(DateFormat.getDateInstance().format(f.getUser().getUpdatedAt()), filename);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void AnnounceFollower(ChannelFollow f) {
System.out.println("Thanks for following "+f.getUser().getDisplayName()+"!");
}
private boolean CreateUserFolder() {
File userDir = new File(USERDIR);
if (!userDir.exists()) {
userDir.mkdir();
System.out.println("Could not find Twitch User directory. Creating in "+USERDIR+".");
return true;
} else {
return false;
}
}
public void draw(Graphics g){
super.draw(g);
DrawUtils.drawText(g, bounds.getX(), bounds.getY()+24, Color.RED, console);
}
}

@ -7,6 +7,7 @@ import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import sig.modules.TouhouMotherModule; import sig.modules.TouhouMotherModule;
import sig.modules.TwitchModule;
import sig.utils.FileUtils; import sig.utils.FileUtils;
import java.awt.Color; import java.awt.Color;
@ -30,9 +31,7 @@ import java.util.Calendar;
import java.util.List; import java.util.List;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.swing.JColorChooser;
import javax.swing.JFrame; import javax.swing.JFrame;
import javax.swing.JPanel;
public class sigIRC{ public class sigIRC{
public static MyPanel panel = null; public static MyPanel panel = null;
@ -52,7 +51,7 @@ public class sigIRC{
static ConfigFile config; static ConfigFile config;
static String server; static String server;
static String nickname; static String nickname;
static String channel; public static String channel;
public static boolean authenticated=false; public static boolean authenticated=false;
public static int lastPlayedDing=0; public static int lastPlayedDing=0;
final public static int DINGTIMER=150; final public static int DINGTIMER=150;
@ -74,6 +73,7 @@ public class sigIRC{
static String usernameFont="GillSansMTStd-Book"; static String usernameFont="GillSansMTStd-Book";
static String touhoumotherConsoleFont="Agency FB Bold"; static String touhoumotherConsoleFont="Agency FB Bold";
static boolean touhoumothermodule_enabled=true; static boolean touhoumothermodule_enabled=true;
static boolean twitchmodule_enabled=true;
static boolean downloadsComplete=false; static boolean downloadsComplete=false;
static boolean hardwareAcceleration=true; static boolean hardwareAcceleration=true;
static boolean playedoAuthSoundOnce=false; static boolean playedoAuthSoundOnce=false;
@ -100,6 +100,7 @@ public class sigIRC{
usernameFont = config.getProperty("usernameFont","Gill Sans"); usernameFont = config.getProperty("usernameFont","Gill Sans");
touhoumotherConsoleFont = config.getProperty("touhoumotherConsoleFont","Agency FB Bold"); touhoumotherConsoleFont = config.getProperty("touhoumotherConsoleFont","Agency FB Bold");
touhoumothermodule_enabled = config.getBoolean("Module_touhoumother_Enabled",true); touhoumothermodule_enabled = config.getBoolean("Module_touhoumother_Enabled",true);
twitchmodule_enabled = config.getBoolean("Module_twitch_Enabled",true);
hardwareAcceleration = config.getBoolean("hardware_acceleration",true); hardwareAcceleration = config.getBoolean("hardware_acceleration",true);
DownloadAllRequiredDependencies(); DownloadAllRequiredDependencies();
@ -166,6 +167,12 @@ public class sigIRC{
"Touhou Mother" "Touhou Mother"
)); ));
} }
if (twitchmodule_enabled) {
modules.add(new TwitchModule(
new Rectangle(320,panel.getHeight()/2,panel.getWidth()-320,96),
"Twitch"
));
}
} }
private static void InitializeCustomSounds() { private static void InitializeCustomSounds() {

@ -69,4 +69,8 @@ public class TextUtils {
} }
return sb.toString(); return sb.toString();
} }
public static String getActualChannelName() {
return sigIRC.channel.replaceFirst("#", "");
}
} }

Loading…
Cancel
Save