http requests, twitch oauth, twitch chat, irc...
This commit is contained in:
parent
4487a03238
commit
48811806e7
|
@ -0,0 +1,10 @@
|
|||
<component name="libraryTable">
|
||||
<library name="cedarsoftware.json.io" type="repository">
|
||||
<properties maven-id="com.cedarsoftware:json-io:4.14.0" />
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/lib/json-io-4.14.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
|
@ -11,5 +11,6 @@
|
|||
<orderEntry type="library" name="lwjgl" level="project" />
|
||||
<orderEntry type="library" name="jna-5.12.1" level="project" />
|
||||
<orderEntry type="library" name="marytts-lang-en-5.2" level="project" />
|
||||
<orderEntry type="library" name="cedarsoftware.json.io" level="project" />
|
||||
</component>
|
||||
</module>
|
|
@ -0,0 +1,33 @@
|
|||
package com.danitheskunk.skunkworks;
|
||||
|
||||
import com.danitheskunk.skunkworks.net.*;
|
||||
|
||||
public class TestTwitch extends BaseGame implements IIrcMessageHandler {
|
||||
Twitch twitch;
|
||||
TwitchChat chat;
|
||||
|
||||
public TestTwitch() {
|
||||
super(new Vec2i(640, 360), "stuff");
|
||||
twitch = new Twitch("thvs1beyj8w6ono2jqirdz7uuu62qu");
|
||||
chat = twitch.connectChat();
|
||||
var chan = chat.join("#danitheskunk");
|
||||
chan.sendMessage("nyaa!");
|
||||
chan.setMessageHandler(this::handleMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(IrcChannel channel, String message, IrcHostmask from) {
|
||||
if(message.equals("!nya")) {
|
||||
channel.sendMessage("*meows at " + from.getNick() + "*");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void update(double delta) {
|
||||
chat.tick();
|
||||
}
|
||||
|
||||
static public void main(String[] params) {
|
||||
new TestTwitch().run();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
package com.danitheskunk.skunkworks.net;
|
||||
|
||||
import com.cedarsoftware.util.io.JsonReader;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class HttpUtils {
|
||||
public static RequestBuilder request(String uriStr) {
|
||||
return new RequestBuilder(uriStr);
|
||||
}
|
||||
|
||||
public static class RequestBuilder {
|
||||
private Map<String, String> customHeader;
|
||||
private Map<String, String> queryParameters;
|
||||
private String requestMethod;
|
||||
private String urlStr;
|
||||
|
||||
private RequestBuilder(String urlStr) {
|
||||
customHeader = new HashMap<>();
|
||||
queryParameters = new HashMap<>();
|
||||
this.urlStr = urlStr;
|
||||
requestMethod = "GET";
|
||||
}
|
||||
|
||||
private static String queryStrHelper(Map.Entry<String, String> entry) {
|
||||
return URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8) +
|
||||
"=" +
|
||||
URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public RequestBuilder header(String key, String value) {
|
||||
customHeader.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public RequestBuilder queryParameter(String key, String value) {
|
||||
queryParameters.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public RequestBuilder requestMethod(String method) {
|
||||
requestMethod = method;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String run() {
|
||||
HttpURLConnection con;
|
||||
|
||||
var paramStr = "";
|
||||
if(queryParameters.size() > 0) {
|
||||
paramStr = "?" + queryParameters.entrySet().stream().map(
|
||||
RequestBuilder::queryStrHelper).collect(Collectors.joining(
|
||||
"&"));
|
||||
}
|
||||
|
||||
try {
|
||||
var url = new URL(urlStr + paramStr);
|
||||
con = (HttpURLConnection) url.openConnection();
|
||||
} catch(IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
try {
|
||||
con.setRequestMethod(requestMethod);
|
||||
} catch(ProtocolException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
for(var entry : customHeader.entrySet()) {
|
||||
con.setRequestProperty(entry.getKey(), entry.getValue());
|
||||
//System.out.printf("%s: %s\n", entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
BufferedReader in;
|
||||
try {
|
||||
in = new BufferedReader(new InputStreamReader(con.getInputStream()));
|
||||
} catch(IOException e) {
|
||||
String inputLine;
|
||||
var ein = new BufferedReader(new InputStreamReader(con.getErrorStream()));
|
||||
try {
|
||||
while((inputLine = ein.readLine()) != null) {
|
||||
System.err.println(inputLine);
|
||||
}
|
||||
} catch(IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
} throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
String inputLine;
|
||||
StringBuffer content = new StringBuffer();
|
||||
try {
|
||||
while((inputLine = in.readLine()) != null) {
|
||||
content.append(inputLine);
|
||||
}
|
||||
in.close();
|
||||
} catch(IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
public java.util.Map runJSON() {
|
||||
return JsonReader.jsonToMaps(run());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.danitheskunk.skunkworks.net;
|
||||
|
||||
public interface IIrcMessageHandler {
|
||||
void handleMessage(IrcChannel channel, String message, IrcHostmask from);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package com.danitheskunk.skunkworks.net;
|
||||
|
||||
public class IrcChannel {
|
||||
private IrcClient irc;
|
||||
private String name;
|
||||
private IIrcMessageHandler messageHandler;
|
||||
|
||||
public IrcChannel(IrcClient irc, String name) {
|
||||
this.irc = irc;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void sendMessage(String message) {
|
||||
irc.privmsg(name, message);
|
||||
}
|
||||
|
||||
public void processMessage(String message, IrcHostmask from) {
|
||||
System.out.printf("[%s] <%s> %s\n", name, from.getNick(), message);
|
||||
if(messageHandler != null) {
|
||||
messageHandler.handleMessage(this, message, from);
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setMessageHandler(IIrcMessageHandler messageHandler) {
|
||||
this.messageHandler = messageHandler;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
package com.danitheskunk.skunkworks.net;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.Socket;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class IrcClient {
|
||||
private String buffer;
|
||||
private Map<String, IrcChannel> channels;
|
||||
private char[] chbuf;
|
||||
private InputStreamReader in;
|
||||
private BufferedWriter out;
|
||||
private Socket sock;
|
||||
|
||||
public IrcClient(String hostname, int port, String nick) {
|
||||
this(hostname, port, nick, null);
|
||||
}
|
||||
|
||||
public IrcClient(String hostname, int port, String nick, String pass) {
|
||||
buffer = "";
|
||||
//todo: increase size
|
||||
chbuf = new char[8];
|
||||
channels = new HashMap<>();
|
||||
try {
|
||||
sock = new Socket(hostname, port);
|
||||
in = new InputStreamReader(sock.getInputStream());
|
||||
out = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
|
||||
} catch(IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
if(pass != null) {
|
||||
send(new IrcMessage("PASS").addParam(pass));
|
||||
}
|
||||
send(new IrcMessage("NICK").addParam(nick));
|
||||
}
|
||||
|
||||
public IrcChannel join(String channel) {
|
||||
send(new IrcMessage("JOIN").addParam(channel));
|
||||
var chan = new IrcChannel(this, channel);
|
||||
channels.put(channel, chan);
|
||||
return chan;
|
||||
}
|
||||
|
||||
public void privmsg(String target, String msg) {
|
||||
send(new IrcMessage("PRIVMSG").addParam(target).addParam(msg));
|
||||
}
|
||||
|
||||
private void processMessage(IrcMessage msg) {
|
||||
var cmd = msg.getCommand();
|
||||
if(cmd.equals("PING")) {
|
||||
send(new IrcMessage("PONG").addParam(msg.getParams().get(0)));
|
||||
} else if(cmd.equals("PRIVMSG")) {
|
||||
var params = msg.getParams();
|
||||
var target = params.get(0);
|
||||
var text = params.get(1);
|
||||
if(channels.containsKey(target)) {
|
||||
channels.get(target).processMessage(
|
||||
text,
|
||||
IrcHostmask.fromPrefix(msg.getPrefix())
|
||||
);
|
||||
} else {
|
||||
System.out.printf("got privmsg for unknown target '%s'\n",
|
||||
target
|
||||
);
|
||||
}
|
||||
}
|
||||
System.out.printf("IRC| %s", msg.toString());
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while(true) {
|
||||
tick();
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch(InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void send(IrcMessage msg) {
|
||||
try {
|
||||
out.write(msg.toString());
|
||||
out.flush();
|
||||
//System.out.print(msg.toString());
|
||||
} catch(IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
try {
|
||||
while(in.ready()) {
|
||||
//System.out.println("reading");
|
||||
int count = in.read(chbuf);
|
||||
var sb = new StringBuilder();
|
||||
sb.append(chbuf, 0, count);
|
||||
buffer += sb.toString();
|
||||
if(buffer.contains("\r\n")) {
|
||||
var sp = buffer.split("\r\n");
|
||||
buffer = sp.length == 1 ? "" : sp[1];
|
||||
processMessage(IrcMessage.fromString(sp[0]));
|
||||
}
|
||||
}
|
||||
} catch(IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package com.danitheskunk.skunkworks.net;
|
||||
|
||||
public class IrcHostmask {
|
||||
private final String nick, user, host;
|
||||
|
||||
public IrcHostmask(String nick, String user, String host) {
|
||||
this.nick = nick;
|
||||
this.user = user;
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public static IrcHostmask fromPrefix(String str) {
|
||||
String nick;
|
||||
String user = "";
|
||||
String host = "";
|
||||
|
||||
if(str.contains("@")) {
|
||||
var sp = str.split("@");
|
||||
host = sp[1];
|
||||
str = sp[0];
|
||||
}
|
||||
|
||||
if(str.contains("!")) {
|
||||
var sp = str.split("!");
|
||||
user = sp[1];
|
||||
str = sp[0];
|
||||
}
|
||||
|
||||
nick = str;
|
||||
|
||||
return new IrcHostmask(nick, user, host);
|
||||
}
|
||||
|
||||
public String getNick() {
|
||||
return nick;
|
||||
}
|
||||
|
||||
public String getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
package com.danitheskunk.skunkworks.net;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class IrcMessage {
|
||||
private String command;
|
||||
private List<String> params;
|
||||
private String prefix;
|
||||
|
||||
public IrcMessage() {
|
||||
params = new ArrayList<>();
|
||||
}
|
||||
|
||||
public IrcMessage(String cmd) {
|
||||
this();
|
||||
command = cmd;
|
||||
}
|
||||
|
||||
public static IrcMessage fromString(String str) {
|
||||
var irc = new IrcMessage();
|
||||
|
||||
if(str.startsWith(":")) {
|
||||
var sp = str.split(" ", 2);
|
||||
irc.setPrefix(sp[0].substring(1));
|
||||
str = sp[1];
|
||||
}
|
||||
|
||||
if(str.contains(" ")) { //has parameters
|
||||
var sp = str.split(" ", 2);
|
||||
irc.setCommand(sp[0]);
|
||||
str = sp[1];
|
||||
while(true) {
|
||||
if(str.startsWith(":")) { //last parameter with :
|
||||
irc.addParam(str.substring(1).strip());
|
||||
break;
|
||||
}
|
||||
if(str.contains(" ")) { //not last parameter
|
||||
sp = str.split(" ", 2);
|
||||
irc.addParam(sp[0]);
|
||||
str = sp[1];
|
||||
} else { //last parameter
|
||||
irc.addParam(str.strip());
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
irc.setCommand(str.strip());
|
||||
}
|
||||
|
||||
return irc;
|
||||
}
|
||||
|
||||
public IrcMessage addParam(String param) {
|
||||
params.add(param);
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public List<String> getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public IrcMessage setCommand(String command) {
|
||||
this.command = command;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IrcMessage setPrefix(String prefix) {
|
||||
this.prefix = prefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
var sb = new StringBuilder();
|
||||
if(prefix != null) {
|
||||
sb.append(":");
|
||||
sb.append(prefix);
|
||||
sb.append(" ");
|
||||
}
|
||||
sb.append(command);
|
||||
if(params.size() > 0) {
|
||||
sb.append(" ");
|
||||
}
|
||||
for(int i = 0; i < params.size(); ++i) {
|
||||
if(i == params.size() - 1) {
|
||||
if(params.get(i).contains(" ")) {
|
||||
sb.append(":");
|
||||
}
|
||||
sb.append(params.get(i));
|
||||
} else {
|
||||
sb.append(params.get(i));
|
||||
sb.append(" ");
|
||||
}
|
||||
}
|
||||
sb.append("\r\n");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.danitheskunk.skunkworks.net;
|
||||
|
||||
public class Twitch {
|
||||
private String clientID;
|
||||
private String token;
|
||||
private String username;
|
||||
|
||||
public Twitch(String clientID) {
|
||||
token = TwitchOauth.getToken(clientID,
|
||||
new String[]{"chat:read", "chat:edit"}
|
||||
);
|
||||
this.clientID = clientID;
|
||||
username = getUser();
|
||||
System.out.printf("Logged into twitch as \"%s\"\n", username);
|
||||
}
|
||||
|
||||
public TwitchChat connectChat() {
|
||||
return new TwitchChat(username, token);
|
||||
}
|
||||
|
||||
private String getUser() {
|
||||
var response = HttpUtils.request("https://api.twitch.tv/helix/users").header("Authorization",
|
||||
"Bearer " + token
|
||||
).header(
|
||||
"Client-Id",
|
||||
clientID
|
||||
).runJSON();
|
||||
var data = (Object[]) response.get("data");
|
||||
var user = (java.util.Map) data[0];
|
||||
var login = (String) user.get("login");
|
||||
|
||||
return login;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package com.danitheskunk.skunkworks.net;
|
||||
|
||||
public class TwitchChat extends IrcClient {
|
||||
public TwitchChat(String nick, String token) {
|
||||
super("irc.chat.twitch.tv", 6667, nick, "oauth:"+token);
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ public class TwitchOauth implements HttpHandler {
|
|||
private String result = null;
|
||||
|
||||
public static String getToken(String clientID, String[] scopes) {
|
||||
var scopeStr = String.join("&",
|
||||
var scopeStr = String.join("+",
|
||||
Arrays.stream(scopes).map((String s) -> URLEncoder.encode(s)).toList()
|
||||
);
|
||||
var uri = URI.create(String.format(
|
||||
|
@ -64,6 +64,9 @@ public class TwitchOauth implements HttpHandler {
|
|||
}
|
||||
System.out.println("waiting for oauth response");
|
||||
}
|
||||
if(instance.errored) {
|
||||
throw new RuntimeException("oauth error of some sorts...");
|
||||
}
|
||||
server.stop(0);
|
||||
return instance.result;
|
||||
}
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue