Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
metagn committed Jan 14, 2016
1 parent ed0e7d0 commit 7740d65
Show file tree
Hide file tree
Showing 10 changed files with 267 additions and 43 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# DiscordG
Developed by Hlaaftana.

To ask me any questions other than "what's the difference between Groovy and Java", go [here](https://discord.gg/0SBTUU1wZTUMeVC4). If you were going to ask the difference between Groovy and Java, [see for yourself](http://www.vogella.com/tutorials/Groovy/article.html).

## What is this?
This is a Groovy wrapper for the complicated connection stuff Discord needs you to do to connect to it and use its services.

Expand All @@ -24,18 +26,22 @@ import ml.hlaaftana.discordg.APIBuilder
API api = APIBuilder.build("[email protected]", "example123")
api.addListener("message create") { Event e ->
if (e.data.message.content.startsWith("!ping")){
e.data.message.channel.sendMessage("Pong!")
e.data.sendMessage("Pong!")
}
}
```

**PLEASE** check out the examples [here](https://github.com/hlaaftana/DiscordG/tree/master/examples). I provide important explanations in some of them (PingPong and PingPongPlus especially)

Oh, by the way,

## Where can I find the documentation?
[Here](http://hlaaftana.ml/discordg/docs/), for one.

You can also check the source code which is populated with Groovydoc.

If you need further help, contact me [here](https://discord.gg/0SBTUU1wZTUMeVC4).

## Where do I install this?
Check the releases for this repository. You'll find .jar files which you can add to your build path in your IDE or add to -cp in your javac and java commands.

Expand Down
24 changes: 24 additions & 0 deletions examples/bot/CommandBotExample.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package ml.hlaaftana.karmafields

import ml.hlaaftana.discordg.APIBuilder
import ml.hlaaftana.discordg.objects.*
import ml.hlaaftana.discordg.util.bot.CommandBot

API api = APIBuilder.build()
CommandBot bot = new CommandBot(api)

bot.defaultPrefix = "!"

bot.addCommand new CommandBot.Command("hello"){
def run(Event e){
e.data.sendMessage("Hello there, ${e.data.message.author.mention}!")
}
}

bot.addCommand new CommandBot.ResponseCommand("Hello there, but sadly I can't access the event data using this method of respondng to commands. :'(", "hello")

bot.addCommand new CommandBot.ClosureCommand({ Event e, Command c ->
e.data.sendMessage("Hello there, ${e.data.message.author.mention}!")
}, "hello")

bot.initialize("[email protected]", "example")
87 changes: 63 additions & 24 deletions src/ml/hlaaftana/discordg/objects/API.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import java.nio.channels.MembershipKey;

import com.mashape.unirest.http.*

import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
import groovy.lang.Closure
import ml.hlaaftana.discordg.request.*
import ml.hlaaftana.discordg.util.*
Expand All @@ -28,8 +30,10 @@ class API{
ml.hlaaftana.discordg.objects.Client client
Map<String, List<Closure>> listeners = new HashMap<String, List<Closure>>()
Map readyData
Map voiceData = [:]
// if you want to use global variables through the API object. mostly for utility
Map<String, Object> fields = [:]
boolean cacheTokens = true

/**
* Builds a new API object. This is safe to do.
Expand Down Expand Up @@ -75,8 +79,37 @@ class API{
Log.info "Logging in..."
this.email = email
this.password = password
Map response = JSONUtil.parse(this.getRequester().post("https://discordapp.com/api/auth/login", ["email": email, "password": password]))
token = response["token"]
File tokenCache = new File("token.json")
if (tokenCache.exists()){
try{
if (cacheTokens){
token = new JsonSlurper().parse(tokenCache)["token"]
}else{
token = JSONUtil.parse(this.getRequester().post("https://discordapp.com/api/auth/login", ["email": email, "password": password]))["token"]
}
}catch (ex){
if (cacheTokens){
Log.warn "Token cache file seems to be malformed."
Log.debug "Token cache file seems to be malformed, full file: " + tokenCache.text

tokenCache.createNewFile()
tokenCache.write(this.getRequester().post("https://discordapp.com/api/auth/login", ["email": email, "password": password]))

token = new JsonSlurper().parseFile(tokenCache)["token"]
}else{
token = JSONUtil.parse(this.getRequester().post("https://discordapp.com/api/auth/login", ["email": email, "password": password]))["token"]
}
}
}else{
if (cacheTokens){
tokenCache.createNewFile()
tokenCache.write(this.getRequester().post("https://discordapp.com/api/auth/login", ["email": email, "password": password]))

token = new JsonSlurper().parse(tokenCache)["token"]
}else{
token = JSONUtil.parse(this.getRequester().post("https://discordapp.com/api/auth/login", ["email": email, "password": password]))["token"]
}
}
SslContextFactory sslFactory = new SslContextFactory()
WebSocketClient client = new WebSocketClient(sslFactory)
WSClient socket = new WSClient(this)
Expand Down Expand Up @@ -311,33 +344,39 @@ class API{
void addPresenceUpdateListener(){
this.addListener("presence change", { Event e ->
Server server = e.data.server
Map serverToAdd = this.readyData["guilds"].find { it["id"].equals(server.id) }
List members = serverToAdd.members.collect({ it })
if (server == null){ server = new Server(this, ["id": e.data.fullData["guild_id"]]) }
Map serverToAdd = this.readyData["guilds"].find { it["id"] == e.data.fullData["guild_id"] }
Map copyServer = [:]; serverToAdd.entrySet().each { copyServer.put(it.key, it.value) }
List members = copyServer.members.collect({ it })

if (e.data["newUser"] != null){
for (m in members){
if (m["user"]["id"] == e.data.newUser.id){
Map m2 = m
m2.user = e.data.newUser.object
serverToAdd.members.remove(m)
serverToAdd.members.add(m2)
}
try{
Map m = members.find { it["user"]["id"] == e.data.newUser.id }
Map m2 = m
m2.user = e.data.newUser.object
serverToAdd.members.remove(m)
serverToAdd.members.add(m2)
}catch (ex){

}
}
List presences = serverToAdd.presences.collect({ it })
for (p in presences){
if (p["user"]["id"] == e.data.member.id){
Map p2 = p
p2.status = e.data.status
if (e.data.game == ""){
p2.game = null
}else{
p2.game = [name: e.data.game]
}
serverToAdd.presences.remove(p)
serverToAdd.presences.add(p)
List presences = copyServer.presences.collect({ it })
try{
Map p = presences.find { it["user"]["id"] == e.data.member.id }
Map p2 = p
p2.status = e.data.status
if (e.data.game == ""){
p2.game = null
}else{
p2.game = [name: e.data.game]
}
serverToAdd.presences.remove(p)
serverToAdd.presences.add(p)
}catch (ex){

}
this.readyData["guilds"].remove(this.readyData["guilds"].find { it["id"].equals(server.id) })
Map serverToRemove = this.readyData["guilds"].find { it["id"].equals(server.id) }
this.readyData["guilds"].remove(serverToRemove)
this.readyData["guilds"].add(serverToAdd)
})
}
Expand Down
5 changes: 1 addition & 4 deletions src/ml/hlaaftana/discordg/objects/Client.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,7 @@ class Client{
* @return the server. null if not found.
*/
Server getServerById(String id){
for (s in this.getServers()){
if (s.getId().equals(id)) return s
}
return null
this.servers.find { it.id == id }
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/ml/hlaaftana/discordg/objects/Server.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ class Server extends Base {
* @return all roles in the server.
*/
List<Role> getRoles() {
List array = object["roles"]
List array = object["roles"].collect { it }
List<Role> roles = new ArrayList<Role>()
for (o in array){
roles.add(new Role(api, o))
Expand All @@ -176,7 +176,7 @@ class Server extends Base {
* @return all members in the server.
*/
List<Member> getMembers() {
List array = object["members"]
List array = object["members"].collect { it }
List<Member> members = new ArrayList<Member>()
for (o in array){
members.add(new Member(api, o))
Expand Down
2 changes: 1 addition & 1 deletion src/ml/hlaaftana/discordg/objects/TextChannel.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class TextChannel extends Channel {
* @return - the sent message as a Message object.
*/
Message sendFile(File file){
return new Message(api, JSONUtil.parse(api.requester.headerUp(Unirest.post("https://discordapp.com/api/channels/${this.id}/messages")).field("file", file).asString().getBody()))
return new Message(api, JSONUtil.parse(Unirest.post("https://discordapp.com/api/channels/${this.id}/messages").header("authorization", api.token).header("user-agent", "https://github.com/hlaaftana/DiscordG, 1.0").field("file", file).asString().getBody()))
}

/**
Expand Down
56 changes: 45 additions & 11 deletions src/ml/hlaaftana/discordg/request/WSClient.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,10 @@ class WSClient{
]
}else if (t("MESSAGE_CREATE")){
eventData = [
message: new Message(api, data)
message: new Message(api, data),
sendMessage: { String cont, boolean tts=false ->
eventData.message.channel.sendMessage(cont, tts)
}
]
}else if (t("MESSAGE_DELETE")){
List<TextChannel> channels = new ArrayList<TextChannel>()
Expand All @@ -194,24 +197,43 @@ class WSClient{
]
}
}else if (t("PRESENCE_UPDATE")){
eventData = [
server: api.client.getServerById(data["guild_id"]),
guild: api.client.getServerById(data["guild_id"]),
member: api.client.getServerById(data["guild_id"]).getMembers().find { it.getUser().getId().equals(data["user"]["id"]) },
game: (data["game"] != null) ? data["game"]["name"] : "",
status: data["status"]
try{
eventData = [
server: api.client.servers.find { it.id == data["guild_id"] },
guild: api.client.servers.find { it.id == data["guild_id"] },
member: api.client.servers.find({ it.id == data["guild_id"] }).members.find { it.getUser().getId().equals(data["user"]["id"]) },
game: (data["game"] != null) ? data["game"]["name"] : "",
status: data["status"]
]
}catch (ex){
if (api.client.servers.find { it.id == data["guild_id"] } != null){
eventData.server = api.client.servers.find { it.id == data["guild_id"] }
eventData.guild = eventData.server
}
}
if (eventData.server == null){
if (api.client.servers.find { it.id == data["guild_id"] } != null){
eventData.server = api.client.servers.find { it.id == data["guild_id"] }
eventData.guild = eventData.server
}
}
// this here is sort of dangerous
if (eventData.member == null) eventData.member = new Member(api, data)
if (data["user"]["username"] != null) eventData["newUser"] = new User(api, data["user"])
}else if (t("TYPING_START")){
eventData = [
channel: api.client.getTextChannelById(data["channel_id"]),
user: api.client.getUserById(data["user_id"])
]
}else{
}/*else if (t("VOICE_STATE_UPDATE")){
api.voiceData << data
}else if (t("VOICE_SERVER_UPDATE")){
api.voiceData << data
}*/else{
eventData = data
}
}catch (ex){
ex.printStackTrace()
if (Log.enableEventRegisteringCrashes) ex.printStackTrace()
Log.info "Ignoring exception from event object registering"
}
eventData.put("fullData", data)
Expand All @@ -225,7 +247,7 @@ class WSClient{
}
}
}catch (ex){
ex.printStackTrace()
if (Log.enableListenerCrashes) ex.printStackTrace()
Log.info "Ignoring exception from event " + entry.key
}
}
Expand All @@ -236,8 +258,20 @@ class WSClient{

@OnWebSocketClose
void onClose(Session session, int code, String reason){
if (keepAliveThread != null) keepAliveThread.interrupt(); keepAliveThread = null
Log.info "Connection closed. Reason: " + reason + ", code: " + code.toString()
try{
if (keepAliveThread != null) keepAliveThread.interrupt(); keepAliveThread = null
}catch (ex){

}
print "Want to reconnect? [y/n] "
Scanner scnr = new Scanner(System.in)
if (!scnr.next() == "y"){
Log.info "Exiting."
System.exit(0)
}else{
api.login(api.email, api.password)
}
}

@OnWebSocketError
Expand Down
2 changes: 2 additions & 0 deletions src/ml/hlaaftana/discordg/util/Log.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class Log {
static boolean enableError = true
static boolean enableWarn = true
static boolean enableDebug = false
static boolean enableListenerCrashes = true
static boolean enableEventRegisteringCrashes = false

/**
* Prints out a log entry.
Expand Down
8 changes: 8 additions & 0 deletions src/ml/hlaaftana/discordg/util/RandomUtil.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,12 @@ class RandomUtil {
Color color = new Color(inte)
return [color.red, color.green, color.blue]
}

static boolean findStrings(String string, String...strings){
boolean returnThis = false
for (s in strings){
returnThis |= s in string
}
return returnThis
}
}
Loading

0 comments on commit 7740d65

Please sign in to comment.