@sapphire/plugin-api 3.0.2 → 3.0.3-next.13bb97b.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/structures/MediaParser.d.ts +1 -1
- package/dist/lib/structures/api/CookieStore.js +128 -123
- package/dist/lib/structures/http/Auth.js +149 -148
- package/dist/lib/structures/http/HttpCodes.js +379 -379
- package/dist/lib/utils/MimeTypes.js +18 -18
- package/dist/lib/utils/RouteData.js +74 -67
- package/package.json +3 -3
|
@@ -36,6 +36,6 @@ export declare abstract class MediaParser extends Piece {
|
|
|
36
36
|
* @since 1.3.0
|
|
37
37
|
* @param request The request to read the body from.
|
|
38
38
|
*/
|
|
39
|
-
protected contentStream(request: ApiRequest):
|
|
39
|
+
protected contentStream(request: ApiRequest): import("zlib").BrotliDecompress | ApiRequest | null;
|
|
40
40
|
}
|
|
41
41
|
//# sourceMappingURL=MediaParser.d.ts.map
|
|
@@ -1,131 +1,136 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
// Copyright (c) 2018 Stanislav Woodger. All rights reserved. MIT license.
|
|
3
3
|
// Source: https://github.com/woodger/cookie-httponly
|
|
4
|
-
Object.defineProperty(exports,
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
5
|
exports.CookieStore = void 0;
|
|
6
|
-
const tslib_1 = require(
|
|
7
|
-
const psl_1 = (0, tslib_1.__importDefault)(require(
|
|
6
|
+
const tslib_1 = require("tslib");
|
|
7
|
+
const psl_1 = (0, tslib_1.__importDefault)(require("psl"));
|
|
8
8
|
class CookieStore extends Map {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
9
|
+
constructor(request, response, secure, domainOverwrite) {
|
|
10
|
+
super();
|
|
11
|
+
Object.defineProperty(this, "request", {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
configurable: true,
|
|
14
|
+
writable: true,
|
|
15
|
+
value: void 0
|
|
16
|
+
});
|
|
17
|
+
Object.defineProperty(this, "response", {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
configurable: true,
|
|
20
|
+
writable: true,
|
|
21
|
+
value: void 0
|
|
22
|
+
});
|
|
23
|
+
Object.defineProperty(this, "domain", {
|
|
24
|
+
enumerable: true,
|
|
25
|
+
configurable: true,
|
|
26
|
+
writable: true,
|
|
27
|
+
value: void 0
|
|
28
|
+
});
|
|
29
|
+
Object.defineProperty(this, "secure", {
|
|
30
|
+
enumerable: true,
|
|
31
|
+
configurable: true,
|
|
32
|
+
writable: true,
|
|
33
|
+
value: void 0
|
|
34
|
+
});
|
|
35
|
+
this.request = request;
|
|
36
|
+
this.response = response;
|
|
37
|
+
// Read cookies
|
|
38
|
+
const { cookie = '' } = request.headers;
|
|
39
|
+
const pairs = cookie.split(';');
|
|
40
|
+
for (const pair of pairs) {
|
|
41
|
+
const index = pair.indexOf('=');
|
|
42
|
+
if (index === -1)
|
|
43
|
+
continue;
|
|
44
|
+
const key = decodeURIComponent(pair.substr(0, index).trim());
|
|
45
|
+
const value = decodeURIComponent(pair.substr(index + 1).trim());
|
|
46
|
+
this.set(key, value);
|
|
47
|
+
}
|
|
48
|
+
const [splitHost] = this.request.headers.host?.split(':') ?? [''];
|
|
49
|
+
this.domain = domainOverwrite ?? this.getHostDomain(splitHost);
|
|
50
|
+
if (this.request.socket.remoteAddress === this.domain) {
|
|
51
|
+
throw new Error('The connection must be established from the domain name (i.e., not an IP address)');
|
|
52
|
+
}
|
|
53
|
+
// RFC 6265 4.1.2.5. The Secure Attribute
|
|
54
|
+
this.secure = secure;
|
|
55
|
+
}
|
|
56
|
+
add(name, value, options) {
|
|
57
|
+
this.insert(name, this.prepare(name, value, options));
|
|
58
|
+
}
|
|
59
|
+
remove(name) {
|
|
60
|
+
this.add(name, '', { expires: new Date(0) });
|
|
61
|
+
}
|
|
62
|
+
insert(name, entry) {
|
|
63
|
+
let set = this.response.getHeader('Set-Cookie');
|
|
64
|
+
if (set === undefined) {
|
|
65
|
+
set = [];
|
|
66
|
+
}
|
|
67
|
+
else if (!Array.isArray(set)) {
|
|
68
|
+
set = [set.toString()];
|
|
69
|
+
}
|
|
70
|
+
set = set.filter((i) => i.substr(0, i.indexOf('=')) !== name);
|
|
71
|
+
set.push(entry);
|
|
72
|
+
this.response.setHeader('Set-Cookie', set);
|
|
73
|
+
}
|
|
74
|
+
prepare(name, value, { expires, maxAge, domain, path, httpOnly } = {}) {
|
|
75
|
+
const now = new Date();
|
|
76
|
+
if (expires === undefined) {
|
|
77
|
+
expires = now;
|
|
78
|
+
}
|
|
79
|
+
// RFC 6265 4.1.1. Syntax
|
|
80
|
+
name = CookieStore.encodeCookieOctet(name);
|
|
81
|
+
value = CookieStore.encodeCookieOctet(value);
|
|
82
|
+
let entry = `${name}=${value}`;
|
|
83
|
+
if (expires !== now) {
|
|
84
|
+
entry += `; Expires=${expires.toUTCString()}`;
|
|
85
|
+
}
|
|
86
|
+
else if (maxAge) {
|
|
87
|
+
entry += `; Max-Age=${maxAge}`;
|
|
88
|
+
}
|
|
89
|
+
// RFC 6265 5.1.3 Domain Matching
|
|
90
|
+
domain = (domain ?? this.domain).toLowerCase();
|
|
91
|
+
entry += `; Domain=${domain}`;
|
|
92
|
+
entry += `; Path=${path ?? '/'}`;
|
|
93
|
+
if (this.secure) {
|
|
94
|
+
entry += `; Secure`;
|
|
95
|
+
}
|
|
96
|
+
if (httpOnly ?? true) {
|
|
97
|
+
entry += `; HttpOnly`;
|
|
98
|
+
}
|
|
99
|
+
return entry;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Parses a host using the {@linkplain https://github.com/lupomontero/psl psl} library to extract the domain.
|
|
103
|
+
* This is used for the domain of the cookie
|
|
104
|
+
* @param host The hot to parse
|
|
105
|
+
* @returns Either the host in all lower case or the parsed domain, ready for use on cookies
|
|
106
|
+
*/
|
|
107
|
+
getHostDomain(host) {
|
|
108
|
+
// Transform the host to lower case
|
|
109
|
+
const lowercaseHost = host.toLowerCase();
|
|
110
|
+
// Try parsing the host with psl
|
|
111
|
+
const pslParsedInfo = psl_1.default.parse(lowercaseHost);
|
|
112
|
+
// If an error ocurred then return the host in lowercase
|
|
113
|
+
if (pslParsedInfo.error)
|
|
114
|
+
return lowercaseHost;
|
|
115
|
+
// If the domain property is not defined then return the host in lowercase
|
|
116
|
+
if (!pslParsedInfo.domain)
|
|
117
|
+
return lowercaseHost;
|
|
118
|
+
// If the domain was found from parsing then prefix it with a . for a cookie that works with subdomains and return it
|
|
119
|
+
return `.${pslParsedInfo.domain}`;
|
|
120
|
+
}
|
|
121
|
+
static encodeCookieOctet(value) {
|
|
122
|
+
if (CookieStore.octetRegExp.test(value)) {
|
|
123
|
+
throw new Error(`Invalid character in value`);
|
|
124
|
+
}
|
|
125
|
+
return encodeURIComponent(value);
|
|
126
|
+
}
|
|
122
127
|
}
|
|
123
128
|
exports.CookieStore = CookieStore;
|
|
124
129
|
// RFC 6265 4.1.1. Syntax
|
|
125
|
-
Object.defineProperty(CookieStore,
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
+
Object.defineProperty(CookieStore, "octetRegExp", {
|
|
131
|
+
enumerable: true,
|
|
132
|
+
configurable: true,
|
|
133
|
+
writable: true,
|
|
134
|
+
value: /[^\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]/g
|
|
130
135
|
});
|
|
131
|
-
//# sourceMappingURL=CookieStore.js.map
|
|
136
|
+
//# sourceMappingURL=CookieStore.js.map
|
|
@@ -1,154 +1,155 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
var _Auth_secret;
|
|
3
|
-
Object.defineProperty(exports,
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.Auth = void 0;
|
|
5
|
-
const tslib_1 = require(
|
|
6
|
-
const utilities_1 = require(
|
|
7
|
-
const crypto_1 = require(
|
|
8
|
-
const v9_1 = require(
|
|
9
|
-
const node_fetch_1 = (0, tslib_1.__importDefault)(require(
|
|
5
|
+
const tslib_1 = require("tslib");
|
|
6
|
+
const utilities_1 = require("@sapphire/utilities");
|
|
7
|
+
const crypto_1 = require("crypto");
|
|
8
|
+
const v9_1 = require("discord-api-types/v9");
|
|
9
|
+
const node_fetch_1 = (0, tslib_1.__importDefault)(require("node-fetch"));
|
|
10
10
|
class Auth {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
11
|
+
constructor(options) {
|
|
12
|
+
/**
|
|
13
|
+
* The client's application id, this can be retrieved in Discord Developer Portal at https://discord.com/developers/applications.
|
|
14
|
+
* @since 1.0.0
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(this, "id", {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
configurable: true,
|
|
19
|
+
writable: true,
|
|
20
|
+
value: void 0
|
|
21
|
+
});
|
|
22
|
+
/**
|
|
23
|
+
* The name for the cookie, this will be used to identify a Secure HttpOnly cookie.
|
|
24
|
+
* @since 1.0.0
|
|
25
|
+
*/
|
|
26
|
+
Object.defineProperty(this, "cookie", {
|
|
27
|
+
enumerable: true,
|
|
28
|
+
configurable: true,
|
|
29
|
+
writable: true,
|
|
30
|
+
value: void 0
|
|
31
|
+
});
|
|
32
|
+
/**
|
|
33
|
+
* The scopes defined at https://discord.com/developers/docs/topics/oauth2#shared-resources-oauth2-scopes.
|
|
34
|
+
* @since 1.0.0
|
|
35
|
+
*/
|
|
36
|
+
Object.defineProperty(this, "scopes", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
configurable: true,
|
|
39
|
+
writable: true,
|
|
40
|
+
value: void 0
|
|
41
|
+
});
|
|
42
|
+
/**
|
|
43
|
+
* The redirect uri.
|
|
44
|
+
* @since 1.0.0
|
|
45
|
+
*/
|
|
46
|
+
Object.defineProperty(this, "redirect", {
|
|
47
|
+
enumerable: true,
|
|
48
|
+
configurable: true,
|
|
49
|
+
writable: true,
|
|
50
|
+
value: void 0
|
|
51
|
+
});
|
|
52
|
+
/**
|
|
53
|
+
* The transformers used for {@link Auth.fetchData}.
|
|
54
|
+
* @since 1.4.0
|
|
55
|
+
*/
|
|
56
|
+
Object.defineProperty(this, "transformers", {
|
|
57
|
+
enumerable: true,
|
|
58
|
+
configurable: true,
|
|
59
|
+
writable: true,
|
|
60
|
+
value: void 0
|
|
61
|
+
});
|
|
62
|
+
Object.defineProperty(this, "domainOverwrite", {
|
|
63
|
+
enumerable: true,
|
|
64
|
+
configurable: true,
|
|
65
|
+
writable: true,
|
|
66
|
+
value: null
|
|
67
|
+
});
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/explicit-member-accessibility
|
|
69
|
+
_Auth_secret.set(this, void 0);
|
|
70
|
+
this.id = options.id;
|
|
71
|
+
this.cookie = options.cookie ?? 'SAPPHIRE_AUTH';
|
|
72
|
+
this.scopes = options.scopes ?? ['identify'];
|
|
73
|
+
this.redirect = options.redirect;
|
|
74
|
+
(0, tslib_1.__classPrivateFieldSet)(this, _Auth_secret, options.secret, "f");
|
|
75
|
+
this.transformers = options.transformers ?? [];
|
|
76
|
+
this.domainOverwrite = options.domainOverwrite ?? null;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The client secret, this can be retrieved in Discord Developer Portal at https://discord.com/developers/applications.
|
|
80
|
+
* @since 1.0.0
|
|
81
|
+
*/
|
|
82
|
+
get secret() {
|
|
83
|
+
return (0, tslib_1.__classPrivateFieldGet)(this, _Auth_secret, "f");
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Encrypts an object with aes-256-cbc to use as a token.
|
|
87
|
+
* @since 1.0.0
|
|
88
|
+
* @param data An object to encrypt
|
|
89
|
+
* @param secret The secret to encrypt the data with
|
|
90
|
+
*/
|
|
91
|
+
encrypt(data) {
|
|
92
|
+
const iv = (0, crypto_1.randomBytes)(16);
|
|
93
|
+
const cipher = (0, crypto_1.createCipheriv)('aes-256-cbc', (0, tslib_1.__classPrivateFieldGet)(this, _Auth_secret, "f"), iv);
|
|
94
|
+
return `${cipher.update(JSON.stringify(data), 'utf8', 'base64') + cipher.final('base64')}.${iv.toString('base64')}`;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Decrypts an object with aes-256-cbc to use as a token.
|
|
98
|
+
* @since 1.0.0
|
|
99
|
+
* @param token An data to decrypt
|
|
100
|
+
* @param secret The secret to decrypt the data with
|
|
101
|
+
*/
|
|
102
|
+
decrypt(token) {
|
|
103
|
+
const [data, iv] = token.split('.');
|
|
104
|
+
const decipher = (0, crypto_1.createDecipheriv)('aes-256-cbc', (0, tslib_1.__classPrivateFieldGet)(this, _Auth_secret, "f"), Buffer.from(iv, 'base64'));
|
|
105
|
+
try {
|
|
106
|
+
const parsed = JSON.parse(decipher.update(data, 'base64', 'utf8') + decipher.final('utf8'));
|
|
107
|
+
// If the token expired, return null:
|
|
108
|
+
return parsed.expires >= Date.now() ? parsed : null;
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Retrieves the data for a specific user.
|
|
116
|
+
* @since 1.4.0
|
|
117
|
+
* @param token The access token from the user.
|
|
118
|
+
*/
|
|
119
|
+
async fetchData(token) {
|
|
120
|
+
// Fetch the information:
|
|
121
|
+
const [user, guilds, connections] = await Promise.all([
|
|
122
|
+
this.fetchInformation('identify', token, `${v9_1.RouteBases.api}${v9_1.Routes.user()}`),
|
|
123
|
+
this.fetchInformation('guilds', token, `${v9_1.RouteBases.api}${v9_1.Routes.userGuilds()}`),
|
|
124
|
+
this.fetchInformation('connections', token, `${v9_1.RouteBases.api}${v9_1.Routes.userConnections()}`)
|
|
125
|
+
]);
|
|
126
|
+
// Transform the information:
|
|
127
|
+
let data = { user, guilds, connections };
|
|
128
|
+
for (const transformer of this.transformers) {
|
|
129
|
+
const result = transformer(data);
|
|
130
|
+
if ((0, utilities_1.isThenable)(result))
|
|
131
|
+
data = await result;
|
|
132
|
+
else
|
|
133
|
+
data = result;
|
|
134
|
+
}
|
|
135
|
+
return data;
|
|
136
|
+
}
|
|
137
|
+
async fetchInformation(scope, token, url) {
|
|
138
|
+
if (!this.scopes.includes(scope))
|
|
139
|
+
return undefined;
|
|
140
|
+
const result = await (0, node_fetch_1.default)(url, {
|
|
141
|
+
headers: {
|
|
142
|
+
authorization: `Bearer ${token}`
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
return result.ok ? (await result.json()) : null;
|
|
146
|
+
}
|
|
147
|
+
static create(options) {
|
|
148
|
+
if (!options?.secret || !options.id)
|
|
149
|
+
return null;
|
|
150
|
+
return new Auth(options);
|
|
151
|
+
}
|
|
151
152
|
}
|
|
152
153
|
exports.Auth = Auth;
|
|
153
154
|
_Auth_secret = new WeakMap();
|
|
154
|
-
//# sourceMappingURL=Auth.js.map
|
|
155
|
+
//# sourceMappingURL=Auth.js.map
|