diff options
Diffstat (limited to 'examples')
-rw-r--r-- | examples/discord-interactions/.env.example | 3 | ||||
-rw-r--r-- | examples/discord-interactions/README.md | 17 | ||||
-rw-r--r-- | examples/discord-interactions/bun_shim/index.js | 10 | ||||
-rw-r--r-- | examples/discord-interactions/bun_shim/rest.js | 48 | ||||
-rw-r--r-- | examples/discord-interactions/bun_shim/server.js | 78 | ||||
-rw-r--r-- | examples/discord-interactions/commands/hello.js | 21 | ||||
-rw-r--r-- | examples/discord-interactions/package.json | 8 | ||||
-rw-r--r-- | examples/discord-interactions/polyfill.js | 2 | ||||
-rw-r--r-- | examples/discord-interactions/run.js | 21 |
9 files changed, 208 insertions, 0 deletions
diff --git a/examples/discord-interactions/.env.example b/examples/discord-interactions/.env.example new file mode 100644 index 000000000..a21515794 --- /dev/null +++ b/examples/discord-interactions/.env.example @@ -0,0 +1,3 @@ +DISCORD_APP_ID= +DISCORD_BOT_TOKEN= +DISCORD_PUBLIC_KEY=
\ No newline at end of file diff --git a/examples/discord-interactions/README.md b/examples/discord-interactions/README.md new file mode 100644 index 000000000..2b62661fc --- /dev/null +++ b/examples/discord-interactions/README.md @@ -0,0 +1,17 @@ +# /create with Bun runtime + +A [slash-create](https://npm.im/slash-create) template, using [Bun runtime](https://bun.sh). + +## Getting Started +### Cloning the repo +```sh +bun create discord-interactions interactions-bot +``` + +After that, make sure to install dependencies using bun or any other npm compatible package manager: +```sh +bun install +``` + +### Development +To run this locally, rename `.env.example` to `.env` and fill in the variables, then you can run `bun run.js` to start a local dev environment and use something like ngrok/cloudflare to tunnel it to a URL.
\ No newline at end of file diff --git a/examples/discord-interactions/bun_shim/index.js b/examples/discord-interactions/bun_shim/index.js new file mode 100644 index 000000000..bcdcf5081 --- /dev/null +++ b/examples/discord-interactions/bun_shim/index.js @@ -0,0 +1,10 @@ +import { Creator } from 'slash-create'; +import { FetchRequestHandler } from './rest.js'; +export { default as BunServer } from './server.js'; + +export class BunSlashCreator extends Creator { + constructor(...args) { + super(...args); + this.requestHandler = new FetchRequestHandler(this); + } +}
\ No newline at end of file diff --git a/examples/discord-interactions/bun_shim/rest.js b/examples/discord-interactions/bun_shim/rest.js new file mode 100644 index 000000000..d1c0b76ee --- /dev/null +++ b/examples/discord-interactions/bun_shim/rest.js @@ -0,0 +1,48 @@ +import { RequestHandler } from 'slash-create'; +import { MultipartData } from 'slash-create/lib/util/multipartData.js'; + +export class FetchRequestHandler extends RequestHandler { + toString() { + return '[RequestHandler]'; + } + + async request(method, url, auth = true, body, file) { + const creator = this._creator; + + const headers = { + 'user-agent': this.userAgent, + 'x-ratelimit-precision': 'millisecond', + }; + + if (auth) { + headers.authorization = creator.options.token; + if (!headers.authorization) throw new Error('No token was set in the SlashCreator.'); + } + + if (body) { + if (method !== 'GET' && method !== 'DELETE') { + body = JSON.stringify(body); + headers['content-type'] = 'application/json'; + } + } + + if (file) { + if (Array.isArray(file)) {} + else if (file.file) file = [file]; + else throw new Error('Invalid file object.'); + + const form = new MultipartData(); + headers['content-type'] = `multipart/form-data; boundary=${form.boundary}`; + + for (const f of file) form.attach(f.name, f.file, f.name); + if (body) form.attach('payload_json', JSON.stringify(body)); + + body = Buffer.concat(form.finish()); + } + + const res = await fetch('https://discord.com' + this.baseURL + url, { body, method, headers }); + + if (res.ok) return res.json(); + throw new Error(`${method} got ${res.status} - ${await res.text()}`); + } +}
\ No newline at end of file diff --git a/examples/discord-interactions/bun_shim/server.js b/examples/discord-interactions/bun_shim/server.js new file mode 100644 index 000000000..d2caff328 --- /dev/null +++ b/examples/discord-interactions/bun_shim/server.js @@ -0,0 +1,78 @@ +import { Server } from 'slash-create'; +import { MultipartData } from 'slash-create/lib/util/multipartData.js'; + +export default class BunServer extends Server { + #server = null; + #handler = null; + isWebserver = true; + + constructor() { + super({ alreadyListening: true }); + } + + stop() { + if (this.#server) this.#server.close(); + else throw new Error('BunServer not started'); + } + + createEndpoint(path, handler) { + this.#handler = handler; + } + + listen(port) { + const getHandler = () => this.#handler; + + this.#server = Bun.serve({ + port, + + async fetch(req) { + const handler = getHandler(); + if (!handler) return new Response('Server has no handler.', { status: 503 }); + if (req.method !== 'POST') return new Response('Server only supports POST requests.', { status: 405 }); + + const reqHeaders = Object.fromEntries(req.headers.entries()); + + const reqBody = await req.json(); + + return await new Promise(async (ok, err) => { + try { + await handler({ + request: req, + body: reqBody, + response: null, + headers: reqHeaders, + }, async response => { + let body = response.body; + const headers = new Headers(); + + if (response.headers) { + for (const key in response.headers) { + headers.set(key, response.headers[key]); + } + } + + if ('string' !== typeof body) { + body = JSON.stringify(body); + headers.set('content-type', 'application/json'); + } + + if (response.files) { + const form = new MultipartData(); + headers.set('content-type', `multipart/form-data; boundary=${form.boundary}`); + + form.attach('payload_json', body); + for (const file of response.files) form.attach(file.name, file.file, file.name); + + body = Buffer.concat(form.finish()); + } + + ok(new Response(body, { headers, status: response.status })); + }); + } catch (error) { + err(error); + } + }); + }, + }); + } +};
\ No newline at end of file diff --git a/examples/discord-interactions/commands/hello.js b/examples/discord-interactions/commands/hello.js new file mode 100644 index 000000000..61d92cf82 --- /dev/null +++ b/examples/discord-interactions/commands/hello.js @@ -0,0 +1,21 @@ +const { SlashCommand, CommandOptionType } = require('slash-create'); + +module.exports = class HelloCommand extends SlashCommand { + constructor(creator) { + super(creator, { + name: 'hello', + description: 'Says hello to you.', + options: [{ + type: CommandOptionType.STRING, + name: 'food', + description: 'What food do you like?' + }] + }); + + this.filePath = __filename; + } + + async run(ctx) { + return ctx.options.food ? `You like ${ctx.options.food}? Nice!` : `Hello, ${ctx.user.username}!`; + } +}
\ No newline at end of file diff --git a/examples/discord-interactions/package.json b/examples/discord-interactions/package.json new file mode 100644 index 000000000..cef65c096 --- /dev/null +++ b/examples/discord-interactions/package.json @@ -0,0 +1,8 @@ +{ + "version": "0.0.42", + "name": "@bun-examples/discord-interactions", + + "dependencies": { + "slash-create": "^5.7.0" + } +}
\ No newline at end of file diff --git a/examples/discord-interactions/polyfill.js b/examples/discord-interactions/polyfill.js new file mode 100644 index 000000000..abe756dc9 --- /dev/null +++ b/examples/discord-interactions/polyfill.js @@ -0,0 +1,2 @@ +Error.captureStackTrace = () => {}; +Buffer.isBuffer = Buffer.isBuffer.bind(Buffer);
\ No newline at end of file diff --git a/examples/discord-interactions/run.js b/examples/discord-interactions/run.js new file mode 100644 index 000000000..749a039d6 --- /dev/null +++ b/examples/discord-interactions/run.js @@ -0,0 +1,21 @@ +// polyfill v8 and node (TODO: fix in bun) +import './polyfill.js'; + +import path from 'node:path'; +import { BunServer, BunSlashCreator } from './bun_shim/index.js'; + +const client = new BunSlashCreator({ + token: process.env.DISCORD_BOT_TOKEN, + publicKey: process.env.DISCORD_PUBLIC_KEY, + applicationID: process.env.DISCORD_APP_ID, +}); + +// client.on('debug', console.log); +client.on('error', console.error); + +client.withServer(new BunServer()); +client.registerCommandsIn(path.join(__dirname, 'commands')).syncCommands(); + +await client.server.listen(1337); + +// client.server.stop(); // stop server
\ No newline at end of file |