Skip to content

🔧 中间件系统

深入了解 Zhin.js 的中间件系统和消息处理管道。

🎯 中间件概述

中间件是 Zhin.js 消息处理管道的核心组件,允许你在消息处理过程中插入自定义逻辑。

🔧 基础中间件

添加中间件

使用 addMiddleware 添加中间件。

typescript
import { addMiddleware } from 'zhin.js'

addMiddleware(async (message, next) => {
  console.log('处理消息前:', message.raw)
  await next()
  console.log('处理消息后')
})

中间件执行顺序

中间件按照添加顺序执行,形成洋葱模型。

typescript
addMiddleware(async (message, next) => {
  console.log('中间件1: 开始')
  await next()
  console.log('中间件1: 结束')
})

addMiddleware(async (message, next) => {
  console.log('中间件2: 开始')
  await next()
  console.log('中间件2: 结束')
})

// 执行顺序:
// 中间件1: 开始
// 中间件2: 开始
// 消息处理
// 中间件2: 结束
// 中间件1: 结束

🛡️ 权限控制中间件

用户权限检查

检查用户是否有权限执行操作。

typescript
import { addMiddleware } from 'zhin.js'

const adminUsers = new Set(['admin1', 'admin2'])

addMiddleware(async (message, next) => {
  // 检查是否为管理员
  if (!adminUsers.has(message.sender.id)) {
    await message.reply('权限不足')
    return // 不继续处理
  }
  
  await next()
})

群组权限控制

根据群组设置不同的权限。

typescript
const groupPermissions = new Map([
  ['group1', ['user1', 'user2']],
  ['group2', ['user3', 'user4']]
])

addMiddleware(async (message, next) => {
  if (message.channel.type === 'group') {
    const allowedUsers = groupPermissions.get(message.channel.id)
    if (allowedUsers && !allowedUsers.includes(message.sender.id)) {
      await message.reply('你在此群组中无权限')
      return
    }
  }
  
  await next()
})

🔍 内容过滤中间件

敏感词过滤

过滤敏感内容。

typescript
const sensitiveWords = ['敏感词1', '敏感词2']

addMiddleware(async (message, next) => {
  const content = message.raw.toLowerCase()
  
  for (const word of sensitiveWords) {
    if (content.includes(word)) {
      await message.reply('消息包含敏感内容,已删除')
      return // 不继续处理
    }
  }
  
  await next()
})

垃圾信息检测

检测和过滤垃圾信息。

typescript
addMiddleware(async (message, next) => {
  // 检测重复消息
  if (isSpamMessage(message)) {
    await message.reply('检测到垃圾信息')
    return
  }
  
  // 检测链接
  if (containsSuspiciousLinks(message.raw)) {
    await message.reply('消息包含可疑链接')
    return
  }
  
  await next()
})

function isSpamMessage(message: Message): boolean {
  // 实现垃圾信息检测逻辑
  return false
}

function containsSuspiciousLinks(content: string): boolean {
  // 实现链接检测逻辑
  return false
}

📊 日志记录中间件

消息日志

记录所有消息。

typescript
import { useLogger } from 'zhin.js'

const logger = useLogger()

addMiddleware(async (message, next) => {
  logger.info(`收到消息: ${message.raw} (用户: ${message.sender.name})`)
  
  const start = Date.now()
  await next()
  const duration = Date.now() - start
  
  logger.info(`消息处理完成,耗时: ${duration}ms`)
})

性能监控

监控消息处理性能。

typescript
addMiddleware(async (message, next) => {
  const start = Date.now()
  
  try {
    await next()
  } finally {
    const duration = Date.now() - start
    
    // 记录慢处理
    if (duration > 1000) {
      logger.warn(`慢消息处理: ${message.raw} (${duration}ms)`)
    }
    
    // 记录性能统计
    recordPerformanceStats(duration, message)
  }
})

🔄 重试机制中间件

自动重试

为失败的操作添加重试机制。

