Fix up some bugs with backend discord+google integration
This commit is contained in:
parent
5c93676b32
commit
ad957f15be
1
node_modules/discord-oauth2/.eslintignore
generated
vendored
Normal file
1
node_modules/discord-oauth2/.eslintignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
node_modules
|
35
node_modules/discord-oauth2/.eslintrc.json
generated
vendored
Normal file
35
node_modules/discord-oauth2/.eslintrc.json
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"es6": true,
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 2020
|
||||||
|
},
|
||||||
|
"extends": "eslint:recommended",
|
||||||
|
"rules": {
|
||||||
|
"semi": "error",
|
||||||
|
"no-var": "error",
|
||||||
|
"prefer-const": "error",
|
||||||
|
"keyword-spacing": "error",
|
||||||
|
"eqeqeq": "error",
|
||||||
|
"eol-last": "error",
|
||||||
|
"brace-style": ["error", "stroustrup"],
|
||||||
|
"comma-dangle": ["error", "always-multiline"],
|
||||||
|
"object-curly-spacing": ["error", "always"],
|
||||||
|
|
||||||
|
"quotes": ["error", "double", {
|
||||||
|
"allowTemplateLiterals": true
|
||||||
|
}],
|
||||||
|
|
||||||
|
"indent": ["error", "tab", {
|
||||||
|
"SwitchCase": 1,
|
||||||
|
"flatTernaryExpressions": true
|
||||||
|
}],
|
||||||
|
|
||||||
|
"object-curly-newline": ["error", {
|
||||||
|
"ExportDeclaration": "never",
|
||||||
|
"ImportDeclaration": "always"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
21
node_modules/discord-oauth2/.github/ISSUE_TEMPLATE/can-t-get-it-to-work.md
generated
vendored
Normal file
21
node_modules/discord-oauth2/.github/ISSUE_TEMPLATE/can-t-get-it-to-work.md
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: Can't get it to work
|
||||||
|
about: Use this template if you are having issues with the library (all issues opened
|
||||||
|
for issues with the library that don't follow this template will be ignored and
|
||||||
|
closed).
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: reboxer
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the error**
|
||||||
|
A clear and concise description of what the error is.
|
||||||
|
|
||||||
|
**NodeJS version**
|
||||||
|
*Your NodeJS version*
|
||||||
|
|
||||||
|
**Relevant code**
|
||||||
|
```js
|
||||||
|
// Put here the code you are using that is not working
|
||||||
|
```
|
18
node_modules/discord-oauth2/.github/workflows/ci.yml
generated
vendored
Normal file
18
node_modules/discord-oauth2/.github/workflows/ci.yml
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
name: Run ESLint
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
name: Run ESlint
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: yarn
|
||||||
|
- run: yarn run lint
|
21
node_modules/discord-oauth2/LICENSE
generated
vendored
Normal file
21
node_modules/discord-oauth2/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2019 reboxer
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
358
node_modules/discord-oauth2/README.md
generated
vendored
Normal file
358
node_modules/discord-oauth2/README.md
generated
vendored
Normal file
@ -0,0 +1,358 @@
|
|||||||
|
# discord-oauth2 [](https://www.npmjs.com/package/discord-oauth2)
|
||||||
|
|
||||||
|
A really simple to use module to use discord's OAuth2 API.
|
||||||
|
|
||||||
|
Please check out discord's OAuth2 documentation: https://discord.com/developers/docs/topics/oauth2
|
||||||
|
|
||||||
|
### Installing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install discord-oauth2
|
||||||
|
```
|
||||||
|
|
||||||
|
# Class constructor
|
||||||
|
|
||||||
|
One parameter is passed to the class constructor:
|
||||||
|
|
||||||
|
### `Options`
|
||||||
|
|
||||||
|
Since the module uses a modified version of [Eris](https://github.com/abalabahaha/eris) request handler, it takes the same options, all of them default to the default Eris Client options if no options are passed.
|
||||||
|
|
||||||
|
Request handler options:
|
||||||
|
```
|
||||||
|
requestTimeout: A number of milliseconds before requests are considered timed out.
|
||||||
|
|
||||||
|
latencyThreshold: The average request latency at which the RequestHandler will start emitting latency errors.
|
||||||
|
|
||||||
|
ratelimiterOffset: A number of milliseconds to offset the ratelimit timing calculations by.
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Others, you can pass these options to the class constructor so you don't have to pass them each time you call a function:
|
||||||
|
```
|
||||||
|
version: The Discord API version to use. Defaults to "v7".
|
||||||
|
|
||||||
|
clientId: Your application's client id.
|
||||||
|
|
||||||
|
clientSecret: Your application's client secret.
|
||||||
|
|
||||||
|
redirectUri: Your URL redirect uri.
|
||||||
|
|
||||||
|
credentials: Base64 encoding of the UTF-8 encoded credentials string of your application, you can pass this in the constructor to not pass it every time you want to use the revokeToken() method.
|
||||||
|
```
|
||||||
|
|
||||||
|
# Events
|
||||||
|
|
||||||
|
In the Eris Library, client extends the `events` modules and the client is passed to the RequestHandler so it's able to emit events, this modified RequestHandler extends `events` so it can emit the same events.
|
||||||
|
|
||||||
|
There are only two events, `debug` and `warn`.
|
||||||
|
|
||||||
|
# Methods
|
||||||
|
|
||||||
|
### `tokenRequest()`
|
||||||
|
|
||||||
|
Only takes an object with the following properties:
|
||||||
|
|
||||||
|
`clientId`: Your application's client id. Can be omitted if provided on the client constructor.
|
||||||
|
|
||||||
|
`clientSecret`: Your application's client secret. Can be omitted if provided on the client constructor.
|
||||||
|
|
||||||
|
`scope`: The scopes requested in your authorization url, can be either a space-delimited string of scopes, or an array of strings containing scopes.
|
||||||
|
|
||||||
|
`redirectUri`: Your URL redirect uri. Can be omitted if provided on the client constructor.
|
||||||
|
|
||||||
|
`grantType`: The grant type to set for the request, either authorization_code or refresh_token.
|
||||||
|
|
||||||
|
`code`: The code from the querystring (grantType `authorization_code` only).
|
||||||
|
|
||||||
|
`refreshToken`: The user's refresh token (grantType `refresh_token` only).
|
||||||
|
|
||||||
|
|
||||||
|
Returns a promise which resolves in an object with the access token.
|
||||||
|
|
||||||
|
Please refer to discord's OAuth2 [documentation](https://discord.com/developers/docs/topics/oauth2#authorization-code-grant-access-token-exchange-example) for the parameters needed.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const DiscordOauth2 = require("discord-oauth2");
|
||||||
|
const oauth = new DiscordOauth2();
|
||||||
|
|
||||||
|
oauth.tokenRequest({
|
||||||
|
clientId: "332269999912132097",
|
||||||
|
clientSecret: "937it3ow87i4ery69876wqire",
|
||||||
|
|
||||||
|
code: "query code",
|
||||||
|
scope: "identify guilds",
|
||||||
|
grantType: "authorization_code",
|
||||||
|
|
||||||
|
redirectUri: "http://localhost/callback",
|
||||||
|
}).then(console.log)
|
||||||
|
```
|
||||||
|
|
||||||
|
Using class constructor options, array of scopes and grantType refresh_token:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const DiscordOauth2 = require("discord-oauth2");
|
||||||
|
const oauth = new DiscordOauth2({
|
||||||
|
clientId: "332269999912132097",
|
||||||
|
clientSecret: "937it3ow87i4ery69876wqire",
|
||||||
|
redirectUri: "http://localhost/callback",
|
||||||
|
});
|
||||||
|
|
||||||
|
oauth.tokenRequest({
|
||||||
|
// clientId, clientSecret and redirectUri are omitted, as they were already set on the class constructor
|
||||||
|
refreshToken: "D43f5y0ahjqew82jZ4NViEr2YafMKhue",
|
||||||
|
grantType: "refresh_token",
|
||||||
|
scope: ["identify", "guilds"],
|
||||||
|
});
|
||||||
|
|
||||||
|
// On successful request both requesting and refreshing an access token return the same object
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
"access_token": "6qrZcUqja7812RVdnEKjpzOL4CvHBFG",
|
||||||
|
"token_type": "Bearer",
|
||||||
|
"expires_in": 604800,
|
||||||
|
"refresh_token": "D43f5y0ahjqew82jZ4NViEr2YafMKhue",
|
||||||
|
"scope": "identify guilds"
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
### `revokeToken()`
|
||||||
|
|
||||||
|
Takes two parameters, the first one is the access_token from the user, the second is a Base64 encoding of the UTF-8 encoded credentials string of your application.
|
||||||
|
|
||||||
|
Returns a promise which resolves in an empty object if successful.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const DiscordOauth2 = require("discord-oauth2");
|
||||||
|
const oauth = new DiscordOauth2();
|
||||||
|
|
||||||
|
const clientID = "332269999912132097";
|
||||||
|
const client_secret = "937it3ow87i4ery69876wqire";
|
||||||
|
const access_token = "6qrZcUqja7812RVdnEKjpzOL4CvHBFG";
|
||||||
|
|
||||||
|
// You must encode your client ID along with your client secret including the colon in between
|
||||||
|
const credentials = Buffer.from(`${clientID}:${client_secret}`).toString("base64"); // MzMyMjY5OTk5OTEyMTMyMDk3OjkzN2l0M293ODdpNGVyeTY5ODc2d3FpcmU=
|
||||||
|
|
||||||
|
oauth.revokeToken(access_token, credentials).then(console.log); // {}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `getUser()`
|
||||||
|
|
||||||
|
Only takes one parameter which is the user's access token.
|
||||||
|
|
||||||
|
Returns the [user](https://discord.com/developers/docs/resources/user#user-object) object of the requester's account, this requires the `identify` scope, which will return the object without an email, and optionally the `email` scope, which returns the object with an email.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const DiscordOauth2 = require("discord-oauth2");
|
||||||
|
const oauth = new DiscordOauth2();
|
||||||
|
|
||||||
|
const access_token = "6qrZcUqja7812RVdnEKjpzOL4CvHBFG";
|
||||||
|
|
||||||
|
oauth.getUser(access_token).then(console.log);
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
username: '1337 Krew',
|
||||||
|
locale: 'en-US',
|
||||||
|
mfa_enabled: true,
|
||||||
|
flags: 128,
|
||||||
|
avatar: '8342729096ea3675442027381ff50dfe',
|
||||||
|
discriminator: '4421',
|
||||||
|
id: '80351110224678912'
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
### `getUserGuilds()`
|
||||||
|
|
||||||
|
Only takes one parameter which is the user's access token.
|
||||||
|
|
||||||
|
Returns a list of partial [guild](https://discord.com/developers/docs/resources/guild#guild-object) objects the current user is a member of. Requires the `guilds` scope.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const DiscordOauth2 = require("discord-oauth2");
|
||||||
|
const oauth = new DiscordOauth2();
|
||||||
|
|
||||||
|
const access_token = "6qrZcUqja7812RVdnEKjpzOL4CvHBFG";
|
||||||
|
|
||||||
|
oauth.getUserGuilds(access_token).then(console.log);
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
"id": "80351110224678912",
|
||||||
|
"name": "1337 Krew",
|
||||||
|
"icon": "8342729096ea3675442027381ff50dfe",
|
||||||
|
"owner": true,
|
||||||
|
"permissions": 36953089,
|
||||||
|
"permissions_new": "36953089"
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
### `getUserConnections()`
|
||||||
|
|
||||||
|
Only takes one parameter which is the user's access token.
|
||||||
|
|
||||||
|
Returns a list of [connection](https://discord.com/developers/docs/resources/user#connection-object) objects. Requires the `connections` OAuth2 scope.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const DiscordOauth2 = require("discord-oauth2");
|
||||||
|
const oauth = new DiscordOauth2();
|
||||||
|
|
||||||
|
const access_token = "6qrZcUqja7812RVdnEKjpzOL4CvHBFG";
|
||||||
|
|
||||||
|
oauth.getUserConnections(access_token).then(console.log);
|
||||||
|
/*
|
||||||
|
[ { verified: true,
|
||||||
|
name: 'epicusername',
|
||||||
|
show_activity: true,
|
||||||
|
friend_sync: false,
|
||||||
|
type: 'twitch',
|
||||||
|
id: '31244565',
|
||||||
|
visibility: 1 } ]
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
### `addMember()`
|
||||||
|
|
||||||
|
Force join a user to a guild (server).
|
||||||
|
|
||||||
|
Takes an object with the following properties:
|
||||||
|
|
||||||
|
`accessToken`: The user access token.
|
||||||
|
|
||||||
|
`botToken`: The token of the bot used to authenticate.
|
||||||
|
|
||||||
|
`guildId`: The ID of the guild to join.
|
||||||
|
|
||||||
|
`userId`: The ID of the user to be added to the guild.
|
||||||
|
|
||||||
|
Optional properties (the above ones are required):
|
||||||
|
|
||||||
|
`nickname`: Value to set users nickname to.
|
||||||
|
|
||||||
|
`roles`: Array of role ids the member is assigned.
|
||||||
|
|
||||||
|
`mute`: Whether the user is muted in voice channels.
|
||||||
|
|
||||||
|
`deaf`: Whether the user is deafened in voice channels.
|
||||||
|
|
||||||
|
Returns a member object if the user wasn't part of the guild, else, returns an empty string (length 0).
|
||||||
|
|
||||||
|
```js
|
||||||
|
const DiscordOauth2 = require("discord-oauth2");
|
||||||
|
const oauth = new DiscordOauth2();
|
||||||
|
|
||||||
|
oauth.addMember({
|
||||||
|
accessToken: "2qRZcUqUa9816RVnnEKRpzOL2CvHBgF",
|
||||||
|
botToken: "NDgyMjM4ODQzNDI1MjU5NTIz.XK93JQ.bnLsc71_DGum-Qnymb4T5F6kGY8",
|
||||||
|
guildId: "216488324594438692",
|
||||||
|
userId: "80351110224678912",
|
||||||
|
|
||||||
|
nickname: "george michael",
|
||||||
|
roles: ["624615851966070786"],
|
||||||
|
mute: true,
|
||||||
|
deaf: true,
|
||||||
|
}).then(console.log); // Member object or empty string
|
||||||
|
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
nick: 'george michael',
|
||||||
|
user: {
|
||||||
|
username: 'some username',
|
||||||
|
discriminator: '0001',
|
||||||
|
id: '421610529323943943',
|
||||||
|
avatar: null
|
||||||
|
},
|
||||||
|
roles: [ '324615841966570766' ],
|
||||||
|
premium_since: null,
|
||||||
|
deaf: true,
|
||||||
|
mute: true,
|
||||||
|
joined_at: '2019-09-20T14:44:12.603123+00:00'
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
### `generateAuthUrl`
|
||||||
|
|
||||||
|
Dynamically generate an OAuth2 URL.
|
||||||
|
|
||||||
|
Takes an object with the following properties:
|
||||||
|
|
||||||
|
`clientId`: Your application's client id. Can be omitted if provided on the client constructor.
|
||||||
|
|
||||||
|
`prompt`: Controls how existing authorizations are handled, either consent or none (for passthrough scopes authorization is always required).
|
||||||
|
|
||||||
|
`scope`: The scopes requested in your authorization url, can be either a space-delimited string of scopes, or an array of strings containing scopes.
|
||||||
|
|
||||||
|
`redirectUri`: Your URL redirect uri. Can be omitted if provided on the client constructor.
|
||||||
|
|
||||||
|
`responseType`: The response type, either code or token (token is for client-side web applications only). Defaults to code.
|
||||||
|
|
||||||
|
`state`: A unique cryptographically secure string (https://discord.com/developers/docs/topics/oauth2#state-and-security).
|
||||||
|
|
||||||
|
`permissions`: The permissions number for the bot invite (only with bot scope) (https://discord.com/developers/docs/topics/permissions).
|
||||||
|
|
||||||
|
`guildId`: The guild id to pre-fill the bot invite (only with bot scope).
|
||||||
|
|
||||||
|
`disableGuildSelect`: Disallows the user from changing the guild for the bot invite, either true or false (only with bot scope).
|
||||||
|
|
||||||
|
```js
|
||||||
|
const crypto = require('crypto')
|
||||||
|
const DiscordOauth2 = require("discord-oauth2");
|
||||||
|
const oauth = new DiscordOauth2({
|
||||||
|
clientId: "332269999912132097",
|
||||||
|
clientSecret: "937it3ow87i4ery69876wqire",
|
||||||
|
redirectUri: "http://localhost/callback",
|
||||||
|
});
|
||||||
|
|
||||||
|
const url = oauth.generateAuthUrl({
|
||||||
|
scope: ["identify", "guilds"],
|
||||||
|
state: crypto.randomBytes(16).toString("hex"), // Be aware that randomBytes is sync if no callback is provided
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(url);
|
||||||
|
// https://discord.com/api/oauth2/authorize?client_id=332269999912132097&redirect_uri=http%3A%2F%2Flocalhost%2Fcallback&response_type=code&scope=identify%20guilds&state=132054f372bfca771de3dfe54aaacece
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
# Debugging
|
||||||
|
|
||||||
|
By default when you log an error to the console, it will look something like this `DiscordHTTPError: 400 Bad Request on POST /api/v7/oauth2/token` followed by a very long stack trace what most of the times won't be useful (if you already know where the function is called).
|
||||||
|
|
||||||
|
To easily debug any issues you are having, you can access the following properties of the error object thrown:
|
||||||
|
|
||||||
|
`req`: The HTTP request sent to discord.
|
||||||
|
|
||||||
|
`res`: The HTTP response sent from discord to our request.
|
||||||
|
|
||||||
|
`code`: If the error is a `DiscordHTTPError`, it will be the HTTP status code of the response (same as `res.statusCode`).<br />
|
||||||
|
If the error is a `DiscordRESTError`, it will be a [Discord API JSON error code](https://discord.com/developers/docs/topics/opcodes-and-status-codes#json-json-error-codes).
|
||||||
|
|
||||||
|
`response`: An object containing properties that describe the error.<br />
|
||||||
|
If the error is a `DiscordHTTPError`, the object will have the `error` and `error_description` properties.<br />
|
||||||
|
If the error is a `DiscordRESTError`, the object will have the `message` and `code` (JSON error code. See `code`.) properties.
|
||||||
|
|
||||||
|
`message`: If the error is a `DiscordHTTPError`, it will be a string including the status of the HTTP request and the endpoint used.<br />
|
||||||
|
If the error is a `DiscordRESTError`, it will be a string including the error code and it's meaning.
|
||||||
|
|
||||||
|
`stack`: The error stack trace.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// error.response for DiscordRESTError
|
||||||
|
{
|
||||||
|
message: 'Missing Permissions',
|
||||||
|
code: 50013
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
// error.response for DiscordHTTPError
|
||||||
|
{
|
||||||
|
error: 'invalid_request',
|
||||||
|
error_description: 'Invalid "code" in request.'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Contributing
|
||||||
|
|
||||||
|
All contributions are welcome.
|
136
node_modules/discord-oauth2/index.d.ts
generated
vendored
Normal file
136
node_modules/discord-oauth2/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
import { EventEmitter } from "events";
|
||||||
|
|
||||||
|
interface User {
|
||||||
|
id: string;
|
||||||
|
username: string;
|
||||||
|
discriminator: string;
|
||||||
|
avatar: string | null | undefined;
|
||||||
|
mfa_enabled?: true;
|
||||||
|
locale?: string;
|
||||||
|
verified?: boolean;
|
||||||
|
email?: string | null | undefined;
|
||||||
|
flags?: number;
|
||||||
|
premium_type?: number;
|
||||||
|
public_flags?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Member {
|
||||||
|
user?: User;
|
||||||
|
nick: string | null | undefined;
|
||||||
|
roles: string[];
|
||||||
|
joined_at: number;
|
||||||
|
premium_since?: number | null | undefined;
|
||||||
|
deaf: boolean;
|
||||||
|
mute: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is not accurate as discord sends a partial object
|
||||||
|
interface Integration {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
enabled: boolean;
|
||||||
|
syncing: boolean;
|
||||||
|
role_id: string;
|
||||||
|
enable_emoticons?: boolean;
|
||||||
|
expire_behavior: 0 | 1;
|
||||||
|
expire_grace_period: number;
|
||||||
|
user?: User;
|
||||||
|
account: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
synced_at: number;
|
||||||
|
subscriber_count: number;
|
||||||
|
revoked: boolean;
|
||||||
|
application?: Application;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Connection {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
revoked?: string;
|
||||||
|
integrations?: Integration[];
|
||||||
|
verified: boolean;
|
||||||
|
friend_sync: boolean;
|
||||||
|
show_activity: boolean;
|
||||||
|
visibility: 0 | 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Application {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
icon: string | null | undefined;
|
||||||
|
description: string;
|
||||||
|
summary: string;
|
||||||
|
bot?: User;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TokenRequestResult {
|
||||||
|
access_token: string;
|
||||||
|
token_type: string;
|
||||||
|
expires_in: number;
|
||||||
|
refresh_token: string;
|
||||||
|
scope: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PartialGuild {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
icon: string | null | undefined;
|
||||||
|
owner?: boolean;
|
||||||
|
permissions?: number;
|
||||||
|
features: string[];
|
||||||
|
permissions_new?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare class OAuth extends EventEmitter {
|
||||||
|
constructor(opts?: {
|
||||||
|
version?: string,
|
||||||
|
clientId?: string,
|
||||||
|
redirectUri?: string,
|
||||||
|
credentials?: string,
|
||||||
|
clientSecret?: string,
|
||||||
|
requestTimeout?: number,
|
||||||
|
latencyThreshold?: number,
|
||||||
|
ratelimiterOffset?: number,
|
||||||
|
});
|
||||||
|
on(event: "debug" | "warn", listener: (message: string) => void): this;
|
||||||
|
tokenRequest(opts: {
|
||||||
|
code?: string,
|
||||||
|
scope: string[] | string,
|
||||||
|
clientId?: string,
|
||||||
|
grantType: "authorization_code" | "refresh_token",
|
||||||
|
redirectUri?: string,
|
||||||
|
refreshToken?: string,
|
||||||
|
clientSecret?: string,
|
||||||
|
}): Promise<TokenRequestResult>;
|
||||||
|
revokeToken(access_token: string, credentials?: string): Promise<string>;
|
||||||
|
getUser(access_token: string): Promise<User>;
|
||||||
|
getUserGuilds(access_token: string): Promise<PartialGuild[]>;
|
||||||
|
getUserConnections(access_token: string): Promise<Connection[]>;
|
||||||
|
addMember(opts: {
|
||||||
|
deaf?: boolean,
|
||||||
|
mute?: boolean,
|
||||||
|
roles?: string[],
|
||||||
|
nickname?: string,
|
||||||
|
userId: string,
|
||||||
|
guildId: string,
|
||||||
|
botToken: string,
|
||||||
|
accessToken: string,
|
||||||
|
}): Promise<Member>;
|
||||||
|
generateAuthUrl(opts: {
|
||||||
|
scope: string[] | string,
|
||||||
|
state?: string,
|
||||||
|
clientId?: string,
|
||||||
|
prompt?: "consent" | "none",
|
||||||
|
redirectUri?: string,
|
||||||
|
responseType?: "code" | "token",
|
||||||
|
permissions?: number,
|
||||||
|
guildId?: string,
|
||||||
|
disableGuildSelect?: boolean,
|
||||||
|
}): string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export = OAuth;
|
3
node_modules/discord-oauth2/index.js
generated
vendored
Normal file
3
node_modules/discord-oauth2/index.js
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
"use strict";
|
||||||
|
const OAuth = require("./lib/oauth");
|
||||||
|
module.exports = OAuth;
|
91
node_modules/discord-oauth2/lib/eris/errors/DiscordHTTPError.js
generated
vendored
Normal file
91
node_modules/discord-oauth2/lib/eris/errors/DiscordHTTPError.js
generated
vendored
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2016-2020 abalabahaha
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable no-prototype-builtins */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
class DiscordHTTPError extends Error {
|
||||||
|
constructor(req, res, response, stack) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
Object.defineProperty(this, "req", {
|
||||||
|
enumerable: false,
|
||||||
|
value: req,
|
||||||
|
writable: false,
|
||||||
|
});
|
||||||
|
Object.defineProperty(this, "res", {
|
||||||
|
enumerable: false,
|
||||||
|
value: res,
|
||||||
|
writable: false,
|
||||||
|
});
|
||||||
|
Object.defineProperty(this, "response", {
|
||||||
|
enumerable: false,
|
||||||
|
value: response,
|
||||||
|
writable: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(this, "code", {
|
||||||
|
value: res.statusCode,
|
||||||
|
writable: false,
|
||||||
|
});
|
||||||
|
let message = `${this.name}: ${res.statusCode} ${res.statusMessage} on ${req.method} ${req.path}`;
|
||||||
|
const errors = this.flattenErrors(response);
|
||||||
|
if (errors.length > 0) {
|
||||||
|
message += "\n " + errors.join("\n ");
|
||||||
|
}
|
||||||
|
Object.defineProperty(this, "message", {
|
||||||
|
value: message,
|
||||||
|
writable: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (stack) {
|
||||||
|
Object.defineProperty(this, "stack", {
|
||||||
|
value: this.message + "\n" + stack,
|
||||||
|
writable: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Error.captureStackTrace(this, DiscordHTTPError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get name() {
|
||||||
|
return this.constructor.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
flattenErrors(errors, keyPrefix = "") {
|
||||||
|
let messages = [];
|
||||||
|
for (const fieldName in errors) {
|
||||||
|
if (!errors.hasOwnProperty(fieldName) || fieldName === "message" || fieldName === "code") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (Array.isArray(errors[fieldName])) {
|
||||||
|
messages = messages.concat(errors[fieldName].map((str) => `${keyPrefix + fieldName}: ${str}`));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return messages;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = DiscordHTTPError;
|
103
node_modules/discord-oauth2/lib/eris/errors/DiscordRESTError.js
generated
vendored
Normal file
103
node_modules/discord-oauth2/lib/eris/errors/DiscordRESTError.js
generated
vendored
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2016-2020 abalabahaha
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable no-prototype-builtins */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
class DiscordRESTError extends Error {
|
||||||
|
constructor(req, res, response, stack) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
Object.defineProperty(this, "req", {
|
||||||
|
enumerable: false,
|
||||||
|
value: req,
|
||||||
|
writable: false,
|
||||||
|
});
|
||||||
|
Object.defineProperty(this, "res", {
|
||||||
|
enumerable: false,
|
||||||
|
value: res,
|
||||||
|
writable: false,
|
||||||
|
});
|
||||||
|
Object.defineProperty(this, "response", {
|
||||||
|
enumerable: false,
|
||||||
|
value: response,
|
||||||
|
writable: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(this, "code", {
|
||||||
|
value: +response.code || -1,
|
||||||
|
writable: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
let message = this.name + ": " + (response.message || "Unknown error");
|
||||||
|
if (response.errors) {
|
||||||
|
message += "\n " + this.flattenErrors(response.errors).join("\n ");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const errors = this.flattenErrors(response);
|
||||||
|
if (errors.length > 0) {
|
||||||
|
message += "\n " + errors.join("\n ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Object.defineProperty(this, "message", {
|
||||||
|
value: message,
|
||||||
|
writable: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (stack) {
|
||||||
|
Object.defineProperty(this, "stack", {
|
||||||
|
value: this.message + "\n" + stack,
|
||||||
|
writable: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Error.captureStackTrace(this, DiscordRESTError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get name() {
|
||||||
|
return `${this.constructor.name} [${this.code}]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
flattenErrors(errors, keyPrefix = "") {
|
||||||
|
let messages = [];
|
||||||
|
for (const fieldName in errors) {
|
||||||
|
if (!errors.hasOwnProperty(fieldName) || fieldName === "message" || fieldName === "code") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (errors[fieldName]._errors) {
|
||||||
|
messages = messages.concat(errors[fieldName]._errors.map((obj) => `${keyPrefix + fieldName}: ${obj.message}`));
|
||||||
|
}
|
||||||
|
else if (Array.isArray(errors[fieldName])) {
|
||||||
|
messages = messages.concat(errors[fieldName].map((str) => `${keyPrefix + fieldName}: ${str}`));
|
||||||
|
}
|
||||||
|
else if (typeof errors[fieldName] === "object") {
|
||||||
|
messages = messages.concat(this.flattenErrors(errors[fieldName], keyPrefix + fieldName + "."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return messages;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = DiscordRESTError;
|
305
node_modules/discord-oauth2/lib/eris/rest/RequestHandler.js
generated
vendored
Normal file
305
node_modules/discord-oauth2/lib/eris/rest/RequestHandler.js
generated
vendored
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
/*
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2016-2020 abalabahaha
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const DiscordHTTPError = require("../errors/DiscordHTTPError");
|
||||||
|
const DiscordRESTError = require("../errors/DiscordRESTError");
|
||||||
|
const HTTPS = require("https");
|
||||||
|
const SequentialBucket = require("../util/SequentialBucket");
|
||||||
|
const EventEmitter = require("events");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles API requests
|
||||||
|
*/
|
||||||
|
class RequestHandler extends EventEmitter {
|
||||||
|
constructor(options) {
|
||||||
|
super();
|
||||||
|
this.version = options.version;
|
||||||
|
this.userAgent = `Discord-OAuth2 (https://github.com/reboxer/discord-oauth2, ${require("../../../package.json").version})`;
|
||||||
|
this.ratelimits = {};
|
||||||
|
this.requestTimeout = options.requestTimeout;
|
||||||
|
this.latencyThreshold = options.latencyThreshold;
|
||||||
|
this.latencyRef = {
|
||||||
|
latency: 500,
|
||||||
|
offset: options.ratelimiterOffset,
|
||||||
|
raw: new Array(10).fill(500),
|
||||||
|
timeOffset: 0,
|
||||||
|
timeOffsets: new Array(10).fill(0),
|
||||||
|
lastTimeOffsetCheck: 0,
|
||||||
|
};
|
||||||
|
this.globalBlock = false;
|
||||||
|
this.readyQueue = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
globalUnblock() {
|
||||||
|
this.globalBlock = false;
|
||||||
|
while (this.readyQueue.length > 0) {
|
||||||
|
this.readyQueue.shift()();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need this for the Add Guild Member endpoint
|
||||||
|
routefy(url) {
|
||||||
|
return url.replace(/\/([a-z-]+)\/(?:[0-9]{17,19})/g, function(match, p) {
|
||||||
|
return p === "guilds" ? match : `/${p}/:id`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make an API request
|
||||||
|
* @arg {String} method Uppercase HTTP method
|
||||||
|
* @arg {String} url URL of the endpoint
|
||||||
|
* @arg {Object} options
|
||||||
|
* @arg {Object} [options.auth]
|
||||||
|
* @arg {String} [options.auth.type] The type of Authorization to use in the header, wheather Basic, Bearer or Bot
|
||||||
|
* @arg {String} [options.auth.creds] The credentials used for the authentication (bot or user access token), if Basic, a base64 string with application's credentials must be passed
|
||||||
|
* @arg {String} options.contentType The content type to set in the headers of the request
|
||||||
|
* @arg {Object} [body] Request payload
|
||||||
|
* @returns {Promise<Object>} Resolves with the returned JSON data
|
||||||
|
*/
|
||||||
|
request(method, url, body, options, _route, short) {
|
||||||
|
const route = _route || this.routefy(url, method);
|
||||||
|
|
||||||
|
const _stackHolder = {}; // Preserve async stack
|
||||||
|
Error.captureStackTrace(_stackHolder);
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let attempts = 0;
|
||||||
|
|
||||||
|
const actualCall = (cb) => {
|
||||||
|
const headers = {
|
||||||
|
"User-Agent": this.userAgent,
|
||||||
|
"Content-Type": options.contentType,
|
||||||
|
};
|
||||||
|
let data;
|
||||||
|
try {
|
||||||
|
if (options.auth) {
|
||||||
|
headers["Authorization"] = `${options.auth.type} ${options.auth.creds}`;
|
||||||
|
}
|
||||||
|
if (headers["Content-Type"] === "application/json") {
|
||||||
|
data = JSON.stringify(body);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data = body;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
cb();
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const req = HTTPS.request({
|
||||||
|
method: method,
|
||||||
|
host: "discord.com",
|
||||||
|
path: `/api/${this.version}` + url,
|
||||||
|
headers: headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
let reqError;
|
||||||
|
|
||||||
|
req.once("abort", () => {
|
||||||
|
cb();
|
||||||
|
reqError = reqError || new Error(`Request aborted by client on ${method} ${url}`);
|
||||||
|
reqError.req = req;
|
||||||
|
reject(reqError);
|
||||||
|
}).once("error", (err) => {
|
||||||
|
reqError = err;
|
||||||
|
req.abort();
|
||||||
|
});
|
||||||
|
|
||||||
|
let latency = Date.now();
|
||||||
|
|
||||||
|
req.once("response", (resp) => {
|
||||||
|
latency = Date.now() - latency;
|
||||||
|
this.latencyRef.raw.push(latency);
|
||||||
|
this.latencyRef.latency = this.latencyRef.latency - ~~(this.latencyRef.raw.shift() / 10) + ~~(latency / 10);
|
||||||
|
|
||||||
|
const headerNow = Date.parse(resp.headers["date"]);
|
||||||
|
if (this.latencyRef.lastTimeOffsetCheck < Date.now() - 5000) {
|
||||||
|
const timeOffset = ~~((this.latencyRef.lastTimeOffsetCheck = Date.now()) - headerNow);
|
||||||
|
if (this.latencyRef.timeOffset - this.latencyRef.latency >= this.latencyThreshold && timeOffset - this.latencyRef.latency >= this.latencyThreshold) {
|
||||||
|
this.emit("warn", new Error(`Your clock is ${this.latencyRef.timeOffset}ms behind Discord's server clock. Please check your connection and system time.`));
|
||||||
|
}
|
||||||
|
this.latencyRef.timeOffset = ~~(this.latencyRef.timeOffset - this.latencyRef.timeOffsets.shift() / 10 + timeOffset / 10);
|
||||||
|
this.latencyRef.timeOffsets.push(timeOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.once("aborted", () => {
|
||||||
|
cb();
|
||||||
|
reqError = reqError || new Error(`Request aborted by server on ${method} ${url}`);
|
||||||
|
reqError.req = req;
|
||||||
|
reject(reqError);
|
||||||
|
});
|
||||||
|
|
||||||
|
let response = "";
|
||||||
|
|
||||||
|
const _respStream = resp;
|
||||||
|
|
||||||
|
_respStream.on("data", (str) => {
|
||||||
|
response += str;
|
||||||
|
}).on("error", (err) => {
|
||||||
|
reqError = err;
|
||||||
|
req.abort();
|
||||||
|
}).once("end", () => {
|
||||||
|
const now = Date.now();
|
||||||
|
|
||||||
|
if (resp.headers["x-ratelimit-limit"]) {
|
||||||
|
this.ratelimits[route].limit = +resp.headers["x-ratelimit-limit"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (method !== "GET" && (resp.headers["x-ratelimit-remaining"] === undefined || resp.headers["x-ratelimit-limit"] === undefined) && this.ratelimits[route].limit !== 1) {
|
||||||
|
this.emit("debug", `Missing ratelimit headers for SequentialBucket(${this.ratelimits[route].remaining}/${this.ratelimits[route].limit}) with non-default limit\n`
|
||||||
|
+ `${resp.statusCode} ${resp.headers["content-type"]}: ${method} ${route} | ${resp.headers["cf-ray"]}\n`
|
||||||
|
+ "content-type = " + "\n"
|
||||||
|
+ "x-ratelimit-remaining = " + resp.headers["x-ratelimit-remaining"] + "\n"
|
||||||
|
+ "x-ratelimit-limit = " + resp.headers["x-ratelimit-limit"] + "\n"
|
||||||
|
+ "x-ratelimit-reset = " + resp.headers["x-ratelimit-reset"] + "\n"
|
||||||
|
+ "x-ratelimit-global = " + resp.headers["x-ratelimit-global"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ratelimits[route].remaining = resp.headers["x-ratelimit-remaining"] === undefined ? 1 : +resp.headers["x-ratelimit-remaining"] || 0;
|
||||||
|
|
||||||
|
if (resp.headers["retry-after"]) {
|
||||||
|
if (resp.headers["x-ratelimit-global"]) {
|
||||||
|
this.globalBlock = true;
|
||||||
|
setTimeout(() => this.globalUnblock(), +resp.headers["retry-after"] || 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.ratelimits[route].reset = (+resp.headers["retry-after"] || 1) + now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (resp.headers["x-ratelimit-reset"]) {
|
||||||
|
if ((~route.lastIndexOf("/reactions/:id")) && (+resp.headers["x-ratelimit-reset"] * 1000 - headerNow) === 1000) {
|
||||||
|
this.ratelimits[route].reset = Math.max(now + 250 - this.latencyRef.timeOffset, now);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.ratelimits[route].reset = Math.max(+resp.headers["x-ratelimit-reset"] * 1000 - this.latencyRef.timeOffset, now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.ratelimits[route].reset = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.statusCode !== 429) {
|
||||||
|
this.emit("debug", `${body && body.content} ${now} ${route} ${resp.statusCode}: ${latency}ms (${this.latencyRef.latency}ms avg) | ${this.ratelimits[route].remaining}/${this.ratelimits[route].limit} left | Reset ${this.ratelimits[route].reset} (${this.ratelimits[route].reset - now}ms left)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.statusCode >= 300) {
|
||||||
|
if (resp.statusCode === 429) {
|
||||||
|
this.emit("debug", `${resp.headers["x-ratelimit-global"] ? "Global" : "Unexpected"} 429 (╯°□°)╯︵ ┻━┻: ${response}\n${body && body.content} ${now} ${route} ${resp.statusCode}: ${latency}ms (${this.latencyRef.latency}ms avg) | ${this.ratelimits[route].remaining}/${this.ratelimits[route].limit} left | Reset ${this.ratelimits[route].reset} (${this.ratelimits[route].reset - now}ms left)`);
|
||||||
|
if (resp.headers["retry-after"]) {
|
||||||
|
setTimeout(() => {
|
||||||
|
cb();
|
||||||
|
this.request(method, url, body, options, route, true).then(resolve).catch(reject);
|
||||||
|
}, +resp.headers["retry-after"]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cb();
|
||||||
|
this.request(method, url, body, options, route, true).then(resolve).catch(reject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (resp.statusCode === 502 && ++attempts < 4) {
|
||||||
|
this.emit("debug", "A wild 502 appeared! Thanks CloudFlare!");
|
||||||
|
setTimeout(() => {
|
||||||
|
this.request(method, url, body, options, route, true).then(resolve).catch(reject);
|
||||||
|
}, Math.floor(Math.random() * 1900 + 100));
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
cb();
|
||||||
|
|
||||||
|
if (response.length > 0) {
|
||||||
|
if (resp.headers["content-type"] === "application/json") {
|
||||||
|
try {
|
||||||
|
response = JSON.parse(response);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let { stack } = _stackHolder;
|
||||||
|
if (stack.startsWith("Error\n")) {
|
||||||
|
stack = stack.substring(6);
|
||||||
|
}
|
||||||
|
let err;
|
||||||
|
if (response.code) {
|
||||||
|
err = new DiscordRESTError(req, resp, response, stack);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
err = new DiscordHTTPError(req, resp, response, stack);
|
||||||
|
}
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.length > 0) {
|
||||||
|
if (resp.headers["content-type"] === "application/json") {
|
||||||
|
try {
|
||||||
|
response = JSON.parse(response);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
cb();
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cb();
|
||||||
|
resolve(response);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
req.setTimeout(this.requestTimeout, () => {
|
||||||
|
reqError = new Error(`Request timed out (>${this.requestTimeout}ms) on ${method} ${url}`);
|
||||||
|
req.abort();
|
||||||
|
});
|
||||||
|
|
||||||
|
req.end(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.globalBlock && (options.auth)) {
|
||||||
|
this.readyQueue.push(() => {
|
||||||
|
if (! this.ratelimits[route]) {
|
||||||
|
this.ratelimits[route] = new SequentialBucket(1, this.latencyRef);
|
||||||
|
}
|
||||||
|
this.ratelimits[route].queue(actualCall, short);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (! this.ratelimits[route]) {
|
||||||
|
this.ratelimits[route] = new SequentialBucket(1, this.latencyRef);
|
||||||
|
}
|
||||||
|
this.ratelimits[route].queue(actualCall, short);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = RequestHandler;
|
105
node_modules/discord-oauth2/lib/eris/util/SequentialBucket.js
generated
vendored
Normal file
105
node_modules/discord-oauth2/lib/eris/util/SequentialBucket.js
generated
vendored
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2016-2020 abalabahaha
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ratelimit requests and release in sequence
|
||||||
|
* @prop {Number} limit How many tokens the bucket can consume in the current interval
|
||||||
|
* @prop {Number} remaining How many tokens the bucket has left in the current interval
|
||||||
|
* @prop {Number} reset Timestamp of next reset
|
||||||
|
* @prop {Boolean} processing Whether the queue is being processed
|
||||||
|
*/
|
||||||
|
class SequentialBucket {
|
||||||
|
/**
|
||||||
|
* Construct a SequentialBucket
|
||||||
|
* @arg {Number} tokenLimit The max number of tokens the bucket can consume per interval
|
||||||
|
* @arg {Object} [latencyRef] An object
|
||||||
|
* @arg {Number} latencyRef.latency Interval between consuming tokens
|
||||||
|
*/
|
||||||
|
constructor(limit, latencyRef = { latency: 0 }) {
|
||||||
|
this.limit = this.remaining = limit;
|
||||||
|
this.resetInterval = 0;
|
||||||
|
this.reset = 0;
|
||||||
|
this.processing = false;
|
||||||
|
this.latencyRef = latencyRef;
|
||||||
|
this._queue = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queue something in the SequentialBucket
|
||||||
|
* @arg {Function} func A function to call when a token can be consumed. The function will be passed a callback argument, which must be called to allow the bucket to continue to work
|
||||||
|
*/
|
||||||
|
queue(func, short) {
|
||||||
|
if (short) {
|
||||||
|
this._queue.unshift(func);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._queue.push(func);
|
||||||
|
}
|
||||||
|
this.check();
|
||||||
|
}
|
||||||
|
|
||||||
|
check(override) {
|
||||||
|
if (this._queue.length === 0) {
|
||||||
|
if (this.processing) {
|
||||||
|
clearTimeout(this.processing);
|
||||||
|
this.processing = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.processing && !override) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const now = Date.now();
|
||||||
|
const offset = this.latencyRef.latency + (this.latencyRef.offset || 0);
|
||||||
|
if (!this.reset) {
|
||||||
|
this.reset = now - offset;
|
||||||
|
this.remaining = this.limit;
|
||||||
|
}
|
||||||
|
else if (this.reset < now - offset) {
|
||||||
|
this.reset = now - offset + (this.resetInterval || 0);
|
||||||
|
this.remaining = this.limit;
|
||||||
|
}
|
||||||
|
this.last = now;
|
||||||
|
if (this.remaining <= 0) {
|
||||||
|
this.processing = setTimeout(() => {
|
||||||
|
this.processing = false;
|
||||||
|
this.check(true);
|
||||||
|
}, Math.max(0, (this.reset || 0) - now) + offset);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
--this.remaining;
|
||||||
|
this.processing = true;
|
||||||
|
this._queue.shift()(() => {
|
||||||
|
if (this._queue.length > 0) {
|
||||||
|
this.check(true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.processing = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = SequentialBucket;
|
218
node_modules/discord-oauth2/lib/oauth.js
generated
vendored
Normal file
218
node_modules/discord-oauth2/lib/oauth.js
generated
vendored
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const RequestHandler = require("./eris/rest/RequestHandler");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make requests to discord's OAuth2 API
|
||||||
|
* @extends requestHandler
|
||||||
|
*/
|
||||||
|
class OAuth extends RequestHandler {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @arg {Object} opts
|
||||||
|
* @arg {String?} opts.version The version of the Discord API to use. Defaults to v7.
|
||||||
|
* @arg {Number} [opts.requestTimeout=15000] A number of milliseconds before requests are considered timed out
|
||||||
|
* @arg {Number} [opts.latencyThreshold=30000] The average request latency at which the RequestHandler will start emitting latency errors
|
||||||
|
* @arg {Number} [opts.ratelimiterOffset=0] A number of milliseconds to offset the ratelimit timing calculations by
|
||||||
|
* @arg {String?} opts.clientId Your application's client id
|
||||||
|
* @arg {String?} opts.clientSecret Your application's client secret
|
||||||
|
* @arg {String?} opts.redirectUri Your URL redirect uri
|
||||||
|
* @arg {String?} opts.credentials Base64 encoding of the UTF-8 encoded credentials string of your application
|
||||||
|
*/
|
||||||
|
constructor(opts = {}) {
|
||||||
|
super({
|
||||||
|
version: opts.version || "v7",
|
||||||
|
requestTimeout: opts.requestTimeout || 15000,
|
||||||
|
latencyThreshold: opts.latencyThreshold || 30000,
|
||||||
|
ratelimiterOffset: opts.ratelimiterOffset || 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.client_id = opts.clientId;
|
||||||
|
this.client_secret = opts.clientSecret;
|
||||||
|
this.redirect_uri = opts.redirectUri;
|
||||||
|
|
||||||
|
this.credentials = opts.credentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
_encode(obj) {
|
||||||
|
let string = "";
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(obj)) {
|
||||||
|
if (!value) continue;
|
||||||
|
string += `&${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exchange the code returned by discord in the query for the user access token
|
||||||
|
* If specified, can also use refresh_token to get a new valid token
|
||||||
|
* Read discord's OAuth2 documentation for a full example (https://discord.com/developers/docs/topics/oauth2)
|
||||||
|
* @arg {Object} opts The object containing the parameters for the request
|
||||||
|
* @arg {String?} opts.clientId Your application's client id
|
||||||
|
* @arg {String?} opts.clientSecret Your application's client secret
|
||||||
|
* @arg {String} opts.grantType Either authorization_code or refresh_token
|
||||||
|
* @arg {String?} opts.code The code from the querystring
|
||||||
|
* @arg {String?} opts.refreshToken The user's refresh token
|
||||||
|
* @arg {String?} opts.redirectUri Your URL redirect uri
|
||||||
|
* @arg {String} opts.scope The scopes requested in your authorization url, space-delimited
|
||||||
|
* @returns {Promise<Object>}
|
||||||
|
*/
|
||||||
|
tokenRequest(opts = {}) {
|
||||||
|
const obj = {
|
||||||
|
client_id: opts.clientId || this.client_id,
|
||||||
|
client_secret: opts.clientSecret || this.client_secret,
|
||||||
|
grant_type: undefined,
|
||||||
|
code: undefined,
|
||||||
|
refresh_token: undefined,
|
||||||
|
redirect_uri: opts.redirectUri || this.redirect_uri,
|
||||||
|
scope: opts.scope instanceof Array ? opts.scope.join(" ") : opts.scope,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (opts.grantType === "authorization_code") {
|
||||||
|
obj.code = opts.code;
|
||||||
|
obj.grant_type = opts.grantType;
|
||||||
|
}
|
||||||
|
else if (opts.grantType === "refresh_token") {
|
||||||
|
obj.refresh_token = opts.refreshToken;
|
||||||
|
obj.grant_type = opts.grantType;
|
||||||
|
}
|
||||||
|
else throw new Error("Invalid grant_type provided, it must be either authorization_code or refresh_token");
|
||||||
|
|
||||||
|
const encoded_string = this._encode(obj);
|
||||||
|
|
||||||
|
return this.request("POST", "/oauth2/token", encoded_string, {
|
||||||
|
contentType: "application/x-www-form-urlencoded",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Revoke the user access token
|
||||||
|
* @arg {String} access_token The user access token
|
||||||
|
* @arg {String} credentials Base64 encoding of the UTF-8 encoded credentials string of your application
|
||||||
|
* @returns {Promise<String>}
|
||||||
|
*/
|
||||||
|
revokeToken(access_token, credentials) {
|
||||||
|
if (!credentials && !this.credentials) throw new Error("Missing credentials for revokeToken method");
|
||||||
|
return this.request("POST", "/oauth2/token/revoke", `token=${access_token}`, {
|
||||||
|
auth: {
|
||||||
|
type: "Basic",
|
||||||
|
creds: credentials || this.credentials,
|
||||||
|
},
|
||||||
|
contentType: "application/x-www-form-urlencoded",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request basic user data
|
||||||
|
* Requires the `identify` scope
|
||||||
|
* @arg {String} access_token The user access token
|
||||||
|
* @returns {Promise<Object>}
|
||||||
|
*/
|
||||||
|
getUser(access_token) {
|
||||||
|
return this.request("GET", "/users/@me", undefined, {
|
||||||
|
auth: {
|
||||||
|
type: "Bearer",
|
||||||
|
creds: access_token,
|
||||||
|
},
|
||||||
|
contentType: "application/json",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request all the guilds the user is in
|
||||||
|
* Requires the `guilds` scope
|
||||||
|
* @arg {String} access_token The user access token
|
||||||
|
* @returns {Promise<Object[]>}
|
||||||
|
*/
|
||||||
|
getUserGuilds(access_token) {
|
||||||
|
return this.request("GET", "/users/@me/guilds", undefined, {
|
||||||
|
auth: {
|
||||||
|
type: "Bearer",
|
||||||
|
creds: access_token,
|
||||||
|
},
|
||||||
|
contentType: "application/json",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request a user's connections
|
||||||
|
* Requires the `connections` scope
|
||||||
|
* @arg {String} access_token The user access token
|
||||||
|
* @returns {Promise<Object[]>}
|
||||||
|
*/
|
||||||
|
getUserConnections(access_token) {
|
||||||
|
return this.request("GET", "/users/@me/connections", undefined, {
|
||||||
|
auth: {
|
||||||
|
type: "Bearer",
|
||||||
|
creds: access_token,
|
||||||
|
},
|
||||||
|
contentType: "application/json",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force a user to join a guild
|
||||||
|
* Requires the `guilds.join` scope
|
||||||
|
* @arg {Object} opts
|
||||||
|
* @arg {String} opts.guildId The ID of the guild to join
|
||||||
|
* @arg {String} opts.userId The ID of the user to be added to the guild
|
||||||
|
* @arg {Boolean?} opts.deaf Whether the user is deafened in voice channels
|
||||||
|
* @arg {Boolean?} opts.mute Whether the user is muted in voice channels
|
||||||
|
* @arg {String?} opts.nickname Value to set users nickname to
|
||||||
|
* @arg {String[]?} opts.roles Array of role ids the member is assigned
|
||||||
|
* @arg {String} opts.accessToken The user access token
|
||||||
|
* @arg {String} opts.botToken The token of the bot used to authenticate
|
||||||
|
* @returns {Promise<Object | String>}
|
||||||
|
*/
|
||||||
|
addMember(opts) {
|
||||||
|
return this.request("PUT", `/guilds/${opts.guildId}/members/${opts.userId}`, {
|
||||||
|
deaf: opts.deaf,
|
||||||
|
mute: opts.mute,
|
||||||
|
nick: opts.nickname,
|
||||||
|
roles: opts.roles,
|
||||||
|
access_token: opts.accessToken,
|
||||||
|
}, {
|
||||||
|
auth: {
|
||||||
|
type: "Bot",
|
||||||
|
creds: opts.botToken,
|
||||||
|
},
|
||||||
|
contentType: "application/json",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @arg {Object} opts
|
||||||
|
* @arg {String} opts.clientId Your application's client id
|
||||||
|
* @arg {String?} opts.prompt Controls how existing authorizations are handled, either consent or none (for passthrough scopes authorization is always required).
|
||||||
|
* @arg {String?} opts.redirectUri Your URL redirect uri
|
||||||
|
* @arg {String?} opts.responseType The response type, either code or token (token is for client-side web applications only). Defaults to code
|
||||||
|
* @arg {String | Array} opts.scope The scopes for your URL
|
||||||
|
* @arg {String?} opts.state A unique cryptographically secure string (https://discord.com/developers/docs/topics/oauth2#state-and-security)
|
||||||
|
* @arg {Number?} opts.permissions The permissions number for the bot invite (only with bot scope) (https://discord.com/developers/docs/topics/permissions)
|
||||||
|
* @arg {String?} opts.guildId The guild id to pre-fill the bot invite (only with bot scope)
|
||||||
|
* @arg {Boolean?} opts.disableGuildSelect Disallows the user from changing the guild for the bot invite, either true or false (only with bot scope)
|
||||||
|
* @returns {String}
|
||||||
|
*/
|
||||||
|
generateAuthUrl(opts = {}) {
|
||||||
|
const obj = {
|
||||||
|
client_id: opts.clientId || this.client_id,
|
||||||
|
prompt: opts.prompt || undefined,
|
||||||
|
redirect_uri: opts.redirectUri || this.redirect_uri,
|
||||||
|
response_type: opts.responseType || "code",
|
||||||
|
scope: opts.scope instanceof Array ? opts.scope.join(" ") : opts.scope,
|
||||||
|
permissions: opts.permissions || undefined,
|
||||||
|
guild_id: opts.guildId || undefined,
|
||||||
|
disable_guild_select: opts.disableGuildSelect || undefined,
|
||||||
|
state: opts.state || undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
const encoded_string = this._encode(obj);
|
||||||
|
|
||||||
|
return `https://discord.com/api/oauth2/authorize?${encoded_string}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = OAuth;
|
56
node_modules/discord-oauth2/package.json
generated
vendored
Normal file
56
node_modules/discord-oauth2/package.json
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"_from": "discord-oauth2",
|
||||||
|
"_id": "discord-oauth2@2.7.1",
|
||||||
|
"_inBundle": false,
|
||||||
|
"_integrity": "sha512-8PiGsieFxujS6FqcDrWtrunhy5LQGIZC6n1Bi58CP/1/rusqxplj3tXMQ2DBZtw/oyDUrJwSBsYGSr7IJJwTeg==",
|
||||||
|
"_location": "/discord-oauth2",
|
||||||
|
"_phantomChildren": {},
|
||||||
|
"_requested": {
|
||||||
|
"type": "tag",
|
||||||
|
"registry": true,
|
||||||
|
"raw": "discord-oauth2",
|
||||||
|
"name": "discord-oauth2",
|
||||||
|
"escapedName": "discord-oauth2",
|
||||||
|
"rawSpec": "",
|
||||||
|
"saveSpec": null,
|
||||||
|
"fetchSpec": "latest"
|
||||||
|
},
|
||||||
|
"_requiredBy": [
|
||||||
|
"#USER",
|
||||||
|
"/"
|
||||||
|
],
|
||||||
|
"_resolved": "https://registry.npmjs.org/discord-oauth2/-/discord-oauth2-2.7.1.tgz",
|
||||||
|
"_shasum": "d71958d6f321c7bebec859ee60fc316fefef7eb7",
|
||||||
|
"_spec": "discord-oauth2",
|
||||||
|
"_where": "/home/sigonasr2/divar/server2",
|
||||||
|
"author": {
|
||||||
|
"name": "reboxer"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/reboxer/discord-oauth2/issues"
|
||||||
|
},
|
||||||
|
"bundleDependencies": false,
|
||||||
|
"deprecated": false,
|
||||||
|
"description": "Easily interact with discord's oauth2 API",
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint": "7.30.0"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/reboxer/discord-oauth2#readme",
|
||||||
|
"keywords": [
|
||||||
|
"api",
|
||||||
|
"discord",
|
||||||
|
"discordapp",
|
||||||
|
"oauth2"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"main": "index.js",
|
||||||
|
"name": "discord-oauth2",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/reboxer/discord-oauth2.git"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"lint": "eslint --ext .js ./"
|
||||||
|
},
|
||||||
|
"version": "2.7.1"
|
||||||
|
}
|
11
node_modules/secrethash/package.json
generated
vendored
11
node_modules/secrethash/package.json
generated
vendored
@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "secrethash",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"main": "secrethash.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
|
||||||
},
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"description": ""
|
|
||||||
}
|
|
5
package-lock.json
generated
5
package-lock.json
generated
@ -104,6 +104,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
||||||
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
|
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
|
||||||
},
|
},
|
||||||
|
"discord-oauth2": {
|
||||||
|
"version": "2.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/discord-oauth2/-/discord-oauth2-2.7.1.tgz",
|
||||||
|
"integrity": "sha512-8PiGsieFxujS6FqcDrWtrunhy5LQGIZC6n1Bi58CP/1/rusqxplj3tXMQ2DBZtw/oyDUrJwSBsYGSr7IJJwTeg=="
|
||||||
|
},
|
||||||
"ee-first": {
|
"ee-first": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
|
"discord-oauth2": "^2.7.1",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"fs": "0.0.1-security",
|
"fs": "0.0.1-security",
|
||||||
"http": "0.0.1-security",
|
"http": "0.0.1-security",
|
||||||
|
66
server.js
66
server.js
@ -4,7 +4,13 @@ var http = require('http');
|
|||||||
var https = require('https');
|
var https = require('https');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
const sh = require('secrethash');
|
const sh = require('./secrethash');
|
||||||
|
const disc = require("discord-oauth2");
|
||||||
|
var refreshToken=""
|
||||||
|
const discord = new disc({
|
||||||
|
clientId: "885738904685281291",
|
||||||
|
clientSecret: process.env.NGSPLANNER_CLIENT_SECRET,
|
||||||
|
redirectUri: "https://localhost:3000#/login",});
|
||||||
|
|
||||||
var key = fs.readFileSync('./projectdivar.com/privkey1.pem');
|
var key = fs.readFileSync('./projectdivar.com/privkey1.pem');
|
||||||
var cert = fs.readFileSync('./projectdivar.com/cert1.pem');
|
var cert = fs.readFileSync('./projectdivar.com/cert1.pem');
|
||||||
@ -427,6 +433,41 @@ for (var test of ["","/test"]) {
|
|||||||
res.status(500).send(err.message)
|
res.status(500).send(err.message)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
app.get(PREFIX+test+"/userData",(req,res)=>{
|
||||||
|
if (req.query.token) {
|
||||||
|
discord.tokenRequest({
|
||||||
|
code:req.query.token,
|
||||||
|
grantType: "authorization_code",
|
||||||
|
scope: ["identify", "email"],
|
||||||
|
})
|
||||||
|
.then(res2=>{return discord.getUser(res2.access_token)})
|
||||||
|
.then(res2=>{
|
||||||
|
//Sample output. We can register the user from here.
|
||||||
|
//{"id":"176012829076226048","username":"sigonasr2","avatar":"c19b2f2a9d530f9f99efa3b1b573d7ef","discriminator":"6262","public_flags":0,"flags":0,"banner":"e0668c23567d5b58e88ea916306ec6d5","banner_color":null,"accent_color":null,"locale":"en-US","mfa_enabled":false,"premium_type":2,"email":"sigonasr2@gmail.com","verified":true}
|
||||||
|
/*var obj = {
|
||||||
|
body:{
|
||||||
|
recoveryhash:res2.id,
|
||||||
|
password:req.query.token,
|
||||||
|
username:res2.username,
|
||||||
|
avatar:"https://cdn.discordapp.com/avatars/"+res2.id+"/"+res2.avatar+".png",
|
||||||
|
userID:res2.id,
|
||||||
|
email:res2.email
|
||||||
|
}
|
||||||
|
}
|
||||||
|
registerUsers(obj,res)*/
|
||||||
|
res2.token=sh(req.query.token)
|
||||||
|
res.status(200).json(res2)
|
||||||
|
})
|
||||||
|
.catch((err)=>{
|
||||||
|
//console.log(err.response)
|
||||||
|
res.status(500).send("Everything is not fine")
|
||||||
|
})
|
||||||
|
//res.status(200).send("Everything is fine")
|
||||||
|
} else {
|
||||||
|
res.status(500).send("Everything is not fine")
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function CreateDynamicEndpoints() {
|
function CreateDynamicEndpoints() {
|
||||||
@ -824,8 +865,8 @@ function registerUsers(req,res){
|
|||||||
return db.query('select * from users where recovery_hash=$1 limit 1',[req.body.recoveryhash])
|
return db.query('select * from users where recovery_hash=$1 limit 1',[req.body.recoveryhash])
|
||||||
.then((data)=>{
|
.then((data)=>{
|
||||||
if (data.rows.length>0) {
|
if (data.rows.length>0) {
|
||||||
db.query('update users set password_hash=$2 where id=$1',[data.rows[0].id,req.body.password])
|
db.query('update users set username=$3,password_hash=$2 where id=$1',[data.rows[0].id,req.body.password,req.body.username])
|
||||||
db2.query('update users set password_hash=$2 where id=$1',[data.rows[0].id,req.body.password])
|
db2.query('update users set username=$3,password_hash=$2 where id=$1',[data.rows[0].id,req.body.password,req.body.username])
|
||||||
res.status(200).json({verified:true})
|
res.status(200).json({verified:true})
|
||||||
} else {
|
} else {
|
||||||
res.status(200).json({verified:true})
|
res.status(200).json({verified:true})
|
||||||
@ -847,10 +888,11 @@ function registerUsers(req,res){
|
|||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
console.log("User with email '"+req.body.email+"' already exists assume it's not a google account. Overwriting...")
|
console.log("User with email '"+req.body.email+"' already exists assume it's not a google account. Overwriting...")
|
||||||
db.query('update users set password_hash=$1,avatar=$2,recovery_hash=$3 where id=$4 returning id',[req.body.password,req.body.avatar,req.body.userID,data.rows[0].id])
|
//console.log(req.body.password)
|
||||||
|
db.query('update users set password_hash=$1,avatar=$2,recovery_hash=$3,username=$5 where id=$4 returning id',[req.body.password,req.body.avatar,req.body.userID,data.rows[0].id,req.body.username])
|
||||||
.then((data)=>{
|
.then((data)=>{
|
||||||
if (data.rows.length>0) {
|
if (data.rows.length>0) {
|
||||||
db2.query('update users set password_hash=$1,avatar=$2,recovery_hash=$3 where id=$4 returning id',[req.body.password,req.body.avatar,req.body.userID,data.rows[0].id])
|
db2.query('update users set password_hash=$1,avatar=$2,recovery_hash=$3,username=$5 where id=$4 returning id',[req.body.password,req.body.avatar,req.body.userID,data.rows[0].id,req.body.username])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
res.status(200).json({verified:true})
|
res.status(200).json({verified:true})
|
||||||
@ -865,9 +907,10 @@ function registerUsers(req,res){
|
|||||||
}
|
}
|
||||||
|
|
||||||
app.post(PREFIX+"/registerUser",registerUsers)
|
app.post(PREFIX+"/registerUser",registerUsers)
|
||||||
|
app.post(PREFIX+"/test/registerUser",registerUsers)
|
||||||
|
|
||||||
app.post(PREFIX+"/validUser",(req,res)=>{
|
function validUser(req,res) {
|
||||||
//console.log(sh.SecretHash("098f6bcd4621d373cade4e832627b4f6"))
|
//console.log(sh("098f6bcd4621d373cade4e832627b4f6"))
|
||||||
if (req.body.recoveryhash&&req.body.password) {
|
if (req.body.recoveryhash&&req.body.password) {
|
||||||
//A recovery hash means this is an external login. Try seeing if it matches something.
|
//A recovery hash means this is an external login. Try seeing if it matches something.
|
||||||
db.query('select * from users where recovery_hash=$1 and password_hash=$2 limit 1',[req.body.recoveryhash,req.body.password])
|
db.query('select * from users where recovery_hash=$1 and password_hash=$2 limit 1',[req.body.recoveryhash,req.body.password])
|
||||||
@ -882,7 +925,7 @@ app.post(PREFIX+"/validUser",(req,res)=>{
|
|||||||
res.status(500).send(err.message)
|
res.status(500).send(err.message)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
db.query('select * from users where username=$1 and password_hash=$2 limit 1',[req.body.username,sh.SecretHash(req.body.password)])
|
db.query('select * from users where username=$1 and password_hash=$2 limit 1',[req.body.username,sh(req.body.password)])
|
||||||
.then((data)=>{
|
.then((data)=>{
|
||||||
if (data.rows.length>0) {
|
if (data.rows.length>0) {
|
||||||
res.status(200).json({verified:true})
|
res.status(200).json({verified:true})
|
||||||
@ -894,7 +937,10 @@ app.post(PREFIX+"/validUser",(req,res)=>{
|
|||||||
res.status(500).send(err.message)
|
res.status(500).send(err.message)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
|
app.post(PREFIX+"/validUser",validUser)
|
||||||
|
app.post(PREFIX+"/test/validUser",validUser)
|
||||||
|
|
||||||
app.post(PREFIX+"/saveskilltree",(req,res)=>{
|
app.post(PREFIX+"/saveskilltree",(req,res)=>{
|
||||||
db4.query('select * from password where password=$1',[req.body.pass])
|
db4.query('select * from password where password=$1',[req.body.pass])
|
||||||
@ -953,7 +999,7 @@ function submitBuild(req,res,db,send) {
|
|||||||
db.query('select users.username from builds join users on users_id=users.id where builds.id=$1',[req.body.id])
|
db.query('select users.username from builds join users on users_id=users.id where builds.id=$1',[req.body.id])
|
||||||
.then((data)=>{
|
.then((data)=>{
|
||||||
console.log(data.rows)
|
console.log(data.rows)
|
||||||
if (data.rows.length>0&&data.rows[0].username===req.body.username&&data.rows[0].password_hash===sh.SecretHash(req.body.pass)) {
|
if (data.rows.length>0&&data.rows[0].username===req.body.username&&data.rows[0].password_hash===sh(req.body.pass)) {
|
||||||
return db.query('update builds set creator=$1,build_name=$2,class1=(SELECT id from class WHERE name=$3 limit 1),class2=(SELECT id from class WHERE name=$4 limit 1),last_modified=$5,data=$6 where id=$7 returning id',[req.body.creator,req.body.build_name,req.body.class1,req.body.class2,new Date(),req.body.data,req.body.id])
|
return db.query('update builds set creator=$1,build_name=$2,class1=(SELECT id from class WHERE name=$3 limit 1),class2=(SELECT id from class WHERE name=$4 limit 1),last_modified=$5,data=$6 where id=$7 returning id',[req.body.creator,req.body.build_name,req.body.class1,req.body.class2,new Date(),req.body.data,req.body.id])
|
||||||
.then((data)=>{
|
.then((data)=>{
|
||||||
if (send) {
|
if (send) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user