Skip to content

Commit

Permalink
feat(core): add guildId to channel table
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Feb 10, 2022
1 parent c6b1b91 commit ea154ac
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 43 deletions.
3 changes: 2 additions & 1 deletion packages/core/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,10 @@ export class App extends Context {
if (this.database) {
if (session.subtype === 'group') {
// attach group data
const channelFields = new Set<Channel.Field>(['flag', 'assignee'])
const channelFields = new Set<Channel.Field>(['flag', 'assignee', 'guildId'])
this.emit('before-attach-channel', session, channelFields)
const channel = await session.observeChannel(channelFields)
channel.guildId = session.guildId

// emit attach event
if (await this.serial(session, 'attach-channel', session)) return
Expand Down
7 changes: 4 additions & 3 deletions packages/core/src/bot.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Dict, Logger, Random, sleep } from '@koishijs/utils'
import { Dict, Logger, makeArray, Random, sleep } from '@koishijs/utils'
import { Adapter } from './adapter'
import { App } from './app'
import { Session } from './session'
Expand Down Expand Up @@ -112,12 +112,13 @@ export abstract class Bot<T extends Bot.BaseConfig = Bot.BaseConfig> {
return Object.fromEntries(list.map(info => [info.userId, info.nickname || info.username]))
}

async broadcast(channels: string[], content: string, delay = this.app.options.delay.broadcast) {
async broadcast(channels: (string | [string, string])[], content: string, delay = this.app.options.delay.broadcast) {
const messageIds: string[] = []
for (let index = 0; index < channels.length; index++) {
if (index && delay) await sleep(delay)
try {
messageIds.push(...await this.sendMessage(channels[index], content, 'unknown'))
const [channelId, guildId] = makeArray(channels[index])
messageIds.push(...await this.sendMessage(channelId, content, guildId))
} catch (error) {
this.app.logger('bot').warn(error)
}
Expand Down
20 changes: 4 additions & 16 deletions packages/core/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -566,24 +566,12 @@ export class Context {
const [content, forced] = args as [string, boolean]
if (!content) return []

const data = this.database
? await this.database.getAssignedChannels(['id', 'assignee', 'flag', 'platform'])
: channels.map((id) => {
const [platform] = id.split(':')
const bot = this.bots.find(bot => bot.platform === platform)
return bot && { id, assignee: bot.selfId, flag: 0, platform }
}).filter(Boolean)

const assignMap: Dict<Dict<string[]>> = {}
for (const { id, assignee, flag, platform } of data) {
const data = await this.database.getAssignedChannels(['id', 'assignee', 'flag', 'platform', 'guildId'])
const assignMap: Dict<Dict<[string, string][]>> = {}
for (const { id, assignee, flag, platform, guildId } of data) {
if (channels && !channels.includes(`${platform}:${id}`)) continue
if (!forced && (flag & Channel.Flag.silent)) continue
const map = assignMap[platform] ||= {}
if (map[assignee]) {
map[assignee].push(id)
} else {
map[assignee] = [id]
}
((assignMap[platform] ||= {})[assignee] ||= []).push([id, guildId])
}

return (await Promise.all(Object.entries(assignMap).flatMap(([platform, map]) => {
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export interface Channel {
platform: string
flag: number
assignee: string
guildId: string
}

export namespace Channel {
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/orm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export class Model {
platform: 'string(63)',
flag: 'unsigned(20)',
assignee: 'string(63)',
guildId: 'string(63)',
}, {
primary: ['id', 'platform'],
})
Expand Down
3 changes: 2 additions & 1 deletion plugins/common/echo/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export function apply(ctx: Context) {
.option('escape', '-e 发送转义消息', { authority: 3 })
.option('user', '-u [user:user] 发送到用户', { authority: 3 })
.option('channel', '-c [channel:channel] 发送到频道', { authority: 3 })
.option('guild', '-g [guild:string] 指定群组编号', { authority: 3 })
.action(async ({ options }, message) => {
if (!message) return template('echo.expect-text')

Expand All @@ -37,7 +38,7 @@ export function apply(ctx: Context) {
} else if (options.user) {
await bot.sendPrivateMessage(id, message)
} else {
await bot.sendMessage(id, message, 'unknown')
await bot.sendMessage(id, message, options.guild)
}
return
}
Expand Down
51 changes: 29 additions & 22 deletions plugins/common/forward/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface Rule {
source: string
target: string
selfId: string
guildId?: string
}

export const Rule = Schema.object({
Expand All @@ -39,30 +40,36 @@ export const schema = Schema.union([
export function apply(ctx: Context, { rules, interval }: Config) {
const relayMap: Dict<Rule> = {}

async function sendRelay(session: Session, target: string, selfId?: string) {
async function sendRelay(session: Session, rule: Partial<Rule>) {
const { author, parsed } = session
if (!parsed.content) return

// get selfId
const [platform, channelId] = parsePlatform(target)
if (!selfId) {
const channel = await ctx.database.getChannel(platform, channelId, ['assignee'])
if (!channel || !channel.assignee) return
selfId = channel.assignee
}

const bot = ctx.bots.get(`${platform}:${selfId}`)
const content = template('forward', author.nickname || author.username, parsed.content)
await bot.sendMessage(channelId, content).then((ids) => {
for (const id of ids) {
relayMap[id] = { source: target, target: session.cid, selfId: session.selfId }
ctx.setTimeout(() => delete relayMap[id], interval)
try {
// get selfId
const [platform, channelId] = parsePlatform(rule.target)
if (!rule.selfId) {
const channel = await ctx.database.getChannel(platform, channelId, ['assignee', 'guildId'])
if (!channel || !channel.assignee) return
rule.selfId = channel.assignee
rule.guildId = channel.guildId
}
})
}

function handleError(error: any) {
ctx.logger('forward').warn(error)
const bot = ctx.bots.get(`${platform}:${rule.selfId}`)
const content = template('forward', author.nickname || author.username, parsed.content)
await bot.sendMessage(channelId, content, rule.guildId).then((ids) => {
for (const id of ids) {
relayMap[id] = {
source: rule.target,
target: session.cid,
selfId: session.selfId,
guildId: session.guildId,
}
ctx.setTimeout(() => delete relayMap[id], interval)
}
})
} catch (error) {
ctx.logger('forward').warn(error)
}
}

ctx.before('attach-channel', (session, fields) => {
Expand All @@ -73,17 +80,17 @@ export function apply(ctx: Context, { rules, interval }: Config) {
const { quote = {}, subtype } = session
if (subtype !== 'group') return
const data = relayMap[quote.messageId]
if (data) return sendRelay(session, data.target, data.selfId)
if (data) return sendRelay(session, data)

const tasks: Promise<void>[] = []
if (ctx.database) {
for (const target of session.channel.forward) {
tasks.push(sendRelay(session, target).catch(handleError))
tasks.push(sendRelay(session, { target }))
}
} else {
for (const rule of rules) {
if (session.cid !== rule.source) continue
tasks.push(sendRelay(session, rule.target, rule.selfId).catch(handleError))
tasks.push(sendRelay(session, rule))
}
}
const [result] = await Promise.all([next(), ...tasks])
Expand Down

0 comments on commit ea154ac

Please sign in to comment.