diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index 7655d3c49..e96dda305 100755 --- a/app/Http/Controllers/Api/DialogController.php +++ b/app/Http/Controllers/Api/DialogController.php @@ -147,18 +147,26 @@ class DialogController extends AbstractController } // 搜索消息会话 if (count($list) < 20) { - $msgs = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.last_at', 'u.mark_unread', 'u.silence', 'u.hide', 'u.color', 'u.updated_at as user_at', 'm.id as search_msg_id']) - ->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id') - ->join('web_socket_dialog_msgs as m', 'web_socket_dialogs.id', '=', 'm.dialog_id') - ->where('u.userid', $user->userid) - ->where('m.key', 'LIKE', "%{$key}%") - ->orderByDesc('m.id') + $msgs = WebSocketDialogMsg::select(['web_socket_dialog_msgs.*']) + ->join('web_socket_dialog_msg_reads as r', 'r.msg_id', '=', 'web_socket_dialog_msgs.id') + ->where('r.userid', $user->userid) + ->where('r.live', 1) + ->where('web_socket_dialog_msgs.key', 'LIKE', "%{$key}%") + ->orderByDesc('r.msg_id') ->take(20 - count($list)) ->get(); - $msgs->transform(function (WebSocketDialog $item) use ($user) { - return $item->formatData($user->userid); - }); - $list = array_merge($list, $msgs->toArray()); + foreach ($msgs as $msg) { + $item = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.last_at', 'u.mark_unread', 'u.silence', 'u.hide', 'u.color', 'u.updated_at as user_at']) + ->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id') + ->where('web_socket_dialogs.id', $msg->dialog_id) + ->first(); + if (empty($item)) { + continue; + } + $item->search_msg_id = $msg->id; + $item->last_msg = $msg; + $list[] = $item->formatData($user->userid); + } } // return Base::retSuccess('success', $list); diff --git a/app/Models/WebSocketDialog.php b/app/Models/WebSocketDialog.php index e0db6a56c..c0beb8543 100644 --- a/app/Models/WebSocketDialog.php +++ b/app/Models/WebSocketDialog.php @@ -200,7 +200,7 @@ class WebSocketDialog extends AbstractModel // if (isset($this->search_msg_id)) { // 最后消息 (搜索预览消息) - $this->last_msg = WebSocketDialogMsg::whereDialogId($this->id)->find($this->search_msg_id); + $this->last_msg = $this->last_msg ?? WebSocketDialogMsg::whereDialogId($this->id)->find($this->search_msg_id); $this->last_at = $this->last_msg ? Carbon::parse($this->last_msg->created_at)->toDateTimeString() : null; } else { // 未读信息 @@ -214,11 +214,11 @@ class WebSocketDialog extends AbstractModel // 是否免打扰 $this->silence = $this->silence ?? $dialogUserFun('silence'); // 对话人数 - $this->people = WebSocketDialogUser::whereDialogId($this->id)->count(); + $this->people = $this->people ?? WebSocketDialogUser::whereDialogId($this->id)->count(); // 有待办 - $this->todo_num = WebSocketDialogMsgTodo::whereDialogId($this->id)->whereUserid($userid)->whereDoneAt(null)->count(); + $this->todo_num = $this->todo_num ?? WebSocketDialogMsgTodo::whereDialogId($this->id)->whereUserid($userid)->whereDoneAt(null)->count(); // 最后消息 - $this->last_msg = WebSocketDialogMsg::whereDialogId($this->id)->orderByDesc('id')->first(); + $this->last_msg = $this->last_msg ?? WebSocketDialogMsg::whereDialogId($this->id)->orderByDesc('id')->first(); } // 对方信息 $this->pinyin = Base::cn2pinyin($this->name); diff --git a/app/Models/WebSocketDialogMsg.php b/app/Models/WebSocketDialogMsg.php index bb374ee28..6f1c0c4ef 100644 --- a/app/Models/WebSocketDialogMsg.php +++ b/app/Models/WebSocketDialogMsg.php @@ -200,6 +200,7 @@ class WebSocketDialogMsg extends AbstractModel 'msg_id' => $this->id, 'userid' => $userid, 'after' => 1, + 'live' => 1, ]); if ($msgRead->saveOrIgnore()) { $this->send = WebSocketDialogMsgRead::whereMsgId($this->id)->count(); @@ -638,16 +639,35 @@ class WebSocketDialogMsg extends AbstractModel } /** - * 生成关键词 - * @return string + * 生成关键词并保存 + * @return void */ - public function generateMsgKey() + public function generateKeyAndSave(): void { - return match ($this->type) { - 'text' => str_replace(" ", " ", strip_tags($this->msg['text'])), - 'meeting', 'file' => $this->msg['name'], - default => '', - }; + $key = ''; + switch ($this->type) { + case 'text': + case 'vote': + case 'word-chain': + $key = strip_tags($this->msg['text']); + break; + + case 'file': + $key = $this->msg['name']; + $key = preg_replace("/^(image|\d+)\.(png|jpg|jpeg|webp|gif)$/i", "", $key); + $key = preg_replace("/^LongText-(.*?)/i", "", $key); + break; + + case 'meeting': + $key = $this->msg['name']; + break; + } + $key = str_replace([""", "&", "<", ">"], "", $key); + $key = str_replace(["\r", "\n", "\t", " "], " ", $key); + $key = preg_replace("/^\/[A-Za-z]+/", " ", $key); + $key = preg_replace("/\s+/", " ", $key); + $this->key = trim($key); + $this->save(); } /** @@ -997,8 +1017,7 @@ class WebSocketDialogMsg extends AbstractModel 'modify' => $modify, ]; $dialogMsg->updateInstance($updateData); - $dialogMsg->key = $dialogMsg->generateMsgKey(); - $dialogMsg->save(); + $dialogMsg->generateKeyAndSave(); // WebSocketDialogUser::whereDialogId($dialog->id)->whereUserid($sender)->whereHide(1)->change([ 'hide' => 0, // 修改消息时,显示会话(仅自己) @@ -1045,8 +1064,7 @@ class WebSocketDialogMsg extends AbstractModel ]); AbstractModel::transaction(function () use ($dialogMsg) { $dialogMsg->send = 1; - $dialogMsg->key = $dialogMsg->generateMsgKey(); - $dialogMsg->save(); + $dialogMsg->generateKeyAndSave(); // if ($dialogMsg->type === 'meeting') { MeetingMsg::createInstance([ diff --git a/app/Models/WebSocketDialogMsgRead.php b/app/Models/WebSocketDialogMsgRead.php index 345d1ec15..878a015cf 100644 --- a/app/Models/WebSocketDialogMsgRead.php +++ b/app/Models/WebSocketDialogMsgRead.php @@ -16,6 +16,7 @@ use Carbon\Carbon; * @property int|null $email 是否发了邮件 * @property int|null $after 在阅读之后才添加的记录 * @property int|null $dot 红点标记 + * @property int|null $live 是否在会话里 * @property \Illuminate\Support\Carbon|null $read_at 阅读时间 * @property-read \App\Models\WebSocketDialogMsg|null $webSocketDialogMsg * @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend() @@ -32,6 +33,7 @@ use Carbon\Carbon; * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereDot($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereEmail($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereLive($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereMention($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereMsgId($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereReadAt($value) diff --git a/app/Observers/WebSocketDialogObserver.php b/app/Observers/WebSocketDialogObserver.php index 45a49c393..7d2e8a0f0 100644 --- a/app/Observers/WebSocketDialogObserver.php +++ b/app/Observers/WebSocketDialogObserver.php @@ -4,6 +4,7 @@ namespace App\Observers; use App\Models\Deleted; use App\Models\WebSocketDialog; +use App\Models\WebSocketDialogMsgRead; use App\Models\WebSocketDialogUser; class WebSocketDialogObserver @@ -39,6 +40,7 @@ class WebSocketDialogObserver public function deleted(WebSocketDialog $webSocketDialog) { Deleted::record('dialog', $webSocketDialog->id, $this->userids($webSocketDialog)); + WebSocketDialogMsgRead::whereDialogId($webSocketDialog->id)->update(['live' => 0]); } /** @@ -49,7 +51,9 @@ class WebSocketDialogObserver */ public function restored(WebSocketDialog $webSocketDialog) { - Deleted::forget('dialog', $webSocketDialog->id, $this->userids($webSocketDialog)); + $userids = $this->userids($webSocketDialog); + Deleted::forget('dialog', $webSocketDialog->id, $userids); + WebSocketDialogMsgRead::whereDialogId($webSocketDialog->id)->whereIn('userid', $userids)->update(['live' => 1]); } /** diff --git a/app/Observers/WebSocketDialogUserObserver.php b/app/Observers/WebSocketDialogUserObserver.php index c76391004..a58c65a42 100644 --- a/app/Observers/WebSocketDialogUserObserver.php +++ b/app/Observers/WebSocketDialogUserObserver.php @@ -3,6 +3,7 @@ namespace App\Observers; use App\Models\Deleted; +use App\Models\WebSocketDialogMsgRead; use App\Models\WebSocketDialogUser; use Carbon\Carbon; @@ -29,6 +30,7 @@ class WebSocketDialogUserObserver } } Deleted::forget('dialog', $webSocketDialogUser->dialog_id, $webSocketDialogUser->userid); + WebSocketDialogMsgRead::whereDialogId($webSocketDialogUser->dialog_id)->whereUserid($webSocketDialogUser->userid)->update(['live' => 1]); } /** @@ -51,6 +53,7 @@ class WebSocketDialogUserObserver public function deleted(WebSocketDialogUser $webSocketDialogUser) { Deleted::record('dialog', $webSocketDialogUser->dialog_id, $webSocketDialogUser->userid); + WebSocketDialogMsgRead::whereDialogId($webSocketDialogUser->dialog_id)->whereUserid($webSocketDialogUser->userid)->update(['live' => 0]); } /** diff --git a/app/Tasks/WebSocketDialogMsgTask.php b/app/Tasks/WebSocketDialogMsgTask.php index e1c45133b..962a8959e 100644 --- a/app/Tasks/WebSocketDialogMsgTask.php +++ b/app/Tasks/WebSocketDialogMsgTask.php @@ -128,6 +128,7 @@ class WebSocketDialogMsgTask extends AbstractTask 'mention' => $mention, 'silence' => $silence, 'dot' => $dot, + 'live' => 1, ])->saveOrIgnore(); $array[$userid] = [ 'userid' => $userid, diff --git a/database/migrations/2022_06_19_233120_add_web_socket_dialog_msgs_key.php b/database/migrations/2022_06_19_233120_add_web_socket_dialog_msgs_key.php index 89fad0638..9be930527 100644 --- a/database/migrations/2022_06_19_233120_add_web_socket_dialog_msgs_key.php +++ b/database/migrations/2022_06_19_233120_add_web_socket_dialog_msgs_key.php @@ -26,11 +26,7 @@ class AddWebSocketDialogMsgsKey extends Migration \App\Models\WebSocketDialogMsg::chunkById(100, function ($lists) { /** @var \App\Models\WebSocketDialogMsg $item */ foreach ($lists as $item) { - $key = $item->generateMsgKey(); - if ($key) { - $item->key = $key; - $item->save(); - } + $item->generateKeyAndSave(); } }); } diff --git a/database/migrations/2024_10_23_204404_add_web_socket_dialog_msg_reads_live.php b/database/migrations/2024_10_23_204404_add_web_socket_dialog_msg_reads_live.php new file mode 100644 index 000000000..2b43e6194 --- /dev/null +++ b/database/migrations/2024_10_23_204404_add_web_socket_dialog_msg_reads_live.php @@ -0,0 +1,130 @@ +integer('live')->nullable()->default(0)->index()->after('dot')->comment('是否在会话里'); + $table->index(['userid', 'live', 'msg_id']); + } + }); + info("update web_socket_dialog_msgs deleted_at"); + Schema::table('web_socket_dialog_msgs', function (Blueprint $table) { + $table->index('deleted_at'); + }); + if ($isAdd) { + // 关键词包含 + $contains = [ + '您可以通过发送以下命令来控制我', + '我的机器人。', + '机器人名称:', + '已加入的会话:', + '你可以通过执行以下命令来请求我:', + '假期类型:', + '评论了此审批', + '我是你的机器人助理', + '打卡时间: ', + '匿名消息使用说明', + '匿名消息将通过', + '导出任务统计已完成', + '我不是你的机器人', + '机器人名称由', + '您没有创建机器人', + '缺卡提醒:', + '打卡提醒:', + '文件下载打包已完成', + '您有一个新任务 #', + '您协助的任务 #', + '您负责的任务 #', + ]; + info("update web_socket_dialog_msgs key contains"); + foreach ($contains as $key) { + WebSocketDialogMsg::whereType('text')->where('key', 'like', "%{$key}%")->update(['key' => '']); + } + + // 关键词开始以 + $starts = [ + '/hello', + '/help', + '/list', + '/info', + '/newbot', + '/setname', + '/deletebot', + '/token', + '/revoke', + '/webhook', + '/clearday', + '/dialog', + '/api', + ]; + info("update web_socket_dialog_msgs key starts"); + foreach ($starts as $key) { + WebSocketDialogMsg::whereType('text')->where('key', 'like', "{$key}%")->update(['key' => '']); + } + + // 关键词等于 + $equals = [ + '我要打卡', + 'IT资讯', + '36氪', + '60s读世界', + '开心笑话', + '心灵鸡汤', + '使用说明', + '隐私说明', + '帮助指令', + 'API接口文档', + '我的机器人', + '清空上下文', + '操作频繁!', + '暂未开启签到功能。', + '暂未开放手动签到。', + '设置成功', + '机器人不存在。', + ]; + info("update web_socket_dialog_msgs key equals"); + foreach ($equals as $key) { + WebSocketDialogMsg::whereType('text')->whereKey($key)->update(['key' => '']); + } + + // 更新是否在会话里面 + info("update web_socket_dialog_msg_reads live value"); + WebSocketDialog::chunk(100, function ($dialogs) { + /** @var WebSocketDialog $dialog */ + foreach ($dialogs as $dialog) { + WebSocketDialogMsgRead::whereDialogId($dialog->id)->whereIn('userid', function ($query) use ($dialog) { + $query->select('userid')->from('web_socket_dialog_users')->whereDialogId($dialog->id); + })->update(['live' => 1]); + } + }); + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +}