Files
claude-relay-service/src/utils/webhookNotifier.js
shaw 08946c67ea feat: 新增 OpenAI-Responses 账户管理功能和独立自动停止标记机制
## 功能新增
- 实现 OpenAI-Responses 账户服务(openaiResponsesAccountService.js)
  - 支持使用账户内置 API Key 进行请求转发
  - 实现每日额度管理和重置机制
  - 支持代理配置和优先级设置
- 实现 OpenAI-Responses 中继服务(openaiResponsesRelayService.js)
  - 处理请求转发和响应流处理
  - 自动记录使用统计信息
  - 支持流式和非流式响应
- 新增管理界面的 OpenAI-Responses 账户管理功能
  - 完整的 CRUD 操作支持
  - 实时额度监控和状态管理
  - 支持手动重置限流和每日额度

## 架构改进
- 引入独立的自动停止标记机制,区分不同原因的自动停止
  - rateLimitAutoStopped: 限流自动停止
  - fiveHourAutoStopped: 5小时限制自动停止
  - tempErrorAutoStopped: 临时错误自动停止
  - quotaAutoStopped: 额度耗尽自动停止
- 修复手动修改调度状态时自动恢复的问题
- 统一清理逻辑,防止状态冲突

## 其他优化
- getAccountUsageStats 支持不同账户类型参数
- 统一调度器支持 OpenAI-Responses 账户类型
- WebHook 通知增强,支持新账户类型的事件

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-10 15:41:52 +08:00

116 lines
3.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const logger = require('./logger')
const webhookService = require('../services/webhookService')
const { getISOStringWithTimezone } = require('./dateHelper')
class WebhookNotifier {
constructor() {
// 保留此类用于兼容性实际功能委托给webhookService
}
/**
* 发送账号异常通知
* @param {Object} notification - 通知内容
* @param {string} notification.accountId - 账号ID
* @param {string} notification.accountName - 账号名称
* @param {string} notification.platform - 平台类型 (claude-oauth, claude-console, gemini)
* @param {string} notification.status - 异常状态 (unauthorized, blocked, error)
* @param {string} notification.errorCode - 异常代码
* @param {string} notification.reason - 异常原因
* @param {string} notification.timestamp - 时间戳
*/
async sendAccountAnomalyNotification(notification) {
try {
// 使用新的webhookService发送通知
await webhookService.sendNotification('accountAnomaly', {
accountId: notification.accountId,
accountName: notification.accountName,
platform: notification.platform,
status: notification.status,
errorCode:
notification.errorCode || this._getErrorCode(notification.platform, notification.status),
reason: notification.reason,
timestamp: notification.timestamp || getISOStringWithTimezone(new Date())
})
} catch (error) {
logger.error('Failed to send account anomaly notification:', error)
}
}
/**
* 测试Webhook连通性兼容旧接口
* @param {string} url - Webhook URL
* @param {string} type - 平台类型(可选)
*/
async testWebhook(url, type = 'custom') {
try {
// 创建临时平台配置
const platform = {
type,
url,
enabled: true,
timeout: 10000
}
const result = await webhookService.testWebhook(platform)
return result
} catch (error) {
return { success: false, error: error.message }
}
}
/**
* 发送账号事件通知
* @param {string} eventType - 事件类型 (account.created, account.updated, account.deleted, account.status_changed)
* @param {Object} data - 事件数据
*/
async sendAccountEvent(eventType, data) {
try {
// 使用webhookService发送通知
await webhookService.sendNotification('accountEvent', {
eventType,
...data,
timestamp: data.timestamp || getISOStringWithTimezone(new Date())
})
} catch (error) {
logger.error(`Failed to send account event (${eventType}):`, error)
}
}
/**
* 获取错误代码映射
* @param {string} platform - 平台类型
* @param {string} status - 状态
* @param {string} _reason - 原因 (未使用)
*/
_getErrorCode(platform, status, _reason) {
const errorCodes = {
'claude-oauth': {
unauthorized: 'CLAUDE_OAUTH_UNAUTHORIZED',
blocked: 'CLAUDE_OAUTH_BLOCKED',
error: 'CLAUDE_OAUTH_ERROR',
disabled: 'CLAUDE_OAUTH_MANUALLY_DISABLED'
},
'claude-console': {
blocked: 'CLAUDE_CONSOLE_BLOCKED',
error: 'CLAUDE_CONSOLE_ERROR',
disabled: 'CLAUDE_CONSOLE_MANUALLY_DISABLED'
},
gemini: {
error: 'GEMINI_ERROR',
unauthorized: 'GEMINI_UNAUTHORIZED',
disabled: 'GEMINI_MANUALLY_DISABLED'
},
openai: {
error: 'OPENAI_ERROR',
unauthorized: 'OPENAI_UNAUTHORIZED',
blocked: 'OPENAI_RATE_LIMITED',
disabled: 'OPENAI_MANUALLY_DISABLED'
}
}
return errorCodes[platform]?.[status] || 'UNKNOWN_ERROR'
}
}
module.exports = new WebhookNotifier()