Skip to content

Commit 7a384f9

Browse files
committed
feat: set up syncing of bot members
1 parent 782202f commit 7a384f9

File tree

4 files changed

+109
-23
lines changed

4 files changed

+109
-23
lines changed

libs/api/bot/data-access/src/lib/api-bot-manager.service.ts

+49-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Injectable, Logger, OnModuleInit } from '@nestjs/common'
2+
import { Cron, CronExpression } from '@nestjs/schedule'
23
import { Bot } from '@prisma/client'
34

45
import { createDiscordRestClient, DiscordBot } from '@pubkey-link/api-bot-util'
@@ -170,11 +171,6 @@ export class ApiBotManagerService implements OnModuleInit {
170171
}
171172

172173
async syncBotServer(userId: string, botId: string, serverId: string) {
173-
const bot = this.ensureBotInstance(botId)
174-
if (!bot) {
175-
console.log(`Can't find bot.`, botId, serverId)
176-
return false
177-
}
178174
const community = await this.core.data.community.findFirst({
179175
where: { bot: { id: botId } },
180176
include: { bot: true },
@@ -183,13 +179,48 @@ export class ApiBotManagerService implements OnModuleInit {
183179
console.log(`Can't find community.`, botId, serverId)
184180
return false
185181
}
182+
await this.core.ensureCommunityAdmin({ userId, communityId: community.id })
183+
await this.syncBotServerMembers({
184+
communityId: community.id,
185+
botId,
186+
serverId,
187+
})
188+
return true
189+
}
190+
191+
@Cron(CronExpression.EVERY_5_MINUTES)
192+
private async syncBotServers() {
193+
const bots = await this.core.data.bot.findMany({ where: { status: BotStatus.Active } })
194+
195+
for (const bot of bots) {
196+
const servers = await this.getBotServers('-no-user-id-', bot.id)
197+
for (const server of servers) {
198+
await this.syncBotServerMembers({ botId: bot.id, communityId: bot.communityId, serverId: server.id })
199+
}
200+
}
201+
}
202+
203+
async syncBotServerMembers({
204+
botId,
205+
communityId,
206+
serverId,
207+
}: {
208+
botId: string
209+
communityId: string
210+
serverId: string
211+
}) {
212+
const discordBot = this.ensureBotInstance(botId)
213+
if (!discordBot) {
214+
console.log(`Can't find bot.`, botId, serverId)
215+
return false
216+
}
186217
this.logger.verbose(`Fetching members... ${botId} ${serverId}`)
187218

188219
const [discordIdentityIds, botMemberIds] = await Promise.all([
189220
this.botMember.getDiscordIdentityIds(),
190221
this.botMember.getBotMemberIds(botId, serverId),
191222
])
192-
const members = await bot.getDiscordServerMembers(serverId)
223+
const members = await discordBot.getDiscordServerMembers(serverId)
193224

194225
this.logger.verbose(`Found ${members.length} members to process`)
195226
const filtered = members
@@ -202,20 +233,28 @@ export class ApiBotManagerService implements OnModuleInit {
202233

203234
if (toBeDeleted.length) {
204235
this.logger.warn(`Found ${toBeDeleted.length} members to delete`)
205-
this.logger.warn(`TODO: DELETE MEMBERS`)
236+
for (const userId of toBeDeleted) {
237+
this.logger.verbose(`Removing member ${userId} from bot ${botId} server ${serverId}...`)
238+
await this.botMember.scheduleRemoveMember({ communityId, botId, serverId, userId })
239+
}
206240
}
207241

208242
this.logger.verbose(`Found ${filtered.length} members to process (filtered)`)
209243
let linkedCount = 0
210244
for (const member of filtered) {
211245
const userId = member.id
212-
await this.botMember.scheduleAddMember(community.bot, serverId, userId)
213-
214-
this.logger.verbose(`${botId} ${serverId} Processed ${member.user.username} (linked: ${!!member.id})`)
246+
await this.botMember.scheduleAddMember({ communityId, botId: botId, serverId, userId })
215247
if (member.id) {
216248
linkedCount++
217249
}
218250
}
251+
await this.core.logInfo(
252+
`Found ${members.length} members to process (filtered ${filtered.length}) (linked ${linkedCount})`,
253+
{
254+
botId,
255+
communityId,
256+
},
257+
)
219258
this.logger.verbose(
220259
`Found ${members.length} members to process (filtered ${filtered.length}) (linked ${linkedCount})`,
221260
)

libs/api/bot/data-access/src/lib/api-bot-member.service.ts

+42-8
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,22 @@ export class ApiBotMemberService {
2323
return
2424
}
2525
this.logger.verbose(`Setting up listeners for bot ${bot.name}`)
26-
instance.client?.on('guildMemberAdd', (member) => this.scheduleAddMember(bot, member.guild.id, member.id))
27-
instance.client.on('guildMemberRemove', (member) => this.scheduleRemoveMember(bot, member.guild.id, member.id))
26+
instance.client?.on('guildMemberAdd', (member) =>
27+
this.scheduleAddMember({
28+
botId: bot.id,
29+
communityId: bot.communityId,
30+
serverId: member.guild.id,
31+
userId: member.id,
32+
}),
33+
)
34+
instance.client.on('guildMemberRemove', (member) =>
35+
this.scheduleRemoveMember({
36+
botId: bot.id,
37+
communityId: bot.communityId,
38+
serverId: member.guild.id,
39+
userId: member.id,
40+
}),
41+
)
2842
}
2943

3044
async upsert({
@@ -146,21 +160,41 @@ export class ApiBotMemberService {
146160
})
147161
}
148162

149-
async scheduleAddMember(bot: Bot, serverId: string, userId: string) {
150-
const jobId = `${bot.id}-${serverId}-${userId}`
163+
async scheduleAddMember({
164+
botId,
165+
communityId,
166+
serverId,
167+
userId,
168+
}: {
169+
botId: string
170+
communityId: string
171+
serverId: string
172+
userId: string
173+
}) {
174+
const jobId = `${botId}-${serverId}-${userId}`
151175
await this.botMemberAddQueue
152-
.add('member-add', { botId: bot.id, communityId: bot.communityId, serverId, userId })
176+
.add('member-add', { botId, communityId, serverId, userId })
153177
.then((res) => {
154178
this.logger.verbose(`scheduleAddMember queued: ${res.id}`)
155179
})
156180
.catch((err) => {
157181
this.logger.error(`scheduleAddMember error: ${jobId}: ${err}`)
158182
})
159183
}
160-
async scheduleRemoveMember(bot: Bot, serverId: string, userId: string) {
161-
const jobId = `${bot.id}-${serverId}-${userId}`
184+
async scheduleRemoveMember({
185+
botId,
186+
communityId,
187+
serverId,
188+
userId,
189+
}: {
190+
botId: string
191+
communityId: string
192+
serverId: string
193+
userId: string
194+
}) {
195+
const jobId = `${botId}-${serverId}-${userId}`
162196
await this.botMemberRemoveQueue
163-
.add('member-remove', { botId: bot.id, communityId: bot.communityId, serverId, userId })
197+
.add('member-remove', { botId, communityId, serverId, userId })
164198
.then((res) => {
165199
this.logger.verbose(`scheduleRemoveMember queued: ${res.id}`)
166200
})

libs/api/network-asset/data-access/src/lib/api-network-asset-sync.service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export class ApiNetworkAssetSyncService {
3939
return !!job.id
4040
}
4141

42-
@Cron(CronExpression.EVERY_MINUTE)
42+
@Cron(CronExpression.EVERY_10_MINUTES)
4343
async syncAll() {
4444
const identities = await this.core.data.identity.findMany({
4545
where: {

libs/web/user/feature/src/lib/user-user-detail-feature.tsx

+17-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,17 @@ import { UserNetworkTokenFeature } from '@pubkey-link/web-network-token-feature'
77
import { UiGrid } from '@pubkey-link/web-ui-core'
88
import { useUserFineOneUser } from '@pubkey-link/web-user-data-access'
99
import { UserUiProfile } from '@pubkey-link/web-user-ui'
10-
import { UiCard, UiContainer, UiDebugModal, UiGroup, UiLoader, UiStack, UiTabRoutes, UiWarning } from '@pubkey-ui/core'
10+
import {
11+
UiCard,
12+
UiContainer,
13+
UiDebugModal,
14+
UiGroup,
15+
UiLoader,
16+
UiStack,
17+
UiTabRoutes,
18+
UiTime,
19+
UiWarning,
20+
} from '@pubkey-ui/core'
1121
import { Link, useParams } from 'react-router-dom'
1222

1323
export function UserUserDetailFeature() {
@@ -43,13 +53,16 @@ export function UserUserDetailFeature() {
4353
/>
4454
{items?.map((identity) => (
4555
<UiCard key={identity.id} p="xs">
46-
<UiGroup align="start">
47-
<Group>
48-
<IdentityUiIcon provider={identity.provider} />
56+
<UiGroup align="center">
57+
<Group gap="xs">
58+
<IdentityUiIcon size={28} provider={identity.provider} />
4959
<Stack gap={0}>
5060
<Text size="sm" fw="bold">
5161
{ellipsify(identity.name ?? identity.providerId, 6)}
5262
</Text>
63+
{identity.syncEnded ? (
64+
<UiTime size="xs" c="dimmed" prefix="Synced " date={new Date(identity.syncEnded)} />
65+
) : null}
5366
</Stack>
5467
</Group>
5568
<Group gap={2}>

0 commit comments

Comments
 (0)