diff --git a/dub.json b/dub.json index 9a55fce..5c75d61 100644 --- a/dub.json +++ b/dub.json @@ -9,6 +9,8 @@ "description": "Discord library", "copyright": "Copyright © 2017, unleashy", "license": "MIT", + "-ddoxTool": "scod", + "DDOCFLAGS": ["-preview=markdown"], "targetPath": "out" } diff --git a/source/droid/api.d b/source/droid/api.d index 94020b4..b2839da 100644 --- a/source/droid/api.d +++ b/source/droid/api.d @@ -1,3 +1,9 @@ +/** + * Implements various api features for Discord + * + * Copyright: © 2019, sledgang + * Author: sledgang + */ module droid.api; import std.conv, @@ -15,6 +21,7 @@ import vibe.http.client, import droid.droidversion, droid.data; +/// class API { enum DEFAULT_BASE_URL = "https://discordapp.com/api/v7"; @@ -47,11 +54,13 @@ 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( @@ -59,6 +68,8 @@ class API ); } + + /// Sends a message to the specified channel Json sendMessage(Snowflake channelId, string content) { return fetch( mixin(DEFAULT_RL_KEY), diff --git a/source/droid/client.d b/source/droid/client.d index 7f73292..a489c86 100644 --- a/source/droid/client.d +++ b/source/droid/client.d @@ -1,3 +1,9 @@ +/** + * A client to interact with the API + * + * Copyright: © 2019, sledgang + * Author: sledgang + */ module droid.client; import std.typecons, @@ -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) @@ -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); @@ -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), diff --git a/source/droid/data/activity.d b/source/droid/data/activity.d index e84cdad..e786e39 100644 --- a/source/droid/data/activity.d +++ b/source/droid/data/activity.d @@ -14,6 +14,7 @@ class Activity { this.type = type; } + /// If the activity is a streaming activity bool isStreaming() { return this.type == 1 && this.url != ""; } diff --git a/source/droid/data/snowflake.d b/source/droid/data/snowflake.d index 17a3cdc..ad2595f 100644 --- a/source/droid/data/snowflake.d +++ b/source/droid/data/snowflake.d @@ -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) diff --git a/source/droid/data/user.d b/source/droid/data/user.d index 89e8b50..21aac69 100644 --- a/source/droid/data/user.d +++ b/source/droid/data/user.d @@ -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; } diff --git a/source/droid/gateway/gateway.d b/source/droid/gateway/gateway.d index 2c3c8f6..ff7c34a 100644 --- a/source/droid/gateway/gateway.d +++ b/source/droid/gateway/gateway.d @@ -1,3 +1,7 @@ +/** + * Copyright: © 2019, sledgang + * Author: sledgang + */ module droid.gateway.gateway; import core.time, @@ -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 @@ -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_)) { @@ -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; @@ -109,6 +120,7 @@ final class Gateway ])); } + /// Resumes a lost connection with Discord private void resume() { opcodeResumeHandle(Json([ "token": Json(api_.token), @@ -178,6 +190,7 @@ final class Gateway return deserializeJson!Packet(parseJsonString(data)); } + /// Sends a heartbeat packet to Discord private void heartbeat() { if (heartbeatNeedsACK_) {