Skip to content

Commit

Permalink
feat: DiscordREST implementation
Browse files Browse the repository at this point in the history
Still needs rate limiting etc
  • Loading branch information
Tim Smart committed Mar 19, 2022
1 parent d58f619 commit fc4ee3d
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 5 deletions.
32 changes: 32 additions & 0 deletions DiscordConfig/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { tag } from "@effect-ts/system/Has"
import * as T from "@effect-ts/core/Effect"

const VERSION = 9

export interface DiscordConfig {
_tag: "DiscordConfig"
token: string
rest: {
baseUrl: string
}
}
export const DiscordConfig = tag<DiscordConfig>()

export interface MakeOpts {
token: string
rest?: {
baseUrl?: string
}
}

export const make = ({ token, rest }: MakeOpts): DiscordConfig => ({
_tag: "DiscordConfig",
token,
rest: {
baseUrl: `https://discord.com/api/v${VERSION}`,
...(rest ?? {}),
},
})

export const token = T.accessService(DiscordConfig)(({ token }) => token)
export const rest = T.accessService(DiscordConfig)(({ rest }) => rest)
14 changes: 11 additions & 3 deletions DiscordREST/http.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import * as T from "@effect-ts/core/Effect"
import * as Axios from "axios"
import { RESTError, Response } from "./types"

export const request =
<A>(axios: Axios.AxiosInstance) =>
(config: Axios.AxiosRequestConfig) =>
T.tryCatchPromise(() => axios.request<A>(config), onReject)
(axios: Axios.AxiosInstance) =>
<A>(config: Axios.AxiosRequestConfig): Response<A> =>
T.tryCatchPromise<RESTError, A>(
() => axios.request<A>(config).then((r) => r.data),
(err) => ({
_tag: "http",
code: (err as Axios.AxiosError).response!.status,
body: (err as Axios.AxiosError).response?.data,
}),
)
81 changes: 81 additions & 0 deletions DiscordREST/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import * as T from "@effect-ts/core/Effect"
import { tag } from "@effect-ts/system/Has"
import Axios, { AxiosInstance, AxiosRequestConfig, Method } from "axios"
import * as Config from "../DiscordConfig"
import { createRoutes, Endpoints } from "../types"
import * as Http from "./http"

export interface DiscordREST extends Endpoints<AxiosRequestConfig> {
_tag: "DiscordREST"
axios: AxiosInstance
}
export const DiscordREST = tag<DiscordREST>()

interface FormData {
append: (key: string, value: unknown) => void
getHeaders: () => Record<string, string>
}

const make = T.gen(function* (_) {
const token = yield* _(Config.token)
const config = yield* _(Config.rest)

const axios = Axios.create({
baseURL: config.baseUrl,
headers: {
Authorization: `Bot ${token}`,
},
})
const request = Http.request(axios)
const routes = createRoutes<AxiosRequestConfig>(
({ method, url, params = {}, options = {} }) => {
const hasBody = method !== "GET" && method !== "DELETE"
let hasFormData = false

if (typeof options.data?.append === "function") {
hasFormData = true
;(options.data as FormData).append(
"payload_json",
JSON.stringify(params),
)
}

const qsParams = hasBody
? options.params
: {
...(options.params || {}),
...params,
}
const data =
hasFormData || !hasBody
? options.data
: {
...(options.data || {}),
...params,
}

const config = {
...options,
headers: {
...(options.headers || {}),
...(hasFormData ? data.getHeaders() : {}),
},
method: method as Method,
url,
params: qsParams,
data,
}
return request(config)
},
)

const rest: DiscordREST = {
_tag: "DiscordREST",
axios,
...routes,
}

return rest
})

export const LiveDiscordREST = T.toLayer(DiscordREST)(make)
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"preserveSymlinks": true,
"moduleResolution": "node",
"module": "CommonJS",
"lib": ["es2020"],
"lib": ["ESNext"],
"sourceMap": true,
"declaration": true,
"strict": true,
Expand Down
2 changes: 1 addition & 1 deletion types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ export interface BulkDeleteMessageParams {
/** an array of message ids to delete (2-100) */
messages: Snowflake[]
}
export interface BulkOverwriteGuildApplicationCommandBulkApplicationCommandParams {
export interface BulkOverwriteGuildApplicationCommandParams {
/** application command id, if known */
id: Snowflake
/** 1-32 character name */
Expand Down

0 comments on commit fc4ee3d

Please sign in to comment.