Skip to content

🤖 Bot 接口实现

深入了解 Zhin.js Bot 接口的实现细节。

🎯 Bot 接口概述

Bot 接口是适配器的核心组件,负责与特定聊天平台的通信。

🔧 基础接口

Bot 基类

typescript
interface Bot<T extends BotConfig = BotConfig> {
  connected: boolean
  config: T
  
  connect(): Promise<void>
  disconnect(): Promise<void>
  sendMessage(options: SendOptions): Promise<void>
}

实现示例

typescript
class MyBot implements Bot<MyBotConfig> {
  public connected = false
  private client: any
  
  constructor(
    private plugin: Plugin,
    public config: MyBotConfig
  ) {}
  
  async connect() {
    // 实现连接逻辑
  }
  
  async disconnect() {
    // 实现断开逻辑
  }
  
  async sendMessage(options: SendOptions) {
    // 实现发送逻辑
  }
}

🔗 连接管理

连接状态

管理 Bot 的连接状态。

typescript
class MyBot implements Bot {
  private _connected = false
  
  get connected(): boolean {
    return this._connected
  }
  
  private setConnected(value: boolean) {
    this._connected = value
    this.plugin.emit('bot.connection.changed', { connected: value })
  }
  
  async connect() {
    try {
      await this.establishConnection()
      this.setConnected(true)
      this.plugin.logger.info('Bot 连接成功')
    } catch (error) {
      this.plugin.logger.error('Bot 连接失败:', error)
      throw error
    }
  }
  
  async disconnect() {
    try {
      await this.closeConnection()
      this.setConnected(false)
      this.plugin.logger.info('Bot 已断开连接')
    } catch (error) {
      this.plugin.logger.error('Bot 断开连接失败:', error)
    }
  }
}

重连机制

实现自动重连功能。

typescript
class MyBot implements Bot {
  private reconnectAttempts = 0
  private maxReconnectAttempts = 5
  private reconnectDelay = 5000
  private reconnectTimer?: NodeJS.Timeout
  
  async connect() {
    try {
      await this.establishConnection()
      this.setConnected(true)
      this.reconnectAttempts = 0
    } catch (error) {
      this.handleConnectionError(error)
    }
  }
  
  private handleConnectionError(error: any) {
    this.plugin.logger.error('连接错误:', error)
    
    if (this.shouldReconnect(error)) {
      this.scheduleReconnect()
    }
  }
  
  private scheduleReconnect() {
    if (this.reconnectAttempts >= this.maxReconnectAttempts) {
      this.plugin.logger.error('重连次数超限,停止重连')
      return
    }
    
    this.reconnectAttempts++
    const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1)
    
    this.plugin.logger.info(`将在 ${delay}ms 后尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})`)
    
    this.reconnectTimer = setTimeout(() => {
      this.connect()
    }, delay)
  }
  
  private shouldReconnect(error: any): boolean {
    // 判断是否应该重连
    return error.code === 'ECONNRESET' || 
           error.code === 'ENOTFOUND' ||
           error.message.includes('timeout')
  }
}

💬 消息处理

发送消息

实现消息发送功能。

typescript
class MyBot implements Bot {
  async sendMessage(options: SendOptions) {
    if (!this.connected) {
      throw new Error('Bot 未连接')
    }
    
    try {
      const platformMessage = this.convertToPlatformFormat(options)
      await this.client.sendMessage(platformMessage)
      
      this.plugin.logger.debug('消息发送成功:', options)
    } catch (error) {
      this.plugin.logger.error('消息发送失败:', error)
      throw error
    }
  }
  
  private convertToPlatformFormat(options: SendOptions): any {
    return {
      channel: options.id,
      content: options.content,
      type: options.type
    }
  }
}

接收消息

处理接收到的消息。

typescript
class MyBot implements Bot {
  private setupMessageHandlers() {
    this.client.on('message', this.handleMessage.bind(this))
  }
  
  private handleMessage(platformMessage: any) {
    try {
      const message = this.convertFromPlatformFormat(platformMessage)
      this.plugin.emit('message.receive', message)
    } catch (error) {
      this.plugin.logger.error('消息处理失败:', error)
    }
  }
  
  private convertFromPlatformFormat(platformMessage: any): Message {
    return {
      id: platformMessage.id,
      adapter: this.config.context,
      bot: this.config.name,
      content: this.parseContent(platformMessage.content),
      sender: {
        id: platformMessage.author.id,
        name: platformMessage.author.name
      },
      channel: {
        id: platformMessage.channel.id,
        type: this.mapChannelType(platformMessage.channel.type)
      },
      timestamp: platformMessage.timestamp || Date.now(),
      raw: platformMessage.content,
      reply: async (content: string) => {
        await this.sendMessage({
          context: this.config.context,
          bot: this.config.name,
          id: platformMessage.channel.id,
          type: platformMessage.channel.type,
          content
        })
      }
    }
  }
}

🔧 事件处理

事件监听

设置事件监听器。

typescript
class MyBot implements Bot {
  private setupEventHandlers() {
    this.client.on('message', this.handleMessage.bind(this))
    this.client.on('error', this.handleError.bind(this))
    this.client.on('disconnect', this.handleDisconnect.bind(this))
    this.client.on('reconnect', this.handleReconnect.bind(this))
  }
  
  private handleError(error: any) {
    this.plugin.logger.error('Bot 错误:', error)
    this.plugin.emit('bot.error', error)
  }
  
  private handleDisconnect() {
    this.setConnected(false)
    this.plugin.emit('bot.disconnect')
  }
  
  private handleReconnect() {
    this.setConnected(true)
    this.plugin.emit('bot.reconnect')
  }
}

自定义事件

触发自定义事件。

typescript
class MyBot implements Bot {
  private triggerCustomEvents(platformMessage: any) {
    // 根据消息类型触发不同事件
    if (platformMessage.type === 'group') {
      this.plugin.emit('message.group.receive', message)
    } else {
      this.plugin.emit('message.private.receive', message)
    }
    
    // 根据内容触发事件
    if (platformMessage.content.includes('@')) {
      this.plugin.emit('message.mention', message)
    }
  }
}

📊 性能监控

统计信息

收集 Bot 的统计信息。

typescript
class MyBot implements Bot {
  private stats = {
    messagesReceived: 0,
    messagesSent: 0,
    errors: 0,
    connectionUptime: Date.now(),
    lastActivity: Date.now()
  }
  
  async sendMessage(options: SendOptions) {
    const start = Date.now()
    
    try {
      await this.client.sendMessage(options)
      this.stats.messagesSent++
      this.stats.lastActivity = Date.now()
      
      const duration = Date.now() - start
      this.plugin.logger.debug(`消息发送成功 (${duration}ms)`)
      
    } catch (error) {
      this.stats.errors++
      throw error
    }
  }
  
  private handleMessage(platformMessage: any) {
    this.stats.messagesReceived++
    this.stats.lastActivity = Date.now()
    
    // 处理消息...
  }
  
  getStats() {
    return {
      ...this.stats,
      uptime: Date.now() - this.stats.connectionUptime,
      lastActivityAgo: Date.now() - this.stats.lastActivity
    }
  }
}

健康检查

实现健康检查功能。

typescript
class MyBot implements Bot {
  private healthCheckInterval?: NodeJS.Timeout
  
  private startHealthCheck() {
    this.healthCheckInterval = setInterval(() => {
      this.performHealthCheck()
    }, 30000) // 30秒检查一次
  }
  
  private performHealthCheck() {
    if (!this.connected) {
      this.plugin.logger.warn('Bot 未连接,尝试重连')
      this.connect()
      return
    }
    
    const lastActivity = Date.now() - this.stats.lastActivity
    if (lastActivity > 300000) { // 5分钟无活动
      this.plugin.logger.warn('Bot 长时间无活动,检查连接')
      this.checkConnection()
    }
  }
  
  private async checkConnection() {
    try {
      await this.client.ping()
    } catch (error) {
      this.plugin.logger.warn('连接检查失败,尝试重连')
      this.connect()
    }
  }
}

🔗 相关链接