From 521cc2d8e239cca75e7c565f574e4573cb109429 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sun, 5 Jan 2025 22:34:04 +0300 Subject: Steam: basic group chat support --- protocols/Steam/Steam.vcxproj | 1 + protocols/Steam/Steam.vcxproj.filters | 3 + protocols/Steam/src/main.cpp | 5 + protocols/Steam/src/stdafx.h | 1 + protocols/Steam/src/steam_chats.cpp | 300 +++++++++++++++++++++++++++++++++ protocols/Steam/src/steam_login.cpp | 10 +- protocols/Steam/src/steam_messages.cpp | 28 +-- protocols/Steam/src/steam_proto.cpp | 18 +- protocols/Steam/src/steam_proto.h | 37 +++- protocols/Steam/src/steam_server.cpp | 3 +- protocols/Steam/src/steam_ws.cpp | 41 ++++- 11 files changed, 406 insertions(+), 41 deletions(-) create mode 100644 protocols/Steam/src/steam_chats.cpp (limited to 'protocols') diff --git a/protocols/Steam/Steam.vcxproj b/protocols/Steam/Steam.vcxproj index 0f29dd2747..445cb17cd3 100644 --- a/protocols/Steam/Steam.vcxproj +++ b/protocols/Steam/Steam.vcxproj @@ -79,6 +79,7 @@ Create + diff --git a/protocols/Steam/Steam.vcxproj.filters b/protocols/Steam/Steam.vcxproj.filters index 3bd5e7610d..c1d24742be 100644 --- a/protocols/Steam/Steam.vcxproj.filters +++ b/protocols/Steam/Steam.vcxproj.filters @@ -111,6 +111,9 @@ Source Files\protobuf + + Source Files + diff --git a/protocols/Steam/src/main.cpp b/protocols/Steam/src/main.cpp index 920345a2e5..828311e40f 100644 --- a/protocols/Steam/src/main.cpp +++ b/protocols/Steam/src/main.cpp @@ -171,6 +171,11 @@ void CMPlugin::InitSteamServices() serviceHandlers[FriendGetRecentMessages] = ServiceResponseHandler(&CSteamProto::OnGotRecentMessages); serviceHandlers[FriendGetIncomingMessage] = ServiceResponseHandler(&CSteamProto::OnGotIncomingMessage); + serviceHandlers[GetMyChatRoomGroups] = ServiceResponseHandler(&CSteamProto::OnGetMyChats); + serviceHandlers[GetChatHistory] = ServiceResponseHandler(&CSteamProto::OnGetChatHistory); + serviceHandlers[NotifyIncomingChatMessage] = ServiceResponseHandler(&CSteamProto::OnGetChatMessage); + serviceHandlers[LeaveChatGroup] = ServiceResponseHandler(&CSteamProto::OnLeftChat); + serviceHandlers[GetOwnAuthorizedDevices] = ServiceResponseHandler(&CSteamProto::OnGotDeviceList); serviceHandlers[NotificationReceived] = ServiceResponseHandler(&CSteamProto::OnGotNotification); diff --git a/protocols/Steam/src/stdafx.h b/protocols/Steam/src/stdafx.h index 56b6647f22..37c008b5b1 100644 --- a/protocols/Steam/src/stdafx.h +++ b/protocols/Steam/src/stdafx.h @@ -13,6 +13,7 @@ #include #include +#include #include #include #include diff --git a/protocols/Steam/src/steam_chats.cpp b/protocols/Steam/src/steam_chats.cpp new file mode 100644 index 0000000000..7d25507bde --- /dev/null +++ b/protocols/Steam/src/steam_chats.cpp @@ -0,0 +1,300 @@ +/* +Copyright (C) 2012-25 Miranda NG team (https://miranda-ng.org) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "stdafx.h" + +void CSteamProto::SendGetChatsRequest() +{ + CChatRoomGetMyChatRoomGroupsRequest request; + WSSendService(GetMyChatRoomGroups, request); +} + +void CSteamProto::OnGetMyChats(const CChatRoomGetMyChatRoomGroupsResponse &reply, const CMsgProtoBufHeader &hdr) +{ + if (hdr.failed()) + return; + + for (int i = 0; i < reply.n_chat_room_groups; i++) { + auto *pGroup = reply.chat_room_groups[i]->group_summary; + + SESSION_INFO *pOwner = 0; + + for (int k = 0; k < pGroup->n_chat_rooms; k++) { + auto *pChat = pGroup->chat_rooms[k]; + CMStringW wszId(FORMAT, L"%lld_%d", pGroup->chat_group_id, pChat->chat_id); + + CMStringW wszTitle(Utf2T(pChat->chat_name)); + if (wszTitle.IsEmpty()) + wszTitle = Utf2T(pGroup->chat_group_name); + + auto *si = Chat_NewSession(GCW_CHATROOM, m_szModuleName, wszId, wszTitle); + Chat_AddGroup(si, TranslateT("Owner")); + Chat_AddGroup(si, TranslateT("Participant")); + + if (pOwner == 0) { + for (int j = 0; j < pGroup->n_top_members; j++) { + uint64_t iSteamId = AccountIdToSteamId(pGroup->top_members[j]); + CMStringW wszUserId(FORMAT, L"%lld", iSteamId), wszNick; + + GCEVENT gce = { si, GC_EVENT_JOIN }; + gce.pszUID.w = wszUserId; + + if (iSteamId == m_iSteamId) { + gce.bIsMe = true; + wszNick = getMStringW("Nick"); + } + else if (MCONTACT hContact = GetContact(iSteamId)) + wszNick = Clist_GetContactDisplayName(hContact); + else + wszNick = L"@" + wszUserId; + + gce.pszNick.w = wszNick; + gce.pszStatus.w = (pGroup->top_members[j] == pGroup->accountid_owner) ? TranslateT("Owner") : TranslateT("Participant"); + Chat_Event(&gce); + } + } + else si->pParent = pOwner; + + setDword(si->hContact, "ChatId", pChat->chat_id); + + if (mir_strlen(pGroup->chat_group_tagline)) { + Utf2T wszTopic(pGroup->chat_group_tagline); + Chat_SetStatusbarText(si, wszTopic); + + GCEVENT gce = { si, GC_EVENT_TOPIC }; + gce.pszText.w = wszTopic; + gce.time = time(0); + Chat_Event(&gce); + } + + Chat_Control(si, WINDOW_HIDDEN); + Chat_Control(si, SESSION_ONLINE); + + uint32_t dwLastMsgId = getDword(si->hContact, DBKEY_LASTMSG); + if (pChat->time_last_message > dwLastMsgId) + SendGetChatHistory(si->hContact, dwLastMsgId); + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CSteamProto::SendGetChatHistory(MCONTACT hContact, uint32_t iLastMsgId) +{ + CChatRoomGetMessageHistoryRequest request; + request.chat_group_id = GetId(hContact, DBKEY_STEAM_ID); request.has_chat_group_id = true; + request.chat_id = getDword(hContact, "ChatId"); request.has_chat_id = true; + request.last_time = iLastMsgId; request.has_last_time = true; + WSSendService(GetChatHistory, request, (void*)hContact); +} + +void CSteamProto::OnGetChatHistory(const CChatRoomGetMessageHistoryResponse &reply, const CMsgProtoBufHeader &hdr) +{ + if (hdr.failed()) + return; + + if (auto *si = Chat_Find(UINT_PTR(GetRequestInfo(hdr.jobid_target)), m_szModuleName)) { + uint32_t iLastMsg = getDword(si->hContact, DBKEY_LASTMSG); + uint32_t iChatId = getDword(si->hContact, "ChatId"); + + for (int i = (int)reply.n_messages - 1; i >= 0; i--) { + auto *pMsg = reply.messages[i]; + if (pMsg->server_timestamp > iLastMsg) + iLastMsg = pMsg->server_timestamp; + + // some slack, skip it + if (pMsg->server_message) + continue; + + char szMsgId[100], szUserId[100]; + mir_snprintf(szMsgId, "%d_%d", iChatId, pMsg->server_timestamp); + _i64toa(AccountIdToSteamId(pMsg->sender), szUserId, 10); + + DB::EventInfo dbei(db_event_getById(m_szModuleName, szMsgId)); + dbei.flags |= DBEF_UTF; + dbei.eventType = EVENTTYPE_MESSAGE; + dbei.szModule = m_szModuleName; + replaceStr(dbei.pBlob, mir_strdup(pMsg->message)); + dbei.cbBlob = (int)mir_strlen(dbei.pBlob); + dbei.timestamp = pMsg->server_timestamp; + dbei.szId = szMsgId; + dbei.szUserId = szUserId; + + if (dbei.getEvent()) + db_event_edit(dbei.getEvent(), &dbei, true); + else + db_event_add(si->hContact, &dbei); + } + + setDword(si->hContact, DBKEY_LASTMSG, iLastMsg); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CSteamProto::OnGetChatMessage(const CChatRoomIncomingChatMessageNotification &reply, const CMsgProtoBufHeader &hdr) +{ + if (hdr.failed()) + return; + + CMStringW wszId(FORMAT, L"%lld_%lld", reply.chat_group_id, reply.chat_id); + if (auto *si = Chat_Find(wszId, m_szModuleName)) { + char szMsgId[100], szUserId[100]; + mir_snprintf(szMsgId, "%lld_%d", reply.chat_id, reply.timestamp); + _i64toa(reply.steamid_sender, szUserId, 10); + + DB::EventInfo dbei(db_event_getById(m_szModuleName, szMsgId)); + dbei.flags |= DBEF_UTF; + dbei.eventType = EVENTTYPE_MESSAGE; + dbei.szModule = m_szModuleName; + replaceStr(dbei.pBlob, mir_strdup(reply.message)); + dbei.cbBlob = (int)mir_strlen(dbei.pBlob); + dbei.timestamp = reply.timestamp; + dbei.szId = szMsgId; + dbei.szUserId = szUserId; + + if (dbei.getEvent()) + db_event_edit(dbei.getEvent(), &dbei, true); + else + db_event_add(si->hContact, &dbei); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +INT_PTR CSteamProto::SvcLeaveChat(WPARAM hContact, LPARAM) +{ + CChatRoomLeaveChatRoomGroupRequest request; + request.chat_group_id = GetId(hContact, DBKEY_STEAM_ID); request.has_chat_group_id = true; + WSSendService(LeaveChatGroup, request, new uint64_t(request.chat_group_id)); + return 0; +} + +void CSteamProto::OnLeftChat(const CChatRoomLeaveChatRoomGroupResponse&, const CMsgProtoBufHeader &hdr) +{ + if (auto *pGroupId = (int64_t *)GetRequestInfo(hdr.jobid_target)) { + for (auto &cc : AccContacts()) { + if (!Contact::IsGroupChat(cc) || GetId(cc, DBKEY_STEAM_ID) != *pGroupId) + continue; + + CMStringW wszId(FORMAT, L"%lld_%lld", *pGroupId, getDword(cc, "ChatId")); + if (auto *si = Chat_Find(wszId, m_szModuleName)) + Chat_Terminate(si); + + db_delete_contact(cc); + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +enum +{ + IDM_LEAVE = 1, +}; + +int CSteamProto::GcEventHook(WPARAM, LPARAM lParam) +{ + GCHOOK *gch = (GCHOOK *)lParam; + if (gch == nullptr) + return 0; + + if (mir_strcmpi(gch->si->pszModule, m_szModuleName)) + return 0; + + switch (gch->iType) { + case GC_USER_MESSAGE: + if (gch->ptszText && mir_wstrlen(gch->ptszText) > 0) { + rtrimw(gch->ptszText); + T2Utf szMessage(gch->ptszText); + + CChatRoomSendChatMessageRequest request; + request.chat_group_id = _wtoi64(gch->si->ptszID); request.has_chat_group_id = true; + request.chat_id = getDword(gch->si->hContact, "ChatId"); request.has_chat_id = true; + request.echo_to_sender = request.has_echo_to_sender = true; + request.message = szMessage; + WSSendService(SendChatMessage, request); + } + break; + + case GC_USER_PRIVMESS: + Chat_SendPrivateMessage(gch); + break; + + case GC_USER_LOGMENU: + Chat_LogMenu(gch); + break; + + case GC_USER_NICKLISTMENU: + break; + } + return 0; +} + +void CSteamProto::Chat_SendPrivateMessage(GCHOOK *gch) +{ + uint64_t iSteamId = _wtoi64(gch->ptszUID); + MCONTACT hContact = GetContact(iSteamId); + if (!hContact) { + PROTOSEARCHRESULT psr = { sizeof(psr) }; + psr.id.w = (wchar_t *)gch->ptszUID; + psr.firstName.w = (wchar_t *)gch->ptszNick; + + hContact = AddToList(PALF_TEMPORARY, &psr); + if (hContact == 0) + return; + + setWString(hContact, "Nick", gch->ptszNick); + Contact::Hide(hContact); + db_set_dw(hContact, "Ignore", "Mask1", 0); + } + + CallService(MS_MSG_SENDMESSAGE, hContact, 0); +} + +void CSteamProto::Chat_LogMenu(GCHOOK *gch) +{ + switch (gch->dwData) { + case IDM_LEAVE: + SvcLeaveChat(gch->si->hContact, 0); + break; + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static gc_item sttLogListItems[] = +{ + { LPGENW("&Leave chat session"), IDM_LEAVE, MENU_ITEM } +}; + +int CSteamProto::GcMenuHook(WPARAM, LPARAM lParam) +{ + GCMENUITEMS *gcmi = (GCMENUITEMS *)lParam; + if (gcmi == nullptr) + return 0; + + if (mir_strcmpi(gcmi->pszModule, m_szModuleName)) + return 0; + + if (gcmi->Type == MENU_ON_LOG) { + Chat_AddMenuItems(gcmi->hMenu, _countof(sttLogListItems), sttLogListItems, &g_plugin); + } + else if (gcmi->Type == MENU_ON_NICKLIST) { + } + return 0; +} diff --git a/protocols/Steam/src/steam_login.cpp b/protocols/Steam/src/steam_login.cpp index 1c2c130287..1235130542 100644 --- a/protocols/Steam/src/steam_login.cpp +++ b/protocols/Steam/src/steam_login.cpp @@ -57,7 +57,7 @@ void CSteamProto::Login() CAuthenticationGetPasswordRSAPublicKeyRequest request; request.account_name = username.get(); - WSSendService(GetPasswordRSAPublicKey, request, true); + WSSendAnon(GetPasswordRSAPublicKey, request); } void CSteamProto::OnGotRsaKey(const CAuthenticationGetPasswordRSAPublicKeyResponse &reply, const CMsgProtoBufHeader &hdr) @@ -98,7 +98,7 @@ void CSteamProto::OnGotRsaKey(const CAuthenticationGetPasswordRSAPublicKeyRespon request.platform_type = details.platform_type; request.has_platform_type = true; request.guard_data = machineId; - WSSendService(BeginAuthSessionViaCredentials, request, true); + WSSendAnon(BeginAuthSessionViaCredentials, request); } void CSteamProto::OnBeginSession(const CAuthenticationBeginAuthSessionViaCredentialsResponse &reply, const CMsgProtoBufHeader &hdr) @@ -191,7 +191,7 @@ void CSteamProto::SendConfirmationCode(bool isEmail, const char *pszCode) request.code_type = EAUTH_SESSION_GUARD_TYPE__k_EAuthSessionGuardType_DeviceCode; request.has_code_type = true; request.code = (char*)pszCode; - WSSendService(UpdateAuthSessionWithSteamGuardCode, request, true); + WSSendAnon(UpdateAuthSessionWithSteamGuardCode, request); } void CSteamProto::OnGotConfirmationCode(const CAuthenticationUpdateAuthSessionWithSteamGuardCodeResponse &, const CMsgProtoBufHeader &hdr) @@ -209,7 +209,7 @@ void CSteamProto::SendPollRequest() CAuthenticationPollAuthSessionStatusRequest request; request.client_id = GetId(DBKEY_CLIENT_ID); request.has_client_id = true; request.request_id.data = m_requestId.data(); request.request_id.len = m_requestId.length(); request.has_request_id = true; - WSSendService(PollAuthSessionStatus, request, true); + WSSendAnon(PollAuthSessionStatus, request); } void CSteamProto::OnPollSession(const CAuthenticationPollAuthSessionStatusResponse &reply, const CMsgProtoBufHeader &) @@ -262,7 +262,7 @@ void CSteamProto::OnClientLogon(const CMsgClientLogonResponse &reply, const CMsg ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, m_iStatus = m_iDesiredStatus); SendPersonaStatus(m_iStatus); - SendDeviceListRequest(); + SendGetChatsRequest(); WSSend(EMsg::ClientChatGetFriendMessageHistoryForOfflineMessages, NoResponse()); } diff --git a/protocols/Steam/src/steam_messages.cpp b/protocols/Steam/src/steam_messages.cpp index 8c8cfab442..da65a5b424 100644 --- a/protocols/Steam/src/steam_messages.cpp +++ b/protocols/Steam/src/steam_messages.cpp @@ -1,42 +1,32 @@ #include "stdafx.h" -int64_t CSteamProto::SendFriendMessage(EChatEntryType entry_type, int64_t steamId, const char *pszMessage) +void CSteamProto::SendFriendMessage(EChatEntryType entry_type, int64_t steamId, const char *pszMessage, void *pInfo) { CFriendMessagesSendMessageRequest request; request.chat_entry_type = (int)entry_type; request.has_chat_entry_type = true; request.contains_bbcode = request.has_contains_bbcode = true; request.steamid = steamId; request.has_steamid = true; request.message = (char *)pszMessage; - return WSSendService(FriendSendMessage, request); + WSSendService(FriendSendMessage, request, pInfo); } void CSteamProto::OnMessageSent(const CFriendMessagesSendMessageResponse &reply, const CMsgProtoBufHeader &hdr) { - COwnMessage tmp(0, 0); - { - mir_cslock lck(m_csOwnMessages); - for (auto &it : m_arOwnMessages) - if (it->iSourceId == hdr.jobid_target) { - tmp = *it; - m_arOwnMessages.remove(m_arOwnMessages.indexOf(&it)); - break; - } - } - - if (!tmp.hContact) + auto *pOwn = (COwnMessage*)GetRequestInfo(hdr.jobid_target); + if (pOwn == nullptr) return; if (hdr.failed()) { CMStringW wszMessage(FORMAT, TranslateT("Message sending has failed with error %d"), hdr.eresult); - ProtoBroadcastAck(tmp.hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)tmp.iMessageId, (LPARAM)wszMessage.c_str()); + ProtoBroadcastAck(pOwn->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)pOwn->iMessageId, (LPARAM)wszMessage.c_str()); } else { uint32_t timestamp = (reply.has_server_timestamp) ? reply.server_timestamp : 0; - if (timestamp > getDword(tmp.hContact, DBKEY_LASTMSG)) - setDword(tmp.hContact, DBKEY_LASTMSG, timestamp); + if (timestamp > getDword(pOwn->hContact, DBKEY_LASTMSG)) + setDword(pOwn->hContact, DBKEY_LASTMSG, timestamp); - tmp.timestamp = timestamp; - ProtoBroadcastAck(tmp.hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)tmp.iMessageId, 0); + pOwn->timestamp = timestamp; + ProtoBroadcastAck(pOwn->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)pOwn->iMessageId, 0); } } diff --git a/protocols/Steam/src/steam_proto.cpp b/protocols/Steam/src/steam_proto.cpp index a21247bf90..f8cee175d0 100644 --- a/protocols/Steam/src/steam_proto.cpp +++ b/protocols/Steam/src/steam_proto.cpp @@ -46,13 +46,17 @@ CSteamProto::CSteamProto(const char *protoName, const wchar_t *userName) : nlu.szSettingsModule = m_szModuleName; m_hNetlibUser = Netlib_RegisterUser(&nlu); - debugLogA(__FUNCTION__":Setting protocol / module name to '%s'", m_szModuleName); + // groupchat initialization + GCREGISTER gcr = {}; + gcr.dwFlags = GC_TYPNOTIF | GC_DATABASE; + gcr.ptszDispName = m_tszUserName; + gcr.pszModule = m_szModuleName; + Chat_Register(&gcr); - if (uint32_t iGlobalValue = getDword(DBKEY_LASTMSG)) { - for (auto &cc : AccContacts()) - setDword(cc, DBKEY_LASTMSG, iGlobalValue); - delSetting(DBKEY_LASTMSG); - } + CreateProtoService(PS_LEAVECHAT, &CSteamProto::SvcLeaveChat); + + HookProtoEvent(ME_GC_EVENT, &CSteamProto::GcEventHook); + HookProtoEvent(ME_GC_BUILDMENU, &CSteamProto::GcMenuHook); } CSteamProto::~CSteamProto() @@ -194,7 +198,7 @@ int CSteamProto::SendMsg(MCONTACT hContact, MEVENT, const char *message) m_arOwnMessages.insert(pOwn); } - pOwn->iSourceId = SendFriendMessage(EChatEntryType::ChatMsg, GetId(hContact, DBKEY_STEAM_ID), message); + SendFriendMessage(EChatEntryType::ChatMsg, GetId(hContact, DBKEY_STEAM_ID), message, pOwn); return hMessage; } diff --git a/protocols/Steam/src/steam_proto.h b/protocols/Steam/src/steam_proto.h index 446680db43..63473ecb9b 100644 --- a/protocols/Steam/src/steam_proto.h +++ b/protocols/Steam/src/steam_proto.h @@ -29,6 +29,13 @@ #define FriendGetRecentMessages "FriendMessages.GetRecentMessages#1" #define FriendGetIncomingMessage "FriendMessagesClient.IncomingMessage#1" +#define GetMyChatRoomGroups "ChatRoom.GetMyChatRoomGroups#1" +#define GetChatHistory "ChatRoom.GetMessageHistory#1" +#define SendChatMessage "ChatRoom.SendChatMessage#1" +#define LeaveChatGroup "ChatRoom.LeaveChatRoomGroup#1" + +#define NotifyIncomingChatMessage "ChatRoomClient.NotifyIncomingChatMessage#1" + #define NotificationReceived "SteamNotificationClient.NotificationsReceived#1" struct SendAuthParam @@ -82,7 +89,6 @@ struct COwnMessage int iMessageId, timestamp = 0; MCONTACT hContact; - uint64_t iSourceId = -1; }; class CSteamProto : public PROTO @@ -137,6 +143,12 @@ class CSteamProto : public PROTO // connection WebSocket *m_ws; + + mir_cs m_csRequestLock; + std::map m_requestInfo; + + void SetRequestInfo(uint64_t, void *); + void* GetRequestInfo(uint64_t); void __cdecl ServerThread(void *); bool ServerThreadStub(const char *szHost); @@ -147,8 +159,9 @@ class CSteamProto : public PROTO void WSSend(EMsg msgType, const ProtobufCppMessage &msg); void WSSendRaw(EMsg msgType, const MBinBuffer &buf); + void WSSendAnon(const char *pszServiceName, const ProtobufCppMessage &msg); void WSSendHeader(EMsg msgType, const CMsgProtoBufHeader &hdr, const ProtobufCppMessage &msg); - int64_t WSSendService(const char *pszServiceName, const ProtobufCppMessage &msg, bool bAnon = false); + void WSSendService(const char *pszServiceName, const ProtobufCppMessage &msg, void *pInfo = nullptr); // requests bool SendRequest(HttpRequest *request); @@ -194,6 +207,24 @@ class CSteamProto : public PROTO INT_PTR __cdecl GetAvatarCaps(WPARAM, LPARAM); INT_PTR __cdecl GetMyAvatar(WPARAM, LPARAM); + // chats + void SendGetChatsRequest(); + void OnGetMyChats(const CChatRoomGetMyChatRoomGroupsResponse &pResponse, const CMsgProtoBufHeader &hdr); + + void SendGetChatHistory(MCONTACT hContact, uint32_t iLastMsgId); + void OnGetChatHistory(const CChatRoomGetMessageHistoryResponse &reply, const CMsgProtoBufHeader &hdr); + + void OnGetChatMessage(const CChatRoomIncomingChatMessageNotification &reply, const CMsgProtoBufHeader &hdr); + void OnLeftChat(const CChatRoomLeaveChatRoomGroupResponse &reply, const CMsgProtoBufHeader &hdr); + + INT_PTR __cdecl SvcLeaveChat(WPARAM, LPARAM); + + int __cdecl GcMenuHook(WPARAM, LPARAM); + int __cdecl GcEventHook(WPARAM, LPARAM); + + void Chat_LogMenu(GCHOOK *gch); + void Chat_SendPrivateMessage(GCHOOK *gch); + // contacts void SetAllContactStatuses(int status); void SetContactStatus(MCONTACT hContact, uint16_t status); @@ -262,7 +293,7 @@ class CSteamProto : public PROTO mir_cs m_csOwnMessages; OBJLIST m_arOwnMessages; - int64_t SendFriendMessage(EChatEntryType, int64_t steamId, const char *pszMessage); + void SendFriendMessage(EChatEntryType, int64_t steamId, const char *pszMessage, void *pInfo = nullptr); void OnGotIncomingMessage(const CFriendMessagesIncomingMessageNotification &reply, const CMsgProtoBufHeader &hdr); void OnMessageSent(const CFriendMessagesSendMessageResponse &reply, const CMsgProtoBufHeader &hdr); int __cdecl OnPreCreateMessage(WPARAM, LPARAM lParam); diff --git a/protocols/Steam/src/steam_server.cpp b/protocols/Steam/src/steam_server.cpp index 41a9ca550e..0714e10e78 100644 --- a/protocols/Steam/src/steam_server.cpp +++ b/protocols/Steam/src/steam_server.cpp @@ -73,9 +73,8 @@ void CSteamProto::SendDeviceListRequest() WSSendService(GetOwnAuthorizedDevices, request); } -void CSteamProto::OnGotDeviceList(const CDeviceAuthGetOwnAuthorizedDevicesResponse &pResponse, const CMsgProtoBufHeader &hdr) +void CSteamProto::OnGotDeviceList(const CDeviceAuthGetOwnAuthorizedDevicesResponse &, const CMsgProtoBufHeader &) { - } ///////////////////////////////////////////////////////////////////////////////////////// diff --git a/protocols/Steam/src/steam_ws.cpp b/protocols/Steam/src/steam_ws.cpp index 27d244c45c..41acb5efbb 100644 --- a/protocols/Steam/src/steam_ws.cpp +++ b/protocols/Steam/src/steam_ws.cpp @@ -288,16 +288,47 @@ void CSteamProto::WSSendHeader(EMsg msgType, const CMsgProtoBufHeader &hdr, cons m_ws->sendBinary(hdrbuf.data(), hdrbuf.length()); } -int64_t CSteamProto::WSSendService(const char *pszServiceName, const ProtobufCppMessage &msg, bool bAnon) +void CSteamProto::WSSendAnon(const char *pszServiceName, const ProtobufCppMessage &msg) { CMsgProtoBufHeader hdr; hdr.has_client_sessionid = hdr.has_steamid = hdr.has_jobid_source = hdr.has_jobid_target = true; - if (!bAnon) - hdr.steamid = m_iSteamId, hdr.client_sessionid = m_iSessionId; hdr.jobid_source = getRandomInt(); hdr.jobid_target = -1; hdr.target_job_name = (char *)pszServiceName; - WSSendHeader(bAnon ? EMsg::ServiceMethodCallFromClientNonAuthed : EMsg::ServiceMethodCallFromClient, hdr, msg); + WSSendHeader(EMsg::ServiceMethodCallFromClientNonAuthed, hdr, msg); +} + +void CSteamProto::WSSendService(const char *pszServiceName, const ProtobufCppMessage &msg, void *pInfo) +{ + CMsgProtoBufHeader hdr; + hdr.has_client_sessionid = hdr.has_steamid = hdr.has_jobid_source = hdr.has_jobid_target = true; + hdr.steamid = m_iSteamId, hdr.client_sessionid = m_iSessionId; + hdr.jobid_source = getRandomInt(); + hdr.jobid_target = -1; + hdr.target_job_name = (char *)pszServiceName; + + if (pInfo) + SetRequestInfo(hdr.jobid_source, pInfo); - return hdr.jobid_source; + WSSendHeader(EMsg::ServiceMethodCallFromClient, hdr, msg); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CSteamProto::SetRequestInfo(uint64_t requestId, void *pInfo) +{ + mir_cslock lck(m_csRequestLock); + m_requestInfo[requestId] = pInfo; +} + +void* CSteamProto::GetRequestInfo(uint64_t requestId) +{ + mir_cslock lck(m_csRequestLock); + auto it = m_requestInfo.find(requestId); + if (it == m_requestInfo.end()) + return nullptr; + + void *pRet = it->second; + m_requestInfo.erase(it); + return pRet; } -- cgit v1.2.3