the ultimate framework

This commit is contained in:
MARCROCK22 2024-03-09 15:49:41 -04:00
parent 37e4125a20
commit d0915ba882
264 changed files with 20156 additions and 6607 deletions

View File

@ -5,9 +5,9 @@ charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 2
indent_style = tab
indent_size = 4
quote_type = single
[Makefile]
indent_style = space
indent_style = tab

62
.gitignore vendored
View File

@ -1,63 +1,5 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
package-lock.json
# Eater asked for this dunno why
bot/
apps/
# Enviorment
.env
# bun
bun-test.js
# NPM
npm/
# DOCS
docs.json
packages/core/docs.json
# dependencies
pnpm-lock.yaml
node_modules
.pnp
.pnp.js
.vscode
# testing
coverage
# node
out/
lib/
dist/
build
package-lock.json
# misc
.DS_Store
*.pem
*.vs
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local
.env
# turbo
.turbo
# tests
__tests__
__test__
# changeset
.changeset

4
.husky/pre-commit Normal file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged

30
.swcrc Normal file
View File

@ -0,0 +1,30 @@
{
"sourceMaps": false,
"module": {
"type": "commonjs",
"strictMode": true,
"noInterop": false
},
"jsc": {
"externalHelpers": false,
"target": "esnext",
"parser": {
"syntax": "typescript",
"tsx": true,
"decorators": true,
"dynamicImport": true
},
"transform": {
"legacyDecorator": true,
"decoratorMetadata": true,
"react": {
"throwIfNamespace": false,
"useBuiltins": false,
"pragma": "React.createElement",
"pragmaFrag": "React.Fragment",
"importSource": "react"
}
},
"keepClassNames": true
}
}

8
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,8 @@
{
"recommendations": [
"biomejs.biome",
"orta.vscode-twoslash-queries",
"eamodio.gitlens",
"yoavbls.pretty-ts-errors"
]
}

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"typescript.tsdk": "node_modules\\typescript\\lib"
}

View File