typescript
addMiddleware(async (message, next) => {
  const maxRetries = 3
  let retries = 0
  
  while (retries < maxRetries) {
    try {
      await next()
      return // 成功,退出重试循环
    } catch (error) {
      retries++
      
      if (retries >= maxRetries) {
        logger.error(`消息处理失败,已重试 ${maxRetries} 次:`, error)
        await message.reply('处理失败,请稍后重试')
        return
      }
      
      logger.warn(`消息处理失败,第 ${retries} 次重试:`, error)
      await new Promise(resolve => setTimeout(resolve, 1000 * retries)) // 指数退避
    }
  }
})

🎨 消息转换中间件

消息格式化

统一格式化消息。

typescript
addMiddleware(async (message, next) => {
  // 标准化消息内容
  message.raw = message.raw.trim()
  
  // 转换表情符号
  message.raw = convertEmojis(message.raw)
  
  await next()
})

function convertEmojis(text: string): string {
  return text
    .replace(/:\)/g, '😊')
    .replace(/:\(/g, '😢')
    .replace(/:D/g, '😄')
}

多语言支持

根据用户语言设置转换消息。

typescript
const userLanguages = new Map<string, string>()

addMiddleware(async (message, next) => {
  const userLang = userLanguages.get(message.sender.id) || 'zh-CN'
  
  // 根据用户语言转换消息
  message.raw = translateMessage(message.raw, userLang)
  
  await next()
})

🔧 高级中间件

条件中间件

根据条件执行不同的中间件。

typescript
function createConditionalMiddleware(condition: (message: Message) => boolean, middleware: Middleware) {
  return async (message: Message, next: () => Promise<void>) => {
    if (condition(message)) {
      await middleware(message, next)
    } else {
      await next()
    }
  }
}

// 只对群消息应用特定中间件
addMiddleware(createConditionalMiddleware(
  (message) => message.channel.type === 'group',
  async (message, next) => {
    console.log('群消息特殊处理')
    await next()
  }
))

中间件组合

组合多个中间件。

typescript
function composeMiddlewares(...middlewares: Middleware[]): Middleware {
  return middlewares.reduceRight((next, middleware) => {
    return async (message, nextFn) => {
      await middleware(message, () => next(message, nextFn))
    }
  })
}

const combinedMiddleware = composeMiddlewares(
  authMiddleware,
  logMiddleware,
  filterMiddleware
)

addMiddleware(combinedMiddleware)

异步中间件

处理异步操作的中间件。

typescript
addMiddleware(async (message, next) => {
  // 异步验证用户
  const isValidUser = await validateUser(message.sender.id)
  
  if (!isValidUser) {
    await message.reply('用户验证失败')
    return
  }
  
  // 异步记录用户活动
  await recordUserActivity(message.sender.id, message.raw)
  
  await next()
})

🧪 测试中间件

单元测试

测试中间件的功能。

typescript
// tests/middleware.test.ts
import { describe, it, expect, vi } from 'vitest'

describe('Auth Middleware', () => {
  it('should allow admin users', async () => {
    const message = createMockMessage({ sender: { id: 'admin1' } })
    const next = vi.fn()
    
    await authMiddleware(message, next)
    
    expect(next).toHaveBeenCalled()
  })
  
  it('should reject non-admin users', async () => {
    const message = createMockMessage({ sender: { id: 'user1' } })
    const next = vi.fn()
    
    await authMiddleware(message, next)
    
    expect(next).not.toHaveBeenCalled()
    expect(message.reply).toHaveBeenCalledWith('权限不足')
  })
})

集成测试

测试中间件与插件的集成。

typescript
describe('Middleware Integration', () => {
  it('should process message through middleware chain', async () => {
    const app = await createApp({
      plugins: ['my-plugin']
    })
    
    await app.start()
    
    // 发送测试消息
    await app.sendMessage({
      context: 'process',
      bot: 'test-bot',
      id: 'test',
      type: 'private',
      content: 'test message'
    })
    
    // 验证中间件是否正确执行
    expect(logMiddleware).toHaveBeenCalled()
    expect(authMiddleware).toHaveBeenCalled()
  })
})

🔗 相关链接