forked from oven-sh/bun
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a577e35
commit 4a927e0
Showing
9 changed files
with
208 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
DISCORD_APP_ID= | ||
DISCORD_BOT_TOKEN= | ||
DISCORD_PUBLIC_KEY= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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()}`); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
}); | ||
}, | ||
}); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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}!`; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"version": "0.0.42", | ||
"name": "@bun-examples/discord-interactions", | ||
|
||
"dependencies": { | ||
"slash-create": "^5.7.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Error.captureStackTrace = () => {}; | ||
Buffer.isBuffer = Buffer.isBuffer.bind(Buffer); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |