diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index 99258413a..14287de11 100755 --- a/app/Http/Controllers/Api/DialogController.php +++ b/app/Http/Controllers/Api/DialogController.php @@ -658,7 +658,7 @@ class DialogController extends AbstractController $userid = intval(Request::input('userid')); $stream_url = trim(Request::input('stream_url')); // - if ($userid < 1 || !str_starts_with($stream_url, 'http')) { + if ($userid <= 0) { return Base::retError('参数错误'); } // diff --git a/app/Http/Controllers/Api/SystemController.php b/app/Http/Controllers/Api/SystemController.php index 4470c6a80..7327e10c7 100755 --- a/app/Http/Controllers/Api/SystemController.php +++ b/app/Http/Controllers/Api/SystemController.php @@ -2,6 +2,8 @@ namespace App\Http\Controllers\Api; +use App\Models\WebSocketDialog; +use App\Models\WebSocketDialogMsg; use Request; use Session; use Response; @@ -228,6 +230,72 @@ class SystemController extends AbstractController return Base::retSuccess('success', $setting ?: json_decode('{}')); } + /** + * @api {get} api/system/setting/aibot 03. 获取会议设置、保存AI机器人设置(限管理员) + * + * @apiVersion 1.0.0 + * @apiGroup system + * @apiName setting__aibot + * + * @apiParam {String} type + * - get: 获取(默认) + * - save: 保存设置(参数:['openai_key', 'openai_agency', 'claude_token', 'claude_agency']) + * @apiSuccess {Number} ret 返回状态码(1正确、0错误) + * @apiSuccess {String} msg 返回信息(错误描述) + * @apiSuccess {Object} data 返回数据 + */ + public function setting__aibot() + { + $user = User::auth('admin'); + // + $type = trim(Request::input('type')); + $setting = Base::setting('aibotSetting'); + if ($type == 'save') { + if (env("SYSTEM_SETTING") == 'disabled') { + return Base::retError('当前环境禁止修改'); + } + $all = Request::input(); + foreach ($all as $key => $value) { + if (!in_array($key, [ + 'openai_key', + 'openai_agency', + 'claude_token', + 'claude_agency', + ])) { + unset($all[$key]); + } + } + $backup = $setting; + $setting = Base::setting('aibotSetting', Base::newTrim($all)); + // + if ($backup['openai_key'] != $setting['openai_key']) { + $botUser = User::botGetOrCreate('ai-openai'); + if ($botUser && $dialog = WebSocketDialog::checkUserDialog($botUser, $user->userid)) { + WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => "设置成功"], $botUser->userid, true, false, true); + } + } + if ($backup['claude_token'] != $setting['claude_token']) { + $botUser = User::botGetOrCreate('ai-claude'); + if ($botUser && $dialog = WebSocketDialog::checkUserDialog($botUser, $user->userid)) { + WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => "设置成功"], $botUser->userid, true, false, true); + } + } + } + // + if (env("SYSTEM_SETTING") == 'disabled') { + foreach ([ + 'openai_key', + 'openai_agency', + 'claude_token', + 'claude_agency', + ] as $item) { + $setting[$item] = substr($setting[$item], 0, 4) . str_repeat('*', strlen($setting[$item]) - 8) . substr($setting[$item], -4); + } + } + // + return Base::retSuccess('success', $setting ?: json_decode('{}')); + } + /** * @api {get} api/system/setting/checkin 04. 获取签到设置、保存签到设置(限管理员) * diff --git a/app/Models/User.php b/app/Models/User.php index d254c1efb..886ac424c 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -533,6 +533,10 @@ class User extends AbstractModel return url("images/avatar/default_anon.png"); case 'approval-alert@bot.system': return url("images/avatar/default_approval.png"); + case 'ai-openai@bot.system': + return url("images/avatar/default_openai.png"); + case 'ai-claude@bot.system': + return url("images/avatar/default_claude.png"); case 'bot-manager@bot.system': return url("images/avatar/default_bot.png"); } @@ -619,6 +623,12 @@ class User extends AbstractModel case 'approval-alert': $update['nickname'] = '审批'; break; + case 'ai-openai': + $update['nickname'] = 'ChatGPT'; + break; + case 'ai-claude': + $update['nickname'] = 'Claude'; + break; case 'bot-manager': $update['nickname'] = '机器人管理'; break; diff --git a/app/Tasks/BotReceiveMsgTask.php b/app/Tasks/BotReceiveMsgTask.php index fb0fa81c6..92fb072c5 100644 --- a/app/Tasks/BotReceiveMsgTask.php +++ b/app/Tasks/BotReceiveMsgTask.php @@ -81,22 +81,7 @@ class BotReceiveMsgTask extends AbstractTask if ($command && !str_starts_with($command, '/') && ($dialog->type === 'user' || $this->mention)) { - $userBot = UserBot::whereBotId($botUser->userid)->first(); - if ($userBot && preg_match("/^https*:\/\//", $userBot->webhook_url)) { - Ihttp::ihttp_post($userBot->webhook_url, [ - 'text' => $command, - 'token' => User::generateToken($botUser), - 'dialog_id' => $dialog->id, - 'dialog_type' => $dialog->type, - 'msg_id' => $msg->id, - 'msg_uid' => $msg->userid, - 'mention' => $this->mention ? 1 : 0, - 'bot_uid' => $botUser->userid, - 'version' => Base::getVersion(), - ], 10); - $userBot->webhook_num++; - $userBot->save(); - } + $this->botManagerWebhook($command, $msg, $botUser, $dialog); } if ($dialog->type !== 'user') { return; @@ -366,6 +351,76 @@ class BotReceiveMsgTask extends AbstractTask } } + /** + * 机器人处理 Webhook + * @param string $command + * @param WebSocketDialogMsg $msg + * @param User $botUser + * @param WebSocketDialog $dialog + * @return void + */ + private function botManagerWebhook(string $command, WebSocketDialogMsg $msg, User $botUser, WebSocketDialog $dialog) + { + $serverUrl = 'http://' . env('APP_IPPR') . '.3'; + $userBot = null; + $extras = []; + switch ($botUser->email) { + // ChatGPT 机器人 + case 'ai-openai@bot.system': + $setting = Base::setting('aibotSetting'); + $webhookUrl = "{$serverUrl}/ai/openai/send"; + $extras = [ + 'openai_key' => $setting['openai_key'], + 'openai_agency' => $setting['openai_agency'], + 'server_url' => $serverUrl, + ]; + if (empty($extras['openai_key'])) { + WebSocketDialogMsg::sendMsg(null, $msg->dialog_id, 'text', ['text' => 'Robot disabled'], $botUser->userid, false, false, true); // todo 未能在任务end事件来发送任务 + return; + } + break; + // Claude 机器人 + case 'ai-claude@bot.system': + $setting = Base::setting('aibotSetting'); + $webhookUrl = "{$serverUrl}/ai/claude/send"; + $extras = [ + 'claude_token' => $setting['claude_token'], + 'claude_agency' => $setting['claude_agency'], + 'server_url' => $serverUrl, + ]; + if (empty($extras['claude_token'])) { + WebSocketDialogMsg::sendMsg(null, $msg->dialog_id, 'text', ['text' => 'Robot disabled'], $botUser->userid, false, false, true); // todo 未能在任务end事件来发送任务 + return; + } + break; + // 其他机器人 + default: + $userBot = UserBot::whereBotId($botUser->userid)->first(); + $webhookUrl = $userBot?->webhook_url; + break; + } + if (!preg_match("/^https*:\/\//", $webhookUrl)) { + return; + } + // + Ihttp::ihttp_post($webhookUrl, [ + 'text' => $command, + 'token' => User::generateToken($botUser), + 'dialog_id' => $dialog->id, + 'dialog_type' => $dialog->type, + 'msg_id' => $msg->id, + 'msg_uid' => $msg->userid, + 'mention' => $this->mention ? 1 : 0, + 'bot_uid' => $botUser->userid, + 'version' => Base::getVersion(), + 'extras' => Base::array2json($extras) + ], 10); + if ($userBot) { + $userBot->webhook_num++; + $userBot->save(); + } + } + /** * @param $botId * @param $userid diff --git a/database/migrations/2023_07_27_145646_create_default_robot.php b/database/migrations/2023_07_27_145646_create_default_robot.php new file mode 100644 index 000000000..c8936c84a --- /dev/null +++ b/database/migrations/2023_07_27_145646_create_default_robot.php @@ -0,0 +1,30 @@ + +