Skip to content

Commit

Permalink
fix(core): support bot reconnect
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Feb 3, 2022
1 parent 14052f8 commit e9da7b4
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 11 deletions.
4 changes: 2 additions & 2 deletions docs/api/core/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ ctx.router.get('/path', (ctx, next) => {

使用 sid 获取机器人实例。

#### ctx.bots.remove(sid)
#### ctx.bots.remove(id)

- **sid:** `string` 机器人的 sid
- **sid:** `string` 机器人的 id
- 返回值: `boolean` 机器人实例是否存在

移除一个机器人实例。
Expand Down
14 changes: 9 additions & 5 deletions packages/core/src/adapter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Logger, paramCase, Dict, Awaitable } from '@koishijs/utils'
import { Logger, paramCase, Dict, Awaitable, remove } from '@koishijs/utils'
import { Session } from './session'
import { App } from './app'
import { Bot } from './bot'
Expand Down Expand Up @@ -51,7 +51,7 @@ export namespace Adapter {
export type BotConfig<R> = R & { bots?: R[] }
export type PluginConfig<S = any, R = any> = S & BotConfig<R>

function join(platform: string, protocol: string) {
export function join(platform: string, protocol: string) {
return protocol ? `${platform}.${protocol}` : platform
}

Expand All @@ -73,6 +73,7 @@ export namespace Adapter {
export function define(platform: string, constructor: Bot.Constructor, ...args: CreatePluginRestParams) {
const name = platform + '-adapter'
platform = platform.toLowerCase()
Bot.library[platform] = constructor

let BotConfig: Schema
if (typeof args[0] === 'function') {
Expand Down Expand Up @@ -144,7 +145,8 @@ export namespace Adapter {
return this.find(bot => bot.sid === sid)
}

create<T extends Bot>(platform: string, options: any, constructor: new (adapter: Adapter, config: any) => T): T {
create<T extends Bot>(platform: string, options: any, constructor?: new (adapter: Adapter, config: any) => T): T {
constructor ||= Bot.library[platform] as any
const adapter = this.resolve(platform, options)
const bot = new constructor(adapter, options)
adapter.bots.push(bot)
Expand All @@ -153,10 +155,12 @@ export namespace Adapter {
return bot
}

async remove(sid: string) {
const index = this.findIndex(bot => bot.sid === sid)
async remove(id: string) {
const index = this.findIndex(bot => bot.id === id)
if (index < 0) return
const [bot] = this.splice(index, 1)
remove(bot.adapter.bots, bot)
bot.config.disabled = true
this.app.emit('bot-removed', bot)
return bot.stop()
}
Expand Down
9 changes: 7 additions & 2 deletions packages/core/src/bot.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Logger, Random, sleep } from '@koishijs/utils'
import { Dict, Logger, Random, sleep } from '@koishijs/utils'
import { Adapter } from './adapter'
import { App } from './app'
import { Session } from './session'
Expand Down Expand Up @@ -63,8 +63,10 @@ export abstract class Bot<T extends Bot.BaseConfig = Bot.BaseConfig> {
}

async start() {
if (this.config.disabled) return
if (['connect', 'reconnect', 'online'].includes(this.status)) return
this.status = 'connect'
try {
this.status = 'connect'
await this.app.parallel('bot-connect', this)
await this.adapter.connect(this)
} catch (error) {
Expand All @@ -73,6 +75,7 @@ export abstract class Bot<T extends Bot.BaseConfig = Bot.BaseConfig> {
}

async stop() {
if (['disconnect', 'offline'].includes(this.status)) return
this.status = 'disconnect'
try {
await this.app.parallel('bot-disconnect', this)
Expand Down Expand Up @@ -124,6 +127,8 @@ export abstract class Bot<T extends Bot.BaseConfig = Bot.BaseConfig> {
}

export namespace Bot {
export const library: Dict<Bot.Constructor> = {}

export interface BaseConfig {
disabled?: boolean
protocol?: string
Expand Down
8 changes: 6 additions & 2 deletions packages/koishi/src/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export namespace InjectedAdapter {
socket.on('close', (code, reason) => {
bot.socket = null
logger.debug(`websocket closed with ${code}`)
if (!this.isListening) return bot.status = 'offline'
if (!this.isListening || bot.config.disabled) return bot.status = 'offline'

// remove query args to protect privacy
const message = reason.toString() || `failed to connect to ${url}`
Expand All @@ -72,7 +72,7 @@ export namespace InjectedAdapter {
bot.status = 'reconnect'
logger.warn(`${message}, will retry in ${Time.formatTimeShort(timeout)}...`)
setTimeout(() => {
if (this.isListening) reconnect()
if (this.isListening && !bot.config.disabled) reconnect()
}, timeout)
})

Expand All @@ -87,6 +87,10 @@ export namespace InjectedAdapter {
reconnect(true)
}

disconnect(bot: Bot) {
bot.socket?.close()
}

start() {
this.isListening = true
}
Expand Down

0 comments on commit e9da7b4

Please sign in to comment.