@ -1,68 +1,57 @@
# biscuit
<div align='center'>
## A brand new bleeding edge non bloated Discord library
# **Seyfert**
<img align="right" src="https://raw.githubusercontent.com/oasisjs/biscuit/main/assets/icon.svg" alt="biscuit"/>
<img src="./assets/icon.png" alt="seyfert" width="200px" />
## Install (for [node18](https://nodejs.org/en/download/))
**A brand new bleeding edge non bloated Discord framework**
```sh-session
npm install @biscuitland/core
yarn add @biscuitland/core
[![License](https://img.shields.io/npm/l/seyfert?style=flat-square&logo=apache&color=white)](https://github.com/tiramisulabs/biscuit/blob/main/LICENSE)
[![Version](https://img.shields.io/npm/v/seyfert?color=%23ff0000&logo=npm&style=flat-square)](https://www.npmjs.com/package/seyfert)
[![Discord](https://img.shields.io/discord/1003825077969764412?color=%23406da2&label=support&logo=discord&style=flat-square)](https://discord.com/invite/XNw2RZFzaP)
</div>
> [!WARNING]
> This readme is work in progress!
# FAQ
## So, what is `seyfert`?
Seyfert is the ultimate Discord framework! With its highly efficient interaction with the Discord API, you can achieve anything you set your mind to.
## Why I should use it?
Seyfert has a good scalability, strict types, smooth developing experience...
> more questions soon...
# User guide
## Installation
> [!NOTE]
> You **NEED** Node.js 18>= for this to work, also we recomended Node.js 20 LTS and Bun latest
```sh
pnpm add seyfert
```
for further reading join our [Discord](https://discord.com/invite/XNw2RZFzaP)
> You may use your preferred package manager, for this example I am using PNPM since is more efficient.
## Most importantly, biscuit:
Stands apart from other libraries like Discord.js or Eris as it takes a conscious and dedicated approach, adhering strictly to [simplicity](https://en.wikipedia.org/wiki/Unix_philosophy). We have examined the features and functionalities that contribute to [bloat](https://en.wikipedia.org/wiki/Code_bloat) in libraries, intentionally removing unnecessary complexities we deliver a [minimalistic](https://en.wikipedia.org/wiki/Minimalism_(computing)) and efficient solution that includes only essential components for Discord API interaction, reducing the library's footprint and enabling scalability.
High RAM usage in other libraries often arises due to unnecessary features and functionalities and suboptimal caching mechanisms tied to the core library.
### Leveraging the power of meta programming
The Proxy object enables dynamic, flexible and efficient calls to the API, it is typesafe due to TypeScript wizardry, meta programming is not for the weak minded.
## Why biscuit?:
- Remarkably minimal memory footprint
- Scalable
- Non feature-rich!
## Example bot (TS/JS)
## Basic bot example
```ts
import { Session } from '@biscuitland/core';
import { GatewayIntentBits, InteractionType, InteractionResponseType } from '@biscuitland/common';
import { Client } from 'seyfert';
const session = new Session({
intents: GatewayIntentBits.Guilds,
token: 'your token goes here'
});
const client = new Client();
const commands = [
{
name: 'ping',
description: 'Replies with pong!'
}
];
session.once('READY', (payload) => {
const username = payload.user.username;
console.log('Logged in as: %s', username);
session.managers.applications.bulkCommands(session.applicationId, commands);
});
session.on('INTERACTION_CREATE', (interaction) => {
if (interaction.type !== InteractionType.ApplicationCommand) return;
session.managers.interactions.reply(interaction.id, interaction.token, {
type: InteractionResponseType.ChannelMessageWithSource,
data: { content: 'pong!' }
});
});
session.start();
(async () => {
await client.start();
await client.uploadCommands().catch(e => {
console.error(JSON.stringify(e, null, 2))
process.exit(1)
})
})();
```
## Links
* [Website](https://biscuitjs.com/)
* [Documentation](https://docs.biscuitjs.com/)
* [Discord](https://discord.gg/XNw2RZFzaP)
* [core](https://www.npmjs.com/package/@biscuitland/core) | [rest](https://www.npmjs.com/package/@biscuitland/rest) | [ws](https://www.npmjs.com/package/@biscuitland/ws) | [helpers](https://www.npmjs.com/package/@biscuitland/helpers)
# Useful links
- [GitHub Repository](https://github.com/tiramisulabs/biscuit)
- [Discord server](https://discord.com/invite/XNw2RZFzaP)
- [npm - core](https://www.npmjs.com/package/seyfert)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 301 KiB

View File

@ -1,75 +1,345 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="52.382698mm"
height="39.664326mm"
viewBox="0 0 52.382698 39.664326"
version="1.1"
id="svg72859"
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
sodipodi:docname="fabicon opt web.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview72861"
pagecolor="#ffffff"
bordercolor="#999999"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:document-units="mm"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="1.300746"
inkscape:cx="124.92831"
inkscape:cy="106.47736"
inkscape:window-width="1366"
inkscape:window-height="705"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs72856" />
<g
inkscape:label="Capa 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-60.052883,-81.833223)">
<g
id="g73848">
<path
style="fill:#898f8c;fill-opacity:1;stroke:none;stroke-width:0.105"
d="m 77.78561,100.07756 c -0.74854,4.03168 1.36028,8.44105 3.63048,11.65499 0.76576,1.08413 1.84117,2.84277 3.29951,3.00626 1.21202,0.13597 2.90472,-1.40217 3.78,-2.10966 0.36992,-0.29894 0.94248,-1.05997 1.4699,-0.74277 1.43304,0.86194 2.32774,2.80129 3.5701,3.92332 1.66257,1.5017 3.68371,2.52273 5.66999,3.50888 1.98073,0.98333 4.16976,2.00235 6.405,2.17897 0.70487,-3.40589 3.62743,-6.96381 6.82499,-8.295 -0.4306,-0.9156 -1.47378,-1.2769 -2.41499,-1.4239 -2.01464,-0.31469 -4.11285,0.29998 -6.09,-0.33443 -2.51485,-0.80692 -4.43918,-3.00121 -6.40541,-4.66189 -0.7287,-0.61551 -1.51735,-1.42274 -2.41458,-1.76977 0.65614,-2.27871 1.40143,-4.42774 1.56555,-6.825003 0.26701,-3.89896 -1.44606,-7.99889 -4.50555,-10.44602 -1.9152,-1.53188 -3.91534,-2.34289 -6.08999,-3.37596 -1.8647,-0.88584 -3.39591,-2.5916 -5.67,-2.53077 -1.90155,0.0509 -2.78806,1.64193 -4.30499,2.42091 -1.05063,0.53948 -2.27945,0.76416 -3.36001,1.25927 -3.0367,1.39139 -6.05884,3.24012 -8.39844,5.63758 -3.22838,3.30823 -4.88029,7.579 -4.10489,12.179993 0.30441,1.80631 1.18473,4.37293 3.36834,4.49295 1.66435,0.0916 3.38325,-1.33078 4.725,-2.13581 1.03421,-0.62055 2.28039,-0.99603 3.255,-1.68902 1.11478,-0.79265 1.97988,-1.94239 3.14999,-2.66374 0.92884,-0.57257 2.08898,-0.68975 3.045,-1.25938"
id="path369864-82-2-3-8" />
<path
style="fill:#dfe5e9;fill-opacity:1;stroke:none;stroke-width:0.105"
d="m 111.17555,112.88755 v 0.21 c -2.51905,1.54203 -5.4896,4.28201 -6.29999,7.245 -1.45141,-0.0624 -2.77315,-0.60574 -4.09499,-1.15374 -2.42645,-1.00612 -4.93101,-2.22852 -6.82457,-4.09784 -1.68956,-1.66781 -2.82136,-3.81895 -4.83043,-5.16977 -1.14964,-0.77301 -2.40533,-0.90867 -3.675,-1.33864 0.45918,-1.38432 2.01643,-2.19367 3.25501,-2.76245 0.84157,-0.3864 1.92244,-1.31344 2.835,-1.40458 1.56039,-0.15582 3.40031,1.09914 4.51499,2.03815 2.09286,1.76305 4.28158,4.30574 6.82499,5.39721 1.95751,0.8401 3.96973,0.16978 5.985,0.31111 0.85323,0.0597 1.54214,0.39637 2.30999,0.72555"
id="path369892-7-5-7-7" />
<path
style="fill:#dfe5e9;fill-opacity:1;stroke:none;stroke-width:0.105"
d="m 94.22389,103.73414 -1.48416,-0.23959 c 0.30365,-1.30028 1.14312,-2.45552 1.50182,-3.756513 0.90558,-3.28374 0.20088,-7.06295 -2.20123,-9.56013 -0.84365,-0.87716 -1.81642,-1.68063 -2.8345,-2.34807 -1.22443,-0.80262 -2.06794,-0.98378 -2.85121,-2.30286 1.36529,0.13372 2.74412,0.99706 3.87308,1.72549 0.98991,0.6387 1.97247,1.3684 2.76379,2.24602 3.8927,4.31727 2.99331,9.23033 1.23241,14.235653"
id="path369888-0-6-7-5" />
<path
style="fill:#dfe5e9;fill-opacity:1;stroke:none;stroke-width:0.105"
d="m 80.75018,82.790847 c -2.11775,0.18734 -3.9062,1.55745 -5.15095,3.20737 -0.40659,0.5113 -0.78493,1.04448 -1.13922,1.59322 0.65257,-1.00756 1.26966,-2.0373 1.89173,-3.06394 -4.01184,1.66344 -8.1914,3.44725 -11.13277,6.76942 -1.39959,1.63616 -2.60521,3.56159 -2.99814,5.70588 -0.34405,2.13885 1.00799,3.987553 1.90515,5.799463 0.46885,0.89423 1.25596,2.17452 0.68408,3.93482 2.20474,-0.89478 4.3388,-2.77361 6.59683,-3.52479 1.04818,-0.8651 2.01495,-1.864 3.11758,-2.64166 1.10122,-0.45261 2.20409,-0.901233 3.30424,-1.356433 0.20037,-1.27862 0.37559,-2.56351 0.90032,-3.75875 0.4672,-1.33123 0.93463,-2.66237 1.40079,-3.99396 -0.58425,0.4536 -1.20063,0.86705 -1.7637,1.34712 0.91888,-1.69492 1.50387,-3.54856 1.85387,-5.43898 0.1353,-0.33711 0.23307,-0.98421 0.68889,-0.9576 0.77324,0.67141 0.80137,1.83022 0.90376,2.78295 0.0789,1.16285 -0.15754,2.35952 -0.90376,3.28181 -1.69376,2.671 -2.90145,5.78765 -2.66715,8.998863 0.15268,3.11908 1.42078,6.09773 3.30568,8.56103 0.38376,0.53726 0.7038,1.35766 1.05848,1.91457 0.62542,0.14036 0.93737,-0.1044 0.92316,-0.75105 0.29772,-1.84544 1.2544,-3.97094 2.96731,-4.87644 1.67168,-0.93946 3.86842,-1.21585 4.96711,-2.96308 2.79949,-3.740853 2.80945,-9.439513 -0.34583,-12.977013 -1.02738,-1.12859 -2.18025,-2.23377 -3.68496,-2.66939 -0.46715,0.0679 -0.41173,-0.35487 -0.76668,-0.86609 -1.08342,-1.91083 -2.74785,-3.87495 -5.09009,-4.05881 -0.27552,-0.0284 -0.54994,-0.0142 -0.82573,0.002 z"
id="path369886-3-4-4-8"
sodipodi:nodetypes="cccccccccccccccccccccccccccccc" />
<path
id="path369890-4-0-3-4"
style="fill:#c4c6c8;fill-opacity:1;stroke:none;stroke-width:0.105"
d="m 61.06212,100.63424 c -0.57591,1.50298 -0.22809,3.21694 0.37144,4.65774 0.39627,0.76014 1.22937,1.75582 2.18374,1.35269 0.86909,-0.5462 0.39563,-1.72342 0.0955,-2.47142 -0.62453,-1.55489 -1.44739,-3.01794 -2.26254,-4.478823 -0.12939,0.313263 -0.25877,0.626543 -0.38816,0.939813 z" />
<path
id="path369896-9-4-8-7"
style="fill:#c4c6c8;fill-opacity:1;stroke:none;stroke-width:0.105"
d="m 84.26313,110.37997 c -0.23248,1.19921 -0.23853,2.47677 0.27591,3.60857 1.58701,-0.38357 3.44289,-0.94231 4.12827,-2.59514 0.24236,-0.49078 -0.86862,-0.50777 -1.20861,-0.79342 -0.98076,-0.44184 -2.04839,-0.66629 -3.12524,-0.64741 -0.0235,0.14247 -0.0469,0.28494 -0.0704,0.4274 z" />
</g>
</g>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 4000 4000" style="enable-background:new 0 0 4000 4000;" xml:space="preserve">
<style type="text/css">
.st0{fill:url(#SVGID_1_);}
.st1{fill:none;stroke:#1D1D19;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;}
.st2{fill:url(#SVGID_00000111161471117857181650000008874287497415348138_);}
.st3{fill:#00AAE6;}
.st4{fill:url(#SVGID_00000154415358219097987360000000950432104712010413_);}
.st5{fill:url(#SVGID_00000080187546048067913100000007428919299044684716_);}
.st6{fill:url(#SVGID_00000080915494984279035640000011859275636825242557_);}
.st7{fill:#001630;}
.st8{fill:#000C28;}
.st9{fill:url(#SVGID_00000012474585635025126550000006984666226631448704_);}
.st10{fill:url(#SVGID_00000135652297518986943980000011147478890175969213_);}
.st11{fill:url(#SVGID_00000101071206471393636430000006601806650292057749_);}
.st12{fill:url(#SVGID_00000071521284048130989020000012508463264477232052_);}
.st13{fill:url(#SVGID_00000090297060644371771830000010583929609890356107_);}
.st14{fill:#00081C;}
.st15{fill:url(#SVGID_00000150795815764103649730000009982554383684358784_);}
.st16{fill:#001335;}
.st17{fill:#002441;}
.st18{fill:#00B4CE;}
.st19{fill:url(#SVGID_00000048461043874345920890000002145403735974172056_);}
.st20{fill:#001A48;}
.st21{fill:#001636;}
.st22{fill:#00123E;}
.st23{fill:#001C4B;}
.st24{fill:#001226;}
</style>
<g id="XMLID_00000052095757296515447230000000036625776780304020_">
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="1128.1837" y1="3302.6326" x2="1712.0858" y2="3302.6326">
<stop offset="0" style="stop-color:#0058B0"/>
<stop offset="1" style="stop-color:#00A1CC"/>
</linearGradient>
<path class="st0" d="M1712.09,3183.04c-33.41,10.17-67.38,18.35-100.69,28.86c-56.22,17.72-110.44,42.1-160.28,73.66
c-24.88,15.75-48.7,33.18-71.2,52.19c-23.3,19.68-44.11,41.67-65.74,63.14c-7.2,7.16-14.49,14.22-21.71,21.33
c-55.02-24.66-111.27-53.13-164.29-85.55c8.1-11.3,26.8-18.93,38.6-25.92c15.96-9.44,32.25-18.3,48.83-26.59
c73.41-36.68,150.16-54.45,230.04-71.23c44.39-9.32,87.76-13.6,132.85-18.32C1622.94,3189.97,1667.5,3186.1,1712.09,3183.04z"/>
</g>
<g>
</g>
</g>
<path class="st1" d="M1333.24,3184.07c-0.7,0-1.71,0.65-2.75,1.34c3.34-0.85,6.68-1.69,10.02-2.51c2.73-0.68,5.48-1.35,8.24-2
c0.49-0.12,0.98-0.24,1.48-0.36c0.1-0.02,0.21-0.04,0.31-0.07c0.91-0.22,1.83-0.45,2.73-0.68
C1346.63,3181.19,1339.95,3182.61,1333.24,3184.07z M1537.11,3146.51c31.27-4.66,62.63-8.85,93.79-14.04
c0.71-0.12,1.44-0.24,2.15-0.36C1600.47,3136.83,1568.65,3141.55,1537.11,3146.51z M1858.04,2932.61
c10.83-7.7,21.52-15.65,32.12-23.68c11.52-8.73,22.92-17.61,34.34-26.47c0.83-0.64,1.96-1.63,3.32-2.87L1858.04,2932.61z
M1796.05,2972.48l-100.56,49C1729.85,3007.22,1763.87,2990.9,1796.05,2972.48z M1630.9,3132.47c0.71-0.12,1.44-0.24,2.15-0.36
c-32.58,4.72-64.4,9.44-95.94,14.4C1568.38,3141.85,1599.75,3137.66,1630.9,3132.47z M1330.5,3185.4c3.34-0.85,6.68-1.69,10.02-2.51
c2.75-0.68,5.49-1.35,8.24-2c0.49-0.12,0.98-0.24,1.48-0.36c0.1-0.02,0.21-0.04,0.31-0.07c0.91-0.22,1.83-0.45,2.73-0.68
c-6.65,1.41-13.33,2.84-20.04,4.29C1332.54,3184.07,1331.53,3184.72,1330.5,3185.4z M1537.11,3146.51
c-15.41,2.42-30.74,4.9-46.07,7.45c26.63-4.16,53.31-8.05,79.94-12.07c14.17-2.14,28.33-4.32,42.48-6.58
c5.82-0.94,11.64-1.89,17.44-2.85c0.71-0.12,1.44-0.24,2.15-0.36C1600.47,3136.83,1568.65,3141.55,1537.11,3146.51z
M1353.28,3179.78c-6.65,1.41-13.33,2.84-20.04,4.29c-0.7,0-1.71,0.65-2.75,1.34c3.34-0.85,6.68-1.69,10.02-2.51
c2.73-0.68,5.48-1.35,8.24-2c0.49-0.12,0.98-0.24,1.48-0.36c0.1-0.02,0.21-0.04,0.31-0.07c1.42-0.34,2.86-0.67,4.3-1.01
C1354.33,3179.55,1353.8,3179.67,1353.28,3179.78z M1121.99,3243.19c-0.04,0.03-0.07,0.04-0.12,0.06c-0.21,0.1-0.4,0.22-0.61,0.33
c-0.43,0.24-0.86,0.48-1.29,0.7c-3.25,1.71-8.52,4.54-16.45,8.91c-0.58,0.33-1.17,0.64-1.75,0.95
C1105.19,3253.12,1131.89,3238.04,1121.99,3243.19z M2569.38,951.05c-5.58-0.46-11.13-1.08-16.67-1.8
c-6.87-0.88-13.73-1.89-20.6-2.84c3.19,0.86,6.52,2,9.28,2c26.72,2.97,51.95,4.45,77.18,7.42c34,3.01,67.67,4.99,101.21,6
C2669.44,960.12,2619.57,955.13,2569.38,951.05z M2460.28,937.51c4.05,0.58,8.12,1.13,12.19,1.68
C2470.69,938.93,2461.39,936.51,2460.28,937.51z"/>
<linearGradient id="SVGID_00000157290804937867201410000002913548497684341399_" gradientUnits="userSpaceOnUse" x1="2065.2195" y1="2160.8179" x2="2065.2195" y2="3165.0955">
<stop offset="0" style="stop-color:#002A58"/>
<stop offset="0.9948" style="stop-color:#0067B0"/>
</linearGradient>
<path style="fill:url(#SVGID_00000157290804937867201410000002913548497684341399_);" d="M2626.74,2642.4
c-5.49,35.48-15.01,70.32-28.41,103.65c-5.14,12.78-9.5,25.89-15.01,38.54c-5.52,12.66-12.01,24.98-18.66,37.1
c-9.17,16.71-19.15,33.01-29.86,48.78c-21.37,31.43-45.76,60.76-72.67,87.57c-27.24,27.12-57.05,51.63-88.8,73.29
c-12.94,8.83-26.21,17.19-39.75,25.07l-4.45,4.45c-34.14,19.3-68.27,35.63-103.89,51.96c-26.72,10.39-54.92,19.3-83.12,28.21
c-96.47,26.72-191.46,29.69-289.42,16.33c-67.28-8.21-132.3-20.5-197.04-33.37c-52.38-10.39-104.59-21.17-157.68-30.46
c13.89-4.97,27.8-9.95,41.69-14.92c37.27-13.35,74.54-26.66,111.79-40.01l0.85-0.31l32.82-11.74l10.36-5.05
c34.36-14.27,68.38-30.58,100.56-49l26.48-12.9l35.52-26.97c10.83-7.7,21.52-15.65,32.12-23.68c11.52-8.73,22.92-17.61,34.34-26.47
c0.83-0.64,1.96-1.63,3.32-2.87l28.39-21.57c39.69,2.97,79.57,2.42,118.62-2.94c14.81-2.03,29.49-4.77,44.01-8.27
c59.67-10.21,114.73-24.51,165.65-58.88c33.32-22.49,62.66-50.84,86.35-83.32c26.15-35.87,35.95-73.13,35.8-117.38
c-0.18-55.8-13.52-108.44-49.9-151.61c-33.6-39.86-76.82-71.63-125.03-91.49c-0.04-0.22-0.1-0.45-0.16-0.67
c-4.66-17.95-11.4-35.38-19.61-52c-24.79-50.15-62.11-93.29-103.45-130.59c113.04-1.69,235.44,32.09,328.72,96.88
c65.99,45.83,119.95,106.2,174.02,165c0.92,3.06,1.8,6.12,2.64,9.19c9.39,34.11,15.35,69.19,17.57,104.52
C2633.69,2571.82,2632.16,2607.4,2626.74,2642.4z"/>
<path class="st3" d="M1956.02,2858.01c-5.45,0-20.44,14.59-28.19,21.58c-1.37,1.23-2.49,2.23-3.32,2.87
c-11.43,8.86-22.83,17.74-34.34,26.47c-10.6,8.03-21.28,15.97-32.12,23.68c-12.62,9-25.45,17.7-38.6,25.9
c-7.67,4.78-15.48,9.44-23.39,13.97c-32.18,18.42-66.2,34.74-100.56,49c-12.32,5.11-24.7,9.96-37.03,14.55
c-2.05,0.76-4.1,1.5-6.14,2.24l-0.85,0.31l-111.79,40.01c-13.89,4.97-27.8,9.95-41.69,14.92c-0.49-0.01-0.98-0.03-1.47-0.06
c-46.8-1.77-93.8-9.55-140.69-13.41c-50.17-4.14-100.51-6.46-150.84-5.64c-52.79,0.86-105.6,5.2-157.64,14.39
c-49.54,8.74-97.93,23.2-145.93,37.47c-47.55-80.65-62.32-173.79-21.74-280.2c48.92-128.32,186.34-196.95,313.02-224.44
c47.79-10.38,68.29,22.5,109.91,46.39c91.72,52.65,196.57,76.08,297.32,104.91c93.37,26.71,185.54,58.77,281.18,75.59
C1905.8,2852.86,1930.87,2856.16,1956.02,2858.01z"/>
<linearGradient id="SVGID_00000151537649501067446000000011787695674670850743_" gradientUnits="userSpaceOnUse" x1="1897.1814" y1="2064.208" x2="1897.1814" y2="3336.6721">
<stop offset="0" style="stop-color:#00606A"/>
<stop offset="0.4665" style="stop-color:#000B33"/>
<stop offset="1" style="stop-color:#000D2C"/>
</linearGradient>
<path style="fill:url(#SVGID_00000151537649501067446000000011787695674670850743_);" d="M2892.94,2626.65v0.01
c-4.97,26.23-11.87,52.22-20.57,77.91c-28.2,80.16-66.79,151.42-123.19,218.22c-72.73,86.1-158.81,146.96-259.74,190.02
c-2.97,1.48-4.45,0-7.42,1.48c-31.17,14.84-65.3,23.75-97.96,35.63c-13.36,4.45-26.72,5.94-40.07,8.91
c-35.62,10.39-71.24,13.36-106.86,16.33c-48.98,4.45-97.96,4.45-146.94,1.48c-75.69-2.97-149.9-1.48-225.6-1.48
c-50.46,1.48-102.41,4.45-152.5,7.88c-44.59,3.06-89.14,6.93-133.58,11.58c-45.09,4.72-88.46,9-132.85,18.32
c-79.88,16.77-156.63,34.54-230.04,71.23c-16.58,8.28-32.88,17.15-48.83,26.59c-11.8,6.99-30.5,14.62-38.6,25.92
c-93.86-57.39-177.62-127.18-226.64-210.2c-0.04-0.07-0.07-0.13-0.12-0.21c48-14.27,96.38-28.73,145.93-37.47
c52.04-9.19,104.84-13.52,157.64-14.39c50.33-0.82,100.67,1.5,150.84,5.64c46.89,3.86,93.89,11.64,140.69,13.41
c0.49,0.03,0.98,0.04,1.47,0.06c-71.24,20.78-142.48,40.08-210.76,68.29c-31.17,13.36-60.85,26.72-90.54,41.57
c-25.59,12.8-50.26,26.5-74.7,39.83c-0.04,0.03-0.07,0.04-0.12,0.06c-0.21,0.1-0.4,0.22-0.61,0.33c-0.43,0.24-0.86,0.48-1.29,0.7
c-3.25,1.71-8.52,4.54-16.45,8.91c-0.58,0.33-1.17,0.64-1.75,0.95c54.35-14.09,106.45-33.39,160.65-49.75
c4.84-1.44,9.68-2.86,14.53-4.29c23.11-6.78,46.47-12.6,69.77-18.66c1.17-0.3,2.33-0.59,3.5-0.91c0.1-0.02,0.21-0.04,0.31-0.07
c0.91-0.22,1.83-0.45,2.73-0.68c16.33-4.02,32.82-7.45,49.39-10.55c0.45-0.09,0.89-0.18,1.34-0.25c28.14-5.24,56.49-9.6,84.54-14.61
c0.09-0.01,0.16-0.03,0.25-0.04c16.04-2.86,32.18-5.39,48.31-7.81c31.27-4.66,62.63-8.85,93.79-14.04c0.71-0.12,1.44-0.24,2.15-0.36
c8.34-1.4,15.38-5.39,22.62-8.14c64.74,12.87,129.76,25.16,197.04,33.37c97.96,13.36,192.95,10.39,289.42-16.33
c28.2-8.91,56.4-17.81,83.12-28.21c35.62-16.33,69.76-32.66,103.89-51.96l4.45-4.45c13.54-7.88,26.8-16.24,39.75-25.07
c31.75-21.66,61.56-46.17,88.8-73.29c26.91-26.81,51.29-56.14,72.67-87.57c10.72-15.77,20.69-32.07,29.86-48.78
c6.65-12.11,13.14-24.44,18.66-37.1c5.51-12.65,9.87-25.76,15.01-38.54c13.4-33.33,22.92-68.17,28.41-103.65
c5.42-35,6.95-70.59,4.72-105.93c-2.23-35.33-8.18-70.41-17.57-104.52c-0.85-3.07-1.72-6.13-2.64-9.19
c-9.38-31.69-21.91-62.13-36.68-91.73c-1.07-2.14-2.15-4.28-3.25-6.4c-0.49-0.95-0.99-1.9-1.5-2.85c-0.83-1.6-1.68-3.19-2.54-4.78
c-0.12-0.25-0.25-0.49-0.39-0.71c-0.92-1.71-1.84-3.41-2.79-5.11c-0.62-1.13-1.26-2.26-1.9-3.37c-0.67-1.22-1.37-2.42-2.06-3.61
c-0.49-0.89-1.01-1.77-1.53-2.63c-0.65-1.16-1.34-2.3-2.02-3.43c-0.61-1.04-1.23-2.08-1.86-3.1c-0.74-1.23-1.5-2.46-2.26-3.68
c-0.59-0.99-1.2-1.97-1.83-2.94c-3.59-5.76-7.32-11.43-11.15-17.01c-0.74-1.1-1.5-2.18-2.26-3.28c-0.31-0.46-0.64-0.91-0.96-1.37
c-0.77-1.11-1.56-2.23-2.36-3.34c-2.2-3.09-4.44-6.16-6.71-9.19c-0.8-1.05-1.59-2.11-2.39-3.15c-0.85-1.13-1.72-2.27-2.6-3.38
c-1.4-1.81-2.82-3.62-4.24-5.4c-0.04-0.06-0.09-0.12-0.13-0.16c-1.42-1.78-2.85-3.56-4.3-5.33c0,0-0.01,0-0.01-0.01
c-78.99-96.25-192.19-160.04-319.46-172.04c-1.93-0.18-3.87-0.37-5.8-0.55c39.94,0.55,80.01,5,121.57,7.97
c4.45,0,10.39,2.97,14.84,2.97c114.28,10.39,222.63,40.08,325.04,90.55c2.97,1.48,5.94,5.94,10.39,7.42
c68.27,35.63,121.71,84.62,163.26,151.42c14.84,25.24,26.72,48.99,37.11,75.71c7.42,22.27,13.36,43.05,17.81,65.32
c8.91,53.44,10.39,105.4,14.49,159L2892.94,2626.65z"/>
<linearGradient id="SVGID_00000048474317101889883790000018157094566315166863_" gradientUnits="userSpaceOnUse" x1="1607.6506" y1="998.0541" x2="1607.6506" y2="2052.2134">
<stop offset="0" style="stop-color:#004F58"/>
<stop offset="1" style="stop-color:#00091E"/>
</linearGradient>
<path style="fill:url(#SVGID_00000048474317101889883790000018157094566315166863_);" d="M2062.67,2017.46l-3.1,34.75
c-40.3-3.83-80.4-7.84-120.43-12.31c-116.2-12.96-231.91-29.88-350.61-58.28c-84.38-18.87-163.44-47.7-232.75-93.58
c-34.33-22.73-66.25-49.63-95.26-81.59c-1.48-1.48-1.48-4.45-2.97-5.94c-17.81-19.3-32.65-40.08-44.53-62.35l-4.45-4.45
c-53.22-99.28-61.83-209.71-52.85-319.14l2.92-12.31c11.95-42.75,25.78-85.11,44.23-125.54c18.37-40.3,41.5-78.34,69.4-112.78
c27.41-33.85,59.58-64.01,96.81-86.83c40.1-24.57,84.73-43.99,129.42-58.52c22.31-7.26,45.15-13.03,68.38-16.51
c22.14-3.33,45.8-5.48,68.16-2.91l6.47,1.04c-16.95,12.94-33.1,26.97-48.71,41.54c-30.38,28.34-58.91,58.86-82.77,92.87
c-34.06,48.5-58.08,103.26-79.98,158.32c-15.39,38.69-15.01,72.65-15.01,113.43c-7.36,62.7-0.22,127.18,17.65,189.27
c34.14,114.31,103.89,207.83,200.37,282.05c7.42,5.94,14.84,10.39,22.26,14.84c68.27,47.5,135.06,77.19,213.73,95.01
c1.48,0,4.45,2.97,5.94,2.97c62.34,14.84,123.19,22.27,185.53,26.72C2061.23,2017.33,2061.94,2017.39,2062.67,2017.46z"/>
<linearGradient id="SVGID_00000017515604425283082870000013321954441328810411_" gradientUnits="userSpaceOnUse" x1="1943.6947" y1="899.934" x2="1943.6947" y2="2065.7371">
<stop offset="0" style="stop-color:#00B0A1"/>
<stop offset="0.1598" style="stop-color:#008891"/>
<stop offset="0.5026" style="stop-color:#00B8AB"/>
<stop offset="0.7938" style="stop-color:#006A83"/>
<stop offset="1" style="stop-color:#00798D"/>
</linearGradient>
<path style="fill:url(#SVGID_00000017515604425283082870000013321954441328810411_);" d="M2475.22,2065.74
c-134.26-30.08-273.73-35-412.55-48.28c-0.73-0.07-1.44-0.13-2.17-0.21c-62.34-4.45-123.19-11.88-185.53-26.72
c-1.48,0-4.45-2.97-5.94-2.97c-78.66-17.81-145.45-47.5-213.73-95.01c-7.42-4.45-14.84-8.91-22.26-14.84
c-96.47-74.22-166.23-167.75-200.37-282.05c-17.87-62.1-25.01-126.57-17.65-189.27c4.26-36.24,13.36-71.89,28.04-106.14
c1.48-2.97,0-4.45,1.48-7.42c38.71-93.32,98.66-172.02,173.18-237.91l2.57-1.17c47.6-20.71,91.46-49.17,140.32-68.32
c51.62-20.22,105.01-35.82,159.14-47.77c102.57-22.64,207.6-32.27,312.5-37.39l9.5-0.33c0.68,0.1,1.37,0.21,2.05,0.33
c4.2,0.7,8.4,1.41,12.62,2.14c69.64,12.35,135.88,25.56,203.86,35.11c-45.95,41.33-93.88,80.47-143.54,117.26
c-48.98,36.28-102.57,66.65-154.74,98.12c-19.77,11.92-39.48,23.93-58.97,36.31c-36.39-5.89-72.34-9.56-109-7.47
c-0.71,0.04-1.44,0.09-2.15,0.12c-25.84,1.56-51.61,2.45-77.33,6.15c-14.35,2.06-28.63,4.68-42.77,7.85
c-7.39,1.65-14.74,3.44-22.04,5.4c-3.25,0.86-6.69,2.12-10.17,3.24c-0.73,0.15-1.45,0.3-2.18,0.45c-0.88,0.18-1.74,0.37-2.6,0.56
c-0.85,0.18-1.71,0.37-2.55,0.58c-0.91,0.21-1.8,0.43-2.67,0.64c-0.19,0.06-0.39,0.1-0.58,0.16c-0.01,0-0.01,0-0.03,0
c-0.01,0-0.01,0-0.03,0c-0.61,0.16-1.23,0.31-1.84,0.49c-0.68,0.18-1.37,0.36-2.05,0.56c-1.87,0.5-3.73,1.05-5.58,1.63
c-129.62,40.44-198.28,193.18-161.65,319.24c28.17,96.91,100.17,183.11,172.47,251.13c167.33,157.42,391.27,223.77,610.19,275.88
L2475.22,2065.74z"/>
<path class="st7" d="M3011.76,821.82c-43.92,28.34-87.05,55.91-134.44,78.32c-47.36,22.4-96.22,41.45-144.78,61.04l-2.69,0.95
c-3.35-0.09-6.72-0.19-10.08-0.3c-50.33-1.72-100.2-6.71-150.39-10.79c-5.58-0.46-11.13-1.08-16.67-1.8l4.63-1.54
c24.39-8.92,48.56-18.35,72.43-28.56c42.34-18.11,83.71-38.69,122.88-62.96c27.55-17.07,54.77-35.67,79.48-56.97
c16.18-13.92,31.27-29.01,44.69-45.56c4.53-5.58,9.07-11.18,13.6-16.76c0.92,0.61,1.83,1.22,2.75,1.84
C2932.92,765.54,2972.21,793.45,3011.76,821.82z"/>
<path class="st8" d="M3132.04,919.35l-17.07,6.12c-18.52,5.31-37.28,9.75-56.21,13.43c-46.05,8.97-93.79,14.99-140.39,18.42
c-63.52,4.68-125.88,6.4-188.52,4.81l2.69-0.95c48.56-19.6,97.42-38.64,144.78-61.04c47.39-22.42,90.52-49.98,134.44-78.32
c14.72,10.55,29.49,21.18,44.35,31.84C3084.9,874.33,3111.14,894.93,3132.04,919.35z"/>
<linearGradient id="SVGID_00000182504939189219026290000001687771729988917677_" gradientUnits="userSpaceOnUse" x1="1833.2477" y1="464.5893" x2="1833.2477" y2="2382.7954">
<stop offset="2.577320e-03" style="stop-color:#9DD32F"/>
<stop offset="0.3376" style="stop-color:#1BC3C5"/>
<stop offset="1" style="stop-color:#008CD8"/>
</linearGradient>
<path style="fill:url(#SVGID_00000182504939189219026290000001687771729988917677_);" d="M2890.41,736.89
c-2.05,1.17-4.11,2.35-6.17,3.52c-50.82,29.02-107.34,48.31-163.49,64.55c-59.62,17.25-120.59,29.66-182.07,38.17
c-61.56,8.54-123.66,13.15-185.79,14.74c-127.64,2.97-256.77,0-384.41,1.48c-114.28,2.97-225.6,4.45-339.88,31.17
c-68.27,16.33-126.16,41.57-187.01,75.71l-4.45,4.45c-16.33,7.42-29.68,17.81-46.01,29.69c-40.07,29.69-74.21,57.9-106.86,95.01
c-1.48,1.48-1.48,4.45-2.97,5.94c-17.81,19.3-34.14,38.6-46.01,62.35l-4.45,4.45c-43.04,74.22-65.31,152.9-74.21,236.03
c-0.33,3.47-0.62,6.95-0.91,10.42c-8.98,109.42-0.37,219.85,52.85,319.14l4.45,4.45c11.87,22.27,26.72,43.05,44.53,62.35
c1.48,1.48,1.48,4.45,2.97,5.94c29,31.96,60.93,58.86,95.26,81.59c25.83,58.04,77.83,99.36,132.97,127.59
c57.08,29.23,117.22,52.86,176.49,77.24c60.23,24.78,120.65,49.06,180.91,73.78c59.71,24.49,119.24,49.42,178.19,75.66
c43.44,19.34,86.56,39.41,129.17,60.54c26.36,13.08,52.39,26.23,78.05,40.62c0.06,0.22,0.12,0.45,0.16,0.67
c3.27,12.74,5.08,25.59,6.52,38.66c-32.15-14.3-68.48-21.35-106.8-19.03c-120.15,7.29-241.3,4.99-361.64,5.42
c-141.13,0.49-284.37-5.46-420-48.11c-87.36-27.48-169.41-70.97-242.22-126.43C735.7,1911.38,672.81,1358.57,938.64,980.53
c90.54-128.74,212.15-234.03,347.1-314.99c246.27-147.8,538.56-215.3,825.28-198.4c176.04,10.38,349.84,52.22,512.36,120.42
C2719.6,628.45,2806.14,680.2,2890.41,736.89z"/>
<linearGradient id="SVGID_00000041294334513375484540000007751390379576468904_" gradientUnits="userSpaceOnUse" x1="1336.1295" y1="3465.8823" x2="2961.1921" y2="1840.8196">
<stop offset="0" style="stop-color:#00155F"/>
<stop offset="0.5077" style="stop-color:#0068C0"/>
<stop offset="1" style="stop-color:#10BAD0"/>
</linearGradient>
<path style="fill:url(#SVGID_00000041294334513375484540000007751390379576468904_);" d="M3244.96,2757.96
c-112.55,421.08-512.84,753.71-941.31,811.77c-48.46,6.56-97.48,7.84-146.37,8.86c-231.71,4.9-452.39-5.97-673.07-81.45
c-56.25-19.24-123.04-44.1-191.73-74.91c7.23-7.11,14.52-14.18,21.71-21.33c21.62-21.47,42.43-43.45,65.74-63.14
c22.5-19.02,46.32-36.44,71.2-52.19c49.84-31.56,104.06-55.94,160.28-73.66c33.31-10.51,67.28-18.69,100.69-28.86
c50.09-3.43,102.04-6.4,152.5-7.88c75.69,0,149.9-1.48,225.6,1.48c48.98,2.97,97.96,2.97,146.94-1.48
c35.62-2.97,71.24-5.94,106.86-16.33c13.36-2.97,26.72-4.45,40.07-8.91c32.65-11.88,66.79-20.78,97.96-35.63
c2.97-1.48,4.45,0,7.42-1.48c100.93-43.05,187.01-103.91,259.74-190.02c56.4-66.8,94.99-138.06,123.19-218.22
c8.7-25.68,15.6-51.68,20.57-77.91v-0.01c13.71-72.31,12.78-146.39-5.73-220.46c-5.94-22.27-11.87-43.05-20.78-63.83
c-8.91-17.81-14.84-37.11-25.23-54.93l-4.45-4.45c-20.93-42.69-51.77-77.83-88.25-105.96c-0.01,0-0.01-0.01-0.01-0.01
c-41.2-50.38-92.32-79.11-149.89-106.75c-62.2-29.87-125.03-58.39-187.97-86.62c-125.91-56.46-252.42-111.74-375.5-174.21
c-47.55-24.14-94.56-49.36-140.6-76.29c-45.18-26.44-94.63-52.77-133.1-88.61c57.5,34.38,135.36,30.31,199.48,32.41
c105.87,3.47,211.74-2.89,317.61-2.49c100.32,0.37,200.86,0.7,300.8,10.3c81.54,7.82,156.38,37.45,230.05,73.48
c138.11,67.53,260.14,168.22,341.6,299.63C3277.57,2262.08,3306.51,2527.64,3244.96,2757.96z"/>
<linearGradient id="SVGID_00000116218201835915488090000007698577740652986507_" gradientUnits="userSpaceOnUse" x1="2670.0232" y1="1333.7509" x2="3138.8401" y2="1333.7509">
<stop offset="0" style="stop-color:#006D88"/>
<stop offset="1" style="stop-color:#001325"/>
</linearGradient>
<path style="fill:url(#SVGID_00000116218201835915488090000007698577740652986507_);" d="M3138.84,1246.53
c-4.05,7.21-8.39,14.3-13.02,21.21c-62.44,93.39-170.24,149.34-281.64,153.16c-55.52,1.92-92.85-38.69-137.04-64.66
c-11.78-6.93-24.25-13.03-37.12-18.59c9.28,0.07,19.16,6.29,27.68,9.8c10.34,4.28,20.69,8.55,31.03,12.81
c28.42,11.73,57.39,27.24,87.98,32.11c30.28,4.81,61.36,0.27,90.66-7.84c39.58-10.96,79.27-27.46,114.66-48.2
C3063.65,1311.94,3106.02,1282.22,3138.84,1246.53z"/>
<linearGradient id="SVGID_00000107554274915499741620000017142357276473639840_" gradientUnits="userSpaceOnUse" x1="2103.0261" y1="1156.8447" x2="3182.2144" y2="1156.8447">
<stop offset="0" style="stop-color:#33C391"/>
<stop offset="1" style="stop-color:#61C961"/>
</linearGradient>
<path style="fill:url(#SVGID_00000107554274915499741620000017142357276473639840_);" d="M3138.84,1246.53
c-32.82,35.69-75.19,65.41-116.81,89.8c-35.38,20.74-75.07,37.25-114.66,48.2c-29.3,8.11-60.38,12.65-90.66,7.84
c-30.59-4.87-59.56-20.38-87.98-32.11c-10.34-4.26-20.69-8.54-31.03-12.81c-8.52-3.5-18.4-9.72-27.68-9.8
c-35.78-15.45-74.73-26.57-111.18-38.82c-113.9-38.26-230.57-68.23-348.8-89.62c-36.75-6.65-72.09-14.35-107.01-20.01
c19.49-12.38,39.2-24.39,58.97-36.31c52.17-31.47,105.76-61.84,154.74-98.12c49.66-36.79,97.59-75.93,143.54-117.26
c1.11-0.99,10.42,1.43,12.19,1.68h0.01c1.72,0.22,3.44,0.46,5.17,0.68c2.12,0.28,4.24,0.55,6.37,0.82c0.86,0.12,1.74,0.22,2.6,0.33
c9.47,1.19,18.97,2.29,28.47,3.28c5.7,0.59,11.37,1.34,17.04,2.12c6.87,0.95,13.73,1.96,20.6,2.84c5.54,0.71,11.09,1.34,16.67,1.8
c50.2,4.08,100.07,9.07,150.39,10.79c3.35,0.1,6.72,0.21,10.08,0.3c62.65,1.59,125-0.13,188.52-4.81
c46.6-3.43,94.34-9.46,140.39-18.42c18.92-3.68,37.68-8.12,56.21-13.43l17.07-6.12c22.44,26.23,38.69,56.89,45.24,96.76
C3190.21,1094.74,3177.84,1177.04,3138.84,1246.53z"/>
<linearGradient id="SVGID_00000020390254334245868170000018312103307704318869_" gradientUnits="userSpaceOnUse" x1="2243.8032" y1="874.23" x2="2832.1287" y2="874.23">
<stop offset="0" style="stop-color:#000C2C"/>
<stop offset="1" style="stop-color:#004857"/>
</linearGradient>
<path style="fill:url(#SVGID_00000020390254334245868170000018312103307704318869_);" d="M2832.13,799.21
c-24.71,21.3-51.93,39.9-79.48,56.97c-39.17,24.27-80.53,44.85-122.88,62.96c-23.87,10.21-48.04,19.64-72.43,28.56l-4.63,1.54
c-6.87-0.88-13.73-1.89-20.6-2.84c-1.96-0.53-3.87-0.96-5.57-0.96c-3.83-0.37-7.66-0.76-11.47-1.16c-9.5-0.99-19-2.09-28.47-3.28
c-0.86-0.1-1.74-0.21-2.6-0.33c-2.12-0.27-4.24-0.53-6.37-0.82c-1.72-0.22-3.44-0.46-5.17-0.68h-0.01
c-1.77-0.25-11.07-2.67-12.19-1.68c-67.98-9.55-134.22-22.76-203.86-35.11c-4.22-0.73-8.42-1.44-12.62-2.14h7.35
c27.67-1.29,55.23-3.1,83.03-4.07c89.66-3.12,179.59-8.21,268.08-23.74C2683.57,858.19,2756.97,831.87,2832.13,799.21z"/>
<path class="st14" d="M2890.41,736.89c-4.53,5.58-9.07,11.18-13.6,16.76c-13.42,16.55-28.51,31.63-44.69,45.56
c-75.16,32.66-148.55,58.98-229.87,73.24c-88.49,15.53-178.42,20.62-268.08,23.74c-27.8,0.96-55.36,2.78-83.03,4.07h-7.35
c-0.68-0.12-1.37-0.22-2.05-0.33c-3.09-0.5-6.16-0.99-9.23-1.47c-2.78-0.43-5.55-0.85-8.34-1.25c-2.05-0.31-4.1-0.61-6.14-0.89
c-5.27-0.76-10.55-1.47-15.85-2.14c-2.18-0.3-4.38-0.56-6.56-0.82c-0.79-0.1-1.57-0.21-2.36-0.3c-2.31-0.28-4.63-0.55-6.95-0.8
c-5.31-0.61-10.61-1.17-15.91-1.69c-2.43-0.24-4.85-0.48-7.27-0.68c-0.37-0.03-0.73-0.07-1.1-0.09c-2.52-0.25-5.05-0.46-7.55-0.65
c-2.57-0.22-5.14-0.43-7.7-0.62c-5.61-0.42-11.24-0.79-16.86-1.1c-2.3-0.15-4.6-0.28-6.9-0.37c-0.28-0.03-0.56-0.04-0.85-0.04
c-2.52-0.15-5.03-0.25-7.55-0.36c-0.01,0-0.01,0-0.03,0h-0.1c-3.13-0.15-6.26-0.25-9.38-0.34c-2.88-0.1-5.77-0.18-8.65-0.24
c-40.06-0.89-79.97,0.82-120.06,5.49c-0.5-0.04-1.02-0.09-1.53-0.13c-155.5-14.25-315.63,18.3-459.26,78.11
c-83.99,34.96-157.96,83.25-234.31,131.76c1.48-1.48,1.48-4.45,2.97-5.94c32.65-37.11,66.79-65.32,106.86-95.01
c16.33-11.88,29.68-22.27,46.01-29.69l4.45-4.45c60.85-34.14,118.74-59.38,187.01-75.71c114.28-26.72,225.6-28.21,339.88-31.17
c127.64-1.48,256.77,1.48,384.41-1.48c62.13-1.59,124.23-6.21,185.79-14.74c61.48-8.51,122.45-20.92,182.07-38.17
c56.15-16.24,112.67-35.52,163.49-64.55C2886.3,739.24,2888.36,738.06,2890.41,736.89z"/>
<linearGradient id="SVGID_00000125600022378541841150000017409231584131792266_" gradientUnits="userSpaceOnUse" x1="2198.241" y1="1201.1409" x2="2198.241" y2="2177">
<stop offset="0.2577" style="stop-color:#001737"/>
<stop offset="0.5954" style="stop-color:#009BAA"/>
<stop offset="0.8479" style="stop-color:#006E95"/>
<stop offset="1" style="stop-color:#000A2D"/>
</linearGradient>
<path style="fill:url(#SVGID_00000125600022378541841150000017409231584131792266_);" d="M2748.48,2177
c-28.21-21.72-59.8-39.26-92.81-52.86c-2.97-1.48-4.45,0-7.42-1.48c-56.34-25.7-114.18-43.72-173.03-56.92l-34.76-9.92
c-218.92-52.11-442.86-118.46-610.19-275.88c-72.3-68.02-144.29-154.22-172.47-251.13c-36.63-126.06,32.03-278.8,161.65-319.24
c1.86-0.58,3.71-1.13,5.58-1.63c0.68-0.21,1.37-0.39,2.05-0.56c0.61-0.18,1.23-0.33,1.84-0.49c0.01,0,0.01,0,0.03,0
c0.01,0,0.01,0,0.03,0c0.19-0.06,0.39-0.1,0.58-0.16c0.88-0.21,1.77-0.43,2.67-0.64c0.85-0.21,1.71-0.4,2.55-0.58
c0.86-0.19,1.72-0.39,2.6-0.56c0.67-0.13,1.34-0.27,2-0.39c0.01,0,0.03-0.01,0.04-0.01c0.62-0.12,1.25-0.25,1.87-0.36
c1.28-0.24,2.55-0.46,3.84-0.67c0.73-0.12,1.45-0.24,2.17-0.34c2.92-0.45,5.86-0.82,8.8-1.1c0.64-0.07,1.26-0.13,1.9-0.19
c0.95-0.09,1.9-0.16,2.85-0.24c11.68-0.86,23.44-0.62,35.12,0.79c-2.29,0.85-4.57,1.71-6.84,2.58
c-78.34,30.31-151.52,85.34-188.18,161.84c-36.26,75.68-30.06,190.74,30.01,253.51c9.25,9.66,19.47,17.62,30.43,24.17h0.01
c38.47,35.84,87.92,62.17,133.1,88.61c46.04,26.93,93.05,52.15,140.6,76.29c123.09,62.47,249.6,117.75,375.5,174.21
c62.95,28.24,125.77,56.75,187.97,86.62C2656.16,2097.89,2707.28,2126.62,2748.48,2177z"/>
<path class="st16" d="M1976.39,891.58c-21.46,2.49-42.98,5.85-64.61,10.09c-0.09,0.01-0.16,0.03-0.25,0.06
c-10.18,2-20.39,4.2-30.62,6.61c-0.67,0-1.65,0.61-2.64,1.26c-1.22,0.82-2.48,1.71-3.29,1.71c-3.34,0.52-6.59,1.16-9.77,1.91h-0.01
c-3.53,0.83-6.99,1.8-10.39,2.84c-0.01,0-0.01,0-0.03,0c-66.4,5.82-130.94,28.71-186.7,65.3c-9.1,5.95-17.93,12.28-26.57,18.87
l-6.47-1.04c-22.35-2.57-46.01-0.42-68.16,2.91c-23.23,3.47-46.07,9.25-68.38,16.51c-44.69,14.53-89.32,33.95-129.42,58.52
c-37.24,22.82-69.4,52.98-96.81,86.83c-27.9,34.44-51.03,72.47-69.4,112.78c-18.45,40.44-32.28,82.79-44.23,125.54l-2.92,12.31
c0.28-3.47,0.58-6.95,0.91-10.42c8.91-83.13,31.17-161.81,74.21-236.03l4.45-4.45c11.87-23.75,28.2-43.05,46.01-62.35
c76.35-48.51,150.32-96.8,234.31-131.76c121.08-50.41,253.89-81.47,385.76-81.44c4.94,0,9.9,0.04,14.84,0.15
c1.14,0,2.29,0.03,3.43,0.06c3.07,0.06,6.14,0.15,9.22,0.25c1.42,0.04,2.85,0.1,4.27,0.16c1.91,0.06,3.83,0.15,5.74,0.24
c2.8,0.12,5.61,0.27,8.42,0.43c2.91,0.16,5.82,0.34,8.73,0.53c0.19,0.01,0.37,0.01,0.56,0.03c2.76,0.19,5.54,0.4,8.3,0.62
c0.31,0.01,0.62,0.04,0.93,0.07c2.95,0.24,5.91,0.49,8.85,0.76c0.07,0,0.13,0,0.21,0.01
C1975.37,891.49,1975.89,891.53,1976.39,891.58z"/>
<path class="st17" d="M1655.67,3123.97c-7.24,2.75-14.28,6.74-22.62,8.14c-0.71,0.12-1.44,0.24-2.15,0.36
c-5.8,0.97-11.62,1.92-17.44,2.85c-14.14,2.27-28.3,4.44-42.48,6.58c-26.63,4.02-53.31,7.91-79.94,12.07
c-0.22,0.03-0.46,0.07-0.71,0.12c-0.5,0.07-1.02,0.16-1.53,0.24c-0.09,0.01-0.16,0.03-0.25,0.04c-28.26,4.41-56.47,9.13-84.54,14.61
c-0.45,0.07-0.89,0.16-1.34,0.25c-15.12,2.95-30.19,6.15-45.21,9.62c-0.85,0.19-1.68,0.39-2.52,0.59c-0.03,0-0.06,0-0.09,0.02
c-1.44,0.34-2.88,0.67-4.3,1.01c-0.1,0.03-0.21,0.06-0.31,0.07c-0.5,0.12-0.99,0.24-1.48,0.36c-2.75,0.65-5.49,1.32-8.24,2
c-3.34,0.82-6.68,1.66-10.02,2.51c0,0-0.01,0-0.01,0.01c-17.93,4.56-35.75,9.5-53.52,14.68c-4.85,1.41-9.69,2.85-14.53,4.29
c-53.71,16.05-106.95,33.89-160.65,49.75c3.41-1.01,30.11-16.09,20.21-10.94c24.45-13.33,49.11-27.03,74.7-39.83
c29.68-14.84,59.37-28.21,90.54-41.57c68.27-28.21,139.52-47.5,210.76-68.29C1551.08,3102.8,1603.29,3113.58,1655.67,3123.97z"/>
<path class="st18" d="M2231.56,2343.47c-25.66-14.38-51.7-27.54-78.05-40.62c-42.61-21.12-85.73-41.19-129.17-60.54
c-58.95-26.25-118.48-51.17-178.19-75.66c-60.26-24.72-120.68-49-180.91-73.78c-59.26-24.38-119.4-48.01-176.49-77.24
c-55.14-28.23-107.14-69.55-132.97-127.59c69.31,45.89,148.38,74.71,232.75,93.58c118.71,28.4,234.42,45.32,350.61,58.28
c18.36,11.91,37.25,23.01,55.48,35.11c16.98,11.28,33.8,22.76,50.26,34.72h0.01c20.7,15.05,40.85,30.85,60.04,47.93
c1.2,1.07,2.39,2.14,3.58,3.21c41.34,37.31,78.66,80.44,103.45,130.59C2220.16,2308.1,2226.9,2325.52,2231.56,2343.47z"/>
<path class="st1" d="M1121.27,3243.58c-6.5,3.56-13,7.08-19.49,10.55"/>
<linearGradient id="SVGID_00000043453862302291417740000006473128975406365587_" gradientUnits="userSpaceOnUse" x1="1658.1101" y1="1124.8477" x2="2193.2344" y2="815.8935">
<stop offset="0" style="stop-color:#001636"/>
<stop offset="0.9948" style="stop-color:#00547A"/>
</linearGradient>
<path style="fill:url(#SVGID_00000043453862302291417740000006473128975406365587_);" d="M2241.76,899.93l-9.5,0.33
c-104.9,5.12-209.93,14.76-312.5,37.39c-54.13,11.95-107.52,27.55-159.14,47.77c-48.86,19.15-92.72,47.61-140.32,68.32l-2.57,1.17
c8.28-3.79,16.74-14.3,23.96-20.32c0.18-0.16,0.34-0.3,0.5-0.43c0.59-0.49,1.19-0.96,1.8-1.45c1.2-0.96,2.4-1.93,3.61-2.89
c0.89-0.71,1.8-1.44,2.7-2.15c1.68-1.32,3.35-2.64,5.05-3.96c11.24-8.77,22.74-17.29,34.51-25.56c1.4-0.98,2.81-1.97,4.23-2.95
c0.98-0.68,1.96-1.37,2.95-2.05c1.83-1.25,3.67-2.51,5.51-3.74c0.46-0.33,0.93-0.64,1.4-0.94c1.84-1.26,3.68-2.49,5.52-3.71
c0.5-0.34,1.01-0.68,1.51-0.99c2-1.34,4.01-2.66,6.01-3.95c2.08-1.37,4.16-2.72,6.25-4.04c0.45-0.3,0.89-0.58,1.34-0.86
c1.14-0.73,2.29-1.44,3.43-2.17c0.21-0.13,0.4-0.27,0.61-0.37c29.02-18.04,60.04-32.57,92.12-44.48c6.29-2.35,12.62-4.57,18.98-6.71
c0.73-0.25,1.45-0.5,2.18-0.74c7.72-2.57,15.48-4.97,23.3-7.21c4.35-1.26,8.7-2.46,13.08-3.62c11.09-2.94,22.26-5.58,33.51-7.93
c20.84-4.36,41.9-7.73,63.08-10.23c40.34-4.75,81.13-6.32,121.59-5.36c2.88,0.06,5.77,0.13,8.65,0.24c3.13,0.09,6.26,0.21,9.38,0.34
h0.1c0.01,0,0.01,0,0.03,0c2.52,0.1,5.05,0.22,7.55,0.36c0.28,0,0.56,0.01,0.85,0.04c2.3,0.1,4.6,0.22,6.9,0.37
c5.62,0.31,11.25,0.68,16.86,1.1c2.57,0.21,5.14,0.4,7.7,0.62c2.52,0.21,5.03,0.42,7.55,0.65c0.37,0.01,0.73,0.06,1.1,0.09
c2.42,0.22,4.85,0.45,7.27,0.68c5.31,0.52,10.61,1.08,15.91,1.69c2.32,0.25,4.63,0.52,6.95,0.8c0.79,0.09,1.57,0.19,2.36,0.3
c2.2,0.25,4.38,0.53,6.56,0.82c5.3,0.67,10.58,1.38,15.85,2.14c2.05,0.28,4.1,0.58,6.14,0.89c2.79,0.4,5.57,0.82,8.34,1.25
C2235.6,898.94,2238.67,899.43,2241.76,899.93z"/>
<path class="st20" d="M2406.65,2587.24c0.15,44.25-9.65,81.51-35.8,117.38c-23.69,32.48-53.03,60.83-86.35,83.32
c-50.92,34.37-105.99,48.66-165.65,58.88c16.79-4.04,33.32-9.1,49.54-15.31c90.71-34.68,169.63-109.27,191.92-203.81
c25.34-107.36-31.79-204.74-122.08-244.91c-1.44-13.06-3.25-25.92-6.52-38.66c48.21,19.86,91.43,51.63,125.03,91.49
C2393.13,2478.8,2406.47,2531.44,2406.65,2587.24z"/>
<path class="st21" d="M1854.78,916.06c-5.09,1.56-10.08,3.31-15.06,5.12c-6,2.17-11.99,4.39-18.17,6.46
c-0.27,0.09-0.55,0.16-0.82,0.25c-29.33,8.91-54.37,22.16-82.3,38.34c-3.29,2.02-6.56,4.05-9.83,6.13c-0.21,0.1-0.4,0.24-0.61,0.37
c-1.59,0.99-3.18,2-4.76,3.03c-2.09,1.32-4.17,2.67-6.25,4.04c-2,1.29-4.01,2.6-6.01,3.95c-0.5,0.31-1.01,0.65-1.51,0.99
c-1.84,1.22-3.68,2.45-5.52,3.71c-0.46,0.3-0.94,0.61-1.4,0.94c-1.84,1.23-3.68,2.48-5.51,3.74c-0.99,0.68-1.97,1.37-2.95,2.05
c-1.41,0.98-2.82,1.97-4.23,2.95c-11.77,8.27-23.27,16.79-34.51,25.56c-1.69,1.31-3.37,2.63-5.05,3.96
c-0.91,0.71-1.81,1.44-2.7,2.15c-1.2,0.96-2.4,1.93-3.61,2.89c-0.77,0.62-1.54,1.25-2.3,1.89c-8.15,6.62-16.13,13.4-23.96,20.32
c-74.52,65.88-134.47,144.59-173.18,237.91c-1.48,2.97,0,4.45-1.48,7.42c-14.68,34.25-23.78,69.9-28.04,106.14
c0-40.78-0.39-74.74,15.01-113.43c21.91-55.06,45.92-109.82,79.98-158.32c23.87-34.01,52.39-64.53,82.77-92.87
c15.61-14.56,31.76-28.59,48.71-41.54c8.64-6.59,17.47-12.92,26.57-18.87C1723.84,944.77,1788.37,921.87,1854.78,916.06z"/>
<path class="st21" d="M1991.87,1181.85c-25.96,1.65-52.29,6.19-79.38,14.89c-5.51,1.77-11.01,3.67-16.5,5.69h-0.01
c-11.68-1.41-23.44-1.65-35.12-0.79c-0.95,0.07-1.9,0.15-2.85,0.24c-0.64,0.06-1.26,0.12-1.9,0.19c-2.94,0.28-5.88,0.65-8.8,1.1
c-0.71,0.1-1.44,0.22-2.17,0.34c-1.29,0.21-2.57,0.43-3.84,0.67c-0.58,0.09-1.16,0.21-1.74,0.31c3.47-1.11,6.92-2.38,10.17-3.24
c7.3-1.96,14.65-3.76,22.04-5.4c14.14-3.18,28.42-5.79,42.77-7.85C1940.27,1184.3,1966.03,1183.41,1991.87,1181.85z"/>
<path class="st22" d="M2513.54,2236.8c-33.31-20.11-65.53-42.96-100.3-60.48c-34.18-17.22-70.54-29.9-107.62-39.29
c-43.43-11.01-87.84-17.61-132.32-22.56c-42.89-4.78-85.22-4.72-128.41-4.72h-0.01c-16.46-11.97-33.28-23.44-50.26-34.72
c-18.23-12.1-37.12-23.2-55.48-35.11c40.03,4.47,80.13,8.48,120.43,12.31c42.63,4.05,85.48,7.93,128.71,11.99
c1.93,0.18,3.87,0.37,5.8,0.55C2321.35,2076.75,2434.55,2140.54,2513.54,2236.8z"/>
<path class="st23" d="M2611.25,2422.76c-54.07-58.8-108.04-119.18-174.02-165c-93.28-64.78-215.69-98.57-328.72-96.88
c-1.19-1.07-2.37-2.14-3.58-3.21c-19.19-17.09-39.33-32.88-60.04-47.93c43.19,0,85.52-0.06,128.41,4.72
c44.48,4.96,88.89,11.55,132.32,22.56c37.08,9.4,73.44,22.07,107.62,39.29c34.78,17.52,67,40.36,100.3,60.48
c0,0.01,0.01,0.01,0.01,0.01c1.44,1.77,2.88,3.53,4.3,5.33c0.04,0.04,0.09,0.1,0.13,0.16c1.42,1.78,2.85,3.59,4.24,5.4
c0.88,1.11,1.75,2.26,2.6,3.38c0.8,1.04,1.59,2.09,2.39,3.15c2.27,3.03,4.51,6.1,6.71,9.19c0.8,1.11,1.59,2.23,2.36,3.34
c0.33,0.46,0.65,0.91,0.96,1.37c0.76,1.1,1.51,2.18,2.26,3.28c3.83,5.58,7.55,11.25,11.15,17.01c0.62,0.98,1.23,1.96,1.83,2.94
c0.76,1.22,1.51,2.45,2.26,3.68c0.62,1.02,1.25,2.06,1.86,3.1c0.68,1.13,1.37,2.27,2.02,3.43c0.52,0.88,1.02,1.75,1.53,2.63
c0.7,1.19,1.4,2.39,2.06,3.61c0.64,1.11,1.28,2.24,1.9,3.37c0.95,1.69,1.87,3.4,2.79,5.11c0.13,0.22,0.27,0.46,0.39,0.71
c0.86,1.59,1.71,3.18,2.54,4.78c0.5,0.95,1.01,1.9,1.5,2.85c1.1,2.12,2.18,4.26,3.25,6.4
C2589.34,2360.63,2601.87,2391.06,2611.25,2422.76z"/>
<path class="st24" d="M2892.94,2626.65l-0.15-2.08c-4.1-53.6-5.58-105.56-14.49-159c-4.45-22.27-10.39-43.05-17.81-65.32
c-10.39-26.72-22.26-50.47-37.11-75.71c-41.56-66.8-94.99-115.79-163.26-151.42c-4.45-1.48-7.42-5.94-10.39-7.42
c-102.41-50.47-210.76-80.16-325.04-90.55c-4.45,0-10.39-2.97-14.84-2.97c-41.56-2.97-81.63-7.42-121.57-7.97
c-43.24-4.07-86.08-7.94-128.71-11.99l3.1-34.75c138.82,13.27,278.29,18.2,412.55,48.28c58.85,13.2,116.69,31.22,173.03,56.92
c2.97,1.48,4.45,0,7.42,1.48c33.01,13.6,64.59,31.14,92.81,52.86c0,0,0,0.01,0.01,0.01c36.48,28.13,67.32,63.27,88.25,105.96
l4.45,4.45c10.39,17.81,16.33,37.11,25.23,54.93c8.91,20.78,14.84,41.57,20.78,63.83
C2905.72,2480.27,2906.65,2554.34,2892.94,2626.65z"/>
</svg>

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -1,35 +1,75 @@
{
"$schema": "https://biomejs.dev/schemas/1.5.0/schema.json",
"linter": {
"enabled": true,
"rules": {
"all": true,
"style": {
"useWhile": "off",
"noNonNullAssertion": "off"
},
"suspicious": {
"noExplicitAny": "off",
"noAssignInExpressions": "off"
"noAssignInExpressions": "off",
"noUnsafeDeclarationMerging": "off",
"noRedeclare": "off",
"noEmptyInterface": "off",
"noConfusingVoidType": "off",
"noImplicitAnyLet": "off"
},
"style": {
"noNonNullAssertion": "off",
"noParameterAssign": "off"
},
"correctness": {
"noUnusedVariables": "off"
},
"nursery": {
"useExportType": "error",
"useImportType": "error",
"useNodejsImportProtocol": "error",
"noUselessLoneBlockStatements": "warn",
"noUselessTernary": "error",
"noEmptyBlockStatements": "off"
},
"complexity": {
"noBannedTypes": "off",
"noForEach": "off",
"noUselessConstructor": "off",
"noThisInStatic": "off"
},
"a11y": {
"all": false
},
"performance": {
"noDelete": "off"
}
}
},
"json": {
"formatter": {
"enabled": true,
"indentWidth": 2,
"lineWidth": 80
}
},
"formatter": {
"enabled": true,
"indentWidth": 2,
"indentStyle": "space",
"lineWidth": 140,
"indentStyle": "tab",
"lineWidth": 120,
"lineEnding": "crlf",
"formatWithErrors": true
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"arrowParentheses": "asNeeded",
"bracketSameLine": true,
"semicolons": "always"
}
},
"files": {
"ignore": [
"node_modules/",
"build",
"dist",
"tsup.config.ts",
"__test__"
]
"ignoreUnknown": true,
"ignore": ["node_modules/", "build", "lib", "__test__"]
},
"organizeImports": {
"enabled": true
"enabled": false
}
}

BIN
bun.lockb

Binary file not shown.

2688
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,70 +1,74 @@
{
"name": "@biscuitland/core",
"workspaces": [
"packages/*"
],
"scripts": {
"build": "turbo run build",
"clean": "turbo run clean",
"check": "biome check ./packages/",
"check:apply": "biome check --apply --max-diagnostics 200 --quote-style single --trailing-comma none ./packages/",
"lint": "biome format --write --quote-style single --trailing-comma none ./packages/",
"dev": "turbo run dev --parallel"
},
"engines": {
"npm": ">=7.0.0",
"node": ">=16.0.0"
},
"devDependencies": {
"@biomejs/biome": "^1.3.3",
"@changesets/cli": "^2.24.1",
"@types/node": "^20.0.0",
"turbo": "^1.4.2",
"typescript": "^5.0.4"
},
"packageManager": "npm@8.19.4",
"bugs": {
"url": "https://github.com/oasisjs/biscuit"
},
"keywords": [
"api",
"discord",
"bots",
"typescript",
"botdev"
],
"license": "Apache-2.0",
"author": "Yuzuru <yuzuru@programmer.net>",
"contributors": [
{
"name": "Yuzuru",
"url": "https://github.com/yuzudev",
"author": true
},
{
"name": "miia",
"url": "https://github.com/dragurimu"
},
{
"name": "n128",
"url": "https://github.com/nicolito128"
},
{
"name": "socram03",
"url": "https://github.com/socram03"
},
{
"name": "Drylozu",
"url": "https://github.com/Drylozu"
},
{
"name": "FreeAoi",
"url": "https://github.com/FreeAoi"
}
],
"homepage": "https://biscuitjs.com",
"repository": {
"type": "git",
"url": "git+https://github.com/oasisjs/biscuit.git"
}
}
"name": "seyfert",
"version": "0.1.0",
"main": "./lib/index.js",
"module": "./lib/index.js",
"types": "./lib/index.d.ts",
"files": [
"lib/**"
],
"scripts": {
"build": "tsc --outDir ./lib",
"dev": "swc src -d lib -w",
"prepublishOnly": "npm run build",
"prepare": "npm run build && husky install",
"lint": "biome lint --apply ./src",
"format": "biome format --write ./src",
"check-h": "biome check --apply ./src",
"check": "biome check --apply --changed --no-errors-on-unmatched ./src"
},
"author": "MARCROCK22",
"license": "ISC",
"dependencies": {
"chokidar": "^3.5.3",
"discord-api-types": "^0.37.71",
"magic-bytes.js": "^1.7.0",
"ts-mixer": "^6.0.3",
"ws": "^8.16.0"
},
"lint-staged": {
"*.ts": [
"biome check --apply",
"biome format --write"
]
},
"devDependencies": {
"lint-staged": "^15.2.2",
"@biomejs/biome": "1.5.0",
"@swc/cli": "^0.1.63",
"@swc/core": "^1.3.102",
"@types/node": "^20.10.7",
"@types/ws": "^8.5.10",
"husky": "^8.0.3",
"typescript": "^5.3.3"
},
"optionalDependencies": {
"ioredis": "^5.3.2",
"tweetnacl": "^1.0.3",
"uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.39.0"
},
"homepage": "https://biscuitjs.com",
"repository": {
"type": "git",
"url": "git+https://github.com/tiramisulabs/biscuit.git"
},
"bugs": {
"url": "https://github.com/tiramisulabs/biscuit"
},
"keywords": [
"api",
"discord",
"bots",
"typescript",
"botdev"
],
"publishConfig": {
"access": "public"
},
"contributors": [
{
"name": "socram03",
"url": "https://github.com/socram03"
}
]
}

View File

@ -1,31 +0,0 @@
# @biscuitland/common
## 0.0.8
### Patch Changes
- idk
## 0.0.7
### Patch Changes
- fix the silly logger and other silly things affected by this bug
## 0.0.6
### Patch Changes
- I meessed up
## 0.0.5
### Patch Changes
- fix: logger on every module
## 0.0.4
### Patch Changes
- first 3.0.\* without bugs

View File

@ -1,20 +0,0 @@
# @biscuitland/common
## Most importantly, biscuit's common is:
Custom types, functions and utility classes, a feature-rich package for sharing in the biscuit libraries
[<img src="https://img.shields.io/badge/GitHub-100000?style=for-the-badge&logo=github&logoColor=white">](https://github.com/oasisjs/biscuit)
[<img src="https://img.shields.io/badge/Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white">](https://discord.gg/XNw2RZFzaP)
<img align="right" src="https://raw.githubusercontent.com/oasisjs/biscuit/main/assets/icon.svg" alt="biscuit"/>
## Install (for [node18](https://nodejs.org/en/download/))
```sh-session
npm install @biscuitland/common
yarn add @biscuitland/common
```
## Links
* [Website](https://biscuitjs.com/)
* [Documentation](https://docs.biscuitjs.com/)
* [Discord](https://discord.gg/XNw2RZFzaP)
* [core](https://www.npmjs.com/package/@biscuitland/core) | [rest](https://www.npmjs.com/package/@biscuitland/rest) | [ws](https://www.npmjs.com/package/@biscuitland/ws) | [helpers](https://www.npmjs.com/package/@biscuitland/helpers)

View File

@ -1,75 +0,0 @@
{
"name": "@biscuitland/common",
"version": "0.0.10",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"type": "module",
"types": "./dist/index.d.ts",
"files": [
"dist/**"
],
"scripts": {
"build": "tsup",
"clean": "rm -rf dist && rm -rf .turbo",
"dev": "tsup --watch"
},
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"require": "./dist/index.cjs"
}
},
"devDependencies": {
"tsup": "^7.0.0"
},
"license": "Apache-2.0",
"author": "Yuzuru <yuzuru@programmer.net>",
"contributors": [
{
"name": "Yuzuru",
"url": "https://github.com/yuzudev"
},
{
"name": "miia",
"url": "https://github.com/dragurimu"
},
{
"name": "n128",
"url": "https://github.com/nicolito128"
},
{
"name": "socram03",
"url": "https://github.com/socram03",
"author": true
},
{
"name": "Drylozu",
"url": "https://github.com/Drylozu"
}
],
"homepage": "https://biscuitjs.com",
"repository": {
"type": "git",
"url": "git+https://github.com/oasisjs/biscuit.git"
},
"bugs": {
"url": "https://github.com/oasisjs/biscuit"
},
"keywords": [
"api",
"discord",
"bots",
"typescript",
"botdev"
],
"publishConfig": {
"access": "public"
},
"dependencies": {
"discord-api-types": "^0.37.39"
}
}

View File

@ -1,165 +0,0 @@
// https://github.com/discordeno/discordeno/blob/main/packages/utils/src/Collection.ts
export class Collection<K, V> extends Map<K, V> {
/**
* The maximum amount of items allowed in this collection. To disable cache, set it 0, set to undefined to make it infinite.
* @default undefined
*/
maxSize: number | undefined;
/** Handler to remove items from the collection every so often. */
sweeper: (CollectionSweeper<K, V> & { intervalId?: NodeJS.Timeout }) | undefined;
constructor(entries?: (ReadonlyArray<readonly [K, V]> | null) | Map<K, V>, options?: CollectionOptions<K, V>) {
super(entries ?? []);
this.maxSize = options?.maxSize;
if (!options?.sweeper) return;
this.startSweeper(options.sweeper);
}
startSweeper(options: CollectionSweeper<K, V>): NodeJS.Timer {
if (this.sweeper?.intervalId) clearInterval(this.sweeper.intervalId);
this.sweeper = options;
this.sweeper.intervalId = setInterval(() => {
// biome-ignore lint/complexity/noForEach: <explanation>
this.forEach((value, key) => {
if (!this.sweeper?.filter(value, key)) return;
this.delete(key);
return key;
});
}, options.interval);
return this.sweeper.intervalId;
}
stopSweeper(): void {
clearInterval(this.sweeper?.intervalId);
}
changeSweeperInterval(newInterval: number): void {
if (this.sweeper == null) return;
this.startSweeper({ filter: this.sweeper.filter, interval: newInterval });
}
changeSweeperFilter(newFilter: (value: V, key: K) => boolean): void {
if (this.sweeper == null) return;
this.startSweeper({ filter: newFilter, interval: this.sweeper.interval });
}
/** Add an item to the collection. Makes sure not to go above the maxSize. */
set(key: K, value: V): this {
// When this collection is maxSized make sure we can add first
if ((this.maxSize !== undefined || this.maxSize === 0) && this.size >= this.maxSize) {
return this;
}
return super.set(key, value);
}
/** Add an item to the collection, no matter what the maxSize is. */
forceSet(key: K, value: V): this {
return super.set(key, value);
}
/** Convert the collection to an array. */
array(): V[] {
return [...this.values()];
}
/** Retrieve the value of the first element in this collection. */
first(): V | undefined {
return this.values().next().value;
}
/** Retrieve the value of the last element in this collection. */
last(): V | undefined {
return [...this.values()][this.size - 1];
}
/** Retrieve the value of a random element in this collection. */
random(): V | undefined {
const array = [...this.values()];
return array[Math.floor(Math.random() * array.length)];
}
/** Find a specific element in this collection. */
find(callback: (value: V, key: K) => boolean): NonNullable<V> | undefined {
for (const key of this.keys()) {
const value = this.get(key)!;
if (callback(value, key)) return value;
}
return undefined;
}
/** Find all elements in this collection that match the given pattern. */
filter(callback: (value: V, key: K) => boolean): Collection<K, V> {
const relevant = new Collection<K, V>();
// biome-ignore lint/complexity/noForEach: <explanation>
this.forEach((value, key) => {
if (callback(value, key)) relevant.set(key, value);
});
return relevant;
}
/** Converts the collection into an array by running a callback on all items in the collection. */
map<T>(callback: (value: V, key: K) => T): T[] {
const results = [];
for (const key of this.keys()) {
const value = this.get(key)!;
results.push(callback(value, key));
}
return results;
}
/** Check if one of the items in the collection matches the pattern. */
some(callback: (value: V, key: K) => boolean): boolean {
for (const key of this.keys()) {
const value = this.get(key)!;
if (callback(value, key)) return true;
}
return false;
}
/** Check if all of the items in the collection matches the pattern. */
every(callback: (value: V, key: K) => boolean): boolean {
for (const key of this.keys()) {
const value = this.get(key)!;
if (!callback(value, key)) return false;
}
return true;
}
/** Runs a callback on all items in the collection, merging them into a single value. */
reduce<T>(callback: (accumulator: T, value: V, key: K) => T, initialValue?: T): T {
let accumulator: T = initialValue!;
for (const key of this.keys()) {
const value = this.get(key)!;
accumulator = callback(accumulator, value, key);
}
return accumulator;
}
}
export interface CollectionOptions<K, V> {
/** Handler to clean out the items in the collection every so often. */
sweeper?: CollectionSweeper<K, V>;
/** The maximum number of items allowed in the collection. */
maxSize?: number;
}
export interface CollectionSweeper<K, V> {
/** The filter to determine whether an element should be deleted or not */
filter: (value: V, key: K, ...args: any[]) => boolean;
/** The interval in which the sweeper should run */
interval: number;
}

View File

@ -1,20 +0,0 @@
export const DiscordEpoch = 14200704e5;
export const API_VERSION = '10';
export const BASE_URL = `/api/v${API_VERSION}`;
export const BASE_HOST = 'https://discord.com';
export const CDN_URL = 'https://cdn.discordapp.com';
export const GATEWAY_BASE_URL = 'wss://gateway.discord.gg/?v=10&encoding=json';
export const OK_STATUS_CODES = [200, 201, 204, 304];
export enum HTTPMethods {
Delete = 'DELETE',
Get = 'GET',
Patch = 'PATCH',
Post = 'POST',
Put = 'PUT'
}

View File

@ -1,128 +0,0 @@
import { Options, bgBrightWhite, black, bold, cyan, gray, italic, red, yellow } from './Util';
export enum LogLevels {
Debug = 0,
Info = 1,
Warn = 2,
Error = 3,
Fatal = 4
}
export enum LogDepth {
Minimal = 0,
Full = 1
}
export type LoggerOptions = {
logLevel?: LogLevels;
name?: string;
active?: boolean;
};
export class Logger {
readonly options: Required<LoggerOptions>;
constructor(options: LoggerOptions) {
this.options = Options(Logger.DEFAULT_OPTIONS, options);
}
set level(level: LogLevels) {
this.options.logLevel = level;
}
get level(): LogLevels {
return this.options.logLevel;
}
set active(active: boolean) {
this.options.active = active;
}
get active(): boolean {
return this.options.active;
}
set name(name: string) {
this.options.name = name;
}
get name(): string {
return this.options.name;
}
rawLog(level: LogLevels, ...args: unknown[]) {
if (!this.active) return;
if (level < this.level) return;
const color = Logger.colorFunctions.get(level) ?? Logger.noColor;
const date = new Date();
const log = [
bgBrightWhite(black(`[${date.toLocaleDateString()} ${date.toLocaleTimeString()}]`)),
color(Logger.prefixes.get(level) ?? 'DEBUG'),
this.name ? `${this.name} >` : '>',
...args
];
switch (level) {
case LogLevels.Debug:
return console.debug(...log);
case LogLevels.Info:
return console.info(...log);
case LogLevels.Warn:
return console.warn(...log);
case LogLevels.Error:
return console.error(...log);
case LogLevels.Fatal:
return console.error(...log);
default:
return console.log(...log);
}
}
debug(...args: any[]) {
this.rawLog(LogLevels.Debug, ...args);
}
info(...args: any[]) {
this.rawLog(LogLevels.Info, ...args);
}
warn(...args: any[]) {
this.rawLog(LogLevels.Warn, ...args);
}
error(...args: any[]) {
this.rawLog(LogLevels.Error, ...args);
}
fatal(...args: any[]) {
this.rawLog(LogLevels.Fatal, ...args);
}
static DEFAULT_OPTIONS: Required<LoggerOptions> = {
logLevel: LogLevels.Info,
name: 'BISCUIT',
active: true
};
static noColor(msg: string) {
return msg;
}
static colorFunctions = new Map<LogLevels, (str: string) => string>([
[LogLevels.Debug, gray],
[LogLevels.Info, cyan],
[LogLevels.Warn, yellow],
[LogLevels.Error, (str: string) => red(str)],
[LogLevels.Fatal, (str: string) => red(bold(italic(str)))]
]);
static prefixes = new Map<LogLevels, string>([
[LogLevels.Debug, 'DEBUG'],
[LogLevels.Info, 'INFO'],
[LogLevels.Warn, 'WARN'],
[LogLevels.Error, 'ERROR'],
[LogLevels.Fatal, 'FATAL']
]);
}

View File

@ -1,46 +0,0 @@
export type Tail<A> = A extends [unknown, ...infer rest] ? rest : A extends [unknown] ? [] : A extends (infer first)[] ? first[] : never;
export type ValueOf<T> = T[keyof T];
export type ArrayFirsElement<A> = A extends [...infer arr] ? arr[0] : never;
export type RestToKeys<T extends unknown[]> = T extends [infer V, ...infer Keys] ? { [K in Extract<Keys[number], string>]: V } : never;
export type Identify<T> = T extends infer U ? { [K in keyof U]: U[K] } : never;
export type TypeArray<T> = T | T[];
export type When<T extends boolean, A, B = never> = T extends true ? A : B;
export type PickPartial<T, K extends keyof T> = {
[P in keyof T]?: T[P] | undefined;
} & {
[P in K]: T[P];
};
export type MakeRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
export type CamelCase<S extends string> = S extends `${infer P1}_${infer P2}${infer P3}`
? `${Lowercase<P1>}${Uppercase<P2>}${CamelCase<P3>}`
: Lowercase<S>;
export type SnakeCase<S extends string> = S extends `${infer A}${infer Rest}`
? A extends Uppercase<A>
? `_${Lowercase<A>}${SnakeCase<Rest>}`
: `${A}${SnakeCase<Rest>}`
: Lowercase<S>;
export type ObjectToLower<T> = Identify<{
[K in keyof T as CamelCase<Exclude<K, symbol | number>>]: T[K] extends unknown[]
? Identify<ObjectToLower<T[K][0]>[]>
: T[K] extends object
? Identify<ObjectToLower<T[K]>>
: T[K];
}>;
export type ObjectToSnake<T> = Identify<{
[K in keyof T as SnakeCase<Exclude<K, symbol | number>>]: T[K] extends unknown[]
? Identify<ObjectToSnake<T[K][0]>[]>
: T[K] extends object
? Identify<ObjectToSnake<T[K]>>
: T[K];
}>;

View File

@ -1,6 +0,0 @@
export * from './Constants';
export * from './Util';
export * from './Types';
export * from 'discord-api-types/v10';
export * from './Collection';
export * from './Logger';

View File

@ -1,7 +0,0 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist"
},
"include": ["src/**/*"]
}

View File

@ -1,12 +0,0 @@
import { defineConfig } from 'tsup';
const isProduction = process.env.NODE_ENV === 'production';
export default defineConfig({
clean: true,
dts: true,
entry: ['src/index.ts'],
format: ['cjs', 'esm'],
minify: isProduction,
sourcemap: false
});

View File

@ -1,171 +0,0 @@
# @biscuitland/core
## 3.0.12
### Patch Changes
- new changes
- new changes
- Updated dependencies
- Updated dependencies
- @biscuitland/ws@3.0.12
## 3.0.8
### Patch Changes
- Updated dependencies
- @biscuitland/common@0.0.8
- @biscuitland/ws@3.0.8
## 3.0.7
### Patch Changes
- Updated dependencies
- @biscuitland/common@0.0.7
- @biscuitland/ws@3.0.7
## 3.0.6
### Patch Changes
- I meessed up
- Updated dependencies
- @biscuitland/common@0.0.6
- @biscuitland/rest@3.0.6
- @biscuitland/ws@3.0.6
## 3.0.5
### Patch Changes
- fix: logger on every module
- Updated dependencies
- @biscuitland/common@0.0.5
- @biscuitland/rest@3.0.5
- @biscuitland/ws@3.0.5
## 3.0.4
### Patch Changes
- first 3.0.\* without bugs
- Updated dependencies
- @biscuitland/common@0.0.4
- @biscuitland/rest@3.0.4
- @biscuitland/ws@3.0.4
## 2.3.0
### Minor Changes
- fix TODO
### Patch Changes
- Updated dependencies
- @biscuitland/api-types@2.3.0
- @biscuitland/rest@2.3.0
- @biscuitland/ws@2.3.0
## 2.2.3
### Patch Changes
- bug fixes
- Updated dependencies
- @biscuitland/api-types@2.2.3
- @biscuitland/rest@2.2.3
- @biscuitland/ws@2.2.3
## 2.2.2
### Patch Changes
- rename guildLocales to guildLocale in interactions
- Updated dependencies
- @biscuitland/api-types@2.2.2
- @biscuitland/rest@2.2.2
- @biscuitland/ws@2.2.2
## 2.2.1
### Patch Changes
- select menu options now can be empty since the latest Discord API update
- Updated dependencies
- @biscuitland/api-types@2.2.1
- @biscuitland/rest@2.2.1
- @biscuitland/ws@2.2.1
## 2.2.0
### Minor Changes
- Functionality to delete ephemeral messages added, select menus were updated
### Patch Changes
- Updated dependencies
- @biscuitland/api-types@2.2.0
- @biscuitland/rest@2.2.0
- @biscuitland/ws@2.2.0
## 2.1.2
### Patch Changes
- minor changes
- Updated dependencies
- @biscuitland/api-types@2.1.2
- @biscuitland/rest@2.1.2
- @biscuitland/ws@2.1.2
## 2.1.1
### Patch Changes
- dumb hotfix that LH asked for (blame Yuzu)
- Updated dependencies
- @biscuitland/api-types@2.1.1
- @biscuitland/rest@2.1.1
- @biscuitland/ws@2.1.1
## 2.1.0
### Minor Changes
- Changes to cache and forum channels ✨
- Forum channels and updates to @biscuitland/cache
### Patch Changes
- Updated dependencies
- Updated dependencies
- @biscuitland/api-types@2.1.0
- @biscuitland/rest@2.1.0
- @biscuitland/ws@2.1.0
## 2.0.6
### Patch Changes
- Minor fixes
- Updated dependencies
- @biscuitland/api-types@2.0.6
- @biscuitland/rest@2.0.6
- @biscuitland/ws@2.0.6
## 2.0.5
### Major Changes
- publish
### Patch Changes
- Updated dependencies
- @biscuitland/api-types@2.0.5
- @biscuitland/rest@2.0.5
- @biscuitland/ws@2.0.5

View File

@ -1,46 +0,0 @@
# @biscuitland/core
Core contains the essentials to launch you to develop your own customized and scalable bot.
[<img src="https://img.shields.io/badge/GitHub-100000?style=for-the-badge&logo=github&logoColor=white">](https://github.com/oasisjs/biscuit)
[<img src="https://img.shields.io/badge/Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white">](https://discord.gg/XNw2RZFzaP)
## Getting Started
### Install (for [node18](https://nodejs.org/en/download/))
```sh-session
npm install @biscuitland/core
yarn add @biscuitland/core
```
### Example bot
`project/index.js`:
```ts
import { Session } from '@biscuitland/core';
import { GatewayIntentBits } from '@biscuitland/common';
const session = new Session({ token: 'your token', intents: GatewayIntentBits.Guilds });
session.on('READY', (payload, shardId) => {
console.log('Logged in as: %s in shard #%s', payload.user.username, shardId);
});
session.start();
```
### Execute
For node 18.+:
```
B:\project> node index.js
```
For node 16.+:
```
B:\project> node --experimental-fetch index.js
```
## Links
* [Website](https://biscuitjs.com/)
* [Documentation](https://docs.biscuitjs.com/)
* [Discord](https://discord.gg/XNw2RZFzaP)
* [rest](https://www.npmjs.com/package/@biscuitland/rest) | [ws](https://www.npmjs.com/package/@biscuitland/ws) | [helpers](https://www.npmjs.com/package/@biscuitland/helpers)

View File

@ -1,78 +0,0 @@
{
"name": "@biscuitland/core",
"version": "3.0.12",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"dist/**"
],
"scripts": {
"build": "tsup",
"clean": "rm -rf dist && rm -rf .turbo",
"dev": "tsup --watch"
},
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.mjs"
},
"require": "./dist/index.js"
}
},
"dependencies": {
"@biscuitland/common": "^0.0.10",
"@biscuitland/rest": "^3.0.7",
"@biscuitland/ws": "^3.0.12",
"eventemitter2": "^6.4.9"
},
"devDependencies": {
"@types/node": "^20.0.0",
"tsup": "^7.0.0"
},
"license": "Apache-2.0",
"author": "Yuzuru <yuzuru@programmer.net>",
"contributors": [
{
"name": "Yuzuru",
"url": "https://github.com/yuzudev"
},
{
"name": "miia",
"url": "https://github.com/dragurimu"
},
{
"name": "n128",
"url": "https://github.com/nicolito128"
},
{
"name": "socram03",
"url": "https://github.com/socram03",
"author": true
},
{
"name": "Drylozu",
"url": "https://github.com/Drylozu"
}
],
"homepage": "https://biscuitjs.com",
"repository": {
"type": "git",
"url": "git+https://github.com/oasisjs/biscuit.git"
},
"bugs": {
"url": "https://github.com/oasisjs/biscuit"
},
"keywords": [
"api",
"discord",
"bots",
"typescript",
"botdev"
],
"publishConfig": {
"access": "public"
}
}

View File

@ -1,17 +0,0 @@
import type { GatewayEvents } from '@biscuitland/ws';
import type { Session } from '../index';
export function actionHandler([session, payload, shardId]: Parameters<ActionHandler>) {
// @ts-expect-error At this point, typescript sucks
session.emit(payload.t, payload.d, shardId);
// @ts-expect-error At this point, typescript sucks
session.emit('RAW', payload.d, shardId);
}
export type ActionHandler<G extends keyof GatewayEvents = keyof GatewayEvents,> = (
...args: [Session<true>, { t: G; d: GatewayEvents[G] }, number]
) => unknown;
export type Handler = {
[K in keyof GatewayEvents]: (...args: [GatewayEvents[K], number]) => unknown;
};

View File

@ -1,6 +0,0 @@
export * from './utils/types';
export * from './utils/utils';
export * from './session';
export { Session as Biscuit } from './session';
export * from './managers/MainManager';
export * from './events/handler';

View File

@ -1,121 +0,0 @@
import {
APIApplicationCommand,
Identify,
MakeRequired,
RESTGetAPIApplicationCommandsQuery,
RESTGetAPIApplicationGuildCommandsQuery,
RESTPatchAPIApplicationCommandJSONBody,
RESTPatchAPIApplicationGuildCommandJSONBody,
RESTPostAPIApplicationCommandsJSONBody,
RESTPostAPIApplicationGuildCommandsJSONBody,
RESTPutAPIApplicationCommandPermissionsJSONBody,
RESTPutAPIApplicationCommandsJSONBody,
RESTPutAPIApplicationGuildCommandsJSONBody,
RESTPutAPIApplicationRoleConnectionMetadataJSONBody
} from '@biscuitland/common';
import { Session } from '..';
export class ApplicationManager {
readonly session!: Session;
constructor(session: Session) {
Object.defineProperty(this, 'session', {
value: session,
writable: false
});
}
getBotGateway() {
return this.session.api.gateway.bot.get();
}
getGateway() {
return this.session.api.gateway.get();
}
getNitroStickerPacks() {
return this.session.api['sticker-packs'].get();
}
getRoleConnectionMetadata(applicationId: string) {
return this.session.api.applications(applicationId)['role-connections'].metadata.get();
}
editRoleConnectionMetadata(applicationId: string, body: RESTPutAPIApplicationRoleConnectionMetadataJSONBody) {
return this.session.api.applications(applicationId)['role-connections'].metadata.put({ body });
}
getCommands(
applicationId: string,
query: RESTGetAPIApplicationCommandsQuery
): Promise<RESTGetAPIApplicationCommandsWithLocalizationsResult>;
getCommands(applicationId: string, query?: RESTGetAPIApplicationCommandsQuery) {
return this.session.api.applications(applicationId).commands.get({ query });
}
createCommand(applicationId: string, body: RESTPostAPIApplicationCommandsJSONBody) {
return this.session.api.applications(applicationId).commands.post({ body });
}
getCommand(applicationId: string, commandId: string) {
return this.session.api.applications(applicationId).commands(commandId).get();
}
editCommand(applicationId: string, commandId: string, body: RESTPatchAPIApplicationCommandJSONBody) {
return this.session.api.applications(applicationId).commands(commandId).patch({ body });
}
deleteCommand(applicationId: string, commandId: string) {
return this.session.api.applications(applicationId).commands(commandId).delete();
}
bulkCommands(applicationId: string, body: RESTPutAPIApplicationCommandsJSONBody) {
return this.session.api.applications(applicationId).commands.put({ body });
}
getCommandPermissions(applicationId: string, guildId: string, commandId: string) {
return this.session.api.applications(applicationId).guilds(guildId).commands(commandId).permissions.get();
}
editCommandPermissions(applicationId: string, guildId: string, commandId: string, body: RESTPutAPIApplicationCommandPermissionsJSONBody) {
return this.session.api.applications(applicationId).guilds(guildId).commands(commandId).permissions.put({ body });
}
getGuildCommands(
applicationId: string,
guildId: string,
query: RESTGetAPIApplicationGuildCommandsQuery
): Promise<RESTGetAPIApplicationGuildCommandsWithLocalizationsResult>;
getGuildCommands(applicationId: string, guildId: string, query?: RESTGetAPIApplicationGuildCommandsQuery) {
return this.session.api.applications(applicationId).guilds(guildId).commands.get({ query });
}
createGuildCommand(applicationId: string, guildId: string, body: RESTPostAPIApplicationGuildCommandsJSONBody) {
return this.session.api.applications(applicationId).guilds(guildId).commands.post({ body });
}
getGuildCommand(applicationId: string, guildId: string, commandId: string) {
return this.session.api.applications(applicationId).guilds(guildId).commands(commandId).get();
}
editGuildCommand(applicationId: string, guildId: string, commandId: string, body: RESTPatchAPIApplicationGuildCommandJSONBody) {
return this.session.api.applications(applicationId).guilds(guildId).commands(commandId).patch({ body });
}
deleteGuildCommand(applicationId: string, guildId: string, commandId: string) {
return this.session.api.applications(applicationId).guilds(guildId).commands(commandId).delete();
}
bulkGuildCommands(applicationId: string, guildId: string, body: RESTPutAPIApplicationGuildCommandsJSONBody) {
return this.session.api.applications(applicationId).guilds(guildId).commands.put({ body });
}
getGuildCommandPermissions(applicationId: string, guildId: string) {
return this.session.api.applications(applicationId).guilds(guildId).commands.permissions.get();
}
}
export type RESTGetAPIApplicationCommandsWithLocalizationsResult = Identify<
MakeRequired<APIApplicationCommand, 'name_localizations' | 'description_localizations'>
>[];
export type RESTGetAPIApplicationGuildCommandsWithLocalizationsResult = RESTGetAPIApplicationCommandsWithLocalizationsResult;

View File

@ -1,214 +0,0 @@
import type {
APIChannel,
RESTGetAPIChannelMessageReactionUsersQuery,
RESTGetAPIChannelThreadMemberQuery,
RESTGetAPIChannelThreadMembersQuery,
RESTGetAPIChannelThreadsArchivedQuery,
RESTPatchAPIChannelJSONBody,
RESTPatchAPIChannelMessageJSONBody,
RESTPatchAPIStageInstanceJSONBody,
RESTPostAPIChannelFollowersJSONBody,
RESTPostAPIChannelInviteJSONBody,
RESTPostAPIChannelMessageJSONBody,
RESTPostAPIChannelMessagesBulkDeleteJSONBody,
RESTPostAPIChannelMessagesThreadsJSONBody,
RESTPostAPIChannelThreadsJSONBody,
RESTPostAPIChannelThreadsResult,
RESTPostAPIChannelWebhookJSONBody,
RESTPostAPIGuildForumThreadsJSONBody,
RESTPutAPIChannelPermissionJSONBody,
RESTPutAPIChannelRecipientJSONBody
} from '@biscuitland/common';
import type { RawFile } from '@biscuitland/rest';
import type { Session } from '../session';
export class ChannelManager {
readonly session!: Session;
constructor(session: Session) {
Object.defineProperty(this, 'session', {
value: session,
writable: false
});
}
get<T extends APIChannel = APIChannel>(id: string) {
return this.session.api.channels(id).get() as Promise<T>;
}
getWebhooks(channelId: string) {
return this.session.api.channels(channelId).webhooks.get();
}
createWebhook(channelId: string, body: RESTPostAPIChannelWebhookJSONBody) {
return this.session.api.channels(channelId).webhooks.post({ body });
}
edit(id: string, data: RESTPatchAPIChannelJSONBody) {
return this.session.api.channels(id).patch({ body: data });
}
delete(id: string) {
return this.session.api.channels(id).delete();
}
getMessages(id: string, limit = 50) {
return this.session.api.channels(id).messages.get({
query: { limit }
});
}
getMessage(id: string, messageId: string) {
return this.session.api.channels(id).messages(messageId).get();
}
createMessage(id: string, data: RESTPostAPIChannelMessageJSONBody) {
return this.session.api.channels(id).messages.post({ body: data });
}
sendTyping(id: string) {
return this.session.api.channels(id).typing.post();
}
getArchivedThreads(channelId: string, options: RESTGetAPIChannelThreadsArchivedOptions) {
const { type, ...query } = options;
if (type === 'private') {
return this.session.api.channels(channelId).threads.archived.private.get({ query });
}
return this.session.api.channels(channelId).threads.archived.public.get({ query });
}
crosspostMessage(channelId: string, messageId: string) {
return this.session.api.channels(channelId).messages(messageId).crosspost.post({});
}
createReaction(channelId: string, messageId: string, emoji: string) {
return this.session.api.channels(channelId).messages(messageId).reactions(emoji)('@me').put({});
}
deleteReaction(channelId: string, messageId: string, emoji: string, user = '@me') {
return this.session.api.channels(channelId).messages(messageId).reactions(emoji)(user).delete();
}
getReactions(channelId: string, messageId: string, emoji: string, query?: RESTGetAPIChannelMessageReactionUsersQuery) {
return this.session.api.channels(channelId).messages(messageId).reactions(emoji).get({ query });
}
deleteAllReactions(channelId: string, messageId: string, emoji?: string) {
if (emoji?.length) return this.session.api.channels(channelId).messages(messageId).reactions(emoji).delete();
return this.session.api.channels(channelId).messages(messageId).reactions.delete();
}
editMessage(channelId: string, messageId: string, body: RESTPatchAPIChannelMessageJSONBody, files?: RawFile[]) {
return this.session.api.channels(channelId).messages(messageId).patch({
body,
files
});
}
deleteMessage(channelId: string, messageId: string, reason?: string) {
return this.session.api.channels(channelId).messages(messageId).delete({ reason });
}
bulkMessages(channelId: string, body: RESTPostAPIChannelMessagesBulkDeleteJSONBody, reason?: string) {
return this.session.api.channels(channelId).messages['bulk-delete'].post({ body, reason });
}
editPermissions(channelId: string, overwriteId: string, body: RESTPutAPIChannelPermissionJSONBody, reason?: string) {
return this.session.api.channels(channelId).permissions(overwriteId).put({ body, reason });
}
deletePermission(channelId: string, overwriteId: string, reason?: string) {
return this.session.api.channels(channelId).permissions(overwriteId).delete({ reason });
}
getInvites(channelId: string) {
return this.session.api.channels(channelId).invites.get();
}
createInvite(channelId: string, body: RESTPostAPIChannelInviteJSONBody) {
return this.session.api.channels(channelId).invites.post({ body });
}
followAnnoucement(channelId: string, body: RESTPostAPIChannelFollowersJSONBody) {
return this.session.api.channels(channelId).followers.post({ body });
}
getPinnedMessages(channelId: string) {
return this.session.api.channels(channelId).pins.get();
}
pinMessage(channelId: string, messageId: string, reason?: string) {
return this.session.api.channels(channelId).pins(messageId).put({ reason });
}
unpinMessage(channelId: string, messageId: string, reason?: string) {
return this.session.api.channels(channelId).pins(messageId).delete({ reason });
}
groupDMAddRecipient(channelId: string, userId: string, body: RESTPutAPIChannelRecipientJSONBody) {
return this.session.api.channels(channelId).recipients(userId).put({ body });
}
groupDMRemoveRecipient(channelId: string, userId: string) {
return this.session.api.channels(channelId).recipients(userId).delete();
}
startThreadFromMessage(channelId: string, messageId: string, body: RESTPostAPIChannelMessagesThreadsJSONBody, reason?: string) {
return this.session.api.channels(channelId).messages(messageId).threads.post({ body, reason });
}
startThread(channelId: string, body: RESTPostAPIChannelThreadsJSONBody, reason?: string): Promise<RESTPostAPIChannelThreadsResult>;
startThread(channelId: string, body: RESTPostAPIGuildForumThreadsJSONBody, reason?: string) {
return this.session.api.channels(channelId).threads.post({ body, reason });
}
getListJoinedPrivateArchivedThreads(channelId: string, query?: RESTGetAPIChannelThreadsArchivedQuery) {
return this.session.api.channels(channelId).users('@me').threads.archived.private.get({ query });
}
getThreadMembers(channelId: string, query?: RESTGetAPIChannelThreadMembersQuery) {
return this.session.api.channels(channelId)['thread-members'].get({ query });
}
getThreadMember(channelId: string, userId: string, query?: RESTGetAPIChannelThreadMemberQuery) {
return this.session.api.channels(channelId)['thread-members'](userId).get({ query });
}
addThreadMember(channelId: string, userId: string) {
return this.session.api.channels(channelId)['thread-members'](userId).put({});
}
removeThreadMember(channelId: string, userId: string) {
return this.session.api.channels(channelId)['thread-members'](userId).delete();
}
leaveThread(channelId: string) {
return this.session.api.channels(channelId)['thread-members']('@me').delete();
}
joinThread(channelId: string) {
return this.session.api.channels(channelId)['thread-members']('@me').put({});
}
getVoiceRegions() {
return this.session.api.voice.region.get();
}
getStageInstance(channelId: string) {
return this.session.api['stage-instances'](channelId).get();
}
editStageInstance(channelId: string, body: RESTPatchAPIStageInstanceJSONBody, reason?: string) {
return this.session.api['stage-instances'](channelId).patch({ body, reason });
}
deleteStageInstance(channelId: string, reason?: string) {
return this.session.api['stage-instances'](channelId).delete({ reason });
}
}
export type RESTGetAPIChannelThreadsArchivedOptions = {
type: 'private' | 'public';
} & RESTGetAPIChannelThreadsArchivedQuery;

View File

@ -1,348 +0,0 @@
import type {
APIGuildChannel,
GuildChannelType,
GuildMFALevel,
RESTGetAPIAuditLogQuery,
RESTGetAPIGuildBansQuery,
RESTGetAPIGuildMembersQuery,
RESTGetAPIGuildMembersSearchQuery,
RESTGetAPIGuildPruneCountQuery,
RESTGetAPIGuildScheduledEventQuery,
RESTGetAPIGuildScheduledEventUsersQuery,
RESTGetAPIGuildScheduledEventsQuery,
RESTGetAPIGuildWidgetImageQuery,
RESTPatchAPIAutoModerationRuleJSONBody,
RESTPatchAPICurrentGuildMemberJSONBody,
RESTPatchAPIGuildChannelPositionsJSONBody,
RESTPatchAPIGuildEmojiJSONBody,
RESTPatchAPIGuildJSONBody,
RESTPatchAPIGuildMemberJSONBody,
RESTPatchAPIGuildRoleJSONBody,
RESTPatchAPIGuildRolePositionsJSONBody,
RESTPatchAPIGuildScheduledEventJSONBody,
RESTPatchAPIGuildStickerJSONBody,
RESTPatchAPIGuildTemplateJSONBody,
RESTPatchAPIGuildVoiceStateCurrentMemberJSONBody,
RESTPatchAPIGuildVoiceStateUserJSONBody,
RESTPatchAPIGuildWelcomeScreenJSONBody,
RESTPatchAPIGuildWidgetSettingsJSONBody,
RESTPostAPIAutoModerationRuleJSONBody,
RESTPostAPIGuildChannelJSONBody,
RESTPostAPIGuildEmojiJSONBody,
RESTPostAPIGuildPruneJSONBody,
RESTPostAPIGuildRoleJSONBody,
RESTPostAPIGuildScheduledEventJSONBody,
RESTPostAPIGuildStickerFormDataBody,
RESTPostAPIGuildTemplatesJSONBody,
RESTPostAPIGuildsJSONBody,
RESTPostAPITemplateCreateGuildJSONBody,
RESTPutAPIGuildBanJSONBody,
RESTPutAPIGuildMemberJSONBody
} from '@biscuitland/common';
import type { Session } from '../session';
export class GuildManager {
readonly session!: Session;
constructor(session: Session) {
Object.defineProperty(this, 'session', {
value: session,
writable: false
});
}
get(guildId: string) {
return this.session.api.guilds(guildId).get();
}
create(options: RESTPostAPIGuildsJSONBody) {
return this.session.api.guilds.post({ body: options });
}
delete(guildId: string) {
return this.session.api.guilds(guildId).delete();
}
edit(guildId: string, options: RESTPatchAPIGuildJSONBody) {
return this.session.api.guilds(guildId).patch({ body: options });
}
getChannels(guildId: string) {
return this.session.api.guilds(guildId).channels.get();
}
createChannel<T extends APIGuildChannel<GuildChannelType>>(guildId: string, body: RESTPostAPIGuildChannelJSONBody) {
return this.session.api.guilds(guildId).channels.post({ body }) as Promise<T>;
}
editChannelPositions(guildId: string, body: RESTPatchAPIGuildChannelPositionsJSONBody): Promise<void> {
return this.session.api.guilds(guildId).channels.patch({ body });
}
getThreads(guildId: string) {
return this.session.api.guilds(guildId).threads.active.get();
}
getBans(guildId: string, query: RESTGetAPIGuildBansQuery = {}) {
return this.session.api.guilds(guildId).bans.get({
query
});
}
getBan(guildId: string, userId: string) {
return this.session.api.guilds(guildId).bans(userId).get();
}
createBan(guildId: string, userId: string, body: RESTPutAPIGuildBanJSONBody) {
return this.session.api.guilds(guildId).bans(userId).put({ body });
}
removeBan(guildId: string, userId: string) {
return this.session.api.guilds(guildId).bans(userId).delete();
}
getRoles(guildId: string) {
return this.session.api.guilds(guildId).roles.get();
}
createRole(guildId: string, options: RESTPostAPIGuildRoleJSONBody) {
return this.session.api.guilds(guildId).roles.post({ body: options });
}
editRolePositions(guildId: string, options: RESTPatchAPIGuildRolePositionsJSONBody) {
return this.session.api.guilds(guildId).roles.patch({ body: options });
}
editRole(guildId: string, roleId: string, options: RESTPatchAPIGuildRoleJSONBody) {
return this.session.api.guilds(guildId).roles(roleId).patch({ body: options });
}
deleteRole(guildId: string, roleId: string) {
return this.session.api.guilds(guildId).roles(roleId).delete();
}
editGuildMFALevel(guildId: string, level: GuildMFALevel) {
return this.session.api.guilds(guildId).mfa.post({ body: { level } });
}
getPruneCount(guildId: string, query: RESTGetAPIGuildPruneCountQuery) {
return this.session.api.guilds(guildId).prune.get({
query
});
}
beginGuildPrune(guildId: string, options: RESTPostAPIGuildPruneJSONBody) {
return this.session.api.guilds(guildId).prune.post({ body: options });
}
getVoiceRegions(guildId: string) {
return this.session.api.guilds(guildId).regions.get();
}
getInvites(guildId: string) {
return this.session.api.guilds(guildId).invites.get();
}
getIntegrations(guildId: string) {
return this.session.api.guilds(guildId).integrations.get();
}
deleteIntegration(guildId: string, integrationId: string) {
return this.session.api.guilds(guildId).integrations(integrationId).delete();
}
getWidget(guildId: string) {
return this.session.api.guilds(guildId).widget.get();
}
editWidget(guildId: string, options: RESTPatchAPIGuildWidgetSettingsJSONBody) {
return this.session.api.guilds(guildId).widget.patch({ body: options });
}
getVanityUrl(guildId: string) {
return this.session.api.guilds(guildId)['vanity-url'].get();
}
getWelcomeScreen(guildId: string) {
return this.session.api.guilds(guildId)['welcome-screen'].get();
}
editWelcomeScreen(guildId: string, options: RESTPatchAPIGuildWelcomeScreenJSONBody) {
return this.session.api.guilds(guildId)['welcome-screen'].patch({ body: options });
}
getAuditLog(guildId: string, query?: RESTGetAPIAuditLogQuery) {
return this.session.api.guilds(guildId)['audit-logs'].get({ query });
}
getAutoModerationRules(guildId: string) {
return this.session.api.guilds(guildId)['auto-moderation'].rules.get();
}
getAutoModerationRule(guildId: string, ruleId: string) {
return this.session.api.guilds(guildId)['auto-moderation'].rules(ruleId).get();
}
createAutoModerationRule(guildId: string, body: RESTPostAPIAutoModerationRuleJSONBody, reason?: string) {
return this.session.api.guilds(guildId)['auto-moderation'].rules.post({ body, reason });
}
editAutoModerationRule(guildId: string, ruleId: string, body: RESTPatchAPIAutoModerationRuleJSONBody, reason?: string) {
return this.session.api.guilds(guildId)['auto-moderation'].rules(ruleId).patch({ body, reason });
}
deleteAutoModerationRule(guildId: string, ruleId: string, reason?: string) {
return this.session.api.guilds(guildId)['auto-moderation'].rules(ruleId).delete({ reason });
}
getTemplate(code: string) {
return this.session.api.guilds.templates(code).get();
}
createTemplate(code: string, body: RESTPostAPITemplateCreateGuildJSONBody) {
return this.session.api.guilds.templates(code).post({ body });
}
getWebhooks(guildId: string) {
return this.session.api.guilds(guildId).webhooks.get();
}
getPreview(guildId: string) {
return this.session.api.guilds(guildId).preview.get();
}
getMembers(guildId: string, query?: RESTGetAPIGuildMembersQuery) {
return this.session.api.guilds(guildId).members.get({ query });
}
searchMembers(guildId: string, query?: RESTGetAPIGuildMembersSearchQuery) {
return this.session.api.guilds(guildId).members.search.get({ query });
}
editCurrentMember(guildId: string, body: RESTPatchAPICurrentGuildMemberJSONBody) {
return this.session.api.guilds(guildId).members['@me'].patch({ body });
}
getMember(guildId: string, memberId: string) {
return this.session.api.guilds(guildId).members(memberId).get();
}
addMember(guildId: string, memberId: string, body: RESTPutAPIGuildMemberJSONBody) {
return this.session.api.guilds(guildId).members(memberId).put({ body });
}
editMember(guildId: string, memberId: string, body: RESTPatchAPIGuildMemberJSONBody) {
return this.session.api.guilds(guildId).members(memberId).patch({ body });
}
removeMember(guildId: string, memberId: string) {
return this.session.api.guilds(guildId).members(memberId).delete();
}
addRoleMember(guildId: string, memberId: string, roleId: string) {
return this.session.api.guilds(guildId).members(memberId).roles(roleId).put({});
}
removeRoleMember(guildId: string, memberId: string, roleId: string) {
return this.session.api.guilds(guildId).members(memberId).roles(roleId).delete({});
}
getWidgetJson(guildId: string) {
return this.session.api.guilds(guildId)['widget.json'].get();
}
getWidgetPng(guildId: string, query?: RESTGetAPIGuildWidgetImageQuery) {
return this.session.api.guilds(guildId)['widget.png'].get({ query });
}
getEmojis(guildId: string) {
return this.session.api.guilds(guildId).emojis.get();
}
createEmoji(guildId: string, body: RESTPostAPIGuildEmojiJSONBody) {
return this.session.api.guilds(guildId).emojis.post({ body });
}
getEmoji(guildId: string, emojiId: string) {
return this.session.api.guilds(guildId).emojis(emojiId).get();
}
editEmoji(guildId: string, emojiId: string, body: RESTPatchAPIGuildEmojiJSONBody) {
return this.session.api.guilds(guildId).emojis(emojiId).patch({ body });
}
deleteEmoji(guildId: string, emojiId: string) {
return this.session.api.guilds(guildId).emojis(emojiId).delete();
}
editCurrentVoiceState(guildId: string, body: RESTPatchAPIGuildVoiceStateCurrentMemberJSONBody) {
return this.session.api.guilds(guildId)['voice-states']['@me'].patch({ body });
}
editMemberVoiceState(guildId: string, memberId: string, body: RESTPatchAPIGuildVoiceStateUserJSONBody) {
return this.session.api.guilds(guildId)['voice-states'](memberId).patch({ body });
}
getStickers(guildId: string) {
return this.session.api.guilds(guildId).stickers.get();
}
createSticker(guildId: string, body: RESTPostAPIGuildStickerFormDataBody) {
return this.session.api.guilds(guildId).stickers.post({ body });
}
getSticker(guildId: string, stickerId: string) {
return this.session.api.guilds(guildId).stickers(stickerId).get();
}
editSticker(guildId: string, stickerId: string, body: RESTPatchAPIGuildStickerJSONBody) {
return this.session.api.guilds(guildId).stickers(stickerId).patch({ body });
}
deleteSticker(guildId: string, stickerId: string) {
return this.session.api.guilds(guildId).stickers(stickerId).delete();
}
getScheduledEvents(guildId: string, query?: RESTGetAPIGuildScheduledEventsQuery) {
return this.session.api.guilds(guildId)['scheduled-events'].get({ query });
}
createScheduledEvent(guildId: string, body: RESTPostAPIGuildScheduledEventJSONBody) {
return this.session.api.guilds(guildId)['scheduled-events'].post({ body });
}
getScheduledEvent(guildId: string, scheduledEvent: string, query?: RESTGetAPIGuildScheduledEventQuery) {
return this.session.api.guilds(guildId)['scheduled-events'](scheduledEvent).get({ query });
}
editScheduledEvent(guildId: string, scheduledEvent: string, body: RESTPatchAPIGuildScheduledEventJSONBody) {
return this.session.api.guilds(guildId)['scheduled-events'](scheduledEvent).patch({ body });
}
deleteScheduledEvent(guildId: string, scheduledEvent: string) {
return this.session.api.guilds(guildId)['scheduled-events'](scheduledEvent).delete();
}
getUsersScheduledEvent(guildId: string, scheduledEvent: string, query: RESTGetAPIGuildScheduledEventUsersQuery) {
return this.session.api.guilds(guildId)['scheduled-events'](scheduledEvent).users.get({ query });
}
getGuildTemplates(guildId: string) {
return this.session.api.guilds(guildId).templates.get();
}
createGuildTemplate(guildId: string, body: RESTPostAPIGuildTemplatesJSONBody) {
return this.session.api.guilds(guildId).templates.post({ body });
}
syncGuildTemplate(guildId: string, code: string) {
return this.session.api.guilds(guildId).templates(code).put({});
}
modifyGuildTemaplte(guildId: string, code: string, body: RESTPatchAPIGuildTemplateJSONBody) {
return this.session.api.guilds(guildId).templates(code).patch({ body });
}
deleteCodeTemplate(guildId: string, code: string) {
return this.session.api.guilds(guildId).templates(code).delete();
}
}

View File

@ -1,57 +0,0 @@
import type {
RESTPatchAPIWebhookWithTokenMessageJSONBody,
RESTPostAPIInteractionCallbackJSONBody,
RESTPostAPIInteractionFollowupJSONBody
} from '@biscuitland/common';
import type { RawFile } from '@biscuitland/rest';
import type { Session } from '..';
export class InteractionManager {
readonly session!: Session;
constructor(session: Session) {
Object.defineProperty(this, 'session', {
value: session,
writable: false
});
}
reply<T extends RESTPostAPIInteractionCallbackJSONBody = RESTPostAPIInteractionCallbackJSONBody>(
interactionId: string,
token: string,
body: T,
files?: RawFile[]
) {
return this.session.api.interactions(interactionId)(token).callback.post({
body,
files
});
}
getResponse(applicationId: string, token: string, messageId = '@original') {
return this.session.api.webhooks(applicationId)(token).messages(messageId).get();
}
editResponse(
applicationId: string,
token: string,
messageId: string,
body: RESTPatchAPIWebhookWithTokenMessageJSONBody,
files?: RawFile[]
) {
return this.session.api.webhooks(applicationId)(token).messages(messageId).patch({
body,
files
});
}
deleteResponse(applicationId: string, token: string, messageId = '@original') {
return this.session.api.webhooks(applicationId)(token).messages(messageId).delete();
}
followUp(applicationId: string, token: string, body: RESTPostAPIInteractionFollowupJSONBody, files?: RawFile[]) {
return this.session.api.webhooks(applicationId)(token).post({
body,
files
});
}
}

View File

@ -1,28 +0,0 @@
import type { Session } from '../session';
import { ApplicationManager } from './ApplicationManager';
import { ChannelManager } from './ChannelManager';
import { GuildManager } from './GuildManager';
import { InteractionManager } from './InteractionManager';
import { MemberManager } from './MemberManager';
import { UserManager } from './UserManager';
import { WebhookManager } from './WebhookManager';
export class MainManager {
constructor(private readonly session: Session) {
this.users = new UserManager(this.session);
this.guilds = new GuildManager(this.session);
this.members = new MemberManager(this.session);
this.channels = new ChannelManager(this.session);
this.applications = new ApplicationManager(this.session);
this.interactions = new InteractionManager(this.session);
this.webhooks = new WebhookManager(this.session);
}
users: UserManager;
guilds: GuildManager;
members: MemberManager;
channels: ChannelManager;
applications: ApplicationManager;
interactions: InteractionManager;
webhooks: WebhookManager;
}

View File

@ -1,19 +0,0 @@
import type { APIGuildMember, MakeRequired } from '@biscuitland/common';
import type { ImageOptions, Session } from '../index';
import { formatImageURL } from '../index';
export class MemberManager {
constructor(private readonly session: Session) {}
dynamicAvatarURL({ avatar, guild_id, user }: DynamicMember, { size, format }: ImageOptions = {}): string {
if (avatar?.length) {
return formatImageURL(this.session.cdn.guilds(guild_id).users(user.id).avatars(avatar).get(), size, format);
}
return this.session.managers.users.avatarURL(user, { size, format });
}
}
export type DynamicMember = MakeRequired<APIGuildMember, 'user'> & {
guild_id: string;
};

View File

@ -1,64 +0,0 @@
import type {
APIUser,
RESTGetAPICurrentUserGuildsQuery,
RESTPatchAPICurrentUserJSONBody,
RESTPutAPICurrentUserApplicationRoleConnectionJSONBody
} from '@biscuitland/common';
import type { ImageOptions, Session } from '../index';
import { formatImageURL } from '../index';
export class UserManager {
readonly session!: Session;
constructor(session: Session) {
Object.defineProperty(this, 'session', {
value: session,
writable: false
});
}
get(userId = '@me') {
return this.session.api.users(userId).get();
}
avatarURL(user: APIUser, { size, format }: ImageOptions = {}) {
if (user.avatar?.length) {
return formatImageURL(this.session.cdn.avatars(user.id).get(user.avatar), size, format);
}
return formatImageURL(this.session.cdn.embed.avatars.get(Number(user.discriminator) % 5));
}
createDM(userId: string) {
return this.session.api.users('@me').channels.post({ body: { recipient_id: userId } });
}
editCurrent(body: RESTPatchAPICurrentUserJSONBody) {
return this.session.api.users('@me').patch({
body
});
}
getGuilds(query?: RESTGetAPICurrentUserGuildsQuery) {
return this.session.api.users('@me').guilds.get({ query });
}
getGuildMember(guildId: string) {
return this.session.api.users('@me').guilds(guildId).member.get();
}
leaveGuild(guildId: string) {
return this.session.api.users('@me').guilds(guildId).delete();
}
getConnections() {
return this.session.api.users('@me').connections.get();
}
getRoleConnections(applicationId: string) {
return this.session.api.users('@me').applications(applicationId)['role-connection'].get();
}
updateRoleConnection(applicationId: string, body: RESTPutAPICurrentUserApplicationRoleConnectionJSONBody) {
return this.session.api.users('@me').applications(applicationId)['role-connection'].put({ body });
}
}

View File

@ -1,124 +0,0 @@
import {
Identify,
RESTPatchAPIWebhookJSONBody,
RESTPatchAPIWebhookResult,
RESTPatchAPIWebhookWithTokenJSONBody,
RESTPatchAPIWebhookWithTokenMessageJSONBody,
RESTPatchAPIWebhookWithTokenResult,
RESTPostAPIChannelWebhookJSONBody,
RESTPostAPIWebhookWithTokenGitHubQuery,
RESTPostAPIWebhookWithTokenGitHubWaitResult,
RESTPostAPIWebhookWithTokenJSONBody,
RESTPostAPIWebhookWithTokenQuery,
RESTPostAPIWebhookWithTokenSlackQuery,
RESTPostAPIWebhookWithTokenSlackWaitResult,
RESTPostAPIWebhookWithTokenWaitResult
} from '@biscuitland/common';
import type { Session } from '..';
export class WebhookManager {
readonly session!: Session;
constructor(session: Session) {
Object.defineProperty(this, 'session', {
value: session,
writable: false
});
}
create(channelId: string, body: RESTPostAPIChannelWebhookJSONBody) {
return this.session.api.channels(channelId).webhooks.post({ body });
}
getChannelWebhooks(channelId: string) {
return this.session.api.channels(channelId).webhooks.get();
}
getGuildWebhooks(guildId: string) {
return this.session.api.guilds(guildId).webhooks.get();
}
get(webhookdId: string, token?: string) {
if (!token?.length) return this.session.api.webhooks(webhookdId).get();
return this.session.api.webhooks(webhookdId)(token).get();
}
edit(webhookId: string, body: RESTPatchAPIWebhookJSONBody): Promise<RESTPatchAPIWebhookResult>;
edit(webhookId: string, body: RESTPatchAPIWebhookWithTokenJSONBody, token: string): Promise<RESTPatchAPIWebhookWithTokenResult>;
edit(webhookId: string, body: RESTPatchAPIWebhookJSONBody, token?: string) {
if (!token?.length) {
return this.session.api.webhooks(webhookId).patch({ body });
}
return this.session.api.webhooks(webhookId)(token).patch({ body });
}
delete(webhookdId: string, token?: string) {
if (!token?.length) return this.session.api.webhooks(webhookdId).delete();
return this.session.api.webhooks(webhookdId)(token).delete();
}
execute(
webhookId: string,
token: string,
body: RESTPostAPIWebhookWithTokenJSONBody,
query: RESTPostAPIWebhookWithTokenWaitQuery
): Promise<RESTPostAPIWebhookWithTokenWaitResult>;
execute(webhookId: string, token: string, body: RESTPostAPIWebhookWithTokenJSONBody, query?: RESTPostAPIWebhookWithTokenQuery) {
return this.session.api.webhooks(webhookId)(token).post({
body,
query
});
}
executeGithub(
webhookId: string,
token: string,
body: RESTPostAPIWebhookWithTokenJSONBody,
query: Identify<RESTPostAPIWebhookWithTokenGitHubQuery & { wait: true }>
): Promise<RESTPostAPIWebhookWithTokenGitHubWaitResult>;
executeGithub(
webhookId: string,
token: string,
body: RESTPostAPIWebhookWithTokenJSONBody,
query?: RESTPostAPIWebhookWithTokenGitHubQuery
) {
return this.session.api.webhooks(webhookId)(token).github.post({
body,
query
});
}
executeSlack(
webhookId: string,
token: string,
body: RESTPostAPIWebhookWithTokenJSONBody,
query: Identify<RESTPostAPIWebhookWithTokenSlackQuery & { wait: true }>
): Promise<RESTPostAPIWebhookWithTokenSlackWaitResult>;
executeSlack(webhookId: string, token: string, body: RESTPostAPIWebhookWithTokenJSONBody, query?: RESTPostAPIWebhookWithTokenSlackQuery) {
return this.session.api.webhooks(webhookId)(token).slack.post({
body,
query
});
}
getMessage(webhookId: string, token: string, messageId: string, query?: { thread_id?: string }) {
return this.session.api.webhooks(webhookId)(token).messages(messageId).get({
query
});
}
editMessage(
webhookId: string,
token: string,
messageId: string,
body: RESTPatchAPIWebhookWithTokenMessageJSONBody,
query?: { thread_id?: string }
) {
return this.session.api.webhooks(webhookId)(token).messages(messageId).patch({ query, body });
}
deleteMessage(webhookId: string, token: string, messageId: string, query?: { thread_id?: string }) {
return this.session.api.webhooks(webhookId)(token).messages(messageId).delete({ query });
}
}
export type RESTPostAPIWebhookWithTokenWaitQuery = Identify<RESTPostAPIWebhookWithTokenQuery & { wait: true }>;

View File

@ -1,121 +0,0 @@
import { GatewayIntentBits, Identify, When } from '@biscuitland/common';
import type { BiscuitRESTOptions, CDNRoutes, Routes } from '@biscuitland/rest';
import { BiscuitREST, CDN, Router } from '@biscuitland/rest';
import { GatewayEvents, ShardManager, ShardManagerOptions } from '@biscuitland/ws';
import EventEmitter2 from 'eventemitter2';
import { MainManager, getBotIdFromToken } from '.';
import { Handler, actionHandler } from './events/handler';
export class Session<On extends boolean = boolean> extends EventEmitter2 {
constructor(public options: BiscuitOptions) {
super();
this.rest = this.createRest(this.options.rest);
this.api = new Router(this.rest).createProxy();
this.cdn = CDN.createProxy();
this.managers = new MainManager(this);
}
rest: BiscuitREST;
api: Routes;
cdn: CDNRoutes;
managers: MainManager;
gateway!: When<On, ShardManager>;
private _applicationId?: string;
private _botId?: string;
override on<K extends keyof GatewayEvents>(event: `${K}`, func: Handler[K]): this;
override on<K extends string>(event: `${K}`, func: (...args: unknown[]) => unknown): this {
const ev = super.on(event, func);
// @ts-expect-error Eventemitter can sometimes return a listener
return ev.emitter ? ev.emitter : ev;
}
override off<K extends keyof GatewayEvents>(event: `${K}`, func: Handler[K]): this;
override off<K extends keyof GatewayEvents>(event: `${K}`, func: (...args: unknown[]) => unknown): this {
return super.off(event, func);
}
override once<K extends keyof GatewayEvents>(event: `${K}`, func: Handler[K]): this;
override once<K extends string>(event: `${K}`, func: (...args: unknown[]) => unknown): this {
const ev = super.on(event, func);
// @ts-expect-error Eventemitter can sometimes return a listener
return ev.emitter ? ev.emitter : ev;
}
override emit<K extends keyof GatewayEvents>(event: `${K}`, ...params: Parameters<Handler[K]>): boolean;
override emit<K extends string>(event: `${K}`, ...params: unknown[]): boolean {
return super.emit(event, ...params);
}
set botId(id: string) {
this._botId = id;
}
set applicationId(id: string) {
this._applicationId = id;
}
get botId() {
return this._botId ?? getBotIdFromToken(this.options.token);
}
get applicationId() {
return this._applicationId ?? this.botId;
}
private createRest(rest: any) {
if (!rest) {
return new BiscuitREST({
token: this.options.token,
...this.options.defaultRestOptions
});
}
if (rest instanceof BiscuitREST || rest.cRest) {
return rest;
}
throw new Error('[CORE] REST not found');
}
async start() {
// alias fixed `this` on handlePayload
const ctx = this as Session<true>;
ctx.gateway = new ShardManager({
token: this.options.token,
intents: this.options.intents ?? 0,
info: this.options.defaultGatewayOptions?.info ?? (await this.api.gateway.bot.get()),
async handlePayload(shard, data) {
const { t, d } = data;
if (!(t && d)) return;
// @ts-expect-error
actionHandler([ctx, { t, d }, shard]);
},
...this.options.defaultGatewayOptions
});
ctx.once('READY', (payload) => {
const { user, application } = payload;
this.botId = user.id;
this.applicationId = application.id;
});
await ctx.gateway.spawnShards();
}
async stop() {
this.removeAllListeners();
await this.gateway.disconnectAll();
}
}
export type HandlePayload = Pick<ShardManagerOptions, 'handlePayload'>['handlePayload'];
export interface BiscuitOptions {
token: string;
intents: number | GatewayIntentBits;
rest?: BiscuitREST;
defaultRestOptions?: Partial<BiscuitRESTOptions>;
defaultGatewayOptions?: Identify<Partial<Omit<ShardManagerOptions, 'token' | 'intents'>>>;
}

View File

@ -1,18 +0,0 @@
import type { ImageFormat } from '@biscuitland/common';
export type EditNickname = { nick?: string; reason?: string };
/**
* @link https://discord.com/developers/docs/reference#image-formatting
*/
export type ImageSize = 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096;
export type ImageOptions = {
format?: ImageFormat;
size?: ImageSize;
};
export enum ThreadTypes {
AnnouncementThread = 10,
PublicThread = 11,
PrivateThread = 12
}

View File

@ -1,60 +0,0 @@
import { ReplaceRegex } from '@biscuitland/common';
import { DiscordEpoch } from '@biscuitland/common';
import { ImageFormat } from '@biscuitland/common';
import type { ImageSize } from './types';
/**
* Convert a timestamp to a snowflake.
* @param timestamp The timestamp to convert.
* @returns The snowflake.
*/
export function snowflakeToTimestamp(id: string): number {
return (Number(id) >> 22) + DiscordEpoch;
}
/**
* Format an image URL.
* @param url The URL to format.
* @param size The size of the image.
* @param format The format of the image.
* @returns The formatted URL.
*/
export function formatImageURL(url: string, size: ImageSize = 128, format?: ImageFormat): string {
return `${url}.${format ?? (url.includes('/a_') ? 'gif' : 'jpg')}?size=${size}`;
}
/**
* Get the bot ID from a token.
* @param token The token to get the bot ID from.
* @returns The bot ID.
* @warning Discord staff has mentioned this may not be stable forever xd.
*/
export function getBotIdFromToken(token: string): string {
return Buffer.from(token.split('.')[0], 'base64').toString('ascii');
}
/**
* Convert an object to a URLSearchParams object.
* @param obj The object to convert.
* @returns The URLSearchParams object.
*/
export function objectToParams(obj: object): URLSearchParams {
const query = new URLSearchParams();
for (const [key, value] of Object.entries(obj)) {
if (!value) continue;
query.append(ReplaceRegex.snake(key), String(value));
}
return query;
}
/**
* Get the channel link from a channel ID and guild ID.
*
* @param channelId The channel ID.
* @param guildId The guild ID.
* @returns The channel link.
*/
export function channelLink(channelId: string, guildId?: string) {
return `https://discord.com/channels/${guildId ?? '@me'}/${channelId}`;
}

