aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAdelyn Breelove <[email protected]>2018-11-29 12:55:10 -0700
committerAdelyn Breelove <[email protected]>2018-11-29 12:55:10 -0700
commit473072f66e6c7e228b4f26730cbc7304941fb12b (patch)
treecd689e7f53bafbf357c8be88e317251b2a4b7539 /lib
parentClean up a bit (diff)
downloaddisml-473072f66e6c7e228b4f26730cbc7304941fb12b.tar.xz
disml-473072f66e6c7e228b4f26730cbc7304941fb12b.zip
functors!
Diffstat (limited to 'lib')
-rw-r--r--lib/client.ml61
-rw-r--r--lib/dis.ml0
-rw-r--r--lib/http.ml439
-rw-r--r--lib/s.ml31
-rw-r--r--lib/sharder.ml549
5 files changed, 562 insertions, 518 deletions
diff --git a/lib/client.ml b/lib/client.ml
index e88b1d5..7adaae3 100644
--- a/lib/client.ml
+++ b/lib/client.ml
@@ -1,35 +1,42 @@
open Async
-type t = {
- sharder: Sharder.t Ivar.t;
- handler: string Pipe.Writer.t;
- token: string;
-}
+module Make(T : S.Token) = struct
+ include T
+
+ module Http = Http.Make(T)
+ module Sharder = Sharder.Make(Http)
-let create ~handler token =
- {
- sharder = Ivar.create ();
- handler;
- token;
+ type t = {
+ sharder: Sharder.t Ivar.t;
+ handler: string Pipe.Writer.t;
+ token: string;
}
-let start ?count client =
- Sharder.start ?count client.token
- >>| fun sharder ->
- Ivar.fill_if_empty client.sharder sharder;
- client
+ let init ~handler () =
+ {
+ sharder = Ivar.create ();
+ handler;
+ token;
+ }
-let set_status ~status client =
- Ivar.read client.sharder
- >>= fun sharder ->
- Sharder.set_status sharder status
+ let start ?count client =
+ Sharder.start ?count client.token
+ >>| fun sharder ->
+ Ivar.fill_if_empty client.sharder sharder;
+ client
-let set_status_with ~f client =
- Ivar.read client.sharder
- >>= fun sharder ->
- Sharder.set_status_with sharder f
+ let set_status ~status client =
+ Ivar.read client.sharder
+ >>= fun sharder ->
+ Sharder.set_status sharder status
-let request_guild_members ~guild ?query ?limit client =
- Ivar.read client.sharder
- >>= fun sharder ->
- Sharder.request_guild_members ~guild ?query ?limit sharder
+ let set_status_with ~f client =
+ Ivar.read client.sharder
+ >>= fun sharder ->
+ Sharder.set_status_with sharder f
+
+ let request_guild_members ~guild ?query ?limit client =
+ Ivar.read client.sharder
+ >>= fun sharder ->
+ Sharder.request_guild_members ~guild ?query ?limit sharder
+end \ No newline at end of file
diff --git a/lib/dis.ml b/lib/dis.ml
deleted file mode 100644
index e69de29..0000000
--- a/lib/dis.ml
+++ /dev/null
diff --git a/lib/http.ml b/lib/http.ml
index 8d0b679..a8e6b22 100644
--- a/lib/http.ml
+++ b/lib/http.ml
@@ -1,319 +1,322 @@
open Async
open Cohttp
-module Base = struct
- exception Invalid_Method
+module Make(T : S.Token) = struct
+ include T
- let base_url = "https://discordapp.com/api/v7"
- let cdn_url = "https://cdn.discordapp.com"
+ module Base = struct
+ exception Invalid_Method
- let process_url path =
- Uri.of_string (base_url ^ path)
+ let base_url = "https://discordapp.com/api/v7"
+ let cdn_url = "https://cdn.discordapp.com"
- let process_request_body body =
- body
- |> Yojson.Basic.to_string
- |> Cohttp_async.Body.of_string
+ let process_url path =
+ Uri.of_string (base_url ^ path)
- let process_request_headers () =
- let token = match Sys.getenv "DISCORD_TOKEN" with
- | Some t -> t
- | None -> failwith "Please provide a token"
- in
- let h = Header.init_with "User-Agent" "Dis.ml v0.1.0" in
- let h = Header.add h "Authorization" ("Bot " ^ token) in
- Header.add h "Content-Type" "application/json"
+ let process_request_body body =
+ body
+ |> Yojson.Basic.to_string
+ |> Cohttp_async.Body.of_string
- (* TODO Finish processor *)
- let process_response (_resp, body) =
- body |> Cohttp_async.Body.to_string >>| Yojson.Basic.from_string
+ let process_request_headers () =
+ let h = Header.init () in
+ Header.add_list h [
+ "User-Agent", "Dis.ml v0.1.0";
+ "Authorization", ("Bot " ^ token);
+ "Content-Type", "application/json";
+ ]
- let request ?(body=`Null) m path =
- let uri = process_url path in
- let headers = process_request_headers () in
- let body = process_request_body body in
- (match m with
- | `DELETE -> Cohttp_async.Client.delete ~headers ~body uri
- | `GET -> Cohttp_async.Client.get ~headers uri
- | `PATCH -> Cohttp_async.Client.patch ~headers ~body uri
- | `POST -> Cohttp_async.Client.post ~headers ~body uri
- | `PUT -> Cohttp_async.Client.put ~headers ~body uri
- | _ -> raise Invalid_Method)
- >>= process_response
-end
+ (* TODO Finish processor *)
+ let process_response (_resp, body) =
+ body |> Cohttp_async.Body.to_string >>| Yojson.Basic.from_string
-let get_gateway () =
- Base.request `GET Endpoints.gateway
+ let request ?(body=`Null) m path =
+ let uri = process_url path in
+ let headers = process_request_headers () in
+ let body = process_request_body body in
+ (match m with
+ | `DELETE -> Cohttp_async.Client.delete ~headers ~body uri
+ | `GET -> Cohttp_async.Client.get ~headers uri
+ | `PATCH -> Cohttp_async.Client.patch ~headers ~body uri
+ | `POST -> Cohttp_async.Client.post ~headers ~body uri
+ | `PUT -> Cohttp_async.Client.put ~headers ~body uri
+ | _ -> raise Invalid_Method)
+ >>= process_response
+ end
-let get_gateway_bot () =
- Base.request `GET Endpoints.gateway_bot
+ let get_gateway () =
+ Base.request `GET Endpoints.gateway
-let get_channel channel_id =
- Base.request `GET (Endpoints.channel channel_id)
+ let get_gateway_bot () =
+ Base.request `GET Endpoints.gateway_bot
-let modify_channel channel_id body =
- Base.request ~body `PATCH (Endpoints.channel channel_id)
+ let get_channel channel_id =
+ Base.request `GET (Endpoints.channel channel_id)
-let delete_channel channel_id =
- Base.request `DELETE (Endpoints.channel channel_id)
+ let modify_channel channel_id body =
+ Base.request ~body `PATCH (Endpoints.channel channel_id)
-let get_messages channel_id =
- Base.request `GET (Endpoints.channel_messages channel_id)
+ let delete_channel channel_id =
+ Base.request `DELETE (Endpoints.channel channel_id)
-let get_message channel_id message_id =
- Base.request `GET (Endpoints.channel_message channel_id message_id)
+ let get_messages channel_id =
+ Base.request `GET (Endpoints.channel_messages channel_id)
-let create_message channel_id body =
- Base.request ~body:body `POST (Endpoints.channel_messages channel_id)
+ let get_message channel_id message_id =
+ Base.request `GET (Endpoints.channel_message channel_id message_id)
-let create_reaction channel_id message_id emoji =
- Base.request `PUT (Endpoints.channel_reaction_me channel_id message_id emoji)
+ let create_message channel_id body =
+ Base.request ~body:body `POST (Endpoints.channel_messages channel_id)
-let delete_own_reaction channel_id message_id emoji =
- Base.request `DELETE (Endpoints.channel_reaction_me channel_id message_id emoji)
+ let create_reaction channel_id message_id emoji =
+ Base.request `PUT (Endpoints.channel_reaction_me channel_id message_id emoji)
-let delete_reaction channel_id message_id emoji user_id =
- Base.request `DELETE (Endpoints.channel_reaction channel_id message_id emoji user_id)
+ let delete_own_reaction channel_id message_id emoji =
+ Base.request `DELETE (Endpoints.channel_reaction_me channel_id message_id emoji)
-let get_reactions channel_id message_id emoji =
- Base.request `GET (Endpoints.channel_reactions_get channel_id message_id emoji)
+ let delete_reaction channel_id message_id emoji user_id =
+ Base.request `DELETE (Endpoints.channel_reaction channel_id message_id emoji user_id)
-let delete_reactions channel_id message_id =
- Base.request `DELETE (Endpoints.channel_reactions_delete channel_id message_id)
+ let get_reactions channel_id message_id emoji =
+ Base.request `GET (Endpoints.channel_reactions_get channel_id message_id emoji)
-let edit_message channel_id message_id body =
- Base.request ~body `PATCH (Endpoints.channel_message channel_id message_id)
+ let delete_reactions channel_id message_id =
+ Base.request `DELETE (Endpoints.channel_reactions_delete channel_id message_id)
-let delete_message channel_id message_id =
- Base.request `DELETE (Endpoints.channel_message channel_id message_id)
+ let edit_message channel_id message_id body =
+ Base.request ~body `PATCH (Endpoints.channel_message channel_id message_id)
-let bulk_delete channel_id body =
- Base.request ~body `POST (Endpoints.channel_bulk_delete channel_id)
+ let delete_message channel_id message_id =
+ Base.request `DELETE (Endpoints.channel_message channel_id message_id)
-let edit_channel_permissions channel_id overwrite_id body =
- Base.request ~body `PUT (Endpoints.channel_permission channel_id overwrite_id)
+ let bulk_delete channel_id body =
+ Base.request ~body `POST (Endpoints.channel_bulk_delete channel_id)
-let get_channel_invites channel_id =
- Base.request `GET (Endpoints.channel_invites channel_id)
+ let edit_channel_permissions channel_id overwrite_id body =
+ Base.request ~body `PUT (Endpoints.channel_permission channel_id overwrite_id)
-let create_channel_invite channel_id body =
- Base.request ~body `POST (Endpoints.channel_invites channel_id)
+ let get_channel_invites channel_id =
+ Base.request `GET (Endpoints.channel_invites channel_id)
-let delete_channel_permission channel_id overwrite_id =
- Base.request `DELETE (Endpoints.channel_permission channel_id overwrite_id)
+ let create_channel_invite channel_id body =
+ Base.request ~body `POST (Endpoints.channel_invites channel_id)
-let broadcast_typing channel_id =
- Base.request `POST (Endpoints.channel_typing channel_id)
+ let delete_channel_permission channel_id overwrite_id =
+ Base.request `DELETE (Endpoints.channel_permission channel_id overwrite_id)
-let get_pinned_messages channel_id =
- Base.request `GET (Endpoints.channel_pins channel_id)
+ let broadcast_typing channel_id =
+ Base.request `POST (Endpoints.channel_typing channel_id)
-let pin_message channel_id message_id =
- Base.request `PUT (Endpoints.channel_pin channel_id message_id)
+ let get_pinned_messages channel_id =
+ Base.request `GET (Endpoints.channel_pins channel_id)
-let unpin_message channel_id message_id =
- Base.request `DELETE (Endpoints.channel_pin channel_id message_id)
+ let pin_message channel_id message_id =
+ Base.request `PUT (Endpoints.channel_pin channel_id message_id)
-let group_recipient_add channel_id user_id =
- Base.request `PUT (Endpoints.group_recipient channel_id user_id)
+ let unpin_message channel_id message_id =
+ Base.request `DELETE (Endpoints.channel_pin channel_id message_id)
-let group_recipient_remove channel_id user_id =
- Base.request `DELETE (Endpoints.group_recipient channel_id user_id)
+ let group_recipient_add channel_id user_id =
+ Base.request `PUT (Endpoints.group_recipient channel_id user_id)
-let get_emojis guild_id =
- Base.request `GET (Endpoints.guild_emojis guild_id)
+ let group_recipient_remove channel_id user_id =
+ Base.request `DELETE (Endpoints.group_recipient channel_id user_id)
-let get_emoji guild_id emoji_id =
- Base.request `GET (Endpoints.guild_emoji guild_id emoji_id)
+ let get_emojis guild_id =
+ Base.request `GET (Endpoints.guild_emojis guild_id)
-let create_emoji guild_id body =
- Base.request ~body `POST (Endpoints.guild_emojis guild_id)
+ let get_emoji guild_id emoji_id =
+ Base.request `GET (Endpoints.guild_emoji guild_id emoji_id)
-let edit_emoji guild_id emoji_id body =
- Base.request ~body `PATCH (Endpoints.guild_emoji guild_id emoji_id)
+ let create_emoji guild_id body =
+ Base.request ~body `POST (Endpoints.guild_emojis guild_id)
-let delete_emoji guild_id emoji_id =
- Base.request `DELETE (Endpoints.guild_emoji guild_id emoji_id)
+ let edit_emoji guild_id emoji_id body =
+ Base.request ~body `PATCH (Endpoints.guild_emoji guild_id emoji_id)
-let create_guild body =
- Base.request ~body `POST Endpoints.guilds
+ let delete_emoji guild_id emoji_id =
+ Base.request `DELETE (Endpoints.guild_emoji guild_id emoji_id)
-let get_guild guild_id =
- Base.request `GET (Endpoints.guild guild_id)
+ let create_guild body =
+ Base.request ~body `POST Endpoints.guilds
-let edit_guild guild_id body =
- Base.request ~body `PATCH (Endpoints.guild guild_id)
+ let get_guild guild_id =
+ Base.request `GET (Endpoints.guild guild_id)
-let delete_guild guild_id =
- Base.request `DELETE (Endpoints.guild guild_id)
+ let edit_guild guild_id body =
+ Base.request ~body `PATCH (Endpoints.guild guild_id)
-let get_guild_channels guild_id =
- Base.request `GET (Endpoints.guild_channels guild_id)
+ let delete_guild guild_id =
+ Base.request `DELETE (Endpoints.guild guild_id)
-let create_guild_channel guild_id body =
- Base.request ~body `POST (Endpoints.guild_channels guild_id)
+ let get_guild_channels guild_id =
+ Base.request `GET (Endpoints.guild_channels guild_id)
-let modify_guild_channel_positions guild_id body =
- Base.request ~body `PATCH (Endpoints.guild_channels guild_id)
+ let create_guild_channel guild_id body =
+ Base.request ~body `POST (Endpoints.guild_channels guild_id)
-let get_member guild_id user_id =
- Base.request `GET (Endpoints.guild_member guild_id user_id)
+ let modify_guild_channel_positions guild_id body =
+ Base.request ~body `PATCH (Endpoints.guild_channels guild_id)
-let get_members guild_id =
- Base.request `GET (Endpoints.guild_members guild_id)
+ let get_member guild_id user_id =
+ Base.request `GET (Endpoints.guild_member guild_id user_id)
-let add_member guild_id user_id body =
- Base.request ~body `PUT (Endpoints.guild_member guild_id user_id)
+ let get_members guild_id =
+ Base.request `GET (Endpoints.guild_members guild_id)
-let edit_member guild_id user_id body =
- Base.request ~body `PATCH (Endpoints.guild_member guild_id user_id)
+ let add_member guild_id user_id body =
+ Base.request ~body `PUT (Endpoints.guild_member guild_id user_id)
-let remove_member guild_id user_id =
- Base.request `DELETE (Endpoints.guild_member guild_id user_id)
+ let edit_member guild_id user_id body =
+ Base.request ~body `PATCH (Endpoints.guild_member guild_id user_id)
-let change_nickname guild_id body =
- Base.request ~body `PATCH (Endpoints.guild_me_nick guild_id)
+ let remove_member guild_id user_id =
+ Base.request `DELETE (Endpoints.guild_member guild_id user_id)
-let add_member_role guild_id user_id role_id =
- Base.request `PUT (Endpoints.guild_member_role guild_id user_id role_id)
+ let change_nickname guild_id body =
+ Base.request ~body `PATCH (Endpoints.guild_me_nick guild_id)
-let remove_member_role guild_id user_id role_id =
- Base.request `DELETE (Endpoints.guild_member_role guild_id user_id role_id)
+ let add_member_role guild_id user_id role_id =
+ Base.request `PUT (Endpoints.guild_member_role guild_id user_id role_id)
-let get_bans guild_id =
- Base.request `GET (Endpoints.guild_bans guild_id)
+ let remove_member_role guild_id user_id role_id =
+ Base.request `DELETE (Endpoints.guild_member_role guild_id user_id role_id)
-let get_ban guild_id user_id =
- Base.request `GET (Endpoints.guild_ban guild_id user_id)
+ let get_bans guild_id =
+ Base.request `GET (Endpoints.guild_bans guild_id)
-let guild_ban_add guild_id user_id body =
- Base.request ~body `PUT (Endpoints.guild_ban guild_id user_id)
+ let get_ban guild_id user_id =
+ Base.request `GET (Endpoints.guild_ban guild_id user_id)
-let guild_ban_remove guild_id user_id =
- Base.request `DELETE (Endpoints.guild_ban guild_id user_id)
+ let guild_ban_add guild_id user_id body =
+ Base.request ~body `PUT (Endpoints.guild_ban guild_id user_id)
-let get_roles guild_id =
- Base.request `GET (Endpoints.guild_roles guild_id)
+ let guild_ban_remove guild_id user_id =
+ Base.request `DELETE (Endpoints.guild_ban guild_id user_id)
-let guild_role_add guild_id body =
- Base.request ~body `POST (Endpoints.guild_roles guild_id)
+ let get_roles guild_id =
+ Base.request `GET (Endpoints.guild_roles guild_id)
-let guild_roles_edit guild_id body =
- Base.request ~body `PATCH (Endpoints.guild_roles guild_id)
+ let guild_role_add guild_id body =
+ Base.request ~body `POST (Endpoints.guild_roles guild_id)
-let guild_role_edit guild_id role_id body =
- Base.request ~body `PATCH (Endpoints.guild_role guild_id role_id)
+ let guild_roles_edit guild_id body =
+ Base.request ~body `PATCH (Endpoints.guild_roles guild_id)
-let guild_role_remove guild_id role_id =
- Base.request `DELETE (Endpoints.guild_role guild_id role_id)
+ let guild_role_edit guild_id role_id body =
+ Base.request ~body `PATCH (Endpoints.guild_role guild_id role_id)
-let guild_prune_count guild_id =
- Base.request `GET (Endpoints.guild_prune guild_id)
+ let guild_role_remove guild_id role_id =
+ Base.request `DELETE (Endpoints.guild_role guild_id role_id)
-let guild_prune_start guild_id body =
- Base.request ~body `POST (Endpoints.guild_prune guild_id)
+ let guild_prune_count guild_id =
+ Base.request `GET (Endpoints.guild_prune guild_id)
-let get_guild_voice_regions guild_id =
- Base.request `GET (Endpoints.guild_voice_regions guild_id)
+ let guild_prune_start guild_id body =
+ Base.request ~body `POST (Endpoints.guild_prune guild_id)
-let get_guild_invites guild_id =
- Base.request `GET (Endpoints.guild_invites guild_id)
+ let get_guild_voice_regions guild_id =
+ Base.request `GET (Endpoints.guild_voice_regions guild_id)
-let get_integrations guild_id =
- Base.request `GET (Endpoints.guild_integrations guild_id)
+ let get_guild_invites guild_id =
+ Base.request `GET (Endpoints.guild_invites guild_id)
-let add_integration guild_id body =
- Base.request ~body `POST (Endpoints.guild_integrations guild_id)
+ let get_integrations guild_id =
+ Base.request `GET (Endpoints.guild_integrations guild_id)
-let edit_integration guild_id integration_id body =
- Base.request ~body `POST (Endpoints.guild_integration guild_id integration_id)
+ let add_integration guild_id body =
+ Base.request ~body `POST (Endpoints.guild_integrations guild_id)
-let delete_integration guild_id integration_id =
- Base.request `DELETE (Endpoints.guild_integration guild_id integration_id)
+ let edit_integration guild_id integration_id body =
+ Base.request ~body `POST (Endpoints.guild_integration guild_id integration_id)
-let sync_integration guild_id integration_id =
- Base.request `POST (Endpoints.guild_integration_sync guild_id integration_id)
+ let delete_integration guild_id integration_id =
+ Base.request `DELETE (Endpoints.guild_integration guild_id integration_id)
-let get_guild_embed guild_id =
- Base.request `GET (Endpoints.guild_embed guild_id)
+ let sync_integration guild_id integration_id =
+ Base.request `POST (Endpoints.guild_integration_sync guild_id integration_id)
-let edit_guild_embed guild_id body =
- Base.request ~body `PATCH (Endpoints.guild_embed guild_id)
+ let get_guild_embed guild_id =
+ Base.request `GET (Endpoints.guild_embed guild_id)
-let get_vanity_url guild_id =
- Base.request `GET (Endpoints.guild_vanity_url guild_id)
+ let edit_guild_embed guild_id body =
+ Base.request ~body `PATCH (Endpoints.guild_embed guild_id)
-let get_invite invite_code =
- Base.request `GET (Endpoints.invite invite_code)
+ let get_vanity_url guild_id =
+ Base.request `GET (Endpoints.guild_vanity_url guild_id)
-let delete_invite invite_code =
- Base.request `DELETE (Endpoints.invite invite_code)
+ let get_invite invite_code =
+ Base.request `GET (Endpoints.invite invite_code)
-let get_current_user () =
- Base.request `GET Endpoints.me
+ let delete_invite invite_code =
+ Base.request `DELETE (Endpoints.invite invite_code)
-let edit_current_user body =
- Base.request ~body `PATCH Endpoints.me
+ let get_current_user () =
+ Base.request `GET Endpoints.me
-let get_guilds () =
- Base.request `GET Endpoints.me_guilds
+ let edit_current_user body =
+ Base.request ~body `PATCH Endpoints.me
-let leave_guild guild_id =
- Base.request `DELETE (Endpoints.me_guild guild_id)
+ let get_guilds () =
+ Base.request `GET Endpoints.me_guilds
-let get_private_channels () =
- Base.request `GET Endpoints.me_channels
+ let leave_guild guild_id =
+ Base.request `DELETE (Endpoints.me_guild guild_id)
-let create_dm body =
- Base.request ~body `POST Endpoints.me_channels
+ let get_private_channels () =
+ Base.request `GET Endpoints.me_channels
-let create_group_dm body =
- Base.request ~body `POST Endpoints.me_channels
+ let create_dm body =
+ Base.request ~body `POST Endpoints.me_channels
-let get_connections () =
- Base.request `GET Endpoints.me_connections
+ let create_group_dm body =
+ Base.request ~body `POST Endpoints.me_channels
-let get_user user_id =
- Base.request `GET (Endpoints.user user_id)
+ let get_connections () =
+ Base.request `GET Endpoints.me_connections
-let get_voice_regions () =
- Base.request `GET Endpoints.regions
+ let get_user user_id =
+ Base.request `GET (Endpoints.user user_id)
-let create_webhook channel_id body =
- Base.request ~body `POST (Endpoints.webhooks_channel channel_id)
+ let get_voice_regions () =
+ Base.request `GET Endpoints.regions
-let get_channel_webhooks channel_id =
- Base.request `GET (Endpoints.webhooks_channel channel_id)
+ let create_webhook channel_id body =
+ Base.request ~body `POST (Endpoints.webhooks_channel channel_id)
-let get_guild_webhooks guild_id =
- Base.request `GET (Endpoints.webhooks_guild guild_id)
+ let get_channel_webhooks channel_id =
+ Base.request `GET (Endpoints.webhooks_channel channel_id)
-let get_webhook webhook_id =
- Base.request `GET (Endpoints.webhook webhook_id)
+ let get_guild_webhooks guild_id =
+ Base.request `GET (Endpoints.webhooks_guild guild_id)
-let get_webhook_with_token webhook_id token =
- Base.request `GET (Endpoints.webhook_token webhook_id token)
+ let get_webhook webhook_id =
+ Base.request `GET (Endpoints.webhook webhook_id)
-let edit_webhook webhook_id body =
- Base.request ~body `PATCH (Endpoints.webhook webhook_id)
+ let get_webhook_with_token webhook_id token =
+ Base.request `GET (Endpoints.webhook_token webhook_id token)
-let edit_webhook_with_token webhook_id token body =
- Base.request ~body `PATCH (Endpoints.webhook_token webhook_id token)
+ let edit_webhook webhook_id body =
+ Base.request ~body `PATCH (Endpoints.webhook webhook_id)
-let delete_webhook webhook_id =
- Base.request `DELETE (Endpoints.webhook webhook_id)
+ let edit_webhook_with_token webhook_id token body =
+ Base.request ~body `PATCH (Endpoints.webhook_token webhook_id token)
-let delete_webhook_with_token webhook_id token =
- Base.request `DELETE (Endpoints.webhook_token webhook_id token)
+ let delete_webhook webhook_id =
+ Base.request `DELETE (Endpoints.webhook webhook_id)
-let execute_webhook webhook_id token body =
- Base.request ~body `POST (Endpoints.webhook_token webhook_id token)
+ let delete_webhook_with_token webhook_id token =
+ Base.request `DELETE (Endpoints.webhook_token webhook_id token)
-let execute_slack_webhook webhook_id token body =
- Base.request ~body `POST (Endpoints.webhook_slack webhook_id token)
+ let execute_webhook webhook_id token body =
+ Base.request ~body `POST (Endpoints.webhook_token webhook_id token)
-let execute_git_webhook webhook_id token body =
- Base.request ~body `POST (Endpoints.webhook_git webhook_id token)
+ let execute_slack_webhook webhook_id token body =
+ Base.request ~body `POST (Endpoints.webhook_slack webhook_id token)
-let get_audit_logs guild_id body =
- Base.request ~body `GET (Endpoints.guild_audit_logs guild_id) \ No newline at end of file
+ let execute_git_webhook webhook_id token body =
+ Base.request ~body `POST (Endpoints.webhook_git webhook_id token)
+
+ let get_audit_logs guild_id body =
+ Base.request ~body `GET (Endpoints.guild_audit_logs guild_id)
+end \ No newline at end of file
diff --git a/lib/s.ml b/lib/s.ml
new file mode 100644
index 0000000..92259a0
--- /dev/null
+++ b/lib/s.ml
@@ -0,0 +1,31 @@
+open Async
+open Cohttp
+
+module type Token = sig
+ val token : string
+end
+
+module type Http = sig
+ module Base : sig
+ exception Invalid_Method
+
+ val base_url : string
+
+ val process_url : string -> Uri.t
+ val process_request_body : Yojson.Basic.json -> Cohttp_async.Body.t
+ val process_request_headers : unit -> Headers.t
+
+ val process_response :
+ Cohttp_async.Response.t * Cohttp_async.Body.t ->
+ Yojson.Basic.json
+
+ val request :
+ ?body:Yojson.Basic.json ->
+ [ `Delete | `Get | `Patch | `Post | `Put ] ->
+ string ->
+ Yojson.Basic.json Deferred.t
+ end
+
+ (* TODO add abstraction sigs *)
+ val token : string
+end \ No newline at end of file
diff --git a/lib/sharder.ml b/lib/sharder.ml
index 7f66b4e..1fa97a0 100644
--- a/lib/sharder.ml
+++ b/lib/sharder.ml
@@ -2,300 +2,303 @@ open Async
open Core
open Websocket_async
-exception Invalid_Payload
-exception Failure_to_Establish_Heartbeat
+module Make(H: S.Http) = struct
+ exception Invalid_Payload
+ exception Failure_to_Establish_Heartbeat
-module Shard = struct
- type shard = {
- hb: unit Ivar.t option;
- seq: int;
- session: string option;
- pipe: Frame.t Pipe.Reader.t * Frame.t Pipe.Writer.t;
- ready: unit Ivar.t;
- token: string;
- url: string;
- id: int * int;
- }
+ let token = H.token
- type 'a t = {
- mutable shard: 'a;
- mutable binds: ('a -> unit) list;
- }
+ module Shard = struct
+ type shard = {
+ hb: unit Ivar.t option;
+ seq: int;
+ session: string option;
+ pipe: Frame.t Pipe.Reader.t * Frame.t Pipe.Writer.t;
+ ready: unit Ivar.t;
+ url: string;
+ id: int * int;
+ }
- let identify_lock = Mutex.create ()
+ type 'a t = {
+ mutable shard: 'a;
+ mutable binds: ('a -> unit) list;
+ }
- let bind ~f t =
- t.binds <- f :: t.binds
+ let identify_lock = Mutex.create ()
- let parse (frame:[`Ok of Frame.t | `Eof]) =
- match frame with
- | `Ok s -> begin
- let open Frame.Opcode in
- match s.opcode with
- | Text -> Some (Yojson.Basic.from_string s.content)
- | _ -> None
- end
- | `Eof -> None
+ let bind ~f t =
+ t.binds <- f :: t.binds
- let push_frame ?payload ~ev shard =
- print_endline @@ "Pushing frame. OP: " ^ Opcode.to_string @@ ev;
- let content = match payload with
- | None -> ""
- | Some p ->
- Yojson.Basic.to_string @@ `Assoc [
- ("op", `Int (Opcode.to_int ev));
- ("d", p);
- ]
- in
- let (_, write) = shard.pipe in
- Pipe.write_if_open write @@ Frame.create ~content ()
- >>| fun () ->
- shard
+ let parse (frame:[`Ok of Frame.t | `Eof]) =
+ match frame with
+ | `Ok s -> begin
+ let open Frame.Opcode in
+ match s.opcode with
+ | Text -> Some (Yojson.Basic.from_string s.content)
+ | _ -> None
+ end
+ | `Eof -> None
- let heartbeat shard =
- let payload = match shard.seq with
- | 0 -> `Null
- | i -> `Int i
- in
- push_frame ~payload ~ev:HEARTBEAT shard
+ let push_frame ?payload ~ev shard =
+ print_endline @@ "Pushing frame. OP: " ^ Opcode.to_string @@ ev;
+ let content = match payload with
+ | None -> ""
+ | Some p ->
+ Yojson.Basic.to_string @@ `Assoc [
+ ("op", `Int (Opcode.to_int ev));
+ ("d", p);
+ ]
+ in
+ let (_, write) = shard.pipe in
+ Pipe.write_if_open write @@ Frame.create ~content ()
+ >>| fun () ->
+ shard
- let dispatch ~payload shard =
- let module J = Yojson.Basic.Util in
- let seq = J.(member "s" payload |> to_int) in
- let t = J.(member "t" payload |> to_string) in
- let data = J.member "d" payload in
- let session = J.(member "session_id" data |> to_string_option) in
- if t = "READY" then begin
- Ivar.fill_if_empty shard.ready ();
- end;
- return { shard with
- seq = seq;
- session = session;
- }
+ let heartbeat shard =
+ let payload = match shard.seq with
+ | 0 -> `Null
+ | i -> `Int i
+ in
+ push_frame ~payload ~ev:HEARTBEAT shard
- let set_status ~status shard =
- let payload = match status with
- | `Assoc [("name", `String name); ("type", `Int t)] ->
- `Assoc [
- ("status", `String "online");
- ("afk", `Bool false);
- ("since", `Null);
- ("game", `Assoc [
- ("name", `String name);
- ("type", `Int t)
- ])
- ]
- | `String name ->
- `Assoc [
- ("status", `String "online");
- ("afk", `Bool false);
- ("since", `Null);
- ("game", `Assoc [
- ("name", `String name);
- ("type", `Int 0)
- ])
- ]
- | _ -> raise Invalid_Payload
- in
- Ivar.read shard.ready >>= fun _ ->
- push_frame ~payload ~ev:STATUS_UPDATE shard
+ let dispatch ~payload shard =
+ let module J = Yojson.Basic.Util in
+ let seq = J.(member "s" payload |> to_int) in
+ let t = J.(member "t" payload |> to_string) in
+ let data = J.member "d" payload in
+ let session = J.(member "session_id" data |> to_string_option) in
+ if t = "READY" then begin
+ Ivar.fill_if_empty shard.ready ();
+ end;
+ return { shard with
+ seq = seq;
+ session = session;
+ }
- let request_guild_members ~guild ?(query="") ?(limit=0) shard =
- let payload = `Assoc [
- ("guild_id", `String (string_of_int guild));
- ("query", `String query);
- ("limit", `Int limit);
- ] in
- Ivar.read shard.ready >>= fun _ ->
- push_frame ~payload ~ev:REQUEST_GUILD_MEMBERS shard
+ let set_status ~status shard =
+ let payload = match status with
+ | `Assoc [("name", `String name); ("type", `Int t)] ->
+ `Assoc [
+ ("status", `String "online");
+ ("afk", `Bool false);
+ ("since", `Null);
+ ("game", `Assoc [
+ ("name", `String name);
+ ("type", `Int t)
+ ])
+ ]
+ | `String name ->
+ `Assoc [
+ ("status", `String "online");
+ ("afk", `Bool false);
+ ("since", `Null);
+ ("game", `Assoc [
+ ("name", `String name);
+ ("type", `Int 0)
+ ])
+ ]
+ | _ -> raise Invalid_Payload
+ in
+ Ivar.read shard.ready >>= fun _ ->
+ push_frame ~payload ~ev:STATUS_UPDATE shard
- let initialize ?data shard =
- let module J = Yojson.Basic.Util in
- let hb = match shard.hb with
- | None -> begin
- match data with
- | Some data ->
- let hb_interval = J.(member "heartbeat_interval" data |> to_int) in
- let finished = Ivar.create () in
- Clock.every'
- ~continue_on_error:true
- ~finished
- (Core.Time.Span.create ~ms:hb_interval ())
- (fun () -> heartbeat shard >>= fun _ -> return ());
- finished
- | None -> raise Failure_to_Establish_Heartbeat
- end
- | Some s -> s
- in
- let shard = { shard with hb = Some hb; } in
- let (cur, max) = shard.id in
- let shards = [`Int cur; `Int max] in
- match shard.session with
- | None -> begin
- Mutex.lock identify_lock;
+ let request_guild_members ~guild ?(query="") ?(limit=0) shard =
let payload = `Assoc [
- ("token", `String shard.token);
- ("properties", `Assoc [
- ("$os", `String Sys.os_type);
- ("$device", `String "dis.ml");
- ("$browser", `String "dis.ml")
- ]);
- ("compress", `Bool false); (* TODO add compression handling*)
- ("large_threshold", `Int 250);
- ("shard", `List shards);
+ ("guild_id", `String (string_of_int guild));
+ ("query", `String query);
+ ("limit", `Int limit);
] in
- push_frame ~payload ~ev:IDENTIFY shard
- >>| fun s -> begin
- Clock.after (Core.Time.Span.create ~sec:5 ())
- >>> (fun _ -> Mutex.unlock identify_lock);
- s
+ Ivar.read shard.ready >>= fun _ ->
+ push_frame ~payload ~ev:REQUEST_GUILD_MEMBERS shard
+
+ let initialize ?data shard =
+ let module J = Yojson.Basic.Util in
+ let hb = match shard.hb with
+ | None -> begin
+ match data with
+ | Some data ->
+ let hb_interval = J.(member "heartbeat_interval" data |> to_int) in
+ let finished = Ivar.create () in
+ Clock.every'
+ ~continue_on_error:true
+ ~finished
+ (Core.Time.Span.create ~ms:hb_interval ())
+ (fun () -> heartbeat shard >>= fun _ -> return ());
+ finished
+ | None -> raise Failure_to_Establish_Heartbeat
end
- end
- | Some s ->
- let payload = `Assoc [
- ("token", `String shard.token);
- ("session_id", `String s);
- ("seq", `Int shard.seq)
- ] in
- push_frame ~payload ~ev:RESUME shard
+ | Some s -> s
+ in
+ let shard = { shard with hb = Some hb; } in
+ let (cur, max) = shard.id in
+ let shards = [`Int cur; `Int max] in
+ match shard.session with
+ | None -> begin
+ Mutex.lock identify_lock;
+ let payload = `Assoc [
+ ("token", `String shard.token);
+ ("properties", `Assoc [
+ ("$os", `String Sys.os_type);
+ ("$device", `String "dis.ml");
+ ("$browser", `String "dis.ml")
+ ]);
+ ("compress", `Bool false); (* TODO add compression handling*)
+ ("large_threshold", `Int 250);
+ ("shard", `List shards);
+ ] in
+ push_frame ~payload ~ev:IDENTIFY shard
+ >>| fun s -> begin
+ Clock.after (Core.Time.Span.create ~sec:5 ())
+ >>> (fun _ -> Mutex.unlock identify_lock);
+ s
+ end
+ end
+ | Some s ->
+ let payload = `Assoc [
+ ("token", `String shard.token);
+ ("session_id", `String s);
+ ("seq", `Int shard.seq)
+ ] in
+ push_frame ~payload ~ev:RESUME shard
- let handle_frame ~f shard =
- let module J = Yojson.Basic.Util in
- let op = J.(member "op" f |> to_int)
- |> Opcode.from_int
- in
- match op with
- | DISPATCH -> dispatch ~payload:f shard
- | HEARTBEAT -> heartbeat shard
- | INVALID_SESSION -> begin
- if J.(member "d" f |> to_bool) then
- initialize shard
- else begin
- initialize { shard with session = None; }
+ let handle_frame ~f shard =
+ let module J = Yojson.Basic.Util in
+ let op = J.(member "op" f |> to_int)
+ |> Opcode.from_int
+ in
+ match op with
+ | DISPATCH -> dispatch ~payload:f shard
+ | HEARTBEAT -> heartbeat shard
+ | INVALID_SESSION -> begin
+ if J.(member "d" f |> to_bool) then
+ initialize shard
+ else begin
+ initialize { shard with session = None; }
+ end
end
- end
- | RECONNECT -> initialize shard
- | HELLO -> initialize ~data:(J.member "d" f) shard
- | HEARTBEAT_ACK -> return shard
- | opcode ->
- print_endline @@ "Invalid Opcode: " ^ Opcode.to_string opcode;
- return shard
+ | RECONNECT -> initialize shard
+ | HELLO -> initialize ~data:(J.member "d" f) shard
+ | HEARTBEAT_ACK -> return shard
+ | opcode ->
+ print_endline @@ "Invalid Opcode: " ^ Opcode.to_string opcode;
+ return shard
- let rec create ~url ~shards ~token () =
- let open Core in
- let uri = (url ^ "?v=6&encoding=json") |> Uri.of_string in
- let extra_headers = Http.Base.process_request_headers () in
- let host = Option.value_exn ~message:"no host in uri" Uri.(host uri) in
- let port =
- match Uri.port uri, Uri_services.tcp_port_of_uri uri with
- | Some p, _ -> p
- | None, Some p -> p
- | _ -> 443 in
- let scheme = Option.value_exn ~message:"no scheme in uri" Uri.(scheme uri) in
- let tcp_fun (net_to_ws, ws_to_net) =
- let (app_to_ws, write) = Pipe.create () in
- let (read, ws_to_app) = Pipe.create () in
- let initialized = Ivar.create () in
- client
- ~initialized
- ~extra_headers
- ~app_to_ws
- ~ws_to_app
- ~net_to_ws
- ~ws_to_net
- uri
- >>> ignore; (* TODO this needs to error check and retry with backoff *)
- Ivar.read initialized >>| fun () ->
- {
- pipe = (read, write);
- ready = Ivar.create ();
- hb = None;
- seq = 0;
- id = shards;
- session = None;
- token;
- url;
- }
- in
- match Unix.getaddrinfo host (string_of_int port) [] with
- | [] -> failwithf "DNS resolution failed for %s" host ()
- | { ai_addr; _ } :: _ ->
- let addr =
- match scheme, ai_addr with
- | _, ADDR_UNIX path -> `Unix_domain_socket path
- | "https", ADDR_INET (h, p)
- | "wss", ADDR_INET (h, p) ->
- let h = Ipaddr_unix.of_inet_addr h in
- `OpenSSL (h, p, Conduit_async.V2.Ssl.Config.create ())
- | _, ADDR_INET (h, p) ->
- let h = Ipaddr_unix.of_inet_addr h in
- `TCP (h, p)
+ let rec create ~url ~shards ~token () =
+ let open Core in
+ let uri = (url ^ "?v=6&encoding=json") |> Uri.of_string in
+ let extra_headers = H.Base.process_request_headers () in
+ let host = Option.value_exn ~message:"no host in uri" Uri.(host uri) in
+ let port =
+ match Uri.port uri, Uri_services.tcp_port_of_uri uri with
+ | Some p, _ -> p
+ | None, Some p -> p
+ | _ -> 443 in
+ let scheme = Option.value_exn ~message:"no scheme in uri" Uri.(scheme uri) in
+ let tcp_fun (net_to_ws, ws_to_net) =
+ let (app_to_ws, write) = Pipe.create () in
+ let (read, ws_to_app) = Pipe.create () in
+ let initialized = Ivar.create () in
+ client
+ ~initialized
+ ~extra_headers
+ ~app_to_ws
+ ~ws_to_app
+ ~net_to_ws
+ ~ws_to_net
+ uri
+ >>> ignore; (* TODO this needs to error check and retry with backoff *)
+ Ivar.read initialized >>| fun () ->
+ {
+ pipe = (read, write);
+ ready = Ivar.create ();
+ hb = None;
+ seq = 0;
+ id = shards;
+ session = None;
+ token;
+ url;
+ }
in
- Conduit_async.V2.connect addr >>= tcp_fun
- and recreate shard =
- print_endline "Reconnecting...";
- (match shard.hb with
- | Some hb -> Ivar.fill_if_empty hb ()
- | None -> ()
- );
- create ~url:(shard.url) ~shards:(shard.id) ~token:(shard.token) ()
-end
+ match Unix.getaddrinfo host (string_of_int port) [] with
+ | [] -> failwithf "DNS resolution failed for %s" host ()
+ | { ai_addr; _ } :: _ ->
+ let addr =
+ match scheme, ai_addr with
+ | _, ADDR_UNIX path -> `Unix_domain_socket path
+ | "https", ADDR_INET (h, p)
+ | "wss", ADDR_INET (h, p) ->
+ let h = Ipaddr_unix.of_inet_addr h in
+ `OpenSSL (h, p, Conduit_async.V2.Ssl.Config.create ())
+ | _, ADDR_INET (h, p) ->
+ let h = Ipaddr_unix.of_inet_addr h in
+ `TCP (h, p)
+ in
+ Conduit_async.V2.connect addr >>= tcp_fun
+ and recreate shard =
+ print_endline "Reconnecting...";
+ (match shard.hb with
+ | Some hb -> Ivar.fill_if_empty hb ()
+ | None -> ()
+ );
+ create ~url:(shard.url) ~shards:(shard.id) ~token:(shard.token) ()
+ end
-type t = {
- shards: (Shard.shard Shard.t) list;
-}
+ type t = {
+ shards: (Shard.shard Shard.t) list;
+ }
-let start ?count token =
- let module J = Yojson.Basic.Util in
- Http.get_gateway_bot () >>= fun data ->
- let url = J.(member "url" data |> to_string) in
- let count = match count with
- | Some c -> c
- | None -> J.(member "shards" data |> to_int)
- in
- let shard_list = (0, count) in
- let rec ev_loop t =
- let (read, _) = t.shard.pipe in
- Pipe.read read
- >>| fun frame ->
- let _ = match parse frame with
- | Some f -> begin
- handle_frame ~f t.shard
- >>> fun shard ->
- t.shard <- shard;
- end
- | None -> t.shard <- recreate t.shard;
+ let start ?count token =
+ let module J = Yojson.Basic.Util in
+ Http.get_gateway_bot () >>= fun data ->
+ let url = J.(member "url" data |> to_string) in
+ let count = match count with
+ | Some c -> c
+ | None -> J.(member "shards" data |> to_int)
+ in
+ let shard_list = (0, count) in
+ let rec ev_loop t =
+ let (read, _) = t.shard.pipe in
+ Pipe.read read
+ >>| fun frame ->
+ let _ = match parse frame with
+ | Some f -> begin
+ handle_frame ~f t.shard
+ >>> fun shard ->
+ t.shard <- shard;
+ end
+ | None -> t.shard <- recreate t.shard;
+ in
+ t
+ >>= fun t ->
+ List.iter ~f:(fun f -> f t.shard) t.binds;
+ ev_loop t
+ in
+ let rec gen_shards l a =
+ match l with
+ | (id, total) when id >= total -> return a
+ | (id, total) ->
+ Shard.create ~url ~shards:(id, total) ~token ()
+ >>= fun shard ->
+ let t = { shard; binds = []; } in
+ ev_loop t >>> ignore;
+ gen_shards (id+1, total) (t :: a)
in
- t
- >>= fun t ->
- List.iter ~f:(fun f -> f t.shard) t.binds;
- ev_loop t
- in
- let rec gen_shards l a =
- match l with
- | (id, total) when id >= total -> return a
- | (id, total) ->
- Shard.create ~url ~shards:(id, total) ~token ()
- >>= fun shard ->
- let t = { shard; binds = []; } in
- ev_loop t >>> ignore;
- gen_shards (id+1, total) (t :: a)
- in
- gen_shards shard_list []
- >>| fun shards ->
- { shards; }
+ gen_shards shard_list []
+ >>| fun shards ->
+ { shards; }
-let set_status sharder status =
- Deferred.all @@ List.map ~f:(fun t ->
- Shard.set_status ~status t.shard
- ) sharder.shards
+ let set_status sharder status =
+ Deferred.all @@ List.map ~f:(fun t ->
+ Shard.set_status ~status t.shard
+ ) sharder.shards
-let set_status_with sharder f =
- Deferred.all @@ List.map ~f:(fun t ->
- Shard.set_status ~status:(f t.shard) t.shard
- ) sharder.shards
+ let set_status_with sharder f =
+ Deferred.all @@ List.map ~f:(fun t ->
+ Shard.set_status ~status:(f t.shard) t.shard
+ ) sharder.shards
-let request_guild_members ~guild ?query ?limit sharder =
- Deferred.all @@ List.map ~f:(fun t ->
- Shard.request_guild_members ~guild ?query ?limit t.shard
- ) sharder.shards
+ let request_guild_members ~guild ?query ?limit sharder =
+ Deferred.all @@ List.map ~f:(fun t ->
+ Shard.request_guild_members ~guild ?query ?limit t.shard
+ ) sharder.shards
+end \ No newline at end of file