fix(bots/discord): give only removed roles for role presets

This commit is contained in:
PalmDevs
2024-08-23 18:05:48 +07:00
parent 94c4fedc06
commit 522ad28fd8
6 changed files with 47 additions and 25 deletions

View File

@@ -33,14 +33,14 @@
"@revanced/bot-api": "workspace:*", "@revanced/bot-api": "workspace:*",
"@revanced/bot-shared": "workspace:*", "@revanced/bot-shared": "workspace:*",
"chalk": "^5.3.0", "chalk": "^5.3.0",
"decancer": "^3.2.3", "decancer": "^3.2.4",
"discord.js": "^14.15.3", "discord.js": "^14.15.3",
"drizzle-orm": "^0.31.4", "drizzle-orm": "^0.31.4",
"parse-duration": "^1.1.0" "parse-duration": "^1.1.0"
}, },
"devDependencies": { "devDependencies": {
"@libsql/client": "^0.7.0", "@libsql/client": "^0.7.0",
"discord-api-types": "^0.37.92", "discord-api-types": "^0.37.97",
"drizzle-kit": "^0.22.8" "drizzle-kit": "^0.22.8"
} }
} }

View File

@@ -16,6 +16,7 @@ export const appliedPresets = sqliteTable(
{ {
memberId: text('member').notNull(), memberId: text('member').notNull(),
guildId: text('guild').notNull(), guildId: text('guild').notNull(),
removedRoles: text('roles', { mode: 'json' }).notNull().$type<string[]>().default([]),
preset: text('preset').notNull(), preset: text('preset').notNull(),
until: integer('until'), until: integer('until'),
}, },

View File

@@ -12,5 +12,5 @@ withContext(on, 'guildMemberAdd', async ({ database }, member) => {
), ),
}) })
for (const { preset } of applieds) await applyRolesUsingPreset(preset, member, true) for (const { preset } of applieds) await applyRolesUsingPreset(preset, member)
}) })

View File

@@ -7,7 +7,7 @@ import { and, eq } from 'drizzle-orm'
type PresetKey = string type PresetKey = string
export const applyRolePreset = async (member: GuildMember, presetName: PresetKey, expires: number) => { export const applyRolePreset = async (member: GuildMember, presetName: PresetKey, expires: number) => {
const afterInsert = await applyRolesUsingPreset(presetName, member, true) const { removed, callback } = await applyRolesUsingPreset(presetName, member)
const until = expires === Infinity ? null : Math.ceil(expires / 1000) const until = expires === Infinity ? null : Math.ceil(expires / 1000)
await database await database
@@ -16,39 +16,60 @@ export const applyRolePreset = async (member: GuildMember, presetName: PresetKey
memberId: member.id, memberId: member.id,
guildId: member.guild.id, guildId: member.guild.id,
preset: presetName, preset: presetName,
removedRoles: removed,
until, until,
}) })
.onConflictDoUpdate({ .onConflictDoUpdate({
target: [appliedPresets.memberId, appliedPresets.preset, appliedPresets.guildId], target: [appliedPresets.memberId, appliedPresets.preset, appliedPresets.guildId],
set: { until }, set: { until },
}) })
.then(afterInsert) .then(callback)
} }
export const removeRolePreset = async (member: GuildMember, presetName: PresetKey) => { export const removeRolePreset = async (member: GuildMember, presetName: PresetKey) => {
const afterDelete = await applyRolesUsingPreset(presetName, member, false) const where = and(
eq(appliedPresets.memberId, member.id),
eq(appliedPresets.preset, presetName),
eq(appliedPresets.guildId, member.guild.id),
)
await database const data = await database.query.appliedPresets.findFirst({ where })
.delete(appliedPresets) if (!data) return false
.where(
and( const { callback } = await applyRolesUsingPreset(presetName, member, data.removedRoles)
eq(appliedPresets.memberId, member.id), await database.delete(appliedPresets).where(where).execute().then(callback)
eq(appliedPresets.preset, presetName),
eq(appliedPresets.guildId, member.guild.id), return true
),
)
.execute()
.then(afterDelete)
} }
export const applyRolesUsingPreset = async (presetName: string, member: GuildMember, applying: boolean) => { export const applyRolesUsingPreset = async (
presetName: string,
member: GuildMember,
removePresetGiveRoles?: string[],
) => {
const preset = config.rolePresets?.guilds[member.guild.id]?.[presetName] const preset = config.rolePresets?.guilds[member.guild.id]?.[presetName]
if (!preset) throw new Error(`The preset "${presetName}" does not exist for this server`) if (!preset) throw new Error(`The preset "${presetName}" does not exist for this server`)
const roles = new Set(member.roles.cache.keys()) const roles = new Set(member.roles.cache.keys())
const removed: string[] = []
for (const role of preset.give) roles[applying ? 'add' : 'delete'](role) // If removePresetGiveRoles is not provided, we're applying a preset
for (const role of preset.take) roles[applying ? 'delete' : 'add'](role) if (!removePresetGiveRoles) {
for (const role of preset.give) roles.add(role)
for (const role of preset.take) {
if (roles.has(role)) {
roles.delete(role)
removed.push(role)
}
}
} else {
const guildRoles = await member.guild.roles.fetch()
for (const role of preset.give) roles.delete(role)
for (const role of removePresetGiveRoles) if (guildRoles.has(role)) roles.add(role)
}
return () => member.roles.set(Array.from(roles)) return {
removed,
callback: () => member.roles.set(Array.from(roles)),
}
} }

BIN
bun.lockb

Binary file not shown.

View File

@@ -32,7 +32,7 @@
"@anolilab/multi-semantic-release": "^1.1.3", "@anolilab/multi-semantic-release": "^1.1.3",
"@biomejs/biome": "^1.8.3", "@biomejs/biome": "^1.8.3",
"@codedependant/semantic-release-docker": "^5.0.3", "@codedependant/semantic-release-docker": "^5.0.3",
"@commitlint/cli": "^19.3.0", "@commitlint/cli": "^19.4.0",
"@commitlint/config-conventional": "^19.2.2", "@commitlint/config-conventional": "^19.2.2",
"@saithodev/semantic-release-backmerge": "^4.0.1", "@saithodev/semantic-release-backmerge": "^4.0.1",
"@semantic-release/changelog": "^6.0.3", "@semantic-release/changelog": "^6.0.3",
@@ -41,10 +41,10 @@
"@tsconfig/strictest": "^2.0.5", "@tsconfig/strictest": "^2.0.5",
"@types/bun": "^1.1.6", "@types/bun": "^1.1.6",
"conventional-changelog-conventionalcommits": "^7.0.2", "conventional-changelog-conventionalcommits": "^7.0.2",
"lefthook": "^1.7.5", "lefthook": "^1.7.14",
"portainer-service-webhook": "https://github.com/newarifrh/portainer-service-webhook#v1", "portainer-service-webhook": "https://github.com/newarifrh/portainer-service-webhook#v1",
"semantic-release": "^24.0.0", "semantic-release": "^24.1.0",
"turbo": "^2.0.9", "turbo": "^2.0.14",
"typescript": "^5.5.4" "typescript": "^5.5.4"
}, },
"trustedDependencies": [ "trustedDependencies": [