package discord.jar;
import org.java_websocket.client.DefaultSSLWebSocketClientFactory;
import org.java_websocket.handshake.ServerHandshake;
import org.json.JSONObject;
import javax.net.ssl.SSLContext;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
public class WebSocketClient extends org.java_websocket.client.WebSocketClient {
public static final int DISCORD_GATEWAY_VERSION = 6;
public boolean loaded = false;
private DiscordAPIImpl api;
private Poll readyPoll;
private Poll banPoll;
private Poll addUserPoll;
private Poll messagePoll;
private Poll kickedPoll;
private Poll typingPoll;
private Poll newContactOrGroupPoll;
private Poll statusPoll;
private Poll updateSettings;
private Poll channelRemovePoll;
private Poll channelUpdatePoll;
private Poll guildAddPoll;
private Poll userUpdatePoll;
private Poll deletePoll;
private Poll webhookPoll;
public WebSocketClient(DiscordAPIImpl api, String url) {
super(URI.create(url));
if (url.startsWith("wss"))
{
try
{
SSLContext sslContext;
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, null, null);
this.setWebSocketFactory(new DefaultSSLWebSocketClientFactory(sslContext));
}
catch (NoSuchAlgorithmException | KeyManagementException e)
{
e.printStackTrace();
}
}
this.api = api;
readyPoll = new ReadyPoll(api);
banPoll = new BanPoll(api);
addUserPoll = new AddUserPoll(api);
messagePoll = new MessagePoll(api);
kickedPoll = new KickPoll(api);
typingPoll = new TypingPoll(api);
newContactOrGroupPoll = new NewContactOrGroupPoll(api);
statusPoll = new StatusPoll(api);
updateSettings = new UpdateSettings(api);
channelRemovePoll = new ChannelRemove(api);
channelUpdatePoll = new ChannelUpdatePoll(api);
guildAddPoll = new GuildAdd(api);
userUpdatePoll = new UserUpdatePoll(api);
deletePoll = new DeleteMessagePoll(api);
webhookPoll = new WebhookUpdatePoll(api);
this.connect();
}
@Override
public void onOpen(ServerHandshake handshakeData) {
loaded = true;
api.log("Identifying...");
send(api.getLoginTokens().getIdentifyPacket());
api.log("Logged in and loaded!");
}
@Override
public void onMessage(ByteBuffer message) {
try {
//Thanks to ShadowLordAlpha for code and debugging.
//Get the compressed message and inflate it
StringBuilder builder = new StringBuilder();
Inflater decompresser = new Inflater();
byte[] bytes = message.array();
decompresser.setInput(bytes, 0, bytes.length);
byte[] result = new byte[128];
while (!decompresser.finished()) {
int resultLength = decompresser.inflate(result);
builder.append(new String(result, 0, resultLength, "UTF-8"));
}
decompresser.end();
// send the inflated message to the TextMessage method
onMessage(builder.toString());
} catch (DataFormatException | UnsupportedEncodingException e) {
e.printStackTrace();
}
}
@Override
public void onClose(int code, String reason, boolean remote) {
api.log("Disconnected... :(");
if (code != 4004 && code != 4010 && code != 4011 && !api.isStopped()) {
api.log("Trying to reconnect");
stop();
api.clear();
try {
api.getLoginTokens().process(api);
} catch (Exception e) {
api.log("Failed to reconnect: " + e.getCause());
api.stop();
}
} else {
api.log("Schutting down api...");
api.stop();
}
}
@Override
public void onMessage(String message) {
try {
JSONObject obj = new JSONObject(message);
if (obj.getInt("op") == 7)
return;
JSONObject key = obj.getJSONObject("d");
String type = obj.getString("t");
Server a = key.isNull("guild_id") ? null : api.getServerById(key.getString("guild_id"));
Server server = key.isNull("guild_id") ? null : (a != null ? a : api.getGroupById(key.getString
("guild_id")).getServer());
switch (type) {
case "READY":
readyPoll.process(key, obj, server);
api.log("Successfully loaded user data!");
break;
case "GUILD_MEMBER_ADD":
addUserPoll.process(key, obj, server);
break;
case "GUILD_MEMBER_REMOVE":
kickedPoll.process(key, obj, server);
break;
case "GUILD_BAN_ADD":
banPoll.process(key, obj, server);
break;
case "GUILD_BAN_REMOVE":
//processBan(key, server);
//Unban?
break;
case "MESSAGE_CREATE":
messagePoll.process(key, obj, server);
break;
case "MESSAGE_UPDATE":
messagePoll.process(key, obj, server);
break;
case "TYPING_START":
typingPoll.process(key, obj, server);
break;
case "CHANNEL_CREATE":
newContactOrGroupPoll.process(key, obj, server);
break;
case "PRESENCE_UPDATE":
statusPoll.process(key, obj, server);
break;
case "USER_UPDATE":
updateSettings.process(key, obj, server);
break;
case "CHANNEL_DELETE":
channelRemovePoll.process(key, obj, server);
break;
case "CHANNEL_UPDATE":
channelUpdatePoll.process(key, obj, server);
break;
case "GUILD_CREATE":
guildAddPoll.process(key, obj, server);
break;
case "MESSAGE_DELETE":
userUpdatePoll.process(key, obj, server);
break;
case "GUILD_MEMBER_UPDATE":
deletePoll.process(key, obj, server);
break;
case "WEBHOOKS_UPDATE":
webhookPoll.process(key, obj, server);
break;
default:
api.log("Unknown type " + type + "\n >" + message);
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onError(Exception ex) {
System.err.println("Internal client error!");
api.log("Attempting go log in (again?)!");
api.stop();
try {
api.login();
} catch (Exception e) {
}
}
public void stop() {
this.close();
((ReadyPoll) readyPoll).stop();
}
}