Current section
Files
Jump to
Current section
Files
src/network/rest.gleam
//// This handles the logic for communicating with the Discord REST API. For more information: https://discord.com/developers/docs/reference#http-api
import gleam/dynamic
import gleam/result.{try}
import gleam/hackney
import gleam/http.{type Header}
import gleam/http/request as req
import gleam/http/response
import gleam/io
import gleam/json
import gleeunit/should
import models/api
import models/decoders
const base_url = "https://discord.com/api"
const api_version = "v10"
/// Acceptable values for an Authorization header
pub type TokenType {
Bearer
Bot
}
pub fn decode_application(
json_string: String,
) -> Result(api.Application, json.DecodeError) {
let user_decoder =
decoders.user(
api.User,
dynamic.field("id", of: dynamic.string),
dynamic.field("username", of: dynamic.string),
dynamic.field("discriminator", of: dynamic.string),
dynamic.optional_field("global_name", of: dynamic.string),
dynamic.optional_field("avatar", of: dynamic.string),
dynamic.optional_field("bot", of: dynamic.bool),
dynamic.optional_field("system", of: dynamic.bool),
dynamic.optional_field("mfa_enabled", of: dynamic.bool),
dynamic.optional_field("banner", of: dynamic.string),
dynamic.optional_field("accent_color", of: dynamic.int),
dynamic.optional_field("locale", of: dynamic.string),
dynamic.optional_field("email", of: dynamic.string),
dynamic.optional_field("flags", of: dynamic.int),
dynamic.optional_field("premium_type", of: dynamic.int),
dynamic.optional_field("public_flags", of: dynamic.int),
dynamic.optional_field("avatar_decoration", of: dynamic.string),
)
let member_decoder =
decoders.member(
api.Member,
dynamic.field("membership_state", of: dynamic.int),
dynamic.field("team_id", of: dynamic.string),
dynamic.field("user", of: user_decoder),
dynamic.field("role", of: dynamic.string),
)
let team_decoder =
decoders.team(
api.Team,
dynamic.field("id", of: dynamic.string),
dynamic.optional_field("icon", of: dynamic.string),
dynamic.field("members", of: dynamic.list(member_decoder)),
dynamic.field("name", of: dynamic.string),
dynamic.field("owner_user_id", of: dynamic.string),
)
let install_params_decoder =
decoders.install_params(
api.InstallParams,
dynamic.field("scopes", dynamic.list(dynamic.string)),
dynamic.field("permissions", dynamic.string),
)
let application_decoder =
decoders.application(
api.Application,
dynamic.field("id", of: dynamic.string),
dynamic.field("name", of: dynamic.string),
dynamic.optional_field("icon", of: dynamic.string),
dynamic.field("description", of: dynamic.string),
dynamic.optional_field("rpc_origins", of: dynamic.list(dynamic.string)),
dynamic.field("bot_public", of: dynamic.bool),
dynamic.field("bot_require_code_grant", of: dynamic.bool),
dynamic.optional_field("bot", of: user_decoder),
dynamic.optional_field("terms_of_service_url", of: dynamic.string),
dynamic.optional_field("privacy_policy_url", of: dynamic.string),
dynamic.optional_field("owner", of: user_decoder),
dynamic.optional_field("summary", of: dynamic.string),
dynamic.field("verify_key", of: dynamic.string),
dynamic.optional_field("team", of: team_decoder),
dynamic.optional_field("guild_id", of: dynamic.string),
dynamic.optional_field("primary_sku_id", of: dynamic.string),
dynamic.optional_field("slug", of: dynamic.string),
dynamic.optional_field("cover_image", of: dynamic.string),
dynamic.optional_field("flags", of: dynamic.int),
dynamic.optional_field("approximate_guild_count", of: dynamic.int),
dynamic.optional_field("redirect_uris", of: dynamic.list(dynamic.string)),
dynamic.optional_field("interactions_endpoint_url", of: dynamic.string),
dynamic.optional_field(
"role_connections_verification_url",
of: dynamic.string,
),
dynamic.optional_field("tags", of: dynamic.list(dynamic.string)),
dynamic.optional_field("install_params", of: install_params_decoder),
dynamic.optional_field("custom_install_url", of: dynamic.string),
)
json.decode(from: json_string, using: application_decoder)
}
pub fn request(
ua_url: String,
version: String,
token_type: TokenType,
token: String,
) {
let token_type_str = case token_type {
Bearer -> "Bearer"
Bot -> "Bot"
}
let assert Ok(req) =
req.to(base_url <> "/" <> api_version <> "/applications/@me")
use response <- try(
req
|> req.prepend_header("Authorization", token_type_str <> " " <> token)
|> req.prepend_header(
"User-Agent",
"DiscordBot(" <> ua_url <> ", " <> version <> ")",
)
|> hackney.send,
)
response
|> io.debug
response.body
|> decode_application
|> io.debug
response.status
|> should.equal(200)
response
|> response.get_header("content-type")
|> should.equal(Ok("application/json"))
Ok(response)
}