Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions dub.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
"description": "Discord library",
"copyright": "Copyright © 2017, unleashy",
"license": "MIT",
"-ddoxTool": "scod",
"DDOCFLAGS": ["-preview=markdown"],

"targetPath": "out"
}
11 changes: 11 additions & 0 deletions source/droid/api.d
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
/**
* Implements various api features for Discord
*
* Copyright: © 2019, sledgang
* Author: sledgang
*/
module droid.api;

import std.conv,
Expand All @@ -15,6 +21,7 @@ import vibe.http.client,
import droid.droidversion,
droid.data;

///
class API
{
enum DEFAULT_BASE_URL = "https://discordapp.com/api/v7";
Expand Down Expand Up @@ -47,18 +54,22 @@ class API
logger_ = logger ? logger : defaultLogger;
}

/// Gets the gateway url from the API
string getGatewayUrl()
{
return fetch(mixin(DEFAULT_RL_KEY), HTTPMethod.GET, "/gateway")["url"].get!string;
}

/// Gets a `droid.data.user.User` by their `droid.data.snowflake.Snowflake`
User getUser(Snowflake id)
{
return deserializeDataObject!User(
fetch(mixin(DEFAULT_RL_KEY), HTTPMethod.GET, "/users/" ~ id.to!string)
);
}


/// Sends a message to the specified channel
Json sendMessage(Snowflake channelId, string content) {
return fetch(
mixin(DEFAULT_RL_KEY),
Expand Down
25 changes: 25 additions & 0 deletions source/droid/client.d
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
/**
* A client to interact with the API
*
* Copyright: © 2019, sledgang
* Author: sledgang
*/
module droid.client;

import std.typecons,
Expand All @@ -10,11 +16,24 @@ import droid.gateway,
droid.cache,
droid.data;


/**
* A config to change various settings
*/
struct Config
{
/**
* The token to use for API requests and the gateway connection.
* Note: If using a bot user, the token must be prefaced with "Bot " to make API requests!
*/
string token;

API api = null;

/// The gateway class to use when connecting to Discord
Gateway gateway = null;

/// The cache to use for storing data
Cache cache = null;

static Config mergeWithDefaults(Config other)
Expand All @@ -31,22 +50,27 @@ struct Config
}
}

/// A basic client that is used to interact with the API and connect to the gateway
class Client
{
private API api_;
private Gateway gateway_;
private DiscordCache cache_;

/// Creates a Client instance with a custom configuration
this(Config config)
{
setupFromConfig(Config.mergeWithDefaults(config));
}

/// Creates a Client instance with the specified token
this(in string token)
{
this(tokenizedConfig(token));
}


/// Starts a gateway connection to Discord
void run(bool blocking = true)
{
gateway_.connect(blocking);
Expand All @@ -59,6 +83,7 @@ class Client
runEventLoop();
}

/// Changes your status on Discord
void changePresence(int idleSince, string status, Activity activity) {
this.gateway_.send(Opcode.STATUS_UPDATE, Json([
"since": idleSince > 0 ? Json(idleSince) : Json(null),
Expand Down
1 change: 1 addition & 0 deletions source/droid/data/activity.d
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class Activity {
this.type = type;
}

/// If the activity is a streaming activity
bool isStreaming() {
return this.type == 1 && this.url != "";
}
Expand Down
4 changes: 4 additions & 0 deletions source/droid/data/snowflake.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
/**
* A custom snowflake typedef to represent a Discord ID
*/
module droid.data.snowflake;

import std.typecons;

///
alias Snowflake = Typedef!ulong;

string toString(Snowflake snowflake)
Expand Down
12 changes: 12 additions & 0 deletions source/droid/data/user.d
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
///
module droid.data.user;

import vibe.data.json;

import droid.data.snowflake;

/// A Discord User
struct User
{

/// The user's `droid.data.snowflake.Snowflake`
Snowflake id;

/// The user's username
string username;

/// The user's discriminator
string discriminator;

/// The user's avatar hash
string avatar;

/// Whether or not the user is a Bot account
@optional bool bot;
}
13 changes: 13 additions & 0 deletions source/droid/gateway/gateway.d
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* Copyright: © 2019, sledgang
* Author: sledgang
*/
module droid.gateway.gateway;

import core.time,
Expand All @@ -21,6 +25,10 @@ import droid.exception,
droid.gateway.packet,
droid.data.event_type;

/**
* A class to interact with the Discord gateway
* This class is used internally within [Client]
*/
final class Gateway
{
// gateway url needs to be https to satisfy vibe's upgrade checks
Expand Down Expand Up @@ -59,6 +67,7 @@ final class Gateway
logger_ = logger ? logger : defaultLogger;
}

/// Attempt a connection to the gateway
void connect(in bool blocking = true, in bool reconnecting = false)
{
if (!tryConnect(gatewayUrl_)) {
Expand All @@ -80,11 +89,13 @@ final class Gateway
if (blocking && !reconnecting) runEventLoop();
}

/// Subscribe to a given event from your own handler
void subscribe(in EventType event, DispatchDelegate handler)
{
dispatchHandlers_[event] ~= handler;
}

/// Sends an Identify packet to Discord
private void identify()
{
import std.system : os;
Expand All @@ -109,6 +120,7 @@ final class Gateway
]));
}

/// Resumes a lost connection with Discord
private void resume() {
opcodeResumeHandle(Json([
"token": Json(api_.token),
Expand Down Expand Up @@ -178,6 +190,7 @@ final class Gateway
return deserializeJson!Packet(parseJsonString(data));
}

/// Sends a heartbeat packet to Discord
private void heartbeat()
{
if (heartbeatNeedsACK_) {
Expand Down