From e7eadee4856f2f3a2d6873712d5f73ce03b11918 Mon Sep 17 00:00:00 2001 From: Alexander Lantsev Date: Mon, 14 Apr 2014 19:49:51 +0000 Subject: Steam: work commit - added joint to game menu item - first approach to contacts management - minor fixes git-svn-id: http://svn.miranda-ng.org/main/trunk@8977 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/Steam/Steam_12.vcxproj | 2 + protocols/Steam/Steam_12.vcxproj.filters | 6 ++ protocols/Steam/src/Steam/friend.h | 24 ++++- protocols/Steam/src/Steam/friend_list.h | 44 ++++++++ protocols/Steam/src/Steam/invitation.h | 77 ++++++++++++++ protocols/Steam/src/Steam/poll.h | 24 +++-- protocols/Steam/src/Steam/steam.h | 10 +- protocols/Steam/src/common.h | 2 + protocols/Steam/src/stdafx.cpp | 4 + protocols/Steam/src/steam_account.cpp | 4 +- protocols/Steam/src/steam_avatars.cpp | 6 +- protocols/Steam/src/steam_contacts.cpp | 173 +++++++++++++++++++++++-------- protocols/Steam/src/steam_events.cpp | 2 + protocols/Steam/src/steam_menus.cpp | 78 ++++++++++++++ protocols/Steam/src/steam_proto.cpp | 40 ++++--- protocols/Steam/src/steam_proto.h | 40 ++++++- protocols/Steam/src/steam_thread.cpp | 27 +++-- protocols/Steam/src/steam_utils.cpp | 13 +++ 18 files changed, 482 insertions(+), 94 deletions(-) create mode 100644 protocols/Steam/src/Steam/invitation.h create mode 100644 protocols/Steam/src/steam_menus.cpp (limited to 'protocols/Steam') diff --git a/protocols/Steam/Steam_12.vcxproj b/protocols/Steam/Steam_12.vcxproj index 6cf599dbfa..e62e575c30 100644 --- a/protocols/Steam/Steam_12.vcxproj +++ b/protocols/Steam/Steam_12.vcxproj @@ -199,6 +199,7 @@ + @@ -214,6 +215,7 @@ + diff --git a/protocols/Steam/Steam_12.vcxproj.filters b/protocols/Steam/Steam_12.vcxproj.filters index e928166046..ee476ff7c2 100644 --- a/protocols/Steam/Steam_12.vcxproj.filters +++ b/protocols/Steam/Steam_12.vcxproj.filters @@ -51,6 +51,9 @@ Source Files + + Source Files + @@ -95,6 +98,9 @@ Header Files + + Header Files\Steam + diff --git a/protocols/Steam/src/Steam/friend.h b/protocols/Steam/src/Steam/friend.h index 9be555a914..3707204734 100644 --- a/protocols/Steam/src/Steam/friend.h +++ b/protocols/Steam/src/Steam/friend.h @@ -30,8 +30,8 @@ namespace SteamWebApi Summary() : gameId(0), created(0), lastEvent(0) { } const char *GetSteamId() const { return steamId.c_str(); } - const wchar_t *GetNickname() const { return nickname.c_str(); } - const wchar_t *GetRealname() const { return realname.c_str(); } + const wchar_t *GetNickName() const { return nickname.c_str(); } + const wchar_t *GetRealName() const { return realname.c_str(); } const char *GetCountryCode() const { return countryCode.c_str(); } const char *GetHomepage() const { return homepage.c_str(); } const char *GetAvatarUrl() const { return avatarUrl.c_str(); } @@ -40,6 +40,26 @@ namespace SteamWebApi int GetState() const { return state; } const DWORD GetCreated() const { return created; } const DWORD GetLastEvent() const { return lastEvent; } + + const wchar_t *GetFirstName() const + { + size_t pos = realname.find(' ', 1); + if (pos > 0) + return realname.substr(0, pos - 1).c_str(); + + return realname.c_str(); + } + + const wchar_t *GetLastName() const + { + size_t pos = realname.find(' ', 1); + if (pos > 0) + { + return realname.substr(pos + 1).c_str(); + } + + return L""; + } }; struct Summaries : public Result diff --git a/protocols/Steam/src/Steam/friend_list.h b/protocols/Steam/src/Steam/friend_list.h index 2b283cc0de..e68e0b1d39 100644 --- a/protocols/Steam/src/Steam/friend_list.h +++ b/protocols/Steam/src/Steam/friend_list.h @@ -53,6 +53,50 @@ namespace SteamWebApi friendList->success = true; } + + static void AddFriend(HANDLE hConnection, const char *sessionId, const char *steamId, Result *result) + { + result->success = false; + + char data[128]; + mir_snprintf(data, SIZEOF(data), + "steamid=%s&sessionID=%s", + sessionId, + steamId); + + SecureHttpPostRequest request(hConnection, STEAM_COM_URL "/actions/AddFriendAjax"); + + mir_ptr response(request.Send()); + if (!response) + return; + + if ((result->status = (HTTP_STATUS)response->resultCode) != HTTP_STATUS_OK) + return; + + result->success = true; + } + + static void RemoveFriend(HANDLE hConnection, const char *sessionId, const char *steamId, Result *result) + { + result->success = false; + + char data[128]; + mir_snprintf(data, SIZEOF(data), + "steamid=%s&sessionID=%s", + sessionId, + steamId); + + SecureHttpPostRequest request(hConnection, STEAM_COM_URL "/actions/RemoveFriendAjax"); + + mir_ptr response(request.Send()); + if (!response) + return; + + if ((result->status = (HTTP_STATUS)response->resultCode) != HTTP_STATUS_OK) + return; + + result->success = true; + } }; } diff --git a/protocols/Steam/src/Steam/invitation.h b/protocols/Steam/src/Steam/invitation.h new file mode 100644 index 0000000000..23386e1267 --- /dev/null +++ b/protocols/Steam/src/Steam/invitation.h @@ -0,0 +1,77 @@ +#ifndef _STEAM_INVITATION_H_ +#define _STEAM_INVITATION_H_ + +namespace SteamWebApi +{ + class InvitationApi : public BaseApi + { + public: + static void Accept(HANDLE hConnection, const char *sessionId, const char *steamId, const char *who, Result *result) + { + result->success = false; + + char url[MAX_PATH]; + mir_snprintf(url, SIZEOF(url), "%s/profiles/%s/home_process", STEAM_COM_URL, steamId); + + char data[MAX_PATH]; + mir_snprintf(data, SIZEOF(data), "sessionID=%&id=%s&perform=accept&action=approvePending&itype=friend&json=1&xml=0", sessionId, who); + + SecureHttpPostRequest request(hConnection, url); + + mir_ptr response(request.Send()); + if (!response) + return; + + if ((result->status = (HTTP_STATUS)response->resultCode) != HTTP_STATUS_OK) + return; + + result->success = true; + } + + static void Ignore(HANDLE hConnection, const char *sessionId, const char *steamId, const char *who, Result *result) + { + result->success = false; + + char url[MAX_PATH]; + mir_snprintf(url, SIZEOF(url), "%s/profiles/%s/home_process", STEAM_COM_URL, steamId); + + char data[MAX_PATH]; + mir_snprintf(data, SIZEOF(data), "sessionID=%&id=%s&perform=ignore&action=approvePending&itype=friend&json=1&xml=0", sessionId, who); + + SecureHttpPostRequest request(hConnection, url); + + mir_ptr response(request.Send()); + if (!response) + return; + + if ((result->status = (HTTP_STATUS)response->resultCode) != HTTP_STATUS_OK) + return; + + result->success = true; + } + + static void Block(HANDLE hConnection, const char *sessionId, const char *steamId, const char *who, Result *result) + { + result->success = false; + + char url[MAX_PATH]; + mir_snprintf(url, SIZEOF(url), "%s/profiles/%s/home_process", STEAM_COM_URL, steamId); + + char data[MAX_PATH]; + mir_snprintf(data, SIZEOF(data), "sessionID=%&id=%s&perform=block&action=approvePending&itype=friend&json=1&xml=0", sessionId, who); + + SecureHttpPostRequest request(hConnection, url); + + mir_ptr response(request.Send()); + if (!response) + return; + + if ((result->status = (HTTP_STATUS)response->resultCode) != HTTP_STATUS_OK) + return; + + result->success = true; + } + }; +} + +#endif //_STEAM_INVITATION_H_ \ No newline at end of file diff --git a/protocols/Steam/src/Steam/poll.h b/protocols/Steam/src/Steam/poll.h index 312f7336e6..ba7a8927ca 100644 --- a/protocols/Steam/src/Steam/poll.h +++ b/protocols/Steam/src/Steam/poll.h @@ -13,9 +13,11 @@ namespace SteamWebApi POOL_TYPE_MYMESSAGE, POOL_TYPE_TYPING, POOL_TYPE_STATE, - POOL_TYPE_CONTACT_AUTH, - POOL_TYPE_CONTACT_ADDED, - POOL_TYPE_CONTACT_DELETED, + POOL_TYPE_CONTACT_REQUEST, + //POOL_TYPE_CONTACT_REQUESTED, + POOL_TYPE_CONTACT_ADD, + POOL_TYPE_CONTACT_IGNORE, + POOL_TYPE_CONTACT_REMOVE, }; class PoolItem// : public Result @@ -182,20 +184,26 @@ namespace SteamWebApi int state = json_as_int(node); if (state == 0) { - // contact was removed - crs->type = POOL_TYPE_CONTACT_DELETED; - + // removed + crs->type = POOL_TYPE_CONTACT_REMOVE; + } + + else if (state == 1) + { + // ignored + crs->type = POOL_TYPE_CONTACT_IGNORE; } else if (state == 2) { // auth request - crs->type = POOL_TYPE_CONTACT_AUTH; + crs->type = POOL_TYPE_CONTACT_REQUEST; } else if (state == 3) { // add to list - crs->type = POOL_TYPE_CONTACT_ADDED; + crs->type = POOL_TYPE_CONTACT_ADD; } + else continue; } /*else if (!lstrcmpi(type, L"leftconversation")) { diff --git a/protocols/Steam/src/Steam/steam.h b/protocols/Steam/src/Steam/steam.h index 603fc877fa..52de0e5441 100644 --- a/protocols/Steam/src/Steam/steam.h +++ b/protocols/Steam/src/Steam/steam.h @@ -6,16 +6,17 @@ namespace SteamWebApi #define STEAM_API_URL "https://api.steampowered.com" #define STEAM_COM_URL "https://steamcommunity.com" - struct Result - { - bool success; - }; + class FriendListApi; + class InvitationApi; class BaseApi { public: class Result { + friend FriendListApi; + friend InvitationApi; + protected: bool success; HTTP_STATUS status; @@ -33,6 +34,7 @@ namespace SteamWebApi #include "Steam\authorization.h" #include "Steam\login.h" #include "Steam\friend_list.h" +#include "Steam\invitation.h" #include "Steam\friend.h" #include "Steam\poll.h" #include "Steam\message.h" diff --git a/protocols/Steam/src/common.h b/protocols/Steam/src/common.h index 436d48239d..fe724a4f93 100644 --- a/protocols/Steam/src/common.h +++ b/protocols/Steam/src/common.h @@ -2,6 +2,7 @@ #define _COMMON_H_ #include +#include #include #include @@ -14,6 +15,7 @@ #include #include #include +#include #include #include #include diff --git a/protocols/Steam/src/stdafx.cpp b/protocols/Steam/src/stdafx.cpp index d3d389fe4d..d51a866ca3 100644 --- a/protocols/Steam/src/stdafx.cpp +++ b/protocols/Steam/src/stdafx.cpp @@ -43,6 +43,8 @@ extern "C" int __declspec(dllexport) Load(void) pd.fnUninit = (pfnUninitProto)CSteamProto::UninitProtoInstance; CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd); + CSteamProto::InitMenus(); + return 0; } @@ -50,5 +52,7 @@ extern "C" int __declspec(dllexport) Unload(void) { CSteamProto::UninitProtoInstances(); + CSteamProto::UninitMenus(); + return 0; } \ No newline at end of file diff --git a/protocols/Steam/src/steam_account.cpp b/protocols/Steam/src/steam_account.cpp index 8e72904583..a12ae85667 100644 --- a/protocols/Steam/src/steam_account.cpp +++ b/protocols/Steam/src/steam_account.cpp @@ -123,7 +123,7 @@ void CSteamProto::Authorize(SteamWebApi::AuthorizationApi::AuthResult *authResul void CSteamProto::LogInThread(void* param) { - while (m_bTerminated && m_hPollingThread != NULL) + while (m_bTerminated || m_hPollingThread != NULL) Sleep(500); ptrA token(getStringA("TokenSecret")); @@ -134,7 +134,7 @@ void CSteamProto::LogInThread(void* param) // if some error if (!authResult.IsSuccess()) { - // todo: dosplay error message from authResult.GetMessage() + // todo: display error message from authResult.GetMessage() //ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_BADUSERID); debugLogA("CSteamProto::LogInThread: Authorization error (%s)", authResult.GetMessage()); diff --git a/protocols/Steam/src/steam_avatars.cpp b/protocols/Steam/src/steam_avatars.cpp index 45ee6b80fe..b009e1c32d 100644 --- a/protocols/Steam/src/steam_avatars.cpp +++ b/protocols/Steam/src/steam_avatars.cpp @@ -99,8 +99,4 @@ INT_PTR CSteamProto::GetMyAvatar(WPARAM wParam, LPARAM lParam) } return -1; -} - -//INT_PTR CSteamProto::SetMyAvatar(WPARAM wParam, LPARAM lParam) -//{ -//} \ No newline at end of file +} \ No newline at end of file diff --git a/protocols/Steam/src/steam_contacts.cpp b/protocols/Steam/src/steam_contacts.cpp index 03969ad2ff..0bf050d18d 100644 --- a/protocols/Steam/src/steam_contacts.cpp +++ b/protocols/Steam/src/steam_contacts.cpp @@ -18,6 +18,25 @@ void CSteamProto::SetAllContactsStatus(WORD status) } } +MCONTACT CSteamProto::GetContactFromAuthEvent(HANDLE hEvent) +{ + DWORD body[3]; + DBEVENTINFO dbei = { sizeof(DBEVENTINFO) }; + dbei.cbBlob = sizeof(DWORD)* 2; + dbei.pBlob = (PBYTE)&body; + + if (db_event_get(hEvent, &dbei)) + return INVALID_CONTACT_ID; + + if (dbei.eventType != EVENTTYPE_AUTHREQUEST) + return INVALID_CONTACT_ID; + + if (strcmp(dbei.szModule, m_szModuleName) != 0) + return INVALID_CONTACT_ID; + + return DbGetAuthEventContact(&dbei); +} + MCONTACT CSteamProto::FindContact(const char *steamId) { MCONTACT hContact = NULL; @@ -43,7 +62,7 @@ void CSteamProto::UpdateContact(MCONTACT hContact, const SteamWebApi::FriendApi: return; // set common data - setWString(hContact, "Nick", contact->GetNickname()); + setWString(hContact, "Nick", contact->GetNickName()); setString(hContact, "Homepage", contact->GetHomepage()); // only for contacts if (hContact) @@ -70,19 +89,17 @@ void CSteamProto::UpdateContact(MCONTACT hContact, const SteamWebApi::FriendApi: } // set name - ptrW realname(mir_wstrdup(contact->GetRealname())); - const wchar_t *p = wcschr(realname, ' '); - if (p == NULL) + const wchar_t *firstName = contact->GetFirstName(); + const wchar_t *lastName = contact->GetLastName(); + if (lstrlen(lastName) == 0) { - setWString(hContact, "FirstName", realname); + setWString(hContact, "FirstName", firstName); delSetting(hContact, "LastName"); } else { - int length = p - (wchar_t*)realname; - realname[length] = '\0'; - setWString(hContact, "FirstName", realname); - setWString(hContact, "LastName", p + 1); + setWString(hContact, "FirstName", firstName); + setWString(hContact, "LastName", lastName); } // avatar @@ -147,9 +164,10 @@ void CSteamProto::UpdateContactsThread(void *arg) MCONTACT hContact = NULL; if (!IsMe(contact->GetSteamId())) { - hContact = this->FindContact(contact->GetSteamId()); + const char *steamId = contact->GetSteamId(); + hContact = this->FindContact(steamId); if (hContact == NULL) - hContact = AddContact(contact); + hContact = AddContact(steamId); if (hContact == NULL) return; } @@ -158,16 +176,16 @@ void CSteamProto::UpdateContactsThread(void *arg) } } -MCONTACT CSteamProto::AddContact(const SteamWebApi::FriendApi::Summary *contact) +MCONTACT CSteamProto::AddContact(const char *steamId) { - MCONTACT hContact = this->FindContact(contact->GetSteamId()); + MCONTACT hContact = this->FindContact(steamId); if (!hContact) { // create contact hContact = (MCONTACT)CallService(MS_DB_CONTACT_ADD, 0, 0); CallService(MS_PROTO_ADDTOCONTACT, hContact, (LPARAM)this->m_szModuleName); - setString(hContact, "SteamID", contact->GetSteamId()); + setString(hContact, "SteamID", steamId); // update info //UpdateContact(hContact, contact); @@ -184,6 +202,97 @@ MCONTACT CSteamProto::AddContact(const SteamWebApi::FriendApi::Summary *contact) return hContact; } +void CSteamProto::RaiseAuthRequestThread(void *arg) +{ + ptrA steamId((char*)arg); + ptrA token(getStringA("TokenSecret")); + + MCONTACT hContact = FindContact(steamId); + if (!hContact) + hContact = AddContact(steamId); + + SteamWebApi::FriendApi::Summaries summaries; + debugLogA("CSteamProto::LoadContactListThread: call SteamWebApi::FriendApi::LoadSummaries"); + SteamWebApi::FriendApi::LoadSummaries(m_hNetlibUser, token, steamId, &summaries); + + if (summaries.IsSuccess()) + { + const SteamWebApi::FriendApi::Summary *contact = summaries.GetAt(0); + + char *nickName = mir_utf8encodeW(contact->GetNickName()); + char *firstName = mir_utf8encodeW(contact->GetFirstName()); + char *lastName = mir_utf8encodeW(contact->GetLastName()); + char reason[MAX_PATH]; + mir_snprintf(reason, SIZEOF(reason), Translate("%s has added you to his or her Friend List"), nickName); + + // blob is: 0(DWORD), hContact(DWORD), nick(ASCIIZ), firstName(ASCIIZ), lastName(ASCIIZ), sid(ASCIIZ), reason(ASCIIZ) + DWORD cbBlob = (DWORD)(sizeof(DWORD)* 2 + strlen(nickName) + strlen(firstName) + strlen(lastName) + strlen(steamId) + strlen(reason) + 5); + + PBYTE pBlob, pCurBlob; + pCurBlob = pBlob = (PBYTE)mir_alloc(cbBlob); + + *((PDWORD)pCurBlob) = 0; + pCurBlob += sizeof(DWORD); + *((PDWORD)pCurBlob) = (DWORD)hContact; + pCurBlob += sizeof(DWORD); + strcpy((char*)pCurBlob, nickName); + pCurBlob += strlen(nickName) + 1; + strcpy((char*)pCurBlob, firstName); + pCurBlob += strlen(firstName) + 1; + strcpy((char*)pCurBlob, lastName); + pCurBlob += strlen(lastName) + 1; + strcpy((char*)pCurBlob, steamId); + pCurBlob += strlen(steamId) + 1; + strcpy((char*)pCurBlob, mir_strdup(reason)); + + AddDBEvent(hContact, EVENTTYPE_AUTHREQUEST, time(NULL), DBEF_UTF, cbBlob, pBlob); + } +} + +void CSteamProto::AuthAllowThread(void *arg) +{ + MCONTACT hContact = (MCONTACT)arg; + if (!hContact) + return; + + ptrA sessionId(getStringA("SessionID")); + ptrA steamId(getStringA("SteamID")); + ptrA who(getStringA(hContact, "SteamID")); + + SteamWebApi::InvitationApi::Result result; + debugLogA("CSteamProto::AuthAllowThread: call SteamWebApi::InvitationApi::Accept"); + SteamWebApi::InvitationApi::Accept(m_hNetlibUser, sessionId, steamId, who, &result); + + if (result.IsSuccess()) + { + delSetting(hContact, "Auth"); + delSetting(hContact, "Grant"); + } +} + +void CSteamProto::AuthDenyThread(void *arg) +{ + MCONTACT hContact = (MCONTACT)arg; + if (!hContact) + return; + + ptrA sessionId(getStringA("SessionID")); + ptrA steamId(getStringA("SteamID")); + ptrA who(getStringA(hContact, "SteamID")); + + SteamWebApi::InvitationApi::Result result; + debugLogA("CSteamProto::AuthDenyThread: call SteamWebApi::InvitationApi::Ignore"); + SteamWebApi::InvitationApi::Ignore(m_hNetlibUser, sessionId, steamId, who, &result); +} + +void CSteamProto::AddContactThread(void *arg) +{ +} + +void CSteamProto::RemoveContactThread(void *arg) +{ +} + void CSteamProto::LoadContactListThread(void*) { ptrA token(getStringA("TokenSecret")); @@ -219,7 +328,7 @@ void CSteamProto::LoadContactListThread(void*) for (size_t i = 0; i < summaries.GetItemCount(); i++) { const SteamWebApi::FriendApi::Summary *summary = summaries.GetAt(i); - MCONTACT hContact = AddContact(summary); + MCONTACT hContact = AddContact(summary->GetSteamId()); if (hContact) UpdateContact(hContact, summary); } @@ -255,20 +364,9 @@ void CSteamProto::SearchByIdThread(void* arg) ssr.hdr.flags = PSR_TCHAR; ssr.hdr.id = mir_wstrdup(steamIdW); - ssr.hdr.nick = mir_wstrdup(contact->GetNickname()); - - const wchar_t *realname = contact->GetRealname(); - const wchar_t *p = wcschr(realname, ' '); - if (p == NULL) - ssr.hdr.firstName = mir_wstrdup(realname); - else - { - int length = p - realname; - ssr.hdr.firstName = (wchar_t*)mir_alloc(sizeof(wchar_t) * (length + 1)); - wmemcpy(ssr.hdr.firstName, realname, length); - ssr.hdr.firstName[length] = '\0'; - ssr.hdr.lastName = mir_wstrdup(p + 1); - } + ssr.hdr.nick = mir_wstrdup(contact->GetNickName()); + ssr.hdr.firstName = mir_wstrdup(contact->GetFirstName()); + ssr.hdr.lastName = mir_wstrdup(contact->GetLastName()); ssr.contact = contact; @@ -322,20 +420,9 @@ void CSteamProto::SearchByNameThread(void* arg) ssr.hdr.flags = PSR_TCHAR; ssr.hdr.id = mir_a2u(contact->GetSteamId()); - ssr.hdr.nick = mir_wstrdup(contact->GetNickname()); - - const wchar_t *realname = contact->GetRealname(); - const wchar_t *p = wcschr(realname, ' '); - if (p == NULL) - ssr.hdr.firstName = mir_wstrdup(realname); - else - { - int length = p - realname; - ssr.hdr.firstName = (wchar_t*)mir_alloc(sizeof(wchar_t) * (length + 1)); - wmemcpy(ssr.hdr.firstName, realname, length); - ssr.hdr.firstName[length] = '\0'; - ssr.hdr.lastName = mir_wstrdup(p + 1); - } + ssr.hdr.nick = mir_wstrdup(contact->GetNickName()); + ssr.hdr.firstName = mir_wstrdup(contact->GetFirstName()); + ssr.hdr.lastName = mir_wstrdup(contact->GetLastName()); ssr.contact = contact; diff --git a/protocols/Steam/src/steam_events.cpp b/protocols/Steam/src/steam_events.cpp index 27e63951b7..2d6daf07d3 100644 --- a/protocols/Steam/src/steam_events.cpp +++ b/protocols/Steam/src/steam_events.cpp @@ -13,6 +13,8 @@ int CSteamProto::OnModulesLoaded(WPARAM, LPARAM) nlu.szSettingsModule = m_szModuleName; m_hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu); + HookEvent(ME_CLIST_PREBUILDCONTACTMENU, &CSteamProto::PrebuildContactMenu); + return 0; } diff --git a/protocols/Steam/src/steam_menus.cpp b/protocols/Steam/src/steam_menus.cpp new file mode 100644 index 0000000000..9ce56ec84c --- /dev/null +++ b/protocols/Steam/src/steam_menus.cpp @@ -0,0 +1,78 @@ +#include "common.h" + +HANDLE CSteamProto::hChooserMenu; +HGENMENU CSteamProto::contactMenuItems[CMI_MAX]; + +template +INT_PTR GlobalService(WPARAM wParam, LPARAM lParam) +{ + CSteamProto *ppro = CSteamProto::GetContactProtoInstance((MCONTACT)wParam); + return ppro ? (ppro->*Service)(wParam, lParam) : 0; +} + +INT_PTR CSteamProto::MenuChooseService(WPARAM wParam, LPARAM lParam) +{ + if (lParam) + *(void**)lParam = (void*)wParam; + + return 0; +} + +int CSteamProto::JoinToGameCommand(WPARAM hContact, LPARAM) +{ + char url[MAX_PATH]; + DWORD gameId = getDword(hContact, "GameID", 0); + mir_snprintf(url, SIZEOF(url), "steam://rungameid/%lu", gameId); + CallService(MS_UTILS_OPENURL, 0, (LPARAM)url); + + return 0; +} + +int CSteamProto::OnPrebuildContactMenu(WPARAM wParam, LPARAM) +{ + MCONTACT hContact = (MCONTACT)wParam; + if (!hContact) + return 0; + + if (!this->IsOnline() || lstrcmpA(GetContactProto(hContact), m_szModuleName)) + return 0; + + //bool ctrlPressed = (GetKeyState(VK_CONTROL) & 0x8000) != 0; + DWORD gameId = getDword(hContact, "GameID", 0); + Menu_ShowItem(contactMenuItems[CMI_JOIN_GAME], gameId > 0); + + return 0; +} + +int CSteamProto::PrebuildContactMenu(WPARAM wParam, LPARAM lParam) +{ + for (int i = 0; i < SIZEOF(CSteamProto::contactMenuItems); i++) + Menu_ShowItem(CSteamProto::contactMenuItems[i], false); + + CSteamProto* ppro = CSteamProto::GetContactProtoInstance((MCONTACT)wParam); + return (ppro) ? ppro->OnPrebuildContactMenu(wParam, lParam) : 0; +} + +void CSteamProto::InitMenus() +{ + hChooserMenu = MO_CreateMenuObject("SkypeAccountChooser", LPGEN("Steam menu chooser"), 0, "Steam/MenuChoose"); + + ////////////////////////////////////////////////////////////////////////////////////// + // Contact menu initialization + CLISTMENUITEM mi = { 0 }; + mi.cbSize = sizeof(CLISTMENUITEM); + mi.flags = CMIF_TCHAR | CMIF_NOTOFFLINE; + + // "Join to game" + mi.pszService = MODULE"/JoinToGame"; + mi.ptszName = LPGENT("Join to game"); + mi.position = -200001000 + CMI_JOIN_GAME; + //mi.icolibItem = CSkypeProto::GetSkinIconHandle("block"); + contactMenuItems[CMI_JOIN_GAME] = Menu_AddContactMenuItem(&mi); + CreateServiceFunction(mi.pszService, GlobalService<&CSteamProto::JoinToGameCommand>); +} + +void CSteamProto::UninitMenus() +{ + CallService(MS_CLIST_REMOVETRAYMENUITEM, (WPARAM)contactMenuItems[CMI_JOIN_GAME], 0); +} \ No newline at end of file diff --git a/protocols/Steam/src/steam_proto.cpp b/protocols/Steam/src/steam_proto.cpp index f30d47a59b..ee535cea99 100644 --- a/protocols/Steam/src/steam_proto.cpp +++ b/protocols/Steam/src/steam_proto.cpp @@ -30,11 +30,12 @@ CSteamProto::CSteamProto(const char* protoName, const TCHAR* userName) : SetAllContactsStatus(ID_STATUS_OFFLINE); - // Avatar API - this->CreateProtoService(PS_GETAVATARINFOT, &CSteamProto::GetAvatarInfo); - this->CreateProtoService(PS_GETAVATARCAPS, &CSteamProto::GetAvatarCaps); - this->CreateProtoService(PS_GETMYAVATART, &CSteamProto::GetMyAvatar); - //this->CreateProtoService(PS_SETMYAVATART, &CSteamProto::SetMyAvatar); + // services + CreateServiceFunction(MODULE"/MenuChoose", CSteamProto::MenuChooseService); + // avatar API + CreateProtoService(PS_GETAVATARINFOT, &CSteamProto::GetAvatarInfo); + CreateProtoService(PS_GETAVATARCAPS, &CSteamProto::GetAvatarCaps); + CreateProtoService(PS_GETMYAVATART, &CSteamProto::GetMyAvatar); } CSteamProto::~CSteamProto() @@ -48,7 +49,9 @@ MCONTACT __cdecl CSteamProto::AddToList(int flags, PROTOSEARCHRESULT* psr) return 0; STEAM_SEARCH_RESULT *ssr = (STEAM_SEARCH_RESULT*)psr; - return AddContact(ssr->contact); + MCONTACT hContact = AddContact(ssr->contact->GetSteamId()); + UpdateContact(hContact, ssr->contact); + return hContact; } MCONTACT __cdecl CSteamProto::AddToListByEvent(int flags, int iContact, HANDLE hDbEvent) @@ -58,7 +61,18 @@ MCONTACT __cdecl CSteamProto::AddToListByEvent(int flags, int iContact, HANDLE h int __cdecl CSteamProto::Authorize(HANDLE hDbEvent) { - return 0; + if (IsOnline() && hDbEvent) + { + MCONTACT hContact = GetContactFromAuthEvent(hDbEvent); + if (hContact == INVALID_CONTACT_ID) + return 1; + + ForkThread(&CSteamProto::AuthAllowThread, (void*)hContact); + // todo: how to return real status? + return 0; + } + + return 1; } int __cdecl CSteamProto::AuthDeny(HANDLE hDbEvent, const TCHAR* szReason) @@ -105,7 +119,7 @@ DWORD_PTR __cdecl CSteamProto:: GetCaps(int type, MCONTACT hContact) case PFLAGNUM_2: return PF2_ONLINE; case PFLAGNUM_4: - return PF4_AVATARS; + return PF4_NOCUSTOMAUTH | PF4_AVATARS | PF4_NOAUTHDENYREASON; case PFLAGNUM_5: return PF2_SHORTAWAY | PF2_HEAVYDND | PF2_OUTTOLUNCH; case PFLAG_UNIQUEIDTEXT: @@ -166,15 +180,7 @@ int __cdecl CSteamProto::RecvFile(MCONTACT hContact, PROTORECVFILET* pre) int __cdecl CSteamProto::RecvMsg(MCONTACT hContact, PROTORECVEVENT* pre) { - DBEVENTINFO dbei = { sizeof(dbei) }; - dbei.szModule = this->m_szModuleName; - dbei.timestamp = pre->timestamp; - dbei.eventType = EVENTTYPE_MESSAGE; - dbei.cbBlob = lstrlenA(pre->szMessage); - dbei.pBlob = (BYTE*)pre->szMessage; - dbei.flags = DBEF_UTF; - - return (INT_PTR)db_event_add(hContact, &dbei); + return (INT_PTR)AddDBEvent(hContact, EVENTTYPE_MESSAGE, time(NULL), DBEF_UTF, lstrlenA(pre->szMessage), (BYTE*)pre->szMessage); } int __cdecl CSteamProto::RecvUrl(MCONTACT hContact, PROTORECVEVENT *) { return 0; } diff --git a/protocols/Steam/src/steam_proto.h b/protocols/Steam/src/steam_proto.h index bc7336dc87..5996d248ba 100644 --- a/protocols/Steam/src/steam_proto.h +++ b/protocols/Steam/src/steam_proto.h @@ -30,6 +30,16 @@ struct STEAM_SEARCH_RESULT const SteamWebApi::FriendApi::Summary *contact; }; +enum +{ + //CMI_AUTH_REQUEST, + //CMI_AUTH_GRANT, + //CMI_AUTH_REVOKE, + //CMI_BLOCK, + CMI_JOIN_GAME, + CMI_MAX // this item shall be the last one +}; + class CSteamProto : public PROTO { @@ -89,6 +99,10 @@ public: static CSteamProto* GetContactProtoInstance(MCONTACT hContact); static void UninitProtoInstances(); + // menus + static void InitMenus(); + static void UninitMenus(); + protected: bool m_bTerminated; HANDLE m_hPollingThread; @@ -116,11 +130,20 @@ protected: void SetContactStatus(MCONTACT hContact, WORD status); void SetAllContactsStatus(WORD status); + MCONTACT GetContactFromAuthEvent(HANDLE hEvent); + void UpdateContact(MCONTACT hContact, const SteamWebApi::FriendApi::Summary *contact); void __cdecl UpdateContactsThread(void*); MCONTACT FindContact(const char *steamId); - MCONTACT AddContact(const SteamWebApi::FriendApi::Summary *contact); + MCONTACT AddContact(const char *steamId); + + void __cdecl RaiseAuthRequestThread(void*); + void __cdecl AuthAllowThread(void*); + void __cdecl AuthDenyThread(void*); + + void __cdecl AddContactThread(void*); + void __cdecl RemoveContactThread(void*); void __cdecl LoadContactListThread(void*); @@ -131,13 +154,24 @@ protected: void __cdecl SendMessageThread(void*); void __cdecl SendTypingThread(void*); + // menus + HGENMENU m_hMenuRoot; + static HANDLE hChooserMenu; + static HGENMENU contactMenuItems[CMI_MAX]; + + int __cdecl JoinToGameCommand(WPARAM, LPARAM); + + static INT_PTR MenuChooseService(WPARAM wParam, LPARAM lParam); + + static int PrebuildContactMenu(WPARAM wParam, LPARAM lParam); + int OnPrebuildContactMenu(WPARAM wParam, LPARAM); + // avatars wchar_t * GetAvatarFilePath(MCONTACT hContact); INT_PTR __cdecl GetAvatarInfo(WPARAM, LPARAM); INT_PTR __cdecl GetAvatarCaps(WPARAM, LPARAM); INT_PTR __cdecl GetMyAvatar(WPARAM, LPARAM); - INT_PTR __cdecl SetMyAvatar(WPARAM, LPARAM); //events int OnModulesLoaded(WPARAM, LPARAM); @@ -151,6 +185,8 @@ protected: static int RsaEncrypt(const SteamWebApi::RsaKeyApi::RsaKey &rsaKey, const char *data, DWORD dataSize, BYTE *encrypted, DWORD &encryptedSize); + HANDLE AddDBEvent(MCONTACT hContact, WORD type, DWORD timestamp, DWORD flags, DWORD cbBlob, PBYTE pBlob); + // options static INT_PTR CALLBACK GuardProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); static INT_PTR CALLBACK CaptchaProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); diff --git a/protocols/Steam/src/steam_thread.cpp b/protocols/Steam/src/steam_thread.cpp index 970cbcd628..e95af473dd 100644 --- a/protocols/Steam/src/steam_thread.cpp +++ b/protocols/Steam/src/steam_thread.cpp @@ -45,15 +45,7 @@ void CSteamProto::PollServer(const char *token, const char *sessionId, UINT32 me { const wchar_t *text = message->GetText(); - DBEVENTINFO dbei = { sizeof(dbei) }; - dbei.szModule = this->m_szModuleName; - dbei.timestamp = message->GetTimestamp(); - dbei.eventType = EVENTTYPE_MESSAGE; - dbei.cbBlob = lstrlen(text); - dbei.pBlob = (BYTE*)mir_utf8encodeW(text); - dbei.flags = DBEF_UTF | DBEF_SENT; - - db_event_add(hContact, &dbei); + AddDBEvent(hContact, EVENTTYPE_MESSAGE, time(NULL), DBEF_UTF | DBEF_SENT, lstrlen(text), (BYTE*)mir_utf8encodeW(text)); } } break; @@ -93,7 +85,7 @@ void CSteamProto::PollServer(const char *token, const char *sessionId, UINT32 me } break; - case SteamWebApi::PollApi::POOL_TYPE_CONTACT_ADDED: + case SteamWebApi::PollApi::POOL_TYPE_CONTACT_ADD: { SteamWebApi::PollApi::Relationship *crs = (SteamWebApi::PollApi::Relationship*)item; @@ -105,7 +97,7 @@ void CSteamProto::PollServer(const char *token, const char *sessionId, UINT32 me } break; - case SteamWebApi::PollApi::POOL_TYPE_CONTACT_DELETED: + case SteamWebApi::PollApi::POOL_TYPE_CONTACT_REMOVE: { SteamWebApi::PollApi::Relationship *crs = (SteamWebApi::PollApi::Relationship*)item; @@ -115,6 +107,19 @@ void CSteamProto::PollServer(const char *token, const char *sessionId, UINT32 me CallService(MS_DB_CONTACT_DELETE, hContact, 0); } break; + + case SteamWebApi::PollApi::POOL_TYPE_CONTACT_REQUEST: + { + SteamWebApi::PollApi::Relationship *crs = (SteamWebApi::PollApi::Relationship*)item; + + const char *steamId = crs->GetSteamId(); + MCONTACT hContact = FindContact(steamId); + if (!hContact) + hContact = AddContact(steamId); + + + } + break; } } diff --git a/protocols/Steam/src/steam_utils.cpp b/protocols/Steam/src/steam_utils.cpp index 6ec2ec89f8..bc5d624a75 100644 --- a/protocols/Steam/src/steam_utils.cpp +++ b/protocols/Steam/src/steam_utils.cpp @@ -129,4 +129,17 @@ int CSteamProto::RsaEncrypt(const SteamWebApi::RsaKeyApi::RsaKey &rsaKey, const CryptReleaseContext(hCSP, 0); return 0; +} + +HANDLE CSteamProto::AddDBEvent(MCONTACT hContact, WORD type, DWORD timestamp, DWORD flags, DWORD cbBlob, PBYTE pBlob) +{ + DBEVENTINFO dbei = { sizeof(dbei) }; + dbei.szModule = m_szModuleName; + dbei.timestamp = timestamp; + dbei.eventType = type; + dbei.cbBlob = cbBlob; + dbei.pBlob = pBlob; + dbei.flags = flags; + + return db_event_add(hContact, &dbei); } \ No newline at end of file -- cgit v1.2.3