View File

@ -1,7 +0,0 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist"
},
"include": ["src/**/*"]
}

View File

@ -1,12 +0,0 @@
import { defineConfig } from 'tsup';
const isProduction = process.env.NODE_ENV === 'production';
export default defineConfig({
clean: true,
dts: true,
entry: ['src/index.ts'],
format: ['cjs', 'esm'],
minify: isProduction,
sourcemap: false
});

View File

@ -1,52 +0,0 @@
# @biscuitland/helpers
## 3.0.14
### Patch Changes
- new changes
- new changes
## 3.0.11
### Patch Changes
- Updated dependencies
- @biscuitland/common@0.0.8
## 3.0.10
### Patch Changes
- Updated dependencies
- @biscuitland/common@0.0.7
## 3.0.9
### Patch Changes
- I meessed up
- Updated dependencies
- @biscuitland/common@0.0.6
## 3.0.8
### Patch Changes
- fix: logger on every module
- Updated dependencies
- @biscuitland/common@0.0.5
## 3.0.7
### Patch Changes
- fix mixer
## 3.0.6
### Patch Changes
- first 3.0.\* without bugs
- Updated dependencies
- @biscuitland/common@0.0.4

View File

@ -1,21 +0,0 @@
# @biscuitland/helpers
## Most importantly, helpers is:
A collection of builders to make your life easier, not built into the core library due to performance concerns.
[<img src="https://img.shields.io/badge/GitHub-100000?style=for-the-badge&logo=github&logoColor=white">](https://github.com/oasisjs/biscuit)
[<img src="https://img.shields.io/badge/Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white">](https://discord.gg/XNw2RZFzaP)
<img align="right" src="https://raw.githubusercontent.com/oasisjs/biscuit/main/assets/icon.svg" alt="biscuit"/>
## Install (for [node18](https://nodejs.org/en/download/))
```sh-session
npm install @biscuitland/helpers
yarn add @biscuitland/helpers
```
## Links
* [Website](https://biscuitjs.com/)
* [Documentation](https://docs.biscuitjs.com/)
* [Discord](https://discord.gg/XNw2RZFzaP)
* [core](https://www.npmjs.com/package/@biscuitland/core) | [rest](https://www.npmjs.com/package/@biscuitland/rest) | [ws](https://www.npmjs.com/package/@biscuitland/ws)

View File

@ -1,76 +0,0 @@
{
"name": "@biscuitland/helpers",
"version": "3.0.14",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"dist/**"
],
"scripts": {
"build": "tsup",
"clean": "rm -rf dist && rm -rf .turbo",
"dev": "tsup --watch"
},
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.mjs"
},
"require": "./dist/index.js"
}
},
"dependencies": {
"@biscuitland/common": "^0.0.10",
"ts-mixer": "^6.0.3"
},
"devDependencies": {
"@types/node": "^20.0.0",
"tsup": "^7.0.0"
},
"license": "Apache-2.0",
"author": "Yuzuru <yuzuru@programmer.net>",
"contributors": [
{
"name": "Yuzuru",
"url": "https://github.com/yuzudev",
"author": true
},
{
"name": "miia",
"url": "https://github.com/dragurimu"
},
{
"name": "n128",
"url": "https://github.com/nicolito128"
},
{
"name": "socram03",
"url": "https://github.com/socram03"
},
{
"name": "Drylozu",
"url": "https://github.com/Drylozu"
}
],
"homepage": "https://biscuitjs.com",
"repository": {
"type": "git",
"url": "git+https://github.com/oasisjs/biscuit.git"
},
"bugs": {
"url": "https://github.com/oasisjs/biscuit"
},
"keywords": [
"api",
"discord",
"bots",
"typescript",
"botdev"
],
"publishConfig": {
"access": "public"
}
}

View File

@ -1,79 +0,0 @@
import { EventEmitter } from 'node:events';
import { MakeRequired, Options } from '@biscuitland/common';
import { Handler, type Session } from '@biscuitland/core';
import { GatewayEvents } from '@biscuitland/ws';
interface CollectorOptions<E extends keyof GatewayEvents> {
event: `${E}`;
filter?: (...args: Parameters<Handler[E]>) => unknown;
max?: number;
time?: number;
idle?: number;
}
export const DEFAULT_OPTIONS = {
filter: () => true,
max: -1
};
export enum CollectorStatus {
Idle = 0,
Started = 1,
Ended = 2
}
export class EventCollector<E extends keyof GatewayEvents> extends EventEmitter {
collected = new Set<Parameters<Handler[E]>[0]>();
status: CollectorStatus = CollectorStatus.Idle;
options: MakeRequired<CollectorOptions<E>, 'filter' | 'max'>;
private timeout: NodeJS.Timeout | null = null;
constructor(readonly session: Session, rawOptions: CollectorOptions<E>) {
super();
this.options = Options(DEFAULT_OPTIONS, rawOptions);
}
start() {
this.session.setMaxListeners(this.session.getMaxListeners() + 1);
this.session.on(this.options.event, (...args: unknown[]) => this.collect(...(args as Parameters<Handler[E]>)));
this.timeout = setTimeout(() => this.stop('time'), this.options.idle ?? this.options.time);
}
private collect(...args: Parameters<Handler[E]>) {
if (this.options.filter?.(...args)) {
this.collected.add(args[0]);
this.emit('collect', ...args);
}
if (this.options.idle) {
if (this.timeout) clearTimeout(this.timeout);
this.timeout = setTimeout(() => this.stop('time'), this.options.idle);
}
if (this.collected.size >= this.options.max!) this.stop('max');
}
stop(reason = 'User stopped') {
if (this.status === CollectorStatus.Ended) return;
if (this.timeout) clearTimeout(this.timeout);
this.session.removeListener(this.options.event, (...args: unknown[]) => this.collect(...(args as Parameters<Handler[E]>)));
this.session.setMaxListeners(this.session.getMaxListeners() - 1);
this.status = CollectorStatus.Ended;
this.emit('end', reason, this.collected);
}
on(event: 'collect', listener: (...args: Parameters<Handler[E]>) => unknown): this;
on(event: 'end', listener: (reason: string | null | undefined, collected: Set<Parameters<Handler[E]>[0]>) => void): this;
on(event: string, listener: unknown): this {
return super.on(event, listener as () => unknown);
}
once(event: 'collect', listener: (...args: Parameters<Handler[E]>) => unknown): this;
once(event: 'end', listener: (reason: string | null | undefined, collected: Set<Parameters<Handler[E]>[0]>) => void): this;
once(event: string, listener: unknown): this {
return super.once(event, listener as () => unknown);
}
}

View File

@ -1,62 +0,0 @@
import { APIEmbed, APIEmbedAuthor, APIEmbedField, APIEmbedFooter, ObjectToLower, TypeArray, toSnakeCase } from '@biscuitland/common';
export class MessageEmbed {
constructor(public data: Partial<APIEmbed> = {}) {
if (!data.fields) this.data.fields = [];
}
setAuthor(author: ObjectToLower<APIEmbedAuthor>): this {
this.data.author = toSnakeCase(author);
return this;
}
// TODO: Color resolve
setColor(color: number): this {
this.data.color = color;
return this;
}
setDescription(desc: string): this {
this.data.description = desc;
return this;
}
addFields(field: TypeArray<APIEmbedField>): this {
this.data.fields = this.data.fields!.concat(field);
return this;
}
setFields(fields: APIEmbedField[]): this {
this.data.fields = fields;
return this;
}
setFooter(footer: ObjectToLower<APIEmbedFooter>): this {
this.data.footer = toSnakeCase(footer);
return this;
}
setImage(url: string): this {
this.data.image = { url };
return this;
}
setTimestamp(time: string | number | Date = Date.now()): this {
this.data.timestamp = new Date(time).toISOString();
return this;
}
setTitle(title: string): this {
this.data.title = title;
return this;
}
setURL(url: string): this {
this.data.url = url;
return this;
}
toJSON(): APIEmbed {
return { ...this.data };
}
}

View File

@ -1,132 +0,0 @@
import { PermissionFlagsBits } from '@biscuitland/common';
export type PermissionsStrings = keyof typeof PermissionFlagsBits;
export type PermissionResolvable = bigint | PermissionsStrings | PermissionsStrings[] | PermissionsStrings | PermissionsStrings[];
export class Permissions {
/** Stores a reference to BitwisePermissionFlags */
static Flags = PermissionFlagsBits;
/** Falsy; Stores the lack of permissions*/
static None = 0n;
/** Stores all entity permissions */
bitfield: bigint;
/**
* Wheter to grant all other permissions to the administrator
* **Not to get confused with Permissions#admin**
*/
__admin__ = true;
constructor(bitfield: PermissionResolvable) {
this.bitfield = Permissions.resolve(bitfield);
}
/** Wheter the bitfield has the administrator flag */
get admin(): boolean {
return this.has(Permissions.Flags.Administrator);
}
get array(): PermissionsStrings[] {
// unsafe cast, do not edit
const permissions = Object.keys(Permissions.Flags) as PermissionsStrings[];
return permissions.filter((bit) => this.has(bit));
}
add(...bits: PermissionResolvable[]): this {
let reduced = 0n;
for (const bit of bits) {
reduced |= Permissions.resolve(bit);
}
this.bitfield |= reduced;
return this;
}
remove(...bits: PermissionResolvable[]): this {
let reduced = 0n;
for (const bit of bits) {
reduced |= Permissions.resolve(bit);
}
this.bitfield &= ~reduced;
return this;
}
has(bit: PermissionResolvable): boolean {
const bbit = Permissions.resolve(bit);
if (this.__admin__ && this.bitfield & BigInt(Permissions.Flags.Administrator)) {
return true;
}
return (this.bitfield & bbit) === bbit;
}
any(bit: PermissionResolvable): boolean {
const bbit = Permissions.resolve(bit);
if (this.__admin__ && this.bitfield & BigInt(Permissions.Flags.Administrator)) {
return true;
}
return (this.bitfield & bbit) !== Permissions.None;
}
equals(bit: PermissionResolvable): boolean {
return !!(this.bitfield & Permissions.resolve(bit));
}
/** Gets all permissions */
static get All(): bigint {
let reduced = 0n;
for (const key in PermissionFlagsBits) {
const perm = PermissionFlagsBits[key];
reduced = reduced | perm;
}
return reduced;
}
static resolve(bit: PermissionResolvable): bigint {
switch (typeof bit) {
case 'bigint':
return bit;
case 'number':
return BigInt(bit);
case 'string':
return BigInt(Permissions.Flags[bit]);
case 'object':
return Permissions.resolve(
bit
.map((p) => (typeof p === 'string' ? BigInt(Permissions.Flags[p]) : BigInt(p)))
.reduce((acc, cur) => acc | cur, Permissions.None)
);
default:
throw new TypeError(`Cannot resolve permission: ${bit}`);
}
}
static sum(permissions: (bigint | number)[]) {
return permissions.reduce((y, x) => BigInt(y) | BigInt(x), Permissions.None);
}
static reduce(permissions: PermissionResolvable[]): Permissions {
const solved = permissions.map(Permissions.resolve);
return new Permissions(solved.reduce((y, x) => y | x, Permissions.None));
}
*[Symbol.iterator]() {
yield* this.array;
}
valueOf() {
return this.bitfield;
}
toJSON(): { fields: string[] } {
const fields = Object.keys(Permissions.Flags).filter((bit) => typeof bit === 'number' && this.has(bit));
return { fields };
}
}

View File

@ -1,42 +0,0 @@
import { APIMessageActionRowComponent, APIModalActionRowComponent, ComponentType } from '@biscuitland/common';
import {
ChannelSelectMenu,
MentionableSelectMenu,
MessageButton,
ModalTextInput,
RoleSelectMenu,
StringSelectMenu,
UserSelectMenu
} from './components';
import { BaseComponent } from './components/BaseComponent';
export function createComponent(data: APIMessageActionRowComponent): HelperComponents;
export function createComponent(data: APIModalActionRowComponent): HelperComponents;
export function createComponent(data: HelperComponents): HelperComponents;
export function createComponent(data: HelperComponents | APIMessageActionRowComponent | APIModalActionRowComponent): HelperComponents {
if (data instanceof BaseComponent) {
return data;
}
switch (data.type) {
case ComponentType.Button:
return new MessageButton(data);
case ComponentType.StringSelect:
return new StringSelectMenu(data);
case ComponentType.TextInput:
return new ModalTextInput(data);
case ComponentType.UserSelect:
return new UserSelectMenu(data);
case ComponentType.RoleSelect:
return new RoleSelectMenu(data);
case ComponentType.MentionableSelect:
return new MentionableSelectMenu(data);
case ComponentType.ChannelSelect:
return new ChannelSelectMenu(data);
}
}
export type OptionValuesLength = { max: number; min: number };
export type MessageSelectMenus = RoleSelectMenu | UserSelectMenu | StringSelectMenu | ChannelSelectMenu | MentionableSelectMenu;
export type MessageComponents = MessageButton | MessageSelectMenus;
export type HelperComponents = MessageComponents | ModalTextInput;

View File

@ -1,43 +0,0 @@
import { ApplicationCommandType, LocalizationMap, RESTPostAPIContextMenuApplicationCommandsJSONBody } from '@biscuitland/common';
import { PermissionResolvable, Permissions } from '../../Permissions';
export type ContextCommandType = ApplicationCommandType.Message | ApplicationCommandType.User;
export class ContextCommand {
name: string = undefined!;
name_localizations?: LocalizationMap;
type: ContextCommandType = undefined!;
default_permission: boolean | undefined = undefined;
default_member_permissions: string | undefined = undefined;
dm_permission: boolean | undefined = undefined;
setName(name: string): this {
this.name = name;
return this;
}
setType(type: ContextCommandType) {
this.type = type;
return this;
}
addNameLocalizations(locals: LocalizationMap): this {
this.name_localizations = locals;
Reflect;
return this;
}
setDMPermission(value = true): this {
this.dm_permission = value;
return this;
}
setDefautlMemberPermissions(permissions: PermissionResolvable[]): this {
this.default_member_permissions = Permissions.reduce(permissions).bitfield.toString();
return this;
}
toJSON(): RESTPostAPIContextMenuApplicationCommandsJSONBody {
return { ...this };
}
}

View File

@ -1,3 +0,0 @@
export * from './contextMenu/ContextCommand';
export * from './slash/SlashCommand';
export * from './slash/SlashCommandOption';

View File

@ -1,53 +0,0 @@
import { ApplicationCommandType, RESTPostAPIChatInputApplicationCommandsJSONBody } from '@biscuitland/common';
import { Mixin } from 'ts-mixer';
import { PermissionResolvable, Permissions } from '../../Permissions';
import { AllSlashOptions, SlashSubcommandGroupOption, SlashSubcommandOption } from './SlashCommandOption';
class SlashCommandB {
constructor(public data: Partial<RESTPostAPIChatInputApplicationCommandsJSONBody> = {}) {}
setDMPermission(value = true): this {
this.data.dm_permission = value;
return this;
}
setNSFW(value = true): this {
this.data.nsfw = value;
return this;
}
setDefautlMemberPermissions(permissions: PermissionResolvable[]): this {
this.data.default_member_permissions = Permissions.reduce(permissions).bitfield.toString();
return this;
}
addSubcommandGroup(fn: (option: SlashSubcommandGroupOption) => SlashSubcommandGroupOption): this {
const option = fn(new SlashSubcommandGroupOption());
this.addRawOption(option.toJSON());
return this;
}
addSubcommand(fn: (option: SlashSubcommandOption) => SlashSubcommandOption): this {
const option = fn(new SlashSubcommandOption());
this.addRawOption(option.toJSON());
return this;
}
addRawOption(option: ReturnType<AllSlashOptions['toJSON']>) {
this.data.options ??= [];
// @ts-expect-error discord-api-types bad typing, again
this.data.options.push(option);
}
toJSON(): RESTPostAPIChatInputApplicationCommandsJSONBody {
return {
...this.data,
type: ApplicationCommandType.ChatInput
} as RESTPostAPIChatInputApplicationCommandsJSONBody & {
type: ApplicationCommandType.ChatInput;
};
}
}
export const SlashCommand = Mixin(SlashCommandB, SlashSubcommandOption);
export type SlashCommand = InstanceType<typeof SlashCommand>;

View File

@ -1,340 +0,0 @@
import {
APIApplicationCommandAttachmentOption,
APIApplicationCommandBooleanOption,
APIApplicationCommandChannelOption,
APIApplicationCommandIntegerOption as AACIO,
APIApplicationCommandMentionableOption,
APIApplicationCommandNumberOption as AACNO,
APIApplicationCommandOption,
APIApplicationCommandOptionBase,
APIApplicationCommandOptionChoice,
APIApplicationCommandRoleOption,
APIApplicationCommandStringOption as AACSO,
APIApplicationCommandSubcommandGroupOption as AACSGO,
APIApplicationCommandSubcommandOption as AACSCO,
APIApplicationCommandUserOption,
ApplicationCommandOptionType,
ChannelType,
LocalizationMap,
RestToKeys,
TypeArray,
When
} from '@biscuitland/common';
import { OptionValuesLength } from '../../';
export type SlashBaseOptionTypes =
| Exclude<APIApplicationCommandOption, AACSO | AACNO | AACIO | AACSCO>
| APIApplicationCommandStringOption
| APIApplicationCommandNumberOption
| APIApplicationCommandIntegerOption
| APIApplicationCommandSubcommandOption;
export type ApplicationCommandBasicOptions =
| APIApplicationCommandAttachmentOption
| APIApplicationCommandChannelOption
| APIApplicationCommandIntegerOption
| APIApplicationCommandMentionableOption
| APIApplicationCommandNumberOption
| APIApplicationCommandStringOption
| APIApplicationCommandRoleOption
| APIApplicationCommandBooleanOption
| APIApplicationCommandUserOption;
export abstract class SlashBaseOption<DataType extends SlashBaseOptionTypes> {
constructor(public data: Partial<DataType> = {}) {}
setName(name: string): this {
this.data.name = name;
return this;
}
setDesciption(desc: string): this {
this.data.description = desc;
return this;
}
addLocalizations(locals: RestToKeys<[LocalizationMap, 'name', 'description']>): this {
this.data.name_localizations = locals.name;
this.data.description_localizations = locals.description;
return this;
}
toJSON(): DataType {
return { ...this.data } as DataType;
}
}
export type SlashRequiredOptionTypes = Exclude<SlashBaseOptionTypes, AACSGO | AACSGO>;
export class SlashRequiredOption<DataType extends SlashRequiredOptionTypes> extends SlashBaseOption<DataType> {
setRequired(required = true): this {
this.data.required = required;
return this;
}
}
/**
* Temporal fix type
* I didn't find the correct way to set this with discord-api-types
* Author: socram03
*/
export interface APIApplicationCommandStringOption<AC extends boolean = boolean>
extends APIApplicationCommandOptionBase<ApplicationCommandOptionType.String> {
/**
* For option type `STRING`, the minimum allowed length (minimum of `0`, maximum of `6000`).
*/
min_length?: number;
/**
* For option type `STRING`, the maximum allowed length (minimum of `1`, maximum of `6000`).
*/
max_length?: number;
autocomplete: When<AC, false | undefined, true>;
choices: When<AC, APIApplicationCommandOptionChoice<string>[], never>;
}
export class SlashStringOption<AC extends boolean = boolean> extends SlashRequiredOption<APIApplicationCommandStringOption<AC>> {
constructor(data: Partial<APIApplicationCommandStringOption<AC>> = {}) {
super({ ...data, type: ApplicationCommandOptionType.String });
}
addChoices(choices: TypeArray<APIApplicationCommandOptionChoice<string>>): SlashStringOption<true> {
const ctx = this as SlashStringOption<true>;
ctx.data.choices ??= [];
ctx.data.choices = ctx.data.choices!.concat(choices);
return ctx;
}
setAutocomplete(auto = true): SlashStringOption<typeof auto> {
const ctx = this as SlashStringOption<typeof auto>;
ctx.data.autocomplete = auto;
return ctx;
}
setLength({ min, max }: OptionValuesLength): this {
this.data.min_length = min;
this.data.max_length = max;
return this;
}
}
/**
* Temporal fix type
* I didn't find the correct way to set this with discord-api-types
* Author: socram03
*/
interface APIApplicationCommandNumberOption<AC extends boolean = boolean>
extends APIApplicationCommandOptionBase<ApplicationCommandOptionType.Number> {
/**
* If the option is an `INTEGER` or `NUMBER` type, the minimum value permitted.
*/
min_value?: number;
/**
* If the option is an `INTEGER` or `NUMBER` type, the maximum value permitted.
*/
max_value?: number;
autocomplete: When<AC, false | undefined, true>;
choices: When<AC, APIApplicationCommandOptionChoice<number>[], never>;
}
export class SlashNumberOption<AC extends boolean = boolean> extends SlashRequiredOption<APIApplicationCommandNumberOption<AC>> {
constructor(data: Partial<APIApplicationCommandNumberOption<AC>> = {}) {
super({ ...data, type: ApplicationCommandOptionType.Number });
}
addChoices(choices: TypeArray<APIApplicationCommandOptionChoice<number>>): SlashNumberOption<true> {
const ctx = this as SlashNumberOption<true>;
ctx.data.choices ??= [];
ctx.data.choices = ctx.data.choices.concat(choices);
return ctx;
}
setValueRange({ min, max }: OptionValuesLength): this {
this.data.max_value = max;
this.data.min_value = min;
return this;
}
setAutocomplete(auto = true): SlashNumberOption<typeof auto> {
const ctx = this as SlashNumberOption<typeof auto>;
ctx.data.autocomplete = auto;
return ctx;
}
}
/**
* Temporal fix type
* I didn't find the correct way to set this with discord-api-types
* Author: socram03
*/
interface APIApplicationCommandIntegerOption<AC extends boolean = boolean>
extends APIApplicationCommandOptionBase<ApplicationCommandOptionType.Integer> {
/**
* If the option is an `INTEGER` or `NUMBER` type, the minimum value permitted.
*/
min_value?: number;
/**
* If the option is an `INTEGER` or `NUMBER` type, the maximum value permitted.
*/
max_value?: number;
autocomplete: When<AC, false | undefined, true>;
choices: When<AC, APIApplicationCommandOptionChoice<number>[], never>;
}
export class SlashIntegerOption<AC extends boolean = boolean> extends SlashRequiredOption<APIApplicationCommandIntegerOption<AC>> {
constructor(data: Partial<APIApplicationCommandIntegerOption<AC>> = {}) {
super({ ...data, type: ApplicationCommandOptionType.Integer });
}
}
export class SlashUserOption extends SlashRequiredOption<APIApplicationCommandUserOption> {
constructor(data: Partial<APIApplicationCommandUserOption> = {}) {
super({ ...data, type: ApplicationCommandOptionType.User });
}
}
export type SlashChannelOptionChannelTypes = Exclude<ChannelType, ChannelType.DM | ChannelType.GroupDM>;
export class SlashChannelOption extends SlashRequiredOption<APIApplicationCommandChannelOption> {
constructor(data: Partial<APIApplicationCommandChannelOption> = {}) {
super({ ...data, type: ApplicationCommandOptionType.Channel });
}
setChannelTypes(types: SlashChannelOptionChannelTypes[]): this {
this.data.channel_types = types;
return this;
}
}
export class SlashRoleOption extends SlashRequiredOption<APIApplicationCommandRoleOption> {
constructor(data: Partial<APIApplicationCommandRoleOption> = {}) {
super({ ...data, type: ApplicationCommandOptionType.Role });
}
}
export class SlashMentionableOption extends SlashRequiredOption<APIApplicationCommandMentionableOption> {
constructor(data: Partial<APIApplicationCommandMentionableOption> = {}) {
super({ ...data, type: ApplicationCommandOptionType.Mentionable });
}
}
export class SlashAttachmentOption extends SlashRequiredOption<APIApplicationCommandAttachmentOption> {
constructor(data: Partial<APIApplicationCommandAttachmentOption> = {}) {
super({ ...data, type: ApplicationCommandOptionType.Attachment });
}
}
export class SlashBooleanOption extends SlashRequiredOption<APIApplicationCommandBooleanOption> {
constructor(data: Partial<APIApplicationCommandBooleanOption> = {}) {
super({ ...data, type: ApplicationCommandOptionType.Boolean });
}
}
export type BasicSlashOptions =
| SlashStringOption
| SlashAttachmentOption
| SlashChannelOption
| SlashIntegerOption
| SlashNumberOption
| SlashRoleOption
| SlashMentionableOption
| SlashUserOption
| SlashBooleanOption;
export type APIApplicationCommandSubcommandOption = AACSCO & {
options?: ApplicationCommandBasicOptions[];
};
export class SlashSubcommandOption extends SlashBaseOption<APIApplicationCommandSubcommandOption> {
constructor(data: Partial<APIApplicationCommandSubcommandOption> = {}) {
super({ ...data, type: ApplicationCommandOptionType.Subcommand });
}
addStringOption(fn: (option: SlashStringOption) => SlashStringOption): this {
const option = fn(new SlashStringOption());
this.addRawOption(option.toJSON());
return this;
}
addNumberOption(fn: (option: SlashNumberOption) => SlashNumberOption): this {
const option = fn(new SlashNumberOption());
this.addRawOption(option.toJSON());
return this;
}
addIntegerOption(fn: (option: SlashIntegerOption) => SlashIntegerOption): this {
const option = fn(new SlashIntegerOption());
this.addRawOption(option.toJSON());
return this;
}
addChannelOption(fn: (option: SlashChannelOption) => SlashChannelOption): this {
const option = fn(new SlashChannelOption());
this.addRawOption(option.toJSON());
return this;
}
addUserOption(fn: (option: SlashUserOption) => SlashUserOption): this {
const option = fn(new SlashUserOption());
this.addRawOption(option.toJSON());
return this;
}
addRoleOption(fn: (option: SlashRoleOption) => SlashRoleOption): this {
const option = fn(new SlashRoleOption());
this.addRawOption(option.toJSON());
return this;
}
addMentionableOption(fn: (option: SlashMentionableOption) => SlashMentionableOption): this {
const option = fn(new SlashMentionableOption());
this.addRawOption(option.toJSON());
return this;
}
addAttachmentOption(fn: (option: SlashAttachmentOption) => SlashAttachmentOption): this {
const option = fn(new SlashAttachmentOption());
this.addRawOption(option.toJSON());
return this;
}
addBooleanOption(fn: (option: SlashBooleanOption) => SlashBooleanOption): this {
const option = fn(new SlashBooleanOption());
this.addRawOption(option.toJSON());
return this;
}
addRawOption(option: ApplicationCommandBasicOptions) {
this.data.options ??= [];
this.data.options.push(option);
}
}
export type APIApplicationCommandSubcommandGroupOption = AACSGO & {
options?: APIApplicationCommandSubcommandOption[];
};
export type AllSlashOptions = BasicSlashOptions | SlashSubcommandGroupOption | SlashSubcommandOption;
export class SlashSubcommandGroupOption extends SlashBaseOption<APIApplicationCommandSubcommandGroupOption> {
constructor(data: Partial<APIApplicationCommandSubcommandGroupOption> = {}) {
if (!data.options) data.options = [];
super({ ...data, type: ApplicationCommandOptionType.SubcommandGroup });
}
addSubCommand(fn: (option: SlashSubcommandOption) => SlashSubcommandOption): this {
const option = fn(new SlashSubcommandOption());
this.addRawOption(option.toJSON());
return this;
}
addRawOption(option: ReturnType<SlashSubcommandOption['toJSON']>) {
this.data.options ??= [];
this.data.options.push(option);
}
}

View File

@ -1,28 +0,0 @@
import { APIActionRowComponent, APIMessageActionRowComponent, ComponentType, TypeArray } from '@biscuitland/common';
import { MessageComponents, createComponent } from '../Utils';
import { BaseComponent } from './BaseComponent';
export class MessageActionRow<T extends MessageComponents> extends BaseComponent<APIActionRowComponent<APIMessageActionRowComponent>> {
constructor({ components, ...data }: Partial<APIActionRowComponent<APIMessageActionRowComponent>> = {}) {
super({ ...data, type: ComponentType.ActionRow });
this.components = (components?.map(createComponent) ?? []) as T[];
}
components: T[];
addComponents(component: TypeArray<T>): this {
this.components = this.components.concat(component);
return this;
}
setComponents(component: T[]): this {
this.components = [...component];
return this;
}
toJSON(): APIActionRowComponent<APIMessageActionRowComponent> {
return {
...this.data,
components: this.components.map((c) => c.toJSON())
} as APIActionRowComponent<ReturnType<T['toJSON']>>;
}
}

View File

@ -1,9 +0,0 @@
import { APIBaseComponent, ComponentType } from '@biscuitland/common';
export abstract class BaseComponent<TYPE extends Partial<APIBaseComponent<ComponentType>> = APIBaseComponent<ComponentType>,> {
constructor(public data: Partial<TYPE>) {}
toJSON(): TYPE {
return { ...this.data } as TYPE;
}
}

View File

@ -1,49 +0,0 @@
import { APIButtonComponentBase, APIMessageComponentEmoji, ButtonStyle, ComponentType, When } from '@biscuitland/common';
import { BaseComponent } from './BaseComponent';
export type ButtonStylesForID = Exclude<ButtonStyle, ButtonStyle.Link>;
export interface APIButtonComponent<WI extends boolean = boolean>
extends APIButtonComponentBase<When<WI, ButtonStylesForID, ButtonStyle.Link>> {
url: When<WI, never, string>;
custom_id: When<WI, string, never>;
}
export class MessageButton<WI extends boolean = boolean> extends BaseComponent<APIButtonComponent<WI>> {
constructor(data: Partial<APIButtonComponent<WI>> = {}) {
super({ ...data, type: ComponentType.Button });
}
setLabel(label: string): this {
this.data.label = label;
return this;
}
setEmoji(emoji: APIMessageComponentEmoji): this {
this.data.emoji = emoji;
return this;
}
setDisabled(disabled = true): this {
this.data.disabled = disabled;
return this;
}
setURL(url: string): MessageButton<false> {
const ctx = this as MessageButton<false>;
ctx.data.url = url;
return ctx;
}
setStyle(style: When<WI, ButtonStylesForID, ButtonStyle.Link>): this {
this.data.style = style;
return this;
}
setCustomId(id: string): MessageButton<true> {
const ctx = this as MessageButton<true>;
ctx.data.custom_id = id;
return ctx;
}
}

View File

@ -1,118 +0,0 @@
import {
APIChannelSelectComponent,
APIMentionableSelectComponent,
APIMessageComponentEmoji,
APIRoleSelectComponent,
APISelectMenuComponent,
APISelectMenuOption,
APIStringSelectComponent,
APIUserSelectComponent,
ChannelType,
ComponentType,
TypeArray
} from '@biscuitland/common';
import { OptionValuesLength } from '..';
import { BaseComponent } from './BaseComponent';
class SelectMenu<Select extends APISelectMenuComponent = APISelectMenuComponent,> extends BaseComponent<Select> {
setCustomId(id: string): this {
this.data.custom_id = id;
return this;
}
setPlaceholder(placeholder: string): this {
this.data.placeholder = placeholder;
return this;
}
setValuesLength({ max, min }: Partial<OptionValuesLength>): this {
this.data.max_values = max;
this.data.min_values = min;
return this;
}
setDisabled(disabled = true): this {
this.data.disabled = disabled;
return this;
}
}
export class UserSelectMenu extends SelectMenu<APIUserSelectComponent> {
constructor(data: Partial<APIUserSelectComponent> = {}) {
super({ ...data, type: ComponentType.UserSelect });
}
}
export class RoleSelectMenu extends SelectMenu<APIRoleSelectComponent> {
constructor(data: Partial<APIRoleSelectComponent> = {}) {
super({ ...data, type: ComponentType.RoleSelect });
}
}
export class MentionableSelectMenu extends SelectMenu<APIMentionableSelectComponent> {
constructor(data: Partial<APIMentionableSelectComponent> = {}) {
super({ ...data, type: ComponentType.MentionableSelect });
}
}
export class ChannelSelectMenu extends SelectMenu<APIChannelSelectComponent> {
constructor(data: Partial<APIChannelSelectComponent> = {}) {
super({ ...data, type: ComponentType.ChannelSelect });
}
setChannelTypes(types: ChannelType[]): this {
this.data.channel_types = types;
return this;
}
}
export class StringSelectMenu extends SelectMenu<APIStringSelectComponent> {
constructor(data: Partial<APIStringSelectComponent> = {}) {
super({ ...data, type: ComponentType.StringSelect });
}
addOption(option: TypeArray<APISelectMenuOption>): this {
this.data.options ??= [];
this.data.options = this.data.options.concat(option);
return this;
}
setOptions(options: APISelectMenuOption[]): this {
this.data.options = options;
return this;
}
}
export class StringSelectOption {
// biome-ignore lint/nursery/noEmptyBlockStatements: <explanation>
constructor(public data: Partial<APISelectMenuOption> = {}) {}
setLabel(label: string): this {
this.data.label = label;
return this;
}
setValue(value: string): this {
this.data.value = value;
return this;
}
setDescription(description: string): this {
this.data.description = description;
return this;
}
setDefault(Default = true): this {
this.data.default = Default;
return this;
}
setEmoji(emoji: APIMessageComponentEmoji): this {
this.data.emoji = emoji;
return this;
}
toJSON(): APISelectMenuOption {
return { ...this.data } as APISelectMenuOption;
}
}

View File

@ -1,45 +0,0 @@
import { APITextInputComponent, ComponentType, TextInputStyle } from '@biscuitland/common';
import { OptionValuesLength } from '..';
import { BaseComponent } from './BaseComponent';
export class ModalTextInput extends BaseComponent<APITextInputComponent> {
constructor(data: Partial<APITextInputComponent> = {}) {
super({ ...data, type: ComponentType.TextInput });
}
setStyle(style: TextInputStyle): this {
this.data.style = style;
return this;
}
setLabel(label: string): this {
this.data.label = label;
return this;
}
setPlaceholder(placeholder: string): this {
this.data.placeholder = placeholder;
return this;
}
setLength({ max, min }: Partial<OptionValuesLength>): this {
this.data.max_length = max;
this.data.min_length = min;
return this;
}
setCustomId(id: string): this {
this.data.custom_id = id;
return this;
}
setValue(value: string): this {
this.data.value = value;
return this;
}
setRequired(required = true): this {
this.data.required = required;
return this;
}
}

View File

@ -1,5 +0,0 @@
export * from './ActionRow';
export * from './BaseComponent';
export * from './MessageButton';
export * from './SelectMenu';
export * from './TextInput';

View File

@ -1,5 +0,0 @@
export * from './MessageEmbed';
export * from './Permissions';
export * from './Utils';
export * from './commands';
export * from './components';

View File

@ -1,7 +0,0 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist"
},
"include": ["src/**/*"]
}

View File

@ -1,12 +0,0 @@
import { defineConfig } from 'tsup';
const isProduction = process.env.NODE_ENV === 'production';
export default defineConfig({
clean: true,
dts: true,
entry: ['src/index.ts'],
format: ['cjs', 'esm'],
minify: isProduction,
sourcemap: false
});

View File

@ -1,113 +0,0 @@
# @biscuitland/rest
## 3.0.6
### Patch Changes
- I meessed up
## 3.0.5
### Patch Changes
- fix: logger on every module
## 3.0.4
### Patch Changes
- first 3.0.\* without bugs
## 2.3.0
### Minor Changes
- fix TODO
### Patch Changes
- Updated dependencies
- @biscuitland/api-types@2.3.0
## 2.2.3
### Patch Changes
- bug fixes
- Updated dependencies
- @biscuitland/api-types@2.2.3
## 2.2.2
### Patch Changes
- rename guildLocales to guildLocale in interactions
- Updated dependencies
- @biscuitland/api-types@2.2.2
## 2.2.1
### Patch Changes
- select menu options now can be empty since the latest Discord API update
- Updated dependencies
- @biscuitland/api-types@2.2.1
## 2.2.0
### Minor Changes
- Functionality to delete ephemeral messages added, select menus were updated
### Patch Changes
- Updated dependencies
- @biscuitland/api-types@2.2.0
## 2.1.2
### Patch Changes
- minor changes
- Updated dependencies
- @biscuitland/api-types@2.1.2
## 2.1.1
### Patch Changes
- dumb hotfix that LH asked for (blame Yuzu)
- Updated dependencies
- @biscuitland/api-types@2.1.1
## 2.1.0
### Minor Changes
- Changes to cache and forum channels ✨
- Forum channels and updates to @biscuitland/cache
### Patch Changes
- Updated dependencies
- Updated dependencies
- @biscuitland/api-types@2.1.0
## 2.0.6
### Patch Changes
- Minor fixes
- Updated dependencies
- @biscuitland/api-types@2.0.6
## 2.0.5
### Major Changes
- publish
### Patch Changes
- Updated dependencies
- @biscuitland/api-types@2.0.5

View File

@ -1,65 +0,0 @@
# @biscuitland/rest
## Most importantly, biscuit's rest is:
A standalone rest library that is yet easy to use and easy to host on a serverless infrastructure, it is meant to be used with biscuit's libraries.
[<img src="https://img.shields.io/badge/GitHub-100000?style=for-the-badge&logo=github&logoColor=white">](https://github.com/oasisjs/biscuit)
[<img src="https://img.shields.io/badge/Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white">](https://discord.gg/XNw2RZFzaP)
<img align="right" src="https://raw.githubusercontent.com/oasisjs/biscuit/main/assets/icon.svg" alt="biscuit"/>
## Install (for [node18](https://nodejs.org/en/download/))
```sh-session
npm install @biscuitland/rest
yarn add @biscuitland/rest
```
## Example (Standalone rest)
```ts
import { BiscuitREST } from "@biscuitland/rest";
import Fastify from "fastify";
const manager = new BiscuitREST({
api: "http://any.rest.proxy/",
version: 10,
token: "your token goes here"
});
const app = Fastify({});
app.all("*", (req, reply) => {
let response: unknown;
switch (req.method) {
case "GET":
response = await rest.get(req.url, req.body);
break;
case "POST":
response = await rest.post(req.url, req.body);
break;
case "PUT":
response = await rest.put(req.url, req.body);
break;
case "PATCH":
response = await rest.patch(req.url, req.body);
break;
case "DELETE":
response = await rest.delete(req.url, req.body);
break;
}
if (response)
reply.status(200).send({ status: 200, data: response });
else
reply.status(204).send({ status: 204, data: null });
});
app.listen({ port: "port..." });
```
## Links
* [Website](https://biscuitjs.com/)
* [Documentation](https://docs.biscuitjs.com/)
* [Discord](https://discord.gg/XNw2RZFzaP)
* [core](https://www.npmjs.com/package/@biscuitland/core) | [ws](https://www.npmjs.com/package/@biscuitland/ws) | [helpers](https://www.npmjs.com/package/@biscuitland/helpers)

View File

@ -1,74 +0,0 @@
{
"name": "@biscuitland/rest",
"version": "3.0.7",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"dist/**"
],
"scripts": {
"build": "tsup",
"clean": "rm -rf dist && rm -rf .turbo",
"dev": "tsup --watch"
},
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.mjs"
},
"require": "./dist/index.js"
}
},
"devDependencies": {
"tsup": "^7.0.0"
},
"license": "Apache-2.0",
"author": "Yuzuru <yuzuru@programmer.net>",
"contributors": [
{
"name": "Yuzuru",
"url": "https://github.com/yuzudev"
},
{
"name": "miia",
"url": "https://github.com/dragurimu"
},
{
"name": "n128",
"url": "https://github.com/nicolito128"
},
{
"name": "socram03",
"url": "https://github.com/socram03",
"author": true
},
{
"name": "Drylozu",
"url": "https://github.com/Drylozu"
}
],
"homepage": "https://biscuitjs.com",
"repository": {
"type": "git",
"url": "git+https://github.com/oasisjs/biscuit.git"
},
"bugs": {
"url": "https://github.com/oasisjs/biscuit"
},
"keywords": [
"api",
"discord",
"bots",
"typescript",
"botdev"
],
"publishConfig": {
"access": "public"
},
"dependencies": {
"@discordjs/rest": "^2.0.0"
}
}

View File

@ -1,68 +0,0 @@
export interface CDNRoutes {
embed: {
avatars: {
get(embed: UserAvatarDefault): string;
};
};
avatars(id: string): {
get(hash: string): string;
};
icons(guildId: string): {
get(hash: string): string;
};
splashes(guildId: string): {
get(hash: string): string;
};
'discovery-splashes'(guidId: string): {
get(hash: string): string;
};
banners(id: string): {
get(hash: string): string;
};
guilds(id: string): {
users(id: string): {
avatars(hash: string): {
get(): string;
};
banners(hash: string): {
get(): string;
};
};
};
emojis(id: string): {
get(): string;
};
appIcons(appId: string): {
get(iconOrCover: string): string;
};
'app-assets'(appId: string): {
get(asset: string): string;
achievements(id: string): {
icons(hash: string): {
get(): string;
};
};
};
'team-icons'(teamId: string): {
get(hash: string): string;
};
stickers(id: string): {
get(): string;
};
'role-icons'(roleId: string): {
get(icon: string): string;
};
'guild-events'(id: string): {
get(cover: string): string;
};
}
export interface CDNRoutes {
'app-assets'(id: '710982414301790216'): {
store(packBannerId: string): {
get(): string;
};
};
}
export type UserAvatarDefault = 1 | 2 | 3 | 4 | 5 | number;

View File

@ -1,83 +0,0 @@
import type { Identify } from '@biscuitland/common';
import type { RawFile, RequestData } from '@discordjs/rest';
import { REST } from '@discordjs/rest';
import type { RequestMethod } from './Router';
export class BiscuitREST {
api: REST;
constructor(public options: BiscuitRESTOptions) {
const { token, ...restOptions } = this.options;
this.api = new REST(restOptions).setToken(token);
}
async get<T>(route: string, options?: RequestObject<RequestMethod.Get>): Promise<T> {
const data = await this.api.get(route as `/${string}`, {
...options,
query: options?.query ? new URLSearchParams(options.query) : undefined
});
return data as T;
}
async post<T>(route: string, body?: RequestObject<RequestMethod.Post>): Promise<T> {
const data = await this.api.post(route as `/${string}`, {
...body,
body: body?.body,
query: body?.query ? new URLSearchParams(body.query) : undefined,
files: body?.files
});
return data as T;
}
async put<T>(route: string, body?: RequestObject<RequestMethod.Put>): Promise<T> {
const data = await this.api.put(route as `/${string}`, {
...body,
body: body?.body,
query: body?.query ? new URLSearchParams(body.query) : undefined,
files: body?.files
});
return data as T;
}
async patch<T>(route: string, body?: RequestObject<RequestMethod.Patch>): Promise<T> {
const data = await this.api.patch(route as `/${string}`, {
...body,
body: body?.body,
query: body?.query ? new URLSearchParams(body.query) : undefined,
files: body?.files
});
return data as T;
}
async delete<T>(route: string, options?: RequestObject<RequestMethod.Delete>): Promise<T> {
const data = await this.api.delete(route as `/${string}`, {
...options,
query: options?.query ? new URLSearchParams(options.query) : undefined
});
return data as T;
}
}
export type BiscuitRESTOptions = Identify<ConstructorParameters<typeof REST>[0] & { token: string }>;
export type RequestOptions = Pick<RequestData, 'passThroughBody' | 'reason' | 'auth'>;
export type RequestObject<M extends RequestMethod, B = Record<string, any>, Q = Record<string, any>> = {
query?: Q;
} & RequestOptions &
(M extends `${RequestMethod.Get}`
? unknown
: {
body?: B;
files?: RawFile[];
});
export type RestArguments<M extends RequestMethod, B = any, Q extends never | Record<string, any> = any> = M extends RequestMethod.Get
? Q extends never
? RequestObject<M, never, B>
: never
: RequestObject<M, B, Q>;

View File

@ -1,64 +0,0 @@
import { CDN_URL } from '@biscuitland/common';
import type { CDNRoutes, Routes } from './';
import { BiscuitREST } from './REST';
export enum RequestMethod {
Delete = 'delete',
Get = 'get',
Patch = 'patch',
Post = 'post',
Put = 'put'
}
const ArrRequestsMethods = Object.values(RequestMethod) as string[];
export class Router {
noop = () => {
return;
};
constructor(private rest: BiscuitREST) {}
createProxy(route = [] as string[]): Routes {
return new Proxy(this.noop, {
get: (_, key: string) => {
if (ArrRequestsMethods.includes(key)) {
return (...options: any[]) => this.rest[key](`/${route.join('/')}`, ...options);
}
return this.createProxy([...route, key]);
},
apply: (...[, _, args]) => {
return this.createProxy([...route, ...args.filter((x) => x != null)]);
}
}) as unknown as Routes;
}
}
export class CDN {
static createProxy(route = [] as string[]): CDNRoutes {
const noop = () => {
return;
};
return new Proxy(noop, {
get: (_, key: string) => {
if (key === 'get') {
return (value?: string) => {
const lastRoute = `${CDN_URL}/${route.join('/')}`;
if (value) {
if (typeof value !== 'string') {
// rome-ignore lint/nursery/noParameterAssign: fix multiples value types
value = String(value);
}
return `${lastRoute}/${value}`;
}
return lastRoute;
};
}
return this.createProxy([...route, key]);
},
apply: (...[, _, args]) => {
return this.createProxy([...route, ...args.filter((x) => x != null)]);
}
}) as unknown as CDNRoutes;
}
}

View File

@ -1,89 +0,0 @@
import {
RESTGetAPIApplicationCommandResult,
RESTGetAPIApplicationCommandsQuery,
RESTGetAPIApplicationCommandsResult,
RESTGetAPIApplicationGuildCommandResult,
RESTGetAPIApplicationGuildCommandsQuery,
RESTGetAPIApplicationGuildCommandsResult,
RESTGetAPIApplicationRoleConnectionMetadataResult,
RESTGetAPIGuildApplicationCommandsPermissionsResult,
RESTPatchAPIApplicationCommandJSONBody,
RESTPatchAPIApplicationCommandResult,
RESTPatchAPIApplicationGuildCommandJSONBody,
RESTPatchAPIApplicationGuildCommandResult,
RESTPostAPIApplicationCommandsJSONBody,
RESTPostAPIApplicationCommandsResult,
RESTPostAPIApplicationGuildCommandsJSONBody,
RESTPostAPIApplicationGuildCommandsResult,
RESTPutAPIApplicationCommandPermissionsJSONBody,
RESTPutAPIApplicationCommandsJSONBody,
RESTPutAPIApplicationCommandsResult,
RESTPutAPIApplicationGuildCommandsJSONBody,
RESTPutAPIApplicationGuildCommandsResult,
RESTPutAPIApplicationRoleConnectionMetadataJSONBody,
RESTPutAPIApplicationRoleConnectionMetadataResult,
RESTPutAPIGuildApplicationCommandsPermissionsResult
} from '@biscuitland/common';
import { RestArguments } from '../REST';
import { RequestMethod } from '../Router';
export interface ApplicationRoutes {
applications: {
(id: string): {
guilds: {
(id: string): {
commands: {
get(
args?: RestArguments<RequestMethod.Get, RESTGetAPIApplicationGuildCommandsQuery>
): Promise<RESTGetAPIApplicationGuildCommandsResult>;
post(
args: RestArguments<RequestMethod.Post, RESTPostAPIApplicationGuildCommandsJSONBody>
): Promise<RESTPostAPIApplicationGuildCommandsResult>;
put(
args: RestArguments<RequestMethod.Put, RESTPutAPIApplicationGuildCommandsJSONBody>
): Promise<RESTPutAPIApplicationGuildCommandsResult>;
permissions: {
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildApplicationCommandsPermissionsResult>;
// put(args: RestArguments<RequestMethod.Put, RESTPutAPIGuildApplicationCommandsPermissionsJSONBody>): Promise<RESTPutAPIGuildApplicationCommandsPermissionsResult>
};
(id: string): {
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIApplicationGuildCommandResult>;
patch(
args: RestArguments<RequestMethod.Patch, RESTPatchAPIApplicationGuildCommandJSONBody>
): Promise<RESTPatchAPIApplicationGuildCommandResult>;
delete(args?: RestArguments<RequestMethod.Delete>): Promise<never>;
permissions: {
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildApplicationCommandsPermissionsResult>;
put(
args: RestArguments<RequestMethod.Put, RESTPutAPIApplicationCommandPermissionsJSONBody>
): Promise<RESTPutAPIGuildApplicationCommandsPermissionsResult>;
};
};
};
};
};
commands: {
get(args?: RestArguments<RequestMethod.Get, RESTGetAPIApplicationCommandsQuery>): Promise<RESTGetAPIApplicationCommandsResult>;
post(
args: RestArguments<RequestMethod.Post, RESTPostAPIApplicationCommandsJSONBody>
): Promise<RESTPostAPIApplicationCommandsResult>;
put(args: RestArguments<RequestMethod.Put, RESTPutAPIApplicationCommandsJSONBody>): Promise<RESTPutAPIApplicationCommandsResult>;
(id: string): {
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIApplicationCommandResult>;
patch(
args: RestArguments<RequestMethod.Patch, RESTPatchAPIApplicationCommandJSONBody>
): Promise<RESTPatchAPIApplicationCommandResult>;
delete(args?: RestArguments<RequestMethod.Delete>): Promise<never>;
};
};
'role-connections': {
metadata: {
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIApplicationRoleConnectionMetadataResult>;
put(
args: RestArguments<RequestMethod.Put, RESTPutAPIApplicationRoleConnectionMetadataJSONBody>
): Promise<RESTPutAPIApplicationRoleConnectionMetadataResult>;
};
};
};
};
}

View File

@ -1,218 +0,0 @@
import {
RESTDeleteAPIChannelAllMessageReactionsResult,
RESTDeleteAPIChannelMessageReactionResult,
RESTDeleteAPIChannelMessageResult,
RESTDeleteAPIChannelPermissionResult,
RESTDeleteAPIChannelPinResult,
RESTDeleteAPIChannelRecipientResult,
RESTDeleteAPIChannelResult,
RESTDeleteAPIChannelThreadMembersResult,
RESTGetAPIChannelInvitesResult,
RESTGetAPIChannelMessageReactionUsersQuery,
RESTGetAPIChannelMessageReactionUsersResult,
RESTGetAPIChannelMessageResult,
RESTGetAPIChannelMessagesQuery,
RESTGetAPIChannelMessagesResult,
RESTGetAPIChannelPinsResult,
RESTGetAPIChannelResult,
RESTGetAPIChannelThreadMemberQuery,
RESTGetAPIChannelThreadMemberResult,
RESTGetAPIChannelThreadMembersQuery,
RESTGetAPIChannelThreadMembersResult,
RESTGetAPIChannelThreadsArchivedPrivateResult,
RESTGetAPIChannelThreadsArchivedPublicResult,
RESTGetAPIChannelThreadsArchivedQuery,
RESTGetAPIChannelUsersThreadsArchivedResult,
RESTGetAPIGuildWebhooksResult,
RESTPatchAPIChannelJSONBody,
RESTPatchAPIChannelMessageJSONBody,
RESTPatchAPIChannelMessageResult,
RESTPatchAPIChannelResult,
RESTPostAPIChannelFollowersJSONBody,
RESTPostAPIChannelFollowersResult,
RESTPostAPIChannelInviteJSONBody,
RESTPostAPIChannelInviteResult,
RESTPostAPIChannelMessageCrosspostResult,
RESTPostAPIChannelMessageJSONBody,
RESTPostAPIChannelMessageResult,
RESTPostAPIChannelMessagesBulkDeleteJSONBody,
RESTPostAPIChannelMessagesBulkDeleteResult,
RESTPostAPIChannelMessagesThreadsJSONBody,
RESTPostAPIChannelMessagesThreadsResult,
RESTPostAPIChannelThreadsJSONBody,
RESTPostAPIChannelThreadsResult,
RESTPostAPIChannelTypingResult,
RESTPostAPIChannelWebhookJSONBody,
RESTPostAPIChannelWebhookResult,
RESTPostAPIGuildForumThreadsJSONBody,
RESTPutAPIChannelMessageReactionResult,
RESTPutAPIChannelPermissionJSONBody,
RESTPutAPIChannelPermissionResult,
RESTPutAPIChannelPinResult,
RESTPutAPIChannelRecipientJSONBody,
RESTPutAPIChannelRecipientResult,
RESTPutAPIChannelThreadMembersResult
} from '@biscuitland/common';
import { RestArguments } from '../REST';
import { RequestMethod } from '../Router';
export interface ChannelRoutes {
channels(id: string): {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIChannelResult>;
//.
patch(args: RestArguments<RequestMethod.Patch, RESTPatchAPIChannelJSONBody>): Promise<RESTPatchAPIChannelResult>;
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIChannelResult>;
users: {
(id: '@me'): {
threads: {
archived: {
private: {
//.
get(
args?: RestArguments<RequestMethod.Get, RESTGetAPIChannelThreadsArchivedQuery>
): Promise<RESTGetAPIChannelUsersThreadsArchivedResult>;
};
};
};
};
};
'thread-members': {
//.
get(args?: RestArguments<RequestMethod.Get, RESTGetAPIChannelThreadMembersQuery>): Promise<RESTGetAPIChannelThreadMembersResult>;
(id: '@me'): {
//.
put(args: RestArguments<RequestMethod.Put>): Promise<RESTPutAPIChannelThreadMembersResult>;
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIChannelThreadMembersResult>;
};
(id: string): {
//.
get(args?: RestArguments<RequestMethod.Get, RESTGetAPIChannelThreadMemberQuery>): Promise<RESTGetAPIChannelThreadMemberResult>;
//.
put(args: RestArguments<RequestMethod.Put>): Promise<RESTPutAPIChannelThreadMembersResult>;
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIChannelThreadMembersResult>;
};
};
threads: {
//.
post(
args: RestArguments<RequestMethod.Post, RESTPostAPIChannelThreadsJSONBody | RESTPostAPIGuildForumThreadsJSONBody>
): Promise<RESTPostAPIChannelThreadsResult>;
archived: {
public: {
//.
get(
args?: RestArguments<RequestMethod.Get, RESTGetAPIChannelThreadsArchivedQuery>
): Promise<RESTGetAPIChannelThreadsArchivedPublicResult>;
};
private: {
//.
get(
args?: RestArguments<RequestMethod.Get, RESTGetAPIChannelThreadsArchivedQuery>
): Promise<RESTGetAPIChannelThreadsArchivedPrivateResult>;
};
};
};
recipients: {
(id: string): {
//.
put(args: RestArguments<RequestMethod.Put, RESTPutAPIChannelRecipientJSONBody>): Promise<RESTPutAPIChannelRecipientResult>;
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIChannelRecipientResult>;
};
};
pins: {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIChannelPinsResult>;
(id: string): {
//.
put(args: RestArguments<RequestMethod.Put>): Promise<RESTPutAPIChannelPinResult>;
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIChannelPinResult>;
};
};
followers: {
//.
post(args: RestArguments<RequestMethod.Post, RESTPostAPIChannelFollowersJSONBody>): Promise<RESTPostAPIChannelFollowersResult>;
};
permissions: {
(id: string): {
//.
put(args: RestArguments<RequestMethod.Put, RESTPutAPIChannelPermissionJSONBody>): Promise<RESTPutAPIChannelPermissionResult>;
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIChannelPermissionResult>;
};
};
invites: {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIChannelInvitesResult>;
//.
post(args: RestArguments<RequestMethod.Post, RESTPostAPIChannelInviteJSONBody>): Promise<RESTPostAPIChannelInviteResult>;
};
messages: {
//.
get(args?: RestArguments<RequestMethod.Get, RESTGetAPIChannelMessagesQuery>): Promise<RESTGetAPIChannelMessagesResult>;
//.
post(args: RestArguments<RequestMethod.Post, RESTPostAPIChannelMessageJSONBody>): Promise<RESTPostAPIChannelMessageResult>;
'bulk-delete': {
//.
post(
args: RestArguments<RequestMethod.Post, RESTPostAPIChannelMessagesBulkDeleteJSONBody>
): Promise<RESTPostAPIChannelMessagesBulkDeleteResult>;
};
(id: string): {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIChannelMessageResult>;
//.
patch(args: RestArguments<RequestMethod.Patch, RESTPatchAPIChannelMessageJSONBody>): Promise<RESTPatchAPIChannelMessageResult>;
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIChannelMessageResult>;
threads: {
//.
post(
args: RestArguments<RequestMethod.Post, RESTPostAPIChannelMessagesThreadsJSONBody>
): Promise<RESTPostAPIChannelMessagesThreadsResult>;
};
crosspost: {
//.
post(args: RestArguments<RequestMethod.Post>): Promise<RESTPostAPIChannelMessageCrosspostResult>;
};
reactions: {
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIChannelAllMessageReactionsResult>;
(emoji: string): {
//.
get(
args?: RestArguments<RequestMethod.Get, RESTGetAPIChannelMessageReactionUsersQuery>
): Promise<RESTGetAPIChannelMessageReactionUsersResult>;
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIChannelMessageReactionResult>;
(id: '@me'): {
//.
put(args: RestArguments<RequestMethod.Put>): Promise<RESTPutAPIChannelMessageReactionResult>;
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIChannelMessageReactionResult>;
};
(id: string): {
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIChannelMessageReactionResult>;
};
};
};
};
};
typing: {
//.
post(args?: RestArguments<RequestMethod.Post>): Promise<RESTPostAPIChannelTypingResult>;
};
webhooks: {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildWebhooksResult>;
//.
post(args: RestArguments<RequestMethod.Post, RESTPostAPIChannelWebhookJSONBody>): Promise<RESTPostAPIChannelWebhookResult>;
};
};
}

View File

@ -1,12 +0,0 @@
import { RESTGetAPIGatewayBotResult, RESTGetAPIGatewayResult } from '@biscuitland/common';
import { RestArguments } from '../REST';
import { RequestMethod } from '../Router';
export interface GatewayRoutes {
gateway: {
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGatewayResult>;
bot: {
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGatewayBotResult>;
};
};
}

View File

@ -1,381 +0,0 @@
import {
APIThreadChannel,
Identify,
RESTDeleteAPIAutoModerationRuleResult,
RESTDeleteAPIGuildBanResult,
RESTDeleteAPIGuildEmojiResult,
RESTDeleteAPIGuildIntegrationResult,
RESTDeleteAPIGuildMemberResult,
RESTDeleteAPIGuildMemberRoleResult,
RESTDeleteAPIGuildResult,
RESTDeleteAPIGuildRoleResult,
RESTDeleteAPIGuildScheduledEventResult,
RESTDeleteAPIGuildStickerResult,
RESTDeleteAPIGuildTemplateResult,
RESTGetAPIAuditLogQuery,
RESTGetAPIAuditLogResult,
RESTGetAPIAutoModerationRuleResult,
RESTGetAPIAutoModerationRulesResult,
RESTGetAPIGuildBanResult,
RESTGetAPIGuildBansQuery,
RESTGetAPIGuildBansResult,
RESTGetAPIGuildChannelsResult,
RESTGetAPIGuildEmojiResult,
RESTGetAPIGuildEmojisResult,
RESTGetAPIGuildIntegrationsResult,
RESTGetAPIGuildInvitesResult,
RESTGetAPIGuildMemberResult,
RESTGetAPIGuildMembersQuery,
RESTGetAPIGuildMembersResult,
RESTGetAPIGuildMembersSearchQuery,
RESTGetAPIGuildMembersSearchResult,
RESTGetAPIGuildPreviewResult,
RESTGetAPIGuildPruneCountQuery,
RESTGetAPIGuildPruneCountResult,
RESTGetAPIGuildQuery,
RESTGetAPIGuildResult,
RESTGetAPIGuildRolesResult,
RESTGetAPIGuildScheduledEventQuery,
RESTGetAPIGuildScheduledEventResult,
RESTGetAPIGuildScheduledEventUsersQuery,
RESTGetAPIGuildScheduledEventUsersResult,
RESTGetAPIGuildScheduledEventsQuery,
RESTGetAPIGuildScheduledEventsResult,
RESTGetAPIGuildStickerResult,
RESTGetAPIGuildStickersResult,
RESTGetAPIGuildTemplatesResult,
RESTGetAPIGuildThreadsResult,
RESTGetAPIGuildVanityUrlResult,
RESTGetAPIGuildVoiceRegionsResult,
RESTGetAPIGuildWebhooksResult,
RESTGetAPIGuildWelcomeScreenResult,
RESTGetAPIGuildWidgetImageQuery,
RESTGetAPIGuildWidgetImageResult,
RESTGetAPIGuildWidgetJSONResult,
RESTGetAPIGuildWidgetSettingsResult,
RESTGetAPITemplateResult,
RESTPatchAPIAutoModerationRuleJSONBody,
RESTPatchAPIAutoModerationRuleResult,
RESTPatchAPICurrentGuildMemberJSONBody,
RESTPatchAPIGuildChannelPositionsJSONBody,
RESTPatchAPIGuildChannelPositionsResult,
RESTPatchAPIGuildEmojiJSONBody,
RESTPatchAPIGuildEmojiResult,
RESTPatchAPIGuildJSONBody,
RESTPatchAPIGuildMemberJSONBody,
RESTPatchAPIGuildMemberResult,
RESTPatchAPIGuildResult,
RESTPatchAPIGuildRoleJSONBody,
RESTPatchAPIGuildRolePositionsJSONBody,
RESTPatchAPIGuildRolePositionsResult,
RESTPatchAPIGuildRoleResult,
RESTPatchAPIGuildScheduledEventJSONBody,
RESTPatchAPIGuildScheduledEventResult,
RESTPatchAPIGuildStickerJSONBody,
RESTPatchAPIGuildStickerResult,
RESTPatchAPIGuildTemplateJSONBody,
RESTPatchAPIGuildTemplateResult,
RESTPatchAPIGuildVoiceStateCurrentMemberJSONBody,
RESTPatchAPIGuildVoiceStateCurrentMemberResult,
RESTPatchAPIGuildVoiceStateUserJSONBody,
RESTPatchAPIGuildVoiceStateUserResult,
RESTPatchAPIGuildWelcomeScreenJSONBody,
RESTPatchAPIGuildWelcomeScreenResult,
RESTPatchAPIGuildWidgetSettingsJSONBody,
RESTPatchAPIGuildWidgetSettingsResult,
RESTPostAPIAutoModerationRuleJSONBody,
RESTPostAPIAutoModerationRuleResult,
RESTPostAPIGuildChannelJSONBody,
RESTPostAPIGuildChannelResult,
RESTPostAPIGuildEmojiJSONBody,
RESTPostAPIGuildEmojiResult,
RESTPostAPIGuildPruneJSONBody,
RESTPostAPIGuildPruneResult,
RESTPostAPIGuildRoleJSONBody,
RESTPostAPIGuildRoleResult,
RESTPostAPIGuildScheduledEventJSONBody,
RESTPostAPIGuildScheduledEventResult,
RESTPostAPIGuildStickerFormDataBody,
RESTPostAPIGuildStickerResult,
RESTPostAPIGuildTemplatesJSONBody,
RESTPostAPIGuildTemplatesResult,
RESTPostAPIGuildsJSONBody,
RESTPostAPIGuildsMFAJSONBody,
RESTPostAPIGuildsMFAResult,
RESTPostAPIGuildsResult,
RESTPostAPITemplateCreateGuildJSONBody,
RESTPostAPITemplateCreateGuildResult,
RESTPutAPIGuildBanJSONBody,
RESTPutAPIGuildBanResult,
RESTPutAPIGuildMemberJSONBody,
RESTPutAPIGuildMemberResult,
RESTPutAPIGuildMemberRoleResult,
RESTPutAPIGuildTemplateSyncResult
} from '@biscuitland/common';
import { RestArguments } from '../REST';
import { RequestMethod } from '../Router';
export interface GuildRoutes {
guilds: {
//.
post(args: RestArguments<RequestMethod.Post, RESTPostAPIGuildsJSONBody>): Promise<RESTPostAPIGuildsResult>;
templates(code: string): {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPITemplateResult>;
//.
post(args: RestArguments<RequestMethod.Post, RESTPostAPITemplateCreateGuildJSONBody>): Promise<RESTPostAPITemplateCreateGuildResult>;
};
(id: string): {
//.
get(args?: RestArguments<RequestMethod.Get, RESTGetAPIGuildQuery>): Promise<RESTGetAPIGuildResult>;
//.
patch(args: RestArguments<RequestMethod.Patch, RESTPatchAPIGuildJSONBody>): Promise<RESTPatchAPIGuildResult>;
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIGuildResult>;
webhooks: {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildWebhooksResult>;
};
preview: {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildPreviewResult>;
};
'audit-logs': {
//.
get(args?: RestArguments<RequestMethod.Get, RESTGetAPIAuditLogQuery>): Promise<RESTGetAPIAuditLogResult>;
};
'auto-moderation': {
rules: {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIAutoModerationRulesResult>;
//.
post(
args: RestArguments<RequestMethod.Post, RESTPostAPIAutoModerationRuleJSONBody>
): Promise<RESTPostAPIAutoModerationRuleResult>;
(id: string): {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIAutoModerationRuleResult>;
//.
patch(
args: RestArguments<RequestMethod.Post, RESTPatchAPIAutoModerationRuleJSONBody>
): Promise<RESTPatchAPIAutoModerationRuleResult>;
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIAutoModerationRuleResult>;
};
};
};
channels: {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildChannelsResult>;
//.
post(args: RestArguments<RequestMethod.Post, RESTPostAPIGuildChannelJSONBody>): Promise<RESTPostAPIGuildChannelResult>;
//.
patch(
args: RestArguments<RequestMethod.Patch, RESTPatchAPIGuildChannelPositionsJSONBody>
): Promise<RESTPatchAPIGuildChannelPositionsResult>;
};
members: {
//.
get(args?: RestArguments<RequestMethod.Get, RESTGetAPIGuildMembersQuery>): Promise<RESTGetAPIGuildMembersResult>;
search: {
//.
get(args: RestArguments<RequestMethod.Get, RESTGetAPIGuildMembersSearchQuery>): Promise<RESTGetAPIGuildMembersSearchResult>;
};
'@me': {
//.
patch(args: RestArguments<RequestMethod.Patch, RESTPatchAPICurrentGuildMemberJSONBody>): Promise<RESTGetAPIGuildMemberResult>;
};
(id: string): {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildMemberResult>;
//.
put(args: RestArguments<RequestMethod.Put, RESTPutAPIGuildMemberJSONBody>): Promise<RESTPutAPIGuildMemberResult>;
//.
//.
patch(args: RestArguments<RequestMethod.Patch, RESTPatchAPIGuildMemberJSONBody>): Promise<RESTPatchAPIGuildMemberResult>;
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIGuildMemberResult>;
roles(id: string): {
//.
put(args: RestArguments<RequestMethod.Put>): Promise<RESTPutAPIGuildMemberRoleResult>;
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIGuildMemberRoleResult>;
};
};
};
threads: {
active: {
//.
get(
args?: RestArguments<RequestMethod.Get>
): Promise<Identify<RESTGetAPIGuildThreadsResult & { threads: Partial<APIThreadChannel> }>>;
};
};
roles: {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildRolesResult>;
//.
post(args: RestArguments<RequestMethod.Post, RESTPostAPIGuildRoleJSONBody>): Promise<RESTPostAPIGuildRoleResult>;
//.
patch(
args: RestArguments<RequestMethod.Patch, RESTPatchAPIGuildRolePositionsJSONBody>
): Promise<RESTPatchAPIGuildRolePositionsResult>;
(id: string): {
//.
patch(args: RestArguments<RequestMethod.Patch, RESTPatchAPIGuildRoleJSONBody>): Promise<RESTPatchAPIGuildRoleResult>;
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIGuildRoleResult>;
};
};
bans: {
//.
get(args: RestArguments<RequestMethod.Get, RESTGetAPIGuildBansQuery>): Promise<RESTGetAPIGuildBansResult>;
(userId: string): {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildBanResult>;
//.
put(args: RestArguments<RequestMethod.Put, RESTPutAPIGuildBanJSONBody>): Promise<RESTPutAPIGuildBanResult>;
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIGuildBanResult>;
};
};
mfa: {
//.
post(args: RestArguments<RequestMethod.Post, RESTPostAPIGuildsMFAJSONBody>): Promise<RESTPostAPIGuildsMFAResult>;
};
prune: {
//.
get(args: RestArguments<RequestMethod.Get, RESTGetAPIGuildPruneCountQuery>): Promise<RESTGetAPIGuildPruneCountResult>;
//.
post(args: RestArguments<RequestMethod.Post, RESTPostAPIGuildPruneJSONBody>): Promise<RESTPostAPIGuildPruneResult>;
};
regions: {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildVoiceRegionsResult>;
};
invites: {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildInvitesResult>;
};
widget: {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildWidgetSettingsResult>;
//.
patch(
args: RestArguments<RequestMethod.Patch, RESTPatchAPIGuildWidgetSettingsJSONBody>
): Promise<RESTPatchAPIGuildWidgetSettingsResult>;
};
'widget.json': {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildWidgetJSONResult>;
};
'widget.png': {
//.
get(args?: RestArguments<RequestMethod.Get, RESTGetAPIGuildWidgetImageQuery>): Promise<RESTGetAPIGuildWidgetImageResult>;
};
integrations: {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildIntegrationsResult>;
(id: string): {
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIGuildIntegrationResult>;
};
};
'vanity-url': {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildVanityUrlResult>;
};
'welcome-screen': {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildWelcomeScreenResult>;
//.
patch(
args: RestArguments<RequestMethod.Patch, RESTPatchAPIGuildWelcomeScreenJSONBody>
): Promise<RESTPatchAPIGuildWelcomeScreenResult>;
};
// onboarding: {
// get(args:RestArguments<RequestMethod.Get,boarding>);
// }
emojis: {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildEmojisResult>;
//.
post(args: RestArguments<RequestMethod.Post, RESTPostAPIGuildEmojiJSONBody>): Promise<RESTPostAPIGuildEmojiResult>;
(id: string): {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildEmojiResult>;
//.
patch(args: RestArguments<RequestMethod.Patch, RESTPatchAPIGuildEmojiJSONBody>): Promise<RESTPatchAPIGuildEmojiResult>;
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIGuildEmojiResult>;
};
};
'voice-states': {
'@me': {
//.
patch(
args: RestArguments<RequestMethod.Patch, RESTPatchAPIGuildVoiceStateCurrentMemberJSONBody>
): Promise<RESTPatchAPIGuildVoiceStateCurrentMemberResult>;
};
(id: string): {
//.
patch(
args: RestArguments<RequestMethod.Patch, RESTPatchAPIGuildVoiceStateUserJSONBody>
): Promise<RESTPatchAPIGuildVoiceStateUserResult>;
};
};
stickers: {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildStickersResult>;
//.
post(args: RestArguments<RequestMethod.Post, RESTPostAPIGuildStickerFormDataBody>): Promise<RESTPostAPIGuildStickerResult>;
(id: string): {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildStickerResult>;
//.
patch(args: RestArguments<RequestMethod.Patch, RESTPatchAPIGuildStickerJSONBody>): Promise<RESTPatchAPIGuildStickerResult>;
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIGuildStickerResult>;
};
};
'scheduled-events': {
//.
get(args?: RestArguments<RequestMethod.Get, RESTGetAPIGuildScheduledEventsQuery>): Promise<RESTGetAPIGuildScheduledEventsResult>;
//.
post(
args: RestArguments<RequestMethod.Post, RESTPostAPIGuildScheduledEventJSONBody>
): Promise<RESTPostAPIGuildScheduledEventResult>;
(id: string): {
//.
get(args?: RestArguments<RequestMethod.Get, RESTGetAPIGuildScheduledEventQuery>): Promise<RESTGetAPIGuildScheduledEventResult>;
//.
patch(
args: RestArguments<RequestMethod.Patch, RESTPatchAPIGuildScheduledEventJSONBody>
): Promise<RESTPatchAPIGuildScheduledEventResult>;
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIGuildScheduledEventResult>;
users: {
//.
get(
args?: RestArguments<RequestMethod.Get, RESTGetAPIGuildScheduledEventUsersQuery>
): Promise<RESTGetAPIGuildScheduledEventUsersResult>;
};
};
};
templates: {
//.
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIGuildTemplatesResult>;
//.
post(args: RestArguments<RequestMethod.Post, RESTPostAPIGuildTemplatesJSONBody>): Promise<RESTPostAPIGuildTemplatesResult>;
(code: string): {
//.
put(args: RestArguments<RequestMethod.Put>): Promise<RESTPutAPIGuildTemplateSyncResult>;
//.
patch(args: RestArguments<RequestMethod.Patch, RESTPatchAPIGuildTemplateJSONBody>): Promise<RESTPatchAPIGuildTemplateResult>;
//.
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIGuildTemplateResult>;
};
};
};
};
}

View File

@ -1,23 +0,0 @@
import { ApplicationRoutes } from './applications';
import { ChannelRoutes } from './channels';
import { GatewayRoutes } from './gateway';
import { GuildRoutes } from './guilds';
import { InteractionRoutes } from './interactions';
import { InviteRoutes } from './invites';
import { StageInstanceRoutes } from './stage-instances';
import { StickerRoutes } from './stickers';
import { UserRoutes } from './users';
import { VoiceRoutes } from './voice';
import { WebhookRoutes } from './webhooks';
export type Routes = ApplicationRoutes &
ChannelRoutes &
GatewayRoutes &
GuildRoutes &
InteractionRoutes &
InviteRoutes &
StageInstanceRoutes &
StickerRoutes &
UserRoutes &
VoiceRoutes &
WebhookRoutes;

View File

@ -1,15 +0,0 @@
import { RESTPostAPIInteractionCallbackJSONBody } from '@biscuitland/common';
import { RestArguments } from '../REST';
import { RequestMethod } from '../Router';
export interface InteractionRoutes {
interactions: {
(id: string): {
(token: string): {
callback: {
post(args: RestArguments<RequestMethod.Post, RESTPostAPIInteractionCallbackJSONBody>): Promise<never>;
};
};
};
};
}

View File

@ -1,10 +0,0 @@
import { RESTDeleteAPIInviteResult, RESTGetAPIInviteQuery, RESTGetAPIInviteResult } from '@biscuitland/common';
import { RestArguments } from '../REST';
import { RequestMethod } from '../Router';
export interface InviteRoutes {
invites(id: string): {
get(args?: RestArguments<RequestMethod.Get, RESTGetAPIInviteQuery>): Promise<RESTGetAPIInviteResult>;
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIInviteResult>;
};
}

View File

@ -1,21 +0,0 @@
import {
RESTDeleteAPIStageInstanceResult,
RESTGetAPIStageInstanceResult,
RESTPatchAPIStageInstanceJSONBody,
RESTPatchAPIStageInstanceResult,
RESTPostAPIStageInstanceJSONBody,
RESTPostAPIStageInstanceResult
} from '@biscuitland/common';
import { RestArguments } from '../REST';
import { RequestMethod } from '../Router';
export interface StageInstanceRoutes {
'stage-instances': {
post(args: RestArguments<RequestMethod.Post, RESTPostAPIStageInstanceJSONBody>): Promise<RESTPostAPIStageInstanceResult>;
(id: string): {
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIStageInstanceResult>;
patch(args: RestArguments<RequestMethod.Patch, RESTPatchAPIStageInstanceJSONBody>): Promise<RESTPatchAPIStageInstanceResult>;
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIStageInstanceResult>;
};
};
}

View File

@ -1,12 +0,0 @@
import { RESTGetAPIStickerResult, RESTGetNitroStickerPacksResult } from '@biscuitland/common';
import { RestArguments } from '../REST';
import { RequestMethod } from '../Router';
export interface StickerRoutes {
stickers(id: string): {
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIStickerResult>;
};
'sticker-packs': {
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetNitroStickerPacksResult>;
};
}

View File

@ -1,53 +0,0 @@
import {
APIDMChannel,
RESTDeleteAPIGuildResult,
RESTGetAPICurrentUserApplicationRoleConnectionResult,
RESTGetAPICurrentUserConnectionsResult,
RESTGetAPICurrentUserGuildsQuery,
RESTGetAPICurrentUserGuildsResult,
RESTGetAPICurrentUserResult,
RESTGetAPIUserResult,
RESTGetCurrentUserGuildMemberResult,
RESTPatchAPICurrentUserJSONBody,
RESTPatchAPICurrentUserResult,
RESTPostAPICurrentUserCreateDMChannelJSONBody,
RESTPutAPICurrentUserApplicationRoleConnectionJSONBody,
RESTPutAPICurrentUserApplicationRoleConnectionResult
} from '@biscuitland/common';
import { RestArguments } from '../REST';
import { RequestMethod } from '../Router';
export interface UserRoutes {
users: {
(id: string): {
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIUserResult>;
};
(id: '@me'): {
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPICurrentUserResult>;
patch(args: RestArguments<RequestMethod.Patch, RESTPatchAPICurrentUserJSONBody>): Promise<RESTPatchAPICurrentUserResult>;
guilds: {
get(args?: RestArguments<RequestMethod.Get, RESTGetAPICurrentUserGuildsQuery>): Promise<RESTGetAPICurrentUserGuildsResult>;
(id: string): {
member: {
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetCurrentUserGuildMemberResult>;
};
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIGuildResult>;
};
};
channels: {
post(args: RestArguments<RequestMethod.Post, RESTPostAPICurrentUserCreateDMChannelJSONBody>): Promise<APIDMChannel>;
};
connections: {
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPICurrentUserConnectionsResult>;
};
applications(applicationId: string): {
'role-connection': {
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPICurrentUserApplicationRoleConnectionResult>;
put(
args: RestArguments<RequestMethod.Put, RESTPutAPICurrentUserApplicationRoleConnectionJSONBody>
): Promise<RESTPutAPICurrentUserApplicationRoleConnectionResult>;
};
};
};
};
}

View File

@ -1,11 +0,0 @@
import { RESTGetAPIVoiceRegionsResult } from '@biscuitland/common';
import { RestArguments } from '../REST';
import { RequestMethod } from '../Router';
export interface VoiceRoutes {
voice: {
region: {
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIVoiceRegionsResult>;
};
};
}

View File

@ -1,61 +0,0 @@
import {
RESTDeleteAPIWebhookResult,
RESTDeleteAPIWebhookWithTokenMessageResult,
RESTDeleteAPIWebhookWithTokenResult,
RESTGetAPIWebhookResult,
RESTGetAPIWebhookWithTokenMessageResult,
RESTGetAPIWebhookWithTokenResult,
RESTPatchAPIWebhookJSONBody,
RESTPatchAPIWebhookResult,
RESTPatchAPIWebhookWithTokenJSONBody,
RESTPatchAPIWebhookWithTokenMessageJSONBody,
RESTPatchAPIWebhookWithTokenMessageResult,
RESTPatchAPIWebhookWithTokenResult,
RESTPostAPIWebhookWithTokenGitHubQuery,
RESTPostAPIWebhookWithTokenGitHubResult,
RESTPostAPIWebhookWithTokenGitHubWaitResult,
RESTPostAPIWebhookWithTokenJSONBody,
RESTPostAPIWebhookWithTokenQuery,
RESTPostAPIWebhookWithTokenResult,
RESTPostAPIWebhookWithTokenSlackQuery,
RESTPostAPIWebhookWithTokenSlackResult,
RESTPostAPIWebhookWithTokenSlackWaitResult,
RESTPostAPIWebhookWithTokenWaitResult
} from '@biscuitland/common';
import { RestArguments } from '../REST';
import { RequestMethod } from '../Router';
export interface WebhookRoutes {
webhooks(id: string): {
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIWebhookResult>;
patch(args: RestArguments<RequestMethod.Patch, RESTPatchAPIWebhookJSONBody>): Promise<RESTPatchAPIWebhookResult>;
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIWebhookResult>;
(token: string): {
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIWebhookWithTokenResult>;
patch(args: RestArguments<RequestMethod.Patch, RESTPatchAPIWebhookWithTokenJSONBody>): Promise<RESTPatchAPIWebhookWithTokenResult>;
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIWebhookWithTokenResult>;
post(
args: RestArguments<RequestMethod.Post, RESTPostAPIWebhookWithTokenJSONBody, RESTPostAPIWebhookWithTokenQuery>
): Promise<RESTPostAPIWebhookWithTokenResult | RESTPostAPIWebhookWithTokenWaitResult>;
slack: {
post(
args: RestArguments<RequestMethod.Post, RESTPostAPIWebhookWithTokenJSONBody, RESTPostAPIWebhookWithTokenSlackQuery>
): Promise<RESTPostAPIWebhookWithTokenSlackResult | RESTPostAPIWebhookWithTokenSlackWaitResult>;
};
github: {
post(
args: RestArguments<RequestMethod.Post, RESTPostAPIWebhookWithTokenJSONBody, RESTPostAPIWebhookWithTokenGitHubQuery>
): Promise<RESTPostAPIWebhookWithTokenGitHubResult | RESTPostAPIWebhookWithTokenGitHubWaitResult>;
};
messages: {
(id: string | '@original'): {
get(args?: RestArguments<RequestMethod.Get>): Promise<RESTGetAPIWebhookWithTokenMessageResult>;
patch(
args: RestArguments<RequestMethod.Patch, RESTPatchAPIWebhookWithTokenMessageJSONBody>
): Promise<RESTPatchAPIWebhookWithTokenMessageResult>;
delete(args?: RestArguments<RequestMethod.Delete>): Promise<RESTDeleteAPIWebhookWithTokenMessageResult>;
};
};
};
};
}

View File

@ -1,5 +0,0 @@
export { REST, type RawFile } from '@discordjs/rest';
export * from './CDN';
export * from './REST';
export * from './Router';
export * from './Routes';

View File

@ -1,7 +0,0 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist"
},
"include": ["src/**/*"]
}

View File

@ -1,12 +0,0 @@
import { defineConfig } from 'tsup';
const isProduction = process.env.NODE_ENV === 'production';
export default defineConfig({
clean: true,
dts: true,
entry: ['src/index.ts'],
format: ['cjs', 'esm'],
minify: isProduction,
sourcemap: false
});

View File

@ -1,149 +0,0 @@
# @biscuitland/ws
## 3.0.12
### Patch Changes
- new changes
- new changes
## 3.0.9
### Patch Changes
- silly bug on options
## 3.0.8
### Patch Changes
- Updated dependencies
- @biscuitland/common@0.0.8
## 3.0.7
### Patch Changes
- Updated dependencies
- @biscuitland/common@0.0.7
## 3.0.6
### Patch Changes
- I meessed up
- Updated dependencies
- @biscuitland/common@0.0.6
- @biscuitland/rest@3.0.6
## 3.0.5
### Patch Changes
- fix: logger on every module
- Updated dependencies
- @biscuitland/common@0.0.5
- @biscuitland/rest@3.0.5
## 3.0.4
### Patch Changes
- first 3.0.\* without bugs
- Updated dependencies
- @biscuitland/common@0.0.4
- @biscuitland/rest@3.0.4
## 2.3.0
### Minor Changes
- fix TODO
### Patch Changes
- Updated dependencies
- @biscuitland/api-types@2.3.0
## 2.2.3
### Patch Changes
- bug fixes
- Updated dependencies
- @biscuitland/api-types@2.2.3
## 2.2.2
### Patch Changes
- rename guildLocales to guildLocale in interactions
- Updated dependencies
- @biscuitland/api-types@2.2.2
## 2.2.1
### Patch Changes
- select menu options now can be empty since the latest Discord API update
- Updated dependencies
- @biscuitland/api-types@2.2.1
## 2.2.0
### Minor Changes
- Functionality to delete ephemeral messages added, select menus were updated
### Patch Changes
- Updated dependencies
- @biscuitland/api-types@2.2.0
## 2.1.2
### Patch Changes
- minor changes
- Updated dependencies
- @biscuitland/api-types@2.1.2
## 2.1.1
### Patch Changes
- dumb hotfix that LH asked for (blame Yuzu)
- Updated dependencies
- @biscuitland/api-types@2.1.1
## 2.1.0
### Minor Changes
- Changes to cache and forum channels ✨
- Forum channels and updates to @biscuitland/cache
### Patch Changes
- Updated dependencies
- Updated dependencies
- @biscuitland/api-types@2.1.0
## 2.0.6
### Patch Changes
- Minor fixes
- Updated dependencies
- @biscuitland/api-types@2.0.6
## 2.0.5
### Major Changes
- publish
### Patch Changes
- Updated dependencies
- @biscuitland/api-types@2.0.5

View File

@ -1,56 +0,0 @@
# @biscuitland/ws
## Advice
This version of @biscuitland/ws is a **fork** of @discordeno/gateway, all credits go to them. However it has been heavily modified for proper use within biscuit.
## Most importantly, biscuit's ws is:
A standalone gateway to interface Discord, it is meant to be used with a rest manager to send fetch requests to Discord
[<img src="https://img.shields.io/badge/GitHub-100000?style=for-the-badge&logo=github&logoColor=white">](https://github.com/oasisjs/biscuit)
[<img src="https://img.shields.io/badge/Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white">](https://discord.gg/XNw2RZFzaP)
<img align="right" src="https://raw.githubusercontent.com/oasisjs/biscuit/main/assets/icon.svg" alt="biscuit"/>
## Install (for [node18](https://nodejs.org/en/download/))
```sh-session
npm install @biscuitland/ws
yarn add @biscuitland/ws
```
## Example
```ts
import { ShardManager } from "@biscuitland/ws";
import { BiscuitREST, Router } from "@biscuitland/rest";
import { GatewayIntentBits } from "@biscuitland/common";
const intents = GatewayIntentBits.Guilds;
const token = "your token goes here";
const rest = new BiscuitREST({ token });
const api = new Router(rest).createProxy();
(async () => {
const connection = await api.gateway.bot.get();
// gateway bot code ↓
const ws = new ShardManager({
token,
intents,
connection,
async handlePayload(shardId, payload) {
console.log("Received payload on shard #%s", shardId, payload);
},
});
await ws.spawnShards();
})();
```
## Links
* [Website](https://biscuitjs.com/)
* [Documentation](https://docs.biscuitjs.com/)
* [Discord](https://discord.gg/XNw2RZFzaP)
* [rest](https://www.npmjs.com/package/@biscuitland/rest) | [core](https://www.npmjs.com/package/@biscuitland/core) | [helpers](https://www.npmjs.com/package/@biscuitland/helpers)

View File

@ -1,82 +0,0 @@
{
"name": "@biscuitland/ws",
"version": "3.0.12",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"dist/**"
],
"scripts": {
"build": "tsup",
"clean": "rm -rf dist && rm -rf .turbo",
"dev": "tsup --watch",
"test": "vitest run"
},
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.mjs"
},
"require": "./dist/index.js"
}
},
"dependencies": {
"@biscuitland/common": "^0.0.10",
"@biscuitland/rest": "^3.0.7",
"ws": "^8.13.0"
},
"devDependencies": {
"@types/node": "^20.0.0",
"@types/ws": "^8.5.4",
"tsup": "^7.0.0"
},
"directories": {
"lib": "src"
},
"license": "Apache-2.0",
"author": "Yuzuru <yuzuru@programmer.net>",
"contributors": [
{
"name": "Yuzuru",
"url": "https://github.com/yuzudev"
},
{
"name": "miia",
"url": "https://github.com/dragurimu"
},
{
"name": "n128",
"url": "https://github.com/nicolito128"
},
{
"name": "socram03",
"url": "https://github.com/socram03",
"author": true
},
{
"name": "Drylozu",
"url": "https://github.com/Drylozu"
}
],
"homepage": "https://biscuitjs.com",
"repository": {
"type": "git",
"url": "git+https://github.com/oasisjs/biscuit.git"
},
"bugs": {
"url": "https://github.com/oasisjs/biscuit"
},
"keywords": [
"api",
"discord",
"bots",
"typescript",
"botdev"
],
"publishConfig": {
"access": "public"
}
}

View File

@ -1,204 +0,0 @@
import type {
APIAuditLogEntry,
APIAutoModerationRule,
APIChannel,
APIGuild,
APIGuildMember,
APIGuildScheduledEvent,
APIStageInstance,
APIUser,
GatewayActivity,
GatewayAutoModerationActionExecutionDispatchData,
GatewayChannelPinsUpdateDispatchData,
GatewayChannelUpdateDispatchData,
GatewayDispatchEvents,
GatewayGuildBanAddDispatchData,
GatewayGuildBanRemoveDispatchData,
GatewayGuildCreateDispatchData,
GatewayGuildDeleteDispatchData,
GatewayGuildEmojisUpdateDispatchData,
GatewayGuildIntegrationsUpdateDispatchData,
GatewayGuildMemberAddDispatchData,
GatewayGuildMemberRemoveDispatchData,
GatewayGuildMemberUpdateDispatchData,
GatewayGuildMembersChunkDispatchData,
GatewayGuildRoleCreateDispatchData,
GatewayGuildRoleDeleteDispatchData,
GatewayGuildRoleUpdateDispatchData,
GatewayGuildScheduledEventUserRemoveDispatchData,
GatewayGuildStickersUpdateDispatchData,
GatewayIntegrationCreateDispatchData,
GatewayIntegrationDeleteDispatchData,
GatewayInteractionCreateDispatchData,
GatewayInviteCreateDispatchData,
GatewayInviteDeleteDispatchData,
GatewayMessageCreateDispatchData,
GatewayMessageDeleteBulkDispatchData,
GatewayMessageDeleteDispatchData,
GatewayMessageReactionAddDispatchData,
GatewayMessageReactionRemoveAllDispatchData,
GatewayMessageReactionRemoveDispatchData,
GatewayMessageReactionRemoveEmojiDispatchData,
GatewayMessageUpdateDispatchData,
GatewayPresenceUpdateData,
GatewayPresenceUpdateDispatchData,
GatewayReadyDispatchData,
GatewayRequestGuildMembersDataWithQuery,
GatewayRequestGuildMembersDataWithUserIds,
GatewayThreadCreateDispatchData,
GatewayThreadDeleteDispatchData,
GatewayThreadListSyncDispatchData,
GatewayThreadMemberUpdateDispatchData,
GatewayThreadMembersUpdateDispatchData,
GatewayTypingStartDispatchData,
GatewayUserUpdateDispatchData,
GatewayVoiceServerUpdateDispatchData,
GatewayVoiceStateUpdateData,
GatewayWebhooksUpdateDispatchData,
PresenceUpdateStatus,
RestToKeys
} from '@biscuitland/common';
/** https://discord.com/developers/docs/topics/gateway-events#update-presence */
export interface StatusUpdate {
/** The user's activities */
activities?: Omit<GatewayActivity, 'created_at' | 'id'>[];
/** The user's new status */
status: PresenceUpdateStatus;
}
/** https://discord.com/developers/docs/topics/gateway#update-voice-state */
export interface UpdateVoiceState {
/** id of the guild */
guild_id: string;
/** id of the voice channel client wants to join (null if disconnecting) */
channel_id: string | null;
/** Is the client muted */
self_mute: boolean;
/** Is the client deafened */
self_deaf: boolean;
}
export type ShardStatusUpdate = Pick<GatewayPresenceUpdateData, 'activities' | 'status'>;
export interface RequestGuildMembersOptions extends GatewayRequestGuildMembersDataWithQuery, GatewayRequestGuildMembersDataWithUserIds {}
export interface GatewayMemberRequest {
/** The unique nonce for this request. */
nonce: string;
/** The resolver handler to run when all members arrive. */
resolve: (value: APIGuildMember[] | PromiseLike<APIGuildMember[]>) => void;
/** The members that have already arrived for this request. */
members: APIGuildMember[];
}
export type AtLeastOne<
T,
U = {
[K in keyof T]: Pick<T, K>;
}
> = Partial<T> & U[keyof U];
export type ClientUser = { bot: true } & APIUser;
export interface Events {
[GatewayDispatchEvents.Ready]: GatewayReadyDispatchData & {
user: ClientUser;
};
[GatewayDispatchEvents.ChannelUpdate]: GatewayChannelUpdateDispatchData;
[GatewayDispatchEvents.AutoModerationActionExecution]: GatewayAutoModerationActionExecutionDispatchData;
[GatewayDispatchEvents.ThreadCreate]: GatewayThreadCreateDispatchData;
[GatewayDispatchEvents.ThreadDelete]: GatewayThreadDeleteDispatchData;
[GatewayDispatchEvents.ThreadUpdate]: GatewayThreadDeleteDispatchData;
[GatewayDispatchEvents.ThreadListSync]: GatewayThreadListSyncDispatchData;
[GatewayDispatchEvents.ThreadMemberUpdate]: GatewayThreadMemberUpdateDispatchData;
[GatewayDispatchEvents.ThreadMembersUpdate]: GatewayThreadMembersUpdateDispatchData;
[GatewayDispatchEvents.ChannelPinsUpdate]: GatewayChannelPinsUpdateDispatchData;
[GatewayDispatchEvents.GuildCreate]: GatewayGuildCreateDispatchData;
[GatewayDispatchEvents.GuildUpdate]: APIGuild;
[GatewayDispatchEvents.GuildDelete]: GatewayGuildDeleteDispatchData;
[GatewayDispatchEvents.GuildAuditLogEntryCreate]: APIAuditLogEntry;
[GatewayDispatchEvents.GuildBanAdd]: GatewayGuildBanAddDispatchData;
[GatewayDispatchEvents.GuildBanRemove]: GatewayGuildBanRemoveDispatchData;
[GatewayDispatchEvents.GuildEmojisUpdate]: GatewayGuildEmojisUpdateDispatchData;
[GatewayDispatchEvents.GuildStickersUpdate]: GatewayGuildStickersUpdateDispatchData;
[GatewayDispatchEvents.GuildIntegrationsUpdate]: GatewayGuildIntegrationsUpdateDispatchData;
[GatewayDispatchEvents.GuildMemberAdd]: GatewayGuildMemberAddDispatchData;
[GatewayDispatchEvents.GuildMemberRemove]: GatewayGuildMemberRemoveDispatchData;
[GatewayDispatchEvents.GuildMemberUpdate]: GatewayGuildMemberUpdateDispatchData;
[GatewayDispatchEvents.GuildMembersChunk]: GatewayGuildMembersChunkDispatchData;
[GatewayDispatchEvents.GuildRoleCreate]: GatewayGuildRoleCreateDispatchData;
[GatewayDispatchEvents.GuildRoleUpdate]: GatewayGuildRoleUpdateDispatchData;
[GatewayDispatchEvents.GuildRoleDelete]: GatewayGuildRoleDeleteDispatchData;
[GatewayDispatchEvents.IntegrationDelete]: GatewayIntegrationDeleteDispatchData;
[GatewayDispatchEvents.InviteCreate]: GatewayInviteCreateDispatchData;
[GatewayDispatchEvents.InviteDelete]: GatewayInviteDeleteDispatchData;
[GatewayDispatchEvents.MessageCreate]: GatewayMessageCreateDispatchData;
[GatewayDispatchEvents.MessageUpdate]: GatewayMessageUpdateDispatchData;
[GatewayDispatchEvents.MessageDelete]: GatewayMessageDeleteDispatchData;
[GatewayDispatchEvents.MessageDeleteBulk]: GatewayMessageDeleteBulkDispatchData;
[GatewayDispatchEvents.MessageReactionAdd]: GatewayMessageReactionAddDispatchData;
[GatewayDispatchEvents.MessageReactionRemove]: GatewayMessageReactionRemoveDispatchData;
[GatewayDispatchEvents.MessageReactionRemoveAll]: GatewayMessageReactionRemoveAllDispatchData;
[GatewayDispatchEvents.MessageReactionRemoveEmoji]: GatewayMessageReactionRemoveEmojiDispatchData;
[GatewayDispatchEvents.PresenceUpdate]: GatewayPresenceUpdateDispatchData;
[GatewayDispatchEvents.TypingStart]: GatewayTypingStartDispatchData;
[GatewayDispatchEvents.UserUpdate]: GatewayUserUpdateDispatchData;
[GatewayDispatchEvents.VoiceStateUpdate]: GatewayVoiceStateUpdateData;
[GatewayDispatchEvents.VoiceServerUpdate]: GatewayVoiceServerUpdateDispatchData;
[GatewayDispatchEvents.WebhooksUpdate]: GatewayWebhooksUpdateDispatchData;
[GatewayDispatchEvents.InteractionCreate]: GatewayInteractionCreateDispatchData;
}
export type StageSameEvents = RestToKeys<
[
APIStageInstance,
GatewayDispatchEvents.StageInstanceCreate,
GatewayDispatchEvents.StageInstanceUpdate,
GatewayDispatchEvents.StageInstanceDelete
]
>;
export type IntegrationSameEvents = RestToKeys<
[GatewayIntegrationCreateDispatchData, GatewayDispatchEvents.IntegrationCreate, GatewayDispatchEvents.IntegrationUpdate]
>;
export type GuildScheduledUserSameEvents = RestToKeys<
[
GatewayGuildScheduledEventUserRemoveDispatchData,
GatewayDispatchEvents.GuildScheduledEventUserRemove,
GatewayDispatchEvents.GuildScheduledEventUserAdd
]
>;
export type GuildScheduledSameEvents = RestToKeys<
[
APIGuildScheduledEvent,
GatewayDispatchEvents.GuildScheduledEventCreate,
GatewayDispatchEvents.GuildScheduledEventDelete,
GatewayDispatchEvents.GuildScheduledEventUpdate
]
>;
export type ChannelSameEvents = RestToKeys<
[APIChannel, GatewayDispatchEvents.ChannelCreate, GatewayDispatchEvents.ChannelDelete, GatewayDispatchEvents.ChannelUpdate]
>;
export type AutoModetaractionRuleEvents = RestToKeys<
[
APIAutoModerationRule,
GatewayDispatchEvents.AutoModerationRuleCreate,
GatewayDispatchEvents.AutoModerationRuleDelete,
GatewayDispatchEvents.AutoModerationRuleUpdate
]
>;
export type NormalizeEvents = Events &
AutoModetaractionRuleEvents &
ChannelSameEvents &
GuildScheduledSameEvents &
GuildScheduledUserSameEvents &
IntegrationSameEvents &
StageSameEvents & { RAW: GatewayDispatchEvents };
export type GatewayEvents = { [x in keyof NormalizeEvents]: NormalizeEvents[x] };

View File

@ -1,40 +0,0 @@
import type { GatewayDispatchPayload } from '@biscuitland/common';
import { ShardManagerOptions } from '../discord';
const COMPRESS = false;
const properties = {
os: process.platform,
browser: 'Biscuit',
device: 'Biscuit'
};
const ShardManagerDefaults: Partial<ShardManagerOptions> = {
totalShards: 1,
spawnShardDelay: 5300,
debug: false,
intents: 0,
properties: properties,
version: 10,
handlePayload: (shardId: number, packet: GatewayDispatchPayload): void => {
console.info(`Packet ${packet.t} on shard ${shardId}`);
}
};
export interface IdentifyProperties {
/**
* Operating system the shard runs on.
* @default "darwin" | "linux" | "windows"
*/
os: string;
/**
* The "browser" where this shard is running on.
*/
browser: string;
/**
* The device on which the shard is running.
*/
device: string;
}
export { COMPRESS, ShardManagerDefaults, properties };

View File

@ -1,302 +0,0 @@
import { inflateSync } from 'node:zlib';
import type { GatewayReceivePayload, GatewaySendPayload, Logger } from '@biscuitland/common';
import { GatewayCloseCodes, GatewayDispatchEvents, GatewayOpcodes } from '@biscuitland/common';
import type WS from 'ws';
import { type CloseEvent, WebSocket } from 'ws';
import { properties } from '../constants';
import { ConnectTimeout, DynamicBucket, PriorityQueue } from '../structures';
import type { ShardData, ShardOptions } from './shared';
import { ShardSocketCloseCodes } from './shared';
export class Shard {
logger: Logger;
data: Partial<ShardData> | ShardData = {
resumeSeq: null
};
websocket: WebSocket | null = null;
connectTimeout = new ConnectTimeout();
heart: {
interval: number;
nodeInterval?: NodeJS.Timeout;
lastAck?: number;
lastBeat?: number;
ack: boolean;
} = {
interval: 30e3,
ack: true
};
bucket: DynamicBucket;
offlineSendQueue = new PriorityQueue<(_?: unknown) => void>();
constructor(public id: number, protected options: ShardOptions) {
this.options.ratelimitOptions ??= {
rateLimitResetInterval: 60_000,
maxRequestsPerRateLimitTick: 120
};
this.logger = options.logger;
const safe = this.calculateSafeRequests();
this.bucket = new DynamicBucket({
limit: safe,
refillAmount: safe,
refillInterval: 6e4,
logger: this.logger
});
}
get latency() {
return this.heart.lastAck && this.heart.lastBeat ? this.heart.lastAck - this.heart.lastBeat : Infinity;
}
get isOpen() {
return this.websocket?.readyState === WebSocket.OPEN;
}
get gatewayURL() {
return this.options.info.url;
}
get resumeGatewayURL() {
return this.data.resume_gateway_url;
}
get currentGatewayURL() {
return this.resumeGatewayURL ?? this.options.info.url;
}
async connect() {
await this.connectTimeout.wait();
this.logger.debug(`[Shard #${this.id}] Connecting to ${this.currentGatewayURL}`);
this.websocket = new WebSocket(this.currentGatewayURL);
this.websocket!.onmessage = (event) => this.handleMessage(event);
this.websocket!.onclose = (event) => this.handleClosed(event);
this.websocket!.onerror = (event) => this.logger.error(event);
this.websocket!.onopen = () => {
this.heart.ack = true;
};
}
async send<T extends GatewaySendPayload = GatewaySendPayload>(priority: number, message: T) {
this.logger.info(`[Shard #${this.id}] Sending: ${GatewayOpcodes[message.op]} ${JSON.stringify(message.d, null, 1)}`);
await this.checkOffline(priority);
await this.bucket.acquire(priority);
await this.checkOffline(priority);
this.websocket?.send(JSON.stringify(message));
}
async identify() {
await this.send(0, {
op: GatewayOpcodes.Identify,
d: {
token: `Bot ${this.options.token}`,
compress: this.options.compress,
properties,
shard: [this.id, this.options.info.shards],
intents: this.options.intents,
presence: this.options.presence
}
});
}
get resumable() {
return !!(this.data.resume_gateway_url && this.data.session_id && this.data.resumeSeq !== null);
}
async resume() {
await this.send(0, {
op: GatewayOpcodes.Resume,
d: {
seq: this.data.resumeSeq!,
session_id: this.data.session_id!,
token: `Bot ${this.options.token}`
}
});
}
async heartbeat(requested: boolean) {
this.logger.debug(`[Shard #${this.id}] Sending ${requested ? '' : 'un'}requested heartbeat (Ack=${this.heart.ack})`);
if (!requested) {
if (!this.heart.ack) {
await this.close(ShardSocketCloseCodes.ZombiedConnection, 'Zombied connection');
return;
}
this.heart.ack = false;
}
this.heart.lastBeat = Date.now();
this.websocket!.send(
JSON.stringify({
op: GatewayOpcodes.Heartbeat,
d: this.data.resumeSeq ?? null
})
);
}
async disconnect() {
this.logger.info(`[Shard #${this.id}] Disconnecting`);
await this.close(ShardSocketCloseCodes.Shutdown, 'Shard down request');
}
async reconnect() {
this.logger.info(`[Shard #${this.id}] Reconnecting`);
await this.disconnect();
await this.connect();
}
async onpacket(packet: GatewayReceivePayload) {
if (packet.s !== null) {
this.data.resumeSeq = packet.s;
}
this.logger.debug(`[Shard #${this.id}]`, packet.t ? packet.t : GatewayOpcodes[packet.op], this.data.resumeSeq);
switch (packet.op) {
case GatewayOpcodes.Hello:
clearInterval(this.heart.nodeInterval);
this.heart.interval = packet.d.heartbeat_interval;
// await delay(Math.ceil(this.heart.interval * (Math.random() || 0.5)));
await this.heartbeat(false);
this.heart.nodeInterval = setInterval(() => this.heartbeat(false), this.heart.interval);
if (this.resumable) {
return this.resume();
}
await this.identify();
break;
case GatewayOpcodes.HeartbeatAck:
this.heart.ack = true;
this.heart.lastAck = Date.now();
break;
case GatewayOpcodes.Heartbeat:
this.heartbeat(true);
break;
case GatewayOpcodes.Reconnect:
await this.reconnect();
break;
case GatewayOpcodes.InvalidSession:
if (packet.d) {
if (!this.resumable) {
return this.logger.fatal(`[Shard #${this.id}] This is a completely unexpected error message.`);
}
await this.resume();
} else {
this.data.resumeSeq = 0;
this.data.session_id = undefined;
await this.identify();
}
break;
case GatewayOpcodes.Dispatch:
switch (packet.t) {
case GatewayDispatchEvents.Resumed:
this.offlineSendQueue.toArray().map((resolve: () => any) => resolve());
break;
case GatewayDispatchEvents.Ready:
this.data.resume_gateway_url = packet.d.resume_gateway_url;
this.data.session_id = packet.d.session_id;
this.offlineSendQueue.toArray().map((resolve: () => any) => resolve());
this.options.handlePayload(this.id, packet);
break;
default:
this.options.handlePayload(this.id, packet);
break;
}
break;
}
}
protected async handleClosed(close: CloseEvent) {
clearInterval(this.heart.nodeInterval);
this.logger.warn(`[Shard #${this.id}] ${GatewayCloseCodes[close.code] ?? close.code}`);
switch (close.code) {
case ShardSocketCloseCodes.Shutdown:
break;
case 1000:
case 1001:
case 1006:
case ShardSocketCloseCodes.ZombiedConnection:
case GatewayCloseCodes.UnknownError:
case GatewayCloseCodes.UnknownOpcode:
case GatewayCloseCodes.DecodeError:
case GatewayCloseCodes.NotAuthenticated:
case GatewayCloseCodes.AlreadyAuthenticated:
case GatewayCloseCodes.InvalidSeq:
case GatewayCloseCodes.RateLimited:
case GatewayCloseCodes.SessionTimedOut:
this.logger.info(`[Shard #${this.id}] Trying to reconnect`);
await this.reconnect();
break;
case GatewayCloseCodes.AuthenticationFailed:
case GatewayCloseCodes.DisallowedIntents:
case GatewayCloseCodes.InvalidAPIVersion:
case GatewayCloseCodes.InvalidIntents:
case GatewayCloseCodes.InvalidShard:
case GatewayCloseCodes.ShardingRequired:
this.logger.fatal(`[Shard #${this.id}] cannot reconnect`);
break;
default:
this.logger.warn(`[Shard #${this.id}] Unknown close code, trying to reconnect anyways`);
await this.reconnect();
break;
}
}
async close(code: number, reason: string) {
if (this.websocket?.readyState !== WebSocket.OPEN) {
return this.logger.warn(`${new Error('418').stack} [Shard #${this.id}] Is not open`);
}
this.logger.warn(`${new Error('418').stack} [Shard #${this.id}] Called close`);
this.websocket?.close(code, reason);
}
protected async handleMessage({ data }: WS.MessageEvent) {
if (data instanceof Buffer) {
data = inflateSync(data);
}
/**
* Idk why, but Bun sends this event when websocket connects.
* MessageEvent {
* type: "message",
* data: "Already authenticated."
* }
*/
if ((data as string).startsWith('{')) {
data = JSON.parse(data as string);
}
const packet = data as unknown as GatewayReceivePayload;
return this.onpacket(packet);
}
checkOffline(priority: number) {
if (!this.isOpen) {
return new Promise((resolve) => this.offlineSendQueue.push(resolve, priority));
}
return Promise.resolve();
}
calculateSafeRequests(): number {
const safeRequests =
this.options.ratelimitOptions!.maxRequestsPerRateLimitTick -
Math.ceil(this.options.ratelimitOptions!.rateLimitResetInterval / this.heart.interval) * 2;
if (safeRequests < 0) {
return 0;
}
return safeRequests;
}
}

View File

@ -1,161 +0,0 @@
import type {
APIGatewayBotInfo,
GatewayUpdatePresence,
GatewayVoiceStateUpdate,
// Logger,
ObjectToLower
} from '@biscuitland/common';
import { Collection, GatewayOpcodes, LogLevels, Logger, Options, toSnakeCase } from '@biscuitland/common';
import { ShardManagerDefaults } from '../constants';
import { SequentialBucket } from '../structures';
import { Shard } from './shard.js';
import type { ShardManagerOptions } from './shared';
export class ShardManager extends Collection<number, Shard> {
connectQueue: SequentialBucket;
options: ShardManagerOptions;
logger: Logger;
constructor(options: ShardManagerOptions) {
super();
this.options = Options<Required<ShardManagerOptions>>(ShardManagerDefaults, options, { info: { shards: options.totalShards } });
this.connectQueue = new SequentialBucket(this.concurrency);
this.logger = new Logger({
active: this.options.debug,
name: '[ShardManager]',
logLevel: LogLevels.Debug
});
}
get remaining(): number {
return this.options.info.session_start_limit.remaining;
}
get concurrency(): number {
return this.options.info.session_start_limit.max_concurrency;
}
calculeShardId(guildId: string) {
return Number((BigInt(guildId) >> 22n) % BigInt(this.options.totalShards ?? 1));
}
spawn(shardId: number) {
this.logger.info(`Spawn shard ${shardId}`);
let shard = this.get(shardId);
shard ??= new Shard(shardId, {
token: this.options.token,
intents: this.options.intents,
info: Options<APIGatewayBotInfo>(this.options.info, { shards: this.options.totalShards }),
handlePayload: this.options.handlePayload,
properties: this.options.properties,
logger: this.logger,
compress: false,
presence: this.options.presence
});
this.set(shardId, shard);
return shard;
}
async spawnShards(): Promise<void> {
const buckets = this.spawnBuckets();
this.logger.info('Spawn shards');
for (const bucket of buckets) {
for (const shard of bucket) {
if (!shard) {
break;
}
this.logger.info(`${shard.id} add to connect queue`);
await this.connectQueue.push(shard.connect.bind(shard));
}
}
}
/*
* spawns buckets in order
* https://discord.com/developers/docs/topics/gateway#sharding-max-concurrency
*/
spawnBuckets(): Shard[][] {
this.logger.info('#0 Preparing buckets');
const chunks = SequentialBucket.chunk(new Array(this.options.totalShards), this.concurrency);
// biome-ignore lint/complexity/noForEach: in maps its okay
chunks.forEach((arr: any[], index: number) => {
for (let i = 0; i < arr.length; i++) {
const id = i + (index > 0 ? index * this.concurrency : 0);
chunks[index][i] = this.spawn(id);
}
});
this.logger.info(`${chunks.length} buckets created`);
return chunks;
}
forceIdentify(shardId: number) {
this.logger.info(`Shard #${shardId} force identify`);
return this.spawn(shardId).identify();
}
disconnect(shardId: number) {
this.logger.info(`Force disconnect shard ${shardId}`);
return this.get(shardId)?.disconnect();
}
disconnectAll() {
this.logger.info('Disconnect all shards');
return new Promise((_resolve) => {
// biome-ignore lint/complexity/noForEach: in maps its okay
this.forEach((shard) => shard.disconnect());
_resolve(null);
});
}
setShardPresence(shardId: number, payload: GatewayUpdatePresence['d']) {
this.logger.info(`Shard #${shardId} update presence`);
return this.get(shardId)?.send<GatewayUpdatePresence>(1, {
op: GatewayOpcodes.PresenceUpdate,
d: payload
});
}
setPresence(payload: GatewayUpdatePresence['d']): Promise<void> | undefined {
return new Promise((_resolve) => {
// biome-ignore lint/complexity/noForEach: in maps its okay
this.forEach((_shard) => {
this.setShardPresence(_shard.id, payload);
}, this);
_resolve();
});
}
joinVoice(guild_id: string, channel_id: string, options: ObjectToLower<Pick<GatewayVoiceStateUpdate['d'], 'self_deaf' | 'self_mute'>>) {
const shardId = this.calculeShardId(guild_id);
this.logger.info(`Shard #${shardId} join voice ${channel_id} in ${guild_id}`);
return this.get(shardId)?.send<GatewayVoiceStateUpdate>(1, {
op: GatewayOpcodes.VoiceStateUpdate,
d: {
guild_id,
channel_id,
...toSnakeCase(options)
}
});
}
leaveVoice(guild_id: string) {
const shardId = this.calculeShardId(guild_id);
this.logger.info(`Shard #${shardId} leave voice in ${guild_id}`);
return this.get(shardId)?.send<GatewayVoiceStateUpdate>(1, {
op: GatewayOpcodes.VoiceStateUpdate,
d: {
guild_id,
channel_id: null,
self_mute: false,
self_deaf: false
}
});
}
}

View File

@ -1,83 +0,0 @@
import type { APIGatewayBotInfo, GatewayDispatchPayload, GatewayIntentBits, GatewayPresenceUpdateData, Logger } from '@biscuitland/common';
import type { IdentifyProperties } from '../constants';
export interface ShardManagerOptions extends ShardDetails {
/** Important data which is used by the manager to connect shards to the gateway. */
info: APIGatewayBotInfo;
/**
* Delay in milliseconds to wait before spawning next shard. OPTIMAL IS ABOVE 5100. YOU DON'T WANT TO HIT THE RATE LIMIT!!!
* @default 5300
*/
spawnShardDelay?: number;
/**
* Total amount of shards your bot uses. Useful for zero-downtime updates or resharding.
* @default 1
*/
totalShards?: number;
/**
* The payload handlers for messages on the shard.
*/
handlePayload(shardId: number, packet: GatewayDispatchPayload): unknown;
/**
* wheter to send debug information to the console
*/
debug?: boolean;
presence?: GatewayPresenceUpdateData;
}
export interface ShardData {
/** resume seq to resume connections */
resumeSeq: number | null;
/**
* resume_gateway_url is the url to resume the connection
* @link https://discord.com/developers/docs/topics/gateway#ready-event
*/
resume_gateway_url?: string;
/**
* session_id is the unique session id of the gateway
* do not mistake with the biscuit client which is named Session
*/
session_id?: string;
}
export interface ShardDetails {
/** Bot token which is used to connect to Discord */
token: string;
/**
* The URL of the gateway which should be connected to.
* @default "wss://gateway.discord.gg"
*/
url?: string;
/**
* The gateway version which should be used.
* @default 10
*/
version?: number;
/**
* The calculated intent value of the events which the shard should receive.
*/
intents: GatewayIntentBits | number;
/**
* Identify properties to use
*/
properties?: IdentifyProperties;
}
export interface ShardOptions extends ShardDetails {
info: APIGatewayBotInfo;
handlePayload(shardId: number, packet: GatewayDispatchPayload): unknown;
ratelimitOptions?: {
maxRequestsPerRateLimitTick: number;
rateLimitResetInterval: number;
};
logger: Logger;
compress: boolean;
presence?: GatewayPresenceUpdateData;
}
export enum ShardSocketCloseCodes {
Shutdown = 3000,
ZombiedConnection = 3010
}

View File

@ -1,343 +0,0 @@
import type { Logger } from '@biscuitland/common';
import { delay } from '@biscuitland/common';
export * from './timeout';
/**
* just any kind of request to queue and resolve later
*/
export type QueuedRequest = (value: void | Promise<void>) => Promise<unknown> | any;
/**
* options of the dynamic bucket
*/
export interface DynamicBucketOptions {
limit: number;
refillInterval: number;
refillAmount: number;
logger: Logger;
}
/**
* generally useless for interaction based bots
* ideally this would only be triggered on certain paths
* example: a huge amount of messages being spammed
*
* a dynamic bucket is just a priority queue implemented using linked lists
* we create an empty bucket for every path
* dynamically allocating memory improves the final memory footprint
*/
export class DynamicBucket {
limit: number;
refillInterval: number;
refillAmount: number;
/** The queue of requests to acquire an available request. Mapped by <shardId, resolve()> */
queue = new PriorityQueue<QueuedRequest>();
/** The amount of requests that have been used up already. */
used = 0;
/** Whether or not the queue is already processing. */
processing = false;
/** The timeout id for the timer to reduce the used amount by the refill amount. */
timeoutId?: NodeJS.Timeout;
/** The timestamp in milliseconds when the next refill is scheduled. */
refillsAt?: number;
logger: Logger;
constructor(options: DynamicBucketOptions) {
this.limit = options.limit;
this.refillInterval = options.refillInterval;
this.refillAmount = options.refillAmount;
this.logger = options.logger;
}
get remaining(): number {
if (this.limit < this.used) {
return 0;
}
return this.limit - this.used;
}
refill(): void {
// Lower the used amount by the refill amount
this.used = this.refillAmount > this.used ? 0 : this.used - this.refillAmount;
// Reset the refillsAt timestamp since it just got refilled
this.refillsAt = undefined;
if (this.used > 0) {
if (this.timeoutId) {
clearTimeout(this.timeoutId);
}
this.timeoutId = setTimeout(() => {
this.refill();
}, this.refillInterval);
this.refillsAt = Date.now() + this.refillInterval;
}
}
/** Begin processing the queue. */
async processQueue(): Promise<void> {
// There is already a queue that is processing
if (this.processing) {
return;
}
// Begin going through the queue.
while (!this.queue.isEmpty()) {
if (this.remaining) {
this.logger.debug(`Processing queue. Remaining: ${this.remaining} Length: ${this.queue.size()}`);
// Resolves the promise allowing the paused execution of this request to resolve and continue.
this.queue.peek()();
this.queue.pop();
// A request can be made
this.used++;
// Create a new timeout for this request if none exists.
if (!this.timeoutId) {
this.timeoutId = setTimeout(() => {
this.refill();
}, this.refillInterval);
// Set the time for when this refill will occur.
this.refillsAt = Date.now() + this.refillInterval;
}
// Check if a refill is scheduled, since we have used up all available requests
} else if (this.refillsAt) {
const now = Date.now();
// If there is time left until next refill, just delay execution.
if (this.refillsAt > now) {
await delay(this.refillsAt - now);
}
}
}
// Loop has ended mark false so it can restart later when needed
this.processing = false;
}
/** Pauses the execution until the request is available to be made. */
async acquire(priority: number): Promise<void> {
return await new Promise((_resolve) => {
this.queue.push(_resolve, priority);
// biome-ignore lint/complexity/noVoid: <explanation>
void this.processQueue();
});
}
toString() {
return [...this.queue].toString();
}
}
/**
* abstract node lol
*/
export interface AbstractNode<T> {
data: T;
next: this | null;
}
export interface QueuePusher<T> {
push(data: T): NonNullable<TNode<T>>;
}
export interface QueuePusherWithPriority<T> {
push(data: T, priority: number): NonNullable<PNode<T>>;
}
export class TNode<T> implements AbstractNode<T> {
data: T;
next: this | null;
constructor(data: T) {
this.data = data;
this.next = null;
}
static null<T>(list: AbstractNode<T> | null): list is null {
return !list;
}
}
export class PNode<T> extends TNode<T> {
priority: number;
constructor(data: T, priority: number) {
super(data);
this.priority = priority;
}
}
export abstract class Queue<T> {
protected abstract head: AbstractNode<T> | null;
/**
* O(1)
*/
public pop() {
if (TNode.null(this.head)) {
throw new Error('cannot pop a list without elements');
}
return (this.head = this.head.next);
}
/**
* O(1)
*/
public peek(): T {
if (TNode.null(this.head)) {
throw new Error('cannot peek an empty list');
}
return this.head.data;
}
/**
* O(n)
*/
public size(): number {
let aux = this.head;
if (TNode.null(aux)) {
return 0;
}
let count = 1;
while (aux.next !== null) {
count++;
aux = aux.next;
}
return count;
}
/**
* O(1)
*/
public isEmpty() {
return TNode.null(this.head);
}
*[Symbol.iterator](): IterableIterator<T> {
let temp = this.head;
while (temp !== null) {
yield temp.data;
temp = temp.next;
}
}
public toArray(): T[] {
return Array.from(this);
}
public toString() {
return this.head?.toString() || '';
}
}
export class LinkedList<T> extends Queue<T> implements QueuePusher<T> {
protected head: TNode<T> | null = null;
/**
* O(1)
*/
public push(data: T): NonNullable<TNode<T>> {
const temp = new TNode<T>(data);
temp.next = this.head;
this.head = temp;
return this.head;
}
}
export class PriorityQueue<T> extends Queue<T> implements QueuePusherWithPriority<T> {
protected head: PNode<T> | null = null;
/**
* O(#priorities)
*/
public push(data: T, priority: number): NonNullable<PNode<T>> {
let start = this.head;
const temp = new PNode(data, priority);
if (TNode.null(this.head) || TNode.null(start)) {
this.head = temp;
return this.head;
}
if (this.head.priority > priority) {
temp.next = this.head;
this.head = temp;
return this.head;
}
while (start.next !== null && start.next.priority < priority) {
start = start.next;
}
temp.next = start.next as PNode<T>;
start.next = temp;
return this.head;
}
}
export class SequentialBucket {
private connections: LinkedList<QueuedRequest>;
private capacity: number; // max_concurrency
private spawnTimeout: number;
constructor(maxCapacity: number) {
this.connections = new LinkedList();
this.capacity = maxCapacity;
this.spawnTimeout = 5000;
}
public async destroy() {
this.connections = new LinkedList();
}
public async push(promise: QueuedRequest) {
this.connections.push(promise);
if (this.capacity <= this.connections.size()) {
await this.acquire();
await delay(this.spawnTimeout);
}
return;
}
public async acquire(promises = this.connections) {
while (!promises.isEmpty()) {
const item = promises.peek();
item().catch((...args: any[]) => {
Promise.reject(...args);
});
promises.pop();
}
return Promise.resolve(true);
}
public static chunk<T>(array: T[], chunks: number): T[][] {
let index = 0;
let resIndex = 0;
const result = Array(Math.ceil(array.length / chunks));
while (index < array.length) {
result[resIndex] = array.slice(index, (index += chunks));
resIndex++;
}
return result;
}
}

View File

@ -1,28 +0,0 @@
export class ConnectTimeout {
promises: { promise: Promise<boolean>; resolve: (x: boolean) => any }[] = [];
interval?: NodeJS.Timeout = undefined;
// biome-ignore lint/nursery/noEmptyBlockStatements: <explanation>
constructor(readonly intervalTime = 5000) {}
wait() {
let resolve = (_x: boolean) => {
//
};
const promise = new Promise<boolean>((r) => (resolve = r));
if (!this.promises.length) {
this.interval = setInterval(() => {
this.shift();
}, this.intervalTime);
}
this.promises.push({ resolve, promise });
return promise;
}
shift() {
this.promises.shift()?.resolve(true);
if (!this.promises.length) {
clearInterval(this.interval);
this.interval = undefined;
}
}
}

View File

@ -1,9 +0,0 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist"
},
"include": [
"src/**/*"
]
}

