#include "netclient.h" #include "../model/datacenter.h" using namespace model; namespace network { NetClient::NetClient(model::DataCenter* dataCenter) :dataCenter(dataCenter) { //不应该在此处初始化websocket //initWebSocket(); } void NetClient::ping() { QNetworkRequest httpReq; httpReq.setUrl(QUrl(HTTP_URL + "/ping")); QNetworkReply* httpResp = httpClient.get(httpReq); connect(httpResp, &QNetworkReply::finished, this, [=]() { //到这里面,说明响应已经回了 if (httpResp->error() != QNetworkReply::NoError) { //请求失败 LOG() << "HTTP请求失败!!!" << httpResp->errorString(); httpResp->deleteLater(); return; } //获取到响应的body QByteArray body = httpResp->readAll(); LOG() << "响应的内容: " << body; httpResp->deleteLater(); }); } void NetClient::initWebSocket() { //准备好所需要的信号槽 connect(&websocketClient, &QWebSocket::connected, this, [=]() { LOG() << "webSocket 连接成功"; //连接成功之后,进行发送身份认证 sendAuth(); }); connect(&websocketClient, &QWebSocket::disconnected, this, [=]() { LOG() << "webSocket 连接断开"; }); connect(&websocketClient, &QWebSocket::textMessageReceived, this, [=](const QString& message) { LOG() << "webSocket 收到文本消息 " << message; }); connect(&websocketClient, &QWebSocket::binaryMessageReceived, this, [=](const QByteArray& byteArray) { LOG() << "webSocket 收到二进制的消息" << byteArray.length(); bite_im::NotifyMessage notifyMessage; notifyMessage.deserialize(&serializer, byteArray); handleWsResponse(notifyMessage); }); //和服务器真正建立连接 websocketClient.open(WEBSOCKET_URL); } void NetClient::handleWsResponse(const bite_im::NotifyMessage& notifyMessage) { if (notifyMessage.notifyType() == bite_im::NotifyTypeGadget::NotifyType::CHAT_MESSAGE_NOTIFY) { //收到消息 //把pb中的MessageInfo转成客户端自己的message Message message; message.load(notifyMessage.newMessageInfo().messageInfo()); //针对自己的message做进一步的处理 handleWsMessage(message); } else if (notifyMessage.notifyType() == bite_im::NotifyTypeGadget::NotifyType::CHAT_SESSION_CREATE_NOTIFY) { //创建新的会话通知 ChatSessionInfo chatSessionInfo; chatSessionInfo.load(notifyMessage.newChatSessionInfo().chatSessionInfo()); handleWsSessionCreate(chatSessionInfo); } else if (notifyMessage.notifyType() == bite_im::NotifyTypeGadget::NotifyType::FRIEND_ADD_APPLY_NOTIFY) { //添加好友申请通知 UserInfo userInfo; userInfo.load(notifyMessage.friendAddApply().userInfo()); handleWsAddfriendApply(userInfo); } else if (notifyMessage.notifyType() == bite_im::NotifyTypeGadget::NotifyType::FRIEND_ADD_PROCESS_NOTIFY) { //添加好友申请的处理结果通知 UserInfo userInfo; userInfo.load(notifyMessage.friendProcessResult().userInfo()); bool agree = notifyMessage.friendProcessResult().agree(); handleWsAddFriendProcess(userInfo, agree); } else if (notifyMessage.notifyType() == bite_im::NotifyTypeGadget::NotifyType::FRIEND_REMOVE_NOTIFY) { const QString& userId = notifyMessage.friendRemove().userId(); handleWsRemoveFriend(userId); } } void NetClient::handleWsMessage(const model::Message& message) { // 这里要考虑两种情况 QList* messageList = dataCenter->getRecentMessageList(message.chatSessionId); if (messageList == nullptr) { //如果当前这个消息所属的会话,里面的消息列表没有在本地加载,此时需要通过网络先加载整个消息列表 connect(dataCenter, &DataCenter::getRecentMessageListDoneNoUI, this, &NetClient::receiveMessage, Qt::UniqueConnection); dataCenter->getRecnetMessageListAsync(message.chatSessionId, false); } else { //若已经在本地加载了,直接把这个消息尾插到消息列表中即可 messageList->push_back(message); this->receiveMessage(message.chatSessionId); } } void NetClient::handleWsRemoveFriend(const QString& userId) { //删除数据 DataCenter 好友列表的数据 dataCenter->removeFriend(userId); //通知界面变化,更新好友列表/会话列表 emit dataCenter->deleteFriendDone(); } void NetClient::handleWsAddfriendApply(const model::UserInfo& userInfo) { //DataCenter中有一个好友申请列表,需要把这个数据添加到好友申请的列表中 QList* applyList = dataCenter->getApplyList(); if (applyList == nullptr) { LOG() << "客户端没有加载到好友申请的列表"; return; } //把新的元素放到列表前面 applyList->push_front(userInfo); //通知界面进行更新 emit dataCenter->receiveFriendApplyDone(); } void NetClient::handleWsAddFriendProcess(const model::UserInfo& userInfo, bool agree) { if (agree) { //对方同意了你的好友申请 QList* friendList = dataCenter->getFriendList(); if (friendList == nullptr) { LOG() << "客户端没有加载好友列表"; return; } friendList->push_front(userInfo); //通知更新一下界面 emit dataCenter->receiveFriendProcessDone(userInfo.nickname, agree); } else { //对方未同意你的好友申请 emit dataCenter->receiveFriendProcessDone(userInfo.nickname, agree); } } void NetClient::handleWsSessionCreate(const model::ChatSessionInfo& chatSessionInfo) { //把这个ChatSessionInfo添加到会话列表中即可 QList* chatSessionList = dataCenter->getChatSessionList(); if (chatSessionList == nullptr) { LOG() << "客户端没有加载会话列表"; return; } //新的元素添加到列表头部 chatSessionList->push_front(chatSessionInfo); //发送一个信号,通知界面更新 emit dataCenter->receiveSessionCreateDone(); } void NetClient::sendAuth() { bite_im::ClientAuthenticationReq req; req.setRequestId(makeRequestId()); req.setSessionId(dataCenter->getLoginSessionId()); QByteArray body = req.serialize(&serializer); websocketClient.sendBinaryMessage(body); LOG() << "[WS身份认证] requestId= " << req.requestId() << ",loginSessionId= " << req.sessionId(); } QString NetClient::makeRequestId() { //基本的要求,确保每个请求的Id都是不重复的(唯一的) //通过UUID实现上述的效果 return "R" + QUuid::createUuid().toString().sliced(25, 12); } //通过这个函数,把发送HTTP请求的操作封装一下 QNetworkReply* NetClient::sendHttpRequest(const QString& apiPath, const QByteArray& body) { //构造出HTTP请求 QNetworkRequest httpReq; httpReq.setUrl(QUrl(HTTP_URL + apiPath)); httpReq.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-protobuf"); //发起HTTP请求 QNetworkReply* httpResp = httpClient.post(httpReq, body); return httpResp; } //在这个函数内部,完成具体的网络通信即可 void NetClient::getMyself(const QString& loginSessionId) { //构造出HTTP请求body部分 bite_im::GetUserInfoReq req; req.setRequestId(makeRequestId()); req.setSessionId(loginSessionId); QByteArray body = req.serialize(&serializer); LOG() << "获取个人信息->发送请求: requestId=" << req.requestId() << ", loginSessionId=" << loginSessionId; //构造出HTTP请求 QNetworkReply* httpResp = sendHttpRequest("/service/user/get_user_info", body); //通过信号槽,获取到当前的响应 connect(httpResp, &QNetworkReply::finished, this, [=]() { //if (httpResp->error() != QNetworkReply::NoError) { // //说明HTTP请求出错了, // LOG() << "HTTP error: " << httpResp->errorString(); // httpResp->deleteLater(); // return; //} ////说明拿到了body //QByteArray respBody = httpResp->readAll(); ////针对body进行反序列化,解析成对象 //bite_im::GetUserInfoRsp respObj; //respObj.deserialize(&serializer, respBody); ////判定一下业务上是否出错 //if (!respObj.success()) { // LOG() << "requestId= " << respObj.requestId() << ", errmsg=" << respObj.errmsg(); // httpResp->deleteLater(); // return; //} //继续处理后续的业务逻辑 //获取http回复 bool ok = false; QString reason; auto resp = handleHttpResponse(httpResp, &ok, &reason); //判定响应是否正确 if (!ok) { LOG() << "获取个人信息->出错 requestId= " << req.requestId() << ", reason= " << reason; return; } //把响应的数据保存到DataCenter dataCenter->resetMyself(resp); //通知调用逻辑,响应已经处理完成了,仍然通过信号槽通知 emit dataCenter->getMyselfDone(); //打印日志 LOG() << "获取个人信息->响应处理完毕 requestId" << req.requestId(); }); } void NetClient::getFriendList(const QString& loginSessionId) { //通过protobuf构造body bite_im::GetFriendListReq req; req.setRequestId(makeRequestId()); req.setSessionId(loginSessionId); QByteArray body = req.serialize(&serializer); LOG() << "获取好友列表->发送请求 requestId=" << req.requestId() << ", loginSessionId= " << loginSessionId; //发送HTTP请求 QNetworkReply* httpResp = this->sendHttpRequest("/service/friend/get_friend_list", body); //处理响应 connect(httpResp, &QNetworkReply::finished, this, [=]() { //解析响应 bool ok = false; QString reason; auto friendListResp = this->handleHttpResponse(httpResp, &ok, &reason); if (!ok) { LOG() << "获取好友列表->失败 requestId= " << req.requestId() << ", reason= " << reason; } LOG() << "获取好友列表->成功"; //把结果保存在DataCenter中 dataCenter->resetFriendList(friendListResp); // 发送信号 emit dataCenter->getFriendListDone(); }); } void NetClient::getChatSessionList(const QString& loginSessionId) { //通过protobuf构造body bite_im::GetChatSessionListReq req; req.setRequestId(makeRequestId()); req.setSessionId(loginSessionId); QByteArray body = req.serialize(&serializer); LOG() << "获取会话列表->发送请求 requestId= " << req.requestId() << ", loginSessionId= " << loginSessionId; //发送HTTP请求 QNetworkReply* resp = this->sendHttpRequest("/service/friend/get_chat_session_list", body); //针对响应进行处理 connect(resp, &QNetworkReply::finished, this, [=]() { //解析响应 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); //判断响应是否正确 if (!ok) { LOG() << "获取会话列表->失败 reason= " << reason; return; } //到这里说明没有问题,把得到的数据,写入到DataCenter中 dataCenter->resetChatSessionList(pbResp); //通知调用者,响应已经处理完毕了 emit dataCenter->getChatSessionListDone(); //打印日志 LOG() << "获取会话列表->处理响应完毕 requestId= " << pbResp->requestId(); }); } void NetClient::getApplyList(const QString& loginSessionId) { //通过protobuf构造body bite_im::GetPendingFriendEventListReq req; req.setRequestId(makeRequestId()); req.setSessionId(loginSessionId); QByteArray body = req.serialize(&serializer); LOG() << "获取好友申请列表->发送请求 reason= " << req.requestId() << ", loginSessonId= " << loginSessionId; //发送HTTP请求 QNetworkReply* resp = this->sendHttpRequest("/service/friend/get_pending_friend_events", body); //处理响应 connect(resp, &QNetworkReply::finished, this, [=]() { //解析响应 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); //判定结果是否正确 if (!ok) { LOG() << "获取好友申请列表->失败 reason= " << reason; return; } //拿到的数据,写入到DataCenter中 dataCenter->resetApplyList(pbResp); //发送信号通知界面,已经处理完毕 emit dataCenter->getApplyListDone(); LOG() << "获取好友申请列表->处理响应完成 requestId= " << req.requestId(); }); } void NetClient::getRecentMessageList(const QString& loginSessionId, const QString& chatSessionId, bool updateUI) { //通过protobuf构造请求body bite_im::GetRecentMsgReq req; req.setRequestId(makeRequestId()); req.setChatSessionId(chatSessionId); req.setMsgCount(50); req.setSessionId(loginSessionId); QByteArray body = req.serialize(&serializer); LOG() << "获取最近消息->发送请求 requestId= " << req.requestId() << ", loginSessionId= " << loginSessionId; //发送http请求 QNetworkReply* resp = this->sendHttpRequest("/service/message_storage/get_recent", body); //处理响应 connect(resp, &QNetworkReply::finished, this, [=]() { //解析响应,反序列化 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); //判定响应是否出错 if (!ok) { LOG() << "获取最近消息->失败 reason= " << reason; return; } //把拿到的数据,设置到DataCenter中 dataCenter->resetRecentMessageList(chatSessionId, pbResp); //发送信号,告知界面进行更新 if (updateUI) { emit dataCenter->getRecentMessageListDone(chatSessionId); } else { emit dataCenter->getRecentMessageListDoneNoUI(chatSessionId); } }); } //此处的extraInfo,可以用来传递扩展信息,尤其是对文件消息来说,通过这个字段表示“文件名” //其他类型的消息暂时不涉及,就直接设置为空,如果后续有消息类型需要,都可以给这个参数,赋予一定的特殊意义 void NetClient::sendMessage(const QString& loginSessionId, const QString& chatSessionId, model::MessageType messageType, const QByteArray& content, const QString& extraInfo) { //通过protobuf 构造 body bite_im::NewMessageReq req; req.setRequestId(makeRequestId()); req.setSessionId(loginSessionId); req.setChatSessionId(chatSessionId); //构造MessageContent bite_im::MessageContent messageContent; if (messageType == MessageType::TEXT_TYPE) { messageContent.setMessageType(bite_im::MessageTypeGadget::MessageType::STRING); bite_im::StringMessageInfo stringMessageInfo; stringMessageInfo.setContent(content); messageContent.setStringMessage(stringMessageInfo); } else if (messageType == MessageType::IMAGE_TYPE) { messageContent.setMessageType(bite_im::MessageTypeGadget::MessageType::IMAGE); bite_im::ImageMessageInfo imageMessageInfo; imageMessageInfo.setFileId(""); imageMessageInfo.setImageContent(content); messageContent.setImageMessage(imageMessageInfo); } else if (messageType == MessageType::FILE_TYPE) { messageContent.setMessageType(bite_im::MessageTypeGadget::MessageType::FILE); bite_im::FileMessageInfo fileMessageInfo; fileMessageInfo.setFileId(""); fileMessageInfo.setFileSize(content.size()); fileMessageInfo.setFileName(extraInfo); fileMessageInfo.setFileContents(content); messageContent.setFileMessage(fileMessageInfo); } else if (messageType == MessageType::SPEECH_TYPE) { messageContent.setMessageType(bite_im::MessageTypeGadget::MessageType::SPEECH); bite_im::SpeechMessageInfo speechMessageInfo; speechMessageInfo.setFileId(""); speechMessageInfo.setFileContents(content); messageContent.setSpeechMessage(speechMessageInfo); } else { LOG() << "错误的消息类型 messageType= " << messageType; } req.setMessage(messageContent); //序列化操作 QByteArray body = req.serialize(&serializer); LOG() << "发送消息->发送请求 requestId= " << req.requestId() << ", loginSessionId=" << req.sessionId() << ", chatSessionId= " << req.chatSessionId() << ", messageType=" << req.message().messageType(); //发送HTTP请求 QNetworkReply* resp = this->sendHttpRequest("/service/message_transmit/new_message", body); //处理HTTP响应 connect(resp, &QNetworkReply::finished, this, [=]() { //针对响应结果,进行解析 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); //判定响应是否正确 if (!ok) { LOG() << "发送消息->处理出错 reason= " << reason; return; } //此处只是记录成功和失败,不需要把内写入到DataCenter中 //通知调用者,响应处理完毕 emit dataCenter->sendMessageDone(messageType, content, extraInfo); //打印日志 LOG() << "发送消息->响应处理完毕 requestId=" << pbResp->requestId(); }); } void NetClient::receiveMessage(const QString& chatSessionId) { //要先判定一下,这个收到消息对应的会话是否是正在被用户选中的“当前会话” //当前会话,就需要把消息显示到消息展示区,也需要更新会话列表消息预览 //若不是,只更新消息预览,并且更新“未读消息数目” if (chatSessionId == dataCenter->getCurrentSessionId()) { //说明是选中的会话 const Message& lastMessage = dataCenter->getRecentMessageList(chatSessionId)->back(); //通过信号,让NetClient模块能够通知界面 emit dataCenter->receiveMessageDone(lastMessage); } else { //说明不是 dataCenter->addUnread(chatSessionId); } //统一更新会话列表的消息预览 emit dataCenter->updateLastMessage(chatSessionId); } void NetClient::changeNickname(const QString& loginSessionId, const QString& nickname) { //通过 protobuf 构造请求body bite_im::SetUserNicknameReq pbReq; pbReq.setRequestId(makeRequestId());; pbReq.setSessionId(loginSessionId); pbReq.setNickname(nickname); QByteArray body = pbReq.serialize(&serializer); LOG() << "修改用户昵称->发送请求 requestId= " << pbReq.requestId() << ", loginSessionId= " << pbReq.sessionId() << ", nickname= " << pbReq.nickname(); //发送HTTP请求 QNetworkReply* resp = this->sendHttpRequest("/service/user/set_nickname", body); //处理HTTP响应 connect(resp, & QNetworkReply::finished, this, [=]() { //解析响应 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); //判定响应是否正确 if (!ok) { LOG() << "修改用户昵称->处理出错 reason= " << reason; return; } //把结果写入到DataCenter中 dataCenter->resetNickname(nickname); //通知调用者,响应已经处理完毕 emit dataCenter->changeNicknameDone(); LOG() << "修改用户昵称->响应处理完毕 requestId= " << pbResp->requestId(); }); } void NetClient::changeDescription(const QString& loginSessionId, const QString& desc) { //通过 protobuf 构造请求body bite_im::SetUserDescriptionReq pbReq; pbReq.setRequestId(makeRequestId()); pbReq.setSessionId(loginSessionId); pbReq.setDescription(desc); QByteArray body = pbReq.serialize(&serializer); LOG() << "修改用户描述->发送请求 requestId= " << pbReq.requestId() << ", loginSessionId= " << pbReq.sessionId() << ", description= " << pbReq.description(); //发送HTTP请求 QNetworkReply* resp = this->sendHttpRequest("/service/user/set_description", body); //处理HTTP响应 connect(resp, &QNetworkReply::finished, this, [=]() { //解析响应 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); //判定响应是否正确 if (!ok) { LOG() << "修改用户描述->处理出错 reason= " << reason; return; } //把得到的结果写入到DataCenter中 dataCenter->resetDescription(desc); //发送信号,通知修改完成 emit dataCenter->changeDescriptionDone(); //打印日志 LOG() << "修改用户描述->响应处理完毕 requestId= " << pbResp->requestId(); }); } void NetClient::getVerifyCode(const QString& email) { //构造请求body bite_im::PhoneVerifyCodeReq pbReq; pbReq.setRequestId(makeRequestId()); pbReq.setPhoneNumber(email); QByteArray body = pbReq.serialize(&serializer); LOG() << "获取验证码->发送请求 requestId= " << pbReq.requestId() << ", email= " << pbReq.phoneNumber(); //发送HTTP请求 QNetworkReply* resp = this->sendHttpRequest("/service/user/get_phone_verify_code", body); //处理HTTP响应 connect(resp, &QNetworkReply::finished, this, [=]() { //解析响应 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); //发送信号给调用者 emit dataCenter->getVerifyCodeDone(ok); //判定响应是否正确 if (!ok) { LOG() << "获取验证码->处理出错 reason= " << reason; return; } //把得到的结果写入到DataCenter中 dataCenter->resetVerifyCodeId(pbResp->verifyCodeId()); //打印日志 LOG() << "获取验证码->响应处理完毕 requestId= " << pbResp->requestId() << "Id= " << dataCenter->getVerifyCodeId(); }); } void NetClient::changeEmail(const QString& loginSessionId, const QString& email, const QString& verifyCodeId, const QString& verifyCode) { //构造请求body bite_im::SetUserPhoneNumberReq pbReq; pbReq.setRequestId(makeRequestId()); pbReq.setSessionId(loginSessionId); pbReq.setPhoneNumber(email); pbReq.setPhoneVerifyCodeId(verifyCodeId); pbReq.setPhoneVerifyCode(verifyCode); QByteArray body = pbReq.serialize(&serializer); LOG() << "修改用户邮箱->发送请求 requestId= " << pbReq.requestId() << ", loginSessionId= " << pbReq.sessionId() << ", email= " << pbReq.phoneNumber() << ", verifyCodeId= " << pbReq.phoneVerifyCodeId() << ", verifyCode= " << pbReq.phoneVerifyCode(); //发送HTTP请求 QNetworkReply* resp = this->sendHttpRequest("/service/user/set_phone", body); //处理HTTP响应 connect(resp, &QNetworkReply::finished, this, [=]() { bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); //判定响应是否正确 if (!ok) { LOG() << "修改用户邮箱->处理出错 reason= " << reason; return; } //把结果记录到DataCenter中 dataCenter->resetPhone(email); //打印日志 LOG() << "修改用户邮箱->响应处理完毕 requestId= " << pbResp->requestId(); }); //发送信号,通知调用者完成 emit dataCenter->changePhoneDone(); } void NetClient::changeAvatar(const QString& loginSessionId, const QByteArray& avatar) { //构造请求body bite_im::SetUserAvatarReq pbReq; pbReq.setRequestId(makeRequestId()); pbReq.setSessionId(loginSessionId); pbReq.setAvatar(avatar); QByteArray body = pbReq.serialize(&serializer); LOG() << "修改用户头像->发送请求 requestId= " << pbReq.requestId() << ", loginSessionId= " << pbReq.sessionId() << ", avatar size= " << pbReq.avatar().size(); //发送HTTP请求 QNetworkReply* resp = this->sendHttpRequest("/service/user/set_avatar", body); //处理HTTP响应 connect(resp, &QNetworkReply::finished, this, [=]() { //解析响应 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); //判定响应是否正确 if (!ok) { LOG() << "修改用户头像->处理出错 reason= " << reason; return; } //把数据写入到DataCenter dataCenter->resetAvatar(avatar); //发送信号 emit dataCenter->changeAvatarDone(); //打印日志 LOG() << "修改用户头像->响应处理完成 requestId= " << pbResp->requestId(); }); } void NetClient::deleteFriend(const QString& loginSessionId, const QString& userId) { //构造请求body bite_im::FriendRemoveReq pbReq; pbReq.setRequestId(makeRequestId()); pbReq.setSessionId(loginSessionId); pbReq.setPeerId(userId); QByteArray body = pbReq.serialize(&serializer); LOG() << "删除好友->发送请求 requestId= " << pbReq.requestId() << ", loginSessionId= " << pbReq.sessionId() << ", userId= " << pbReq.peerId(); //发送HTTP请求 QNetworkReply* resp = this->sendHttpRequest("/service/friend/remove_friend", body); //处理HTTP响应 connect(resp, &QNetworkReply::finished, this, [=]() { //解析响应 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); //判定响应结果是否正确 if (!ok) { LOG() << "删除好友->处理出错 reason= " << reason; return; } //把结果写入到DataCenter中,把该用户从好友列表中删除掉 dataCenter->removeFriend(userId); //发送信号,通知调用者当前好友删除完毕 emit dataCenter->deleteFriendDone(); //打印日志 LOG() << "删除好友->响应完成 requestId= " << pbResp->requestId(); }); } void NetClient::addFriendApply(const QString& loginSessionId, const QString& userId) { //构造请求body bite_im::FriendAddReq pbReq; pbReq.setRequestId(makeRequestId()); pbReq.setSessionId(loginSessionId); pbReq.setRespondentId(userId); QByteArray body = pbReq.serialize(&serializer); LOG() << "添加好友申请->发送请求 requestId= " << pbReq.requestId() << ", loginSessionId= " << pbReq.sessionId() << ", userId= " << userId; //发送HTTP请求 QNetworkReply* resp = this->sendHttpRequest("/service/friend/add_friend_apply", body); //处理响应 connect(resp, &QNetworkReply::finished, this, [=]() { //解析响应 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); //判定响应是否正确 if (!ok) { LOG() << "添加好友申请->响应失败 reason= " << reason; return; } //记录结果到DataCenter,此处不需要记录任何数据 //发送信号,通知调用者 emit dataCenter->addFriendApplyDone(); //打印日志 LOG() << "添加好友申请->响应完毕 requestId= " << pbResp->requestId(); }); } void NetClient::acceptFriendApply(const QString& loginSessionId, const QString& userId) { //构造请求body bite_im::FriendAddProcessReq pbReq; pbReq.setRequestId(makeRequestId()); pbReq.setSessionId(loginSessionId); pbReq.setAgree(true); pbReq.setApplyUserId(userId); QByteArray body = pbReq.serialize(&serializer); LOG() << "同意好友申请->发送请求 requestId= " << pbReq.requestId() << ", loginSessionId= " << pbReq.sessionId() << ", userId= " << pbReq.applyUserId(); //发送HTTP请求 QNetworkReply* resp = this->sendHttpRequest("/service/friend/add_friend_process", body); //处理HTTP响应 connect(resp, &QNetworkReply::finished, this, [=]() { //解析响应 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); //判定响应结果是否正确 if (!ok) { LOG() << "同意好友申请->处理出错 reason= " << reason; return; } //此处做一个好友列表的更新 //把好友从申请列表中删除掉 //并将该好友添加到好友列表中 UserInfo applyUser = dataCenter->removeFromApplyList(userId); QList* friendList = dataCenter->getFriendList(); friendList->push_front(applyUser); //发送信号,通知界面进行更新 emit dataCenter->acceptFriendApplyDone(); //打印日志 LOG() << "同意好友申请->相应完成 requestId= " << pbResp->requestId(); }); } void NetClient::rejectFriendApply(const QString& loginSessionId, const QString& userId) { //构造请求body bite_im::FriendAddProcessReq pbReq; pbReq.setRequestId(makeRequestId()); pbReq.setSessionId(loginSessionId); pbReq.setAgree(false); pbReq.setApplyUserId(userId); QByteArray body = pbReq.serialize(&serializer); LOG() << "拒绝好友申请->发送请求 requestId= " << pbReq.requestId() << ", loginSessionId= " << pbReq.sessionId() << ", userId= " << pbReq.applyUserId(); //发送HTTP请求 QNetworkReply* resp = this->sendHttpRequest("/service/friend/add_friend_process", body); //处理HTTP响应 connect(resp, &QNetworkReply::finished, this, [=]() { //解析响应 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); //判定响应结果是否正确 if (!ok) { LOG() << "拒绝好友申请->处理出错 reason= " << reason; return; } //把好友从申请列表中删除掉 dataCenter->removeFromApplyList(userId); //发送信号,通知界面进行更新 emit dataCenter->rejectFriendApplyDone(); //打印日志 LOG() << "拒绝好友申请->相应完成 requestId= " << pbResp->requestId(); }); } void NetClient::createGroupChatSession(const QString& loginSessionId, const QList& userIdList) { //构造请求body bite_im::ChatSessionCreateReq pbReq; pbReq.setRequestId(makeRequestId()); pbReq.setSessionId(loginSessionId); pbReq.setChatSessionName("新的群聊"); pbReq.setMemberIdList(userIdList); QByteArray body = pbReq.serialize(&serializer); LOG() << "创建群聊会话->发送请求 requestId= " << pbReq.requestId() << ", loginSessionId= " << loginSessionId << ", userIdList= " << userIdList; //发送HTTP请求 QNetworkReply* resp = this->sendHttpRequest("/service/friend/create_chat_session", body); //处理响应 connect(resp, &QNetworkReply::finished, this, [=]() { //解析响应 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); //判断结果是否正确 if (!ok) { LOG() << "创建群聊会话->响应失败 reason= " << reason; return; } //这里无需更新DataCenter, 后续通过websocket的逻辑来更新即可 //通知调用者 emit dataCenter->createGroupChatSessionDone(); //打印日志 LOG() << "创建群聊会话->响应完成 requestId= " << pbResp->requestId(); }); } void NetClient::getMemberList(const QString& loginSessionId, const QString& chatSessionId) { //构造请求body bite_im::GetChatSessionMemberReq pbReq; pbReq.setRequestId(makeRequestId()); pbReq.setSessionId(loginSessionId); pbReq.setChatSessionId(chatSessionId); QByteArray body = pbReq.serialize(&serializer); LOG() << "获取会话成员列表->发送请求 requestId= " << pbReq.requestId() << ", loginSessionId= " << pbReq.sessionId() << ", chatSessionId= " << pbReq.chatSessionId(); //发送HTTP请求 QNetworkReply* resp = this->sendHttpRequest("/service/friend/get_chat_session_member", body); //处理响应 connect(resp, &QNetworkReply::finished, this, [=]() { //解析响应 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); //判定响应结果是否正确 if (!ok) { LOG() << "获取会话成员列表->响应失败 reason= " << reason; return; } //把结果记录到DataCenter dataCenter->resetMemberList(chatSessionId, pbResp->memberInfoList()); //发送信号 emit dataCenter->getMemberListDone(chatSessionId); //打印日志 LOG() << "获取会话成员列表->响应完成 requestId= " << pbResp->requestId(); }); } void NetClient::searchUser(const QString& loginSessionId, const QString& searchKey) { // 1. 构造请求 body bite_im::FriendSearchReq pbReq; pbReq.setRequestId(makeRequestId()); pbReq.setSessionId(loginSessionId); pbReq.setSearchKey(searchKey); QByteArray body = pbReq.serialize(&serializer); LOG() << "搜索用户->发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << loginSessionId << ", searchKey=" << searchKey; // 2. 发送 HTTP 请求 QNetworkReply* resp = this->sendHttpRequest("/service/friend/search_friend", body); // 3. 处理响应 connect(resp, &QNetworkReply::finished, this, [=]() { // a) 解析响应 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); // b) 判定响应成功 if (!ok) { LOG() << "搜索用户->响应失败 reason=" << reason; return; } // c) 把得到的结果, 记录到 DataCenter dataCenter->resetSearchUserResult(pbResp->userInfo()); // d) 发送信号, 通知调用者 emit dataCenter->searchUserDone(); // e) 打印日志 LOG() << "搜索用户->响应完成 requestId=" << pbResp->requestId(); }); } void NetClient::searchMessage(const QString& loginSessionId, const QString& chatSessionId, const QString& searchKey) { // 1. 构造请求 body bite_im::MsgSearchReq pbReq; pbReq.setRequestId(makeRequestId()); pbReq.setSessionId(loginSessionId); pbReq.setChatSessionId(chatSessionId); pbReq.setSearchKey(searchKey); QByteArray body = pbReq.serialize(&serializer); LOG() << "按关键词搜索历史消息->发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << pbReq.sessionId() << ", chatSessionId=" << pbReq.chatSessionId() << ", searchKey=" << searchKey; // 2. 发送 HTTP 请求 QNetworkReply* resp = this->sendHttpRequest("/service/message_storage/search_history", body); // 3. 处理响应 connect(resp, &QNetworkReply::finished, this, [=]() { // a) 解析响应 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); // b) 判定响应是否正确 if (!ok) { LOG() << "按关键词搜索历史消息->响应失败! reason=" << reason; return; } // c) 把响应结果写入到 DataCenter dataCenter->resetSearchMessageResult(pbResp->msgList()); // d) 发送信号 emit dataCenter->searchMessageDone(); // e) 打印日志 LOG() << "按关键词搜索历史消息->响应完成 requestId=" << pbResp->requestId(); }); } void NetClient::searchMessageByTime(const QString& loginSessionId, const QString& chatSessionId, const QDateTime& begTime, const QDateTime& endTime) { // 1. 构造请求 body bite_im::GetHistoryMsgReq pbReq; pbReq.setRequestId(makeRequestId()); pbReq.setSessionId(loginSessionId); pbReq.setChatSessionId(chatSessionId); pbReq.setStartTime(begTime.toSecsSinceEpoch()); pbReq.setOverTime(endTime.toSecsSinceEpoch()); QByteArray body = pbReq.serialize(&serializer); LOG() << "按时间搜索历史消息->发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << pbReq.sessionId() << ", chatSessionId=" << pbReq.chatSessionId() << ", begTime= " << begTime << ", endTime= " << endTime; // 2. 发送 HTTP 请求 QNetworkReply* resp = this->sendHttpRequest("/service/message_storage/get_history", body); // 3. 处理响应 connect(resp, &QNetworkReply::finished, this, [=]() { // a) 解析响应 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); // b) 判定响应是否正确 if (!ok) { LOG() << "按时间搜索历史消息->响应失败! reason=" << reason; return; } // c) 把响应结果写入到 DataCenter dataCenter->resetSearchMessageResult(pbResp->msgList()); // d) 发送信号 emit dataCenter->searchMessageDone(); // e) 打印日志 LOG() << "按时间搜索历史消息->响应完成 requestId=" << pbResp->requestId(); }); } void NetClient::userLogin(const QString& username, const QString& password) { // 1. 构造请求 body bite_im::UserLoginReq pbReq; pbReq.setRequestId(makeRequestId()); pbReq.setNickname(username); pbReq.setPassword(password); pbReq.setVerifyCodeId(""); pbReq.setVerifyCode(""); QByteArray body = pbReq.serialize(&serializer); LOG() << "用户名登录->发送请求 requestId=" << pbReq.requestId() << ", username=" << pbReq.nickname() << ", password=" << pbReq.password(); // 2. 发送 HTTP 请求 QNetworkReply* resp = this->sendHttpRequest("/service/user/username_login", body); // 3. 处理响应 connect(resp, &QNetworkReply::finished, this, [=]() { // a) 解析响应内容 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); // b) 判定响应结果是否正确 if (!ok) { LOG() << "用户名登录->处理失败 reason=" << reason; emit dataCenter->userLoginDone(false, reason); return; } // c) 记录一下当前返回的数据 dataCenter->resetLoginSessionId(pbResp->loginSessionId()); // d) 发送信号, 通知调用者, 处理完毕了. emit dataCenter->userLoginDone(true, ""); // e) 打印日志 LOG() << "用户名登录->处理响应 requestId=" << pbResp->requestId(); }); } void NetClient::userRegister(const QString& username, const QString& password) { // 1. 构造请求 body bite_im::UserRegisterReq pbReq; pbReq.setRequestId(makeRequestId()); pbReq.setNickname(username); pbReq.setPassword(password); pbReq.setVerifyCodeId(""); pbReq.setVerifyCode(""); QByteArray body = pbReq.serialize(&serializer); LOG() << "用户名注册->发送请求 requestId=" << pbReq.requestId() << ", username=" << pbReq.nickname() << ", password=" << pbReq.password(); // 2. 发送 HTTP 请求 QNetworkReply* resp = this->sendHttpRequest("/service/user/username_register", body); // 3. 处理响应 connect(resp, &QNetworkReply::finished, this, [=]() { // a) 解析响应 body bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); // b) 判定响应结果是否正确 if (!ok) { LOG() << "用户名注册->响应失败! reason=" << reason; emit dataCenter->userRegisterDone(false, reason); return; } // c) 把返回的数据保存到 DataCenter 中 // 对于注册来说, 不需要保存任何信息, 直接跳过这个环节. // d) 通知调用者响应处理完成 emit dataCenter->userRegisterDone(true, ""); // e) 打印日志 LOG() << "用户名注册->响应完成 requestId=" << pbResp->requestId(); }); } void NetClient::phoneLogin(const QString& phone, const QString& verifyCodeId, const QString& verifyCode) { // 1. 构造请求 body bite_im::PhoneLoginReq pbReq; pbReq.setRequestId(makeRequestId()); pbReq.setPhoneNumber(phone); pbReq.setVerifyCodeId(verifyCodeId); pbReq.setVerifyCode(verifyCode); QByteArray body = pbReq.serialize(&serializer); LOG() << "手机号登录->发送请求 requestId=" << pbReq.requestId() << ", phone=" << pbReq.phoneNumber() << ", verifyCodeId=" << pbReq.verifyCodeId() << ", verifyCode=" << pbReq.verifyCode(); // 2. 发送 HTTP 请求 QNetworkReply* resp = this->sendHttpRequest("/service/user/phone_login", body); // 3. 处理响应 connect(resp, &QNetworkReply::finished, this, [=]() { // a) 解析响应 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); // b) 判定响应是否成功 if (!ok) { LOG() << "手机号登录->响应出错! reason=" << reason; emit dataCenter->phoneLoginDone(false, reason); return; } // c) 把响应结果记录到 DataCenter dataCenter->resetLoginSessionId(pbResp->loginSessionId()); // d) 发送信号 emit dataCenter->phoneLoginDone(true, ""); // e) 打印日志 LOG() << "手机号登录->响应完毕 requestId=" << pbResp->requestId(); }); } void NetClient::phoneRegister(const QString& phone, const QString& verifyCodeId, const QString& verifyCode) { // 1. 构造请求 body bite_im::PhoneRegisterReq pbReq; pbReq.setRequestId(makeRequestId()); pbReq.setPhoneNumber(phone); pbReq.setVerifyCodeId(verifyCodeId); pbReq.setVerifyCode(verifyCode); QByteArray body = pbReq.serialize(&serializer); LOG() << "手机号注册->发送请求 requestId=" << pbReq.requestId() << ", phone=" << pbReq.phoneNumber() << ", verifyCodeId=" << pbReq.verifyCodeId() << ", verifyCode=" << pbReq.verifyCode(); // 2. 发送 HTTP 请求 QNetworkReply* resp = this->sendHttpRequest("/service/user/phone_register", body); // 3. 处理响应 connect(resp, &QNetworkReply::finished, this, [=]() { // a) 解析响应 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); // b) 判定响应是否成功 if (!ok) { LOG() << "手机号注册->响应失败! reason=" << reason; emit dataCenter->phoneRegisterDone(false, reason); return; } // c) 让 DataCenter 记录结果, 注册操作不需要记录 // d) 发送信号 emit dataCenter->phoneRegisterDone(true, ""); // e) 打印日志 LOG() << "手机号注册->响应完成 requestId=" << pbResp->requestId(); }); } void NetClient::getSingleFile(const QString& loginSessionId, const QString& fileId) { //构造请求body bite_im::GetSingleFileReq pbReq; pbReq.setRequestId(makeRequestId()); pbReq.setSessionId(loginSessionId); pbReq.setFileId(fileId); QByteArray body = pbReq.serialize(&serializer); LOG() << "获取文件内容->发送请求 requestId= " << pbReq.requestId() << ", fileId= " << fileId; //发送HTTP请求 QNetworkReply* resp = this->sendHttpRequest("/service/file/get_single_file", body); //处理响应 connect(resp, &QNetworkReply::finished, this, [=]() { //解析响应 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); //判定响应结果是否正确 if (!ok) { LOG() << "获取文件内容->响应失败 reason= " << reason; return; } //这里涉及的文件可能会很多,不使用DataCenter保存 //直接通过信号把文件数据,投送到调用者位置 //发送信号 emit dataCenter->getSingleFileDone(fileId, pbResp->fileData().fileContent()); //打印日志 LOG() << "获取文件内容->响应完成 requestId= " << pbResp->requestId(); }); } void NetClient::speechConvertText(const QString& loginSessionId, const QString& fileId, const QByteArray& content) { // 1. 构造请求 body bite_im::SpeechRecognitionReq pbReq; pbReq.setRequestId(makeRequestId()); pbReq.setSessionId(loginSessionId); pbReq.setSpeechContent(content); QByteArray body = pbReq.serialize(&serializer); LOG() << "[语音转文字] 发送请求 requestId=" << pbReq.requestId() << ", loginSessonId=" << pbReq.sessionId(); // 2. 发送 HTTP 请求 QNetworkReply* resp = this->sendHttpRequest("/service/speech/recognition", body); // 3. 处理响应 connect(resp, &QNetworkReply::finished, this, [=]() { // a) 解析响应 bool ok = false; QString reason; auto pbResp = this->handleHttpResponse(resp, &ok, &reason); // b) 判定响应结果 if (!ok) { LOG() << "[语音转文字] 响应错误! reason=" << reason; return; } // c) 把结果写入到 DataCenter 中. 此处不打算通过 DataCenter 表示这里的语音识别结果. 直接通过 信号 通知结果即可. // d) 发送信号, 通知调用者 emit dataCenter->speechConvertTextDone(fileId, pbResp->recognitionResult()); // e) 打印日志 LOG() << "[语音转文字] 响应完成 requestId=" << pbResp->requestId(); }); } } //end namespace network