Skip to content

Commit 80462df

Browse files
committed
feat(role.controller.ts): implement role addition
1 parent 2beb6b5 commit 80462df

4 files changed

Lines changed: 372 additions & 8 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[
2+
"TEAM_OWNER",
3+
"BUILDER",
4+
"STAFF",
5+
"BUILD_TEAM_STAFF"
6+
]

src/commands/position.command.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const pseudoteamPositions: Record<string, Record<string, string>> = loadSyncJSON
1616
"../../../config/extensions/pseudoteamPositions.json5"
1717
)
1818
)
19+
1920
const forbiddenRoles = loadSyncJSON5(
2021
path.join(
2122
path.dirname(url.fileURLToPath(import.meta.url)) +

src/struct/web/methods/api/role.controller.ts

Lines changed: 161 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
1+
import { loadSyncJSON5, noop } from "@buildtheearth/bot-utils"
12
import { Controller, Get, Post, Param, Req, Res, Body } from "@nestjs/common"
23
import { GuildMember } from "discord.js"
34
import { Response, Request } from "express"
5+
import path from "path"
6+
import url from "url"
7+
8+
const allowedRoleKeys = loadSyncJSON5(
9+
path.join(
10+
path.dirname(url.fileURLToPath(import.meta.url)),
11+
"../../../../../config/extensions/allowedRolesToSync.json5"
12+
)
13+
)
414

515
@Controller("/api/v1/role")
616
export default class RoleController {
@@ -59,17 +69,164 @@ export default class RoleController {
5969
return
6070
}
6171

72+
6273
@Post(":id")
6374
async builderPost(
6475
@Req() req: Request,
6576
@Res() res: Response,
6677
@Param("id") id: string,
67-
@Body("add") add: boolean
78+
@Body("add") add: boolean,
79+
@Body("roles") roles: string[]
6880
): Promise<unknown> {
6981
res.type("application/json")
70-
return res.status(501).send({
71-
error: "NOT_IMPLEMENTED",
72-
message: "Function not implemented: Role Post"
82+
83+
if (!id) {
84+
return res.status(400).send({
85+
error: "MISSING_PARAMETER",
86+
message: "Missing parameter: id"
87+
})
88+
}
89+
90+
if (typeof add !== "boolean") {
91+
return res.status(400).send({
92+
error: "MISSING_PARAMETER",
93+
message: "Missing parameter: add (boolean)"
94+
})
95+
}
96+
97+
if (!roles || !Array.isArray(roles) || roles.length === 0) {
98+
return res.status(400).send({
99+
error: "MISSING_PARAMETER",
100+
message: "Missing parameter: roles (array of role keys)"
101+
})
102+
}
103+
104+
if (allowedRoleKeys.length === 0) {
105+
return res.status(503).send({
106+
error: "SERVICE_UNAVAILABLE",
107+
message: "Role sync whitelist is not configured or empty"
108+
})
109+
}
110+
111+
const invalidRoles = roles.filter(roleKey => !allowedRoleKeys.includes(roleKey))
112+
if (invalidRoles.length > 0) {
113+
return res.status(403).send({
114+
error: "FORBIDDEN",
115+
message: "One or more role keys are not allowed to be synced",
116+
invalidRoles
117+
})
118+
}
119+
120+
const roleMappings = globalThis.client.roles
121+
122+
const mainGuild = globalThis.client.customGuilds.main()
123+
const staffGuild = globalThis.client.customGuilds.staff()
124+
125+
let mainUser: GuildMember | null = null
126+
let staffUser: GuildMember | null = null
127+
128+
try {
129+
mainUser = await mainGuild.members.fetch({ user: id }).catch(noop)
130+
} catch {
131+
// User not in main guild
132+
}
133+
134+
try {
135+
staffUser = await staffGuild.members.fetch({ user: id }).catch(noop)
136+
} catch {
137+
// User not in staff guild
138+
}
139+
140+
if (!mainUser && !staffUser) {
141+
return res.status(404).send({
142+
error: "NOT_FOUND",
143+
message: "User not found in any guild"
144+
})
145+
}
146+
147+
const results = {
148+
main: {
149+
success: [] as string[],
150+
failure: [] as Array<{ roleKey: string; error: string }>
151+
},
152+
staff: {
153+
success: [] as string[],
154+
failure: [] as Array<{ roleKey: string; error: string }>
155+
}
156+
}
157+
158+
for (const roleKey of roles) {
159+
const roleIds = roleMappings[roleKey]
160+
161+
if (!roleIds || roleIds.length === 0) {
162+
// Role key not found in mappings
163+
results.main.failure.push({
164+
roleKey,
165+
error: "Role key not found in role mappings"
166+
})
167+
results.staff.failure.push({
168+
roleKey,
169+
error: "Role key not found in role mappings"
170+
})
171+
continue
172+
}
173+
174+
175+
for (const roleId of roleIds) {
176+
// Check if this role exists in main guild
177+
if (mainUser) {
178+
const mainRole = mainGuild.roles.cache.get(roleId)
179+
if (mainRole) {
180+
try {
181+
if (add) {
182+
await mainUser.roles.add(roleId)
183+
} else {
184+
await mainUser.roles.remove(roleId)
185+
}
186+
if (!results.main.success.includes(roleKey)) {
187+
results.main.success.push(roleKey)
188+
}
189+
} catch (error) {
190+
if (!results.main.failure.some(f => f.roleKey === roleKey)) {
191+
results.main.failure.push({
192+
roleKey,
193+
error: error instanceof Error ? error.message : "Unknown error"
194+
})
195+
}
196+
}
197+
}
198+
}
199+
200+
// Check if this role exists in staff guild
201+
if (staffUser) {
202+
const staffRole = staffGuild.roles.cache.get(roleId)
203+
if (staffRole) {
204+
try {
205+
if (add) {
206+
await staffUser.roles.add(roleId)
207+
} else {
208+
await staffUser.roles.remove(roleId)
209+
}
210+
if (!results.staff.success.includes(roleKey)) {
211+
results.staff.success.push(roleKey)
212+
}
213+
} catch (error) {
214+
if (!results.staff.failure.some(f => f.roleKey === roleKey)) {
215+
results.staff.failure.push({
216+
roleKey,
217+
error: error instanceof Error ? error.message : "Unknown error"
218+
})
219+
}
220+
}
221+
}
222+
}
223+
}
224+
}
225+
226+
return res.status(200).send({
227+
userId: id,
228+
operation: add ? "add" : "remove",
229+
results
73230
})
74231
}
75232
}

0 commit comments

Comments
 (0)