View File

@ -1,12 +0,0 @@
import { defineConfig } from 'tsup';
const isProduction = process.env.NODE_ENV === 'production';
export default defineConfig({
clean: true,
dts: true,
entry: ['src/index.ts'],
format: ['cjs', 'esm'],
minify: isProduction,
sourcemap: false
});

View File

@ -1,6 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base"
]
}

328
src/api/CDN.ts Normal file
View File

@ -0,0 +1,328 @@
/* eslint-disable jsdoc/check-param-names */
import { CDN_URL } from '../common/index.js';
import {
ALLOWED_EXTENSIONS,
ALLOWED_SIZES,
ALLOWED_STICKER_EXTENSIONS,
type ImageExtension,
type ImageSize,
type StickerExtension,
} from './utils/constants.js';
/**
* The options used for image URLs
*/
export interface BaseImageURLOptions {
/**
* The extension to use for the image URL
*
* @defaultValue `'webp'`
*/
extension?: ImageExtension;
/**
* The size specified in the image URL
*/
size?: ImageSize;
}
/**
* The options used for image URLs with animated content
*/
export interface ImageURLOptions extends BaseImageURLOptions {
/**
* Whether or not to prefer the static version of an image asset.
*/
forceStatic?: boolean;
}
/**
* The options to use when making a CDN URL
*/
export interface MakeURLOptions {
/**
* The allowed extensions that can be used
*/
allowedExtensions?: readonly string[];
/**
* The extension to use for the image URL
*
* @defaultValue `'webp'`
*/
extension?: string | undefined;
/**
* The size specified in the image URL
*/
size?: ImageSize;
}
/**
* The CDN link builder
*/
export class CDN {
public constructor(private readonly base: string = CDN_URL) {}
/**
* Generates an app asset URL for a client's asset.
*
* @param clientId - The client id that has the asset
* @param assetHash - The hash provided by Discord for this asset
* @param options - Optional options for the asset
*/
public appAsset(clientId: string, assetHash: string, options?: Readonly<BaseImageURLOptions>): string {
return this.makeURL(`/app-assets/${clientId}/${assetHash}`, options);
}
/**
* Generates an app icon URL for a client's icon.
*
* @param clientId - The client id that has the icon
* @param iconHash - The hash provided by Discord for this icon
* @param options - Optional options for the icon
*/
public appIcon(clientId: string, iconHash: string, options?: Readonly<BaseImageURLOptions>): string {
return this.makeURL(`/app-icons/${clientId}/${iconHash}`, options);
}
/**
* Generates an avatar URL, e.g. for a user or a webhook.
*
* @param id - The id that has the icon
* @param avatarHash - The hash provided by Discord for this avatar
* @param options - Optional options for the avatar
*/
public avatar(id: string, avatarHash: string, options?: Readonly<ImageURLOptions>): string {
return this.dynamicMakeURL(`/avatars/${id}/${avatarHash}`, avatarHash, options);
}
/**
* Generates a user avatar decoration URL.
*
* @param userId - The id of the user
* @param userAvatarDecoration - The hash provided by Discord for this avatar decoration
* @param options - Optional options for the avatar decoration
*/
public avatarDecoration(
userId: string,
userAvatarDecoration: string,
options?: Readonly<BaseImageURLOptions>,
): string {
return this.makeURL(`/avatar-decorations/${userId}/${userAvatarDecoration}`, options);
}
/**
* Generates a banner URL, e.g. for a user or a guild.
*
* @param id - The id that has the banner splash
* @param bannerHash - The hash provided by Discord for this banner
* @param options - Optional options for the banner
*/
public banner(id: string, bannerHash: string, options?: Readonly<ImageURLOptions>): string {
return this.dynamicMakeURL(`/banners/${id}/${bannerHash}`, bannerHash, options);
}
/**
* Generates an icon URL for a channel, e.g. a group DM.
*
* @param channelId - The channel id that has the icon
* @param iconHash - The hash provided by Discord for this channel
* @param options - Optional options for the icon
*/
public channelIcon(channelId: string, iconHash: string, options?: Readonly<BaseImageURLOptions>): string {
return this.makeURL(`/channel-icons/${channelId}/${iconHash}`, options);
}
/**
* Generates a default avatar URL
*
* @param index - The default avatar index
* @remarks
* To calculate the index for a user do `(userId >> 22) % 6`,
* or `discriminator % 5` if they're using the legacy username system.
*/
public defaultAvatar(index: number): string {
return this.makeURL(`/embed/avatars/${index}`, { extension: 'png' });
}
/**
* Generates a discovery splash URL for a guild's discovery splash.
*
* @param guildId - The guild id that has the discovery splash
* @param splashHash - The hash provided by Discord for this splash
* @param options - Optional options for the splash
*/
public discoverySplash(guildId: string, splashHash: string, options?: Readonly<BaseImageURLOptions>): string {
return this.makeURL(`/discovery-splashes/${guildId}/${splashHash}`, options);
}
/**
* Generates an emoji's URL for an emoji.
*
* @param emojiId - The emoji id
* @param options - Optional options for the emoji
*/
public emoji(emojiId: string, options?: Readonly<BaseImageURLOptions>): string {
const resolvedOptions = options;
return this.makeURL(`/emojis/${emojiId}`, resolvedOptions);
}
/**
* Generates a guild member avatar URL.
*
* @param guildId - The id of the guild
* @param userId - The id of the user
* @param avatarHash - The hash provided by Discord for this avatar
* @param options - Optional options for the avatar
*/
public guildMemberAvatar(
guildId: string,
userId: string,
avatarHash: string,
options?: Readonly<ImageURLOptions>,
): string {
return this.dynamicMakeURL(`/guilds/${guildId}/users/${userId}/avatars/${avatarHash}`, avatarHash, options);
}
/**
* Generates a guild member banner URL.
*
* @param guildId - The id of the guild
* @param userId - The id of the user
* @param bannerHash - The hash provided by Discord for this banner
* @param options - Optional options for the banner
*/
public guildMemberBanner(
guildId: string,
userId: string,
bannerHash: string,
options?: Readonly<ImageURLOptions>,
): string {
return this.dynamicMakeURL(`/guilds/${guildId}/users/${userId}/banner`, bannerHash, options);
}
/**
* Generates an icon URL, e.g. for a guild.
*
* @param id - The id that has the icon splash
* @param iconHash - The hash provided by Discord for this icon
* @param options - Optional options for the icon
*/
public icon(id: string, iconHash: string, options?: Readonly<ImageURLOptions>): string {
return this.dynamicMakeURL(`/icons/${id}/${iconHash}`, iconHash, options);
}
/**
* Generates a URL for the icon of a role
*
* @param roleId - The id of the role that has the icon
* @param roleIconHash - The hash provided by Discord for this role icon
* @param options - Optional options for the role icon
*/
public roleIcon(roleId: string, roleIconHash: string, options?: Readonly<BaseImageURLOptions>): string {
return this.makeURL(`/role-icons/${roleId}/${roleIconHash}`, options);
}
/**
* Generates a guild invite splash URL for a guild's invite splash.
*
* @param guildId - The guild id that has the invite splash
* @param splashHash - The hash provided by Discord for this splash
* @param options - Optional options for the splash
*/
public splash(guildId: string, splashHash: string, options?: Readonly<BaseImageURLOptions>): string {
return this.makeURL(`/splashes/${guildId}/${splashHash}`, options);
}
/**
* Generates a sticker URL.
*
* @param stickerId - The sticker id
* @param extension - The extension of the sticker
* @privateRemarks
* Stickers cannot have a `.webp` extension, so we default to a `.png`
*/
public sticker(stickerId: string, extension: StickerExtension = 'png'): string {
return this.makeURL(`/stickers/${stickerId}`, { allowedExtensions: ALLOWED_STICKER_EXTENSIONS, extension });
}
/**
* Generates a sticker pack banner URL.
*
* @param bannerId - The banner id
* @param options - Optional options for the banner
*/
public stickerPackBanner(bannerId: string, options?: Readonly<BaseImageURLOptions>): string {
return this.makeURL(`/app-assets/710982414301790216/store/${bannerId}`, options);
}
/**
* Generates a team icon URL for a team's icon.
*
* @param teamId - The team id that has the icon
* @param iconHash - The hash provided by Discord for this icon
* @param options - Optional options for the icon
*/
public teamIcon(teamId: string, iconHash: string, options?: Readonly<BaseImageURLOptions>): string {
return this.makeURL(`/team-icons/${teamId}/${iconHash}`, options);
}
/**
* Generates a cover image for a guild scheduled event.
*
* @param scheduledEventId - The scheduled event id
* @param coverHash - The hash provided by discord for this cover image
* @param options - Optional options for the cover image
*/
public guildScheduledEventCover(
scheduledEventId: string,
coverHash: string,
options?: Readonly<BaseImageURLOptions>,
): string {
return this.makeURL(`/guild-events/${scheduledEventId}/${coverHash}`, options);
}
/**
* Constructs the URL for the resource, checking whether or not `hash` starts with `a_` if `dynamic` is set to `true`.
*
* @param route - The base cdn route
* @param hash - The hash provided by Discord for this icon
* @param options - Optional options for the link
*/
private dynamicMakeURL(
route: string,
hash: string,
{ forceStatic = false, ...options }: Readonly<ImageURLOptions> = {},
): string {
return this.makeURL(route, !forceStatic && hash.startsWith('a_') ? { ...options, extension: 'gif' } : options);
}
/**
* Constructs the URL for the resource
*
* @param route - The base cdn route
* @param options - The extension/size options for the link
*/
private makeURL(
route: string,
{ allowedExtensions = ALLOWED_EXTENSIONS, extension = 'webp', size }: Readonly<MakeURLOptions> = {},
): string {
// eslint-disable-next-line no-param-reassign
extension = String(extension).toLowerCase();
if (!allowedExtensions.includes(extension)) {
throw new RangeError(`Invalid extension provided: ${extension}\nMust be one of: ${allowedExtensions.join(', ')}`);
}
if (size && !ALLOWED_SIZES.includes(size)) {
throw new RangeError(`Invalid size provided: ${size}\nMust be one of: ${ALLOWED_SIZES.join(', ')}`);
}
const url = new URL(`${this.base}${route}.${extension}`);
if (size) {
url.searchParams.set('size', String(size));
}
return url.toString();
}
}

13
src/api/README.md Normal file
View File

@ -0,0 +1,13 @@
<div align='center'>
# **Seyfert**
<img src="../../assets/icon.png" alt="seyfert" width="200px" />
**A brand new bleeding edge non bloated Discord framework**
[![License](https://img.shields.io/npm/l/seyfert?style=flat-square&logo=apache&color=white)](https://github.com/tiramisulabs/biscuit/blob/main/LICENSE)
[![Version](https://img.shields.io/npm/v/seyfert?color=%23ff0000&logo=npm&style=flat-square)](https://www.npmjs.com/package/seyfert)
[![Discord](https://img.shields.io/discord/1003825077969764412?color=%23406da2&label=support&logo=discord&style=flat-square)](https://discord.com/invite/XNw2RZFzaP)
</div>

64
src/api/Router.ts Normal file
View File

@ -0,0 +1,64 @@
import { CDN_URL } from '../common';
import type { APIRoutes, ApiHandler, CDNRoute } from './index';
import type { HttpMethods } from './shared';
export enum ProxyRequestMethod {
Delete = 'delete',
Get = 'get',
Patch = 'patch',
Post = 'post',
Put = 'put',
}
const ArrRequestsMethods = Object.freeze(Object.values(ProxyRequestMethod)) as string[];
export class Router {
noop = () => {
return;
};
constructor(private rest: ApiHandler) {}
createProxy(route = [] as string[]): APIRoutes {
return new Proxy(this.noop, {
get: (_, key: string) => {
if (ArrRequestsMethods.includes(key)) {
return (...options: any[]) =>
this.rest.request(key.toUpperCase() as HttpMethods, `/${route.join('/')}`, ...options);
}
return this.createProxy([...route, key]);
},
apply: (...[, _, args]) => {
return this.createProxy([...route, ...args.filter(x => x != null)]);
},
}) as unknown as APIRoutes;
}
}
export const CDNRouter = {
createProxy(route = [] as string[]): CDNRoute {
const noop = () => {
return;
};
return new Proxy(noop, {
get: (_, key: string) => {
if (key === 'get') {
return (value?: string) => {
const lastRoute = `${CDN_URL}/${route.join('/')}`;
if (value) {
if (typeof value !== 'string') {
value = String(value);
}
return `${lastRoute}/${value}`;
}
return lastRoute;
};
}
return this.createProxy([...route, key]);
},
apply: (...[, _, args]) => {
return this.createProxy([...route, ...args.filter(x => x != null)]);
},
}) as unknown as CDNRoute;
},
};

View File

@ -0,0 +1,105 @@
import type {
RESTGetAPIApplicationCommandResult,
RESTGetAPIApplicationCommandsQuery,
RESTGetAPIApplicationCommandsResult,
RESTGetAPIApplicationGuildCommandResult,
RESTGetAPIApplicationGuildCommandsQuery,
RESTGetAPIApplicationGuildCommandsResult,
RESTGetAPIApplicationRoleConnectionMetadataResult,
RESTGetAPIGuildApplicationCommandsPermissionsResult,
RESTPatchAPIApplicationCommandJSONBody,
RESTPatchAPIApplicationCommandResult,
RESTPatchAPIApplicationGuildCommandJSONBody,
RESTPatchAPIApplicationGuildCommandResult,
RESTPostAPIApplicationCommandsJSONBody,
RESTPostAPIApplicationCommandsResult,
RESTPostAPIApplicationGuildCommandsJSONBody,
RESTPostAPIApplicationGuildCommandsResult,
RESTPutAPIApplicationCommandPermissionsJSONBody,
RESTPutAPIApplicationCommandsJSONBody,
RESTPutAPIApplicationCommandsResult,
RESTPutAPIApplicationGuildCommandsJSONBody,
RESTPutAPIApplicationGuildCommandsResult,
RESTPutAPIApplicationRoleConnectionMetadataJSONBody,
RESTPutAPIApplicationRoleConnectionMetadataResult,
RESTPutAPIGuildApplicationCommandsPermissionsResult,
} from '../../common';
import type { RestArguments } from '../api';
import type { ProxyRequestMethod } from '../Router';
export interface ApplicationRoutes {
applications: {
(
id: string,
): {
guilds: {
(
id: string,
): {
commands: {
get(
args?: RestArguments<ProxyRequestMethod.Get, RESTGetAPIApplicationGuildCommandsQuery>,
): Promise<RESTGetAPIApplicationGuildCommandsResult>;
post(
args: RestArguments<ProxyRequestMethod.Post, RESTPostAPIApplicationGuildCommandsJSONBody>,
): Promise<RESTPostAPIApplicationGuildCommandsResult>;
put(
args?: RestArguments<ProxyRequestMethod.Put, RESTPutAPIApplicationGuildCommandsJSONBody>,
): Promise<RESTPutAPIApplicationGuildCommandsResult>;
permissions: {
get(
args?: RestArguments<ProxyRequestMethod.Get>,
): Promise<RESTGetAPIGuildApplicationCommandsPermissionsResult>;
// put(args?: RestArguments<ProxyRequestMethod.Put, RESTPutAPIGuildApplicationCommandsPermissionsJSONBody>): Promise<RESTPutAPIGuildApplicationCommandsPermissionsResult>
};
(
id: string,
): {
get(args?: RestArguments<ProxyRequestMethod.Get>): Promise<RESTGetAPIApplicationGuildCommandResult>;
patch(
args: RestArguments<ProxyRequestMethod.Patch, RESTPatchAPIApplicationGuildCommandJSONBody>,
): Promise<RESTPatchAPIApplicationGuildCommandResult>;
delete(args?: RestArguments<ProxyRequestMethod.Delete>): Promise<never>;
permissions: {
get(
args?: RestArguments<ProxyRequestMethod.Get>,
): Promise<RESTGetAPIGuildApplicationCommandsPermissionsResult>;
put(
args?: RestArguments<ProxyRequestMethod.Put, RESTPutAPIApplicationCommandPermissionsJSONBody>,
): Promise<RESTPutAPIGuildApplicationCommandsPermissionsResult>;
};
};
};
};
};
commands: {
get(
args?: RestArguments<ProxyRequestMethod.Get, RESTGetAPIApplicationCommandsQuery>,
): Promise<RESTGetAPIApplicationCommandsResult>;
post(
args: RestArguments<ProxyRequestMethod.Post, RESTPostAPIApplicationCommandsJSONBody>,
): Promise<RESTPostAPIApplicationCommandsResult>;
put(
args?: RestArguments<ProxyRequestMethod.Put, RESTPutAPIApplicationCommandsJSONBody>,
): Promise<RESTPutAPIApplicationCommandsResult>;
(
id: string,
): {
get(args?: RestArguments<ProxyRequestMethod.Get>): Promise<RESTGetAPIApplicationCommandResult>;
patch(
args: RestArguments<ProxyRequestMethod.Patch, RESTPatchAPIApplicationCommandJSONBody>,
): Promise<RESTPatchAPIApplicationCommandResult>;
delete(args?: RestArguments<ProxyRequestMethod.Delete>): Promise<never>;
};
};
'role-connections': {
metadata: {
get(args?: RestArguments<ProxyRequestMethod.Get>): Promise<RESTGetAPIApplicationRoleConnectionMetadataResult>;
put(
args: RestArguments<ProxyRequestMethod.Put, RESTPutAPIApplicationRoleConnectionMetadataJSONBody>,
): Promise<RESTPutAPIApplicationRoleConnectionMetadataResult>;
};
};
};
};
}

68
src/api/Routes/cdn.ts Normal file
View File

@ -0,0 +1,68 @@
export interface CDNRoute {
embed: {
avatars: {
get(embed: UserAvatarDefault): string;
};
};
avatars(id: string): {
get(hash: string): string;
};
icons(guildId: string): {
get(hash: string): string;
};
splashes(guildId: string): {
get(hash: string): string;
};
'discovery-splashes'(guidId: string): {
get(hash: string): string;
};
banners(id: string): {
get(hash: string): string;
};
guilds(id: string): {
users(id: string): {
avatars(hash: string): {
get(): string;
};
banners(hash: string): {
get(): string;
};
};
};
emojis(id: string): {
get(): string;
};
appIcons(appId: string): {
get(iconOrCover: string): string;
};
'app-assets'(appId: string): {
get(asset: string): string;
achievements(id: string): {
icons(hash: string): {
get(): string;
};
};
};
'team-icons'(teamId: string): {
get(hash: string): string;
};
stickers(id: string): {
get(): string;
};
'role-icons'(roleId: string): {
get(icon: string): string;
};
'guild-events'(id: string): {
get(cover: string): string;
};
}
export interface CDNRoute {
'app-assets'(id: '710982414301790216'): {
store(packBannerId: string): {
get(): string;
};
};
}
export type UserAvatarDefault = 1 | 2 | 3 | 4 | 5 | number;

Some files were not shown because too many files have changed in this diff Show More