simple-discord-bot.js 0.1.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/api.js +61 -0
- package/client.js +166 -0
- package/gateway.js +91 -0
- package/index.js +5 -0
- package/package.json +16 -0
- package/structures/Message.js +23 -0
package/api.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const https = require("https")
|
|
2
|
+
|
|
3
|
+
class API {
|
|
4
|
+
constructor(token) {
|
|
5
|
+
this.token = token
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
request(method, path, body = null) {
|
|
9
|
+
return new Promise((resolve, reject) => {
|
|
10
|
+
const data = body ? JSON.stringify(body) : null
|
|
11
|
+
|
|
12
|
+
const headers = {
|
|
13
|
+
Authorization: `Bot ${this.token}`,
|
|
14
|
+
"Content-Type": "application/json"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (data) {
|
|
18
|
+
headers["Content-Length"] = Buffer.byteLength(data)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const req = https.request({
|
|
22
|
+
hostname: "discord.com",
|
|
23
|
+
path: `/api/v10${path}`,
|
|
24
|
+
method,
|
|
25
|
+
headers
|
|
26
|
+
}, res => {
|
|
27
|
+
let result = ""
|
|
28
|
+
|
|
29
|
+
res.on("data", chunk => {
|
|
30
|
+
result += chunk
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
res.on("end", () => {
|
|
34
|
+
try {
|
|
35
|
+
resolve(JSON.parse(result))
|
|
36
|
+
} catch {
|
|
37
|
+
resolve(result)
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
req.on("error", reject)
|
|
43
|
+
|
|
44
|
+
if (data) {
|
|
45
|
+
req.write(data)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
req.end()
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
registerCommands(applicationId, commands) {
|
|
53
|
+
return this.request(
|
|
54
|
+
"PUT",
|
|
55
|
+
`/applications/${applicationId}/commands`,
|
|
56
|
+
commands
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
module.exports = API
|
package/client.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
const EventEmitter = require("events")
|
|
2
|
+
const Gateway = require("./gateway")
|
|
3
|
+
const API = require("./api")
|
|
4
|
+
const Message = require("./structures/Message")
|
|
5
|
+
|
|
6
|
+
const PermissionFlags = {
|
|
7
|
+
CreateInstantInvite: 1n << 0n,
|
|
8
|
+
KickMembers: 1n << 1n,
|
|
9
|
+
BanMembers: 1n << 2n,
|
|
10
|
+
Administrator: 1n << 3n,
|
|
11
|
+
ManageChannels: 1n << 4n,
|
|
12
|
+
ManageGuild: 1n << 5n,
|
|
13
|
+
AddReactions: 1n << 6n,
|
|
14
|
+
ViewAuditLog: 1n << 7n,
|
|
15
|
+
PrioritySpeaker: 1n << 8n,
|
|
16
|
+
Stream: 1n << 9n,
|
|
17
|
+
ViewChannel: 1n << 10n,
|
|
18
|
+
SendMessages: 1n << 11n,
|
|
19
|
+
SendTTSMessages: 1n << 12n,
|
|
20
|
+
ManageMessages: 1n << 13n,
|
|
21
|
+
EmbedLinks: 1n << 14n,
|
|
22
|
+
AttachFiles: 1n << 15n,
|
|
23
|
+
ReadMessageHistory: 1n << 16n,
|
|
24
|
+
MentionEveryone: 1n << 17n,
|
|
25
|
+
UseExternalEmojis: 1n << 18n,
|
|
26
|
+
ViewGuildInsights: 1n << 19n,
|
|
27
|
+
Connect: 1n << 20n,
|
|
28
|
+
Speak: 1n << 21n,
|
|
29
|
+
MuteMembers: 1n << 22n,
|
|
30
|
+
DeafenMembers: 1n << 23n,
|
|
31
|
+
MoveMembers: 1n << 24n,
|
|
32
|
+
UseVAD: 1n << 25n,
|
|
33
|
+
ChangeNickname: 1n << 26n,
|
|
34
|
+
ManageNicknames: 1n << 27n,
|
|
35
|
+
ManageRoles: 1n << 28n,
|
|
36
|
+
ManageWebhooks: 1n << 29n,
|
|
37
|
+
ManageGuildExpressions: 1n << 30n,
|
|
38
|
+
UseApplicationCommands: 1n << 31n
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
class Permissions {
|
|
42
|
+
constructor(value) {
|
|
43
|
+
this.bitfield = BigInt(value || 0)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
has(permission) {
|
|
47
|
+
const flag = PermissionFlags[permission]
|
|
48
|
+
|
|
49
|
+
if (flag === undefined) {
|
|
50
|
+
return false
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if ((this.bitfield & PermissionFlags.Administrator) !== 0n) {
|
|
54
|
+
return true
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return (this.bitfield & flag) !== 0n
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
class Client extends EventEmitter {
|
|
62
|
+
constructor() {
|
|
63
|
+
super()
|
|
64
|
+
|
|
65
|
+
this.token = null
|
|
66
|
+
this.user = null
|
|
67
|
+
this.api = null
|
|
68
|
+
this.gateway = new Gateway(this)
|
|
69
|
+
this.commands = new Map()
|
|
70
|
+
this.stopping = false
|
|
71
|
+
|
|
72
|
+
this.on("rawMessage", data => {
|
|
73
|
+
const message = new Message(this, data)
|
|
74
|
+
this.emit("message", message)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
this.on("rawInteraction", data => {
|
|
78
|
+
if (data.type !== 2) return
|
|
79
|
+
|
|
80
|
+
const command = this.commands.get(data.data.name)
|
|
81
|
+
|
|
82
|
+
if (!command) return
|
|
83
|
+
|
|
84
|
+
const member = data.member
|
|
85
|
+
|
|
86
|
+
const interaction = {
|
|
87
|
+
id: data.id,
|
|
88
|
+
token: data.token,
|
|
89
|
+
|
|
90
|
+
commandName: data.data.name,
|
|
91
|
+
|
|
92
|
+
user: member?.user || data.user,
|
|
93
|
+
|
|
94
|
+
member: member ? {
|
|
95
|
+
...member,
|
|
96
|
+
|
|
97
|
+
permissions: new Permissions(member.permissions)
|
|
98
|
+
} : null,
|
|
99
|
+
|
|
100
|
+
channelId: data.channel_id,
|
|
101
|
+
|
|
102
|
+
guildId: data.guild_id || null,
|
|
103
|
+
|
|
104
|
+
options: {},
|
|
105
|
+
|
|
106
|
+
reply: content => {
|
|
107
|
+
return this.api.request(
|
|
108
|
+
"POST",
|
|
109
|
+
`/interactions/${data.id}/${data.token}/callback`,
|
|
110
|
+
{
|
|
111
|
+
type: 4,
|
|
112
|
+
data: {
|
|
113
|
+
content: content
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
for (const option of data.data.options || []) {
|
|
121
|
+
interaction.options[option.name] = option.value
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
command.handler(interaction)
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
process.on("SIGINT", () => {
|
|
128
|
+
if (this.stopping) return
|
|
129
|
+
|
|
130
|
+
this.stopping = true
|
|
131
|
+
|
|
132
|
+
console.log("Stopping bot...")
|
|
133
|
+
|
|
134
|
+
this.destroy()
|
|
135
|
+
|
|
136
|
+
setTimeout(() => {
|
|
137
|
+
process.exit(0)
|
|
138
|
+
}, 1000)
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
login(token) {
|
|
143
|
+
this.token = token
|
|
144
|
+
this.api = new API(token)
|
|
145
|
+
|
|
146
|
+
return this.gateway.connect(token)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
destroy() {
|
|
150
|
+
this.gateway.destroy()
|
|
151
|
+
this.emit("disconnect")
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
command(name, handler, options = {}) {
|
|
155
|
+
this.commands.set(name, {
|
|
156
|
+
command: {
|
|
157
|
+
name: name,
|
|
158
|
+
description: options.description || "No description",
|
|
159
|
+
options: options.options || []
|
|
160
|
+
},
|
|
161
|
+
handler
|
|
162
|
+
})
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
module.exports = Client
|
package/gateway.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const WebSocket = require("ws")
|
|
2
|
+
|
|
3
|
+
class Gateway {
|
|
4
|
+
constructor(client) {
|
|
5
|
+
this.client = client
|
|
6
|
+
this.ws = null
|
|
7
|
+
this.heartbeat = null
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
connect(token) {
|
|
11
|
+
this.ws = new WebSocket(
|
|
12
|
+
"wss://gateway.discord.gg/?v=10&encoding=json"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
this.ws.on("open", () => {
|
|
16
|
+
this.ws.send(JSON.stringify({
|
|
17
|
+
op: 2,
|
|
18
|
+
d: {
|
|
19
|
+
token: token,
|
|
20
|
+
intents: 33281,
|
|
21
|
+
properties: {
|
|
22
|
+
os: "android",
|
|
23
|
+
browser: "SimpleDiscord.js",
|
|
24
|
+
device: "SimpleDiscord.js"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}))
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
this.ws.on("message", data => {
|
|
31
|
+
const packet = JSON.parse(data)
|
|
32
|
+
|
|
33
|
+
if (packet.op === 10) {
|
|
34
|
+
this.startHeartbeat(packet.d.heartbeat_interval)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (packet.t === "READY") {
|
|
38
|
+
this.client.user = packet.d.user
|
|
39
|
+
this.client.emit("ready", packet.d)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (packet.t === "MESSAGE_CREATE") {
|
|
43
|
+
this.client.emit("rawMessage", packet.d)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (packet.t === "INTERACTION_CREATE") {
|
|
47
|
+
this.client.emit("rawInteraction", packet.d)
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
this.ws.on("error", error => {
|
|
52
|
+
this.client.emit("error", error)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
this.ws.on("close", () => {
|
|
56
|
+
this.stopHeartbeat()
|
|
57
|
+
this.ws = null
|
|
58
|
+
this.client.emit("disconnect")
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
startHeartbeat(interval) {
|
|
63
|
+
this.stopHeartbeat()
|
|
64
|
+
|
|
65
|
+
this.heartbeat = setInterval(() => {
|
|
66
|
+
if (!this.ws) return
|
|
67
|
+
|
|
68
|
+
this.ws.send(JSON.stringify({
|
|
69
|
+
op: 1,
|
|
70
|
+
d: null
|
|
71
|
+
}))
|
|
72
|
+
}, interval)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
stopHeartbeat() {
|
|
76
|
+
if (this.heartbeat) {
|
|
77
|
+
clearInterval(this.heartbeat)
|
|
78
|
+
this.heartbeat = null
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
destroy() {
|
|
83
|
+
this.stopHeartbeat()
|
|
84
|
+
|
|
85
|
+
if (this.ws) {
|
|
86
|
+
this.ws.close(1000, "Bot stopped")
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
module.exports = Gateway
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "simple-discord-bot.js",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A simple Discord bot library",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"discord",
|
|
9
|
+
"discord-bot",
|
|
10
|
+
"discord-library",
|
|
11
|
+
"discord-api"
|
|
12
|
+
],
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"ws": "^8.18.3"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
class Message {
|
|
2
|
+
constructor(client, data) {
|
|
3
|
+
this.client = client
|
|
4
|
+
|
|
5
|
+
this.id = data.id
|
|
6
|
+
this.content = data.content
|
|
7
|
+
this.channelId = data.channel_id
|
|
8
|
+
this.guildId = data.guild_id
|
|
9
|
+
this.author = data.author
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
reply(content) {
|
|
13
|
+
return this.client.api.request(
|
|
14
|
+
"POST",
|
|
15
|
+
`/channels/${this.channelId}/messages`,
|
|
16
|
+
{
|
|
17
|
+
content: content
|
|
18
|
+
}
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = Message
|